summaryrefslogtreecommitdiffstats
path: root/src/CBot
diff options
context:
space:
mode:
Diffstat (limited to 'src/CBot')
-rw-r--r--src/CBot/CBot.apsbin0 -> 44112 bytes
-rw-r--r--src/CBot/CBot.cpp4055
-rw-r--r--src/CBot/CBot.dsp158
-rw-r--r--src/CBot/CBot.dsw44
-rw-r--r--src/CBot/CBot.h1611
-rw-r--r--src/CBot/CBot.libbin0 -> 107676 bytes
-rw-r--r--src/CBot/CBot.optbin0 -> 53760 bytes
-rw-r--r--src/CBot/CBot.plg61
-rw-r--r--src/CBot/CBot.rc279
-rw-r--r--src/CBot/CBotAddExpr.cpp128
-rw-r--r--src/CBot/CBotClass.cpp867
-rw-r--r--src/CBot/CBotCompExpr.cpp117
-rw-r--r--src/CBot/CBotDll.h1185
-rw-r--r--src/CBot/CBotFunction.cpp1634
-rw-r--r--src/CBot/CBotIf.cpp145
-rw-r--r--src/CBot/CBotProgram.cpp1102
-rw-r--r--src/CBot/CBotStack.cpp1460
-rw-r--r--src/CBot/CBotString.cpp588
-rw-r--r--src/CBot/CBotToken.cpp540
-rw-r--r--src/CBot/CBotToken.h23
-rw-r--r--src/CBot/CBotTwoOpExpr ordre inversé.cpp302
-rw-r--r--src/CBot/CBotTwoOpExpr.cpp552
-rw-r--r--src/CBot/CBotVar.cpp2231
-rw-r--r--src/CBot/CBotWhile.cpp1413
-rw-r--r--src/CBot/ClassFILE.cpp412
-rw-r--r--src/CBot/Copie de CBot.rc184
-rw-r--r--src/CBot/Copie de CBotTwoOpExpr.cpp295
-rw-r--r--src/CBot/StringFunctions.cpp420
-rw-r--r--src/CBot/TestCBot/B.txt18
-rw-r--r--src/CBot/TestCBot/BUG2.txt107
-rw-r--r--src/CBot/TestCBot/CBotConsoleDlg.cpp205
-rw-r--r--src/CBot/TestCBot/CBotConsoleDlg.h69
-rw-r--r--src/CBot/TestCBot/ChildFrm.cpp58
-rw-r--r--src/CBot/TestCBot/ChildFrm.h50
-rw-r--r--src/CBot/TestCBot/Deleted.txt23
-rw-r--r--src/CBot/TestCBot/MaClass.txt16
-rw-r--r--src/CBot/TestCBot/MainFrm.cpp100
-rw-r--r--src/CBot/TestCBot/MainFrm.h56
-rw-r--r--src/CBot/TestCBot/Mc2.txt4
-rw-r--r--src/CBot/TestCBot/Mon fichier.txt2
-rw-r--r--src/CBot/TestCBot/Nop.txt4
-rw-r--r--src/CBot/TestCBot/POS.txt14
-rw-r--r--src/CBot/TestCBot/PerformDlg.cpp161
-rw-r--r--src/CBot/TestCBot/PerformDlg.h62
-rw-r--r--src/CBot/TestCBot/Routines.cpp139
-rw-r--r--src/CBot/TestCBot/StdAfx.cpp6
-rw-r--r--src/CBot/TestCBot/StdAfx.h26
-rw-r--r--src/CBot/TestCBot/T.txt4
-rw-r--r--src/CBot/TestCBot/TESTALL.txt161
-rw-r--r--src/CBot/TestCBot/TestCB1.txt18
-rw-r--r--src/CBot/TestCBot/TestCBot.clw316
-rw-r--r--src/CBot/TestCBot/TestCBot.cpp253
-rw-r--r--src/CBot/TestCBot/TestCBot.dsp201
-rw-r--r--src/CBot/TestCBot/TestCBot.h64
-rw-r--r--src/CBot/TestCBot/TestCBot.rc564
-rw-r--r--src/CBot/TestCBot/TestCBot1.txt27
-rw-r--r--src/CBot/TestCBot/TestCBot3.txt24
-rw-r--r--src/CBot/TestCBot/TestCBotDoc.cpp683
-rw-r--r--src/CBot/TestCBot/TestCBotDoc.h64
-rw-r--r--src/CBot/TestCBot/TestCBotView.cpp126
-rw-r--r--src/CBot/TestCBot/TestCBotView.h64
-rw-r--r--src/CBot/TestCBot/TestNull.txt15
-rw-r--r--src/CBot/TestCBot/TestRestoreState.txt67
-rw-r--r--src/CBot/TestCBot/TestStatic.txt31
-rw-r--r--src/CBot/TestCBot/TestStr.txt17
-rw-r--r--src/CBot/TestCBot/Z.txt14
-rw-r--r--src/CBot/TestCBot/array.txt24
-rw-r--r--src/CBot/TestCBot/a§1.txt96
-rw-r--r--src/CBot/TestCBot/bug.txt12
-rw-r--r--src/CBot/TestCBot/bugmw.txt9
-rw-r--r--src/CBot/TestCBot/ccc.txt8
-rw-r--r--src/CBot/TestCBot/enum.txt9
-rw-r--r--src/CBot/TestCBot/fibo.txt25
-rw-r--r--src/CBot/TestCBot/file.txt70
-rw-r--r--src/CBot/TestCBot/h.txt5
-rw-r--r--src/CBot/TestCBot/include.txt27
-rw-r--r--src/CBot/TestCBot/intrinsic.txt16
-rw-r--r--src/CBot/TestCBot/methode1.txt57
-rw-r--r--src/CBot/TestCBot/methode2.txt50
-rw-r--r--src/CBot/TestCBot/mp1.txt25
-rw-r--r--src/CBot/TestCBot/mp2.txt28
-rw-r--r--src/CBot/TestCBot/mw.txt16
-rw-r--r--src/CBot/TestCBot/null.txt5
-rw-r--r--src/CBot/TestCBot/opnew.txt20
-rw-r--r--src/CBot/TestCBot/plante.txt25
-rw-r--r--src/CBot/TestCBot/pointer.txt41
-rw-r--r--src/CBot/TestCBot/postinc.txt7
-rw-r--r--src/CBot/TestCBot/radar.txt39
-rw-r--r--src/CBot/TestCBot/res/TestCBot.icobin0 -> 1078 bytes
-rw-r--r--src/CBot/TestCBot/res/TestCBot.rc213
-rw-r--r--src/CBot/TestCBot/res/TestCBotDoc.icobin0 -> 1078 bytes
-rw-r--r--src/CBot/TestCBot/res/Toolbar.bmpbin0 -> 1198 bytes
-rw-r--r--src/CBot/TestCBot/resource.h30
-rw-r--r--src/CBot/TestCBot/solution.txt13
-rw-r--r--src/CBot/TestCBot/test.txt8
-rw-r--r--src/CBot/TestCBot/test23.txt10
-rw-r--r--src/CBot/TestCBot/testmw.txt14
-rw-r--r--src/CBot/TestCBot/this.txt13
-rw-r--r--src/CBot/TestCBot/tt.txt12
-rw-r--r--src/CBot/TestCBot/tt2.txt5
-rw-r--r--src/CBot/TestCBot/vide.txt0
-rw-r--r--src/CBot/TestCBot/xTestCBot.clw245
-rw-r--r--src/CBot/TestCBot/zz.txt6
-rw-r--r--src/CBot/_Copy.bat2
-rw-r--r--src/CBot/colobot.ini49
-rw-r--r--src/CBot/idees.txt39
-rw-r--r--src/CBot/old CBotAddExpr.cpp130
-rw-r--r--src/CBot/old CBotCompExpr.cpp120
-rw-r--r--src/CBot/old TstCBot/BotConsoleDlg.cpp164
-rw-r--r--src/CBot/old TstCBot/BotConsoleDlg.h65
-rw-r--r--src/CBot/old TstCBot/BotErrorDlg.cpp56
-rw-r--r--src/CBot/old TstCBot/BotErrorDlg.h51
-rw-r--r--src/CBot/old TstCBot/CBotTest.txt36
-rw-r--r--src/CBot/old TstCBot/CMyThread.cpp107
-rw-r--r--src/CBot/old TstCBot/CMyThread.h44
-rw-r--r--src/CBot/old TstCBot/MainFrm.cpp91
-rw-r--r--src/CBot/old TstCBot/MainFrm.h55
-rw-r--r--src/CBot/old TstCBot/ReadMe.txt93
-rw-r--r--src/CBot/old TstCBot/Resource.h68
-rw-r--r--src/CBot/old TstCBot/StdAfx.cpp6
-rw-r--r--src/CBot/old TstCBot/StdAfx.h26
-rw-r--r--src/CBot/old TstCBot/TstCBot.clw189
-rw-r--r--src/CBot/old TstCBot/TstCBot.cpp412
-rw-r--r--src/CBot/old TstCBot/TstCBot.dsp180
-rw-r--r--src/CBot/old TstCBot/TstCBot.h62
-rw-r--r--src/CBot/old TstCBot/TstCBot.rc471
-rw-r--r--src/CBot/old TstCBot/TstCBotDoc.cpp83
-rw-r--r--src/CBot/old TstCBot/TstCBotDoc.h55
-rw-r--r--src/CBot/old TstCBot/TstCBotView.cpp291
-rw-r--r--src/CBot/old TstCBot/TstCBotView.h81
-rw-r--r--src/CBot/old TstCBot/res/TstCBot.icobin0 -> 1078 bytes
-rw-r--r--src/CBot/old TstCBot/res/TstCBot.rc213
-rw-r--r--src/CBot/old TstCBot/res/TstCBotDoc.icobin0 -> 1078 bytes
-rw-r--r--src/CBot/old TstCBot/test complet 1.txt213
-rw-r--r--src/CBot/old TstCBot/x.txt43
-rw-r--r--src/CBot/resource.h166
136 files changed, 28083 insertions, 0 deletions
diff --git a/src/CBot/CBot.aps b/src/CBot/CBot.aps
new file mode 100644
index 0000000..cd294ec
--- /dev/null
+++ b/src/CBot/CBot.aps
Binary files differ
diff --git a/src/CBot/CBot.cpp b/src/CBot/CBot.cpp
new file mode 100644
index 0000000..79a0b6f
--- /dev/null
+++ b/src/CBot/CBot.cpp
@@ -0,0 +1,4055 @@
+///////////////////////////////////////////////////////////////////////
+// compilation des diverses instructions
+// toutes les routines Compile sont statiques
+// et retournent un object selon ce qui a été trouvé comme instruction
+
+// principe de compilation:
+// les routines Compile retournent un objet de la classe correspondant à l'opération trouvée
+// il s'agit toujours d'une classe fille de CBotInstr.
+// ( les objets CBotInstr ne sont jamais utilisés directement )
+
+// si la routine Compile retourne NULL, c'est que l'instruction est fausse
+// ou incomprise.
+// L'erreur se trouve alors sur la pile CBotCStack::IsOk() est FALSE
+
+
+#include "CBot.h"
+
+// les divers constructeurs / destructeurs
+// pour libérer tout selon l'arbre établi
+CBotInstr::CBotInstr()
+{
+ name = "CBotInstr";
+ m_next = NULL;
+ m_next2b = NULL;
+ m_next3 = NULL;
+ m_next3b = NULL;
+}
+
+CBotInstr::~CBotInstr()
+{
+ delete m_next;
+ delete m_next2b;
+ delete m_next3;
+ delete m_next3b;
+}
+
+// compteur de boucles imbriquées,
+// pour détermniner les break et continue valides
+// et liste des labels utilisables
+
+int CBotInstr::m_LoopLvl = 0;
+CBotStringArray
+ CBotInstr::m_labelLvl = CBotStringArray();
+
+// ajoute un niveau avec un label
+void CBotInstr::IncLvl(CBotString& label)
+{
+ m_labelLvl.SetSize(m_LoopLvl+1);
+ m_labelLvl[m_LoopLvl] = label;
+ m_LoopLvl++;
+}
+
+// ajoute un niveau (instruction switch)
+void CBotInstr::IncLvl()
+{
+ m_labelLvl.SetSize(m_LoopLvl+1);
+ m_labelLvl[m_LoopLvl] = "#SWITCH";
+ m_LoopLvl++;
+}
+
+// libère un niveau
+void CBotInstr::DecLvl()
+{
+ m_LoopLvl--;
+ m_labelLvl[m_LoopLvl].Empty();
+}
+
+// controle la validité d'un break ou continu
+BOOL CBotInstr::ChkLvl(CBotString& label, int type)
+{
+ int i = m_LoopLvl;
+ while (--i>=0)
+ {
+ if ( type == ID_CONTINUE && m_labelLvl[i] == "#SWITCH") continue;
+ if ( label.IsEmpty() ) return TRUE;
+ if ( m_labelLvl[i] == label ) return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CBotInstr::IsOfClass(CBotString n)
+{
+ return name == n;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// gestion de base de la classe CBotInstr
+
+// définie le token correspondant à l'instruction
+
+void CBotInstr::SetToken(CBotToken* p)
+{
+ m_token = *p;
+}
+
+void CBotInstr::SetToken(CBotString* name, int start, int end)
+{
+ SetToken( &CBotToken( *name, CBotString(), start, end));
+}
+
+
+// rend le type du token associé à l'instruction
+
+int CBotInstr::GivTokenType()
+{
+ return m_token.GivType();
+}
+
+// rend le token associé
+
+CBotToken* CBotInstr::GivToken()
+{
+ return &m_token;
+}
+
+// ajoute une instruction à la suite des autres
+
+void CBotInstr::AddNext(CBotInstr* n)
+{
+ CBotInstr* p = this;
+ while ( p->m_next != NULL ) p = p->m_next;
+ p->m_next = n;
+}
+
+void CBotInstr::AddNext3(CBotInstr* n)
+{
+ CBotInstr* p = this;
+ while ( p->m_next3 != NULL ) p = p->m_next3;
+ p->m_next3 = n;
+}
+
+void CBotInstr::AddNext3b(CBotInstr* n)
+{
+ CBotInstr* p = this;
+ while ( p->m_next3b != NULL ) p = p->m_next3b;
+ p->m_next3b = n;
+}
+
+// donne l'instruction suivante
+
+CBotInstr* CBotInstr::GivNext()
+{
+ return m_next;
+}
+
+CBotInstr* CBotInstr::GivNext3()
+{
+ return m_next3;
+}
+
+CBotInstr* CBotInstr::GivNext3b()
+{
+ return m_next3b;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction, qui peut être
+// while, do, try, throw, if, for, switch, break, continu, return
+// int, float, boolean, string,
+// déclaration d'une instance d'une classe
+// expression quelconque
+
+CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p;
+
+ if ( p == NULL ) return NULL;
+
+ int type = p->GivType(); // quel est le prochaine token ?
+
+ // y a-t-il un label ?
+ if ( IsOfType( pp, TokenTypVar ) &&
+ IsOfType( pp, ID_DOTS ) )
+ {
+ type = pp->GivType();
+ // seules ces instructions acceptent un label
+ if (!IsOfTypeList( pp, ID_WHILE, ID_FOR, ID_DO, ID_REPEAT, 0 ))
+ {
+ pStack->SetError(TX_LABEL, pp->GivStart());
+ return NULL;
+ }
+ }
+
+ // appel la routine de compilation correspondant au token trouvé
+ switch (type)
+ {
+ case ID_WHILE:
+ return CBotWhile::Compile(p, pStack);
+
+ case ID_FOR:
+ return CBotFor::Compile(p, pStack);
+
+ case ID_DO:
+ return CBotDo::Compile(p, pStack);
+
+ case ID_REPEAT:
+ return CBotRepeat::Compile(p, pStack);
+
+ case ID_BREAK:
+ case ID_CONTINUE:
+ return CBotBreak::Compile(p, pStack);
+
+ case ID_SWITCH:
+ return CBotSwitch::Compile(p, pStack);
+
+ case ID_TRY:
+ return CBotTry::Compile(p, pStack);
+
+ case ID_THROW:
+ return CBotThrow::Compile(p, pStack);
+
+ case ID_DEBUGDD:
+ return CBotStartDebugDD::Compile(p, pStack);
+
+ case ID_INT:
+ return CBotInt::Compile(p, pStack);
+
+ case ID_FLOAT:
+ return CBotFloat::Compile(p, pStack);
+
+ case ID_STRING:
+ return CBotIString::Compile(p, pStack);
+
+ case ID_BOOLEAN:
+ case ID_BOOL:
+ return CBotBoolean::Compile(p, pStack);
+
+ case ID_IF:
+ return CBotIf::Compile(p, pStack);
+
+ case ID_RETURN:
+ return CBotReturn::Compile(p, pStack);
+
+ case ID_ELSE:
+ pStack->SetStartError(p->GivStart());
+ pStack->SetError(TX_ELSEWITHOUTIF, p->GivEnd());
+ return NULL;
+
+ case ID_CASE:
+ pStack->SetStartError(p->GivStart());
+ pStack->SetError(TX_OUTCASE, p->GivEnd());
+ return NULL;
+ }
+
+ pStack->SetStartError(p->GivStart());
+
+ // ne doit pas être un mot réservé par DefineNum
+ if ( p->GivType() == TokenTypDef )
+ {
+ pStack->SetError(TX_RESERVED, p);
+ return NULL;
+ }
+
+ // ce peut être une définition d'instance de class
+ CBotToken* ppp = p;
+ if ( IsOfType( ppp, TokenTypVar ) /* && IsOfType( ppp, TokenTypVar )*/ )
+ {
+ if ( CBotClass::Find(p) != NULL )
+ {
+ // oui, compile la déclaration de l'instance
+ return CBotClassInst::Compile(p, pStack);
+ }
+ }
+
+ // ce peut être une instruction arithmétique
+ CBotInstr* inst = CBotExpression::Compile(p, pStack);
+ if (IsOfType(p, ID_SEP))
+ {
+ return inst;
+ }
+ pStack->SetError(TX_ENDOF, p->GivStart());
+ delete inst;
+ return NULL;
+}
+
+BOOL CBotInstr::Execute(CBotStack* &pj)
+{
+ CBotString ClassManquante = name;
+ __asm int 3; // ne doit jamais passer par cette routine
+ // mais utiliser les routines des classes filles
+ return FALSE;
+}
+
+BOOL CBotInstr::Execute(CBotStack* &pj, CBotVar* pVar)
+{
+ if ( !Execute(pj) ) return FALSE;
+ pVar->SetVal( pj->GivVar() );
+ return TRUE;
+}
+
+void CBotInstr::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotString ClassManquante = name;
+ __asm int 3; // ne doit jamais passer par cette routine
+ // mais utiliser les routines des classes filles
+}
+
+
+BOOL CBotInstr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
+{
+ __asm int 3; // papa sait pas faire, voir les filles
+ return FALSE;
+}
+
+BOOL CBotInstr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep, BOOL bExtend)
+{
+ __asm int 3; // papa sait pas faire, voir les filles
+ return FALSE;
+}
+
+void CBotInstr::RestoreStateVar(CBotStack* &pile, BOOL bMain)
+{
+ __asm int 3; // papa sait pas faire, voir les filles
+}
+
+// cette routine n'est définie que pour la classe fille CBotCase
+// cela permet de faire l'appel CompCase sur toutes les instructions
+// pour savoir s'il s'agit d'un case pour la valeur désirée.
+
+BOOL CBotInstr::CompCase(CBotStack* &pj, int val)
+{
+ return FALSE;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un bloc d'instruction " { i ; i ; } "
+
+// cette classe n'a pas de constructeur, car il n'y a jamais d'instance de cette classe
+// l'objet retourné par Compile est généralement de type CBotListInstr
+
+
+CBotInstr* CBotBlock::Compile(CBotToken* &p, CBotCStack* pStack, BOOL bLocal)
+{
+ pStack->SetStartError(p->GivStart());
+
+ if (IsOfType(p, ID_OPBLK))
+ {
+ CBotInstr* inst = CBotListInstr::Compile( p, pStack, bLocal );
+
+ if (IsOfType(p, ID_CLBLK))
+ {
+ return inst;
+ }
+
+ pStack->SetError(TX_CLOSEBLK, p->GivStart()); // manque la parenthèse
+ delete inst;
+ return NULL;
+ }
+
+ pStack->SetError(TX_OPENBLK, p->GivStart());
+ return NULL;
+}
+
+CBotInstr* CBotBlock::CompileBlkOrInst(CBotToken* &p, CBotCStack* pStack, BOOL bLocal)
+{
+ // est-ce un nouveau bloc ?
+ if ( p->GivType() == ID_OPBLK ) return CBotBlock::Compile(p, pStack);
+
+ // sinon, cherche une instruction unique à la place
+
+ // pour gérer les cas avec définition local à l'instructin (*)
+ CBotCStack* pStk = pStack->TokenStack(p, bLocal);
+
+ return pStack->Return( CBotInstr::Compile(p, pStk), // une instruction unique
+ pStk);
+}
+
+// (*) c'est le cas dans l'instruction suivante
+// if ( 1 == 1 ) int x = 0;
+// où la variable x n'est connue que dans le bloc qui suit le if.
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile une liste d'instruction, séparés par des points-virgules
+
+CBotListInstr::CBotListInstr()
+{
+ m_Instr = NULL;
+ name = "CBotListInstr";
+}
+
+CBotListInstr::~CBotListInstr()
+{
+ delete m_Instr;
+}
+
+CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, BOOL bLocal)
+{
+ CBotCStack* pStk = pStack->TokenStack(p, bLocal); // les variables sont locales
+
+ CBotListInstr* inst = new CBotListInstr();
+
+ while (TRUE)
+ {
+ if ( p == NULL ) break;
+
+ if (IsOfType(p, ID_SEP)) continue; // instruction vide ignorée
+ if ( p->GivType() == ID_CLBLK ) break; // déja plus d'instruction
+
+ if (IsOfType(p, 0))
+ {
+ pStack->SetError(TX_CLOSEBLK, p->GivStart());
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ CBotInstr* i = CBotBlock::CompileBlkOrInst( p, pStk ); // compile la suivante
+
+ if (!pStk->IsOk())
+ {
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ if ( inst->m_Instr == NULL ) inst->m_Instr = i;
+ else inst->m_Instr->AddNext(i); // ajoute à la suite
+ }
+ return pStack->Return(inst, pStk);
+}
+
+// exécute une liste d'instructions
+
+BOOL CBotListInstr::Execute(CBotStack* &pj)
+{
+
+ CBotStack* pile = pj->AddStack(this, TRUE);//indispensable pour SetState()
+ if ( pile->StackOver() ) return pj->Return( pile );
+
+
+ CBotInstr* p = m_Instr; // la première expression
+
+ int state = pile->GivState();
+ while (state-->0) p = p->GivNext(); // revient sur l'opération interrompue
+
+ if ( p != NULL ) while (TRUE)
+ {
+// DEBUG( "CBotListInstr", pile->GivState(), pile );
+
+ if ( !p->Execute(pile) ) return FALSE;
+ p = p->GivNext();
+ if ( p == NULL ) break;
+ if (!pile->IncState()) ;//return FALSE; // prêt pour la suivante
+ }
+
+ return pj->Return( pile ); // transmet en dessous
+}
+
+void CBotListInstr::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ CBotInstr* p = m_Instr; // la première expression
+
+ int state = pile->GivState();
+ while ( p != NULL && state-- > 0)
+ {
+ p->RestoreState(pile, FALSE);
+ p = p->GivNext(); // revient sur l'opération interrompue
+ }
+
+ if ( p != NULL ) p->RestoreState(pile, TRUE);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compilation d'un élément se trouvant à gauche d'une assignation
+
+CBotLeftExprVar::CBotLeftExprVar()
+{
+ name = "CBotLeftExprVar";
+ m_typevar = -1;
+ m_nIdent = 0;
+}
+
+CBotLeftExprVar::~CBotLeftExprVar()
+{
+}
+
+CBotInstr* CBotLeftExprVar::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ // vérifie que le token est un nom de variable
+ if (p->GivType() != TokenTypVar)
+ {
+ pStack->SetError( TX_NOVAR, p->GivStart());
+ return NULL;
+ }
+
+ CBotLeftExprVar* inst = new CBotLeftExprVar();
+ inst->SetToken(p);
+ p = p->GivNext();
+
+ return inst;
+}
+
+// crée une variable et lui assigne le résultat de la pile
+BOOL CBotLeftExprVar::Execute(CBotStack* &pj)
+{
+ CBotVar* var1;
+ CBotVar* var2;
+
+ var1 = CBotVar::Create(m_token.GivString(), m_typevar);
+ var1->SetUniqNum(m_nIdent); // avec cet identificateur unique
+ pj->AddVar(var1); // la place sur la pile
+
+ var2 = pj->GivVar(); // resultat sur la pile
+ if ( var2 ) var1->SetVal(var2); // fait l'assignation
+
+ return TRUE; // opération faite
+}
+
+void CBotLeftExprVar::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotVar* var1;
+
+ var1 = pj->FindVar(m_token.GivString());
+ if ( var1 == NULL ) __asm int 3;
+
+ var1->SetUniqNum(m_nIdent); // avec cet identificateur unique
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// définition d'un tableau de n'importe quel type
+// int a[12];
+// point x[];
+
+CBotInstArray::CBotInstArray()
+{
+ m_var = NULL;
+ m_listass = NULL;
+ name = "CBotInstArray";
+}
+
+CBotInstArray::~CBotInstArray()
+{
+ delete m_var;
+ delete m_listass;
+}
+
+
+CBotInstr* CBotInstArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
+{
+ CBotCStack* pStk = pStack->TokenStack(p);
+
+ CBotInstArray* inst = new CBotInstArray(); // crée l'objet
+
+ CBotToken* vartoken = p;
+ inst->SetToken(vartoken);
+
+ // détermine l'expression valable pour l'élément gauche
+ if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
+ {
+ if (pStk->CheckVarLocal(vartoken)) // redéfinition de la variable ?
+ {
+ pStk->SetError(TX_REDEFVAR, vartoken);
+ goto error;
+ }
+
+ CBotInstr* i;
+ while (IsOfType(p, ID_OPBRK)) // avec des indices ?
+ {
+ if ( p->GivType() != ID_CLBRK )
+ i = CBotExpression::Compile( p, pStk ); // expression pour la valeur
+ else
+ i = new CBotEmpty(); // spécial si pas de formule
+
+ inst->AddNext3b(i); // construit une liste
+ type = CBotTypResult(CBotTypArrayPointer, type);
+
+ if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ) )
+ {
+ pStk->SetError(TX_CLBRK, p->GivStart());
+ goto error;
+ }
+ }
+
+ CBotVar* var = CBotVar::Create(vartoken, type); // crée avec une instance
+ inst->m_typevar = type;
+
+ var->SetUniqNum(
+ ((CBotLeftExprVar*)inst->m_var)->m_nIdent = CBotVar::NextUniqNum());
+ // lui attribut un numéro unique
+ pStack->AddVar(var); // la place sur la pile
+
+ if ( IsOfType(p, ID_ASS) ) // avec une assignation
+ {
+ inst->m_listass = CBotListArray::Compile( p, pStk, type.GivTypElem() );
+ }
+
+ if ( pStk->IsOk() ) return pStack->Return(inst, pStk);
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+
+// exécute la définition d'un tableau
+
+BOOL CBotInstArray::Execute(CBotStack* &pj)
+{
+ CBotStack* pile1 = pj->AddStack(this);
+// if ( pile1 == EOX ) return TRUE;
+
+ CBotStack* pile = pile1;
+
+ if ( pile1->GivState() == 0 )
+ {
+ // cherche les dimensions max du tableau
+ CBotInstr* p = GivNext3b(); // les différentes formules
+ int nb = 0;
+
+ while (p != NULL)
+ {
+ pile = pile->AddStack(); // petite place pour travailler
+ nb++;
+ if ( pile->GivState() == 0 )
+ {
+ if ( !p->Execute(pile) ) return FALSE; // calcul de la taille // interrompu?
+ pile->IncState();
+ }
+ p = p->GivNext3b();
+ }
+
+ p = GivNext3b();
+ pile = pile1; // revient sur la pile
+ int n = 0;
+ int max[100];
+
+ while (p != NULL)
+ {
+ pile = pile->AddStack(); // récupère la même petite place
+ CBotVar* v = pile->GivVar(); // résultat
+ max[n] = v->GivValInt(); // valeur
+ if (max[n]>MAXARRAYSIZE)
+ {
+ pile->SetError(TX_OUTARRAY, &m_token);
+ return pj->Return ( pile );
+ }
+ n++;
+ p = p->GivNext3b();
+ }
+ while (n<100) max[n++] = 0;
+
+ m_typevar.SetArray( max ); // mémorise les limitations
+
+ // crée simplement un pointeur null
+ CBotVar* var = CBotVar::Create(m_var->GivToken(), m_typevar);
+ var->SetPointer(NULL);
+ var->SetUniqNum(((CBotLeftExprVar*)m_var)->m_nIdent);
+ pj->AddVar(var); // inscrit le tableau de base sur la pile
+
+#if STACKMEM
+ pile1->AddStack()->Delete();
+#else
+ delete pile1->AddStack(); // plus besoin des indices
+#endif
+ pile1->IncState();
+ }
+
+ if ( pile1->GivState() == 1 )
+ {
+ if ( m_listass != NULL ) // il y a des assignation pour ce tableau
+ {
+ CBotVar* pVar = pj->FindVar(((CBotLeftExprVar*)m_var)->m_nIdent);
+
+ if ( !m_listass->Execute(pile1, pVar) ) return FALSE;
+ }
+ pile1->IncState();
+ }
+
+ if ( pile1->IfStep() ) return FALSE; // montre ce pas ?
+
+ if ( m_next2b &&
+ !m_next2b->Execute( pile1 ) ) return FALSE;
+
+ return pj->Return( pile1 ); // transmet en dessous
+}
+
+void CBotInstArray::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotStack* pile1 = pj;
+
+ CBotVar* var = pj->FindVar(m_var->GivToken()->GivString());
+ if ( var != NULL ) var->SetUniqNum(((CBotLeftExprVar*)m_var)->m_nIdent);
+
+ if ( bMain )
+ {
+ pile1 = pj->RestoreStack(this);
+ CBotStack* pile = pile1;
+ if ( pile == NULL ) return;
+
+ if ( pile1->GivState() == 0 )
+ {
+ // cherche les dimensions max du tableau
+ CBotInstr* p = GivNext3b(); // les différentes formules
+
+ while (p != NULL)
+ {
+ pile = pile->RestoreStack(); // petite place pour travailler
+ if ( pile == NULL ) return;
+ if ( pile->GivState() == 0 )
+ {
+ p->RestoreState(pile, bMain); // calcul de la taille // interrompu!
+ return;
+ }
+ p = p->GivNext3b();
+ }
+ }
+ if ( pile1->GivState() == 1 && m_listass != NULL )
+ {
+ m_listass->RestoreState(pile1, bMain);
+ }
+
+ }
+
+
+ if ( m_next2b ) m_next2b->RestoreState( pile1, bMain );
+}
+
+// cas particulier pour les indices vides
+BOOL CBotEmpty :: Execute(CBotStack* &pj)
+{
+ CBotVar* pVar = CBotVar::Create("", CBotTypInt);
+ pVar->SetValInt(-1); // met la valeur -1 sur la pile
+ pj->SetVar(pVar);
+ return TRUE;
+}
+
+void CBotEmpty :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// définition d'une liste d'initialisation pour un tableau
+// int [ ] a [ ] = ( ( 1, 2, 3 ) , ( 3, 2, 1 ) ) ;
+
+
+CBotListArray::CBotListArray()
+{
+ m_expr = NULL;
+ name = "CBotListArray";
+}
+
+CBotListArray::~CBotListArray()
+{
+ delete m_expr;
+}
+
+
+CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
+{
+ CBotCStack* pStk = pStack->TokenStack(p);
+
+ CBotToken* pp = p;
+
+ if ( IsOfType( p, ID_NULL ) )
+ {
+ CBotInstr* inst = new CBotExprNull ();
+ inst->SetToken( pp );
+// CBotVar* var = CBotVar::Create("", CBotTypNullPointer);
+// pStk->SetVar(var);
+ return pStack->Return(inst, pStk); // ok avec élément vide
+ }
+
+ CBotListArray* inst = new CBotListArray(); // crée l'objet
+
+ if ( IsOfType( p, ID_OPENPAR ) )
+ {
+ // prend chaque élément l'un après l'autre
+ if ( type.Eq( CBotTypArrayPointer ) )
+ {
+ type = type.GivTypElem();
+
+ pStk->SetStartError(p->GivStart());
+ if ( NULL == ( inst->m_expr = CBotListArray::Compile( p, pStk, type ) ) )
+ {
+ goto error;
+ }
+
+ while ( IsOfType( p, ID_COMMA ) ) // d'autres éléments ?
+ {
+ pStk->SetStartError(p->GivStart());
+
+ CBotInstr* i = CBotListArray::Compile( p, pStk, type );
+ if ( NULL == i )
+ {
+ goto error;
+ }
+
+ inst->m_expr->AddNext3(i);
+ }
+ }
+ else
+ {
+ pStk->SetStartError(p->GivStart());
+ if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
+ {
+ goto error;
+ }
+ CBotVar* pv = pStk->GivVar(); // le résultat de l'expression
+
+ if ( pv == NULL || !TypesCompatibles( type, pv->GivTypResult() )) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }
+
+ while ( IsOfType( p, ID_COMMA ) ) // d'autres éléments ?
+ {
+ pStk->SetStartError(p->GivStart());
+
+ CBotInstr* i = CBotTwoOpExpr::Compile( p, pStk ) ;
+ if ( NULL == i )
+ {
+ goto error;
+ }
+
+ CBotVar* pv = pStk->GivVar(); // le résultat de l'expression
+
+ if ( pv == NULL || !TypesCompatibles( type, pv->GivTypResult() )) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }
+ inst->m_expr->AddNext3(i);
+ }
+ }
+
+ if (!IsOfType(p, ID_CLOSEPAR) )
+ {
+ pStk->SetError(TX_CLOSEPAR, p->GivStart());
+ goto error;
+ }
+
+ return pStack->Return(inst, pStk);
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+
+// exécute la définition d'un tableau
+
+BOOL CBotListArray::Execute(CBotStack* &pj, CBotVar* pVar)
+{
+ CBotStack* pile1 = pj->AddStack();
+// if ( pile1 == EOX ) return TRUE;
+ CBotVar* pVar2;
+
+ CBotInstr* p = m_expr;
+
+ int n = 0;
+
+ for ( ; p != NULL ; n++, p = p->GivNext3() )
+ {
+ if ( pile1->GivState() > n ) continue;
+
+ pVar2 = pVar->GivItem(n, TRUE);
+
+ if ( !p->Execute(pile1, pVar2) ) return FALSE; // évalue l'expression
+
+ pile1->IncState();
+ }
+
+ return pj->Return( pile1 ); // transmet en dessous
+}
+
+void CBotListArray::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain )
+ {
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ CBotInstr* p = m_expr;
+
+ int state = pile->GivState();
+
+ while( state-- > 0 ) p = p->GivNext3() ;
+
+ p->RestoreState(pile, bMain); // calcul de la taille // interrompu!
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// définition d'une variable entière
+// int a, b = 12;
+
+CBotInt::CBotInt()
+{
+ m_next = NULL; // pour les définitions multiples
+ m_var =
+ m_expr = NULL;
+ name = "CBotInt";
+}
+
+CBotInt::~CBotInt()
+{
+ delete m_var;
+ delete m_expr;
+// delete m_next; // fait par le destructeur de la classe de base ~CBotInstr()
+}
+
+CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, BOOL first)
+{
+ if ( IsOfType(p, ID_OPBRK) )
+ {
+ if ( !IsOfType(p, ID_CLBRK) )
+ {
+ pStack->SetError(TX_CLBRK, p->GivStart());
+ return NULL;
+ }
+
+ CBotInstr* inst = CompileArray(p, pStack, CBotTypResult( CBotTypArrayPointer, type ), FALSE);
+ if ( inst != NULL || !pStack->IsOk() ) return inst;
+ }
+
+ // compile une déclaration de tableau
+ if (first) return NULL ;
+
+ CBotInstr* inst = CBotInstArray::Compile( p, pStack, type );
+ if ( inst == NULL ) return NULL;
+
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst->m_next2b = CBotInstArray::CompileArray(p, pStack, type, FALSE) )) // compile la suivante
+ {
+ return inst;
+ }
+ delete inst;
+ return NULL;
+ }
+
+ if (IsOfType(p, ID_SEP)) // instruction terminée
+ {
+ return inst;
+ }
+
+ delete inst;
+ pStack->SetError(TX_ENDOF, p->GivStart());
+ return NULL;
+}
+
+CBotInstr* CBotInt::Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont, BOOL noskip)
+{
+ CBotToken* pp = cont ? NULL : p; // pas de répétition du token "int"
+
+ if (!cont && !IsOfType(p, ID_INT)) return NULL;
+
+ CBotInt* inst = (CBotInt*)CompileArray(p, pStack, CBotTypInt);
+ if ( inst != NULL || !pStack->IsOk() ) return inst;
+
+ CBotCStack* pStk = pStack->TokenStack(pp);
+
+ inst = new CBotInt(); // crée l'objet
+
+ inst->m_expr = NULL;
+
+ CBotToken* vartoken = p;
+ inst->SetToken( vartoken );
+
+ // détermine l'expression valable pour l'élément gauche
+ if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
+ {
+ ((CBotLeftExprVar*)inst->m_var)->m_typevar = CBotTypInt;
+ if (pStk->CheckVarLocal(vartoken)) // redéfinition de la variable
+ {
+ pStk->SetError(TX_REDEFVAR, vartoken);
+ goto error;
+ }
+
+ if (IsOfType(p, ID_OPBRK)) // avec des indices ?
+ {
+ delete inst; // n'est pas de type CBotInt
+ p = vartoken; // revient sur le nom de la variable
+
+ // compile une déclaration de tableau
+
+ CBotInstr* inst2 = CBotInstArray::Compile( p, pStk, CBotTypInt );
+
+ if (!pStk->IsOk() )
+ {
+ pStk->SetError(TX_CLBRK, p->GivStart());
+ goto error;
+ }
+
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst2->m_next2b = CBotInt::Compile(p, pStk, TRUE, noskip) )) // compile la suivante
+ {
+ return pStack->Return(inst2, pStk);
+ }
+ }
+ inst = (CBotInt*)inst2;
+ goto suite; // pas d'assignation, variable déjà créée
+ }
+
+ if (IsOfType(p, ID_ASS)) // avec une assignation ?
+ {
+ if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
+ {
+ goto error;
+ }
+ if ( pStk->GivType() >= CBotTypBoolean ) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }
+ }
+
+ {
+ CBotVar* var = CBotVar::Create(vartoken, CBotTypInt);// crée la variable (après l'assignation évaluée)
+ var->SetInit(inst->m_expr != NULL); // la marque initialisée si avec assignation
+ var->SetUniqNum(
+ ((CBotLeftExprVar*)inst->m_var)->m_nIdent = CBotVar::NextUniqNum());
+ // lui attribut un numéro unique
+ pStack->AddVar(var); // la place sur la pile
+ }
+
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst->m_next2b = CBotInt::Compile(p, pStk, TRUE, noskip) )) // compile la suivante
+ {
+ return pStack->Return(inst, pStk);
+ }
+ }
+suite:
+ if (noskip || IsOfType(p, ID_SEP)) // instruction terminée
+ {
+ return pStack->Return(inst, pStk);
+ }
+
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute la définition de la variable entière
+
+BOOL CBotInt::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this); //indispensable pour SetState()
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr && !m_expr->Execute(pile)) return FALSE; // valeur initiale // interrompu?
+ m_var->Execute( pile ); // crée et fait l'assigation du résultat
+
+ if (!pile->SetState(1)) return FALSE;
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ if ( m_next2b &&
+ !m_next2b->Execute(pile)) return FALSE; // autre(s) définition(s)
+
+ return pj->Return( pile ); // transmet en dessous
+}
+
+void CBotInt::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotStack* pile = pj;
+ if ( bMain )
+ {
+ pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr) m_expr->RestoreState(pile, bMain); // valeur initiale // interrompu!
+ return;
+ }
+ }
+
+ m_var->RestoreState(pile, bMain);
+
+ if ( m_next2b ) m_next2b->RestoreState(pile, bMain); // autre(s) définition(s)
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// définition d'une variable booléen
+// int a, b = false;
+
+CBotBoolean::CBotBoolean()
+{
+ m_var =
+ m_expr = NULL;
+ name = "CBotBoolean";
+}
+
+CBotBoolean::~CBotBoolean()
+{
+ delete m_var;
+ delete m_expr;
+}
+
+CBotInstr* CBotBoolean::Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont, BOOL noskip)
+{
+ CBotToken* pp = cont ? NULL : p;
+
+ if (!cont && !IsOfType(p, ID_BOOLEAN, ID_BOOL)) return NULL;
+
+ CBotBoolean* inst = (CBotBoolean*)CompileArray(p, pStack, CBotTypBoolean);
+ if ( inst != NULL || !pStack->IsOk() ) return inst;
+
+ CBotCStack* pStk = pStack->TokenStack(pp);
+
+ inst = new CBotBoolean();
+
+ inst->m_expr = NULL;
+
+ CBotToken* vartoken = p;
+ inst->SetToken( vartoken );
+ CBotVar* var = NULL;
+
+ if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
+ {
+ ((CBotLeftExprVar*)inst->m_var)->m_typevar = CBotTypBoolean;
+ if (pStk->CheckVarLocal(vartoken)) // redéfinition de la variable
+ {
+ pStk->SetError(TX_REDEFVAR, vartoken);
+ goto error;
+ }
+
+ if (IsOfType(p, ID_OPBRK)) // avec des indices ?
+ {
+ delete inst; // n'est pas de type CBotInt
+ p = vartoken; // revient sur le nom de la variable
+
+ // compile une déclaration de tableau
+
+ inst = (CBotBoolean*)CBotInstArray::Compile( p, pStk, CBotTypBoolean );
+
+ if (!pStk->IsOk() )
+ {
+ pStk->SetError(TX_CLBRK, p->GivStart());
+ goto error;
+ }
+ goto suite; // pas d'assignation, variable déjà créée
+ }
+
+ if (IsOfType(p, ID_ASS)) // avec une assignation ?
+ {
+ if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
+ {
+ goto error;
+ }
+ if ( !pStk->GivTypResult().Eq(CBotTypBoolean) ) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }
+ }
+
+ var = CBotVar::Create(vartoken, CBotTypBoolean);// crée la variable (après l'assignation évaluée)
+ var->SetInit(inst->m_expr != NULL); // la marque initialisée si avec assignation
+ var->SetUniqNum(
+ ((CBotLeftExprVar*)inst->m_var)->m_nIdent = CBotVar::NextUniqNum());
+ // lui attribut un numéro unique
+ pStack->AddVar(var); // la place sur la pile
+suite:
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst->m_next2b = CBotBoolean::Compile(p, pStk, TRUE, noskip) )) // compile la suivante
+ {
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ if (noskip || IsOfType(p, ID_SEP)) // instruction terminée
+ {
+ return pStack->Return(inst, pStk);
+ }
+
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute une définition de variable booléenne
+
+BOOL CBotBoolean::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);//indispensable pour SetState()
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr && !m_expr->Execute(pile)) return FALSE; // valeur initiale // interrompu?
+ m_var->Execute( pile ); // crée et fait l'assigation du résultat
+
+ if (!pile->SetState(1)) return FALSE;
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ if ( m_next2b &&
+ !m_next2b->Execute(pile)) return FALSE; // autre(s) définition(s)
+
+ return pj->Return( pile ); // transmet en dessous
+}
+
+void CBotBoolean::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotStack* pile = pj;
+ if ( bMain )
+ {
+ pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr) m_expr->RestoreState(pile, bMain); // valeur initiale interrompu?
+ return;
+ }
+ }
+
+ m_var->RestoreState( pile, bMain ); //
+
+ if ( m_next2b )
+ m_next2b->RestoreState(pile, bMain); // autre(s) définition(s)
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// définition d'une variable réelle
+// int a, b = 12.4;
+
+CBotFloat::CBotFloat()
+{
+ m_var =
+ m_expr = NULL;
+ name = "CBotFloat";
+}
+
+CBotFloat::~CBotFloat()
+{
+ delete m_var;
+ delete m_expr;
+}
+
+CBotInstr* CBotFloat::Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont, BOOL noskip)
+{
+ CBotToken* pp = cont ? NULL : p;
+
+ if (!cont && !IsOfType(p, ID_FLOAT)) return NULL;
+
+ CBotFloat* inst = (CBotFloat*)CompileArray(p, pStack, CBotTypFloat);
+ if ( inst != NULL || !pStack->IsOk() ) return inst;
+
+ CBotCStack* pStk = pStack->TokenStack(pp);
+
+ inst = new CBotFloat();
+
+ inst->m_expr = NULL;
+
+ CBotToken* vartoken = p;
+ CBotVar* var = NULL;
+ inst->SetToken(vartoken);
+
+ if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
+ {
+ ((CBotLeftExprVar*)inst->m_var)->m_typevar = CBotTypFloat;
+ if (pStk->CheckVarLocal(vartoken)) // redéfinition de la variable
+ {
+ pStk->SetStartError(vartoken->GivStart());
+ pStk->SetError(TX_REDEFVAR, vartoken->GivEnd());
+ goto error;
+ }
+
+ if (IsOfType(p, ID_OPBRK)) // avec des indices ?
+ {
+ delete inst; // n'est pas de type CBotInt
+ p = vartoken; // revient sur le nom de la variable
+
+ // compile une déclaration de tableau
+
+ inst = (CBotFloat*)CBotInstArray::Compile( p, pStk, CBotTypFloat );
+
+ if (!pStk->IsOk() )
+ {
+ pStk->SetError(TX_CLBRK, p->GivStart());
+ goto error;
+ }
+ goto suite; // pas d'assignation, variable déjà créée
+ }
+
+ if (IsOfType(p, ID_ASS)) // avec une assignation ?
+ {
+ if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
+ {
+ goto error;
+ }
+ if ( pStk->GivType() >= CBotTypBoolean ) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }
+ }
+
+ var = CBotVar::Create(vartoken, CBotTypFloat); // crée la variable (après l'assignation évaluée)
+ var->SetInit(inst->m_expr != NULL); // la marque initialisée si avec assignation
+ var->SetUniqNum(
+ ((CBotLeftExprVar*)inst->m_var)->m_nIdent = CBotVar::NextUniqNum());
+ // lui attribut un numéro unique
+ pStack->AddVar(var); // la place sur la pile
+suite:
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst->m_next2b = CBotFloat::Compile(p, pStk, TRUE, noskip) )) // compile la suivante
+ {
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ if (noskip || IsOfType(p, ID_SEP)) // instruction terminée
+ {
+ return pStack->Return(inst, pStk);
+ }
+
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute la défintion de la variable réelle
+
+BOOL CBotFloat::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);//indispensable pour SetState()
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr && !m_expr->Execute(pile)) return FALSE; // valeur initiale // interrompu?
+ m_var->Execute( pile ); // crée et fait l'assigation du résultat
+
+ if (!pile->SetState(1)) return FALSE;
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ if ( m_next2b &&
+ !m_next2b->Execute(pile)) return FALSE; // autre(s) définition(s)
+
+ return pj->Return( pile ); // transmet en dessous
+}
+
+void CBotFloat::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotStack* pile = pj;
+ if ( bMain )
+ {
+ pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr) m_expr->RestoreState(pile, bMain); // valeur initiale interrompu?
+ return;
+ }
+ }
+
+ m_var->RestoreState( pile, bMain ); //
+
+ if ( m_next2b )
+ m_next2b->RestoreState(pile, bMain); // autre(s) définition(s)
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// définition d'une variable chaîne de caractères
+// int a, b = "salut";
+
+CBotIString::CBotIString()
+{
+ m_var =
+ m_expr = NULL;
+ name = "CBotIString";
+}
+
+CBotIString::~CBotIString()
+{
+ delete m_var;
+ delete m_expr;
+}
+
+CBotInstr* CBotIString::Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont, BOOL noskip)
+{
+ CBotToken* pp = cont ? NULL : p;
+
+ if (!cont && !IsOfType(p, ID_STRING)) return NULL;
+
+ CBotIString* inst = (CBotIString*)CompileArray(p, pStack, CBotTypString);
+ if ( inst != NULL || !pStack->IsOk() ) return inst;
+
+ CBotCStack* pStk = pStack->TokenStack(pp);
+
+ inst = new CBotIString();
+
+ inst->m_expr = NULL;
+
+ CBotToken* vartoken = p;
+ inst->SetToken( vartoken );
+
+ if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
+ {
+ ((CBotLeftExprVar*)inst->m_var)->m_typevar = CBotTypString;
+ if (pStk->CheckVarLocal(vartoken)) // redéfinition de la variable
+ {
+ pStk->SetStartError(vartoken->GivStart());
+ pStk->SetError(TX_REDEFVAR, vartoken->GivEnd());
+ goto error;
+ }
+
+ if (IsOfType(p, ID_ASS)) // avec une assignation ?
+ {
+ if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
+ {
+ goto error;
+ }
+/* if ( !pStk->GivTypResult().Eq(CBotTypString) ) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }*/
+ }
+
+ CBotVar* var = CBotVar::Create(vartoken, CBotTypString); // crée la variable (après l'assignation évaluée)
+ var->SetInit(inst->m_expr != NULL); // la marque initialisée si avec assignation
+ var->SetUniqNum(
+ ((CBotLeftExprVar*)inst->m_var)->m_nIdent = CBotVar::NextUniqNum());
+ // lui attribut un numéro unique
+ pStack->AddVar(var); // la place sur la pile
+
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst->m_next2b = CBotIString::Compile(p, pStk, TRUE, noskip) )) // compile la suivante
+ {
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ if (noskip || IsOfType(p, ID_SEP)) // instruction terminée
+ {
+ return pStack->Return(inst, pStk);
+ }
+
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute la définition de la variable string
+
+BOOL CBotIString::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);//indispensable pour SetState()
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr && !m_expr->Execute(pile)) return FALSE; // valeur initiale // interrompu?
+ m_var->Execute( pile ); // crée et fait l'assigation du résultat
+
+ if (!pile->SetState(1)) return FALSE;
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ if ( m_next2b &&
+ !m_next2b->Execute(pile)) return FALSE; // autre(s) définition(s)
+
+ return pj->Return( pile ); // transmet en dessous
+}
+
+void CBotIString::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotStack* pile = pj;
+
+ if ( bMain )
+ {
+ pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState()==0)
+ {
+ if (m_expr) m_expr->RestoreState(pile, bMain); // valeur initiale interrompu?
+ return;
+ }
+ }
+
+ m_var->RestoreState( pile, bMain ); //
+
+ if ( m_next2b )
+ m_next2b->RestoreState(pile, bMain); // autre(s) définition(s)
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile une instruction de type " x = 123 " ou " z * 5 + 4 "
+// avec ou sans assignation donc
+
+CBotExpression::CBotExpression()
+{
+ m_leftop = NULL;
+ m_rightop = NULL;
+ name = "CBotExpression";
+}
+
+CBotExpression::~CBotExpression()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p;
+
+ CBotExpression* inst = new CBotExpression();
+
+ inst->m_leftop = CBotLeftExpr::Compile(p, pStack);
+
+ inst->SetToken(p);
+ int OpType = p->GivType();
+
+ if ( pStack->IsOk() &&
+ IsOfTypeList(p, ID_ASS, ID_ASSADD, ID_ASSSUB, ID_ASSMUL, ID_ASSDIV, ID_ASSMODULO,
+ ID_ASSAND, ID_ASSXOR, ID_ASSOR,
+ ID_ASSSL , ID_ASSSR, ID_ASSASR, 0 ))
+ {
+ if ( inst->m_leftop == NULL )
+ {
+ pStack->SetError(TX_BADLEFT, p->GivEnd());
+ delete inst;
+ return NULL;
+ }
+
+ inst->m_rightop = CBotExpression::Compile(p, pStack);
+ if (inst->m_rightop == NULL)
+ {
+ delete inst;
+ return NULL;
+ }
+
+ CBotTypResult type1 = pStack->GivTypResult();
+
+ // récupère la variable pour la marquer assignée
+ CBotVar* var = NULL;
+ inst->m_leftop->ExecuteVar(var, pStack);
+ if ( var == NULL )
+ {
+ delete inst;
+ return NULL;
+ }
+
+ if (OpType != ID_ASS && var->GivInit() != IS_DEF)
+ {
+ pStack->SetError(TX_NOTINIT, pp);
+ delete inst;
+ return NULL;
+ }
+
+ CBotTypResult type2 = var->GivTypResult();
+
+ // quels sont les types acceptables ?
+ switch (OpType)
+ {
+ case ID_ASS:
+ // if (type2 == CBotTypClass) type2 = -1; // pas de classe
+ if ( (type1.Eq(CBotTypPointer) && type2.Eq(CBotTypPointer) ) ||
+ (type1.Eq(CBotTypClass) && type2.Eq(CBotTypClass) ) )
+ {
+/* CBotClass* c1 = type1.GivClass();
+ CBotClass* c2 = type2.GivClass();
+ if ( !c1->IsChildOf(c2) ) type2.SetType(-1); // pas la même classe
+//- if ( !type1.Eq(CBotTypClass) ) var->SetPointer(pStack->GivVar()->GivPointer());*/
+ var->SetInit(2);
+ }
+ else
+ var->SetInit(TRUE);
+
+ break;
+ case ID_ASSADD:
+ if (type2.Eq(CBotTypBoolean) ||
+ type2.Eq(CBotTypPointer) ) type2 = -1; // nombres et chaines
+ break;
+ case ID_ASSSUB:
+ case ID_ASSMUL:
+ case ID_ASSDIV:
+ case ID_ASSMODULO:
+ if (type2.GivType() >= CBotTypBoolean) type2 = -1; // nombres uniquement
+ break;
+ }
+
+ if (!TypeCompatible( type1, type2, OpType ))
+ {
+ pStack->SetError(TX_BADTYPE, &inst->m_token);
+ delete inst;
+ return NULL;
+ }
+
+ return inst; // types compatibles ?
+ }
+
+ delete inst;
+// p = p->GivNext();
+ int start, end, error = pStack->GivError(start, end);
+
+ p = pp; // revient au début
+ pStack->SetError(0,0); // oublie l'erreur
+
+// return CBotTwoOpExpr::Compile(p, pStack); // essaie sans assignation
+ CBotInstr* i = CBotTwoOpExpr::Compile(p, pStack); // essaie sans assignation
+ if ( i != NULL && error == TX_PRIVATE && p->GivType() == ID_ASS )
+ pStack->ResetError( error, start, end );
+ return i;
+}
+
+// exécute une expression avec assignation
+
+BOOL CBotExpression::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ CBotToken* pToken = m_leftop->GivToken();
+ CBotVar* pVar = NULL;
+
+ CBotStack* pile1 = pile;
+
+ BOOL IsInit = TRUE;
+ CBotVar* result = NULL;
+
+ // doit être fait avant pour les indices éventuels (pile peut être changée)
+ if ( !m_leftop->ExecuteVar(pVar, pile, NULL, FALSE) ) return FALSE; // variable avant évaluation de la valeur droite
+
+// DEBUG( "CBotExpression::Execute", -1, pj);
+ if ( pile1->GivState()==0)
+ {
+ pile1->SetCopyVar(pVar); // garde une copie sur la pile (si interrompu)
+ pile1->IncState();
+ }
+
+ CBotStack* pile2 = pile->AddStack(); // attention pile et surtout pas pile1
+
+ if ( pile2->GivState()==0)
+ {
+// DEBUG( "CBotExpression::Execute", -2, pj);
+ if (m_rightop && !m_rightop->Execute(pile2)) return FALSE; // valeur initiale // interrompu?
+ pile2->IncState();
+ }
+
+ if ( pile1->GivState() == 1 )
+ {
+// DEBUG( "CBotExpression::Execute", -3, pj);
+ if ( m_token.GivType() != ID_ASS )
+ {
+ pVar = pile1->GivVar(); // récupére si interrompu
+ IsInit = pVar->GivInit();
+ if ( IsInit == IS_NAN )
+ {
+ pile2->SetError(TX_OPNAN, m_leftop->GivToken());
+ return pj->Return(pile2);
+ }
+ result = CBotVar::Create("", pVar->GivTypResult(2));
+ }
+
+ switch ( m_token.GivType() )
+ {
+ case ID_ASS:
+ break;
+ case ID_ASSADD:
+ result->Add(pile1->GivVar(), pile2->GivVar()); // additionne
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSSUB:
+ result->Sub(pile1->GivVar(), pile2->GivVar()); // soustrait
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSMUL:
+ result->Mul(pile1->GivVar(), pile2->GivVar()); // multiplie
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSDIV:
+ if (IsInit &&
+ result->Div(pile1->GivVar(), pile2->GivVar())) // divise
+ pile2->SetError(TX_DIVZERO, &m_token);
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSMODULO:
+ if (IsInit &&
+ result->Modulo(pile1->GivVar(), pile2->GivVar())) // reste de la division
+ pile2->SetError(TX_DIVZERO, &m_token);
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSAND:
+ result->And(pile1->GivVar(), pile2->GivVar()); // multiplie
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSXOR:
+ result->XOr(pile1->GivVar(), pile2->GivVar());
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSOR:
+ result->Or(pile1->GivVar(), pile2->GivVar());
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSSL:
+ result->SL(pile1->GivVar(), pile2->GivVar());
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSSR:
+ result->SR(pile1->GivVar(), pile2->GivVar());
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ case ID_ASSASR:
+ result->ASR(pile1->GivVar(), pile2->GivVar());
+ pile2->SetVar(result); // re-place le résultat
+ break;
+ default:
+ __asm int 3;
+ }
+ if (!IsInit)
+ pile2->SetError(TX_NOTINIT, m_leftop->GivToken());
+
+ pile1->IncState();
+ }
+
+// DEBUG( "CBotExpression::Execute", -4, pj);
+ if ( !m_leftop->Execute( pile2, pile1 ) )
+ return FALSE; // crée et fait l'assigation du résultat
+
+ return pj->Return( pile2 ); // transmet en dessous
+}
+
+
+void CBotExpression::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain )
+ {
+ CBotToken* pToken = m_leftop->GivToken();
+ CBotVar* pVar = NULL;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ CBotStack* pile1 = pile;
+
+
+ if ( pile1->GivState()==0)
+ {
+ m_leftop->RestoreStateVar(pile, TRUE); // variable avant évaluation de la valeur droite
+ return;
+ }
+
+ m_leftop->RestoreStateVar(pile, FALSE); // variable avant évaluation de la valeur droite
+
+ CBotStack* pile2 = pile->RestoreStack(); // attention pile et surtout pas pile1
+ if ( pile2 == NULL ) return;
+
+ if ( pile2->GivState()==0)
+ {
+ if (m_rightop) m_rightop->RestoreState(pile2, bMain); // valeur initiale // interrompu?
+ return;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile une instruction de type " ( condition ) "
+// la condition doit être de type booléen
+
+// cette classe n'a pas de constructeur, car il n'y a jamais d'instance de cette classe
+// l'objet retourné par Compile est généralement de type CBotExpression
+
+CBotInstr* CBotCondition::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ pStack->SetStartError(p->GivStart());
+ if ( IsOfType(p, ID_OPENPAR ))
+ {
+ CBotInstr* inst = CBotBoolExpr::Compile( p, pStack );
+ if ( NULL != inst )
+ {
+ if ( IsOfType(p, ID_CLOSEPAR ))
+ {
+ return inst;
+ }
+ pStack->SetError(TX_CLOSEPAR, p->GivStart()); // manque la parenthèse
+ }
+ delete inst;
+ }
+
+ pStack->SetError(TX_OPENPAR, p->GivStart()); // manque la parenthèse
+
+ return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile une instruction de type " condition "
+// la condition doit être de type booléen
+
+// cette classe n'a pas de constructeur, car il n'y a jamais d'instance de cette classe
+// l'objet retourné par Compile est généralement de type CBotExpression
+
+CBotInstr* CBotBoolExpr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ pStack->SetStartError(p->GivStart());
+
+ CBotInstr* inst = CBotTwoOpExpr::Compile( p, pStack );
+
+ if ( NULL != inst )
+ {
+ if ( pStack->GivTypResult().Eq(CBotTypBoolean) )
+ {
+ return inst;
+ }
+ pStack->SetError(TX_NOTBOOL, p->GivStart()); // n'est pas un booléan
+ }
+
+ delete inst;
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile soit :
+// une instruction entre parenthèses (...)
+// une expression unaire (négatif, not)
+// nom de variable
+// les variables prè et post incrémentées ou décrémentées
+// un nombre donné par DefineNum
+// une constante
+// un appel de procédure
+// l'instruction new
+
+// cette classe n'a pas de constructeur, car il n'y a jamais d'instance de cette classe
+// l'objet retourné par Compile est de la classe correspondant à l'instruction
+
+CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack();
+
+ pStk->SetStartError(p->GivStart());
+
+ // est-ce une expression entre parenthèse ?
+ if (IsOfType(p, ID_OPENPAR))
+ {
+ CBotInstr* inst = CBotExpression::Compile( p, pStk );
+
+ if ( NULL != inst )
+ {
+ if (IsOfType(p, ID_CLOSEPAR))
+ {
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_CLOSEPAR, p->GivStart());
+ }
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ // est-ce une opération unaire ?
+ CBotInstr* inst = CBotExprUnaire::Compile(p, pStk);
+ if (inst != NULL || !pStk->IsOk())
+ return pStack->Return(inst, pStk);
+
+ // est-ce un nom de variable ?
+ if (p->GivType() == TokenTypVar)
+ {
+ // c'est peut-être un appel de méthode sans le "this." devant
+ inst = CBotExprVar::CompileMethode(p, pStk);
+ if ( inst != NULL ) return pStack->Return(inst, pStk);
+
+
+ // est-ce un appel de procédure ?
+ inst = CBotInstrCall::Compile(p, pStk);
+ if ( inst != NULL || !pStk->IsOk() )
+ return pStack->Return(inst, pStk);
+
+
+ CBotToken* pvar = p;
+ // non, c'est une variable "ordinaire"
+ inst = CBotExprVar::Compile(p, pStk);
+
+ CBotToken* pp = p;
+ // post incrémenté ou décrémenté ?
+ if (IsOfType(p, ID_INC, ID_DEC))
+ {
+ if ( pStk->GivType() >= CBotTypBoolean )
+ {
+ pStk->SetError(TX_BADTYPE, pp);
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ // recompile la variable pour read-only
+ delete inst;
+ p = pvar;
+ inst = CBotExprVar::Compile(p, pStk, PR_READ);
+ p = p->GivNext();
+
+ CBotPostIncExpr* i = new CBotPostIncExpr();
+ i->SetToken(pp);
+ i->m_Instr = inst; // instruction associée
+ return pStack->Return(i, pStk);
+ }
+ return pStack->Return(inst, pStk);
+ }
+
+ // est-ce une variable préincrémentée ou prédécrémentée ?
+ CBotToken* pp = p;
+ if (IsOfType(p, ID_INC, ID_DEC))
+ {
+ CBotPreIncExpr* i = new CBotPreIncExpr();
+ i->SetToken(pp);
+
+ if (p->GivType() == TokenTypVar)
+ {
+ if (NULL != (i->m_Instr = CBotExprVar::Compile(p, pStk, PR_READ)))
+ {
+ if ( pStk->GivType() >= CBotTypBoolean )
+ {
+ pStk->SetError(TX_BADTYPE, pp);
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ return pStack->Return(i, pStk);
+ }
+ delete i;
+ return pStack->Return(NULL, pStk);
+ }
+ }
+
+ // est-ce un nombre ou un DefineNum ?
+ if (p->GivType() == TokenTypNum ||
+ p->GivType() == TokenTypDef )
+ {
+ CBotInstr* inst = CBotExprNum::Compile( p, pStk );
+ return pStack->Return(inst, pStk);
+ }
+
+ // est-ce une chaine ?
+ if (p->GivType() == TokenTypString)
+ {
+ CBotInstr* inst = CBotExprAlpha::Compile(p, pStk);
+ return pStack->Return(inst, pStk);
+ }
+
+ // est un élément "true" ou "false"
+ if (p->GivType() == ID_TRUE ||
+ p->GivType() == ID_FALSE )
+ {
+ CBotInstr* inst = CBotExprBool::Compile( p, pStk );
+ return pStack->Return(inst, pStk);
+ }
+
+ // est un objet à créer avec new
+ if (p->GivType() == ID_NEW)
+ {
+ CBotInstr* inst = CBotNew::Compile( p, pStk );
+ return pStack->Return(inst, pStk);
+ }
+
+ // est un pointeur nul
+ if (IsOfType( p, ID_NULL ))
+ {
+ CBotInstr* inst = new CBotExprNull ();
+ inst->SetToken( pp );
+ CBotVar* var = CBotVar::Create("", CBotTypNullPointer);
+ pStk->SetVar(var);
+ return pStack->Return(inst, pStk);
+ }
+
+ // est un nombre nan
+ if (IsOfType( p, ID_NAN ))
+ {
+ CBotInstr* inst = new CBotExprNan ();
+ inst->SetToken( pp );
+ CBotVar* var = CBotVar::Create("", CBotTypInt);
+ var->SetInit(IS_NAN);
+ pStk->SetVar(var);
+ return pStack->Return(inst, pStk);
+ }
+
+
+ return pStack->Return(NULL, pStk);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// gestion du post et pré- incrément/décrément
+
+// il n'y a pas de routine Compile, l'objet est créé directement
+// dans CBotParExpr::Compile
+
+CBotPostIncExpr::CBotPostIncExpr()
+{
+ m_Instr = NULL;
+ name = "CBotPostIncExpr";
+}
+
+CBotPostIncExpr::~CBotPostIncExpr()
+{
+ delete m_Instr;
+}
+
+CBotPreIncExpr::CBotPreIncExpr()
+{
+ m_Instr = NULL;
+ name = "CBotPreIncExpr";
+}
+
+CBotPreIncExpr::~CBotPreIncExpr()
+{
+ delete m_Instr;
+}
+
+BOOL CBotPostIncExpr::Execute(CBotStack* &pj)
+{
+ CBotStack* pile1 = pj->AddStack(this);
+ CBotStack* pile2 = pile1;
+
+ CBotVar* var1 = NULL;
+
+ if ( !((CBotExprVar*)m_Instr)->ExecuteVar(var1, pile2, NULL, TRUE) ) return FALSE; // récupère la variable selon champs et index
+
+ pile1->SetState(1);
+ pile1->SetCopyVar(var1); // place le résultat (avant incrémentation);
+
+ CBotStack* pile3 = pile2->AddStack(this);
+ if ( pile3->IfStep() ) return FALSE;
+
+ if ( var1->GivInit() == IS_NAN )
+ {
+ pile1->SetError( TX_OPNAN, &m_token );
+ }
+
+ if ( var1->GivInit() != IS_DEF )
+ {
+ pile1->SetError( TX_NOTINIT, &m_token );
+ }
+
+ if (GivTokenType() == ID_INC) var1->Inc();
+ else var1->Dec();
+
+ return pj->Return(pile1); // opération faite, résultat sur pile2
+}
+
+void CBotPostIncExpr::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile1 = pj->RestoreStack(this);
+ if ( pile1 == NULL ) return;
+
+ ((CBotExprVar*)m_Instr)->RestoreStateVar(pile1, bMain);
+
+ if ( pile1 != NULL ) pile1->RestoreStack(this);
+}
+
+BOOL CBotPreIncExpr::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ CBotVar* var1;
+
+ if ( pile->GivState() == 0 )
+ {
+ CBotStack* pile2 = pile;
+ if ( !((CBotExprVar*)m_Instr)->ExecuteVar(var1, pile2, NULL, TRUE) ) return FALSE; // récupère la variable selon champs et index
+ // pile2 est modifié en retour
+
+ if ( var1->GivInit() == IS_NAN )
+ {
+ pile->SetError( TX_OPNAN, &m_token );
+ return pj->Return(pile); // opération faite
+ }
+
+ if ( var1->GivInit() != IS_DEF )
+ {
+ pile->SetError( TX_NOTINIT, &m_token );
+ return pj->Return(pile); // opération faite
+ }
+
+ if (GivTokenType() == ID_INC) var1->Inc();
+ else var1->Dec(); // ((CBotVarInt*)var1)->m_val
+
+ pile->IncState();
+ }
+
+ if ( !m_Instr->Execute(pile) ) return FALSE;
+ return pj->Return(pile); // opération faite
+}
+
+
+void CBotPreIncExpr::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState() == 0 )
+ {
+ return;
+ }
+
+ m_Instr->RestoreState(pile, bMain);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile une expression unaire
+// +
+// -
+// not
+// !
+// ~
+
+CBotExprUnaire::CBotExprUnaire()
+{
+ m_Expr = NULL;
+ name = "CBotExprUnaire";
+}
+
+CBotExprUnaire::~CBotExprUnaire()
+{
+ delete m_Expr;
+}
+
+CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ int op = p->GivType();
+ CBotToken* pp = p;
+ if ( !IsOfTypeList( p, ID_ADD, ID_SUB, ID_LOG_NOT, ID_TXT_NOT, ID_NOT, 0 ) ) return NULL;
+
+ CBotCStack* pStk = pStack->TokenStack(pp);
+
+ CBotExprUnaire* inst = new CBotExprUnaire();
+ inst->SetToken(pp);
+
+ if ( NULL != (inst->m_Expr = CBotParExpr::Compile( p, pStk )) )
+ {
+ if ( op == ID_ADD && pStk->GivType() < CBotTypBoolean ) // seulement avec des nombre
+ return pStack->Return(inst, pStk);
+ if ( op == ID_SUB && pStk->GivType() < CBotTypBoolean ) // seulement avec des nombre
+ return pStack->Return(inst, pStk);
+ if ( op == ID_NOT && pStk->GivType() < CBotTypFloat ) // seulement avec des entiers
+ return pStack->Return(inst, pStk);
+ if ( op == ID_LOG_NOT && pStk->GivTypResult().Eq(CBotTypBoolean) )// seulement avec des booléens
+ return pStack->Return(inst, pStk);
+ if ( op == ID_TXT_NOT && pStk->GivTypResult().Eq(CBotTypBoolean) )// seulement avec des booléens
+ return pStack->Return(inst, pStk);
+
+ pStk->SetError(TX_BADTYPE, &inst->m_token);
+ }
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute l'expresson unaire
+
+BOOL CBotExprUnaire::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState() == 0 )
+ {
+ if (!m_Expr->Execute( pile )) return FALSE; // interrompu ?
+ pile->IncState();
+ }
+
+ CBotStack* pile2 = pile->AddStack();
+ if ( pile2->IfStep() ) return FALSE;
+
+ CBotVar* var = pile->GivVar(); // récupère le résultat sur la pile
+
+ switch (GivTokenType())
+ {
+ case ID_ADD:
+ break; // ne fait donc rien
+ case ID_SUB:
+ var->Neg(); // change le signe
+ break;
+ case ID_NOT:
+ case ID_LOG_NOT:
+ case ID_TXT_NOT:
+ var->Not();
+ break;
+ }
+ return pj->Return(pile); // transmet en dessous
+}
+
+void CBotExprUnaire::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL) return;
+
+ if ( pile->GivState() == 0 )
+ {
+ m_Expr->RestoreState( pile, bMain ); // interrompu ici !
+ return;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// gestion des index pour les tableaux
+// array [ expression ]
+
+
+CBotIndexExpr::CBotIndexExpr()
+{
+ m_expr = NULL;
+ name = "CBotIndexExpr";
+}
+
+CBotIndexExpr::~CBotIndexExpr()
+{
+ delete m_expr;
+}
+
+// trouve un champ à partir de l'instance à la compilation
+
+BOOL CBotIndexExpr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
+{
+ if ( pVar->GivType(1) != CBotTypArrayPointer )
+ __asm int 3;
+
+ pVar = ((CBotVarArray*)pVar)->GivItem(0, FALSE); // à la compilation rend l'élément [0]
+ if ( pVar == NULL )
+ {
+ pile->SetError(TX_OUTARRAY, m_token.GivEnd());
+ return FALSE;
+ }
+ if ( m_next3 != NULL ) return m_next3->ExecuteVar(pVar, pile);
+ return TRUE;
+}
+
+// idem à l'exécution
+// attention, modifie le pointeur à la pile volontairement
+// place les index calculés sur la pile supplémentaire
+
+BOOL CBotIndexExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep, BOOL bExtend)
+{
+ CBotStack* pj = pile;
+// DEBUG( "CBotIndexExpr::ExecuteVar", -1 , pj);
+
+ if ( pVar->GivType(1) != CBotTypArrayPointer )
+ __asm int 3;
+
+ pile = pile->AddStack();
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState() == 0 )
+ {
+ if ( !m_expr->Execute(pile) ) return FALSE;
+ pile->IncState();
+ }
+ // traite les tableaux
+
+ CBotVar* p = pile->GivVar(); // résultat sur la pile
+
+ if ( p == NULL || p->GivType() > CBotTypDouble )
+ {
+ pile->SetError(TX_BADINDEX, prevToken);
+ return pj->Return(pile);
+ }
+
+ int n = p->GivValInt(); // position dans le tableau
+// DEBUG( "CBotIndexExpr::ExecuteVar", n , pj);
+
+ pVar = ((CBotVarArray*)pVar)->GivItem(n, bExtend);
+ if ( pVar == NULL )
+ {
+ pile->SetError(TX_OUTARRAY, prevToken);
+ return pj->Return(pile);
+ }
+
+// DEBUG( "CBotIndexExpr::ExecuteVar", -2 , pj);
+ //if ( bUpdate )
+ pVar->Maj(pile->GivPUser(), TRUE);
+
+// DEBUG( "CBotIndexExpr::ExecuteVar", -3 , pj);
+ if ( m_next3 != NULL &&
+ !m_next3->ExecuteVar(pVar, pile, prevToken, bStep, bExtend) ) return FALSE;
+
+// DEBUG( "CBotIndexExpr::ExecuteVar", -4 , pj);
+ return TRUE; // ne libère pas la pile
+ // pour éviter de recalculer les index deux fois le cas échéant
+}
+
+void CBotIndexExpr::RestoreStateVar(CBotStack* &pile, BOOL bMain)
+{
+ pile = pile->RestoreStack();
+ if ( pile == NULL ) return;
+
+ if ( bMain && pile->GivState() == 0 )
+ {
+ m_expr->RestoreState(pile, TRUE);
+ return;
+ }
+
+ if ( m_next3 )
+ m_next3->RestoreStateVar(pile, bMain);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// gestion des champs dans une instance (opérateur point)
+// toto.x
+
+
+CBotFieldExpr::CBotFieldExpr()
+{
+ name = "CBotFieldExpr";
+ m_nIdent = 0;
+}
+
+CBotFieldExpr::~CBotFieldExpr()
+{
+}
+
+void CBotFieldExpr::SetUniqNum(int num)
+{
+ m_nIdent = num;
+}
+
+
+// trouve un champ à partir de l'instance à la compilation
+
+BOOL CBotFieldExpr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
+{
+ if ( pVar->GivType(1) != CBotTypPointer )
+ __asm int 3;
+
+// pVar = pVar->GivItem(m_token.GivString());
+ pVar = pVar->GivItemRef(m_nIdent);
+ if ( pVar == NULL )
+ {
+ pile->SetError(TX_NOITEM, &m_token);
+ return FALSE;
+ }
+
+ if ( m_next3 != NULL &&
+ !m_next3->ExecuteVar(pVar, pile) ) return FALSE;
+
+ return TRUE;
+}
+
+// idem à l'exécution
+
+BOOL CBotFieldExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep, BOOL bExtend)
+{
+ CBotStack* pj = pile;
+ pile = pile->AddStack(this); // modifie pile en sortie
+ if ( pile == EOX ) return TRUE;
+
+// DEBUG( "CBotFieldExpre::ExecuteVar "+m_token.GivString(), 0, pj );
+
+ if ( pVar->GivType(1) != CBotTypPointer )
+ __asm int 3;
+
+ CBotVarClass* pItem = pVar->GivPointer();
+ if ( pItem == NULL )
+ {
+ pile->SetError(TX_NULLPT, prevToken);
+ return pj->Return( pile );
+ }
+ if ( pItem->GivUserPtr() == OBJECTDELETED )
+ {
+ pile->SetError(TX_DELETEDPT, prevToken);
+ return pj->Return( pile );
+ }
+
+ if ( bStep && pile->IfStep() ) return FALSE;
+
+// pVar = pVar->GivItem(m_token.GivString());
+ pVar = pVar->GivItemRef(m_nIdent);
+ if ( pVar == NULL )
+ {
+ pile->SetError(TX_NOITEM, &m_token);
+ return pj->Return( pile );
+ }
+
+ if ( pVar->IsStatic() )
+ {
+// DEBUG( "IsStatic", 0, pj) ;
+ // pour une variable statique, la prend dans la classe elle-même
+ CBotClass* pClass = pItem->GivClass();
+ pVar = pClass->GivItem(m_token.GivString());
+// DEBUG( "done "+pVar->GivName(), 0, pj) ;
+ }
+
+ // demande la mise à jour de l'élément, s'il y a lieu
+ pVar->Maj(pile->GivPUser(), TRUE);
+
+ if ( m_next3 != NULL &&
+ !m_next3->ExecuteVar(pVar, pile, &m_token, bStep, bExtend) ) return FALSE;
+
+ return TRUE; // ne libère pas la pile
+ // pour conserver l'état SetState() correspondant à l'étape
+}
+
+void CBotFieldExpr::RestoreStateVar(CBotStack* &pj, BOOL bMain)
+{
+ pj = pj->RestoreStack(this); // modifie pj en sortie
+ if ( pj == NULL ) return;
+
+ if ( m_next3 != NULL )
+ m_next3->RestoreStateVar(pj, bMain);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un opérande gauche pour une assignation
+
+CBotLeftExpr::CBotLeftExpr()
+{
+ name = "CBotLeftExpr";
+ m_nIdent = 0;
+}
+
+CBotLeftExpr::~CBotLeftExpr()
+{
+}
+
+// compile une expression pour un left-opérande ( à gauche d'une assignation)
+// cela peut être
+// toto
+// toto[ 3 ]
+// toto.x
+// toto.pos.x
+// toto[2].pos.x
+// toto[1].pos[2].x
+// toto[1][2][3]
+
+CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack();
+
+ pStk->SetStartError(p->GivStart());
+
+ // est-ce un nom de variable ?
+ if (p->GivType() == TokenTypVar)
+ {
+ CBotLeftExpr* inst = new CBotLeftExpr(); // crée l'objet
+
+ inst->SetToken(p);
+
+ CBotVar* var;
+
+ if ( NULL != (var = pStk->FindVar(p)) ) // cherche si variable connue
+ {
+ inst->m_nIdent = var->GivUniqNum();
+ if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
+ {
+ if ( var->IsPrivate(PR_READ) &&
+ !pStk->GivBotCall()->m_bCompileClass)
+ {
+ pStk->SetError( TX_PRIVATE, p );
+ goto err;
+ }
+ // il s'agit d'un élement de la classe courante
+ // ajoute l'équivalent d'un this. devant
+ CBotToken pthis("this");
+ inst->SetToken(&pthis);
+ inst->m_nIdent = -2; // ident pour this
+
+ CBotFieldExpr* i = new CBotFieldExpr(); // nouvel élément
+ i->SetToken( p ); // garde le nom du token
+ inst->AddNext3(i); // ajoute à la suite
+
+ var = pStk->FindVar(pthis);
+ var = var->GivItem(p->GivString());
+ i->SetUniqNum(var->GivUniqNum());
+ }
+ p = p->GivNext(); // token suivant
+
+ while (TRUE)
+ {
+ if ( var->GivType() == CBotTypArrayPointer ) // s'il sagit d'un tableau
+ {
+ if ( IsOfType( p, ID_OPBRK ) ) // regarde s'il y a un index
+ {
+ CBotIndexExpr* i = new CBotIndexExpr();
+ i->m_expr = CBotExpression::Compile(p, pStk); // compile la formule
+ inst->AddNext3(i); // ajoute à la chaine
+
+ var = ((CBotVarArray*)var)->GivItem(0,TRUE); // donne le composant [0]
+
+ if ( i->m_expr == NULL )
+ {
+ pStk->SetError( TX_BADINDEX, p->GivStart() );
+ goto err;
+ }
+
+ if ( !pStk->IsOk() || !IsOfType( p, ID_CLBRK ) )
+ {
+ pStk->SetError( TX_CLBRK, p->GivStart() );
+ goto err;
+ }
+ continue;
+ }
+ }
+
+ if ( var->GivType(1) == CBotTypPointer ) // pour les classes
+ {
+ if ( IsOfType(p, ID_DOT) )
+ {
+ CBotToken* pp = p;
+
+ CBotFieldExpr* i = new CBotFieldExpr(); // nouvel élément
+ i->SetToken( pp ); // garde le nom du token
+ inst->AddNext3(i); // ajoute à la suite
+
+ if ( p->GivType() == TokenTypVar ) // doit être un nom
+ {
+ var = var->GivItem(p->GivString()); // récupère l'item correpondant
+ if ( var != NULL )
+ {
+ if ( var->IsPrivate(PR_READ) &&
+ !pStk->GivBotCall()->m_bCompileClass)
+ {
+ pStk->SetError( TX_PRIVATE, pp );
+ goto err;
+ }
+
+ i->SetUniqNum(var->GivUniqNum());
+ p = p->GivNext(); // saute le nom
+ continue;
+ }
+ pStk->SetError( TX_NOITEM, p );
+ }
+ pStk->SetError( TX_DOT, p->GivStart() );
+ goto err;
+ }
+ }
+ break;
+ }
+
+
+ if ( pStk->IsOk() ) return (CBotLeftExpr*) pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_UNDEFVAR, p);
+err:
+ delete inst;
+ return (CBotLeftExpr*) pStack->Return(NULL, pStk);
+ }
+
+ return (CBotLeftExpr*) pStack->Return(NULL, pStk);
+}
+
+// exécute, trouve une variable et lui assigne le résultat de la pile
+
+BOOL CBotLeftExpr::Execute(CBotStack* &pj, CBotStack* array)
+{
+ CBotStack* pile = pj->AddStack();
+// if ( pile == EOX ) return TRUE;
+
+// if ( pile->IfStep() ) return FALSE;
+
+ CBotVar* var1 = NULL;
+ CBotVar* var2 = NULL;
+
+// var1 = pile->FindVar(m_token, FALSE, TRUE);
+ if (!ExecuteVar( var1, array, NULL, FALSE )) return FALSE;
+ // retrouve la variable (et pas la copie)
+ if (pile->IfStep()) return FALSE;
+
+ if ( var1 )
+ {
+ var2 = pj->GivVar(); // resultat sur la pile d'entrée
+ if ( var2 )
+ {
+ CBotTypResult t1 = var1->GivTypResult();
+ CBotTypResult t2 = var2->GivTypResult();
+ if ( t2.Eq(CBotTypPointer) )
+ {
+ CBotClass* c1 = t1.GivClass();
+ CBotClass* c2 = t2.GivClass();
+ if ( !c2->IsChildOf(c1))
+ {
+ CBotToken* pt = &m_token;
+ pile->SetError(TX_BADTYPE, pt);
+ return pj->Return(pile); // opération faite
+ }
+ }
+ var1->SetVal(var2); // fait l'assignation
+ }
+ pile->SetCopyVar( var1 ); // remplace sur la pile par une copie de la variable elle-même
+ // (pour avoir le nom)
+ }
+
+ return pj->Return(pile); // opération faite
+}
+
+// retrouve une variable pendant la compilation
+
+BOOL CBotLeftExpr::ExecuteVar(CBotVar* &pVar, CBotCStack* &pile)
+{
+ pVar = pile->FindVar(m_token);
+ if ( pVar == NULL ) return FALSE;
+
+ if ( m_next3 != NULL &&
+ !m_next3->ExecuteVar(pVar, pile) ) return FALSE;
+
+ return TRUE;
+}
+
+// retrouve une variable à l'exécution
+
+BOOL CBotLeftExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep)
+{
+ pile = pile->AddStack( this ); // déplace la pile
+
+ pVar = pile->FindVar(m_nIdent);
+ if ( pVar == NULL )
+ {
+#ifdef _DEBUG
+ __asm int 3;
+#endif
+ pile->SetError(2, &m_token);
+ return FALSE;
+ }
+
+ if ( bStep && m_next3 == NULL && pile->IfStep() ) return FALSE;
+
+ if ( m_next3 != NULL &&
+ !m_next3->ExecuteVar(pVar, pile, &m_token, bStep, TRUE) ) return FALSE;
+
+ return TRUE;
+}
+
+void CBotLeftExpr::RestoreStateVar(CBotStack* &pile, BOOL bMain)
+{
+ pile = pile->RestoreStack( this ); // déplace la pile
+ if ( pile == NULL ) return;
+
+ if ( m_next3 != NULL )
+ m_next3->RestoreStateVar(pile, bMain);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// transforme une chaîne en nombre entier
+// peut être de la forme 0xabc123
+
+long GivNumInt( const char* p )
+{
+ long num = 0;
+ while (*p >= '0' && *p <= '9')
+ {
+ num = num * 10 + *p - '0';
+ p++;
+ }
+ if ( *p == 'x' || *p == 'X' )
+ {
+ while (*++p != 0)
+ {
+ if ( *p >= '0' && *p <= '9' )
+ {
+ num = num * 16 + *p - '0';
+ continue;
+ }
+ if ( *p >= 'A' && *p <= 'F' )
+ {
+ num = num * 16 + *p - 'A' + 10;
+ continue;
+ }
+ if ( *p >= 'a' && *p <= 'f' )
+ {
+ num = num * 16 + *p - 'a' + 10;
+ continue;
+ }
+ break;
+ }
+ }
+ return num;
+}
+
+// transforme une chaîne en un nombre réel
+
+extern float GivNumFloat( const char* p )
+{
+ double num = 0;
+ double div = 10;
+ BOOL bNeg = FALSE;
+
+ if (*p == '-')
+ {
+ bNeg = TRUE;
+ p++;
+ }
+ while (*p >= '0' && *p <= '9')
+ {
+ num = num * 10. + (*p - '0');
+ p++;
+ }
+
+ if ( *p == '.' )
+ {
+ p++;
+ while (*p >= '0' && *p <= '9')
+ {
+ num = num + (*p - '0') / div;
+ div = div * 10;
+ p++;
+ }
+ }
+
+ int exp = 0;
+ if ( *p == 'e' || *p == 'E' )
+ {
+ char neg = 0;
+ p++;
+ if ( *p == '-' || *p == '+' ) neg = *p++;
+
+ while (*p >= '0' && *p <= '9')
+ {
+ exp = exp * 10 + (*p - '0');
+ p++;
+ }
+ if ( neg == '-' ) exp = -exp;
+ }
+
+ while ( exp > 0 )
+ {
+ num *= 10.0;
+ exp--;
+ }
+
+ while ( exp < 0 )
+ {
+ num /= 10.0;
+ exp++;
+ }
+
+ if ( bNeg ) num = -num;
+ return (float)num;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un token représentant un nombre
+
+CBotExprNum::CBotExprNum()
+{
+ name = "CBotExprNum";
+}
+
+CBotExprNum::~CBotExprNum()
+{
+}
+
+CBotInstr* CBotExprNum::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack();
+
+ CBotExprNum* inst = new CBotExprNum();
+
+ inst->SetToken(p);
+ CBotString s = p->GivString();
+
+ inst->m_numtype = CBotTypInt;
+ if ( p->GivType() == TokenTypDef )
+ {
+ inst->m_valint = p->GivIdKey();
+ }
+ else
+ {
+ if ( s.Find('.') >= 0 || ( s.Find('x') < 0 && ( s.Find('e') >= 0 || s.Find('E') >= 0 ) ) )
+ {
+ inst->m_numtype = CBotTypFloat;
+ inst->m_valfloat = GivNumFloat(s);
+ }
+ else
+ {
+ inst->m_valint = GivNumInt(s);
+ }
+ }
+
+ if (pStk->NextToken(p))
+ {
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, inst->m_numtype);
+ pStk->SetVar(var);
+
+ return pStack->Return(inst, pStk);
+ }
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute, retourne le nombre correspondant
+
+BOOL CBotExprNum::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, m_numtype);
+
+ CBotString nombre ;
+ if ( m_token.GivType() == TokenTypDef )
+ {
+ nombre = m_token.GivString();
+ }
+
+ switch (m_numtype)
+ {
+ case CBotTypShort:
+ case CBotTypInt:
+ var->SetValInt( m_valint, nombre ); // valeur du nombre
+ break;
+ case CBotTypFloat:
+ var->SetValFloat( m_valfloat ); // valeur du nombre
+ break;
+ }
+ pile->SetVar( var ); // mis sur la pile
+
+ return pj->Return(pile); // c'est ok
+}
+
+void CBotExprNum::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain ) pj->RestoreStack(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un token représentant une chaine de caractères
+
+CBotExprAlpha::CBotExprAlpha()
+{
+ name = "CBotExprAlpha";
+}
+
+CBotExprAlpha::~CBotExprAlpha()
+{
+}
+
+CBotInstr* CBotExprAlpha::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack();
+
+ CBotExprAlpha* inst = new CBotExprAlpha();
+
+ inst->SetToken(p);
+ p = p->GivNext();
+
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypString);
+ pStk->SetVar(var);
+
+ return pStack->Return(inst, pStk);
+}
+
+// exécute, retourne la chaîne correspondante
+
+BOOL CBotExprAlpha::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypString);
+
+ CBotString chaine = m_token.GivString();
+ chaine = chaine.Mid(1, chaine.GivLength()-2); // enlève les guillemets
+
+ var->SetValString( chaine ); // valeur du nombre
+
+ pile->SetVar( var ); // mis sur la pile
+
+ return pj->Return(pile);
+}
+
+void CBotExprAlpha::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain ) pj->RestoreStack(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un token représentant true ou false
+
+CBotExprBool::CBotExprBool()
+{
+ name = "CBotExprBool";
+}
+
+CBotExprBool::~CBotExprBool()
+{
+}
+
+CBotInstr* CBotExprBool::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack();
+ CBotExprBool* inst = NULL;
+
+ if ( p->GivType() == ID_TRUE ||
+ p->GivType() == ID_FALSE )
+ {
+ inst = new CBotExprBool();
+ inst->SetToken(p); // mémorise l'opération false ou true
+ p = p->GivNext();
+
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypBoolean);
+ pStk->SetVar(var);
+ }
+
+ return pStack->Return(inst, pStk);
+}
+
+// exécute, retourne true ou false
+
+BOOL CBotExprBool::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypBoolean);
+
+ if (GivTokenType() == ID_TRUE) var->SetValInt(1);
+ else var->SetValInt(0);
+
+ pile->SetVar( var ); // mis sur la pile
+ return pj->Return(pile); // transmet en dessous
+}
+
+void CBotExprBool::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain ) pj->RestoreStack(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// gestion de l'opérande "null"
+
+CBotExprNull::CBotExprNull()
+{
+ name = "CBotExprNull";
+}
+
+CBotExprNull::~CBotExprNull()
+{
+}
+
+// exécute, retourne un pointeur vide
+
+BOOL CBotExprNull::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypNullPointer);
+
+ var->SetInit(TRUE); // pointeur null valide
+ pile->SetVar( var ); // mis sur la pile
+ return pj->Return(pile); // transmet en dessous
+}
+
+void CBotExprNull::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain ) pj->RestoreStack(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// gestion de l'opérande "nan"
+
+CBotExprNan::CBotExprNan()
+{
+ name = "CBotExprNan";
+}
+
+CBotExprNan::~CBotExprNan()
+{
+}
+
+// exécute, retourne un pointeur vide
+
+BOOL CBotExprNan::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypInt);
+
+ var->SetInit(IS_NAN); // nombre nan
+ pile->SetVar( var ); // mis sur la pile
+ return pj->Return(pile); // transmet en dessous
+}
+
+void CBotExprNan::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain ) pj->RestoreStack(this);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un nom de variable
+// vérifie qu'elle est connue sur la pile
+// et qu'elle a été initialisée
+
+CBotExprVar::CBotExprVar()
+{
+ name = "CBotExprVar";
+ m_nIdent = 0;
+}
+
+CBotExprVar::~CBotExprVar()
+{
+}
+
+CBotInstr* CBotExprVar::Compile(CBotToken* &p, CBotCStack* pStack, int privat)
+{
+ CBotToken* pDebut = p;
+ CBotCStack* pStk = pStack->TokenStack();
+
+ pStk->SetStartError(p->GivStart());
+
+ // est-ce un nom de variable ?
+ if (p->GivType() == TokenTypVar)
+ {
+ CBotInstr* inst = new CBotExprVar(); // crée l'objet
+
+ inst->SetToken(p);
+
+ CBotVar* var;
+
+ if ( NULL != (var = pStk->FindVar(p)) ) // cherche si variable connue
+ {
+ int ident = var->GivUniqNum();
+ ((CBotExprVar*)inst)->m_nIdent = ident; // l'identifie par son numéro
+
+ if (ident > 0 && ident < 9000)
+ {
+ if ( var->IsPrivate(privat) &&
+ !pStk->GivBotCall()->m_bCompileClass)
+ {
+ pStk->SetError( TX_PRIVATE, p );
+ goto err;
+ }
+
+ // il s'agit d'un élement de la classe courante
+ // ajoute l'équivalent d'un this. devant
+ inst->SetToken(&CBotToken("this"));
+ ((CBotExprVar*)inst)->m_nIdent = -2; // ident pour this
+
+ CBotFieldExpr* i = new CBotFieldExpr(); // nouvel élément
+ i->SetToken( p ); // garde le nom du token
+ i->SetUniqNum(ident);
+ inst->AddNext3(i); // ajoute à la suite
+ }
+
+ p = p->GivNext(); // token suivant
+
+ while (TRUE)
+ {
+ if ( var->GivType() == CBotTypArrayPointer ) // s'il sagit d'un tableau
+ {
+ if ( IsOfType( p, ID_OPBRK ) ) // regarde s'il y a un index
+ {
+ CBotIndexExpr* i = new CBotIndexExpr();
+ i->m_expr = CBotExpression::Compile(p, pStk); // compile la formule
+ inst->AddNext3(i); // ajoute à la chaine
+
+ var = ((CBotVarArray*)var)->GivItem(0,TRUE); // donne le composant [0]
+
+ if ( i->m_expr == NULL )
+ {
+ pStk->SetError( TX_BADINDEX, p->GivStart() );
+ goto err;
+ }
+ if ( !pStk->IsOk() || !IsOfType( p, ID_CLBRK ) )
+ {
+ pStk->SetError( TX_CLBRK, p->GivStart() );
+ goto err;
+ }
+ continue;
+ }
+ //// pStk->SetError( TX_OPBRK, p->GivStart() );
+ }
+ if ( var->GivType(1) == CBotTypPointer ) // pour les classes
+ {
+ if ( IsOfType(p, ID_DOT) )
+ {
+ CBotToken* pp = p;
+
+ if ( p->GivType() == TokenTypVar ) // doit être un nom
+ {
+ if ( p->GivNext()->GivType() == ID_OPENPAR )// un appel de méthode ?
+ {
+ CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
+ if ( !pStk->IsOk() ) goto err;
+ inst->AddNext3(i); // ajoute à la suite
+ return pStack->Return(inst, pStk);
+ }
+ else
+ {
+ CBotFieldExpr* i = new CBotFieldExpr(); // nouvel élément
+ i->SetToken( pp ); // garde le nom du token
+ inst->AddNext3(i); // ajoute à la suite
+ var = var->GivItem(p->GivString()); // récupère l'item correpondant
+ if ( var != NULL )
+ {
+ i->SetUniqNum(var->GivUniqNum());
+ if ( var->IsPrivate() &&
+ !pStk->GivBotCall()->m_bCompileClass)
+ {
+ pStk->SetError( TX_PRIVATE, pp );
+ goto err;
+ }
+ }
+ }
+
+
+ if ( var != NULL )
+ {
+ p = p->GivNext(); // saute le nom
+ continue;
+ }
+ pStk->SetError( TX_NOITEM, p );
+ goto err;
+ }
+ pStk->SetError( TX_DOT, p->GivStart() );
+ goto err;
+ }
+ }
+
+ break;
+ }
+
+ pStk->SetCopyVar(var); // place une copie de la variable sur la pile (pour le type)
+ if ( pStk->IsOk() ) return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_UNDEFVAR, p);
+err:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ return pStack->Return(NULL, pStk);
+}
+
+CBotInstr* CBotExprVar::CompileMethode(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p;
+ CBotCStack* pStk = pStack->TokenStack();
+
+ pStk->SetStartError(pp->GivStart());
+
+ // est-ce un nom de variable ?
+ if (pp->GivType() == TokenTypVar)
+ {
+ CBotToken pthis("this");
+ CBotVar* var = pStk->FindVar(pthis);
+ if ( var == 0 ) return pStack->Return(NULL, pStk);
+
+ CBotInstr* inst = new CBotExprVar(); // crée l'objet
+
+ // il s'agit d'un élement de la classe courante
+ // ajoute l'équivalent d'un this. devant
+ inst->SetToken(&pthis);
+ ((CBotExprVar*)inst)->m_nIdent = -2; // ident pour this
+
+ CBotToken* pp = p;
+
+ if ( pp->GivType() == TokenTypVar ) // doit être un nom
+ {
+ if ( pp->GivNext()->GivType() == ID_OPENPAR ) // un appel de méthode ?
+ {
+ CBotInstr* i = CBotInstrMethode::Compile(pp, pStk, var);
+ if ( pStk->IsOk() )
+ {
+ inst->AddNext3(i); // ajoute à la suite
+ p = pp; // instructions passées
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(0,0); // l'erreur n'est pas traitée ici
+ }
+ }
+ delete inst;
+ }
+ return pStack->Return(NULL, pStk);
+}
+
+
+// exécute, rend la valeur d'une variable
+
+BOOL CBotExprVar::Execute(CBotStack* &pj)
+{
+ CBotVar* pVar = NULL;
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+// if ( pile->IfStep() ) return FALSE;
+
+ CBotStack* pile1 = pile;
+
+ if ( pile1->GivState() == 0 )
+ {
+ if ( !ExecuteVar(pVar, pile, NULL, TRUE) ) return FALSE; // récupère la variable selon champs et index
+// DEBUG("CBotExprVar::Execute", 1 , pj);
+
+ if ( pVar ) pile1->SetCopyVar(pVar); // la place une copie sur la pile
+ else
+ {
+//-- pile1->SetVar(NULL); // la pile contient déjà le resultat (méthode)
+ return pj->Return(pile1);
+ }
+ pile1->IncState();
+ }
+
+ pVar = pile1->GivVar(); // récupère si interrompu
+
+ if ( pVar == NULL )
+ {
+// pile1->SetError(TX_NULLPT, &m_token);
+ return pj->Return(pile1);
+ }
+
+ if ( pVar->GivInit() == IS_UNDEF )
+ {
+ CBotToken* pt = &m_token;
+ while ( pt->GivNext() != NULL ) pt = pt->GivNext();
+ pile1->SetError(TX_NOTINIT, pt);
+ return pj->Return(pile1);
+ }
+ return pj->Return(pile1); // opération faite
+}
+
+void CBotExprVar::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ CBotStack* pile1 = pile;
+
+ if ( pile1->GivState() == 0 )
+ {
+ RestoreStateVar(pile, bMain); // récupère la variable selon champs et index
+ return;
+ }
+}
+
+// retrouve une variable à l'exécution
+
+BOOL CBotExprVar::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, BOOL bStep)
+{
+ CBotStack* pile = pj;
+ pj = pj->AddStack( this );
+
+ if ( bStep && m_nIdent>0 && pj->IfStep() ) return FALSE;
+
+ pVar = pj->FindVar(m_nIdent, TRUE); // cherche la variable avec mise à jour si nécessaire
+ if ( pVar == NULL )
+ {
+#ifdef _DEBUG
+ __asm int 3;
+#endif
+ pj->SetError(1, &m_token);
+ return FALSE;
+ }
+ if ( m_next3 != NULL &&
+ !m_next3->ExecuteVar(pVar, pj, &m_token, bStep, FALSE) )
+ return FALSE; // Champs d'une instance, tableau, méthode ?
+
+ return pile->ReturnKeep( pj ); // ne rend pas la pile mais récupère le résultat si une méthode a été appelée
+}
+
+
+// retrouve une variable à l'exécution
+
+void CBotExprVar::RestoreStateVar(CBotStack* &pj, BOOL bMain)
+{
+ pj = pj->RestoreStack( this );
+ if ( pj == NULL ) return;
+
+ if ( m_next3 != NULL )
+ m_next3->RestoreStateVar(pj, bMain);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+// compile une liste de paramètres
+
+CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
+{
+ BOOL first = TRUE;
+ CBotInstr* ret = NULL; // pour la liste à retourner
+
+// pStack->SetStartError(p->GivStart());
+ CBotCStack* pile = pStack;
+ int i = 0;
+
+ if ( IsOfType(p, ID_OPENPAR) )
+ {
+ int start, end;
+ if (!IsOfType(p, ID_CLOSEPAR)) while (TRUE)
+ {
+ start = p->GivStart();
+ pile = pile->TokenStack(); // garde les résultats sur la pile
+
+ if ( first ) pStack->SetStartError(start);
+ first = FALSE;
+
+ CBotInstr* param = CBotExpression::Compile(p, pile);
+ end = p->GivStart();
+
+ if ( !pile->IsOk() )
+ {
+ return pStack->Return(NULL, pile);
+ }
+
+ if ( ret == NULL ) ret = param;
+ else ret->AddNext(param); // construit la liste
+
+ if ( param != NULL )
+ {
+ if ( pile->GivTypResult().Eq(99) )
+ {
+ delete pStack->TokenStack();
+ pStack->SetError(TX_VOID, p->GivStart());
+ return NULL;
+ }
+ ppVars[i] = pile->GivVar();
+ ppVars[i]->GivToken()->SetPos(start, end);
+ i++;
+
+ if (IsOfType(p, ID_COMMA)) continue; // saute la virgule
+ if (IsOfType(p, ID_CLOSEPAR)) break;
+ }
+
+ pStack->SetError(TX_CLOSEPAR, p->GivStart());
+ delete pStack->TokenStack();
+ return NULL;
+ }
+ }
+ ppVars[i] = NULL;
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile un appel d'une méthode
+
+CBotInstrMethode::CBotInstrMethode()
+{
+ m_Parameters = NULL;
+ m_MethodeIdent = 0;
+// m_nThisIdent = 0;
+ name = "CBotInstrMethode";
+}
+
+CBotInstrMethode::~CBotInstrMethode()
+{
+ delete m_Parameters;
+}
+
+CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* var)
+{
+ CBotInstrMethode* inst = new CBotInstrMethode();
+ inst->SetToken(p); // token correspondant
+
+// inst->m_nThisIdent = CBotVar::NextUniqNum();
+
+ if ( NULL != var )
+ {
+ CBotToken* pp = p;
+ p = p->GivNext();
+
+ if ( p->GivType() == ID_OPENPAR )
+ {
+ inst->m_NomMethod = pp->GivString();
+
+ // compile la liste des paramètres
+ CBotVar* ppVars[1000];
+ inst->m_Parameters = CompileParams(p, pStack, ppVars);
+
+ if ( pStack->IsOk() )
+ {
+ CBotClass* pClass = var->GivClass(); // pointeur à la classe
+ inst->m_ClassName = pClass->GivName(); // le nom de la classe
+ CBotTypResult r = pClass->CompileMethode(inst->m_NomMethod, var, ppVars,
+ pStack, inst->m_MethodeIdent);
+ delete pStack->TokenStack(); // libères les paramètres encore sur la pile
+ inst->m_typRes = r;
+
+ if (inst->m_typRes.GivType() > 20)
+ {
+ pStack->SetError(inst->m_typRes.GivType(), pp);
+ delete inst;
+ return NULL;
+ }
+ // met un résultat sur la pile pour avoir quelque chose
+ if (inst->m_typRes.GivType() > 0)
+ {
+ CBotVar* pResult = CBotVar::Create("", inst->m_typRes);
+ if (inst->m_typRes.Eq(CBotTypClass))
+ {
+// CBotClass* pClass = CBotClass::Find(inst->m_RetClassName);
+ pResult->SetClass(inst->m_typRes.GivClass());
+ }
+ pStack->SetVar(pResult);
+ }
+ return inst;
+ }
+ delete inst;
+ return NULL;
+ }
+ }
+ pStack->SetError( 1234, p );
+ delete inst;
+ return NULL;
+}
+
+// exécute l'appel de méthode
+
+BOOL CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, BOOL bStep, BOOL bExtend)
+{
+ CBotVar* ppVars[1000];
+ CBotStack* pile1 = pj->AddStack(this, TRUE); // une place pour la copie de This
+// if ( pile1 == EOX ) return TRUE;
+
+// DEBUG( "CBotInstrMethode::ExecuteVar", 0, pj );
+
+ if ( pVar->GivPointer() == NULL )
+ {
+ pj->SetError( TX_NULLPT, prevToken );
+ }
+
+ if ( pile1->IfStep() ) return FALSE;
+
+ CBotStack* pile2 = pile1->AddStack(); // et pour les paramètres à venir
+
+ if ( pile1->GivState() == 0)
+ {
+ CBotVar* pThis = CBotVar::Create(pVar);
+ pThis->Copy(pVar);
+ // la valeur de This doit être prise avant l'évaluation des paramètres
+ // Test.Action( Test = Autre );
+ // Action doit agir sur la valeur avant Test = Autre !!
+ pThis->SetName("this");
+// pThis->SetUniqNum(m_nThisIdent);
+ pThis->SetUniqNum(-2);
+ pile1->AddVar(pThis);
+ pile1->IncState();
+ }
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+ if ( p != NULL) while ( TRUE )
+ {
+ if ( pile2->GivState() == 0 )
+ {
+ if (!p->Execute(pile2)) return FALSE; // interrompu ici ?
+ if (!pile2->SetState(1)) return FALSE; // marque spéciale pour reconnaîre les paramètres
+ }
+ ppVars[i++] = pile2->GivVar(); // construit la liste des pointeurs
+ pile2 = pile2->AddStack(); // de la place sur la pile pour les résultats
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ CBotClass* pClass = CBotClass::Find(m_ClassName);
+ CBotVar* pThis = pile1->FindVar(-2);
+ CBotVar* pResult = NULL;
+ if (m_typRes.GivType() > 0) pResult = CBotVar::Create("", m_typRes);
+ if (m_typRes.Eq(CBotTypClass))
+ {
+// CBotClass* pClass = CBotClass::Find(m_RetClassName);
+ pResult->SetClass(m_typRes.GivClass());
+ }
+ CBotVar* pRes = pResult;
+
+ if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
+ pThis, ppVars,
+ pResult, pile2, GivToken())) return FALSE; // interrompu
+ if (pRes != pResult) delete pRes;
+
+ pVar = NULL; // ne retourne pas une valeur par cela
+ return pj->Return(pile2); // libère toute la pile
+}
+
+void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotVar* ppVars[1000];
+ CBotStack* pile1 = pile->RestoreStack(this); // une place pour la copie de This
+ if ( pile1 == NULL ) return;
+
+ CBotStack* pile2 = pile1->RestoreStack(); // et pour les paramètres à venir
+ if ( pile2 == NULL ) return;
+
+ CBotVar* pThis = pile1->FindVar("this");
+// pThis->SetUniqNum(m_nThisIdent);
+ pThis->SetUniqNum(-2);
+
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+ if ( p != NULL) while ( TRUE )
+ {
+ if ( pile2->GivState() == 0 )
+ {
+ p->RestoreState(pile2, TRUE); // interrompu ici !
+ return;
+ }
+ ppVars[i++] = pile2->GivVar(); // construit la liste des pointeurs
+ pile2 = pile2->RestoreStack();
+ if ( pile2 == NULL ) return;
+
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ CBotClass* pClass = CBotClass::Find(m_ClassName);
+ CBotVar* pResult = NULL;
+
+ CBotVar* pRes = pResult;
+
+ pClass->RestoreMethode(m_MethodeIdent, m_NomMethod,
+ pThis, ppVars, pile2);
+}
+
+
+BOOL CBotInstrMethode::Execute(CBotStack* &pj)
+{
+ CBotVar* ppVars[1000];
+ CBotStack* pile1 = pj->AddStack(this, TRUE); // une place pour la copie de This
+// if ( pile1 == EOX ) return TRUE;
+
+ if ( pile1->IfStep() ) return FALSE;
+
+ CBotStack* pile2 = pile1->AddStack(); // et pour les paramètres à venir
+
+ if ( pile1->GivState() == 0)
+ {
+ CBotVar* pThis = pile1->CopyVar(m_token);
+ // la valeur de This doit être prise avant l'évaluation des paramètres
+ // Test.Action( Test = Autre );
+ // Action doit agir sur la valeur avant Test = Autre !!
+ pThis->SetName("this");
+ pile1->AddVar(pThis);
+ pile1->IncState();
+ }
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+ if ( p != NULL) while ( TRUE )
+ {
+ if ( pile2->GivState() == 0 )
+ {
+ if (!p->Execute(pile2)) return FALSE; // interrompu ici ?
+ if (!pile2->SetState(1)) return FALSE; // marque spéciale pour reconnaîre les paramètres
+ }
+ ppVars[i++] = pile2->GivVar(); // construit la liste des pointeurs
+ pile2 = pile2->AddStack(); // de la place sur la pile pour les résultats
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ CBotClass* pClass = CBotClass::Find(m_ClassName);
+ CBotVar* pThis = pile1->FindVar("this");
+ CBotVar* pResult = NULL;
+ if (m_typRes.GivType()>0) pResult = CBotVar::Create("", m_typRes);
+ if (m_typRes.Eq(CBotTypClass))
+ {
+// CBotClass* pClass = CBotClass::Find(m_RetClassName);
+ pResult->SetClass(m_typRes.GivClass());
+ }
+ CBotVar* pRes = pResult;
+
+ if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
+ pThis, ppVars,
+ pResult, pile2, GivToken())) return FALSE; // interrompu
+
+ // met la nouvelle valeur de this à la place de l'ancienne variable
+ CBotVar* old = pile1->FindVar(m_token);
+ old->Copy(pThis, FALSE);
+
+ if (pRes != pResult) delete pRes;
+
+ return pj->Return(pile2); // libère toute la pile
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "new"
+
+CBotNew::CBotNew()
+{
+ name = "CBotNew";
+ m_Parameters = NULL;
+ m_nMethodeIdent = 0;
+// m_nThisIdent = 0;
+}
+
+CBotNew::~CBotNew()
+{
+}
+
+CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p;
+ if ( !IsOfType(p, ID_NEW) ) return NULL;
+
+ // vérifie que le token est un nom de classe
+ if (p->GivType() != TokenTypVar) return NULL;
+
+ CBotClass* pClass = CBotClass::Find(p);
+ if (pClass == NULL)
+ {
+ pStack->SetError(TX_BADNEW, p);
+ return NULL;
+ }
+/* if ( !pClass->m_IsDef )
+ {
+ pStack->SetError(TX_BADNEW, p);
+ return NULL;
+ }*/
+
+ CBotNew* inst = new CBotNew();
+ inst->SetToken(pp);
+
+ inst->m_vartoken = p;
+ p = p->GivNext();
+
+ // crée l'objet sur le "tas"
+ // avec un pointeur sur cet objet
+ CBotVar* pVar = CBotVar::Create("", pClass);
+// inst->m_nThisIdent = CBotVar::NextUniqNum();
+
+ // fait l'appel du créateur
+ CBotCStack* pStk = pStack->TokenStack();
+ {
+ // regarde s'il y a des paramètres
+ CBotVar* ppVars[1000];
+ inst->m_Parameters = CompileParams(p, pStk, ppVars);
+ if ( !pStk->IsOk() ) goto error;
+
+ // le constructeur existe-il ?
+// CBotString noname;
+ CBotTypResult r = pClass->CompileMethode(pClass->GivName(), pVar, ppVars, pStk, inst->m_nMethodeIdent);
+ delete pStk->TokenStack(); // libère le supplément de pile
+ int typ = r.GivType();
+
+ // s'il n'y a pas de constructeur, et pas de paramètres non plus, c'est ok
+ if ( typ == TX_UNDEFCALL && inst->m_Parameters == NULL ) typ = 0;
+ pVar->SetInit(TRUE); // marque l'instance comme init
+
+ if (typ>20)
+ {
+ pStk->SetError(typ, inst->m_vartoken.GivEnd());
+ goto error;
+ }
+
+ // si le constructeur n'existe pas, mais qu'il y a des paramètres
+ if (typ<0 && inst->m_Parameters != NULL)
+ {
+ pStk->SetError(TX_NOCONST, &inst->m_vartoken);
+ goto error;
+ }
+
+ // rend le pointeur à l'objet sur la pile
+ pStk->SetVar(pVar);
+ return pStack->Return(inst, pStk);
+ }
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// exécute une instruction "new"
+
+BOOL CBotNew::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this); //pile principale
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ CBotStack* pile1 = pj->AddStack2(); //pile secondaire
+
+ CBotVar* pThis = NULL;
+
+ CBotToken* pt = &m_vartoken;
+ CBotClass* pClass = CBotClass::Find(pt);
+
+ // crée la variable "this" de type pointeur à l'objet
+
+ if ( pile->GivState()==0)
+ {
+ // crée une instance de la classe demandée
+ // et initialise le pointeur à cet objet
+
+ pThis = CBotVar::Create("this", pClass);
+// pThis->SetUniqNum( m_nThisIdent ) ;
+ pThis->SetUniqNum( -2 ) ;
+
+ pile1->SetVar(pThis); // la place sur la pile1
+ pile->IncState();
+ }
+
+ // retrouve le pointeur this si on a été interrompu
+ if ( pThis == NULL)
+ {
+ pThis = pile1->GivVar(); // retrouve le pointeur
+ }
+
+ // y a-t-il une assignation ou des paramètres (constructeur)
+ if ( pile->GivState()==1)
+ {
+ // évalue le constructeur de l'instance
+
+ CBotVar* ppVars[1000];
+ CBotStack* pile2 = pile;
+
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+
+ if ( p != NULL) while ( TRUE )
+ {
+ pile2 = pile2->AddStack(); // de la place sur la pile pour les résultats
+ if ( pile2->GivState() == 0 )
+ {
+ if (!p->Execute(pile2)) return FALSE; // interrompu ici ?
+ pile2->SetState(1);
+ }
+ ppVars[i++] = pile2->GivVar();
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ // crée une variable pour le résultat
+ CBotVar* pResult = NULL; // constructeurs toujours void
+
+ if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GivName(),
+ pThis, ppVars,
+ pResult, pile2, GivToken())) return FALSE; // interrompu
+
+ pThis->ConstructorSet(); // signale que le constructeur a été appelé
+// pile->Return(pile2); // libère un bout de pile
+
+// pile->IncState();
+ }
+
+ return pj->Return( pile1 ); // transmet en dessous
+}
+
+void CBotNew::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this); //pile principale
+ if ( pile == NULL ) return;
+
+ CBotStack* pile1 = pj->AddStack2(); //pile secondaire
+
+ CBotToken* pt = &m_vartoken;
+ CBotClass* pClass = CBotClass::Find(pt);
+
+ // crée la variable "this" de type pointeur à l'objet
+
+ if ( pile->GivState()==0)
+ {
+ return;
+ }
+
+ CBotVar* pThis = pile1->GivVar(); // retrouve le pointeur
+// pThis->SetUniqNum( m_nThisIdent );
+ pThis->SetUniqNum( -2 );
+
+ // y a-t-il une assignation ou des paramètres (constructeur)
+ if ( pile->GivState()==1)
+ {
+ // évalue le constructeur de l'instance
+
+ CBotVar* ppVars[1000];
+ CBotStack* pile2 = pile;
+
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+
+ if ( p != NULL) while ( TRUE )
+ {
+ pile2 = pile2->RestoreStack(); // de la place sur la pile pour les résultats
+ if ( pile2 == NULL ) return;
+
+ if ( pile2->GivState() == 0 )
+ {
+ p->RestoreState(pile2, bMain); // interrompu ici !
+ return;
+ }
+ ppVars[i++] = pile2->GivVar();
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ pClass->RestoreMethode(m_nMethodeIdent, m_vartoken.GivString(), pThis,
+ ppVars, pile2) ; // interrompu ici !
+ }
+}
+
+/////////////////////////////////////////////////////////////
+// regarde si deux résultats sont compatibles pour faire une opération
+
+BOOL TypeCompatible( CBotTypResult& type1, CBotTypResult& type2, int op )
+{
+ int t1 = type1.GivType();
+ int t2 = type2.GivType();
+
+ int max = (t1 > t2) ? t1 : t2;
+
+ if ( max == 99 ) return FALSE; // un résultat est void ?
+
+ // cas particulier pour les concaténation de chaînes
+ if (op == ID_ADD && max >= CBotTypString) return TRUE;
+ if (op == ID_ASSADD && max >= CBotTypString) return TRUE;
+ if (op == ID_ASS && t1 == CBotTypString) return TRUE;
+
+ if ( max >= CBotTypBoolean )
+ {
+ if ( (op == ID_EQ || op == ID_NE) &&
+ (t1 == CBotTypPointer && t2 == CBotTypNullPointer)) return TRUE;
+ if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
+ (t2 == CBotTypPointer && t1 == CBotTypNullPointer)) return TRUE;
+ if ( (op == ID_EQ || op == ID_NE) &&
+ (t1 == CBotTypArrayPointer && t2 == CBotTypNullPointer)) return TRUE;
+ if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
+ (t2 == CBotTypArrayPointer && t1 == CBotTypNullPointer)) return TRUE;
+ if (t2 != t1) return FALSE;
+ if (t1 == CBotTypArrayPointer) return type1.Compare(type2);
+ if (t1 == CBotTypPointer ||
+ t1 == CBotTypClass ||
+ t1 == CBotTypIntrinsic )
+ {
+ CBotClass* c1 = type1.GivClass();
+ CBotClass* c2 = type2.GivClass();
+
+ return c1->IsChildOf(c2) || c2->IsChildOf(c1);
+ // accepte le caste à l'envers,
+ // l'opération sera refusée à l'exécution si le pointeur n'est pas compatible
+ }
+
+ return TRUE;
+ }
+
+ type1.SetType(max);
+ type2.SetType(max);
+ return TRUE;
+}
+
+// regarde si deux variables sont compatible pour un passage de paramètre
+
+BOOL TypesCompatibles( CBotTypResult& type1, CBotTypResult& type2 )
+{
+ int t1 = type1.GivType();
+ int t2 = type2.GivType();
+
+ if ( t1 == CBotTypIntrinsic ) t1 = CBotTypClass;
+ if ( t2 == CBotTypIntrinsic ) t2 = CBotTypClass;
+
+ int max = (t1 > t2) ? t1 : t2;
+
+ if ( max == 99 ) return FALSE; // un résultat est void ?
+
+ if ( max >= CBotTypBoolean )
+ {
+ if ( t2 != t1 ) return FALSE;
+
+ if ( max == CBotTypArrayPointer )
+ return TypesCompatibles(type1.GivTypElem(), type2.GivTypElem());
+
+ if ( max == CBotTypClass || max == CBotTypPointer )
+ return type1.GivClass() == type2.GivClass() ;
+
+ return TRUE ;
+ }
+ return TRUE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+// Gestion des fichiers
+
+// nécessaire car il n'est pas possible de faire le fopen dans le programme principal
+// et les fwrite ou fread dans une dll en utilisant le FILE* rendu.
+
+FILE* fOpen(const char* name, const char* mode)
+{
+ return fopen(name, mode);
+}
+
+int fClose(FILE* filehandle)
+{
+ return fclose(filehandle);
+}
+
+size_t fWrite(const void *buffer, size_t elemsize, size_t length, FILE* filehandle)
+{
+ return fwrite(buffer, elemsize, length, filehandle);
+}
+
+size_t fRead(void *buffer, size_t elemsize, size_t length, FILE* filehandle)
+{
+ return fread(buffer, elemsize, length, filehandle);
+}
+
+size_t fWrite(const void *buffer, size_t length, FILE* filehandle)
+{
+ return fwrite(buffer, 1, length, filehandle);
+}
+
+size_t fRead(void *buffer, size_t length, FILE* filehandle)
+{
+ return fread(buffer, 1, length, filehandle);
+}
+
+
+////////////////////////////////////////
+
+
+#if FALSE
+
+CBotString num(int n)
+{
+ CBotString s;
+ if ( n<0 ) {n = -n; s += "-";}
+ if ( n > 9 )
+ {
+ s += num(n/10);
+ }
+ s += '0' + n%10;
+ return s;
+}
+
+extern void DEBUG( const char* text, int val, CBotStack* pile )
+{
+ CBotProgram* p = pile->GivBotCall(TRUE);
+ if ( !p->m_bDebugDD ) return;
+
+ FILE* pf = fopen("CbotDebug.txt", "a");
+
+ fputs( text, pf );
+
+ CBotString v = " " + num(val) + "\n";
+ fputs( v, pf );
+
+ fclose( pf);
+}
+
+#endif
diff --git a/src/CBot/CBot.dsp b/src/CBot/CBot.dsp
new file mode 100644
index 0000000..062660a
--- /dev/null
+++ b/src/CBot/CBot.dsp
@@ -0,0 +1,158 @@
+# Microsoft Developer Studio Project File - Name="CBot" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=CBot - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "CBot.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "CBot.mak" CFG="CBot - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "CBot - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CBot - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "CBot - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "CBot - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x40c /d "_DEBUG"
+# ADD RSC /l 0x40c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# Begin Custom Build
+InputPath=.\Debug\CBot.dll
+SOURCE=$(InputPath)
+
+".\TestCBot\CBot.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ copy .\Debug\CBot.dll .\TestCBot\CBot.dll
+ copy .\Debug\CBot.dll "C:\Program Files\Colobot\CBot.dll"
+ _Copy.bat
+
+# End Custom Build
+
+!ENDIF
+
+# Begin Target
+
+# Name "CBot - Win32 Release"
+# Name "CBot - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\CBot.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBot.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBot.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotClass.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotDll.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotFunction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotIf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotProgram.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotStack.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotToken.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotToken.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotTwoOpExpr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotVar.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CBotWhile.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/src/CBot/CBot.dsw b/src/CBot/CBot.dsw
new file mode 100644
index 0000000..31e2133
--- /dev/null
+++ b/src/CBot/CBot.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "CBot"=".\CBot.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "TestCBot"=".\TestCBot\TestCBot.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name CBot
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/src/CBot/CBot.h b/src/CBot/CBot.h
new file mode 100644
index 0000000..bf95c90
--- /dev/null
+++ b/src/CBot/CBot.h
@@ -0,0 +1,1611 @@
+////////////////////////////////////////////////////////////////////
+// interpréteur pour le language CBot du jeu COLOBOT
+
+// dernière révision : 03/10/2002 DD
+
+#define EXTENDS TRUE
+
+
+#include "resource.h"
+#include "CBotDll.h" // définitions publiques
+#include "CBotToken.h" // gestion des tokens
+
+#define STACKRUN TRUE // reprise de l'exécution direct sur une routine suspendue
+#define STACKMEM TRUE // préréserve la mémoire pour la pile d'exécution
+#define MAXSTACK 990 // taille du stack réservé
+
+#define EOX (CBotStack*)-1 // marqueur condition spéciale
+
+/////////////////////////////////////////////////////////////////////
+// résumé des classes utilisées, définies ci-après
+
+class CBotCompExpr; // une expression telle que
+ // () <= ()
+class CBotAddExpr; // une expression telle que
+ // () + ()
+class CBotParExpr; // un élément de base ou entre parenthèse
+ // Toto.truc
+ // 12.5
+ // "chaine"
+ // ( expression )
+class CBotExprVar; // un nom de variable tel que
+ // Toto
+ // chose.truc.machin
+class CBotWhile; // while (...) {...};
+class CBotIf; // if (...) {...} else {...}
+class CBotDefParam; // liste de paramètres d'une fonction
+class CBotRepeat; // repeat (nb) {...}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Gestion de la pile d'exécution
+////////////////////////////////////////////////////////////////////////
+
+// en fait, en externe, la seule chose qu'il est possible de faire
+// c'est de créer une instance d'une pile
+// pour l'utiliser pour la routine CBotProgram::Execute(CBotStack)
+
+class CBotStack
+{
+private:
+ CBotStack* m_next;
+ CBotStack* m_next2;
+ CBotStack* m_prev;
+ friend class CBotInstArray;
+
+#ifdef _DEBUG
+ int m_index;
+#endif
+ int m_state;
+ int m_step;
+ static int m_error;
+ static int m_start;
+ static int m_end;
+ static
+ CBotVar* m_retvar; // résultat d'un return
+
+ CBotVar* m_var; // résultat des opérations
+ CBotVar* m_listVar; // les variables déclarées à ce niveau
+
+ BOOL m_bBlock; // fait partie d'un bloc (variables sont locales à ce bloc)
+ BOOL m_bOver; // limites de la pile ?
+// BOOL m_bDontDelete; // spécial, ne pas détruire les variables au delete
+ CBotProgram* m_prog; // les fonctions définies par user
+
+ static
+ int m_initimer;
+ static
+ int m_timer;
+ static
+ CBotString m_labelBreak;
+ static
+ void* m_pUser;
+
+ CBotInstr* m_instr; // l'instruction correspondante
+ BOOL m_bFunc; // une entrée d'une fonction ?
+ CBotCall* m_call; // point de reprise dans un call extern
+ friend class CBotTry;
+
+public:
+#if STACKMEM
+ static
+ CBotStack* FirstStack();
+ void Delete();
+#endif
+ CBotStack(CBotStack* ppapa);
+ ~CBotStack();
+ BOOL StackOver();
+
+ int GivError(int& start, int& end);
+ int GivError(); // rend le numéro d'erreur retourné
+
+ void Reset(void* pUser); // plus d'erreur, timer au début
+ void SetType(CBotTypResult& type); // détermine le type
+ int GivType(int mode = 0); // donne le type de valeur sur le stack
+ CBotTypResult GivTypResult(int mode = 0); // donne le type complet de valeur sur le stack
+
+// void AddVar(CBotVar* p, BOOL bDontDelete=FALSE); // ajoute une variable locale
+ void AddVar(CBotVar* p); // ajoute une variable locale
+// void RestoreVar(CBotVar* pVar);
+
+ CBotVar* FindVar(CBotToken* &p, BOOL bUpdate = FALSE,
+ BOOL bModif = FALSE); // trouve une variable
+ CBotVar* FindVar(CBotToken& Token, BOOL bUpdate = FALSE,
+ BOOL bModif = FALSE);
+ CBotVar* FindVar(const char* name);
+ CBotVar* FindVar(long ident, BOOL bUpdate = FALSE,
+ BOOL bModif = FALSE);
+
+ CBotVar* CopyVar(CBotToken& Token, BOOL bUpdate = FALSE); // trouve et rend une copie
+
+
+ CBotStack* AddStack(CBotInstr* instr = NULL, BOOL bBlock = FALSE); // étend le stack
+ CBotStack* AddStackEOX(CBotCall* instr = NULL, BOOL bBlock = FALSE); // étend le stack
+ CBotStack* RestoreStack(CBotInstr* instr = NULL);
+ CBotStack* RestoreStackEOX(CBotCall* instr = NULL);
+
+ CBotStack* AddStack2(BOOL bBlock = FALSE); // étend le stack
+ BOOL Return(CBotStack* pFils); // transmet le résultat au dessus
+ BOOL ReturnKeep(CBotStack* pFils); // transmet le résultat sans réduire la pile
+ BOOL BreakReturn(CBotStack* pfils, const char* name = NULL);
+ // en cas de break éventuel
+ BOOL IfContinue(int state, const char* name);
+ // ou de "continue"
+
+ BOOL IsOk();
+
+ BOOL SetState(int n, int lim = -10); // sélectionne un état
+ int GivState(); // dans quel état j'ère ?
+ BOOL IncState(int lim = -10); // passe à l'état suivant
+ BOOL IfStep(); // faire du pas à pas ?
+ BOOL Execute();
+
+ void SetVar( CBotVar* var );
+ void SetCopyVar( CBotVar* var );
+ CBotVar* GivVar();
+ CBotVar* GivCopyVar();
+ CBotVar* GivPtVar();
+ BOOL GivRetVar(BOOL bRet);
+ long GivVal();
+
+ void SetStartError(int pos);
+ void SetError(int n, CBotToken* token = NULL);
+ void SetPosError(CBotToken* token);
+ void ResetError(int n, int start, int end);
+ void SetBreak(int val, const char* name);
+
+ void SetBotCall(CBotProgram* p);
+ CBotProgram* GivBotCall(BOOL bFirst = FALSE);
+ void* GivPUser();
+ BOOL GivBlock();
+
+
+// BOOL ExecuteCall(CBotToken* token, CBotVar** ppVar, CBotTypResult& rettype);
+ BOOL ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotTypResult& rettype);
+ void RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar);
+
+ BOOL SaveState(FILE* pf);
+ BOOL RestoreState(FILE* pf, CBotStack* &pStack);
+
+ static
+ void SetTimer(int n);
+
+ void GetRunPos(const char* &FunctionName, int &start, int &end);
+ CBotVar* GivStackVars(const char* &FunctionName, int level);
+
+ int m_temp;
+};
+
+// les routines inline doivent être déclarées dans le fichier .h
+
+inline BOOL CBotStack::IsOk()
+{
+ return (m_error == 0);
+}
+
+inline int CBotStack::GivState()
+{
+ return m_state;
+}
+
+inline int CBotStack::GivError()
+{
+ return m_error;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Gestion de la pile de compilation
+////////////////////////////////////////////////////////////////////////
+
+
+class CBotCStack
+{
+private:
+ CBotCStack* m_next;
+ CBotCStack* m_prev;
+
+ static
+ int m_error;
+ static
+ int m_end;
+ int m_start;
+
+ CBotVar* m_var; // résultat des opérations
+
+ BOOL m_bBlock; // fait partie d'un bloc (variables sont locales à ce bloc)
+ CBotVar* m_listVar;
+
+ static
+ CBotProgram* m_prog; // liste des fonctions compilées
+ static
+ CBotTypResult m_retTyp;
+// static
+// CBotToken* m_retClass;
+
+public:
+ CBotCStack(CBotCStack* ppapa);
+ ~CBotCStack();
+
+ BOOL IsOk();
+ int GivError();
+ int GivError(int& start, int& end);
+ // rend le numéro d'erreur retourné
+
+ void SetType(CBotTypResult& type);// détermine le type
+ CBotTypResult GivTypResult(int mode = 0); // donne le type de valeur sur le stack
+ int GivType(int mode = 0); // donne le type de valeur sur le stack
+ CBotClass* GivClass(); // donne la classe de la valeur sur le stack
+
+ void AddVar(CBotVar* p); // ajoute une variable locale
+ CBotVar* FindVar(CBotToken* &p); // trouve une variable
+ CBotVar* FindVar(CBotToken& Token);
+ BOOL CheckVarLocal(CBotToken* &pToken);
+ CBotVar* CopyVar(CBotToken& Token); // trouve et rend une copie
+
+ CBotCStack* TokenStack(CBotToken* pToken = NULL, BOOL bBlock = FALSE);
+ CBotInstr* Return(CBotInstr* p, CBotCStack* pParent); // transmet le résultat au dessus
+ CBotFunction* ReturnFunc(CBotFunction* p, CBotCStack* pParent); // transmet le résultat au dessus
+
+ void SetVar( CBotVar* var );
+ void SetCopyVar( CBotVar* var );
+ CBotVar* GivVar();
+
+ void SetStartError(int pos);
+ void SetError(int n, int pos);
+ void SetError(int n, CBotToken* p);
+ void ResetError(int n, int start, int end);
+
+ void SetRetType(CBotTypResult& type);
+ CBotTypResult GivRetType();
+
+// void SetBotCall(CBotFunction* &pFunc);
+ void SetBotCall(CBotProgram* p);
+ CBotProgram* GivBotCall();
+ CBotTypResult CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent);
+ BOOL CheckCall(CBotToken* &pToken, CBotDefParam* pParam);
+
+ BOOL NextToken(CBotToken* &p);
+};
+
+
+extern BOOL SaveVar(FILE* pf, CBotVar* pVar);
+
+
+/////////////////////////////////////////////////////////////////////
+// classes définissant une instruction
+class CBotInstr
+{
+private:
+ static
+ CBotStringArray
+ m_labelLvl;
+protected:
+ CBotToken m_token; // conserve le token
+ CBotString name; // debug
+ CBotInstr* m_next; // instructions chaînées
+ CBotInstr* m_next2b; // seconde liste pour définition en chaîne
+ CBotInstr* m_next3; // troisième liste pour les indices et champs
+ CBotInstr* m_next3b; // nécessaire pour la déclaration des tableaux
+/*
+ par exemple, le programme suivant
+ int x[]; x[1] = 4;
+ int y[x[1]][10], z;
+ va généré
+ CBotInstrArray
+ m_next3b-> CBotEmpty
+ m_next->
+ CBotExpression ....
+ m_next->
+ CBotInstrArray
+ m_next3b-> CBotExpression ('x') ( m_next3-> CBotIndexExpr ('1') )
+ m_next3b-> CBotExpression ('10')
+ m_next2-> 'z'
+ m_next->...
+
+*/
+
+ static
+ int m_LoopLvl;
+ friend class CBotClassInst;
+ friend class CBotInt;
+ friend class CBotListArray;
+
+public:
+ CBotInstr();
+ virtual
+ ~CBotInstr();
+
+ DllExport//debug
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ static
+ CBotInstr* CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, BOOL first = TRUE);
+
+ virtual
+ BOOL Execute(CBotStack* &pj);
+ virtual
+ BOOL Execute(CBotStack* &pj, CBotVar* pVar);
+ virtual
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+
+ virtual
+ BOOL ExecuteVar(CBotVar* &pVar, CBotCStack* &pile);
+ virtual
+ BOOL ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep, BOOL bExtend);
+ virtual
+ void RestoreStateVar(CBotStack* &pile, BOOL bMain);
+
+ virtual
+ BOOL CompCase(CBotStack* &pj, int val);
+
+ void SetToken(CBotToken* p);
+ void SetToken(CBotString* name, int start=0, int end=0);
+ int GivTokenType();
+ CBotToken* GivToken();
+
+ void AddNext(CBotInstr* n);
+ CBotInstr* GivNext();
+ void AddNext3(CBotInstr* n);
+ CBotInstr* GivNext3();
+ void AddNext3b(CBotInstr* n);
+ CBotInstr* GivNext3b();
+
+ static
+ void IncLvl(CBotString& label);
+ static
+ void IncLvl();
+ static
+ void DecLvl();
+ static
+ BOOL ChkLvl(CBotString& label, int type);
+
+ BOOL IsOfClass(CBotString name);
+};
+
+class CBotWhile : public CBotInstr
+{
+private:
+ CBotInstr* m_Condition; // la condition
+ CBotInstr* m_Block; // les instructions
+ CBotString m_label; // une étiquette s'il y a
+
+public:
+ CBotWhile();
+ ~CBotWhile();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotRepeat : public CBotInstr
+{
+private:
+ CBotInstr* m_NbIter; // le nombre d'itération
+ CBotInstr* m_Block; // les instructions
+ CBotString m_label; // une étiquette s'il y a
+
+public:
+ CBotRepeat();
+ ~CBotRepeat();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotDo : public CBotInstr
+{
+private:
+ CBotInstr* m_Block; // les instructions
+ CBotInstr* m_Condition; // la condition
+ CBotString m_label; // une étiquette s'il y a
+
+public:
+ CBotDo();
+ ~CBotDo();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotFor : public CBotInstr
+{
+private:
+ CBotInstr* m_Init; // intruction initiale
+ CBotInstr* m_Test; // la condition de test
+ CBotInstr* m_Incr; // instruction pour l'incrément
+ CBotInstr* m_Block; // les instructions
+ CBotString m_label; // une étiquette s'il y a
+
+public:
+ CBotFor();
+ ~CBotFor();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotBreak : public CBotInstr
+{
+private:
+ CBotString m_label; // une étiquette s'il y a
+
+public:
+ CBotBreak();
+ ~CBotBreak();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotReturn : public CBotInstr
+{
+private:
+ CBotInstr* m_Instr; // le paramètre à retourner
+
+public:
+ CBotReturn();
+ ~CBotReturn();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotSwitch : public CBotInstr
+{
+private:
+ CBotInstr* m_Value; // value à chercher
+ CBotInstr* m_Block; // les instructions
+
+public:
+ CBotSwitch();
+ ~CBotSwitch();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotCase : public CBotInstr
+{
+private:
+ CBotInstr* m_Value; // valeur à comparer
+
+public:
+ CBotCase();
+ ~CBotCase();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+ BOOL CompCase(CBotStack* &pj, int val);
+};
+
+class CBotCatch : public CBotInstr
+{
+private:
+ CBotInstr* m_Block; // les instructions
+ CBotInstr* m_Cond; // la condition
+ CBotCatch* m_next; // le catch suivant
+ friend class CBotTry;
+
+public:
+ CBotCatch();
+ ~CBotCatch();
+ static
+ CBotCatch* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL TestCatch(CBotStack* &pj, int val);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+ void RestoreCondState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotTry : public CBotInstr
+{
+private:
+ CBotInstr* m_Block; // les instructions
+ CBotCatch* m_ListCatch; // les catches
+ CBotInstr* m_FinalInst; // instruction finale
+
+public:
+ CBotTry();
+ ~CBotTry();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotThrow : public CBotInstr
+{
+private:
+ CBotInstr* m_Value; // la valeur à envoyer
+
+public:
+ CBotThrow();
+ ~CBotThrow();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotStartDebugDD : public CBotInstr
+{
+private:
+
+public:
+ CBotStartDebugDD();
+ ~CBotStartDebugDD();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+};
+
+
+class CBotIf : public CBotInstr
+{
+private:
+ CBotInstr* m_Condition; // la condition
+ CBotInstr* m_Block; // les instructions
+ CBotInstr* m_BlockElse; // les instructions
+
+public:
+ CBotIf();
+ ~CBotIf();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+// définition d'un nombre entier
+
+class CBotInt : public CBotInstr
+{
+private:
+ CBotInstr* m_var; // la variable à initialiser
+ CBotInstr* m_expr; // la valeur à mettre, s'il y a
+/// CBotInstr* m_next; // plusieurs définitions enchaînées
+
+public:
+ CBotInt();
+ ~CBotInt();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont = FALSE, BOOL noskip = FALSE);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// définition d'un tableau
+
+class CBotInstArray : public CBotInstr
+{
+private:
+ CBotInstr* m_var; // la variable à initialiser
+ CBotInstr* m_listass; // liste d'assignations pour le tableau
+ CBotTypResult
+ m_typevar; // type d'éléments
+// CBotString m_ClassName;
+
+public:
+ CBotInstArray();
+ ~CBotInstArray();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+// définition d'une liste d'assignation pour un tableau
+// int [ ] a [ ] = ( ( 1, 2, 3 ) , ( 3, 2, 1 ) ) ;
+
+class CBotListArray : public CBotInstr
+{
+private:
+ CBotInstr* m_expr; // expression pour un élément
+ // les autres sont chaînés avec CBotInstr::m_next3;
+public:
+ CBotListArray();
+ ~CBotListArray();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type);
+ BOOL Execute(CBotStack* &pj, CBotVar* pVar);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotEmpty : public CBotInstr
+{
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// définition d'un booléen
+
+class CBotBoolean : public CBotInstr
+{
+private:
+ CBotInstr* m_var; // la variable à initialiser
+ CBotInstr* m_expr; // la valeur à mettre, s'il y a
+
+public:
+ CBotBoolean();
+ ~CBotBoolean();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont = FALSE, BOOL noskip=FALSE);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+// définition d'un nombre réel
+
+class CBotFloat : public CBotInstr
+{
+private:
+ CBotInstr* m_var; // la variable à initialiser
+ CBotInstr* m_expr; // la valeur à mettre, s'il y a
+
+public:
+ CBotFloat();
+ ~CBotFloat();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont = FALSE, BOOL noskip=FALSE);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// définition d'un elément string
+
+class CBotIString : public CBotInstr
+{
+private:
+ CBotInstr* m_var; // la variable à initialiser
+ CBotInstr* m_expr; // la valeur à mettre, s'il y a
+
+public:
+ CBotIString();
+ ~CBotIString();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, BOOL cont = FALSE, BOOL noskip=FALSE);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// définition d'un elément dans une classe quelconque
+
+class CBotClassInst : public CBotInstr
+{
+private:
+ CBotInstr* m_var; // la variable à initialiser
+ CBotClass* m_pClass; // référence à la classe
+ CBotInstr* m_Parameters; // les paramètres à évaluer pour le constructeur
+ CBotInstr* m_expr; // la valeur à mettre, s'il y a
+ BOOL m_hasParams; // il y a des paramètres ?
+ long m_nMethodeIdent;
+
+public:
+ CBotClassInst();
+ ~CBotClassInst();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass = NULL);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotCondition : public CBotInstr
+{
+private:
+
+public:
+
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+};
+
+
+// left opérande
+// n'accepte que les expressions pouvant être à gauche d'une assignation
+
+class CBotLeftExpr : public CBotInstr
+{
+private:
+ long m_nIdent;
+
+public:
+ CBotLeftExpr();
+ ~CBotLeftExpr();
+ static
+ CBotLeftExpr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pStack, CBotStack* array);
+
+ BOOL ExecuteVar(CBotVar* &pVar, CBotCStack* &pile);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep);
+ void RestoreStateVar(CBotStack* &pile, BOOL bMain);
+};
+
+
+// gestion des champs d'une instance
+
+class CBotFieldExpr : public CBotInstr
+{
+private:
+ friend class CBotExpression;
+ int m_nIdent;
+
+public:
+ CBotFieldExpr();
+ ~CBotFieldExpr();
+ void SetUniqNum(int num);
+// static
+// CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotCStack* &pile);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep, BOOL bExtend);
+ void RestoreStateVar(CBotStack* &pj, BOOL bMain);
+};
+
+// gestion des index dans les tableaux
+
+class CBotIndexExpr : public CBotInstr
+{
+private:
+ CBotInstr* m_expr; // expression pour le calcul de l'index
+ friend class CBotLeftExpr;
+ friend class CBotExprVar;
+
+public:
+ CBotIndexExpr();
+ ~CBotIndexExpr();
+// static
+// CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotCStack* &pile);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep, BOOL bExtend);
+ void RestoreStateVar(CBotStack* &pj, BOOL bMain);
+};
+
+// une expression du genre
+// x = a;
+// x * y + 3;
+
+class CBotExpression : public CBotInstr
+{
+private:
+ CBotLeftExpr* m_leftop; // élément de gauche
+ CBotInstr* m_rightop; // élément de droite
+
+public:
+ CBotExpression();
+ ~CBotExpression();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pStack);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotListExpression : public CBotInstr
+{
+private:
+ CBotInstr* m_Expr; // la 1ère expression à évaluer
+
+public:
+ CBotListExpression();
+ ~CBotListExpression();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pStack);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotLogicExpr : public CBotInstr
+{
+private:
+ CBotInstr* m_condition; // test à évaluer
+ CBotInstr* m_op1; // élément de gauche
+ CBotInstr* m_op2; // élément de droite
+ friend class CBotTwoOpExpr;
+
+public:
+ CBotLogicExpr();
+ ~CBotLogicExpr();
+// static
+// CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pStack);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+
+class CBotBoolExpr : public CBotInstr
+{
+private:
+
+public:
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+};
+
+
+
+// une expression éventuellement entre parenthèses ( ... )
+// il n'y a jamais d'instance de cette classe
+// l'objet retourné étant le contenu de la parenthése
+class CBotParExpr : public CBotInstr
+{
+private:
+
+public:
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+};
+
+// expression unaire
+class CBotExprUnaire : public CBotInstr
+{
+private:
+ CBotInstr* m_Expr; // l'expression à évaluer
+public:
+ CBotExprUnaire();
+ ~CBotExprUnaire();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pStack);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// toutes les opérations à 2 opérandes
+
+class CBotTwoOpExpr : public CBotInstr
+{
+private:
+ CBotInstr* m_leftop; // élément de gauche
+ CBotInstr* m_rightop; // élément de droite
+public:
+ CBotTwoOpExpr();
+ ~CBotTwoOpExpr();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations = NULL);
+ BOOL Execute(CBotStack* &pStack);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+
+
+// un bloc d'instructions { .... }
+class CBotBlock : public CBotInstr
+{
+private:
+
+public:
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, BOOL bLocal = TRUE);
+ static
+ CBotInstr* CompileBlkOrInst(CBotToken* &p, CBotCStack* pStack, BOOL bLocal = FALSE);
+};
+
+
+// le contenu d'un bloc d'instructions ... ; ... ; ... ; ... ;
+class CBotListInstr : public CBotInstr
+{
+private:
+ CBotInstr* m_Instr; // les instructions à faire
+
+public:
+ CBotListInstr();
+ ~CBotListInstr();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, BOOL bLocal = TRUE);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotInstrCall : public CBotInstr
+{
+private:
+ CBotInstr* m_Parameters; // les paramètres à évaluer
+// int m_typeRes; // type du résultat
+// CBotString m_RetClassName; // class du résultat
+ CBotTypResult
+ m_typRes; // type complet du résultat
+ long m_nFuncIdent; // id de la fonction
+
+public:
+ CBotInstrCall();
+ ~CBotInstrCall();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// un appel d'une méthode
+
+class CBotInstrMethode : public CBotInstr
+{
+private:
+ CBotInstr* m_Parameters; // les paramètres à évaluer
+// int m_typeRes; // type du résultat
+// CBotString m_RetClassName; // class du résultat
+ CBotTypResult
+ m_typRes; // type complet du résultat
+
+ CBotString m_NomMethod; // nom de la méthode
+ long m_MethodeIdent; // identificateur de la méthode
+// long m_nThisIdent; // identificateur pour "this"
+ CBotString m_ClassName; // nom de la classe
+
+public:
+ CBotInstrMethode();
+ ~CBotInstrMethode();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* pVar);
+ BOOL Execute(CBotStack* &pj);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, BOOL bStep, BOOL bExtend);
+ void RestoreStateVar(CBotStack* &pj, BOOL bMain);
+};
+
+// expression donnant un nom de variable
+
+class CBotExprVar : public CBotInstr
+{
+private:
+ long m_nIdent;
+ friend class CBotPostIncExpr;
+ friend class CBotPreIncExpr;
+
+public:
+ CBotExprVar();
+ ~CBotExprVar();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int privat=PR_PROTECT);
+ static
+ CBotInstr* CompileMethode(CBotToken* &p, CBotCStack* pStack);
+
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+ BOOL ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, BOOL bStep);
+ BOOL Execute2Var(CBotVar* &pVar, CBotStack* &pj, CBotToken* prevToken, BOOL bStep);
+ void RestoreStateVar(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotPostIncExpr : public CBotInstr
+{
+private:
+ CBotInstr* m_Instr;
+ friend class CBotParExpr;
+
+public:
+ CBotPostIncExpr();
+ ~CBotPostIncExpr();
+// static
+// CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotPreIncExpr : public CBotInstr
+{
+private:
+ CBotInstr* m_Instr;
+ friend class CBotParExpr;
+
+public:
+ CBotPreIncExpr();
+ ~CBotPreIncExpr();
+// static
+// CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotLeftExprVar : public CBotInstr
+{
+private:
+public:
+ CBotTypResult
+ m_typevar; // type de variable déclarée
+ long m_nIdent; // identificateur unique pour cette variable
+
+public:
+ CBotLeftExprVar();
+ ~CBotLeftExprVar();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotExprBool : public CBotInstr
+{
+private:
+
+public:
+ CBotExprBool();
+ ~CBotExprBool();
+
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+class CBotExprNull : public CBotInstr
+{
+private:
+
+public:
+ CBotExprNull();
+ ~CBotExprNull();
+
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotExprNan : public CBotInstr
+{
+private:
+
+public:
+ CBotExprNan();
+ ~CBotExprNan();
+
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+class CBotNew : public CBotInstr
+{
+private:
+ CBotInstr* m_Parameters; // les paramètres à évaluer
+ long m_nMethodeIdent;
+// long m_nThisIdent;
+ CBotToken m_vartoken;
+
+public:
+ CBotNew();
+ ~CBotNew();
+
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+// expression représentant un nombre
+
+class CBotExprNum : public CBotInstr
+{
+private:
+ int m_numtype; // et le type de nombre
+ long m_valint; // valeur pour un int
+ float m_valfloat; // valeur pour un float
+
+public:
+ CBotExprNum();
+ ~CBotExprNum();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+
+// expression représentant une chaine de caractères
+
+class CBotExprAlpha : public CBotInstr
+{
+private:
+
+public:
+ CBotExprAlpha();
+ ~CBotExprAlpha();
+ static
+ CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+};
+
+
+#define MAX(a,b) ((a>b) ? a : b)
+
+
+// classe pour la gestion des nombres entier (int)
+class CBotVarInt : public CBotVar
+{
+private:
+ int m_val; // la valeur
+ CBotString m_defnum; // le nom si donné par DefineNum
+ friend class CBotVar;
+
+public:
+ CBotVarInt( const CBotToken* name );
+// ~CBotVarInt();
+
+ void SetValInt(int val, const char* s = NULL);
+ void SetValFloat(float val);
+ int GivValInt();
+ float GivValFloat();
+ CBotString GivValString();
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+
+
+ void Add(CBotVar* left, CBotVar* right); // addition
+ void Sub(CBotVar* left, CBotVar* right); // soustraction
+ void Mul(CBotVar* left, CBotVar* right); // multiplication
+ int Div(CBotVar* left, CBotVar* right); // division
+ int Modulo(CBotVar* left, CBotVar* right); // reste de division
+ void Power(CBotVar* left, CBotVar* right); // puissance
+
+ BOOL Lo(CBotVar* left, CBotVar* right);
+ BOOL Hi(CBotVar* left, CBotVar* right);
+ BOOL Ls(CBotVar* left, CBotVar* right);
+ BOOL Hs(CBotVar* left, CBotVar* right);
+ BOOL Eq(CBotVar* left, CBotVar* right);
+ BOOL Ne(CBotVar* left, CBotVar* right);
+
+ void XOr(CBotVar* left, CBotVar* right);
+ void Or(CBotVar* left, CBotVar* right);
+ void And(CBotVar* left, CBotVar* right);
+
+ void SL(CBotVar* left, CBotVar* right);
+ void SR(CBotVar* left, CBotVar* right);
+ void ASR(CBotVar* left, CBotVar* right);
+
+ void Neg();
+ void Not();
+ void Inc();
+ void Dec();
+
+ BOOL Save0State(FILE* pf);
+ BOOL Save1State(FILE* pf);
+
+};
+
+// classe pour la gestion des nombres réels (float)
+class CBotVarFloat : CBotVar
+{
+private:
+ float m_val; // la valeur
+
+public:
+ CBotVarFloat( const CBotToken* name );
+// ~CBotVarFloat();
+
+ void SetValInt(int val, const char* s = NULL);
+ void SetValFloat(float val);
+ int GivValInt();
+ float GivValFloat();
+ CBotString GivValString();
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+
+
+ void Add(CBotVar* left, CBotVar* right); // addition
+ void Sub(CBotVar* left, CBotVar* right); // soustraction
+ void Mul(CBotVar* left, CBotVar* right); // multiplication
+ int Div(CBotVar* left, CBotVar* right); // division
+ int Modulo(CBotVar* left, CBotVar* right); // reste de division
+ void Power(CBotVar* left, CBotVar* right); // puissance
+
+ BOOL Lo(CBotVar* left, CBotVar* right);
+ BOOL Hi(CBotVar* left, CBotVar* right);
+ BOOL Ls(CBotVar* left, CBotVar* right);
+ BOOL Hs(CBotVar* left, CBotVar* right);
+ BOOL Eq(CBotVar* left, CBotVar* right);
+ BOOL Ne(CBotVar* left, CBotVar* right);
+
+ void Neg();
+ void Inc();
+ void Dec();
+
+ BOOL Save1State(FILE* pf);
+};
+
+
+// classe pour la gestion des chaînes (String)
+class CBotVarString : CBotVar
+{
+private:
+ CBotString m_val; // la valeur
+
+public:
+ CBotVarString( const CBotToken* name );
+// ~CBotVarString();
+
+ void SetValString(const char* p);
+ CBotString GivValString();
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+
+ void Add(CBotVar* left, CBotVar* right); // addition
+
+ BOOL Lo(CBotVar* left, CBotVar* right);
+ BOOL Hi(CBotVar* left, CBotVar* right);
+ BOOL Ls(CBotVar* left, CBotVar* right);
+ BOOL Hs(CBotVar* left, CBotVar* right);
+ BOOL Eq(CBotVar* left, CBotVar* right);
+ BOOL Ne(CBotVar* left, CBotVar* right);
+
+ BOOL Save1State(FILE* pf);
+};
+
+// classe pour la gestion des boolean
+class CBotVarBoolean : CBotVar
+{
+private:
+ BOOL m_val; // la valeur
+
+public:
+ CBotVarBoolean( const CBotToken* name );
+// ~CBotVarBoolean();
+
+ void SetValInt(int val, const char* s = NULL);
+ void SetValFloat(float val);
+ int GivValInt();
+ float GivValFloat();
+ CBotString GivValString();
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+
+ void And(CBotVar* left, CBotVar* right);
+ void Or(CBotVar* left, CBotVar* right);
+ void XOr(CBotVar* left, CBotVar* right);
+ void Not();
+ BOOL Eq(CBotVar* left, CBotVar* right);
+ BOOL Ne(CBotVar* left, CBotVar* right);
+
+ BOOL Save1State(FILE* pf);
+};
+
+
+// classe pour la gestion des instances de classe
+class CBotVarClass : public CBotVar
+{
+private:
+ static
+ CBotVarClass* m_ExClass; // liste des instances existantes à un moment donné
+ CBotVarClass* m_ExNext; // pour cette liste générale
+ CBotVarClass* m_ExPrev; // pour cette liste générale
+
+private:
+ CBotClass* m_pClass; // la définition de la classe
+ CBotVarClass* m_pParent; // l'instance dans la classe parent
+ CBotVar* m_pVar; // contenu
+ friend class CBotVar; // mon papa est un copain
+ friend class CBotVarPointer; // et le pointeur aussi
+ int m_CptUse; // compteur d'utilisation
+ long m_ItemIdent; // identificateur (unique) de l'instance
+ BOOL m_bConstructor; // set si un constructeur a été appelé
+
+public:
+ CBotVarClass( const CBotToken* name, CBotTypResult& type );
+// CBotVarClass( const CBotToken* name, CBotTypResult& type, int &nIdent );
+ ~CBotVarClass();
+// void InitCBotVarClass( const CBotToken* name, CBotTypResult& type, int &nIdent );
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+ void SetClass(CBotClass* pClass); //, int &nIdent);
+ CBotClass* GivClass();
+ CBotVar* GivItem(const char* name); // rend un élément d'une classe selon son nom (*)
+ CBotVar* GivItemRef(int nIdent);
+
+ CBotVar* GivItem(int n, BOOL bExtend);
+ CBotVar* GivItemList();
+
+ CBotString GivValString();
+
+ BOOL Save1State(FILE* pf);
+ void Maj(void* pUser, BOOL bContinue);
+
+ void IncrementUse(); // une référence en plus
+ void DecrementUse(); // une référence en moins
+
+ CBotVarClass*
+ GivPointer();
+ void SetItemList(CBotVar* pVar);
+
+ void SetIdent(long n);
+
+ static
+ CBotVarClass*
+ CBotVarClass::Find(long id);
+
+
+// CBotVar* GivMyThis();
+
+ BOOL Eq(CBotVar* left, CBotVar* right);
+ BOOL Ne(CBotVar* left, CBotVar* right);
+
+ void ConstructorSet();
+};
+
+
+// classe pour la gestion des pointeurs à une instances de classe
+class CBotVarPointer : public CBotVar
+{
+private:
+ CBotVarClass*
+ m_pVarClass; // contenu
+ CBotClass* m_pClass; // la classe prévue pour ce pointeur
+ friend class CBotVar; // mon papa est un copain
+
+public:
+ CBotVarPointer( const CBotToken* name, CBotTypResult& type );
+ ~CBotVarPointer();
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+ void SetClass(CBotClass* pClass);
+ CBotClass* GivClass();
+ CBotVar* GivItem(const char* name); // rend un élément d'une classe selon son nom (*)
+ CBotVar* GivItemRef(int nIdent);
+ CBotVar* GivItemList();
+
+ CBotString GivValString();
+ void SetPointer(CBotVar* p);
+ CBotVarClass*
+ GivPointer();
+
+ void SetIdent(long n); // associe un numéro d'identification (unique)
+ long GivIdent(); // donne le numéro d'identification associé
+ void ConstructorSet();
+
+ BOOL Save1State(FILE* pf);
+ void Maj(void* pUser, BOOL bContinue);
+
+ BOOL Eq(CBotVar* left, CBotVar* right);
+ BOOL Ne(CBotVar* left, CBotVar* right);
+};
+
+
+// classe pour les tableaux
+
+#define MAXARRAYSIZE 9999
+
+class CBotVarArray : public CBotVar
+{
+private:
+ CBotVarClass*
+ m_pInstance; // instance gérant le tableau
+
+ friend class CBotVar; // papa est un copain
+
+public:
+ CBotVarArray( const CBotToken* name, CBotTypResult& type );
+ ~CBotVarArray();
+
+ void SetPointer(CBotVar* p);
+ CBotVarClass*
+ GivPointer();
+
+ void Copy(CBotVar* pSrc, BOOL bName=TRUE);
+ CBotVar* GivItem(int n, BOOL bGrow=FALSE); // rend un élément selon son index numérique
+ // agrandi le tableau si nécessaire si bExtend
+// CBotVar* GivItem(const char* name); // rend un élément selon son index litéral
+ CBotVar* GivItemList(); // donne le premier élément de la liste
+
+ CBotString GivValString(); // donne le contenu du tableau dans une chaîne
+
+ BOOL Save1State(FILE* pf);
+};
+
+
+extern CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars);
+
+extern BOOL TypeCompatible( CBotTypResult& type1, CBotTypResult& type2, int op = 0 );
+extern BOOL TypesCompatibles( CBotTypResult& type1, CBotTypResult& type2 );
+
+extern BOOL WriteWord(FILE* pf, WORD w);
+extern BOOL ReadWord(FILE* pf, WORD& w);
+extern BOOL ReadLong(FILE* pf, long& w);
+extern BOOL WriteFloat(FILE* pf, float w);
+extern BOOL WriteLong(FILE* pf, long w);
+extern BOOL ReadFloat(FILE* pf, float& w);
+extern BOOL WriteString(FILE* pf, CBotString s);
+extern BOOL ReadString(FILE* pf, CBotString& s);
+extern BOOL WriteType(FILE* pf, CBotTypResult type);
+extern BOOL ReadType(FILE* pf, CBotTypResult& type);
+
+extern float GivNumFloat( const char* p );
+
+#ifdef _DEBUG
+extern void DEBUG( const char* text, int val, CBotStack* pile );
+#endif
+
+///////////////////////////////////////////
+// classe pour les appels de routines (externes)
+
+class CBotCall
+{
+private:
+ static
+ CBotCall* m_ListCalls;
+ static
+ void* m_pUser;
+ long m_nFuncIdent;
+
+private:
+ CBotString m_name;
+ BOOL (*m_rExec) (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser) ;
+ CBotTypResult
+ (*m_rComp) (CBotVar* &pVar, void* pUser) ;
+ CBotCall* m_next;
+
+public:
+ CBotCall(const char* name,
+ BOOL rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+ CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
+ ~CBotCall();
+
+ static
+ BOOL AddFunction(const char* name,
+ BOOL rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+ CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
+
+ static
+ CBotTypResult
+ CompileCall(CBotToken* &p, CBotVar** ppVars, CBotCStack* pStack, long& nIdent);
+ static
+ BOOL CheckCall(const char* name);
+
+// static
+// int DoCall(CBotToken* &p, CBotVar** ppVars, CBotStack* pStack, CBotTypResult& rettype);
+ static
+ int DoCall(long& nIdent, CBotToken* token, CBotVar** ppVars, CBotStack* pStack, CBotTypResult& rettype);
+#if STACKRUN
+ BOOL Run(CBotStack* pStack);
+ static
+ BOOL RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack);
+#endif
+
+ CBotString GivName();
+ CBotCall* Next();
+
+ static void SetPUser(void* pUser);
+ static void Free();
+};
+
+// classe gérant les méthodes déclarées par AddFunction sur une classe
+
+class CBotCallMethode
+{
+private:
+ CBotString m_name;
+ BOOL (*m_rExec) (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception);
+ CBotTypResult
+ (*m_rComp) (CBotVar* pThis, CBotVar* &pVar);
+ CBotCallMethode* m_next;
+ friend class CBotClass;
+ long m_nFuncIdent;
+
+public:
+ CBotCallMethode(const char* name,
+ BOOL rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+ CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar));
+ ~CBotCallMethode();
+
+ CBotTypResult
+ CompileCall(const char* name, CBotVar* pThis,
+ CBotVar** ppVars, CBotCStack* pStack,
+ long& nIdent);
+
+ int DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotVar* &pResult, CBotStack* pStack, CBotToken* pFunc);
+
+ CBotString GivName();
+ CBotCallMethode* Next();
+ void AddNext(CBotCallMethode* p);
+
+};
+
+// une liste de paramètres
+
+class CBotDefParam
+{
+private:
+ CBotToken m_token; // nom du paramètre
+ CBotString m_typename; // nom du type
+ CBotTypResult m_type; // type de paramètre
+ CBotDefParam* m_next; // paramètre suivant
+ long m_nIdent;
+
+public:
+ CBotDefParam();
+ ~CBotDefParam();
+ static
+ CBotDefParam* Compile(CBotToken* &p, CBotCStack* pStack);
+ BOOL Execute(CBotVar** ppVars, CBotStack* &pj);
+ void RestoreState(CBotStack* &pj, BOOL bMain);
+
+ void AddNext(CBotDefParam* p);
+ int GivType();
+ CBotTypResult GivTypResult();
+ CBotDefParam* GivNext();
+
+ CBotString GivParamString();
+};
+
+
+// une déclaration de fonction
+
+class CBotFunction : CBotInstr
+{
+private:
+ // gestion d'une liste (static) de fonctions publiques
+ static
+ CBotFunction* m_listPublic;
+ CBotFunction* m_nextpublic;
+ CBotFunction* m_prevpublic;
+ friend class CBotCStack;
+// long m_nThisIdent;
+ long m_nFuncIdent;
+ BOOL m_bSynchro; // méthode synchronisée ?
+
+private:
+ CBotDefParam* m_Param; // liste des paramètres
+ CBotInstr* m_Block; // le bloc d'instructions
+ CBotFunction* m_next;
+ CBotToken m_retToken; // si retourne un CBotTypClass
+ CBotTypResult m_retTyp; // type complet du résultat
+
+ BOOL m_bPublic; // fonction publique
+ BOOL m_bExtern; // fonction extern
+ CBotString m_MasterClass; // nom de la classe qu'on dérive
+ CBotProgram* m_pProg;
+ friend class CBotProgram;
+ friend class CBotClass;
+
+ CBotToken m_extern; // pour la position du mot "extern"
+ CBotToken m_openpar;
+ CBotToken m_closepar;
+ CBotToken m_openblk;
+ CBotToken m_closeblk;
+public:
+ CBotFunction::CBotFunction();
+ CBotFunction::~CBotFunction();
+ static
+ CBotFunction* Compile(CBotToken* &p, CBotCStack* pStack, CBotFunction* pFunc, BOOL bLocal = TRUE);
+ static
+ CBotFunction* Compile1(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass);
+ BOOL Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance = NULL);
+ void RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance = NULL);
+
+ void AddNext(CBotFunction* p);
+ CBotTypResult CompileCall(const char* name, CBotVar** ppVars, long& nIdent);
+ CBotFunction* FindLocalOrPublic(long& nIdent, const char* name, CBotVar** ppVars, CBotTypResult& TypeOrError, BOOL bPublic = TRUE);
+
+ int DoCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken);
+ void RestoreCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack);
+ int DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass);
+ void RestoreCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass);
+ BOOL CheckParam(CBotDefParam* pParam);
+
+ static
+ void AddPublic(CBotFunction* pfunc);
+
+ CBotString GivName();
+ CBotString GivParams();
+ BOOL IsPublic();
+ BOOL IsExtern();
+ CBotFunction* Next();
+
+ BOOL GetPosition(int& start, int& stop, CBotGet modestart, CBotGet modestop);
+};
+
+
diff --git a/src/CBot/CBot.lib b/src/CBot/CBot.lib
new file mode 100644
index 0000000..548361f
--- /dev/null
+++ b/src/CBot/CBot.lib
Binary files differ
diff --git a/src/CBot/CBot.opt b/src/CBot/CBot.opt
new file mode 100644
index 0000000..9387019
--- /dev/null
+++ b/src/CBot/CBot.opt
Binary files differ
diff --git a/src/CBot/CBot.plg b/src/CBot/CBot.plg
new file mode 100644
index 0000000..dae6fc9
--- /dev/null
+++ b/src/CBot/CBot.plg
@@ -0,0 +1,61 @@
+--------------------Configuration: CBot - Win32 Release--------------------
+Begining build with project "D:\Robot\projet1\CBot\CBot.dsp", at root.
+Active configuration is Win32 (x86) Dynamic-Link Library (based on Win32 (x86) Dynamic-Link Library)
+
+Project's tools are:
+ "32-bit C/C++ Compiler for 80x86" with flags "/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR"Release/" /Fp"Release/CBot.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c "
+ "OLE Type Library Maker" with flags "/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 "
+ "Win32 Resource Compiler" with flags "/l 0x40c /fo"Release/CBot.res" /d "NDEBUG" "
+ "Browser Database Maker" with flags "/nologo /o"Release/CBot.bsc" "
+ "COFF Linker for 80x86" with flags "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"Release/CBot.pdb" /machine:I386 /out:"Release/CBot.dll" /implib:"Release/CBot.lib" "
+ "Custom Build" with flags ""
+ "<Component 0xa>" with flags ""
+
+Creating command line "rc.exe /l 0x40c /fo"Release/CBot.res" /d "NDEBUG" "D:\Robot\projet1\CBot\CBot.rc""
+Creating temp file "C:\DOCUME~1\ROUXDA~1\LOCALS~1\Temp\RSP9.tmp" with contents </nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR"Release/" /Fp"Release/CBot.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c
+"D:\Robot\projet1\CBot\CBot.cpp"
+"D:\Robot\projet1\CBot\CBotClass.cpp"
+"D:\Robot\projet1\CBot\CBotFunction.cpp"
+"D:\Robot\projet1\CBot\CBotIf.cpp"
+"D:\Robot\projet1\CBot\CBotProgram.cpp"
+"D:\Robot\projet1\CBot\CBotStack.cpp"
+"D:\Robot\projet1\CBot\CBotString.cpp"
+"D:\Robot\projet1\CBot\CBotToken.cpp"
+"D:\Robot\projet1\CBot\CBotTwoOpExpr.cpp"
+"D:\Robot\projet1\CBot\CBotVar.cpp"
+"D:\Robot\projet1\CBot\CBotWhile.cpp"
+>
+Creating command line "cl.exe @C:\DOCUME~1\ROUXDA~1\LOCALS~1\Temp\RSP9.tmp"
+Creating temp file "C:\DOCUME~1\ROUXDA~1\LOCALS~1\Temp\RSPA.tmp" with contents <kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"Release/CBot.pdb" /machine:I386 /out:"Release/CBot.dll" /implib:"Release/CBot.lib"
+.\Release\CBot.obj
+.\Release\CBotClass.obj
+.\Release\CBotFunction.obj
+.\Release\CBotIf.obj
+.\Release\CBotProgram.obj
+.\Release\CBotStack.obj
+.\Release\CBotString.obj
+.\Release\CBotToken.obj
+.\Release\CBotTwoOpExpr.obj
+.\Release\CBotVar.obj
+.\Release\CBotWhile.obj
+.\Release\CBot.res>
+Creating command line "link.exe @C:\DOCUME~1\ROUXDA~1\LOCALS~1\Temp\RSPA.tmp"
+Compiling resources...
+Compiling...
+CBot.cpp
+CBotClass.cpp
+CBotFunction.cpp
+CBotIf.cpp
+CBotProgram.cpp
+CBotStack.cpp
+CBotString.cpp
+CBotToken.cpp
+CBotTwoOpExpr.cpp
+CBotVar.cpp
+CBotWhile.cpp
+Linking...
+ Creating library Release/CBot.lib and object Release/CBot.exp
+
+
+
+CBot.dll - 0 error(s), 0 warning(s)
diff --git a/src/CBot/CBot.rc b/src/CBot/CBot.rc
new file mode 100644
index 0000000..d8b5b74
--- /dev/null
+++ b/src/CBot/CBot.rc
@@ -0,0 +1,279 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_IF "if"
+ ID_ELSE "else"
+ ID_WHILE "while"
+ ID_DO "do"
+ ID_FOR "for"
+ ID_BREAK "break"
+ ID_CONTINUE "continue"
+ ID_SWITCH "switch"
+ ID_CASE "case"
+ ID_DEFAULT "default"
+ ID_TRY "try"
+ ID_THROW "throw"
+ ID_CATCH "catch"
+ ID_FINALLY "finally"
+ ID_TXT_AND "and"
+ ID_TXT_OR "or"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_DEBUGDD "STARTDEBUGDD"
+ ID_INT "int"
+ ID_FLOAT "float"
+ ID_BOOLEAN "boolean"
+ ID_STRING "string"
+ ID_VOID "void"
+ ID_BOOL "bool"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TXT_NOT "not"
+ ID_RETURN "return"
+ ID_CLASS "class"
+ ID_EXTENDS "extends"
+ ID_SYNCHO "synchronized"
+ ID_NEW "new"
+ ID_PUBLIC "public"
+ ID_EXTERN "extern"
+ ID_FINAL "final"
+ ID_STATIC "static"
+ ID_PROTECTED "protected"
+ ID_PRIVATE "private"
+ ID_REPEAT "repeat"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OPENPAR "Il manque une parenthèse ouvrante."
+ TX_CLOSEPAR "Il manque une parenthèse fermante."
+ TX_NOTBOOL "L'expression doit être un boolean."
+ TX_UNDEFVAR "Variable non déclarée."
+ TX_BADLEFT "Assignation impossible."
+ TX_ENDOF "Terminateur point-virgule non trouvé."
+ TX_OUTCASE "Instruction ""case"" hors d'un bloc ""switch""."
+ TX_NOTERM "Instructions après la fin."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_CLOSEBLK "Il manque la fin du bloc."
+ TX_ELSEWITHOUTIF "Instruction ""else"" sans ""if"" correspondant."
+ TX_OPENBLK "Début d'un bloc attendu."
+ TX_BADTYPE "Mauvais type de résultat pour l'assignation."
+ TX_REDEFVAR "Redéfinition d'une variable."
+ TX_BAD2TYPE "Les deux opérandes ne sont pas de types compatibles."
+ TX_UNDEFCALL "Routine inconnue."
+ TX_MISDOTS "Séparateur "" : "" attendu."
+ TX_WHILE "Manque le mot ""while""."
+ TX_BREAK "Instruction ""break"" en dehors d'une boucle."
+ TX_LABEL "Un label ne peut se placer que devant un ""for"", un ""while"" ou un ""do""."
+ TX_NOLABEL "Cette étiquette n'existe pas"
+ TX_NOCASE "Manque une instruction ""case""."
+ TX_BADNUM "Un nombre est attendu."
+ TX_VOID "Paramètre void."
+ TX_NOTYP "Déclaration de type attendu."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_DIVZERO "Division par zéro."
+ TX_NOTINIT "Variable non initialisée."
+ TX_BADTHROW "Valeur négative refusée pour ""throw""."
+ TX_NORETVAL "La fonction n'a pas retourné de résultat"
+ TX_NORUN "Pas de fonction en exécution"
+ TX_NOCALL "Appel d'une fonction inexistante"
+ TX_NOCLASS "Cette classe n'existe pas"
+ TX_NULLPT "Pointeur nul."
+ TX_OPNAN "Opération sur un ""nan"""
+ TX_OUTARRAY "Accès hors du tableau"
+ TX_STACKOVER "Dépassement de la pile"
+ TX_DELETEDPT "Pointeur à un objet détruit"
+ TX_FILEOPEN "Ouverture du fichier impossible"
+ TX_NOTOPEN "Fichier pas ouvert"
+ TX_ERRREAD "Erreur de lecture"
+ TX_ERRWRITE "Erreur d'écriture"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_NOVAR "Nom d'une variable attendu."
+ TX_NOFONC "Nom de la fonction attendu."
+ TX_OVERPARAM "Trop de paramètres."
+ TX_REDEF "Cette fonction existe déjà."
+ TX_LOWPARAM "Pas assez de paramètres."
+ TX_BADPARAM "Aucune fonction de ce nom n'accepte ce(s) type(s) de paramètre(s)."
+ TX_NUMPARAM "Aucune fonction de ce nom n'accepte ce nombre de paramètres."
+ TX_NOITEM "Cet élément n'existe pas dans cette classe."
+ TX_DOT "L'objet n'est pas une instance d'une classe."
+ TX_NOCONST "Il n'y a pas de constructeur approprié."
+ TX_REDEFCLASS "Cette classe existe déjà."
+ TX_CLBRK """ ] "" attendu."
+ TX_RESERVED "Ce mot est réservé."
+ TX_BADNEW "Mauvais argument pour ""new""."
+ TX_OPBRK """ [ "" attendu."
+ TX_BADSTRING "Une chaîne de caractère est attendue."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BADINDEX "Mauvais type d'index"
+ TX_PRIVATE "Membre privé de la classe"
+ TX_NOPUBLIC """public"" manque"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_OPENPAR "("
+ ID_CLOSEPAR ")"
+ ID_OPBLK "{"
+ ID_CLBLK "}"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SEP ";"
+ ID_COMMA ","
+ ID_DOTS ":"
+ ID_DOT "."
+ ID_OPBRK "["
+ ID_CLBRK "]"
+ ID_DBLDOTS "::"
+ ID_LOGIC "?"
+ ID_ADD "+"
+ ID_SUB "-"
+ ID_MUL "*"
+ ID_DIV "/"
+ ID_ASS "="
+ ID_ASSADD "+="
+ ID_ASSSUB "-="
+ ID_ASSMUL "*="
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TRUE "true"
+ ID_FALSE "false"
+ ID_NULL "null"
+ ID_NAN "nan"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_ASSDIV "/="
+ ID_ASSOR "|="
+ ID_ASSAND "&="
+ ID_ASSXOR "^="
+ ID_ASSSL "<<="
+ ID_ASSSR ">>>="
+ ID_ASSASR ">>="
+ ID_SL "<<"
+ ID_SR ">>>"
+ ID_ASR ">>"
+ ID_INC "++"
+ ID_DEC "--"
+ ID_LO "<"
+ ID_HI ">"
+ ID_LS "<="
+ ID_HS ">="
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_EQ "=="
+ ID_NE "!="
+ ID_AND "&"
+ ID_XOR "^"
+ ID_OR "|"
+ ID_LOG_AND "&&"
+ ID_LOG_OR "||"
+ ID_LOG_NOT "!"
+ ID_NOT "~"
+ ID_MODULO "%"
+ ID_POWER "**"
+ ID_ASSMODULO "%="
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_UNDEF "undefined"
+ TX_NAN "not a number"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SUPER "super"
+END
+
+#endif // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/CBot/CBotAddExpr.cpp b/src/CBot/CBotAddExpr.cpp
new file mode 100644
index 0000000..1d2555a
--- /dev/null
+++ b/src/CBot/CBotAddExpr.cpp
@@ -0,0 +1,128 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 + Opérande2
+// Opérande1 - Opérande2
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotAddExpr::CBotAddExpr()
+{
+ m_leftop =
+ m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
+ name = "CBotAddExpr"; // debug
+}
+
+CBotAddExpr::~CBotAddExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+
+// compile une instruction de type A + B
+
+CBotInstr* CBotAddExpr::Compile(CBotToken* &p, CBotStack* pStack)
+{
+ CBotStack* pStk = pStack->TokenStack(); // un bout de pile svp
+
+ // cherche des instructions qui peuvent convenir à gauche de l'opération + ou -
+
+ CBotInstr* left = CBotMulExpr::Compile( p, pStk ); // expression A * B à gauche
+ if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
+
+ // est-ce qu'on a le token + ou - ensuite ?
+
+ if ( p->GetType() == ID_ADD ||
+ p->GetType() == ID_SUB) // plus ou moins
+ {
+ CBotAddExpr* inst = new CBotAddExpr(); // élément pour opération
+ inst->SetToken(p); // mémorise l'opération
+
+ int type1, type2;
+ type1 = pStack->GetType(); // de quel type le premier opérande ?
+
+ p = p->Next(); // saute le token de l'opération
+
+ // cherche des instructions qui peuvent convenir à droite
+
+ if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression (...) à droite
+ {
+ // il y a un second opérande acceptable
+
+ type2 = pStack->GetType(); // de quel type le résultat ?
+
+ if ( type1 == type2 ) // les résultats sont-ils compatibles
+ {
+ // si ok, enregistre l'opérande dans l'objet
+ inst->m_leftop = left;
+ // et rend l'object à qui l'a demandé
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ // en cas d'erreur, libère les éléments
+ delete left;
+ delete inst;
+ // et transmet l'erreur qui se trouve sur la pile
+ return pStack->Return(NULL, pStk);
+ }
+
+ // si on n'a pas affaire à une opération + ou -
+ // rend à qui l'a demandé, l'opérande (de gauche) trouvé
+ // à la place de l'objet "addition"
+ return pStack->Return(left, pStk);
+}
+
+
+
+
+// fait l'opération d'addition ou de soustraction
+
+BOOL CBotAddExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pSk1 == EOX ) return TRUE;
+
+
+ // selon la reprise, on peut être dans l'un des 2 états
+
+ if ( pStk1->GetState() == 0 && // 1er état, évalue l'opérande de gauche
+ !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ // passe à l'étape suivante
+ pStk1->SetState(1); // prêt pour la suite
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ // qui se trouve sur la pile, justement.
+
+ CBotStack* pStk2 = pStk1->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // 2e état, évalue l'opérande de droite
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+
+ int type1 = pStk1->GetType(); // de quels types les résultats ?
+ int type2 = pStk2->GetType();
+
+ // crée une variable temporaire pour y mettre le résultat
+ CBotVar* result = new CBotVar( NULL, MAX(type1, type2));
+
+ // fait l'opération selon la demande
+ switch (GetTokenType())
+ {
+ case ID_ADD:
+ result->Add(pStk1->GetVar(), pStk2->GetVar()); // additionne
+ break;
+ case ID_SUB:
+ result->Sub(pStk1->GetVar(), pStk2->GetVar()); // soustrait
+ break;
+ }
+ pStk2->SetVar(result); // met le résultat sur la pile
+
+ pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
+
diff --git a/src/CBot/CBotClass.cpp b/src/CBot/CBotClass.cpp
new file mode 100644
index 0000000..180faf3
--- /dev/null
+++ b/src/CBot/CBotClass.cpp
@@ -0,0 +1,867 @@
+///////////////////////////////////////////////////////////////////////
+// Gestion des variables de type classe
+//
+
+#include "CBot.h"
+
+
+CBotClass* CBotClass::m_ExClass = NULL;
+
+CBotClass::CBotClass(const char* name, CBotClass* pPapa, BOOL bIntrinsic)
+{
+ m_pParent = pPapa;
+ m_name = name;
+ m_pVar = NULL;
+ m_next = NULL;
+ m_pCalls = NULL;
+ m_pMethod = NULL;
+ m_rMaj = NULL;
+ m_IsDef = TRUE;
+ m_bIntrinsic= bIntrinsic;
+ m_cptLock = 0;
+ m_cptOne = 0;
+ m_nbVar = m_pParent == NULL ? 0 : m_pParent->m_nbVar;
+
+ for ( int j= 0; j< 5 ; j++ )
+ {
+ m_ProgInLock[j] = NULL;
+ }
+
+
+ // se place tout seul dans la liste
+ if (m_ExClass) m_ExClass->m_ExPrev = this;
+ m_ExNext = m_ExClass;
+ m_ExPrev = NULL;
+ m_ExClass = this;
+
+}
+
+CBotClass::~CBotClass()
+{
+ // retire la classe de la liste
+ if ( m_ExPrev ) m_ExPrev->m_ExNext = m_ExNext;
+ else m_ExClass = m_ExNext;
+
+ if ( m_ExNext ) m_ExNext->m_ExPrev = m_ExPrev;
+ m_ExPrev = NULL;
+ m_ExNext = NULL;
+
+ delete m_pVar;
+ delete m_pCalls;
+ delete m_pMethod;
+
+ delete m_next; // libère toutes celle de ce niveau
+}
+
+
+void CBotClass::Free()
+{
+ while ( m_ExClass != NULL )
+ {
+ delete m_ExClass;
+ }
+}
+
+void CBotClass::Purge()
+{
+ if ( this == NULL ) return;
+
+ delete m_pVar;
+ m_pVar = NULL;
+ delete m_pCalls;
+ m_pCalls = NULL;
+ delete m_pMethod;
+ m_pMethod = NULL;
+ m_IsDef = FALSE;
+
+ m_nbVar = m_pParent == NULL ? 0 : m_pParent->m_nbVar;
+
+ m_next->Purge();
+ m_next = NULL; // n'appartient plus à cette chaîne
+}
+
+BOOL CBotClass::Lock(CBotProgram* p)
+{
+ int i = m_cptLock++;
+
+ if ( i == 0 )
+ {
+ m_cptOne = 1;
+ m_ProgInLock[0] = p;
+ return TRUE;
+ }
+ if ( p == m_ProgInLock[0] )
+ {
+ m_cptOne++;
+ m_cptLock--; // a déjà été compté
+ return TRUE;
+ }
+
+ for ( int j = 1 ; j <= i ; j++)
+ {
+ if ( p == m_ProgInLock[j] )
+ {
+ m_cptLock--;
+ return FALSE; // déjà en attente
+ }
+ }
+
+ if ( i < 5 ) // maxi 5 en attente
+ {
+ m_ProgInLock[i] = p; // se place dans la queue
+ }
+ else
+ m_cptLock--;
+
+ return FALSE;
+}
+
+void CBotClass::Unlock()
+{
+ if ( --m_cptOne > 0 ) return ;
+
+ int i = --m_cptLock;
+ if ( i<0 )
+ {
+ m_cptLock = 0;
+ return;
+ }
+
+ for ( int j= 0; j< i ; j++ )
+ {
+ m_ProgInLock[j] = m_ProgInLock[j+1];
+ }
+ m_ProgInLock[i] = 0;
+}
+
+void CBotClass::FreeLock(CBotProgram* p)
+{
+ CBotClass* pClass = m_ExClass;
+
+ while ( pClass != NULL )
+ {
+ if ( p == pClass->m_ProgInLock[0] )
+ {
+ pClass->m_cptLock -= pClass->m_cptOne;
+ pClass->m_cptOne = 0;
+ }
+
+ for ( int j = 1; j < 5 ; j++ )
+ if ( p == pClass->m_ProgInLock[j] )
+ pClass->m_cptLock--;
+
+ pClass = pClass->m_ExNext;
+ }
+}
+
+
+
+BOOL CBotClass::AddItem(CBotString name, CBotTypResult type, int mPrivate)
+{
+ CBotToken token(name, CBotString());
+ CBotClass* pClass = type.GivClass();
+
+ CBotVar* pVar = CBotVar::Create( name, type );
+/// pVar->SetUniqNum(CBotVar::NextUniqNum());
+ pVar->SetPrivate( mPrivate );
+
+ if ( pClass != NULL )
+ {
+// pVar->SetClass(pClass);
+ if ( type.Eq(CBotTypClass) )
+ {
+ // ajoute une instruction new pour initialiser l'object
+ pVar->m_InitExpr = new CBotNew() ;
+ CBotToken nom( pClass->GivName() );
+ pVar->m_InitExpr->SetToken(&nom);
+ }
+ }
+ return AddItem( pVar );
+}
+
+
+BOOL CBotClass::AddItem(CBotVar* pVar)
+{
+ pVar->SetUniqNum(++m_nbVar);
+
+ if ( m_pVar == NULL ) m_pVar = pVar;
+ else m_pVar->AddNext(pVar);
+
+ return TRUE;
+}
+
+void CBotClass::AddNext(CBotClass* pClass)
+{
+ CBotClass* p = this;
+ while (p->m_next != NULL) p = p->m_next;
+
+ p->m_next = pClass;
+}
+
+CBotString CBotClass::GivName()
+{
+ return m_name;
+}
+
+CBotClass* CBotClass::GivParent()
+{
+ if ( this == NULL ) return NULL;
+ return m_pParent;
+}
+
+BOOL CBotClass::IsChildOf(CBotClass* pClass)
+{
+ CBotClass* p = this;
+ while ( p != NULL )
+ {
+ if ( p == pClass ) return TRUE;
+ p = p->m_pParent;
+ }
+ return FALSE;
+}
+
+
+CBotVar* CBotClass::GivVar()
+{
+ return m_pVar;
+}
+
+CBotVar* CBotClass::GivItem(const char* name)
+{
+ CBotVar* p = m_pVar;
+
+ while ( p != NULL )
+ {
+ if ( p->GivName() == name ) return p;
+ p = p->GivNext();
+ }
+ if ( m_pParent != NULL ) return m_pParent->GivItem(name);
+ return NULL;
+}
+
+CBotVar* CBotClass::GivItemRef(int nIdent)
+{
+ CBotVar* p = m_pVar;
+
+ while ( p != NULL )
+ {
+ if ( p->GivUniqNum() == nIdent ) return p;
+ p = p->GivNext();
+ }
+ if ( m_pParent != NULL ) return m_pParent->GivItemRef(nIdent);
+ return NULL;
+}
+
+BOOL CBotClass::IsIntrinsic()
+{
+ return m_bIntrinsic;
+}
+
+CBotClass* CBotClass::Find(CBotToken* &pToken)
+{
+ return Find(pToken->GivString());
+}
+
+CBotClass* CBotClass::Find(const char* name)
+{
+ CBotClass* p = m_ExClass;
+
+ while ( p != NULL )
+ {
+ if ( p->GivName() == name ) return p;
+ p = p->m_ExNext;
+ }
+
+ return NULL;
+}
+
+BOOL CBotClass::AddFunction(const char* name,
+ BOOL rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+ CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar))
+{
+ // mémorise les pointeurs aux deux fonctions
+ CBotCallMethode* p = m_pCalls;
+ CBotCallMethode* pp = NULL;
+
+ while ( p != NULL )
+ {
+ if ( name == p->GivName() )
+ {
+ if ( pp == NULL ) m_pCalls = p->m_next;
+ else pp->m_next = p->m_next;
+ delete p;
+ break;
+ }
+ pp = p;
+ p = p->m_next;
+ }
+
+ p = new CBotCallMethode(name, rExec, rCompile);
+
+ if (m_pCalls == NULL) m_pCalls = p;
+ else m_pCalls->AddNext(p); // ajoute à la liste
+
+ return TRUE;
+}
+
+BOOL CBotClass::AddUpdateFunc( void rMaj ( CBotVar* pThis, void* pUser ) )
+{
+ m_rMaj = rMaj;
+ return TRUE;
+}
+
+// compile une méthode associée à une instance de classe
+// la méthode peut être déclarée par AddFunction ou par l'utilisateur
+
+CBotTypResult CBotClass::CompileMethode(const char* name,
+ CBotVar* pThis, CBotVar** ppParams,
+ CBotCStack* pStack, long& nIdent)
+{
+ nIdent = 0; // oublie le précédent s'il y a lieu
+
+ // recherche dans les méthodes déclarées par AddFunction
+
+ CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack, nIdent);
+ if ( r.GivType() >= 0) return r;
+
+ // recherche dans les méthodes déclarées par l'utilisateur
+
+ r = m_pMethod->CompileCall(name, ppParams, nIdent);
+ if ( r.Eq(TX_UNDEFCALL) && m_pParent != NULL )
+ return m_pParent->m_pMethod->CompileCall(name, ppParams, nIdent);
+ return r;
+}
+
+// exécute une méthode
+
+BOOL CBotClass::ExecuteMethode(long& nIdent, const char* name,
+ CBotVar* pThis, CBotVar** ppParams,
+ CBotVar* &pResult, CBotStack* &pStack,
+ CBotToken* pToken)
+{
+ int ret = m_pCalls->DoCall(nIdent, name, pThis, ppParams, pResult, pStack, pToken);
+ if (ret>=0) return ret;
+
+ ret = m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, this);
+ return ret;
+}
+
+// rétabli la pile d'exécution
+
+void CBotClass::RestoreMethode(long& nIdent, const char* name, CBotVar* pThis,
+ CBotVar** ppParams, CBotStack* &pStack)
+{
+ m_pMethod->RestoreCall(nIdent, name, pThis, ppParams, pStack, this);
+}
+
+
+
+
+BOOL CBotClass::SaveStaticState(FILE* pf)
+{
+ if (!WriteWord( pf, CBOTVERSION*2)) return FALSE;
+
+ // sauve l'état des variables statiques dans les classes
+ CBotClass* p = m_ExClass;
+
+ while ( p != NULL )
+ {
+ if (!WriteWord( pf, 1)) return FALSE;
+ // enregistre le nom de la classe
+ if (!WriteString( pf, p->GivName() )) return FALSE;
+
+ CBotVar* pv = p->GivVar();
+ while( pv != NULL )
+ {
+ if ( pv->IsStatic() )
+ {
+ if (!WriteWord( pf, 1)) return FALSE;
+ if (!WriteString( pf, pv->GivName() )) return FALSE;
+
+ if ( !pv->Save0State(pf)) return FALSE; // entête commune
+ if ( !pv->Save1State(pf) ) return FALSE; // sauve selon la classe fille
+ if ( !WriteWord( pf, 0)) return FALSE;
+ }
+ pv = pv->GivNext();
+ }
+
+ if (!WriteWord( pf, 0)) return FALSE;
+ p = p->m_ExNext;
+ }
+
+ if (!WriteWord( pf, 0)) return FALSE;
+ return TRUE;
+}
+
+BOOL CBotClass::RestoreStaticState(FILE* pf)
+{
+ CBotString ClassName, VarName;
+ CBotClass* pClass;
+ WORD w;
+
+ if (!ReadWord( pf, w )) return FALSE;
+ if ( w != CBOTVERSION*2 ) return FALSE;
+
+ while (TRUE)
+ {
+ if (!ReadWord( pf, w )) return FALSE;
+ if ( w == 0 ) return TRUE;
+
+ if (!ReadString( pf, ClassName )) return FALSE;
+ pClass = Find(ClassName);
+
+ while (TRUE)
+ {
+ if (!ReadWord( pf, w )) return FALSE;
+ if ( w == 0 ) break;
+
+ CBotVar* pVar = NULL;
+ CBotVar* pv = NULL;
+
+ if (!ReadString( pf, VarName )) return FALSE;
+ if ( pClass != NULL ) pVar = pClass->GivItem(VarName);
+
+ if (!CBotVar::RestoreState(pf, pv)) return FALSE; // la variable temp
+
+ if ( pVar != NULL ) pVar->Copy(pv);
+ delete pv;
+ }
+ }
+ return TRUE;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+
+CBotClassInst::CBotClassInst()
+{
+ m_next = NULL;
+ m_var = NULL;
+ m_Parameters = NULL;
+ m_expr = NULL;
+ m_hasParams = FALSE;
+ m_nMethodeIdent = 0;
+ name = "CBotClassInst";
+}
+
+CBotClassInst::~CBotClassInst()
+{
+ delete m_var;
+// delete m_next; // fait par le destructeur de la classe de base ~CBotInstr()
+}
+
+// définition de pointeur(s) à un objet
+// du style
+// CPoint A, B ;
+
+CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass)
+{
+ // cherche la classe correspondante
+ if ( pClass == NULL )
+ {
+ pStack->SetStartError(p->GivStart());
+ pClass = CBotClass::Find(p);
+ if ( pClass == NULL )
+ {
+ // pas trouvé ? c'est bizare
+ pStack->SetError(TX_NOCLASS, p);
+ return NULL;
+ }
+ p = p->GivNext();
+ }
+
+ BOOL bIntrinsic = pClass->IsIntrinsic();
+ CBotTypResult
+ type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer,
+ pClass );
+ CBotClassInst* inst = (CBotClassInst*)CompileArray(p, pStack, type);
+ if ( inst != NULL || !pStack->IsOk() ) return inst;
+
+ CBotCStack* pStk = pStack->TokenStack();
+
+ inst = new CBotClassInst();
+
+ inst->SetToken(&pClass->GivName(), p->GivStart(), p->GivEnd());
+ CBotToken* vartoken = p;
+
+ if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
+ {
+ ((CBotLeftExprVar*)inst->m_var)->m_typevar = type;
+ if (pStk->CheckVarLocal(vartoken)) // redéfinition de la variable
+ {
+ pStk->SetStartError(vartoken->GivStart());
+ pStk->SetError(TX_REDEFVAR, vartoken->GivEnd());
+ goto error;
+ }
+
+ if (IsOfType(p, ID_OPBRK)) // avec des indices ?
+ {
+ delete inst; // n'est pas de type CBotInt
+ p = vartoken; // revient sur le nom de la variable
+
+ // compile une déclaration de tableau
+
+ inst = (CBotClassInst*)CBotInstArray::Compile( p, pStk, type );
+
+ if (!pStk->IsOk() )
+ {
+ pStk->SetError(TX_CLBRK, p->GivStart());
+ goto error;
+ }
+ goto suite; // pas d'assignation, variable déjà créée
+ }
+
+
+ CBotVar* var;
+ var = CBotVar::Create(vartoken->GivString(), type); // crée l'instance
+// var->SetClass(pClass);
+ var->SetUniqNum(
+ ((CBotLeftExprVar*)inst->m_var)->m_nIdent = CBotVar::NextUniqNum());
+ // lui attribut un numéro unique
+ pStack->AddVar(var); // la place sur la pile
+
+ // regarde s'il y a des paramètres
+ inst->m_hasParams = (p->GivType() == ID_OPENPAR);
+
+ CBotVar* ppVars[1000];
+ inst->m_Parameters = CompileParams(p, pStk, ppVars);
+ if ( !pStk->IsOk() ) goto error;
+
+ // s'il y a des paramètres, fait l'équivalent de l'instruction new
+ // CPoint A ( 0, 0 ) est équivalent à
+ // CPoint A = new CPoint( 0, 0 )
+
+// if ( NULL != inst->m_Parameters )
+ if ( inst->m_hasParams )
+ {
+ // le constructeur existe-il ?
+// CBotString noname;
+ CBotTypResult r = pClass->CompileMethode(pClass->GivName(), var, ppVars, pStk, inst->m_nMethodeIdent);
+ delete pStk->TokenStack(); // libère le supplément de pile
+ int typ = r.GivType();
+
+ if (typ == TX_UNDEFCALL)
+ {
+ // si le constructeur n'existe pas
+ if (inst->m_Parameters != NULL) // avec des paramètres
+ {
+ pStk->SetError(TX_NOCONST, vartoken);
+ goto error;
+ }
+ typ = 0;
+ }
+
+ if (typ>20)
+ {
+ pStk->SetError(typ, vartoken->GivEnd());
+ goto error;
+ }
+
+ }
+
+ if (IsOfType(p, ID_ASS)) // avec une assignation ?
+ {
+ if (inst->m_hasParams)
+ {
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ goto error;
+ }
+
+ if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
+ {
+ goto error;
+ }
+ CBotClass* result = pStk->GivClass();
+ if ( !pStk->GivTypResult(1).Eq(CBotTypNullPointer) &&
+ ( !pStk->GivTypResult(1).Eq(CBotTypPointer) ||
+ ( result != NULL && !pClass->IsChildOf(result) ))) // type compatible ?
+ {
+ pStk->SetError(TX_BADTYPE, p->GivStart());
+ goto error;
+ }
+// if ( !bIntrinsic ) var->SetPointer(pStk->GivVar()->GivPointer());
+ if ( !bIntrinsic )
+ {
+ // n'utilise pas le résultat sur la pile, pour imposer la classe
+ CBotVar* pvar = CBotVar::Create("", pClass);
+ var->SetPointer( pvar ); // var déjà déclarée pointe l'instance
+ delete pvar; // supprime le second pointeur
+ }
+ var->SetInit(TRUE); // marque le pointeur comme init
+ }
+ else if (inst->m_hasParams)
+ {
+ // crée l'objet sur le "tas"
+ // avec un pointeur sur cet objet
+ if ( !bIntrinsic )
+ {
+ CBotVar* pvar = CBotVar::Create("", pClass);
+ var->SetPointer( pvar ); // var déjà déclarée pointe l'instance
+ delete pvar; // supprime le second pointeur
+ }
+ var->SetInit(2); // marque le pointeur comme init
+ }
+suite:
+ if (IsOfType(p, ID_COMMA)) // plusieurs définitions enchaînées
+ {
+ if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compile la suivante
+ {
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ if (IsOfType(p, ID_SEP)) // instruction terminée
+ {
+ return pStack->Return(inst, pStk);
+ }
+
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ }
+
+error:
+ delete inst;
+ return pStack->Return(NULL, pStk);
+}
+
+// déclaration de l'instance d'une classe, par exemple:
+// CPoint A, B;
+
+BOOL CBotClassInst::Execute(CBotStack* &pj)
+{
+ CBotVar* pThis = NULL;
+
+ CBotStack* pile = pj->AddStack(this);//indispensable pour SetState()
+// if ( pile == EOX ) return TRUE;
+
+ CBotToken* pt = &m_token;
+ CBotClass* pClass = CBotClass::Find(pt);
+
+ BOOL bIntrincic = pClass->IsIntrinsic();
+
+ // crée la variable de type pointeur à l'objet
+
+ if ( pile->GivState()==0)
+ {
+ CBotString name = m_var->m_token.GivString();
+ if ( bIntrincic )
+ {
+ pThis = CBotVar::Create(name, CBotTypResult( CBotTypIntrinsic, pClass ));
+ }
+ else
+ {
+ pThis = CBotVar::Create(name, CBotTypResult( CBotTypPointer, pClass ));
+ }
+
+ pThis->SetUniqNum(((CBotLeftExprVar*)m_var)->m_nIdent); // lui attribut un numéro unique
+ pile->AddVar(pThis); // la place sur la pile
+ pile->IncState();
+ }
+
+ if ( pThis == NULL ) pThis = pile->FindVar(((CBotLeftExprVar*)m_var)->m_nIdent);
+
+ if ( pile->GivState()<3)
+ {
+ // y a-t-il une assignation ou des paramètres (constructeur)
+
+// CBotVarClass* pInstance = NULL;
+
+ if ( m_expr != NULL )
+ {
+ // évalue l'expression pour l'assignation
+ if (!m_expr->Execute(pile)) return FALSE;
+
+ if ( bIntrincic )
+ {
+ CBotVar* pv = pile->GivVar();
+ if ( pv == NULL || pv->GivPointer() == NULL )
+ {
+ pile->SetError(TX_NULLPT, &m_token);
+ return pj->Return(pile);
+ }
+ pThis->Copy(pile->GivVar(), FALSE);
+ }
+ else
+ {
+ CBotVarClass* pInstance;
+ pInstance = ((CBotVarPointer*)pile->GivVar())->GivPointer(); // valeur pour l'assignation
+ pThis->SetPointer(pInstance);
+ }
+ pThis->SetInit(TRUE);
+ }
+
+ else if ( m_hasParams )
+ {
+ // évalue le constructeur d'une instance
+
+ if ( !bIntrincic && pile->GivState() == 1)
+ {
+ CBotToken* pt = &m_token;
+ CBotClass* pClass = CBotClass::Find(pt);
+
+ // crée une instance de la classe demandée
+
+ CBotVarClass* pInstance;
+ pInstance = (CBotVarClass*)CBotVar::Create("", pClass);
+ pThis->SetPointer(pInstance);
+ delete pInstance;
+
+ pile->IncState();
+ }
+
+ CBotVar* ppVars[1000];
+ CBotStack* pile2 = pile;
+
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+
+ if ( p != NULL) while ( TRUE )
+ {
+ pile2 = pile2->AddStack(); // de la place sur la pile pour les résultats
+ if ( pile2->GivState() == 0 )
+ {
+ if (!p->Execute(pile2)) return FALSE; // interrompu ici ?
+ pile2->SetState(1);
+ }
+ ppVars[i++] = pile2->GivVar();
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ // crée une variable pour le résultat
+ CBotVar* pResult = NULL; // constructeurs toujours void
+
+ if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GivName(),
+ pThis, ppVars,
+ pResult, pile2, GivToken())) return FALSE; // interrompu
+
+ pThis->SetInit(TRUE);
+ pThis->ConstructorSet(); // signale que le constructeur a été appelé
+ pile->Return(pile2); // libère un bout de pile
+
+// pInstance = pThis->GivPointer();
+
+ }
+
+// if ( !bIntrincic ) pThis->SetPointer(pInstance); // le fait pointer l'instance
+
+ pile->SetState(3); // fini cette partie
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ if ( m_next2b != NULL &&
+ !m_next2b->Execute(pile)) return FALSE; // autre(s) définition(s)
+
+ return pj->Return( pile ); // transmet en dessous
+}
+
+
+
+void CBotClassInst::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotVar* pThis = NULL;
+
+ CBotStack* pile = pj;
+ if ( bMain ) pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ // crée la variable de type pointeur à l'objet
+ {
+ CBotString name = m_var->m_token.GivString();
+ pThis = pile->FindVar(name);
+ pThis->SetUniqNum(((CBotLeftExprVar*)m_var)->m_nIdent); // lui attribut un numéro unique
+ }
+
+ CBotToken* pt = &m_token;
+ CBotClass* pClass = CBotClass::Find(pt);
+ BOOL bIntrincic = pClass->IsIntrinsic();
+
+ if ( bMain && pile->GivState()<3)
+ {
+ // y a-t-il une assignation ou des paramètres (constructeur)
+
+// CBotVarClass* pInstance = NULL;
+
+ if ( m_expr != NULL )
+ {
+ // évalue l'expression pour l'assignation
+ m_expr->RestoreState(pile, bMain);
+ return;
+ }
+
+ else if ( m_hasParams )
+ {
+ // évalue le constructeur d'une instance
+
+ if ( !bIntrincic && pile->GivState() == 1)
+ {
+ return;
+ }
+
+ CBotVar* ppVars[1000];
+ CBotStack* pile2 = pile;
+
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+
+ if ( p != NULL) while ( TRUE )
+ {
+ pile2 = pile2->RestoreStack(); // de la place sur la pile pour les résultats
+ if ( pile2 == NULL ) return;
+
+ if ( pile2->GivState() == 0 )
+ {
+ p->RestoreState(pile2, bMain); // interrompu ici ?
+ return;
+ }
+ ppVars[i++] = pile2->GivVar();
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ // crée une variable pour le résultat
+ CBotVar* pResult = NULL; // constructeurs toujours void
+
+ pClass->RestoreMethode(m_nMethodeIdent, pClass->GivName(), pThis, ppVars, pile2);
+ return;
+ }
+ }
+
+ if ( m_next2b != NULL )
+ m_next2b->RestoreState(pile, bMain); // autre(s) définition(s)
+}
+
+
+// test si un nom de procédure est déjà défini quelque part
+
+BOOL CBotClass::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
+{
+ CBotString name = pToken->GivString();
+
+ if ( CBotCall::CheckCall(name) ) return TRUE;
+
+ CBotFunction* pp = m_pMethod;
+ while ( pp != NULL )
+ {
+ if ( pToken->GivString() == pp->GivName() )
+ {
+ // les paramètres sont-ils exactement les mêmes ?
+ if ( pp->CheckParam( pParam ) )
+ return TRUE;
+ }
+ pp = pp->Next();
+ }
+
+ return FALSE;
+}
+
diff --git a/src/CBot/CBotCompExpr.cpp b/src/CBot/CBotCompExpr.cpp
new file mode 100644
index 0000000..99abfb9
--- /dev/null
+++ b/src/CBot/CBotCompExpr.cpp
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 > Opérande2
+// Opérande1 != Opérande2
+// etc.
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotCompExpr::CBotCompExpr()
+{
+ m_leftop =
+ m_rightop = NULL;
+ name = "CBotCompExpr";
+}
+
+CBotCompExpr::~CBotCompExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+fichier plus utilise;
+
+// compile une instruction de type A < B
+
+CBotInstr* CBotCompExpr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->AddStack();
+
+ CBotInstr* left = CBotAddExpr::Compile( p, pStk ); // expression A + B à gauche
+ if (left == NULL) return pStack->Return(NULL, pStk); // erreur
+
+ if ( p->GetType() == ID_HI ||
+ p->GetType() == ID_LO ||
+ p->GetType() == ID_HS ||
+ p->GetType() == ID_LS ||
+ p->GetType() == ID_EQ ||
+ p->GetType() == ID_NE) // les diverses comparaisons
+ {
+ CBotCompExpr* inst = new CBotCompExpr(); // élément pour opération
+ inst->SetToken(p); // mémorise l'opération
+
+ int type1, type2;
+ type1 = pStack->GetType();
+
+ p = p->Next();
+ if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression A + B à droite
+ {
+ type2 = pStack->GetType();
+ // les résultats sont-ils compatibles
+ if ( type1 == type2 )
+ {
+ inst->m_leftop = left;
+ pStk->SetVar(new CBotVar(NULL, CBotTypBoolean));
+ // le résultat est un boolean
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ delete left;
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ return pStack->Return(left, pStk);
+}
+
+
+// fait l'opération
+
+BOOL CBotCompExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(this);
+// if ( pStk1 == EOX ) return TRUE;
+
+ if ( pStk1->GetState() == 0 && !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ pStk1->SetState(1); // opération terminée
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ CBotStack* pStk2 = pStk1->AddStack();
+
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+
+ int type1 = pStk1->GetType();
+ int type2 = pStk2->GetType();
+
+ CBotVar* result = new CBotVar( NULL, CBotTypBoolean );
+
+ switch (GetTokenType())
+ {
+ case ID_LO:
+ result->Lo(pStk1->GetVar(), pStk2->GetVar()); // inférieur
+ break;
+ case ID_HI:
+ result->Hi(pStk1->GetVar(), pStk2->GetVar()); // supérieur
+ break;
+ case ID_LS:
+ result->Ls(pStk1->GetVar(), pStk2->GetVar()); // inférieur ou égal
+ break;
+ case ID_HS:
+ result->Hs(pStk1->GetVar(), pStk2->GetVar()); // supérieur ou égal
+ break;
+ case ID_EQ:
+ result->Eq(pStk1->GetVar(), pStk2->GetVar()); // égal
+ break;
+ case ID_NE:
+ result->Ne(pStk1->GetVar(), pStk2->GetVar()); // différent
+ break;
+ }
+ pStk2->SetVar(result); // met le résultat sur la pile
+
+ pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
diff --git a/src/CBot/CBotDll.h b/src/CBot/CBotDll.h
new file mode 100644
index 0000000..4e0c5b1
--- /dev/null
+++ b/src/CBot/CBotDll.h
@@ -0,0 +1,1185 @@
+////////////////////////////////////////////////////////////////////////
+// Librairie pour l'interprétation du language CBOT
+// pour le jeu COLOBOT
+//
+
+//#include "stdafx.h"
+
+#include <windows.h>
+#include <stdio.h>
+
+#define DllExport __declspec( dllexport )
+
+#define CBOTVERSION 104
+
+////////////////////////////////////////////////////////////////////////
+// quelques classes définies par ailleurs
+
+class CBotToken; // programme transformé en "jetons"
+class CBotStack; // pile pour l'exécution
+class CBotClass; // classe d'object
+class CBotInstr; // instruction à exécuter
+class CBotFunction; // les fonctions user
+class CBotVar; // les variables
+class CBotVarClass; // une instance de classe
+class CBotVarPointer; // pointeur à une instance de classe
+class CBotCall; // les fonctions
+class CBotCallMethode; // les méthodes
+class CBotDefParam; // liste de paramètres
+
+
+////////////////////////////////////////////////////////////////////////
+// Gestion des variables
+////////////////////////////////////////////////////////////////////////
+
+// ces types sont calqués sur les types Java
+// ne pas changer l'ordre de ces types
+
+enum CBotType
+{
+ CBotTypVoid = 0, // fonction retournant void
+ CBotTypByte = 1, //n // nombre entier ( 8 bits)
+ CBotTypShort = 2, //n // nombre entier (16 bits)
+ CBotTypChar = 3, //n // caractère "unicode" (16 bits)
+ CBotTypInt = 4, // nombre entier (32 bits)
+ CBotTypLong = 5, //n // nombre entier (64 bits)
+ CBotTypFloat = 6, // nombre décimal (32 bits)
+ CBotTypDouble = 7, //n // nombre décimal (64 bits)
+ CBotTypBoolean = 8, // true ou false exclusivement
+ CBotTypString = 9, // chaine de caractère
+
+ CBotTypArrayPointer = 10, // un tableau de variables
+ CBotTypArrayBody = 11, // idem mais crée l'instance
+
+ CBotTypPointer = 12, // pointeur à une instance
+ CBotTypNullPointer = 13, // pointeur null est spécial
+
+ CBotTypClass = 15, // instance d'une classe
+ CBotTypIntrinsic = 16 // instance d'une classe intrinsèque
+};
+ //n = non encore implémenté
+
+// pour SetUserPtr lors de la suppression d'un objet
+#define OBJECTDELETED ((void*)-1)
+// valeur mise avant initialisation
+#define OBJECTCREATED ((void*)-2)
+
+
+// classe permettant de définir le type complet d'un résultat
+class CBotTypResult
+{
+private:
+ int m_type;
+ CBotTypResult* m_pNext; // pour les types de types
+ CBotClass* m_pClass; // pour les dérivés de classe
+ int m_limite; // limitation des tableaux
+ friend class CBotVarClass;
+ friend class CBotVarPointer;
+
+public:
+ // divers constructeurs selon les besoins
+ DllExport
+ CBotTypResult(int type);
+ // pour les types simples (CBotTypInt à CBotTypString)
+ DllExport
+ CBotTypResult(int type, const char* name);
+ // pour les types pointeur et classe intrinsic
+ DllExport
+ CBotTypResult(int type, CBotClass* pClass);
+ // idem à partir de l'instance d'une classe
+ DllExport
+ CBotTypResult(int type, CBotTypResult elem);
+ // pour les tableaux de variables
+
+ DllExport
+ CBotTypResult(CBotTypResult& typ);
+ // pour les assignations
+ DllExport
+ CBotTypResult();
+ // pour par défaut
+ DllExport
+ ~CBotTypResult();
+
+ DllExport
+ int GivType(int mode = 0);
+ // rend le type CBotTyp* du résultat
+
+ void SetType(int n);
+ // modifie le type
+
+ DllExport
+ CBotClass* GivClass();
+ // rend le pointeur à la classe (pour les CBotTypClass, CBotTypPointer)
+
+ DllExport
+ int GivLimite();
+ // rend la taille limite du tableau (CBotTypArray)
+
+ DllExport
+ void SetLimite(int n);
+ // fixe une limite au tableau
+
+ void SetArray(int* max );
+ // idem avec une liste de dimension (tableaux de tableaux)
+
+ DllExport
+ CBotTypResult& GivTypElem();
+ // rend le type des éléments du tableau (CBotTypArray)
+
+ DllExport
+ BOOL Compare(CBotTypResult& typ);
+ // compare si les types sont compatibles
+ DllExport
+ BOOL Eq(int type);
+ // compare le type
+
+ DllExport
+ CBotTypResult&
+ operator=(const CBotTypResult& src);
+ // copie un type complet dans un autre
+};
+
+/*
+// pour définir un résultat en sortie, utiliser par exemple
+
+ // pour rendre un simple Float
+ return CBotTypResult( CBotTypFloat );
+
+
+ // pour rendre un tableau de string
+ return CBotTypResult( CBotTypArray, CBotTypResult( CBotTypString ) );
+
+ // pour rendre un tableau de tableau de "point"
+ CBotTypResult typPoint( CBotTypIntrinsic, "point" );
+ CBotTypResult arrPoint( CBotTypArray, typPoint );
+ return CBotTypResult( CBotTypArray, arrPoint );
+*/
+
+
+////////////////////////////////////////////////////////////////////////
+// Gestion des erreurs compilation et exécution
+////////////////////////////////////////////////////////////////////////
+
+// voici la liste des erreurs pouvant être retournées par le module
+// pour la compilation
+
+#define CBotErrOpenPar 5000 // manque la parenthèse ouvrante
+#define CBotErrClosePar 5001 // manque la parenthèse fermante
+#define CBotErrNotBoolean 5002 // l'expression doit être un boolean
+#define CBotErrUndefVar 5003 // variable non déclarée
+#define CBotErrBadLeft 5004 // assignation impossible ( 5 = ... )
+#define CBotErrNoTerminator 5005 // point-virgule attendu
+#define CBotErrCaseOut 5006 // case en dehors d'un switch
+// CBotErrNoTerm 5007, plus utile
+#define CBotErrCloseBlock 5008 // manque " } "
+#define CBotErrElseWhitoutIf 5009 // else sans if correspondant
+#define CBotErrOpenBlock 5010 // manque " { "
+#define CBotErrBadType1 5011 // mauvais type pour l'assignation
+#define CBotErrRedefVar 5012 // redéfinition de la variable
+#define CBotErrBadType2 5013 // 2 opérandes de type incompatibles
+#define CBotErrUndefCall 5014 // routine inconnue
+#define CBotErrNoDoubleDots 5015 // " : " attendu
+// CBotErrWhile 5016, plus utile
+#define CBotErrBreakOutside 5017 // break en dehors d'une boucle
+#define CBotErrUndefLabel 5019 // label inconnu
+#define CBotErrLabel 5018 // label ne peut se mettre ici
+#define CBotErrNoCase 5020 // manque " case "
+#define CBotErrBadNum 5021 // nombre attendu
+#define CBotErrVoid 5022 // " void " pas possible ici
+#define CBotErrNoType 5023 // déclaration de type attendue
+#define CBotErrNoVar 5024 // nom de variable attendu
+#define CBotErrNoFunc 5025 // nom de fonction attendu
+#define CBotErrOverParam 5026 // trop de paramètres
+#define CBotErrRedefFunc 5027 // cette fonction existe déjà
+#define CBotErrLowParam 5028 // pas assez de paramètres
+#define CBotErrBadParam 5029 // mauvais types de paramètres
+#define CBotErrNbParam 5030 // mauvais nombre de paramètres
+#define CBotErrUndefItem 5031 // élément n'existe pas dans la classe
+#define CBotErrUndefClass 5032 // variable n'est pas une classe
+#define CBotErrNoConstruct 5033 // pas de constructeur approprié
+#define CBotErrRedefClass 5034 // classe existe déjà
+#define CBotErrCloseIndex 5035 // " ] " attendu
+#define CBotErrReserved 5036 // mot réservé (par un DefineNum)
+#define CBotErrBadNew 5037 // mauvais paramètre pour new
+#define CBotErrOpenIndex 5038 // " [ " attendu
+#define CBotErrBadString 5039 // chaîne de caractère attendue
+#define CBotErrBadIndex 5040 // mauvais type d'index "[ false ]"
+#define CBotErrPrivate 5041 // élément protégé
+#define CBotErrNoPublic 5042 // manque le mot "public"
+
+// voici la liste des erreurs pouvant être retournées par le module
+// pour l'exécution
+
+#define CBotErrZeroDiv 6000 // division par zéro
+#define CBotErrNotInit 6001 // variable non initialisée
+#define CBotErrBadThrow 6002 // throw d'une valeur négative
+#define CBotErrNoRetVal 6003 // fonction n'a pas retourné de résultat
+#define CBotErrNoRun 6004 // Run() sans fonction active
+#define CBotErrUndefFunc 6005 // appel d'une fonction qui n'existe plus
+#define CBotErrNotClass 6006 // cette classe n'existe pas
+#define CBotErrNull 6007 // pointeur null
+#define CBotErrNan 6008 // calcul avec un NAN
+#define CBotErrOutArray 6009 // index hors du tableau
+#define CBotErrStackOver 6010 // dépassement de la pile
+#define CBotErrDeletedPtr 6011 // pointeur à un objet détruit
+
+#define CBotErrFileOpen 6012 // ouverture du fichier impossible
+#define CBotErrNotOpen 6013 // canal pas ouvert
+#define CBotErrRead 6014 // erreur à la lecture
+#define CBotErrWrite 6015 // erreur à l'écriture
+
+// d'autres valeurs peuvent être rendues
+// par exemple les exceptions rendues par les routines externes
+// et les " throw " avec un nombre quelconque.
+
+
+////////////////////////////////////////////////////////////////////////
+// définie une classe pour l'utilisation des strings
+// car CString fait partie de MFC pas utilisé ici.
+//
+// ( toutes les fonctions ne sont pas encore implémentées )
+
+class CBotString
+{
+private:
+ char* m_ptr; // pointeur à la chaine
+ int m_lg; // longueur de la chaine
+ static
+ HINSTANCE m_hInstance;
+
+public:
+ DllExport
+ CBotString();
+ DllExport
+ CBotString(const char* p);
+ DllExport
+ CBotString(const CBotString& p);
+ DllExport
+ ~CBotString();
+
+ DllExport
+ void Empty();
+ DllExport
+ BOOL IsEmpty();
+ DllExport
+ int GivLength();
+ DllExport
+ int Find(const char c);
+ DllExport
+ int Find(LPCTSTR lpsz);
+ DllExport
+ int ReverseFind(const char c);
+ DllExport
+ int ReverseFind(LPCTSTR lpsz);
+ DllExport
+ BOOL LoadString(UINT id);
+ DllExport
+ CBotString Mid(int nFirst, int nCount) const;
+ DllExport
+ CBotString Mid(int nFirst) const;
+ DllExport
+ CBotString Left(int nCount) const;
+ DllExport
+ CBotString Right(int nCount) const;
+
+ DllExport
+ const CBotString&
+ operator=(const CBotString& stringSrc);
+ DllExport
+ const CBotString&
+ operator=(const char ch);
+ DllExport
+ const CBotString&
+ operator=(const char* pString);
+ DllExport
+ const CBotString&
+ operator+(const CBotString& str);
+ DllExport
+ friend CBotString
+ operator+(const CBotString& string, LPCTSTR lpsz);
+
+ DllExport
+ const CBotString&
+ operator+=(const char ch);
+ DllExport
+ const CBotString&
+ operator+=(const CBotString& str);
+ DllExport
+ BOOL operator==(const CBotString& str);
+ DllExport
+ BOOL operator==(const char* p);
+ DllExport
+ BOOL operator!=(const CBotString& str);
+ DllExport
+ BOOL operator!=(const char* p);
+ DllExport
+ BOOL operator>(const CBotString& str);
+ DllExport
+ BOOL operator>(const char* p);
+ DllExport
+ BOOL operator>=(const CBotString& str);
+ DllExport
+ BOOL operator>=(const char* p);
+ DllExport
+ BOOL operator<(const CBotString& str);
+ DllExport
+ BOOL operator<(const char* p);
+ DllExport
+ BOOL operator<=(const CBotString& str);
+ DllExport
+ BOOL operator<=(const char* p);
+
+ DllExport
+ operator LPCTSTR() const; // as a C string
+
+ int Compare(LPCTSTR lpsz) const;
+
+ DllExport
+ CBotString Mid(int start, int lg=-1);
+
+ DllExport
+ void MakeUpper();
+ DllExport
+ void MakeLower();
+};
+
+
+// idem avec la gestion en tableau
+
+class CBotStringArray : public CBotString
+{
+private:
+ int m_nSize; // nombre d'éléments
+ int m_nMaxSize; // taille réservée
+ CBotString* m_pData; // ^aux données
+
+public:
+ DllExport
+ CBotStringArray();
+ DllExport
+ ~CBotStringArray();
+ DllExport
+ void SetSize(int nb);
+ DllExport
+ int GivSize();
+ DllExport
+ void Add(const CBotString& str);
+ DllExport
+ CBotString& operator[](int nIndex);
+
+ DllExport
+ CBotString& ElementAt(int nIndex);
+};
+
+// différents mode pour GetPosition
+enum CBotGet
+{
+ GetPosExtern = 1,
+ GetPosNom = 2,
+ GetPosParam = 3,
+ GetPosBloc = 4
+};
+
+////////////////////////////////////////////////////////////////////
+// classe principale gérant un programme CBot
+//
+
+class CBotProgram
+{
+private:
+ CBotFunction* m_Prog; // les fonctions définies par l'utilisateur
+ CBotFunction* m_pRun; // la fonction de base pour l'exécution
+ CBotClass* m_pClass; // les classes définies dans cette partie
+ CBotStack* m_pStack; // la pile d'exécution
+ CBotVar* m_pInstance; // instance de la classe parent
+ friend class CBotFunction;
+
+ int m_ErrorCode;
+ int m_ErrorStart;
+ int m_ErrorEnd;
+
+ long m_Ident; // identificateur associé
+
+public:
+ static
+ CBotString m_DebugVarStr; // a fin de debug
+ BOOL m_bDebugDD; // idem déclanchable par robot
+
+ BOOL m_bCompileClass;
+
+public:
+ DllExport
+ static
+ void Init();
+ // initialise le module (défini les mots clefs pour les erreurs)
+ // doit être fait une fois (et une seule) au tout début
+ DllExport
+ static
+ void Free();
+ // libère les zones mémoires statiques
+
+ DllExport
+ static
+ int GivVersion();
+ // donne la version de la librairie CBOT
+
+
+ DllExport
+ CBotProgram();
+ DllExport
+ CBotProgram(CBotVar* pInstance);
+ DllExport
+ ~CBotProgram();
+
+ DllExport
+ BOOL Compile( const char* program, CBotStringArray& ListFonctions, void* pUser = NULL);
+ // compile le programme donné en texte
+ // retourne FALSE s'il y a une erreur à la compilation
+ // voir GetCompileError() pour récupérer l'erreur
+ // ListFonctions retourne le nom des fonctions déclarées extern
+ // pUser permet de passer un pointeur pour les routines définies par AddFunction
+
+ DllExport
+ void SetIdent(long n);
+ // associe un identificateur avec l'instance CBotProgram
+
+ DllExport
+ long GivIdent();
+ // redonne l'identificateur
+
+ DllExport
+ int GivError();
+ DllExport
+ BOOL GetError(int& code, int& start, int& end);
+ DllExport
+ BOOL GetError(int& code, int& start, int& end, CBotProgram* &pProg);
+ // si TRUE
+ // donne l'erreur trouvée à la compilation
+ // ou à l'exécution
+ // start et end délimite le bloc où se trouve l'erreur
+ // pProg permet de savoir dans quel "module" s'est produite l'erreur d'exécution
+ DllExport
+ static
+ CBotString GivErrorText(int code);
+
+
+ DllExport
+ BOOL Start(const char* name);
+ // définie quelle fonction doit être exécutée
+ // retourne FALSE si la fontion name n'est pas trouvée
+ // le programme ne fait rien, il faut appeller Run() pour cela
+
+ DllExport
+ BOOL Run(void* pUser = NULL, int timer = -1);
+ // exécute le programme
+ // retourne FALSE si le programme a été suspendu
+ // retourne TRUE si le programme s'est terminé avec ou sans erreur
+ // timer = 0 permet de faire une avance pas à pas
+
+ DllExport
+ BOOL GetRunPos(const char* &FunctionName, int &start, int &end);
+ // donne la position dans le programme en exécution
+ // retourne FALSE si on n'est pas en exécution (programme terminé)
+ // FunctionName est un pointeur rendu sur le nom de la fonction
+ // start et end la position dans le texte du token en traitement
+
+ DllExport
+ CBotVar* GivStackVars(const char* &FunctionName, int level);
+ // permet d'obtenir le pointeur aux variables sur la pile d'exécution
+ // level est un paramètre d'entrée, 0 pour le dernier niveau, -1, -2, etc pour les autres niveau
+ // la valeur retournée (CBotVar*) est une liste de variable (ou NULL)
+ // qui peut être traité que la liste des paramètres reçu par une routine
+ // FunctionName donne le nom de la fonction où se trouvent ces variables
+ // FunctionName == NULL signifiant qu'on est plus dans le programme (selon level)
+
+ DllExport
+ void Stop();
+ // arrête l'exécution du programme
+ // quitte donc le mode "suspendu"
+
+ DllExport
+ static
+ void SetTimer(int n);
+ // défini le nombre de pas (parties d'instructions) à faire
+ // dans Run() avant de rendre la main "FALSE"
+
+ DllExport
+ static
+ BOOL AddFunction(const char* name,
+ BOOL rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+ CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
+ // cet appel permet d'ajouter de manière externe (**)
+ // une nouvelle fonction utilisable par le programme CBot
+
+ DllExport
+ static
+ BOOL DefineNum(const char* name, long val);
+
+ DllExport
+ BOOL SaveState(FILE* pf);
+ // sauvegarde l'état d'exécution dans le fichier
+ // le fichier doit avoir été ouvert avec l'appel fopen de cette dll
+ // sinon le système plante
+ DllExport
+ BOOL RestoreState(FILE* pf);
+ // rétablie l'état de l'exécution depuis le fichier
+ // le programme compilé doit évidemment être identique
+
+ DllExport
+ BOOL GetPosition(const char* name, int& start, int& stop,
+ CBotGet modestart = GetPosExtern,
+ CBotGet modestop = GetPosBloc);
+ // donne la position d'une routine dans le texte d'origine
+ // le mode permet de choisir l'élément à trouver pour le début et la fin
+ // voir les modes ci-dessus dans CBotGet
+
+
+ CBotFunction* GivFunctions();
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// routines pour la gestion d'un fichier (FILE*)
+ DllExport
+ FILE* fOpen(const char* name, const char* mode);
+ DllExport
+ int fClose(FILE* filehandle);
+ DllExport
+ size_t fWrite(const void *buffer, size_t elemsize, size_t length, FILE* filehandle);
+ DllExport
+ size_t fRead(void *buffer, size_t elemsize, size_t length, FILE* filehandle);
+
+
+#if 0
+/*
+(**) Note:
+ Pour définir une fonction externe, il faut procéder ainsi:
+
+ a) définir une routine pour la compilation
+ cette routine reçois la liste des paramètres (sans valeurs)
+ et retourne soit un type de résultat (CBotTyp... ou 0 = void)
+ soit un numéro d'erreur
+ b) définir une routine pour l'exécution
+ cette rourine reCoit la liste des paramètres (avec valeurs),
+ une variable pour stocker le résultat (selon le type donné à la compilation)
+
+ Par exemple, une routine qui calcule la moyenne d'une liste de paramètres */
+
+int cMoyenne(CBotVar* &pVar, CBotString& ClassName)
+{
+ if ( pVar == NULL ) return 6001; // il n'y a aucun paramètre !
+
+ while ( pVar != NULL )
+ {
+ if ( pVar->GivType() > CBotTypDouble ) return 6002; // ce n'est pas un nombre
+ pVar = pVar -> GivNext();
+ }
+
+ return CBotTypFloat; // le type du résultat pourrait dépendre des paramètres !
+}
+
+
+BOOL rMoyenne(CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ float total = 0;
+ int nb = 0;
+ while (pVar != NULL)
+ {
+ total += pVar->GivValFloat();
+ pVar = pVar->GivNext();
+ nb++;
+ }
+ pResult->SetValFloat(total/nb); // retourne la valeur moyenne
+
+ return TRUE; // opération totalement terminée
+}
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////
+// Classe pour la gestion des variables
+
+// les méthodes marquées DllExport
+// peuvent être utile à l'exterieur du module
+// ( il n'est pour l'instant pas prévu de pouvoir créer ces objets en externe )
+
+// résultats pour GivInit()
+#define IS_UNDEF 0 // variable indéfinie
+#define IS_DEF 1 // variable définie
+#define IS_NAN 999 // variable définie comme étant not a number
+
+// type de variable SetPrivate / IsPrivate
+#define PR_PUBLIC 0 // variable publique
+#define PR_READ 1 // read only
+#define PR_PROTECT 2 // protected (héritage)
+#define PR_PRIVATE 3 // strictement privée
+
+class CBotVar
+{
+protected:
+ CBotToken* m_token; // le token correspondant
+
+ CBotVar* m_next; // liste de variables
+ friend class CBotStack;
+ friend class CBotCStack;
+ friend class CBotInstrCall;
+ friend class CBotProgram;
+
+ CBotTypResult m_type; // type de valeur
+
+ int m_binit; // pas initialisée ?
+ CBotVarClass* m_pMyThis; // ^élément this correspondant
+ void* m_pUserPtr; // ^données user s'il y a lieu
+ BOOL m_bStatic; // élément static (dans une classe)
+ int m_mPrivate; // élément public, protected ou private ?
+
+ CBotInstr* m_InitExpr; // expression pour le contenu initial
+ CBotInstr* m_LimExpr; // liste des limites pour un tableau
+ friend class CBotClass;
+ friend class CBotVarClass;
+ friend class CBotVarPointer;
+ friend class CBotVarArray;
+
+ long m_ident; // identificateur unique
+ static long m_identcpt; // compteur
+
+public:
+ CBotVar();
+virtual ~CBotVar( ); // destructeur
+
+
+/* DllExport
+ static
+ CBotVar* Create( const char* name, int type, const char* ClassName = NULL);
+ // crée une variable selon son type,*/
+
+ DllExport
+ static
+ CBotVar* Create( const char* name, CBotTypResult type);
+ // idem à partir du type complet
+
+ DllExport
+ static
+ CBotVar* Create( const char* name, CBotClass* pClass);
+ // idem pour une instance d'une classe connue
+
+ static
+ CBotVar* Create( const CBotToken* name, int type );
+ static
+ CBotVar* Create( const CBotToken* name, CBotTypResult type );
+
+ static
+ CBotVar* Create( const char* name, int type, CBotClass* pClass);
+
+ static
+ CBotVar* Create( CBotVar* pVar );
+
+
+ DllExport
+ void SetUserPtr(void* pUser);
+ // associe un pointeur utilisateur à une instance
+
+ DllExport
+ virtual void SetIdent(long UniqId);
+ // associe un identificateur unique à une instance
+ // ( c'est à l'utilisateur de s'assurer que l'id est unique)
+
+ DllExport
+ void* GivUserPtr();
+ // rend le pointeur associé à la variable
+
+ DllExport
+ CBotString GivName(); // le nom de la variable, s'il est connu
+ ////////////////////////////////////////////////////////////////////////////////////
+ void SetName(const char* name); // change le nom de la variable
+
+ DllExport
+ int GivType(int mode = 0); // rend le type de base (int) de la variable
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ DllExport
+ CBotTypResult GivTypResult(int mode = 0); // rend le type complet de la variable
+
+
+ CBotToken* GivToken();
+ void SetType(CBotTypResult& type);
+
+ DllExport
+ void SetInit(int bInit); // met la variable dans l'état IS_UNDEF, IS_DEF, IS_NAN
+
+ DllExport
+ int GivInit(); // donne l'état de la variable
+
+ DllExport
+ void SetStatic(BOOL bStatic);
+ DllExport
+ BOOL IsStatic();
+
+ DllExport
+ void SetPrivate(int mPrivate);
+ DllExport
+ BOOL IsPrivate(int mode = PR_PROTECT);
+ DllExport
+ int GivPrivate();
+
+ virtual
+ void ConstructorSet();
+
+ void SetVal(CBotVar* var); // remprend une valeur
+
+ DllExport
+ virtual
+ CBotVar* GivItem(const char* name); // rend un élément d'une classe selon son nom (*)
+ virtual
+ CBotVar* GivItemRef(int nIdent); // idem à partir du n° ref
+
+ DllExport
+ virtual
+ CBotVar* GivItem(int row, BOOL bGrow = FALSE);
+
+ DllExport
+ virtual
+ CBotVar* GivItemList(); // donne la liste des éléments
+
+ DllExport
+ CBotVar* GivStaticVar(); // rend le pointeur à la variable si elle est statique
+
+ DllExport
+ BOOL IsElemOfClass(const char* name);
+ // dit si l'élément appartient à la classe "name"
+ // rend TRUE si l'objet est d'une classe fille
+
+ DllExport
+ CBotVar* GivNext(); // prochaine variable dans la liste (paramètres)
+ ////////////////////////////////////////////////////////////////////////////////////////////
+
+ void AddNext(CBotVar* pVar); // ajoute dans une liste
+
+ virtual
+ void Copy(CBotVar* pSrc, BOOL bName = TRUE); // fait une copie de la variable
+
+ DllExport
+ virtual void SetValInt(int val, const char* name = NULL);
+ // initialise avec une valeur entière (#)
+ /////////////////////////////////////////////////////////////////////////////////
+
+ DllExport
+ virtual void SetValFloat(float val); // initialise avec une valeur réelle (#)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ DllExport
+ virtual void SetValString(const char* p);// initialise avec une valeur chaîne (#)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ DllExport
+ virtual int GivValInt(); // demande la valeur entière (#)
+ ////////////////////////////////////////////////////////////////////////
+
+ DllExport
+ virtual float GivValFloat(); // demande la valeur réelle (#)
+ ///////////////////////////////////////////////////////////////////////
+
+ virtual
+ CBotString GivValString(); // demande la valeur chaîne (#)
+ ///////////////////////////////////////////////////////////////////////
+
+ virtual void SetClass(CBotClass* pClass);
+ virtual
+ CBotClass* GivClass();
+
+ virtual void SetPointer(CBotVar* p);
+ virtual
+ CBotVarClass* GivPointer();
+// virtual void SetIndirection(CBotVar* pVar);
+
+ virtual void Add(CBotVar* left, CBotVar* right); // addition
+ virtual void Sub(CBotVar* left, CBotVar* right); // soustraction
+ virtual void Mul(CBotVar* left, CBotVar* right); // multiplication
+ virtual int Div(CBotVar* left, CBotVar* right); // division
+ virtual int Modulo(CBotVar* left, CBotVar* right); // reste de division
+ virtual void Power(CBotVar* left, CBotVar* right); // puissance
+
+ virtual BOOL Lo(CBotVar* left, CBotVar* right);
+ virtual BOOL Hi(CBotVar* left, CBotVar* right);
+ virtual BOOL Ls(CBotVar* left, CBotVar* right);
+ virtual BOOL Hs(CBotVar* left, CBotVar* right);
+ virtual BOOL Eq(CBotVar* left, CBotVar* right);
+ virtual BOOL Ne(CBotVar* left, CBotVar* right);
+
+ virtual void And(CBotVar* left, CBotVar* right);
+ virtual void Or(CBotVar* left, CBotVar* right);
+ virtual void XOr(CBotVar* left, CBotVar* right);
+ virtual void ASR(CBotVar* left, CBotVar* right);
+ virtual void SR(CBotVar* left, CBotVar* right);
+ virtual void SL(CBotVar* left, CBotVar* right);
+
+ virtual void Neg();
+ virtual void Not();
+ virtual void Inc();
+ virtual void Dec();
+
+
+ virtual BOOL Save0State(FILE* pf);
+ virtual BOOL Save1State(FILE* pf);
+ static BOOL RestoreState(FILE* pf, CBotVar* &pVar);
+
+ DllExport
+ void debug();
+
+// virtual
+// CBotVar* GivMyThis();
+
+ DllExport
+ virtual
+ void Maj(void* pUser = NULL, BOOL bContinue = TRUE);
+
+ void SetUniqNum(long n);
+ long GivUniqNum();
+ static long NextUniqNum();
+};
+
+/* NOTE (#)
+ les méthodes SetValInt() SetValFloat() et SetValString()
+ ne peuvent êtes appellées qu'avec des objets respectivement entier, réelle ou chaîne
+ toujours s'assurer du type de la variable avant d'appeller ces méthodes
+
+ if ( pVar->GivType() == CBotInt() ) pVar->SetValFloat( 3.3 ); // plante !!
+
+ les méthodes GivValInt(), GivValFloat() et GivValString()
+ font des conversions de valeur,
+ GivValString() fonctionne sur des nombres (rend la chaîne correspondante)
+ par contre il ne faut pas faire de GivValInt() avec une variable de type chaîne !
+*/
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Gestion des classes
+////////////////////////////////////////////////////////////////////////
+
+// classe pour définir de nouvelle classes dans le language CBOT
+// par exemple pour définir la classe CPoint (x,y)
+
+class CBotClass
+{
+private:
+ static
+ CBotClass* m_ExClass; // liste des classes existante à un moment donné
+ CBotClass* m_ExNext; // pour cette liste générale
+ CBotClass* m_ExPrev; // pour cette liste générale
+
+private:
+ CBotClass* m_pParent; // classe parent
+ CBotString m_name; // nom de cette classe-ci
+ int m_nbVar; // nombre de variables dans la chaîne
+ CBotVar* m_pVar; // contenu de la classe
+ BOOL m_bIntrinsic; // classe intrinsèque
+ CBotClass* m_next; // chaine les classe
+ CBotCallMethode* m_pCalls; // liste des méthodes définie en externe
+ CBotFunction* m_pMethod; // liste des méthodes compilées
+ void (*m_rMaj) ( CBotVar* pThis, void* pUser );
+ friend class CBotVarClass;
+ int m_cptLock; // pour Lock / UnLock
+ int m_cptOne; // pour réentrance Lock
+ CBotProgram* m_ProgInLock[5];// processus en attente pour synchro
+
+public:
+ BOOL m_IsDef; // marque si est définie ou pas encore
+
+ DllExport
+ CBotClass( const char* name,
+ CBotClass* pParent, BOOL bIntrinsic = FALSE ); // constructeur
+ // Dès qu'une classe est créée, elle est connue
+ // partout dans CBot
+ // le mode intrinsic donne une classe qui n'est pas gérée par des pointeurs
+
+ DllExport
+ ~CBotClass( ); // destructeur
+
+ DllExport
+ BOOL AddFunction(const char* name,
+ BOOL rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+ CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar));
+ // cet appel permet d'ajouter de manière externe (**)
+ // une nouvelle méthode utilisable par les objets de cette classe
+
+ DllExport
+ BOOL AddUpdateFunc( void rMaj ( CBotVar* pThis, void* pUser ) );
+ // défini la routine qui sera appellée pour mettre à jour les élements de la classe
+
+ DllExport
+ BOOL AddItem(CBotString name, CBotTypResult type, int mPrivate = PR_PUBLIC);
+ // ajoute un élément à la classe
+// DllExport
+// BOOL AddItem(CBotString name, CBotClass* pClass);
+ // idem pour des éléments appartenant à pClass
+ DllExport
+ BOOL AddItem(CBotVar* pVar);
+ // idem en passant le pointeur à une instance d'une variable
+ // l'objet est pris tel quel, il ne faut donc pas le détruire
+
+
+
+ // idem en donnant un élément de type CBotVar
+ void AddNext(CBotClass* pClass);
+
+ DllExport
+ CBotString GivName(); // rend le nom de la classe
+ DllExport
+ CBotClass* GivParent(); // donne la classe père (ou NULL)
+
+ // dit si une classe est dérivée (Extends) d'une autre
+ // rend TRUE aussi si les classes sont identiques
+ DllExport
+ BOOL IsChildOf(CBotClass* pClass);
+
+ static
+ CBotClass* Find(CBotToken* &pToken); // trouve une classe d'après son nom
+
+ DllExport
+ static
+ CBotClass* Find(const char* name);
+
+ CBotVar* GivVar(); // rend la liste des variables
+ CBotVar* GivItem(const char* name); // l'une des variables selon son nom
+ CBotVar* GivItemRef(int nIdent);
+
+ CBotTypResult CompileMethode(const char* name, CBotVar* pThis, CBotVar** ppParams,
+ CBotCStack* pStack, long& nIdent);
+
+ BOOL ExecuteMethode(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppParams, CBotVar* &pResult, CBotStack* &pStack, CBotToken* pToken);
+ void RestoreMethode(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppParams, CBotStack* &pStack);
+
+ // compile une classe déclarée par l'utilisateur
+ static
+ CBotClass* Compile(CBotToken* &p, CBotCStack* pStack);
+ static
+ CBotClass* Compile1(CBotToken* &p, CBotCStack* pStack);
+
+ BOOL CompileDefItem(CBotToken* &p, CBotCStack* pStack, BOOL bSecond);
+
+ BOOL IsIntrinsic();
+ void Purge();
+ static
+ void Free();
+
+ DllExport
+ static
+ BOOL SaveStaticState(FILE* pf);
+
+ DllExport
+ static
+ BOOL RestoreStaticState(FILE* pf);
+
+ BOOL Lock(CBotProgram* p);
+ void Unlock();
+ static
+ void FreeLock(CBotProgram* p);
+
+ BOOL CheckCall(CBotToken* &pToken, CBotDefParam* pParam);
+
+};
+
+#define MAXDEFNUM 1000 // nombre limite des DefineNum
+
+/////////////////////////////////////////////////////////////////////////////////////
+// gestion des jetons (tokens)
+
+#define TokenTypKeyWord 1 // un mot clef du language (voir TokenKeyWord)
+#define TokenTypNum 2 // un nombre
+#define TokenTypString 3 // une chaine
+#define TokenTypVar 4 // un nom de variable
+#define TokenTypDef 5 // une valeur selon DefineNum
+
+#define TokenKeyWord 2000 // les mots clefs du langage
+#define TokenKeyDeclare 2100 // mots clefs pour déclarations (int, float,..)
+#define TokenKeyVal 2200 // les mots représentant une "valeur" (true, false, null, nan)
+#define TokenKeyOp 2300 // les opérateurs
+
+
+class CBotToken
+{
+private:
+ static
+ CBotStringArray m_ListKeyWords; // liste des mots clefs du language
+ static
+ int m_ListIdKeyWords[200]; // les codes correspondants
+
+ static
+ CBotStringArray m_ListKeyDefine; // les noms définis par un DefineNum
+ static
+ long m_ListKeyNums[MAXDEFNUM]; // les valeurs associées
+
+private:
+ CBotToken* m_next; // suivant dans la liste
+ CBotToken* m_prev;
+ int m_type; // type de Token
+ long m_IdKeyWord; // numéro du mot clef si c'en est un
+ // ou valeur du "define"
+
+ CBotString m_Text; // mot trouvé comme token
+ CBotString m_Sep; // séparateurs qui suivent
+
+ int m_start; // position dans le texte d'origine (programme)
+ int m_end; // itou pour la fin du token
+
+ static
+ int GivKeyWords(const char* w); // est-ce un mot clef ?
+ static
+ BOOL GivKeyDefNum(const char* w, CBotToken* &token);
+
+ static
+ void LoadKeyWords(); // fait la liste des mots clefs
+
+public:
+ CBotToken();
+ CBotToken(const CBotToken* pSrc);
+ CBotToken(CBotString& mot, CBotString& sep, int start=0, int end=0);
+ CBotToken(const char* mot, const char* sep = NULL);
+ // constructeur
+ ~CBotToken(); // destructeur
+
+ DllExport
+ int GivType(); // rend le type du token
+
+ DllExport
+ CBotString& GivString(); // rend la chaine correspondant à ce token
+
+ DllExport
+ CBotString& GivSep(); // rend le séparateur suivant le token
+
+ DllExport
+ int GivStart(); // position du début dans le texte
+ DllExport
+ int GivEnd(); // position de fin dans le texte
+
+ DllExport
+ CBotToken* GivNext(); // rend le suivant dans la liste
+ DllExport
+ CBotToken* GivPrev(); // rend le Précédent dans la liste
+
+ DllExport
+ static
+ CBotToken* CompileTokens(const char* p, int& error);
+ // transforme tout le programme
+ DllExport
+ static
+ void Delete(CBotToken* pToken); // libère la liste
+
+
+ // fonctions non utiles en export
+ static
+ BOOL DefineNum(const char* name, long val);
+ void SetString(const char* name);
+
+ void SetPos(int start, int end);
+ long GivIdKey();
+ void AddNext(CBotToken* p); // ajoute un token (une copie)
+
+ static
+ CBotToken* NextToken(char* &program, int& error, BOOL first = FALSE);
+ // trouve le prochain token
+ const CBotToken&
+ operator=(const CBotToken& src);
+
+ static
+ void Free();
+};
+
+
+
+#if 0
+////////////////////////////////////////////////////////////////////////
+// Exemples d'utilisation
+// Définition de classes et de fonctions
+
+
+// définie la classe globale CPoint
+// --------------------------------
+ m_pClassPoint = new CBotClass("CPoint", NULL);
+ // ajoute le composant ".x"
+ m_pClassPoint->AddItem("x", CBotTypResult(CBotTypFloat));
+ // ajoute le composant ".y"
+ m_pClassPoint->AddItem("y", CBotTypResult(CBotTypFloat));
+ // le joueur peut alors utiliser les instructions
+ // CPoint position; position.x = 12; position.y = -13.6
+
+// définie la classe CColobotObject
+// --------------------------------
+// cette classe gère tous les objets dans le monde de COLOBOT
+// le programme utilisateur "main" appartient à cette classe
+ m_pClassObject = new CBotClass("CColobotObject", m_pClassBase);
+ // ajoute le composant ".position"
+ m_pClassObject->AddItem("position", m_pClassPoint);
+ // ajoute le composant ".type"
+ m_pClassObject->AddItem("type", CBotTypResult(CBotTypShort));
+ // ajoute une définition de constante
+ m_pClassObject->AddConst("ROBOT", CBotTypShort, 1); // ROBOT équivalent à la valeur 1
+ // ajoute la routine FIND
+ m_pClassObject->AddFunction( rCompFind, rDoFind );
+ // le joueur peut maintenant utiliser les instructions
+ // CColobotObject chose; chose = FIND( ROBOT )
+
+
+
+// définie la classe CColobotRobot dérivée de CColobotObject
+// ---------------------------------------------------------
+// les programmes "main" associés aux robots font partie de cette classe
+ m_pClassRobot = new CBotClass("CColobotRobot", m_pClassObject);
+ // ajoute la routine GOTO
+ m_pClassRobot->AddFunction( rCompGoto, rDoGoto );
+ // le joueur peut maintenant faire
+ // GOTO( FIND ( ROBOT ) );
+
+
+// crée une instance de la classe Robot
+// ------------------------------------
+// par exemple un nouveau robot qui vient d'être fabriqué
+ CBotVar* m_pMonRobot = new CBotVar("MonRobot", m_pClassRobot);
+
+// compile le programme main pour ce robot-là
+// ------------------------------------------
+ CString LeProgramme( "void main() {GOTO(0, 0); return 0;}" );
+ if ( !m_pMonRobot->Compile( LeProgramme ) ) {gestion d'erreur...};
+
+// construit une pile pour l'interpréteur
+// --------------------------------------
+ CBotStack* pStack = new CBotStack(NULL);
+
+// exécute le programme main
+// -------------------------
+ while( FALSE = m_pMonRobot->Execute( "main", pStack ))
+ {
+ // programme suspendu
+ // on pourrait passer la main à un autre (en sauvegardant pStack pour ce robot-là)
+ };
+ // programme "main" terminé !
+
+
+
+
+// routine implémentant l'instruction GOTO( CPoint pos )
+BOOL rDoGoto( CBotVar* pVar, CBotVar* pResult, int& exception )
+{
+ if (pVar->GivType() != CBotTypeClass ||
+ pVar->IsElemOfClas("CPoint") ) { exception = 6522; return FALSE; )
+ // le paramètre n'est pas de la bonne classe ?
+ // NB en fait ce contrôle est déjà fait par la routine pour la compilation
+
+ m_PosToGo.Copy( pVar ); // garde la position à atteindre (object type CBotVar)
+
+ // ou alors
+ CBotVar* temp;
+ temp = pVar->GivItem("x"); // trouve forcément pour un object de type "CPoint"
+ ASSERT (temp != NULL && temp->GivType() == CBotTypFloat);
+ m_PosToGo.x = temp->GivValFloat();
+
+ temp = pVar->GivItem("y"); // trouve forcément pour un object de type "CPoint"
+ ASSERT (temp != NULL && temp->GivType() == CBotTypFloat);
+ m_PosToGo.y = temp->GivValFloat();
+
+ return (m_CurentPos == m_PosToGo); // rend TRUE si la position est atteinte
+ // rend FALSE s'il faut patienter encore
+}
+
+#endif \ No newline at end of file
diff --git a/src/CBot/CBotFunction.cpp b/src/CBot/CBotFunction.cpp
new file mode 100644
index 0000000..43dbc83
--- /dev/null
+++ b/src/CBot/CBotFunction.cpp
@@ -0,0 +1,1634 @@
+///////////////////////////////////////////////////////////////////////
+// compilation des diverses fonctions déclarées par l'utilisateur
+//
+
+#include "CBot.h"
+
+// les divers constructeurs / destructeurs
+// pour libérer tout selon l'arbre établi
+CBotFunction::CBotFunction()
+{
+ m_Param = NULL; // liste des paramètres vide
+ m_Block = NULL; // le bloc d'instructions
+ m_next = NULL; // les fonctions peuvent être chaînées
+ m_bPublic = FALSE; // fonction non publique
+ m_bExtern = FALSE; // fonction non externe
+ m_nextpublic = NULL;
+ m_prevpublic = NULL;
+ m_pProg = NULL;
+// m_nThisIdent = 0;
+ m_nFuncIdent = 0;
+ m_bSynchro = FALSE;
+}
+
+CBotFunction* CBotFunction::m_listPublic = NULL;
+
+CBotFunction::~CBotFunction()
+{
+ delete m_Param; // liste des paramètres vide
+ delete m_Block; // le bloc d'instructions
+ delete m_next;
+
+ // enlève de la liste publique s'il y a lieu
+ if ( m_bPublic )
+ {
+ if ( m_nextpublic != NULL )
+ {
+ m_nextpublic->m_prevpublic = m_prevpublic;
+ }
+ if ( m_prevpublic != NULL)
+ {
+ m_prevpublic->m_nextpublic = m_nextpublic;
+ }
+ else
+ {
+ // si prev = next = null peut ne pas être dans la liste !
+ if ( m_listPublic == this ) m_listPublic = m_nextpublic;
+ }
+ }
+}
+
+BOOL CBotFunction::IsPublic()
+{
+ return m_bPublic;
+}
+
+BOOL CBotFunction::IsExtern()
+{
+ return m_bExtern;
+}
+
+BOOL CBotFunction::GetPosition(int& start, int& stop, CBotGet modestart, CBotGet modestop)
+{
+ start = m_extern.GivStart();
+ stop = m_closeblk.GivEnd();
+
+ if (modestart == GetPosExtern)
+ {
+ start = m_extern.GivStart();
+ }
+ if (modestop == GetPosExtern)
+ {
+ stop = m_extern.GivEnd();
+ }
+ if (modestart == GetPosNom)
+ {
+ start = m_token.GivStart();
+ }
+ if (modestop == GetPosNom)
+ {
+ stop = m_token.GivEnd();
+ }
+ if (modestart == GetPosParam)
+ {
+ start = m_openpar.GivStart();
+ }
+ if (modestop == GetPosParam)
+ {
+ stop = m_closepar.GivEnd();
+ }
+ if (modestart == GetPosBloc)
+ {
+ start = m_openblk.GivStart();
+ }
+ if (modestop == GetPosBloc)
+ {
+ stop = m_closeblk.GivEnd();
+ }
+
+ return TRUE;
+}
+
+
+CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type)
+{
+ while ( IsOfType( p, ID_OPBRK ) )
+ {
+ if ( !IsOfType( p, ID_CLBRK ) )
+ {
+ pile->SetError(TX_CLBRK, p->GivStart());
+ return CBotTypResult( -1 );
+ }
+ type = CBotTypResult( CBotTypArrayPointer, type );
+ }
+ return type;
+}
+
+CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile)
+{
+ CBotClass* pClass = NULL;
+
+ switch (p->GivType())
+ {
+ case ID_INT:
+ p = p->GivNext();
+ return ArrayType(p, pile, CBotTypResult( CBotTypInt ));
+ case ID_FLOAT:
+ p = p->GivNext();
+ return ArrayType(p, pile, CBotTypResult( CBotTypFloat ));
+ case ID_BOOLEAN:
+ case ID_BOOL:
+ p = p->GivNext();
+ return ArrayType(p, pile, CBotTypResult( CBotTypBoolean ));
+ case ID_STRING:
+ p = p->GivNext();
+ return ArrayType(p, pile, CBotTypResult( CBotTypString ));
+ case ID_VOID:
+ p = p->GivNext();
+ return CBotTypResult( 0 );
+
+ case TokenTypVar:
+ pClass = CBotClass::Find(p);
+ if ( pClass != NULL)
+ {
+ p = p->GivNext();
+ return ArrayType(p, pile,
+ pClass->IsIntrinsic() ?
+ CBotTypResult( CBotTypIntrinsic, pClass ) :
+ CBotTypResult( CBotTypPointer, pClass ) );
+ }
+ }
+ return CBotTypResult( -1 );
+}
+
+// compile une nouvelle fonction
+// bLocal permet de mettre la déclaration des paramètres au même niveau
+// que le éléments appartenant à la classe pour les méthodes
+CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunction* finput, BOOL bLocal)
+{
+ CBotToken* pp;
+ CBotFunction* func = finput;
+ if ( func == NULL ) func = new CBotFunction();
+
+ CBotCStack* pStk = pStack->TokenStack(p, bLocal);
+
+// func->m_nFuncIdent = CBotVar::NextUniqNum();
+
+ while (TRUE)
+ {
+ if ( IsOfType(p, ID_PUBLIC) )
+ {
+ func->m_bPublic = TRUE;
+ continue;
+ }
+ pp = p;
+ if ( IsOfType(p, ID_EXTERN) )
+ {
+ func->m_extern = pp; // pour la position du mot "extern"
+ func->m_bExtern = TRUE;
+// func->m_bPublic = TRUE; // donc aussi publique!
+ continue;
+ }
+ break;
+ }
+
+ func->m_retToken = *p;
+// CBotClass* pClass;
+ func->m_retTyp = TypeParam(p, pStk); // type du résultat
+
+ if (func->m_retTyp.GivType() >= 0)
+ {
+ CBotToken* pp = p;
+ func->m_token = *p;
+
+ if ( IsOfType(p, ID_NOT) )
+ {
+ CBotToken d("~" + p->GivString());
+ func->m_token = d;
+ }
+
+ // un nom de fonction est-il là ?
+ if (IsOfType(p, TokenTypVar))
+ {
+ if ( IsOfType( p, ID_DBLDOTS ) ) // méthode pour une classe
+ {
+ func->m_MasterClass = pp->GivString();
+ CBotClass* pClass = CBotClass::Find(pp);
+ if ( pClass == NULL ) goto bad;
+
+// pp = p;
+ func->m_token = *p;
+ if (!IsOfType(p, TokenTypVar)) goto bad;
+
+ }
+ func->m_openpar = p;
+ func->m_Param = CBotDefParam::Compile( p, pStk );
+ func->m_closepar = p->GivPrev();
+ if (pStk->IsOk())
+ {
+ pStk->SetRetType(func->m_retTyp); // pour savoir de quel type les return
+
+ if (!func->m_MasterClass.IsEmpty())
+ {
+ // rend "this" connu
+ CBotVar* pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, func->m_MasterClass ));
+ pThis->SetInit(2);
+// pThis->SetUniqNum(func->m_nThisIdent = -2); //CBotVar::NextUniqNum() va pas
+ pThis->SetUniqNum(-2);
+ pStk->AddVar(pThis);
+
+ // initialise les variables selon This
+ // n'enregistre que le pointeur à la première,
+ // le reste est chainé
+ CBotVar* pv = pThis->GivItemList();
+// int num = 1;
+ while (pv != NULL)
+ {
+ CBotVar* pcopy = CBotVar::Create(pv);
+// pcopy->SetInit(2);
+ pcopy->Copy(pv);
+ pcopy->SetPrivate(pv->GivPrivate());
+// pcopy->SetUniqNum(pv->GivUniqNum()); //num++);
+ pStk->AddVar(pcopy);
+ pv = pv->GivNext();
+ }
+ }
+
+ // et compile le bloc d'instruction qui suit
+ func->m_openblk = p;
+ func->m_Block = CBotBlock::Compile(p, pStk, FALSE);
+ func->m_closeblk = p->GivPrev();
+ if ( pStk->IsOk() )
+ {
+ if ( func->m_bPublic ) // fonction publique, la rend connue pour tous
+ {
+ CBotFunction::AddPublic(func);
+ }
+ return pStack->ReturnFunc(func, pStk);
+ }
+ }
+ }
+bad:
+ pStk->SetError(TX_NOFONC, p);
+ }
+ pStk->SetError(TX_NOTYP, p);
+ if ( finput == NULL ) delete func;
+ return pStack->ReturnFunc(NULL, pStk);
+}
+
+// pré-compile une nouvelle fonction
+CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass)
+{
+ CBotFunction* func = new CBotFunction();
+ func->m_nFuncIdent = CBotVar::NextUniqNum();
+
+ CBotCStack* pStk = pStack->TokenStack(p, TRUE);
+
+ while (TRUE)
+ {
+ if ( IsOfType(p, ID_PUBLIC) )
+ {
+ // func->m_bPublic = TRUE; // sera fait en passe 2
+ continue;
+ }
+ if ( IsOfType(p, ID_EXTERN) )
+ {
+ func->m_bExtern = TRUE;
+ continue;
+ }
+ break;
+ }
+
+ func->m_retToken = *p;
+ func->m_retTyp = TypeParam(p, pStack); // type du résultat
+
+ if (func->m_retTyp.GivType() >= 0)
+ {
+ CBotToken* pp = p;
+ func->m_token = *p;
+ // un nom de fonction est-il là ?
+ if (IsOfType(p, TokenTypVar))
+ {
+ if ( IsOfType( p, ID_DBLDOTS ) ) // méthode pour une classe
+ {
+ func->m_MasterClass = pp->GivString();
+ CBotClass* pClass = CBotClass::Find(pp);
+ if ( pClass == NULL )
+ {
+ pStk->SetError(TX_NOCLASS, pp);
+ goto bad;
+ }
+
+ pp = p;
+ func->m_token = *p;
+ if (!IsOfType(p, TokenTypVar)) goto bad;
+
+ }
+ func->m_Param = CBotDefParam::Compile( p, pStk );
+ if (pStk->IsOk())
+ {
+ // regarde si la fonction existe ailleurs
+ if (( pClass != NULL || !pStack->CheckCall(pp, func->m_Param)) &&
+ ( pClass == NULL || !pClass->CheckCall(pp, func->m_Param)) )
+ {
+ if (IsOfType(p, ID_OPBLK))
+ {
+ int level = 1;
+ // et saute le bloc d'instructions qui suit
+ do
+ {
+ int type = p->GivType();
+ p = p->GivNext();
+ if (type == ID_OPBLK) level++;
+ if (type == ID_CLBLK) level--;
+ }
+ while (level > 0 && p != NULL);
+
+ return pStack->ReturnFunc(func, pStk);
+ }
+ pStk->SetError(TX_OPENBLK, p);
+ }
+ }
+ pStk->SetError(TX_REDEF, pp);
+ }
+bad:
+ pStk->SetError(TX_NOFONC, p);
+ }
+ pStk->SetError(TX_NOTYP, p);
+ delete func;
+ return pStack->ReturnFunc(NULL, pStk);
+}
+
+#ifdef _DEBUG
+static int xx = 0;
+#endif
+
+BOOL CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
+{
+ CBotStack* pile = pj->AddStack(this, 2); // un bout de pile local à cette fonction
+// if ( pile == EOX ) return TRUE;
+
+ pile->SetBotCall(m_pProg); // bases pour les routines
+
+ if ( pile->GivState() == 0 )
+ {
+ if ( !m_Param->Execute(ppVars, pile) ) return FALSE; // défini les paramètres
+ pile->IncState();
+ }
+
+ if ( pile->GivState() == 1 && !m_MasterClass.IsEmpty() )
+ {
+ // rend "this" connu
+ CBotVar* pThis ;
+ if ( pInstance == NULL )
+ {
+ pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, m_MasterClass ));
+ pThis->SetInit(2);
+ }
+ else
+ {
+ pThis = CBotVar::Create("this", CBotTypResult( CBotTypPointer, m_MasterClass ));
+ pThis->SetPointer(pInstance);
+ pThis->SetInit(2);
+ }
+
+// pThis->SetUniqNum(m_nThisIdent);
+ pThis->SetUniqNum(-2);
+ pile->AddVar(pThis);
+
+ pile->IncState();
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ if ( !m_Block->Execute(pile) )
+ {
+ if ( pile->GivError() < 0 )
+ pile->SetError( 0 );
+ else
+ return FALSE;
+ }
+
+ return pj->Return(pile);
+}
+
+
+void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
+{
+ CBotStack* pile = pj->RestoreStack(this); // un bout de pile local à cette fonction
+ if ( pile == NULL ) return;
+ CBotStack* pile2 = pile;
+
+ pile->SetBotCall(m_pProg); // bases pour les routines
+
+ if ( pile->GivBlock() < 2 )
+ {
+ CBotStack* pile2 = pile->RestoreStack(NULL); // un bout de pile local à cette fonction
+ if ( pile2 == NULL ) return;
+ pile->SetState(pile->GivState() + pile2->GivState());
+ pile2->Delete();
+ }
+
+ m_Param->RestoreState(pile2, TRUE); // les paramètres
+
+ if ( !m_MasterClass.IsEmpty() )
+ {
+ CBotVar* pThis = pile->FindVar("this");
+ pThis->SetInit(2);
+ pThis->SetUniqNum(-2);
+ }
+
+ m_Block->RestoreState(pile2, TRUE);
+}
+
+void CBotFunction::AddNext(CBotFunction* p)
+{
+ CBotFunction* pp = this;
+ while (pp->m_next != NULL) pp = pp->m_next;
+
+ pp->m_next = p;
+}
+
+
+CBotTypResult CBotFunction::CompileCall(const char* name, CBotVar** ppVars, long& nIdent)
+{
+ nIdent = 0;
+ CBotTypResult type;
+
+ CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type);
+ return type;
+}
+
+
+// trouve une fonction selon son identificateur unique
+// si l'identificateur n'est pas trouvé, cherche selon le nom et les paramètres
+
+CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const char* name, CBotVar** ppVars, CBotTypResult& TypeOrError, BOOL bPublic)
+{
+ TypeOrError.SetType(TX_UNDEFCALL); // pas de routine de ce nom
+ CBotFunction* pt;
+
+ if ( nIdent )
+ {
+ if ( this != NULL ) for ( pt = this ; pt != NULL ; pt = pt->m_next )
+ {
+ if ( pt->m_nFuncIdent == nIdent )
+ {
+ TypeOrError = pt->m_retTyp;
+ return pt;
+ }
+ }
+
+ // recherche dans la liste des fonctions publiques
+
+ for ( pt = m_listPublic ; pt != NULL ; pt = pt->m_nextpublic )
+ {
+ if ( pt->m_nFuncIdent == nIdent )
+ {
+ TypeOrError = pt->m_retTyp;
+ return pt;
+ }
+ }
+ }
+
+ if ( name == NULL ) return NULL;
+
+ int delta = 99999; // cherche la signature la plus faible
+ CBotFunction* pFunc = NULL; // la meilleure fonction trouvée
+
+ if ( this != NULL )
+ {
+ for ( pt = this ; pt != NULL ; pt = pt->m_next )
+ {
+ if ( pt->m_token.GivString() == name )
+ {
+ int i = 0;
+ int alpha = 0; // signature des paramètres
+ // les paramètres sont-ils compatibles ?
+ CBotDefParam* pv = pt->m_Param; // liste des paramètres attendus
+ CBotVar* pw = ppVars[i++]; // liste des paramètres fournis
+ while ( pv != NULL && pw != NULL)
+ {
+ if (!TypesCompatibles(pv->GivTypResult(), pw->GivTypResult()))
+ {
+ if ( pFunc == NULL ) TypeOrError = TX_BADPARAM;
+ break;
+ }
+ int d = pv->GivType() - pw->GivType(2);
+ alpha += d>0 ? d : -10*d; // perte de qualité, 10 fois plus cher !!
+
+ pv = pv->GivNext();
+ pw = ppVars[i++];
+ }
+ if ( pw != NULL )
+ {
+ if ( pFunc != NULL ) continue;
+ if ( TypeOrError.Eq(TX_LOWPARAM) ) TypeOrError.SetType(TX_NUMPARAM);
+ if ( TypeOrError.Eq(TX_UNDEFCALL)) TypeOrError.SetType(TX_OVERPARAM);
+ continue; // trop de paramètres
+ }
+ if ( pv != NULL )
+ {
+ if ( pFunc != NULL ) continue;
+ if ( TypeOrError.Eq(TX_OVERPARAM) ) TypeOrError.SetType(TX_NUMPARAM);
+ if ( TypeOrError.Eq(TX_UNDEFCALL) ) TypeOrError.SetType(TX_LOWPARAM);
+ continue; // pas assez de paramètres
+ }
+
+ if (alpha == 0) // signature parfaite
+ {
+ nIdent = pt->m_nFuncIdent;
+ TypeOrError = pt->m_retTyp;
+ return pt;
+ }
+
+ if ( alpha < delta ) // une meilleur signature ?
+ {
+ pFunc = pt;
+ delta = alpha;
+ }
+ }
+ }
+ }
+
+ if ( bPublic )
+ {
+ for ( pt = m_listPublic ; pt != NULL ; pt = pt->m_nextpublic )
+ {
+ if ( pt->m_token.GivString() == name )
+ {
+ int i = 0;
+ int alpha = 0; // signature des paramètres
+ // les paramètres sont-ils compatibles ?
+ CBotDefParam* pv = pt->m_Param; // liste des paramètres attendus
+ CBotVar* pw = ppVars[i++]; // liste des paramètres fournis
+ while ( pv != NULL && pw != NULL)
+ {
+ if (!TypesCompatibles(pv->GivTypResult(), pw->GivTypResult()))
+ {
+ if ( pFunc == NULL ) TypeOrError = TX_BADPARAM;
+ break;
+ }
+ int d = pv->GivType() - pw->GivType(2);
+ alpha += d>0 ? d : -10*d; // perte de qualité, 10 fois plus cher !!
+
+ pv = pv->GivNext();
+ pw = ppVars[i++];
+ }
+ if ( pw != NULL )
+ {
+ if ( pFunc != NULL ) continue;
+ if ( TypeOrError.Eq(TX_LOWPARAM) ) TypeOrError.SetType(TX_NUMPARAM);
+ if ( TypeOrError.Eq(TX_UNDEFCALL)) TypeOrError.SetType(TX_OVERPARAM);
+ continue; // trop de paramètres
+ }
+ if ( pv != NULL )
+ {
+ if ( pFunc != NULL ) continue;
+ if ( TypeOrError.Eq(TX_OVERPARAM) ) TypeOrError.SetType(TX_NUMPARAM);
+ if ( TypeOrError.Eq(TX_UNDEFCALL) ) TypeOrError.SetType(TX_LOWPARAM);
+ continue; // pas assez de paramètres
+ }
+
+ if (alpha == 0) // signature parfaite
+ {
+ nIdent = pt->m_nFuncIdent;
+ TypeOrError = pt->m_retTyp;
+ return pt;
+ }
+
+ if ( alpha < delta ) // une meilleur signature ?
+ {
+ pFunc = pt;
+ delta = alpha;
+ }
+ }
+ }
+ }
+
+ if ( pFunc != NULL )
+ {
+ nIdent = pFunc->m_nFuncIdent;
+ TypeOrError = pFunc->m_retTyp;
+ return pFunc;
+ }
+ return NULL;
+}
+
+
+// fait un appel à une fonction
+
+int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
+{
+ CBotTypResult type;
+ CBotFunction* pt = NULL;
+
+ pt = FindLocalOrPublic(nIdent, name, ppVars, type);
+
+ if ( pt != NULL )
+ {
+ CBotStack* pStk1 = pStack->AddStack(pt, 2); // pour mettre "this"
+// if ( pStk1 == EOX ) return TRUE;
+
+ pStk1->SetBotCall(pt->m_pProg); // on a peut-être changé de module
+
+ if ( pStk1->IfStep() ) return FALSE;
+
+ CBotStack* pStk3 = pStk1->AddStack(NULL, TRUE); // paramètres
+
+ // prépare les paramètres sur la pile
+
+ if ( pStk1->GivState() == 0 )
+ {
+ if ( !pt->m_MasterClass.IsEmpty() )
+ {
+ CBotVar* pInstance = m_pProg->m_pInstance;
+ // rend "this" connu
+ CBotVar* pThis ;
+ if ( pInstance == NULL )
+ {
+ pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, pt->m_MasterClass ));
+ pThis->SetInit(2);
+ }
+ else
+ {
+ pThis = CBotVar::Create("this", CBotTypResult( CBotTypPointer, pt->m_MasterClass ));
+ pThis->SetPointer(pInstance);
+ pThis->SetInit(2);
+ }
+
+ pThis->SetUniqNum(-2);
+ pStk1->AddVar(pThis);
+
+ }
+
+ // initialise les variables selon paramètres
+ pt->m_Param->Execute(ppVars, pStk3); // ne peut pas être interrompu
+
+ pStk1->IncState();
+ }
+
+ // finalement exécute la fonction trouvée
+
+ if ( !pStk3->GivRetVar( // remet le résultat sur la pile
+ pt->m_Block->Execute(pStk3) )) // GivRetVar dit si c'est interrompu
+ {
+ if ( !pStk3->IsOk() && pt->m_pProg != m_pProg )
+ {
+#ifdef _DEBUG
+ if ( m_pProg->GivFunctions()->GivName() == "LaCommande" ) return FALSE;
+#endif
+ pStk3->SetPosError(pToken); // indique l'erreur sur l'appel de procédure
+ }
+ return FALSE; // interrompu !
+ }
+
+ return pStack->Return( pStk3 );
+ }
+ return -1;
+}
+
+void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar** ppVars, CBotStack* pStack)
+{
+ CBotTypResult type;
+ CBotFunction* pt = NULL;
+ CBotStack* pStk1;
+ CBotStack* pStk3;
+
+ // recherche la fonction pour remettre l'identificateur ok
+
+ pt = FindLocalOrPublic(nIdent, name, ppVars, type);
+
+ if ( pt != NULL )
+ {
+ pStk1 = pStack->RestoreStack(pt);
+ if ( pStk1 == NULL ) return;
+
+ pStk1->SetBotCall(pt->m_pProg); // on a peut-être changé de module
+
+ if ( pStk1->GivBlock() < 2 )
+ {
+ CBotStack* pStk2 = pStk1->RestoreStack(NULL); // plus utilisé
+ if ( pStk2 == NULL ) return;
+ pStk3 = pStk2->RestoreStack(NULL);
+ if ( pStk3 == NULL ) return;
+ }
+ else
+ {
+ pStk3 = pStk1->RestoreStack(NULL);
+ if ( pStk3 == NULL ) return;
+ }
+
+ // prépare les paramètres sur la pile
+
+ {
+ if ( !pt->m_MasterClass.IsEmpty() )
+ {
+ CBotVar* pInstance = m_pProg->m_pInstance;
+ // rend "this" connu
+ CBotVar* pThis = pStk1->FindVar("this");
+ pThis->SetInit(2);
+ pThis->SetUniqNum(-2);
+ }
+ }
+
+ if ( pStk1->GivState() == 0 )
+ {
+ pt->m_Param->RestoreState(pStk3, TRUE);
+ return;
+ }
+
+ // initialise les variables selon paramètres
+ pt->m_Param->RestoreState(pStk3, FALSE);
+ pt->m_Block->RestoreState(pStk3, TRUE);
+ }
+}
+
+
+
+// fait un appel d'une méthode
+// note : this est déjà sur la pile, le pointeur pThis est juste là pour simplifier
+
+int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
+{
+ CBotTypResult type;
+ CBotProgram* pProgCurrent = pStack->GivBotCall();
+
+ CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type, FALSE);
+
+ if ( pt != NULL )
+ {
+// DEBUG( "CBotFunction::DoCall" + pt->GivName(), 0, pStack);
+
+ CBotStack* pStk = pStack->AddStack(pt, 2);
+// if ( pStk == EOX ) return TRUE;
+
+ pStk->SetBotCall(pt->m_pProg); // on a peut-être changé de module
+ CBotStack* pStk3 = pStk->AddStack(NULL, TRUE); // pour mettre les paramètres passés
+
+ // prépare les paramètres sur la pile
+
+ if ( pStk->GivState() == 0 )
+ {
+ // met la variable "this" sur la pile
+ CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
+ pthis->Copy(pThis, FALSE);
+ pthis->SetUniqNum(-2); // valeur spéciale
+ pStk->AddVar(pthis);
+
+ CBotClass* pClass = pThis->GivClass()->GivParent();
+ if ( pClass )
+ {
+ // met la variable "super" sur la pile
+ CBotVar* psuper = CBotVar::Create("super", CBotTypNullPointer);
+ psuper->Copy(pThis, FALSE); // en fait identique à "this"
+ psuper->SetUniqNum(-3); // valeur spéciale
+ pStk->AddVar(psuper);
+ }
+ // initialise les variables selon paramètres
+ pt->m_Param->Execute(ppVars, pStk3); // ne peut pas être interrompu
+ pStk->IncState();
+ }
+
+ if ( pStk->GivState() == 1 )
+ {
+ if ( pt->m_bSynchro )
+ {
+ CBotProgram* pProgBase = pStk->GivBotCall(TRUE);
+ if ( !pClass->Lock(pProgBase) ) return FALSE; // attend de pouvoir
+ }
+ pStk->IncState();
+ }
+ // finalement appelle la fonction trouvée
+
+ if ( !pStk3->GivRetVar( // remet le résultat sur la pile
+ pt->m_Block->Execute(pStk3) )) // GivRetVar dit si c'est interrompu
+ {
+ if ( !pStk3->IsOk() )
+ {
+ if ( pt->m_bSynchro )
+ {
+ pClass->Unlock(); // libère la fonction
+ }
+
+ if ( pt->m_pProg != pProgCurrent )
+ {
+ pStk3->SetPosError(pToken); // indique l'erreur sur l'appel de procédure
+ }
+ }
+ return FALSE; // interrompu !
+ }
+
+ if ( pt->m_bSynchro )
+ {
+ pClass->Unlock(); // libère la fonction
+ }
+
+ return pStack->Return( pStk3 );
+ }
+ return -1;
+}
+
+void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
+{
+ CBotTypResult type;
+ CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type);
+
+ if ( pt != NULL )
+ {
+ CBotStack* pStk = pStack->RestoreStack(pt);
+ if ( pStk == NULL ) return;
+ pStk->SetBotCall(pt->m_pProg); // on a peut-être changé de module
+
+ CBotVar* pthis = pStk->FindVar("this");
+ pthis->SetUniqNum(-2);
+
+ CBotStack* pStk3 = pStk->RestoreStack(NULL); // pour mettre les paramètres passés
+ if ( pStk3 == NULL ) return;
+
+ pt->m_Param->RestoreState(pStk3, TRUE); // les paramètres
+
+ if ( pStk->GivState() > 1 && // vérouillage est effectif ?
+ pt->m_bSynchro )
+ {
+ CBotProgram* pProgBase = pStk->GivBotCall(TRUE);
+ pClass->Lock(pProgBase); // vérouille la classe
+ }
+
+ // finalement appelle la fonction trouvée
+
+ pt->m_Block->RestoreState(pStk3, TRUE); // interrompu !
+ }
+}
+
+// regarde si la "signature" des paramètres est identique
+BOOL CBotFunction::CheckParam(CBotDefParam* pParam)
+{
+ CBotDefParam* pp = m_Param;
+ while ( pp != NULL && pParam != NULL )
+ {
+ CBotTypResult type1 = pp->GivType();
+ CBotTypResult type2 = pParam->GivType();
+ if ( !type1.Compare(type2) ) return FALSE;
+ pp = pp->GivNext();
+ pParam = pParam->GivNext();
+ }
+ return ( pp == NULL && pParam == NULL );
+}
+
+CBotString CBotFunction::GivName()
+{
+ return m_token.GivString();
+}
+
+CBotString CBotFunction::GivParams()
+{
+ if ( m_Param == NULL ) return CBotString("()");
+
+ CBotString params = "( ";
+ CBotDefParam* p = m_Param; // liste des paramètres
+
+ while (p != NULL)
+ {
+ params += p->GivParamString();
+ p = p->GivNext();
+ if ( p != NULL ) params += ", ";
+ }
+
+ params += " )";
+ return params;
+}
+
+CBotFunction* CBotFunction::Next()
+{
+ return m_next;
+}
+
+void CBotFunction::AddPublic(CBotFunction* func)
+{
+ if ( m_listPublic != NULL )
+ {
+ func->m_nextpublic = m_listPublic;
+ m_listPublic->m_prevpublic = func;
+ }
+ m_listPublic = func;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// gestion des paramètres
+
+
+CBotDefParam::CBotDefParam()
+{
+ m_next = NULL;
+ m_nIdent = 0;
+}
+
+CBotDefParam::~CBotDefParam()
+{
+ delete m_next;
+}
+
+
+// compile une liste de paramètres
+CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ // surtout pas de pStack->TokenStack ici
+ // les variables déclarées doivent rester visibles par la suite
+
+ pStack->SetStartError(p->GivStart());
+
+ if (IsOfType(p, ID_OPENPAR))
+ {
+ CBotDefParam* list = NULL;
+
+ while (!IsOfType(p, ID_CLOSEPAR))
+ {
+ CBotDefParam* param = new CBotDefParam();
+ if (list == NULL) list = param;
+ else list->AddNext(param); // ajoute à la liste
+
+ CBotClass* pClass = NULL;//= CBotClass::Find(p);
+ param->m_typename = p->GivString();
+ CBotTypResult type = param->m_type = TypeParam(p, pStack);
+// if ( type == CBotTypPointer ) type = CBotTypClass; // il faut créer un nouvel objet
+
+ if (param->m_type.GivType() > 0)
+ {
+ CBotToken* pp = p;
+ param->m_token = *p;
+ if (pStack->IsOk() && IsOfType(p, TokenTypVar) )
+ {
+
+ // variable déjà déclarée ?
+ if (pStack->CheckVarLocal(pp))
+ {
+ pStack->SetError(TX_REDEFVAR, pp);
+ break;
+ }
+
+ if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
+ CBotVar* var = CBotVar::Create(pp->GivString(), type); // crée la variable
+// if ( pClass ) var->SetClass(pClass);
+ var->SetInit(2); // la marque initialisée
+ param->m_nIdent = CBotVar::NextUniqNum();
+ var->SetUniqNum(param->m_nIdent);
+ pStack->AddVar(var); // la place sur la pile
+
+ if (IsOfType(p, ID_COMMA) || p->GivType() == ID_CLOSEPAR)
+ continue;
+ }
+ pStack->SetError(TX_CLOSEPAR, p->GivStart());
+ }
+ pStack->SetError(TX_NOTYP, p);
+ delete list;
+ return NULL;
+ }
+ return list;
+ }
+ pStack->SetError(TX_OPENPAR, p->GivStart());
+ return NULL;
+}
+
+void CBotDefParam::AddNext(CBotDefParam* p)
+{
+ CBotDefParam* pp = this;
+ while (pp->m_next != NULL) pp = pp->m_next;
+
+ pp->m_next = p;
+}
+
+
+BOOL CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
+{
+ int i = 0;
+ CBotDefParam* p = this;
+
+ while ( p != NULL )
+ {
+ // crée une variable locale sur la pile
+ CBotVar* newvar = CBotVar::Create(p->m_token.GivString(), p->m_type);
+
+ // procède ainsi pour faire la transformation des types :
+ if ( ppVars != NULL && ppVars[i] != NULL )
+ {
+ switch (p->m_type.GivType())
+ {
+ case CBotTypInt:
+ newvar->SetValInt(ppVars[i]->GivValInt());
+ break;
+ case CBotTypFloat:
+ newvar->SetValFloat(ppVars[i]->GivValFloat());
+ break;
+ case CBotTypString:
+ newvar->SetValString(ppVars[i]->GivValString());
+ break;
+ case CBotTypBoolean:
+ newvar->SetValInt(ppVars[i]->GivValInt());
+ break;
+ case CBotTypIntrinsic:
+ ((CBotVarClass*)newvar)->Copy(ppVars[i], FALSE);
+ break;
+ case CBotTypPointer:
+ case CBotTypArrayPointer:
+ {
+ newvar->SetPointer(ppVars[i]->GivPointer());
+ }
+ break;
+ default:
+ __asm int 3;
+ }
+ }
+ newvar->SetUniqNum(p->m_nIdent);
+ pj->AddVar(newvar); // place la variable
+ p = p->m_next;
+ i++;
+ }
+
+ return TRUE;
+}
+
+void CBotDefParam::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ int i = 0;
+ CBotDefParam* p = this;
+
+ while ( p != NULL )
+ {
+ // crée une variable locale sur la pile
+ CBotVar* var = pj->FindVar(p->m_token.GivString());
+ var->SetUniqNum(p->m_nIdent);
+ p = p->m_next;
+ }
+}
+
+int CBotDefParam::GivType()
+{
+ return m_type.GivType();
+}
+
+CBotTypResult CBotDefParam::GivTypResult()
+{
+ return m_type;
+}
+
+CBotDefParam* CBotDefParam::GivNext()
+{
+ return m_next;
+}
+
+CBotString CBotDefParam::GivParamString()
+{
+ CBotString param;
+
+ param = m_typename;
+ param += ' ';
+
+ param += m_token.GivString();
+ return param;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// retour des paramètres
+
+CBotReturn::CBotReturn()
+{
+ m_Instr = NULL;
+ name = "CBotReturn"; // debug
+}
+
+CBotReturn::~CBotReturn()
+{
+ delete m_Instr;
+}
+
+CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p;
+
+ if (!IsOfType(p, ID_RETURN)) return NULL; // ne devrait jamais arriver
+
+ CBotReturn* inst = new CBotReturn(); // crée l'objet
+ inst->SetToken( pp );
+
+ CBotTypResult type = pStack->GivRetType();
+
+ if ( type.GivType() == 0 ) // retourne void ?
+ {
+ if ( IsOfType( p, ID_SEP ) ) return inst;
+ pStack->SetError( TX_BADTYPE, pp );
+ return NULL;
+ }
+
+ inst->m_Instr = CBotExpression::Compile(p, pStack);
+ if ( pStack->IsOk() )
+ {
+ CBotTypResult retType = pStack->GivTypResult(2);
+ if (TypeCompatible(retType, type, ID_ASS))
+ {
+ if ( IsOfType( p, ID_SEP ) )
+ return inst;
+
+ pStack->SetError(TX_ENDOF, p->GivStart());
+ }
+ pStack->SetError(TX_BADTYPE, p->GivStart());
+ }
+
+ delete inst;
+ return NULL; // pas d'objet, l'erreur est sur la pile
+}
+
+BOOL CBotReturn::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState() == 0 )
+ {
+ if ( m_Instr != NULL && !m_Instr->Execute(pile) ) return FALSE; // évalue le résultat
+ // le résultat est sur la pile
+ pile->IncState();
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ pile->SetBreak(3, CBotString());
+ return pj->Return(pile);
+}
+
+void CBotReturn::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState() == 0 )
+ {
+ if ( m_Instr != NULL ) m_Instr->RestoreState(pile, bMain); // évalue le résultat
+ return;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Les appels à ces fonctions
+
+CBotInstrCall::CBotInstrCall()
+{
+ m_Parameters = NULL;
+ m_nFuncIdent = 0;
+ name = "CBotInstrCall";
+}
+
+CBotInstrCall::~CBotInstrCall()
+{
+ delete m_Parameters;
+}
+
+CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotVar* ppVars[1000];
+
+ int i = 0;
+
+ CBotToken* pp = p;
+ p = p->GivNext();
+
+ pStack->SetStartError(p->GivStart());
+ CBotCStack* pile = pStack;
+
+ if ( IsOfType(p, ID_OPENPAR) )
+ {
+ int start, end;
+ CBotInstrCall* inst = new CBotInstrCall();
+ inst->SetToken(pp);
+
+ // compile la liste des paramètres
+ if (!IsOfType(p, ID_CLOSEPAR)) while (TRUE)
+ {
+ start = p->GivStart();
+ pile = pile->TokenStack(); // garde les résultats sur la pile
+
+ CBotInstr* param = CBotExpression::Compile(p, pile);
+ end = p->GivStart();
+ if ( inst->m_Parameters == NULL ) inst->m_Parameters = param;
+ else inst->m_Parameters->AddNext(param); // construit la liste
+
+ if ( !pile->IsOk() )
+ {
+ delete inst;
+ return pStack->Return(NULL, pile);
+ }
+
+ if ( param != NULL )
+ {
+ if ( pile->GivTypResult().Eq(99) )
+ {
+ delete pStack->TokenStack();
+ pStack->SetError(TX_VOID, p->GivStart());
+ delete inst;
+ return NULL;
+ }
+ ppVars[i] = pile->GivVar();
+ ppVars[i]->GivToken()->SetPos(start, end);
+ i++;
+
+ if (IsOfType(p, ID_COMMA)) continue; // saute la virgule
+ if (IsOfType(p, ID_CLOSEPAR)) break;
+ }
+
+ pStack->SetError(TX_CLOSEPAR, p->GivStart());
+ delete pStack->TokenStack();
+ delete inst;
+ return NULL;
+ }
+ ppVars[i] = NULL;
+
+ // la routine est-elle connue ?
+// CBotClass* pClass = NULL;
+ inst->m_typRes = pStack->CompileCall(pp, ppVars, inst->m_nFuncIdent);
+ if ( inst->m_typRes.GivType() >= 20 )
+ {
+// if (pVar2!=NULL) pp = pVar2->RetToken();
+ pStack->SetError( inst->m_typRes.GivType(), pp );
+ delete pStack->TokenStack();
+ delete inst;
+ return NULL;
+ }
+
+ delete pStack->TokenStack();
+ if ( inst->m_typRes.GivType() > 0 )
+ {
+ CBotVar* pRes = CBotVar::Create("", inst->m_typRes);
+ pStack->SetVar(pRes); // pour connaître le type du résultat
+ }
+ else pStack->SetVar(NULL); // routine retourne void
+
+ return inst;
+ }
+ p = pp;
+ delete pStack->TokenStack();
+ return NULL;
+}
+
+BOOL CBotInstrCall::Execute(CBotStack* &pj)
+{
+ CBotVar* ppVars[1000];
+ CBotStack* pile = pj->AddStack(this);
+ if ( pile->StackOver() ) return pj->Return( pile );
+
+ CBotStack* pile1 = pile;
+
+ int i = 0;
+
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+ if ( p != NULL) while ( TRUE )
+ {
+ pile = pile->AddStack(); // de la place sur la pile pour les résultats
+ if ( pile->GivState() == 0 )
+ {
+ if (!p->Execute(pile)) return FALSE; // interrompu ici ?
+ pile->SetState(1); // marque spéciale pour reconnaîre les paramètres
+ }
+ ppVars[i++] = pile->GivVar();
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ CBotStack* pile2 = pile->AddStack();
+ if ( pile2->IfStep() ) return FALSE;
+
+ if ( !pile2->ExecuteCall(m_nFuncIdent, GivToken(), ppVars, m_typRes)) return FALSE; // interrompu
+
+ return pj->Return(pile2); // libère toute la pile
+}
+
+void CBotInstrCall::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ CBotStack* pile1 = pile;
+
+ int i = 0;
+ CBotVar* ppVars[1000];
+ CBotInstr* p = m_Parameters;
+ // évalue les paramètres
+ // et place les valeurs sur la pile
+ // pour pouvoir être interrompu n'importe quand
+ if ( p != NULL) while ( TRUE )
+ {
+ pile = pile->RestoreStack(); // de la place sur la pile pour les résultats
+ if ( pile == NULL ) return;
+ if ( pile->GivState() == 0 )
+ {
+ p->RestoreState(pile, bMain); // interrompu ici !
+ return;
+ }
+ ppVars[i++] = pile->GivVar(); // construit la liste des paramètres
+ p = p->GivNext();
+ if ( p == NULL) break;
+ }
+ ppVars[i] = NULL;
+
+ CBotStack* pile2 = pile->RestoreStack();
+ if ( pile2 == NULL ) return;
+
+ pile2->RestoreCall(m_nFuncIdent, GivToken(), ppVars);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// déclaration des classes par l'utilisateur
+
+// pré-compile une nouvelle class
+// l'analyse est complète à l'execption du corps des routines
+
+CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
+{
+ if ( !IsOfType(p, ID_PUBLIC) )
+ {
+ pStack->SetError(TX_NOPUBLIC, p);
+ return NULL;
+ }
+
+ if ( !IsOfType(p, ID_CLASS) ) return NULL;
+
+ CBotString name = p->GivString();
+
+ CBotClass* pOld = CBotClass::Find(name);
+ if ( pOld != NULL && pOld->m_IsDef )
+ {
+ pStack->SetError( TX_REDEFCLASS, p );
+ return NULL;
+ }
+
+ // un nom pour la classe est-il là ?
+ if (IsOfType(p, TokenTypVar))
+ {
+ CBotClass* pPapa = NULL;
+#if EXTENDS
+ if ( IsOfType( p, ID_EXTENDS ) )
+ {
+ CBotString name = p->GivString();
+ pPapa = CBotClass::Find(name);
+
+ if (!IsOfType(p, TokenTypVar) || pPapa == NULL )
+ {
+ pStack->SetError( TX_NOCLASS, p );
+ return NULL;
+ }
+ }
+#endif
+ CBotClass* classe = (pOld == NULL) ? new CBotClass(name, pPapa) : pOld;
+ classe->Purge(); // vide les anciennes définitions
+ classe->m_IsDef = FALSE; // définition en cours
+
+ if ( !IsOfType( p, ID_OPBLK) )
+ {
+ pStack->SetError(TX_OPENBLK, p);
+ return NULL;
+ }
+
+ while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
+ {
+ classe->CompileDefItem(p, pStack, FALSE);
+ }
+
+ if (pStack->IsOk()) return classe;
+ }
+ pStack->SetError(TX_ENDOF, p);
+ return NULL;
+}
+
+BOOL CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, BOOL bSecond)
+{
+ BOOL bStatic = FALSE;
+ int mProtect = PR_PUBLIC;
+ BOOL bSynchro = FALSE;
+
+ while (IsOfType(p, ID_SEP)) ;
+
+ CBotTypResult type( -1 );
+
+ if ( IsOfType(p, ID_SYNCHO) ) bSynchro = TRUE;
+ CBotToken* pBase = p;
+
+ if ( IsOfType(p, ID_STATIC) ) bStatic = TRUE;
+ if ( IsOfType(p, ID_PUBLIC) ) mProtect = PR_PUBLIC;
+ if ( IsOfType(p, ID_PRIVATE) ) mProtect = PR_PRIVATE;
+ if ( IsOfType(p, ID_PROTECTED) ) mProtect = PR_PROTECT;
+ if ( IsOfType(p, ID_STATIC) ) bStatic = TRUE;
+
+// CBotClass* pClass = NULL;
+ type = TypeParam(p, pStack); // type du résultat
+
+ if ( type.Eq(-1) )
+ {
+ pStack->SetError(TX_NOTYP, p);
+ return FALSE;
+ }
+
+ while (pStack->IsOk())
+ {
+ CBotToken* pp = p;
+ IsOfType(p, ID_NOT); // saute le ~ éventuel (destructeur)
+
+ if (IsOfType(p, TokenTypVar))
+ {
+ CBotInstr* limites = NULL;
+ while ( IsOfType( p, ID_OPBRK ) ) // un tableau ?
+ {
+ CBotInstr* i = NULL;
+
+ if ( p->GivType() != ID_CLBRK )
+ i = CBotExpression::Compile( p, pStack ); // expression pour la valeur
+ else
+ i = new CBotEmpty(); // spécial si pas de formule
+
+ type = CBotTypResult(CBotTypArrayPointer, type);
+
+ if (!pStack->IsOk() || !IsOfType( p, ID_CLBRK ) )
+ {
+ pStack->SetError(TX_CLBRK, p->GivStart());
+ return FALSE;
+ }
+
+/* CBotVar* pv = pStack->GivVar();
+ if ( pv->GivType()>= CBotTypBoolean )
+ {
+ pStack->SetError(TX_BADTYPE, p->GivStart());
+ return FALSE;
+ }*/
+
+ if (limites == NULL) limites = i;
+ else limites->AddNext3(i);
+ }
+
+ if ( p->GivType() == ID_OPENPAR )
+ {
+ if ( !bSecond )
+ {
+ p = pBase;
+ CBotFunction* f =
+ CBotFunction::Compile1(p, pStack, this);
+
+ if ( f == NULL ) return FALSE;
+
+ if (m_pMethod == NULL) m_pMethod = f;
+ else m_pMethod->AddNext(f);
+ }
+ else
+ {
+ // retrouve la méthode précompilée en passe 1
+ CBotFunction* pf = m_pMethod;
+ CBotFunction* prev = NULL;
+ while ( pf != NULL )
+ {
+ if (pf->GivName() == pp->GivString()) break;
+ prev = pf;
+ pf = pf->Next();
+ }
+
+ BOOL bConstructor = (pp->GivString() == GivName());
+ CBotCStack* pile = pStack->TokenStack(NULL, TRUE);
+
+ // rend "this" connu
+ CBotToken TokenThis(CBotString("this"), CBotString());
+ CBotVar* pThis = CBotVar::Create(&TokenThis, CBotTypResult( CBotTypClass, this ) );
+ pThis->SetUniqNum(-2);
+ pile->AddVar(pThis);
+
+ if ( m_pParent )
+ {
+ // rend "super" connu
+ CBotToken TokenSuper(CBotString("super"), CBotString());
+ CBotVar* pThis = CBotVar::Create(&TokenSuper, CBotTypResult( CBotTypClass, m_pParent ) );
+ pThis->SetUniqNum(-3);
+ pile->AddVar(pThis);
+ }
+
+// int num = 1;
+ CBotClass* my = this;
+ while (my != NULL)
+ {
+ // place une copie des varibles de la classe (this) sur la pile
+ CBotVar* pv = my->m_pVar;
+ while (pv != NULL)
+ {
+ CBotVar* pcopy = CBotVar::Create(pv);
+ pcopy->SetInit(!bConstructor || pv->IsStatic());
+ pcopy->SetUniqNum(pv->GivUniqNum());
+ pile->AddVar(pcopy);
+ pv = pv->GivNext();
+ }
+ my = my->m_pParent;
+ }
+
+ // compile une méthode
+ p = pBase;
+ CBotFunction* f =
+ CBotFunction::Compile(p, pile, NULL/*, FALSE*/);
+
+ if ( f != NULL )
+ {
+ f->m_pProg = pStack->GivBotCall();
+ f->m_bSynchro = bSynchro;
+ // remplace l'élément dans la chaîne
+ f->m_next = pf->m_next;
+ pf->m_next = NULL;
+ delete pf;
+ if (prev == NULL) m_pMethod = f;
+ else prev->m_next = f;
+ }
+ pStack->Return(NULL, pile);
+ }
+
+ return pStack->IsOk();
+ }
+
+ // définition d'un élément
+ if (type.Eq(0))
+ {
+ pStack->SetError(TX_ENDOF, p);
+ return FALSE;
+ }
+
+ CBotInstr* i = NULL;
+ if ( IsOfType(p, ID_ASS ) )
+ {
+ if ( type.Eq(CBotTypArrayPointer) )
+ {
+ i = CBotListArray::Compile(p, pStack, type.GivTypElem());
+ }
+ else
+ {
+ // il y a une assignation à calculer
+ i = CBotTwoOpExpr::Compile(p, pStack);
+ }
+ if ( !pStack->IsOk() ) return FALSE;
+ }
+
+
+ if ( !bSecond )
+ {
+ CBotVar* pv = CBotVar::Create(pp->GivString(), type);
+ pv -> SetStatic( bStatic );
+ pv -> SetPrivate( mProtect );
+
+ AddItem( pv );
+
+ pv->m_InitExpr = i;
+ pv->m_LimExpr = limites;
+
+
+ if ( pv->IsStatic() && pv->m_InitExpr != NULL )
+ {
+ CBotStack* pile = CBotStack::FirstStack(); // une pile indépendante
+ while(pile->IsOk() && !pv->m_InitExpr->Execute(pile)); // évalue l'expression sans timer
+ pv->SetVal( pile->GivVar() ) ;
+ pile->Delete();
+ }
+ }
+ else
+ delete i;
+
+ if ( IsOfType(p, ID_COMMA) ) continue;
+ if ( IsOfType(p, ID_SEP) ) break;
+ }
+ pStack->SetError(TX_ENDOF, p);
+ }
+ return pStack->IsOk();
+}
+
+
+CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ if ( !IsOfType(p, ID_PUBLIC) ) return NULL;
+ if ( !IsOfType(p, ID_CLASS) ) return NULL;
+
+ CBotString name = p->GivString();
+
+ // un nom pour la classe est-il là ?
+ if (IsOfType(p, TokenTypVar))
+ {
+ // la classe à été créée par Compile1
+ CBotClass* pOld = CBotClass::Find(name);
+
+#if EXTENDS
+ if ( IsOfType( p, ID_EXTENDS ) )
+ {
+ IsOfType(p, TokenTypVar); // forcément
+ }
+#endif
+ IsOfType( p, ID_OPBLK); // forcément
+
+ while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
+ {
+ pOld->CompileDefItem(p, pStack, TRUE);
+ }
+
+ pOld->m_IsDef = TRUE; // définition terminée
+ if (pStack->IsOk()) return pOld;
+ }
+ pStack->SetError(TX_ENDOF, p);
+ return NULL;
+}
diff --git a/src/CBot/CBotIf.cpp b/src/CBot/CBotIf.cpp
new file mode 100644
index 0000000..c0f561a
--- /dev/null
+++ b/src/CBot/CBotIf.cpp
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////
+// instruction if (condition) opération1 else opération2;
+
+#include "CBot.h"
+
+// les divers constructeurs / destructeurs
+CBotIf::CBotIf()
+{
+ m_Condition =
+ m_Block =
+ m_BlockElse = NULL; // NULL pour pouvoir faire delete directement
+ name = "CBotIf"; // debug
+}
+
+CBotIf::~CBotIf()
+{
+ delete m_Condition; // libère la condition
+ delete m_Block; // libère le bloc d'instruction1
+ delete m_BlockElse; // libère le bloc d'instruction2
+}
+
+// compilation (routine statique)
+// appelé lorsque le token "if" a été trouvé
+
+CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p; // conserve le ^au token (début instruction)
+
+ if (!IsOfType(p, ID_IF)) return NULL; // ne doit jamais arriver
+
+ CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
+
+ CBotIf* inst = new CBotIf(); // crée l'object
+ inst->SetToken( pp );
+
+ if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
+ {
+ // la condition existe bel et bien
+
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ if ( pStk->IsOk() )
+ {
+ // le bloc d'instruction est ok (peut être vide)
+
+ // regarde si l'instruction suivante est le token "else"
+ if (IsOfType(p, ID_ELSE))
+ {
+ // si oui, compile le bloc d'instruction qui suit
+ inst->m_BlockElse = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ if (!pStk->IsOk())
+ {
+ // il n'y a pas de bloc correct après le else
+ // libère l'objet, et transmet l'erreur qui est sur la pile
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ }
+
+ // rend l'object correct à qui le demande.
+ return pStack->Return(inst, pStk);
+ }
+ }
+
+ // erreur, libère l'objet
+ delete inst;
+ // et transmet l'erreur qui se trouve sur la pile.
+ return pStack->Return(NULL, pStk);
+}
+
+
+// exécution de l'instruction
+
+BOOL CBotIf :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ // selon la reprise, on peut être dans l'un des 2 états
+ if( pile->GivState() == 0 )
+ {
+ // évalue la condition
+ if ( !m_Condition->Execute(pile) ) return FALSE; // interrompu ici ?
+
+ // termine s'il y a une erreur
+ if ( !pile->IsOk() )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ // passe dans le second état
+ if (!pile->SetState(1)) return FALSE; // prêt pour la suite
+ }
+
+ // second état, évalue les instructions associées
+ // le résultat de la condition est sur la pile
+
+ if ( pile->GivVal() == TRUE ) // condition était vraie ?
+ {
+ if ( m_Block != NULL && // bloc peut être absent
+ !m_Block->Execute(pile) ) return FALSE; // interrompu ici ?
+ }
+ else
+ {
+ if ( m_BlockElse != NULL && // s'il existe un bloc alternatif
+ !m_BlockElse->Execute(pile) ) return FALSE; // interrompu ici
+ }
+
+ // transmet le résultat et libère la pile
+ return pj->Return(pile);
+}
+
+
+void CBotIf :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this); // ajoute un élément à la pile
+ if ( pile == NULL ) return;
+
+ // selon la reprise, on peut être dans l'un des 2 états
+ if( pile->GivState() == 0 )
+ {
+ // évalue la condition
+ m_Condition->RestoreState(pile, bMain); // interrompu ici !
+ return;
+ }
+
+ // second état, évalue les instructions associées
+ // le résultat de la condition est sur la pile
+
+ if ( pile->GivVal() == TRUE ) // condition était vraie ?
+ {
+ if ( m_Block != NULL ) // bloc peut être absent
+ m_Block->RestoreState(pile, bMain); // interrompu ici !
+ }
+ else
+ {
+ if ( m_BlockElse != NULL ) // s'il existe un bloc alternatif
+ m_BlockElse->RestoreState(pile, bMain); // interrompu ici !
+ }
+}
+
diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp
new file mode 100644
index 0000000..ba14f89
--- /dev/null
+++ b/src/CBot/CBotProgram.cpp
@@ -0,0 +1,1102 @@
+//////////////////////////////////////////////////////////////////////
+// gestion de base d'un programme CBot
+
+#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;
+ m_pClass->Purge(); // purge les anciennes définitions des classes
+ // mais sans détruire l'object
+ 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);
+ CBotToken* p = pBaseToken->GivNext(); // saute le 1er token (séparateur)
+
+ pStack->SetBotCall(this); // défini les routines utilisables
+ CBotCall::SetPUser(pUser);
+
+ // fait une première passe rapide juste pour prendre les entêtes de routines et de classes
+ 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
+
+ p = pBaseToken->GivNext(); // revient au début
+
+ 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;
+ CBotClass::Compile(p, pStack); // complète la définition de la classe
+ }
+ 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();
+ }
+ }
+
+// delete m_Prog; // la liste de la 1ère passe
+// 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
+ m_pStack = new CBotStack(NULL); // crée une pile d'exécution
+#endif
+
+ m_pStack->SetBotCall(this); // bases pour les routines
+
+ return TRUE; // on est prêt pour un Run()
+}
+
+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;
+
+ m_pStack->Reset(pUser); // vide l'éventuelle erreur précédente, et remet le timer
+ if ( timer >= 0 ) m_pStack->SetTimer(timer);
+
+ m_pStack->SetBotCall(this); // bases pour les routines
+
+#if STACKRUN
+ // reprend l'exécution sur le haut de la pile
+ 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
+ // revient sur l'exécution normale
+ ok = m_pRun->Execute(NULL, m_pStack, m_pInstance);
+#endif
+ }
+#else
+ ok = m_pRun->Execute(NULL, m_pStack, m_pInstance);
+#endif
+
+ // terminé sur une erreur ?
+ 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;
+ return TRUE; // exécution terminée !!
+ }
+
+ if ( ok ) m_pRun = NULL; // plus de fonction en exécution
+ 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];
+ sprintf(buf, "Exception numéro %d.", code);
+ 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))
+{
+ // mémorise les pointeurs aux deux fonctions
+ 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;
+
+ // récupère la pile depuis l'enregistrement
+ // utilise un pointeur NULL (m_pStack) mais c'est ok comme ça
+ if (!m_pStack->RestoreState(pf, m_pStack)) return FALSE;
+ m_pStack->SetBotCall(this); // bases pour les routines
+
+ // rétabli certains états dans la pile selon la structure
+ 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 )
+ {
+ // libère une fonction qu'on redéfini
+ if ( pp ) pp->m_next = p->m_next;
+ else m_ListCalls = p->m_next;
+ pp = p;
+ p = p->m_next;
+ pp->m_next = NULL; // ne pas détruire la suite de la liste
+ delete pp;
+ continue;
+ }
+ pp = p; // pointeur précédent
+ 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
+// en une liste de variables chaînées
+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;
+}
+
+// trouve un appel acceptable selon le nom de la procédure
+// et les paramètres donnés
+
+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();
+
+ // si une classe est retournée, c'est en fait un pointeur
+ 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
+ // fait la liste des paramètres selon le contenu de la pile (pStackVar)
+
+ CBotVar* pVar = MakeListVars(ppVar, TRUE);
+ CBotVar* pVarToDelete = pVar;
+
+ // crée une variable pour le résultat
+ 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());
+
+ if ( pResult != pRes ) delete pRes; // si résultat différent rendu
+ 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;
+
+ // fait la liste des paramètres selon le contenu de la pile (pStackVar)
+
+ CBotVar* pVar = MakeListVars(ppVar, TRUE);
+ CBotVar* pVarToDelete = pVar;
+
+ // crée une variable pour le résultat
+ 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);
+ }
+ if ( pResult != pRes ) delete pResult; // si résultat différent rendu
+ return FALSE;
+ }
+
+ if ( pResult != NULL ) pStack->SetCopyVar( pResult );
+ if ( pResult != pRes ) delete pResult; // si résultat différent rendu
+
+ 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;
+}
+
+// trouve un appel acceptable selon le nom de la procédure
+// et les paramètres donnés
+
+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 )
+ {
+ // fait la liste des paramètres selon le contenu de la pile (pStackVar)
+
+ 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 )
+ {
+ // fait la liste des paramètres selon le contenu de la pile (pStackVar)
+
+ 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 )
+{
+ // pas de paramètre
+ if ( pVar != NULL ) return CBotTypResult( TX_OVERPARAM );
+
+ // la fonction retourne un résultat "string"
+ return CBotTypResult( CBotTypString );
+}
+
+
+#include "StringFunctions.cpp"
+
+void CBotProgram::Init()
+{
+ CBotToken::DefineNum( "CBotErrOpenPar", 5000) ; // manque la parenthèse ouvrante
+ CBotToken::DefineNum( "CBotErrClosePar", 5001) ; // manque la parenthèse fermante
+ CBotToken::DefineNum( "CBotErrNotBoolean", 5002) ; // l'expression doit être un boolean
+ CBotToken::DefineNum( "CBotErrUndefVar", 5003) ; // variable non déclarée
+ 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
+ CBotToken::DefineNum( "CBotErrRedefVar", 5012) ; // redéfinition de la variable
+ CBotToken::DefineNum( "CBotErrBadType2", 5013) ; // 2 opérandes de type incompatibles
+ 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
+ CBotToken::DefineNum( "CBotErrNoType", 5023) ; // déclaration de type attendue
+ CBotToken::DefineNum( "CBotErrNoVar", 5024) ; // nom de variable attendu
+ CBotToken::DefineNum( "CBotErrNoFunc", 5025) ; // nom de fonction attendu
+ CBotToken::DefineNum( "CBotErrOverParam", 5026) ; // trop de paramètres
+ CBotToken::DefineNum( "CBotErrRedefFunc", 5027) ; // cette fonction existe déjà
+ CBotToken::DefineNum( "CBotErrLowParam", 5028) ; // pas assez de paramètres
+ CBotToken::DefineNum( "CBotErrBadParam", 5029) ; // mauvais types de paramètres
+ CBotToken::DefineNum( "CBotErrNbParam", 5030) ; // mauvais nombre de paramètres
+ CBotToken::DefineNum( "CBotErrUndefItem", 5031) ; // élément n'existe pas dans la classe
+ CBotToken::DefineNum( "CBotErrUndefClass", 5032) ; // variable n'est pas une classe
+ CBotToken::DefineNum( "CBotErrNoConstruct", 5033) ; // pas de constructeur approprié
+ CBotToken::DefineNum( "CBotErrRedefClass", 5034) ; // classe existe déjà
+ CBotToken::DefineNum( "CBotErrCloseIndex", 5035) ; // " ] " attendu
+ CBotToken::DefineNum( "CBotErrReserved", 5036) ; // mot réservé (par un DefineNum)
+
+// voici la liste des erreurs pouvant être retournées par le module
+// pour l'exécution
+
+ CBotToken::DefineNum( "CBotErrZeroDiv", 6000) ; // division par zéro
+ CBotToken::DefineNum( "CBotErrNotInit", 6001) ; // variable non initialisée
+ CBotToken::DefineNum( "CBotErrBadThrow", 6002) ; // throw d'une valeur négative
+ CBotToken::DefineNum( "CBotErrNoRetVal", 6003) ; // fonction n'a pas retourné de résultat
+ 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() ;
+}
+
diff --git a/src/CBot/CBotStack.cpp b/src/CBot/CBotStack.cpp
new file mode 100644
index 0000000..c313a8b
--- /dev/null
+++ b/src/CBot/CBotStack.cpp
@@ -0,0 +1,1460 @@
+//////////////////////////////////////////////////////////////////////
+// gestion de la pile (stack)
+
+#include "CBot.h"
+
+
+#define ITIMER 100
+
+////////////////////////////////////////////////////////////////////////////
+// gestion de la pile d'exécution
+////////////////////////////////////////////////////////////////////////////
+
+int CBotStack::m_initimer = ITIMER; // init la variable statique
+int CBotStack::m_timer = 0; // init la variable statique
+CBotVar* CBotStack::m_retvar = NULL; // init la variable statique
+int CBotStack::m_error = 0; // init la variable statique
+int CBotStack::m_start = 0; // init la variable statique
+int CBotStack::m_end = 0; // init la variable statique
+CBotString CBotStack::m_labelBreak=""; // init la variable statique
+void* CBotStack::m_pUser = NULL;
+
+#if STACKMEM
+
+CBotStack* CBotStack::FirstStack()
+{
+ CBotStack* p;
+
+ long size = sizeof(CBotStack);
+ size *= (MAXSTACK+10);
+
+ // demande une tranche mémoire pour la pile
+ p = (CBotStack*)malloc(size);
+
+ // la vide totalement
+ memset(p, 0, size);
+
+ p-> m_bBlock = TRUE;
+ m_timer = m_initimer; // met le timer au début
+
+ CBotStack* pp = p;
+ pp += MAXSTACK;
+ for ( int i = 0 ; i< 10 ; i++ )
+ {
+ pp->m_bOver = TRUE;
+ pp ++;
+ }
+#ifdef _DEBUG
+ int n = 1;
+ pp = p;
+ for ( i = 0 ; i< MAXSTACK+10 ; i++ )
+ {
+ pp->m_index = n++;
+ pp ++;
+ }
+#endif
+
+ m_error = 0; // évite des blocages car m_error est static
+ return p;
+}
+
+CBotStack::CBotStack(CBotStack* ppapa)
+{
+ // constructeur doit exister, sinon le destructeur n'est jamais appelé !
+ __asm int 3;
+}
+
+CBotStack::~CBotStack()
+{
+ __asm int 3; // utiliser Delete() à la place
+}
+
+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 )
+ m_prev->m_next = NULL; // enlève de la chaîne
+
+ if ( m_prev->m_next2 == this )
+ m_prev->m_next2 = NULL; // enlève de la chaîne
+ }
+
+ delete m_var;
+ delete m_listVar;
+
+ CBotStack* p = m_prev;
+ BOOL bOver = m_bOver;
+#ifdef _DEBUG
+ int n = m_index;
+#endif
+
+ // efface le bloc libéré
+ memset(this, 0, sizeof(CBotStack));
+ m_bOver = bOver;
+#ifdef _DEBUG
+ m_index = n;
+#endif
+
+ if ( p == NULL )
+ free( this );
+}
+
+
+// routine optimisée
+CBotStack* CBotStack::AddStack(CBotInstr* instr, BOOL bBlock)
+{
+ 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 );
+
+ m_next = p; // chaîne l'élément
+ 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;
+ p->m_bFunc = FALSE;
+ return p;
+}
+
+CBotStack* CBotStack::AddStackEOX(CBotCall* instr, BOOL bBlock)
+{
+ 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;
+ p->m_bFunc = 2; // spécial
+ return p;
+}
+
+CBotStack* CBotStack::AddStack2(BOOL bBlock)
+{
+ if (m_next2 != NULL)
+ {
+ m_next2->m_prog = m_prog; // spécial évite un RestoreStack2
+ return m_next2; // reprise dans une pile existante
+ }
+
+ CBotStack* p = this;
+ do
+ {
+ p ++;
+ }
+ while ( p->m_prev != NULL );
+
+ m_next2 = p; // chaîne l'élément
+ p->m_prev = this;
+ p->m_bBlock = bBlock;
+ p->m_prog = m_prog;
+ p->m_step = 0;
+ return p;
+}
+
+BOOL CBotStack::GivBlock()
+{
+ return m_bBlock;
+}
+
+BOOL CBotStack::Return(CBotStack* pfils)
+{
+ if ( pfils == this ) return TRUE; // spécial
+
+ if (m_var != NULL) delete m_var; // valeur remplacée ?
+ m_var = pfils->m_var; // résultat transmis
+ pfils->m_var = NULL; // ne pas détruire la variable
+
+ m_next->Delete();m_next = NULL; // libère la pile au dessus
+ m_next2->Delete();m_next2 = NULL; // aussi la seconde pile (catch)
+
+ return (m_error == 0); // interrompu si erreur
+}
+
+BOOL CBotStack::ReturnKeep(CBotStack* pfils)
+{
+ if ( pfils == this ) return TRUE; // spécial
+
+ if (m_var != NULL) delete m_var; // valeur remplacée ?
+ m_var = pfils->m_var; // résultat transmis
+ pfils->m_var = NULL; // ne pas détruire la variable
+
+ return (m_error == 0); // interrompu si erreur
+}
+
+BOOL CBotStack::StackOver()
+{
+ if (!m_bOver) return FALSE;
+ m_error = TX_STACKOVER;
+ return TRUE;
+}
+
+#else
+
+CBotStack::CBotStack(CBotStack* ppapa)
+{
+ m_next = NULL;
+ m_next2 = NULL;
+ m_prev = ppapa;
+
+ m_bBlock = (ppapa == NULL) ? TRUE : FALSE;
+
+ m_state = 0;
+ m_step = 1;
+
+ if (ppapa == NULL) m_timer = m_initimer; // met le timer au début
+
+ m_listVar = NULL;
+ m_bDontDelete = FALSE;
+
+ m_var = NULL;
+ m_prog = NULL;
+ m_instr = NULL;
+ m_call = NULL;
+ m_bFunc = FALSE;
+}
+
+// destructeur
+CBotStack::~CBotStack()
+{
+ if ( m_next != EOX) delete m_next;
+ delete m_next2;
+ if (m_prev != NULL && m_prev->m_next == this )
+ m_prev->m_next = NULL; // enlève de la chaîne
+
+ delete m_var;
+ if ( !m_bDontDelete ) delete m_listVar;
+}
+
+// routine à optimiser
+CBotStack* CBotStack::AddStack(CBotInstr* instr, BOOL bBlock)
+{
+ if (m_next != NULL)
+ {
+ return m_next; // reprise dans une pile existante
+ }
+ CBotStack* p = new CBotStack(this);
+ m_next = p; // chaîne l'élément
+ p->m_bBlock = bBlock;
+ p->m_instr = instr;
+ p->m_prog = m_prog;
+ p->m_step = 0;
+ return p;
+}
+
+CBotStack* CBotStack::AddStackEOX(CBotCall* instr, BOOL bBlock)
+{
+ 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);
+ m_next = p; // chaîne l'élément
+ p->m_bBlock = bBlock;
+ p->m_call = instr;
+ p->m_prog = m_prog;
+ p->m_step = 0;
+ p->m_bFunc = 2; // spécial
+ return p;
+}
+
+CBotStack* CBotStack::AddStack2(BOOL bBlock)
+{
+ if (m_next2 != NULL)
+ {
+ m_next2->m_prog = m_prog; // spécial évite un RestoreStack2
+ return m_next2; // reprise dans une pile existante
+ }
+
+ CBotStack* p = new CBotStack(this);
+ m_next2 = p; // chaîne l'élément
+ p->m_bBlock = bBlock;
+ p->m_prog = m_prog;
+ p->m_step = 0;
+
+ return p;
+}
+
+BOOL CBotStack::Return(CBotStack* pfils)
+{
+ if ( pfils == this ) return TRUE; // spécial
+
+ if (m_var != NULL) delete m_var; // valeur remplacée ?
+ m_var = pfils->m_var; // résultat transmis
+ pfils->m_var = NULL; // ne pas détruite la variable
+
+ if ( m_next != EOX ) delete m_next; // libère la pile au dessus
+ delete m_next2;m_next2 = NULL; // aussi la seconde pile (catch)
+
+ return (m_error == 0); // interrompu si erreur
+}
+
+BOOL CBotStack::StackOver()
+{
+ return FALSE; // pas de test de débordement dans cette version
+}
+
+#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)
+ {
+ m_next->m_instr = instr; // réinit (si reprise après restitution)
+ 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;
+}
+
+
+
+// routine pour l'exécution pas à pas
+BOOL CBotStack::IfStep()
+{
+ if ( m_initimer > 0 || m_step++ > 0 ) return FALSE;
+ return TRUE;
+}
+
+
+BOOL CBotStack::BreakReturn(CBotStack* pfils, const char* name)
+{
+ if ( m_error>=0 ) return FALSE; // sortie normale
+ if ( m_error==-3 ) return FALSE; // sortie normale (return en cours)
+
+ if (!m_labelBreak.IsEmpty() && (name[0] == 0 || m_labelBreak != name))
+ return FALSE; // c'est pas pour moi
+
+ m_error = 0;
+ m_labelBreak.Empty();
+ return Return(pfils);
+}
+
+BOOL CBotStack::IfContinue(int state, const char* name)
+{
+ if ( m_error != -2 ) return FALSE;
+
+ if (!m_labelBreak.IsEmpty() && (name == NULL || m_labelBreak != name))
+ return FALSE; // c'est pas pour moi
+
+ m_state = state; // où reprendre ?
+ m_error = 0;
+ m_labelBreak.Empty();
+ if ( m_next != EOX ) m_next->Delete(); // purge la pile au dessus
+ return TRUE;
+}
+
+void CBotStack::SetBreak(int val, const char* name)
+{
+ m_error = -val; // réagit comme une Exception
+ m_labelBreak = name;
+ if (val == 3) // pour un return
+ {
+ m_retvar = m_var;
+ m_var = NULL;
+ }
+}
+
+// remet sur la pile la valeur calculée par le dernier CBotReturn
+
+BOOL CBotStack::GivRetVar(BOOL bRet)
+{
+ if (m_error == -3)
+ {
+ if ( m_var ) delete m_var;
+ m_var = m_retvar;
+ m_retvar = NULL;
+ m_error = 0;
+ return TRUE;
+ }
+ 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
+// ce peut être une variable composée avec un point
+CBotVar* CBotStack::FindVar(CBotToken* &pToken, BOOL bUpdate, BOOL bModif)
+{
+ CBotStack* p = this;
+ CBotString name = pToken->GivString();
+
+ while (p != NULL)
+ {
+ CBotVar* pp = p->m_listVar;
+ while ( pp != NULL)
+ {
+ if (pp->GivName() == name)
+ {
+ if ( bUpdate )
+ pp->Maj(m_pUser, FALSE);
+
+ 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;
+}
+
+// retrouve une variable sur la pile selon son numéro d'identification
+// ce qui va plus vite que de comparer les noms.
+
+CBotVar* CBotStack::FindVar(long ident, BOOL bUpdate, BOOL bModif)
+{
+ CBotStack* p = this;
+ while (p != NULL)
+ {
+ CBotVar* pp = p->m_listVar;
+ while ( pp != NULL)
+ {
+ if (pp->GivUniqNum() == ident)
+ {
+ if ( bUpdate )
+ pp->Maj(m_pUser, FALSE);
+
+ return pp;
+ }
+ pp = pp->m_next;
+ }
+ p = p->m_prev;
+ }
+ return NULL;
+}
+
+
+CBotVar* CBotStack::FindVar(CBotToken& Token, BOOL bUpdate, BOOL bModif)
+{
+ CBotToken* pt = &Token;
+ return FindVar(pt, bUpdate, bModif);
+}
+
+
+CBotVar* CBotStack::CopyVar(CBotToken& Token, BOOL bUpdate)
+{
+ CBotVar* pVar = FindVar( Token, bUpdate );
+
+ if ( pVar == NULL) return NULL;
+
+ CBotVar* pCopy = CBotVar::Create(pVar);
+ pCopy->Copy(pVar);
+ return pCopy;
+}
+
+
+BOOL CBotStack::SetState(int n, int limite)
+{
+ m_state = n;
+
+ m_timer--; // décompte les opérations
+ return ( m_timer > limite ); // interrompu si timer passé
+}
+
+BOOL CBotStack::IncState(int limite)
+{
+ m_state++;
+
+ m_timer--; // décompte les opérations
+ return ( m_timer > limite ); // interrompu si timer passé
+}
+
+
+void CBotStack::SetError(int n, CBotToken* token)
+{
+ if ( n!= 0 && m_error != 0) return; // ne change pas une erreur déjà existante
+ 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;
+}
+
+BOOL CBotStack::Execute()
+{
+ CBotCall* instr = NULL; // instruction la plus élevée
+ 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;
+ }
+
+ if ( instr == NULL ) return TRUE; // exécution normale demandée
+
+ if (!instr->Run(pile)) return FALSE; // exécution à partir de là
+
+#if STACKMEM
+ pile->m_next->Delete();
+#else
+ delete pile->m_next;
+#endif
+
+ pile->m_next = EOX; // spécial pour reprise
+ return TRUE;
+}
+
+// met sur le stack le pointeur à une variable
+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;
+ m_var = NULL; // ne sera pas détruit donc
+ 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;
+
+ // revient sur l'élement père
+ 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;
+
+ *pp = pVar; // ajoute à la suite
+
+#ifdef _DEBUG
+ if ( pVar->GivUniqNum() == 0 ) __asm int 3;
+#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;
+ m_bFunc = TRUE;
+}
+
+CBotProgram* CBotStack::GivBotCall(BOOL bFirst)
+{
+ 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;
+}
+
+
+BOOL CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotTypResult& rettype)
+{
+ 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();
+
+ // si pas trouvé (recompilé ?) cherche selon le nom
+
+ 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);
+ return TRUE;
+}
+
+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 );
+}
+
+
+BOOL SaveVar(FILE* pf, CBotVar* pVar)
+{
+ while ( TRUE )
+ {
+ if ( pVar == NULL )
+ {
+ return WriteWord(pf, 0); // met un terminateur
+ }
+
+ if ( !pVar->Save0State(pf)) return FALSE; // entête commune
+ if ( !pVar->Save1State(pf) ) return FALSE; // sauve selon la classe fille
+
+ pVar = pVar->GivNext();
+ }
+}
+
+void CBotStack::GetRunPos(const char* &FunctionName, int &start, int &end)
+{
+ CBotProgram* prog = m_prog; // programme courrant
+
+ CBotInstr* funct = NULL; // fonction trouvée
+ CBotInstr* instr = NULL; // instruction la plus élevée
+
+ 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;
+ }
+
+
+ // descend sur les éléments de block
+ 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;
+}
+
+BOOL CBotStack::SaveState(FILE* pf)
+{
+ if ( this == NULL ) // fin de l'arbre ?
+ {
+ return WriteWord(pf, 0); // met un terminateur
+ }
+
+ if ( m_next2 != NULL )
+ {
+ if (!WriteWord(pf, 2)) return FALSE; // une marque de poursuite
+ if (!m_next2->SaveState(pf)) return FALSE;
+ }
+ else
+ {
+ if (!WriteWord(pf, 1)) return FALSE; // une marque de poursuite
+ }
+ if (!WriteWord(pf, m_bBlock)) return FALSE; // est-ce un bloc local
+ if (!WriteWord(pf, m_state)) return FALSE; // dans quel état
+ if (!WriteWord(pf, 0)) return FALSE; // par compatibilité m_bDontDelete
+ if (!WriteWord(pf, m_step)) return FALSE; // dans quel état
+
+
+ if (!SaveVar(pf, m_var)) return FALSE; // le résultat courant
+ if (!SaveVar(pf, m_listVar)) return FALSE; // les variables locales
+
+ return m_next->SaveState(pf); // enregistre la suite
+}
+
+
+BOOL CBotStack::RestoreState(FILE* pf, CBotStack* &pStack)
+{
+ WORD w;
+
+ pStack = NULL;
+ if (!ReadWord(pf, w)) return FALSE;
+ if ( w == 0 ) return TRUE;
+
+#if STACKMEM
+ if ( this == NULL ) pStack = FirstStack();
+ else pStack = AddStack();
+#else
+ pStack = new CBotStack(this);
+#endif
+
+ if ( w == 2 )
+ {
+ if (!pStack->RestoreState(pf, pStack->m_next2)) return FALSE;
+ }
+
+ if (!ReadWord(pf, w)) return FALSE; // est-ce un bloc local
+ pStack->m_bBlock = w;
+
+ if (!ReadWord(pf, w)) return FALSE; // dans quel état j'ère ?
+ pStack->SetState((short)w); // dans le bon état
+
+ if (!ReadWord(pf, w)) return FALSE; // dont delete ?
+ // plus utilisé
+
+ if (!ReadWord(pf, w)) return FALSE; // pas à pas
+ pStack->m_step = w;
+
+ if (!CBotVar::RestoreState(pf, pStack->m_var)) return FALSE; // la variable temp
+ if (!CBotVar::RestoreState(pf, pStack->m_listVar)) return FALSE;// les variables locales
+
+ return pStack->RestoreState(pf, pStack->m_next);
+}
+
+
+BOOL CBotVar::Save0State(FILE* pf)
+{
+ if (!WriteWord(pf, 100+m_mPrivate))return FALSE; // variable privé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 ?
+ return WriteString(pf, m_token->GivString()); // et le nom de la variable
+}
+
+BOOL CBotVarInt::Save0State(FILE* pf)
+{
+ if ( !m_defnum.IsEmpty() )
+ {
+ if(!WriteWord(pf, 200 )) return FALSE; // marqueur spécial
+ if(!WriteString(pf, m_defnum)) return FALSE; // nom de la valeur
+ }
+
+ return CBotVar::Save0State(pf);
+}
+
+BOOL CBotVarInt::Save1State(FILE* pf)
+{
+ return WriteWord(pf, m_val); // la valeur de la variable
+}
+
+BOOL CBotVarBoolean::Save1State(FILE* pf)
+{
+ return WriteWord(pf, m_val); // la valeur de la variable
+}
+
+BOOL CBotVarFloat::Save1State(FILE* pf)
+{
+ return WriteFloat(pf, m_val); // la valeur de la variable
+}
+
+BOOL CBotVarString::Save1State(FILE* pf)
+{
+ return WriteString(pf, m_val); // la valeur de la variable
+}
+
+
+
+BOOL CBotVarClass::Save1State(FILE* pf)
+{
+ if ( !WriteType(pf, m_type) ) return FALSE;
+ if ( !WriteLong(pf, m_ItemIdent) ) return FALSE;
+
+ return SaveVar(pf, m_pVar); // contenu de l'objet
+}
+
+BOOL CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
+{
+ WORD w, wi, prv, st;
+ float ww;
+ CBotString name, s;
+
+ delete pVar;
+
+ pVar = NULL;
+ CBotVar* pNew = NULL;
+ CBotVar* pPrev = NULL;
+
+ while ( TRUE ) // recupère toute une liste
+ {
+ if (!ReadWord(pf, w)) return FALSE; // privé ou type ?
+ if ( w == 0 ) return TRUE;
+
+ CBotString defnum;
+ if ( w == 200 )
+ {
+ if (!ReadString(pf, defnum)) return FALSE; // nombre avec un identifiant
+ if (!ReadWord(pf, w)) return FALSE; // type
+ }
+
+ prv = 100; st = 0;
+ if ( w >= 100 )
+ {
+ prv = w;
+ if (!ReadWord(pf, st)) return FALSE; // statique
+ if (!ReadWord(pf, w)) return FALSE; // type
+ }
+
+ if ( w == CBotTypClass ) w = CBotTypIntrinsic; // forcément intrinsèque
+
+ if (!ReadWord(pf, wi)) return FALSE; // init ?
+
+ if (!ReadString(pf, name)) return FALSE; // nom de la variable
+
+ CBotToken token(name, CBotString());
+
+ switch (w)
+ {
+ case CBotTypInt:
+ case CBotTypBoolean:
+ pNew = CBotVar::Create(&token, w); // crée une variable
+ if (!ReadWord(pf, w)) return FALSE;
+ pNew->SetValInt((short)w, defnum);
+ break;
+ case CBotTypFloat:
+ pNew = CBotVar::Create(&token, w); // crée une variable
+ if (!ReadFloat(pf, ww)) return FALSE;
+ pNew->SetValFloat(ww);
+ break;
+ case CBotTypString:
+ pNew = CBotVar::Create(&token, w); // crée une variable
+ if (!ReadString(pf, s)) return FALSE;
+ pNew->SetValString(s);
+ break;
+
+ // restitue un objet intrinsic ou un élément d'un array
+ case CBotTypIntrinsic:
+ case CBotTypArrayBody:
+ {
+ CBotTypResult r;
+ long id;
+ if (!ReadType(pf, r)) return FALSE; // type complet
+ if (!ReadLong(pf, id) ) return FALSE;
+
+// if (!ReadString(pf, s)) return FALSE;
+ {
+ CBotVar* p = NULL;
+ if ( id ) p = CBotVarClass::Find(id) ;
+
+ pNew = new CBotVarClass(&token, r); // crée directement une instance
+ // attention cptuse = 0
+ if ( !RestoreState(pf, ((CBotVarClass*)pNew)->m_pVar)) return FALSE;
+ pNew->SetIdent(id);
+
+ if ( p != NULL )
+ {
+ delete pNew;
+ pNew = p; // reprend l'élément connu
+ }
+ }
+ }
+ break;
+
+ case CBotTypPointer:
+ case CBotTypNullPointer:
+ if (!ReadString(pf, s)) return FALSE;
+ {
+ pNew = CBotVar::Create(&token, CBotTypResult(w, s));// crée une variable
+ 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;
+ if ( !CBotVar::RestoreState( pf, pInstance ) ) return FALSE;
+ ((CBotVarPointer*)pNew)->SetPointer( pInstance ); // et pointe dessus
+
+// if ( p != NULL ) ((CBotVarPointer*)pNew)->SetPointer( p ); // plutôt celui-ci !
+
+ }
+ break;
+
+ case CBotTypArrayPointer:
+ {
+ CBotTypResult r;
+ if (!ReadType(pf, r)) return FALSE;
+
+ pNew = CBotVar::Create(&token, r); // crée une variable
+
+ // restitue une copie de l'instance d'origine
+ CBotVar* pInstance = NULL;
+ if ( !CBotVar::RestoreState( pf, pInstance ) ) return FALSE;
+ ((CBotVarPointer*)pNew)->SetPointer( pInstance ); // et pointe dessus
+ }
+ break;
+ default:
+ __asm int 3;
+ }
+
+ 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;
+ }
+ return TRUE;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// gestion de la pile à la compilation
+////////////////////////////////////////////////////////////////////////////
+
+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;
+ m_bBlock = TRUE;
+ }
+ else
+ {
+ m_start = ppapa->m_start;
+ m_bBlock = FALSE;
+ }
+
+ m_listVar = NULL;
+ m_var = NULL;
+}
+
+// destructeur
+CBotCStack::~CBotCStack()
+{
+ if (m_next != NULL) delete m_next;
+ if (m_prev != NULL) m_prev->m_next = NULL; // enlève de la chaîne
+
+ delete m_var;
+ delete m_listVar;
+}
+
+// utilisé uniquement à la compilation
+CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, BOOL bBlock)
+{
+ if (m_next != NULL) return m_next; // reprise dans une pile existante
+
+ CBotCStack* p = new CBotCStack(this);
+ m_next = p; // chaîne l'élément
+ 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;
+
+ if (m_var != NULL) delete m_var; // valeur remplacée ?
+ m_var = pfils->m_var; // résultat transmis
+ pfils->m_var = NULL; // ne pas détruire la variable
+
+ if (m_error)
+ {
+ m_start = pfils->m_start; // récupère la position de l'erreur
+ m_end = pfils->m_end;
+ }
+
+ delete pfils;
+ return inst;
+}
+
+CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
+{
+ if (m_var != NULL) delete m_var; // valeur remplacée ?
+ m_var = pfils->m_var; // résultat transmis
+ pfils->m_var = NULL; // ne pas détruire la variable
+
+ if (m_error)
+ {
+ m_start = pfils->m_start; // récupère la position de l'erreur
+ 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
+// le token peut être une suite de TokenTypVar (objet d'une classe)
+// 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;
+}
+
+BOOL CBotCStack::IsOk()
+{
+ return (m_error == 0);
+}
+
+
+void CBotCStack::SetStartError( int pos )
+{
+ if ( m_error != 0) return; // ne change pas une erreur déjà existante
+ m_start = pos;
+}
+
+void CBotCStack::SetError(int n, int pos)
+{
+ if ( n!= 0 && m_error != 0) return; // ne change pas une erreur déjà existante
+ m_error = n;
+ m_end = pos;
+}
+
+void CBotCStack::SetError(int n, CBotToken* p)
+{
+ if (m_error) return; // ne change pas une erreur déjà existante
+ 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;
+}
+
+BOOL CBotCStack::NextToken(CBotToken* &p)
+{
+ CBotToken* pp = p;
+
+ p = p->GivNext();
+ if (p!=NULL) return TRUE;
+
+ SetError(TX_ENDOF, pp->GivEnd());
+ return FALSE;
+}
+
+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;
+
+ // revient sur l'élement père
+ 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;
+
+ *pp = pVar; // ajoute à la suite
+
+#ifdef _DEBUG
+ if ( pVar->GivUniqNum() == 0 ) __asm int 3;
+#endif
+}
+
+// test si une variable est déjà définie localement
+
+BOOL CBotCStack::CheckVarLocal(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 TRUE;
+ pp = pp->m_next;
+ }
+ if ( p->m_bBlock ) return FALSE;
+ p = p->m_prev;
+ }
+ return FALSE;
+}
+
+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 )
+ {
+ // pVar = NULL; // l'erreur n'est pas sur un paramètre en particulier
+ SetError( -val.GivType(), p );
+ val.SetType(-val.GivType());
+ return val;
+ }
+ }
+ return val;
+}
+
+// test si un nom de procédure est déjà défini quelque part
+
+BOOL CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
+{
+ CBotString name = pToken->GivString();
+
+ if ( CBotCall::CheckCall(name) ) return TRUE;
+
+ CBotFunction* pp = m_prog->GivFunctions();
+ while ( pp != NULL )
+ {
+ if ( pToken->GivString() == pp->GivName() )
+ {
+ // les paramètres sont-ils exactement les mêmes ?
+ if ( pp->CheckParam( pParam ) )
+ return TRUE;
+ }
+ pp = pp->Next();
+ }
+
+ pp = CBotFunction::m_listPublic;
+ while ( pp != NULL )
+ {
+ if ( pToken->GivString() == pp->GivName() )
+ {
+ // les paramètres sont-ils exactement les mêmes ?
+ if ( pp->CheckParam( pParam ) )
+ return TRUE;
+ }
+ pp = pp->m_nextpublic;
+ }
+
+ return FALSE;
+}
+
diff --git a/src/CBot/CBotString.cpp b/src/CBot/CBotString.cpp
new file mode 100644
index 0000000..bcbe399
--- /dev/null
+++ b/src/CBot/CBotString.cpp
@@ -0,0 +1,588 @@
+/////////////////////////////////////////////////////
+// gestion de chaine
+// basé sur le CString de MFC
+// mais moins complet
+
+#include "CBot.h"
+
+#include <string.h>
+
+HINSTANCE CBotString::m_hInstance = (HINSTANCE)LoadLibrary("Cbot.dll"); // comment le récupérer autrement ??
+
+
+CBotString::CBotString()
+{
+ m_ptr = NULL; // chaine vide
+ m_lg = 0;
+}
+
+CBotString::~CBotString()
+{
+ if (m_ptr != NULL) free(m_ptr);
+}
+
+
+CBotString::CBotString(const char* p)
+{
+ m_lg = lstrlen( p );
+
+ m_ptr = NULL;
+ if (m_lg>0)
+ {
+ m_ptr = (char*)malloc(m_lg+1);
+ lstrcpy(m_ptr, p);
+ }
+}
+
+CBotString::CBotString(const CBotString& srcString)
+{
+ m_lg = srcString.m_lg;
+
+ m_ptr = NULL;
+ if (m_lg>0)
+ {
+ m_ptr = (char*)malloc(m_lg+1);
+ lstrcpy(m_ptr, srcString.m_ptr);
+ }
+}
+
+
+
+
+int CBotString::GivLength()
+{
+ if ( m_ptr == NULL ) return 0;
+ return lstrlen( m_ptr );
+}
+
+
+
+CBotString CBotString::Left(int nCount) const
+{
+ char chaine[2000];
+
+ int i;
+ for (i = 0; i < m_lg && i < nCount && i < 1999; i++)
+ {
+ chaine[i] = m_ptr[i];
+ }
+ chaine[i] = 0 ;
+
+ return CBotString( chaine );
+}
+
+CBotString CBotString::Right(int nCount) const
+{
+ char chaine[2000];
+
+ int i = m_lg - nCount;
+ if ( i < 0 ) i = 0;
+
+ for ( int j = 0; i < m_lg && i < 1999; i++)
+ {
+ chaine[j++] = m_ptr[i];
+ }
+ chaine[j] = 0 ;
+
+ return CBotString( chaine );
+}
+
+CBotString CBotString::Mid(int nFirst, int nCount) const
+{
+ char chaine[2000];
+
+ int i;
+
+ for ( i = nFirst; i < m_lg && i < 1999 && i <= nFirst + nCount; i++)
+ {
+ chaine[i] = m_ptr[i];
+ }
+ chaine[i] = 0 ;
+
+ return CBotString( chaine );
+}
+
+CBotString CBotString::Mid(int nFirst) const
+{
+ char chaine[2000];
+
+ int i;
+
+ for ( i = nFirst; i < m_lg && i < 1999 ; i++)
+ {
+ chaine[i] = m_ptr[i];
+ }
+ chaine[i] = 0 ;
+
+ return CBotString( chaine );
+}
+
+
+int CBotString::Find(const char c)
+{
+ int i;
+ for (i = 0; i < m_lg; i++)
+ {
+ if (m_ptr[i] == c) return i;
+ }
+ return -1;
+}
+
+int CBotString::Find(LPCTSTR lpsz)
+{
+ int i, j;
+ int l = lstrlen(lpsz);
+
+ for (i = 0; i <= m_lg-l; i++)
+ {
+ for (j = 0; j < l; j++)
+ {
+ if (m_ptr[i+j] != lpsz[j]) goto bad;
+ }
+ return i;
+bad:;
+ }
+ return -1;
+}
+
+int CBotString::ReverseFind(const char c)
+{
+ int i;
+ for (i = m_lg-1; i >= 0; i--)
+ {
+ if (m_ptr[i] == c) return i;
+ }
+ return -1;
+}
+
+int CBotString::ReverseFind(LPCTSTR lpsz)
+{
+ int i, j;
+ int l = lstrlen(lpsz);
+
+ for (i = m_lg-l; i >= 0; i--)
+ {
+ for (j = 0; j < l; j++)
+ {
+ if (m_ptr[i+j] != lpsz[j]) goto bad;
+ }
+ return i;
+bad:;
+ }
+ return -1;
+}
+
+CBotString CBotString::Mid(int start, int lg)
+{
+ CBotString res;
+ if (start >= m_lg) return res;
+
+ if ( lg < 0 ) lg = m_lg - start;
+
+ char* p = (char*)malloc(m_lg+1);
+ lstrcpy(p, m_ptr+start);
+ p[lg] = 0;
+
+ res = p;
+ free(p);
+ return res;
+}
+
+void CBotString::MakeUpper()
+{
+ int i;
+
+ for ( i = 0; i < m_lg && i < 1999 ; i++)
+ {
+ char c = m_ptr[i];
+ if ( c >= 'a' && c <= 'z' ) m_ptr[i] = c - 'a' + 'A';
+ }
+}
+
+void CBotString::MakeLower()
+{
+ int i;
+
+ for ( i = 0; i < m_lg && i < 1999 ; i++)
+ {
+ char c = m_ptr[i];
+ if ( c >= 'A' && c <= 'Z' ) m_ptr[i] = c - 'A' + 'a';
+ }
+}
+
+
+
+#define MAXSTRING 256
+
+BOOL CBotString::LoadString(UINT id)
+{
+ char buffer[MAXSTRING];
+
+ m_lg = ::LoadString( m_hInstance, id, buffer, MAXSTRING );
+
+ if (m_ptr != NULL) free(m_ptr);
+
+ m_ptr = NULL;
+ if (m_lg > 0)
+ {
+ m_ptr = (char*)malloc(m_lg+1);
+ lstrcpy(m_ptr, buffer);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+const CBotString& CBotString::operator=(const CBotString& stringSrc)
+{
+ if (m_ptr != NULL) free(m_ptr);
+
+ m_lg = stringSrc.m_lg;
+ m_ptr = NULL;
+
+ if (m_lg > 0)
+ {
+ m_ptr = (char*)malloc(m_lg+1);
+ lstrcpy(m_ptr, stringSrc.m_ptr);
+ }
+
+ return *this;
+}
+
+CBotString operator+(const CBotString& string, LPCTSTR lpsz)
+{
+ CBotString s ( string );
+ s += lpsz;
+ return s;
+}
+
+const CBotString& CBotString::operator+(const CBotString& stringSrc)
+{
+ char* p = (char*)malloc(m_lg+stringSrc.m_lg+1);
+
+ lstrcpy(p, m_ptr);
+ char* pp = p + m_lg;
+ lstrcpy(pp, stringSrc.m_ptr);
+
+ if (m_ptr != NULL) free(m_ptr);
+ m_ptr = p;
+ m_lg += stringSrc.m_lg;
+
+ return *this;
+}
+
+const CBotString& CBotString::operator=(const char ch)
+{
+ if (m_ptr != NULL) free(m_ptr);
+
+ m_lg = 1;
+
+ m_ptr = (char*)malloc(2);
+ m_ptr[0] = ch;
+ m_ptr[1] = 0;
+
+ return *this;
+}
+
+const CBotString& CBotString::operator=(const char* pString)
+{
+ if (m_ptr != NULL) free(m_ptr);
+ m_ptr = NULL;
+
+ if ( pString != NULL )
+ {
+ m_lg = lstrlen(pString);
+
+ if (m_lg != 0)
+ {
+ m_ptr = (char*)malloc(m_lg+1);
+ lstrcpy(m_ptr, pString);
+ }
+ }
+
+ return *this;
+}
+
+
+const CBotString& CBotString::operator+=(const char ch)
+{
+ char* p = (char*)malloc(m_lg+2);
+
+ if (m_ptr!=NULL) lstrcpy(p, m_ptr);
+ p[m_lg++] = ch;
+ p[m_lg] = 0;
+
+ if (m_ptr != NULL) free(m_ptr);
+
+ m_ptr = p;
+
+ return *this;
+}
+
+const CBotString& CBotString::operator+=(const CBotString& str)
+{
+ char* p = (char*)malloc(m_lg+str.m_lg+1);
+
+ lstrcpy(p, m_ptr);
+ char* pp = p + m_lg;
+ lstrcpy(pp, str.m_ptr);
+
+ m_lg = m_lg + str.m_lg;
+
+ if (m_ptr != NULL) free(m_ptr);
+
+ m_ptr = p;
+
+ return *this;
+}
+
+BOOL CBotString::operator==(const CBotString& str)
+{
+ return Compare(str) == 0;
+}
+
+BOOL CBotString::operator==(const char* p)
+{
+ return Compare(p) == 0;
+}
+
+BOOL CBotString::operator!=(const CBotString& str)
+{
+ return Compare(str) != 0;
+}
+
+BOOL CBotString::operator!=(const char* p)
+{
+ return Compare(p) != 0;
+}
+
+BOOL CBotString::operator>(const CBotString& str)
+{
+ return Compare(str) > 0;
+}
+
+BOOL CBotString::operator>(const char* p)
+{
+ return Compare(p) > 0;
+}
+
+BOOL CBotString::operator>=(const CBotString& str)
+{
+ return Compare(str) >= 0;
+}
+
+BOOL CBotString::operator>=(const char* p)
+{
+ return Compare(p) >= 0;
+}
+
+BOOL CBotString::operator<(const CBotString& str)
+{
+ return Compare(str) < 0;
+}
+
+BOOL CBotString::operator<(const char* p)
+{
+ return Compare(p) < 0;
+}
+
+BOOL CBotString::operator<=(const CBotString& str)
+{
+ return Compare(str) <= 0;
+}
+
+BOOL CBotString::operator<=(const char* p)
+{
+ return Compare(p) <= 0;
+}
+
+BOOL CBotString::IsEmpty()
+{
+ return (m_lg == 0);
+}
+
+void CBotString::Empty()
+{
+ if (m_ptr != NULL) free(m_ptr);
+ m_ptr = NULL;
+ m_lg = 0;
+}
+
+static char nilstring[] = {0};
+
+CBotString::operator LPCTSTR() const
+{
+ if (this == NULL || m_ptr == NULL) return nilstring;
+ return m_ptr;
+}
+
+
+int CBotString::Compare(LPCTSTR lpsz) const
+{
+ char* p = m_ptr;
+ if (lpsz == NULL) lpsz = nilstring;
+ if (m_ptr == NULL) p = nilstring;
+ return strcmp(p, lpsz); // wcscmp
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// tableaux de chaines
+
+CBotStringArray::CBotStringArray()
+{
+ m_pData = NULL;
+ m_nSize = m_nMaxSize = 0;
+}
+
+CBotStringArray::~CBotStringArray()
+{
+ SetSize(0); // détruit les données !
+}
+
+
+int CBotStringArray::GivSize()
+{
+ return m_nSize;
+}
+
+void CBotStringArray::Add(const CBotString& str)
+{
+ SetSize(m_nSize+1);
+
+ m_pData[m_nSize-1] = str;
+}
+
+
+///////////////////////////////////////////////////////////////////////
+// routines utilitaires
+
+static inline void ConstructElement(CBotString* pNewData)
+{
+ memset(pNewData, 0, sizeof(CBotString));
+}
+
+static inline void DestructElement(CBotString* pOldData)
+{
+ pOldData->~CBotString();
+}
+
+static inline void CopyElement(CBotString* pSrc, CBotString* pDest)
+{
+ *pSrc = *pDest;
+}
+
+static void ConstructElements(CBotString* pNewData, int nCount)
+{
+ while (nCount--)
+ {
+ ConstructElement(pNewData);
+ pNewData++;
+ }
+}
+
+static void DestructElements(CBotString* pOldData, int nCount)
+{
+ while (nCount--)
+ {
+ DestructElement(pOldData);
+ pOldData++;
+ }
+}
+
+static void CopyElements(CBotString* pDest, CBotString* pSrc, int nCount)
+{
+ while (nCount--)
+ {
+ *pDest = *pSrc;
+ ++pDest;
+ ++pSrc;
+ }
+}
+
+
+
+// sélect la taille du tableau
+
+void CBotStringArray::SetSize(int nNewSize)
+{
+ if (nNewSize == 0)
+ {
+ // shrink to nothing
+
+ DestructElements(m_pData, m_nSize);
+ delete[] (BYTE*)m_pData;
+ m_pData = NULL;
+ m_nSize = m_nMaxSize = 0;
+ }
+ else if (m_pData == NULL)
+ {
+ // create one with exact size
+ m_pData = (CBotString*) new BYTE[nNewSize * sizeof(CBotString)];
+
+ ConstructElements(m_pData, nNewSize);
+
+ m_nSize = m_nMaxSize = nNewSize;
+ }
+ else if (nNewSize <= m_nMaxSize)
+ {
+ // it fits
+ if (nNewSize > m_nSize)
+ {
+ // initialize the new elements
+
+ ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
+
+ }
+
+ else if (m_nSize > nNewSize) // destroy the old elements
+ DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
+
+ m_nSize = nNewSize;
+ }
+ else
+ {
+ // otherwise, grow array
+ int nGrowBy;
+ {
+ // heuristically determine growth when nGrowBy == 0
+ // (this avoids heap fragmentation in many situations)
+ nGrowBy = min(1024, max(4, m_nSize / 8));
+ }
+ int nNewMax;
+ if (nNewSize < m_nMaxSize + nGrowBy)
+ nNewMax = m_nMaxSize + nGrowBy; // granularity
+ else
+ nNewMax = nNewSize; // no slush
+
+ CBotString* pNewData = (CBotString*) new BYTE[nNewMax * sizeof(CBotString)];
+
+ // copy new data from old
+ memcpy(pNewData, m_pData, m_nSize * sizeof(CBotString));
+
+ // construct remaining elements
+ ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
+
+
+ // Ret rid of old stuff (note: no destructors called)
+ delete[] (BYTE*)m_pData;
+ m_pData = pNewData;
+ m_nSize = nNewSize;
+ m_nMaxSize = nNewMax;
+ }
+}
+
+
+CBotString& CBotStringArray::operator[](int nIndex)
+{
+ return ElementAt(nIndex);
+}
+
+CBotString& CBotStringArray::ElementAt(int nIndex)
+{
+ return m_pData[nIndex];
+}
+
+
+
diff --git a/src/CBot/CBotToken.cpp b/src/CBot/CBotToken.cpp
new file mode 100644
index 0000000..4e99cf9
--- /dev/null
+++ b/src/CBot/CBotToken.cpp
@@ -0,0 +1,540 @@
+//////////////////////////////////////////////////////////////////
+// Gestion des Tokens
+// le texte d'un programme est d'abord transformé
+// en une suite de tokens pour facilité l'interprétation
+
+// il faudra traiter le seul cas d'erreur possible
+// qui est un caractère illégal dans une string
+
+
+#include "CBot.h"
+
+CBotStringArray CBotToken::m_ListKeyWords;
+int CBotToken::m_ListIdKeyWords[200];
+CBotStringArray CBotToken::m_ListKeyDefine;
+long CBotToken::m_ListKeyNums[MAXDEFNUM];
+
+// constructeurs
+CBotToken::CBotToken()
+{
+ m_next = NULL;
+ m_prev = NULL;
+
+ m_type = TokenTypVar; // à priori un nom d'une variable
+ m_IdKeyWord = -1;
+}
+
+CBotToken::CBotToken(const CBotToken* pSrc)
+{
+ m_next = NULL;
+ m_prev = NULL;
+
+ m_Text.Empty();
+ m_Sep.Empty();
+
+ m_type = 0;
+ m_IdKeyWord = 0;
+
+ m_start = 0;
+ m_end = 0;
+
+ if ( pSrc != NULL )
+ {
+ m_Text = pSrc->m_Text;
+ m_Sep = pSrc->m_Sep;
+
+ m_type = pSrc->m_type;
+ m_IdKeyWord = pSrc->m_IdKeyWord;
+
+ m_start = pSrc->m_start;
+ m_end = pSrc->m_end;
+ }
+}
+
+CBotToken::CBotToken(CBotString& mot, CBotString& sep, int start, int end)
+{
+ m_Text = mot; // mot trouvé comme token
+ m_Sep = sep; // séparateurs qui suivent
+ m_next = NULL;
+ m_prev = NULL;
+ m_start = start;
+ m_end = end;
+
+ m_type = TokenTypVar; // à priori un nom d'une variable
+ m_IdKeyWord = -1;
+}
+
+CBotToken::CBotToken(const char* mot, const char* sep)
+{
+ m_Text = mot;
+ if ( sep != NULL ) m_Sep = sep;
+ m_next = NULL;
+ m_prev = NULL;
+
+ m_type = TokenTypVar; // à priori un nom d'une variable
+ m_IdKeyWord = -1;
+}
+
+CBotToken::~CBotToken()
+{
+ delete m_next; // récursif
+ m_next = NULL;
+}
+
+void CBotToken::Free()
+{
+ m_ListKeyDefine.SetSize(0);
+}
+
+const CBotToken& CBotToken::operator=(const CBotToken& src)
+{
+ if (m_next != NULL) delete(m_next);
+ m_next = NULL;
+ m_prev = NULL;
+
+ m_Text = src.m_Text;
+ m_Sep = src.m_Sep;
+
+ m_type = src.m_type;
+ m_IdKeyWord = src.m_IdKeyWord;
+
+ m_start = src.m_start;
+ m_end = src.m_end;
+ return *this;
+}
+
+
+int CBotToken::GivType()
+{
+ if (this == NULL) return 0;
+ if (m_type == TokenTypKeyWord) return m_IdKeyWord;
+ return m_type;
+}
+
+long CBotToken::GivIdKey()
+{
+ return m_IdKeyWord;
+}
+
+CBotToken* CBotToken::GivNext()
+{
+ if (this == NULL) return NULL;
+ return m_next;
+}
+
+CBotToken* CBotToken::GivPrev()
+{
+ if (this == NULL) return NULL;
+ return m_prev;
+}
+
+void CBotToken::AddNext(CBotToken* p)
+{
+ CBotToken* n = new CBotToken(p);
+ CBotToken* pt = this;
+
+ while ( pt->m_next != NULL ) pt = pt->m_next;
+
+ pt->m_next = n;
+ n->m_prev = pt;
+}
+
+
+CBotString& CBotToken::GivString()
+{
+ return m_Text;
+}
+
+CBotString& CBotToken::GivSep()
+{
+ return m_Sep;
+}
+
+void CBotToken::SetString(const char* name)
+{
+ m_Text = name;
+}
+
+
+int CBotToken::GivStart()
+{
+ if (this == NULL) return -1;
+ return m_start;
+}
+
+int CBotToken::GivEnd()
+{
+ if (this == NULL) return -1;
+ return m_end;
+}
+
+void CBotToken::SetPos(int start, int end)
+{
+ m_start = start;
+ m_end = end;
+}
+
+BOOL CharInList(const char c, const char* list)
+{
+ int i = 0;
+
+ while (TRUE)
+ {
+ if (c == list[i++]) return TRUE;
+ if (list[i] == 0) return FALSE;
+ }
+}
+
+BOOL Char2InList(const char c, const char cc, const char* list)
+{
+ int i = 0;
+
+ while (TRUE)
+ {
+ if (c == list[i++] &&
+ cc == list[i++]) return TRUE;
+
+ if (list[i] == 0) return FALSE;
+ }
+}
+
+static char* sep1 = " \r\n\t,:()[]{}-+*/=;><!~^|&%.";
+static char* sep2 = " \r\n\t"; // séparateurs pures
+static char* sep3 = ",:()[]{}-+*/=;<>!~^|&%."; // séparateurs opérationnels
+static char* num = "0123456789"; // le point (unique) est testé séparément
+static char* hexnum = "0123456789ABCDEFabcdef";
+static char* nch = "\"\r\n\t"; // refusé dans les chaines
+
+//static char* duo = "+=-=*=/===!=<=>=++--///**/||&&";// les opérateurs doubles
+
+// cherche le prochain token dans une phrase
+// ne doit pas commencer par des séparateurs
+// qui sont pris avec le token précédent
+CBotToken* CBotToken::NextToken(char* &program, int& error, BOOL first)
+{
+ CBotString mot; // le mot trouvé
+ CBotString sep; // les séparateurs qui le suivent
+ char c;
+ BOOL stop = first;
+
+ if (*program == 0) return NULL;
+
+ c = *(program++); // prochain caractère
+
+ if (!first)
+ {
+ mot = c; // construit le mot
+ c = *(program++); // prochain caractère
+
+ // cas particulier pour les chaînes de caractères
+ if ( mot[0] == '\"' )
+ {
+ while (c != 0 && !CharInList(c, nch))
+ {
+ mot += c;
+ c = *(program++); // prochain caractère
+ if ( c == '\\' )
+ {
+ c = *(program++); // prochain caractère
+ if ( c == 'n' ) c = '\n';
+ if ( c == 'r' ) c = '\r';
+ if ( c == 't' ) c = '\t';
+ mot += c;
+ c = *(program++); // prochain caractère
+ }
+ }
+ if ( c == '\"' )
+ {
+ mot += c; // chaîne complète
+ c = *(program++); // prochain caractère
+ }
+ stop = TRUE;
+ }
+
+ // cas particulier pour les nombres
+ if ( CharInList(mot[0], num ))
+ {
+ BOOL bdot = FALSE; // trouvé un point ?
+ BOOL bexp = FALSE; // trouvé un exposant ?
+
+ char* liste = num;
+ if (mot[0] == '0' && c == 'x') // valeur hexadécimale ?
+ {
+ mot += c;
+ c = *(program++); // prochain caractère
+ liste = hexnum;
+ }
+cw:
+ while (c != 0 && CharInList(c, liste))
+ {
+cc: mot += c;
+ c = *(program++); // prochain caractère
+ }
+ if ( liste == num ) // pas pour les exadécimaux
+ {
+ if ( !bdot && c == '.' ) { bdot = TRUE; goto cc; }
+ if ( !bexp && ( c == 'e' || c == 'E' ) )
+ {
+ bexp = TRUE;
+ mot += c;
+ c = *(program++); // prochain caractère
+ if ( c == '-' ||
+ c == '+' ) goto cc;
+ goto cw;
+ }
+
+ }
+ stop = TRUE;
+ }
+
+ if (CharInList(mot[0], sep3)) // un séparateur opérationnel ?
+ {
+ CBotString motc = mot;
+ while (motc += c, c != 0 && GivKeyWords(motc)>0) // cherche l'opérande le plus long possible
+ {
+ mot += c; // construit le mot
+ c = *(program++); // prochain caractère
+ }
+
+ stop = TRUE;
+ }
+ }
+
+
+
+ while (TRUE)
+ {
+ if (stop || c == 0 || CharInList(c, sep1))
+ {
+ if (!first && mot.IsEmpty()) return NULL; // fin de l'analyse
+bis:
+ while (CharInList(c, sep2))
+ {
+ sep += c; // tous les séparateurs qui suivent
+ c = *(program++);
+ }
+ if (c == '/' && *program == '/') // un commentaire dans le tas ?
+ {
+ while( c != '\n' && c != 0 )
+ {
+ sep += c;
+ c = *(program++); // prochain caractère
+ }
+ goto bis;
+ }
+
+ if (c == '/' && *program == '*') // un commentaire dans le tas ?
+ {
+ while( c != 0 && (c != '*' || *program != '/'))
+ {
+ sep += c;
+ c = *(program++); // prochain caractère
+ }
+ if ( c != 0 )
+ {
+ sep += c;
+ c = *(program++); // prochain caractère
+ sep += c;
+ c = *(program++); // prochain caractère
+ }
+ goto bis;
+ }
+
+ program--;
+
+ CBotToken* token = new CBotToken(mot, sep);
+
+ if (CharInList( mot[0], num )) token->m_type = TokenTypNum;
+ if (mot[0] == '\"') token->m_type = TokenTypString;
+ if (first) token->m_type = 0;
+
+ token->m_IdKeyWord = GivKeyWords(mot);
+ if (token->m_IdKeyWord > 0) token->m_type = TokenTypKeyWord;
+ else GivKeyDefNum(mot, token) ; // traite les DefineNum
+
+ return token;
+ }
+
+ mot += c; // construit le mot
+ c = *(program++); // prochain caractère
+ }
+}
+
+CBotToken* CBotToken::CompileTokens(const char* program, int& error)
+{
+ CBotToken *nxt, *prv, *tokenbase;
+ char* p = (char*) program;
+ int pos = 0;
+
+ error = 0;
+ prv = tokenbase = NextToken(p, error, TRUE);
+
+ if (tokenbase == NULL) return NULL;
+
+ tokenbase->m_start = pos;
+ pos += tokenbase->m_Text.GivLength();
+ tokenbase->m_end = pos;
+ pos += tokenbase->m_Sep.GivLength();
+
+ char* pp = p;
+ while (NULL != (nxt = NextToken(p, error)))
+ {
+ prv->m_next = nxt; // ajoute à la suite
+ nxt->m_prev = prv;
+ prv = nxt; // avance
+
+ nxt->m_start = pos;
+/* pos += nxt->m_Text.GivLength(); // la chaîne peut être plus courte (BOA supprimés)
+ nxt->m_end = pos;
+ pos += nxt->m_Sep.GivLength();*/
+ pos += (p - pp); // taille totale
+ nxt->m_end = pos - nxt->m_Sep.GivLength();
+ pp = p;
+ }
+
+ // ajoute un token comme terminateur
+ // ( utile pour avoir le précédent )
+ nxt = new CBotToken();
+ nxt->m_type = 0;
+ prv->m_next = nxt; // ajoute à la suite
+ nxt->m_prev = prv;
+
+ return tokenbase;
+}
+
+void CBotToken::Delete(CBotToken* pToken)
+{
+ delete pToken;
+}
+
+
+// recherche si un mot fait parti des mots clefs
+
+int CBotToken::GivKeyWords(const char* w)
+{
+ int i;
+ int l = m_ListKeyWords.GivSize();
+
+ if (l == 0)
+ {
+ LoadKeyWords(); // prend la liste la première fois
+ l = m_ListKeyWords.GivSize();
+ }
+
+ for (i = 0; i < l; i++)
+ {
+ if (m_ListKeyWords[i] == w) return m_ListIdKeyWords[ i ];
+ }
+
+ return -1;
+}
+
+BOOL CBotToken::GivKeyDefNum(const char* w, CBotToken* &token)
+{
+ int i;
+ int l = m_ListKeyDefine.GivSize();
+
+ for (i = 0; i < l; i++)
+ {
+ if (m_ListKeyDefine[i] == w)
+ {
+ token->m_IdKeyWord = m_ListKeyNums[i];
+ token->m_type = TokenTypDef;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// reprend la liste des mots clefs dans les ressources
+
+void CBotToken::LoadKeyWords()
+{
+ CBotString s;
+ int i, n = 0;
+
+ i = TokenKeyWord;
+ while (s.LoadString(i))
+ {
+ m_ListKeyWords.Add(s);
+ m_ListIdKeyWords[n++] = i++;
+ }
+
+ i = TokenKeyDeclare;
+ while (s.LoadString(i))
+ {
+ m_ListKeyWords.Add(s);
+ m_ListIdKeyWords[n++] = i++;
+ }
+
+
+ i = TokenKeyVal;
+ while (s.LoadString(i))
+ {
+ m_ListKeyWords.Add(s);
+ m_ListIdKeyWords[n++] = i++;
+ }
+
+ i = TokenKeyOp;
+ while (s.LoadString(i))
+ {
+ m_ListKeyWords.Add(s);
+ m_ListIdKeyWords[n++] = i++;
+ }
+}
+
+BOOL CBotToken::DefineNum(const char* name, long val)
+{
+ int i;
+ int l = m_ListKeyDefine.GivSize();
+
+ for (i = 0; i < l; i++)
+ {
+ if (m_ListKeyDefine[i] == name) return FALSE;
+ }
+ if ( i == MAXDEFNUM ) return FALSE;
+
+ m_ListKeyDefine.Add( name );
+ m_ListKeyNums[i] = val;
+ return TRUE;
+}
+
+BOOL IsOfType(CBotToken* &p, int type1, int type2)
+{
+ if (p->GivType() == type1 ||
+ p->GivType() == type2 )
+ {
+ p = p->GivNext();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// idem avec un nombre indéfini d'arguments
+// il faut mettre un zéro comme dernier argument
+BOOL IsOfTypeList(CBotToken* &p, int type1, ...)
+{
+ int i = type1;
+ int max = 20;
+ int type = p->GivType();
+
+ va_list marker;
+ va_start( marker, type1 ); /* Initialize variable arguments. */
+
+ while (TRUE)
+ {
+ if (type == i)
+ {
+ p = p->GivNext();
+ va_end( marker ); /* Reset variable arguments. */
+ return TRUE;
+ }
+ if (--max == 0 || 0 == (i = va_arg( marker, int)))
+ {
+ va_end( marker ); /* Reset variable arguments. */
+ return FALSE;
+ }
+ }
+}
+
diff --git a/src/CBot/CBotToken.h b/src/CBot/CBotToken.h
new file mode 100644
index 0000000..2715dd5
--- /dev/null
+++ b/src/CBot/CBotToken.h
@@ -0,0 +1,23 @@
+////////////////////////////////////////////////////////////////////
+// interpréteur pour le language CBot du jeu COLOBOT
+
+
+// un programme écrit est tout d'abord transformé en une liste de tokens
+// avant d'aborder le compilateur proprement dit
+// par exemple
+// int var = 3 * ( pos.y + x )
+// est décomposé en (chaque ligne est un token)
+// int
+// var
+// =
+// 3
+// *
+// (
+// pos.y
+// +
+// x
+// )
+
+
+extern BOOL IsOfType(CBotToken* &p, int type1, int type2 = -1);
+extern BOOL IsOfTypeList(CBotToken* &p, int type1, ...);
diff --git a/src/CBot/CBotTwoOpExpr ordre inversé.cpp b/src/CBot/CBotTwoOpExpr ordre inversé.cpp
new file mode 100644
index 0000000..65adcba
--- /dev/null
+++ b/src/CBot/CBotTwoOpExpr ordre inversé.cpp
@@ -0,0 +1,302 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 + Opérande2
+// Opérande1 > Opérande2
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotTwoOpExpr::CBotTwoOpExpr()
+{
+ m_leftop =
+ m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
+ name = "CBotTwoOpExpr"; // debug
+}
+
+CBotTwoOpExpr::~CBotTwoOpExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+// type d'opérandes acceptés par les opérations
+#define ENTIER ((1<<CBotTypByte)|(1<<CBotTypShort)|(1<<CBotTypChar)|(1<<CBotTypInt)|(1<<CBotTypLong))
+#define FLOTANT ((1<<CBotTypFloat)|(1<<CBotTypDouble))
+#define BOOLEEN (1<<CBotTypBoolean)
+#define CHAINE (1<<CBotTypString)
+#define CLASSE (1<<CBotTypClass)
+
+// liste des opérations (précéance)
+static int ListOp[] =
+{
+ BOOLEEN, ID_LOG_OR, 0,
+ BOOLEEN, ID_LOG_AND, 0,
+ BOOLEEN|ENTIER, ID_OR, 0,
+ ENTIER, ID_XOR, 0,
+ BOOLEEN|ENTIER, ID_AND, 0,
+ BOOLEEN|ENTIER|FLOTANT, ID_EQ,
+ BOOLEEN|ENTIER|FLOTANT, ID_NE, 0,
+ ENTIER|FLOTANT, ID_HI,
+ ENTIER|FLOTANT, ID_LO,
+ ENTIER|FLOTANT, ID_HS,
+ ENTIER|FLOTANT, ID_LS, 0,
+ ENTIER, ID_SR,
+ ENTIER, ID_SL,
+ ENTIER, ID_ASR, 0,
+ ENTIER|FLOTANT|CHAINE, ID_ADD,
+ ENTIER|FLOTANT, ID_SUB, 0,
+ ENTIER|FLOTANT, ID_MUL,
+ ENTIER|FLOTANT, ID_DIV,
+ ENTIER|FLOTANT, ID_MODULO, 0,
+ 0,
+};
+
+BOOL IsInList( int val, int* list, int& typemasque )
+{
+ while (TRUE)
+ {
+ if ( *list == 0 ) return FALSE;
+ typemasque = *list++;
+ if ( *list++ == val ) return TRUE;
+ }
+}
+
+BOOL TypeOk( int type, int test )
+{
+ while (TRUE)
+ {
+ if ( type == 0 ) return (test & 1);
+ type--; test /= 2;
+ }
+}
+
+// compile une instruction de type A op B
+
+CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
+{
+ int typemasque;
+
+ if ( pOperations == NULL ) pOperations = ListOp;
+ int* pOp = pOperations;
+ while ( *pOp++ != 0 ); // suite de la table
+
+ CBotCStack* pStk = pStack->TokenStack(); // un bout de pile svp
+
+ // cherche des instructions qui peuvent convenir à gauche de l'opération
+ CBotInstr* left = CBotParExpr::Compile( p, pStk ) ; // expression (...) à gauche
+
+ if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
+
+
+ CBotToken* pp = p;
+ int TypeOp = pp->GetType(); // type d'opération
+ p = p->Next(); // saute le token de l'opération
+
+ // cherche des instructions qui peuvent convenir à droite
+
+ CBotInstr* right = (*pOp == 0) ?
+ CBotParExpr::Compile( p, pStk ) : // expression (...) à droite
+ CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A op B à droite
+
+ if (right == NULL) return pStack->Return(left, pStk); // pas d'opérande à droite ?
+
+ // est-ce qu'on a l'opération prévue entre les deux ?
+ if ( IsInList( TypeOp, pOperations, typemasque ) )
+ {
+ CBotTwoOpExpr* inst = new CBotTwoOpExpr(); // élément pour opération
+ inst->SetToken(pp); // mémorise l'opération
+
+ int type1, type2;
+ type1 = pStk->GetType(); // de quel type le premier opérande ?
+
+ inst->m_rightop = right;
+ {
+ // il y a un second opérande acceptable
+
+ type2 = pStk->GetType(); // de quel type le résultat ?
+
+ // quel est le type du résultat ?
+ int TypeRes = MAX( type1, type2 );
+ if (!TypeOk( TypeRes, typemasque )) type1 = 99; // erreur de type
+
+ switch ( TypeOp )
+ {
+ case ID_LOG_OR:
+ case ID_LOG_AND:
+ case ID_EQ:
+ case ID_NE:
+ case ID_HI:
+ case ID_LO:
+ case ID_HS:
+ case ID_LS:
+ TypeRes = CBotTypBoolean;
+ }
+ if ( TypeCompatible (type1, type2) || // les résultats sont-ils compatibles
+ // cas particulier pour les concaténation de chaînes
+ (TypeOp == ID_ADD && (type1 == CBotTypString || type2 == CBotTypString)))
+ {
+ // si ok, enregistre l'opérande dans l'objet
+ inst->m_leftop = left;
+ // met une variable sur la pile pour avoir le type de résultat
+ pStk->SetVar(new CBotVar(NULL, TypeRes));
+ // et rend l'object à qui l'a demandé
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_BAD2TYPE, &inst->m_token);
+ }
+
+ // en cas d'erreur, libère les éléments
+ delete left;
+ delete inst;
+ // et transmet l'erreur qui se trouve sur la pile
+ return pStack->Return(NULL, pStk);
+ }
+
+ // si on n'a pas affaire à une opération + ou -
+ // rend à qui l'a demandé, l'opérande (de gauche) trouvé
+ // à la place de l'objet "addition"
+ return pStack->Return(left, pStk);
+}
+
+
+
+
+// fait l'opération d'addition ou de soustraction
+
+BOOL CBotTwoOpExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pStk1 == EOX ) return TRUE;
+
+
+ // selon la reprise, on peut être dans l'un des 2 états
+
+ if ( pStk1->GetState() == 0 && // 1er état, évalue l'opérande de gauche
+ !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ // passe à l'étape suivante
+ pStk1->SetState(1); // prêt pour la suite
+
+ // pour les OU et ET logique, n'évalue pas la seconde expression si pas nécessaire
+ if ( GetTokenType() == ID_LOG_AND && pStk1->GetVal() == FALSE )
+ {
+ CBotVar* res = CBotVar::Create( NULL, CBotTypBoolean);
+ res->SetValInt(FALSE);
+ pStk1->SetVar(res);
+ return pStack->Return(pStk1); // transmet le résultat
+ }
+ if ( GetTokenType() == ID_LOG_OR && pStk1->GetVal() == TRUE )
+ {
+ CBotVar* res = CBotVar::Create( NULL, CBotTypBoolean);
+ res->SetValInt(TRUE);
+ pStk1->SetVar(res);
+ return pStack->Return(pStk1); // transmet le résultat
+ }
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ // qui se trouve sur la pile, justement.
+
+ CBotStack* pStk2 = pStk1->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // 2e état, évalue l'opérande de droite
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+
+ int type1 = pStk1->GetType(); // de quels types les résultats ?
+ int type2 = pStk2->GetType();
+
+ // crée une variable temporaire pour y mettre le résultat
+ // quel est le type du résultat ?
+ int TypeRes = MAX(type1, type2);
+ switch ( GetTokenType() )
+ {
+ case ID_LOG_OR:
+ case ID_LOG_AND:
+ case ID_EQ:
+ case ID_NE:
+ case ID_HI:
+ case ID_LO:
+ case ID_HS:
+ case ID_LS:
+ TypeRes = CBotTypBoolean;
+ }
+ CBotVar* result = CBotVar::Create( NULL, TypeRes);
+ CBotVar* temp = CBotVar::Create( NULL, MAX(type1, type2) );
+
+ int err = 0;
+ // fait l'opération selon la demande
+ switch (GetTokenType())
+ {
+ case ID_ADD:
+ result->Add(pStk1->GetVar(), pStk2->GetVar()); // additionne
+ break;
+ case ID_SUB:
+ result->Sub(pStk1->GetVar(), pStk2->GetVar()); // soustrait
+ break;
+ case ID_MUL:
+ result->Mul(pStk1->GetVar(), pStk2->GetVar()); // multiplie
+ break;
+ case ID_DIV:
+ err = result->Div(pStk1->GetVar(), pStk2->GetVar());// divise
+ break;
+ case ID_MODULO:
+ err = result->Modulo(pStk1->GetVar(), pStk2->GetVar());// reste de division
+ break;
+ case ID_LO:
+ temp->Lo(pStk1->GetVar(), pStk2->GetVar()); // inférieur
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_HI:
+ temp->Hi(pStk1->GetVar(), pStk2->GetVar()); // supérieur
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_LS:
+ temp->Ls(pStk1->GetVar(), pStk2->GetVar()); // inférieur ou égal
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_HS:
+ temp->Hs(pStk1->GetVar(), pStk2->GetVar()); // supérieur ou égal
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_EQ:
+ temp->Eq(pStk1->GetVar(), pStk2->GetVar()); // égal
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_NE:
+ temp->Ne(pStk1->GetVar(), pStk2->GetVar()); // différent
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_LOG_AND:
+ case ID_AND:
+ result->And(pStk1->GetVar(), pStk2->GetVar()); // ET
+ break;
+ case ID_LOG_OR:
+ case ID_OR:
+ result->Or(pStk1->GetVar(), pStk2->GetVar()); // OU
+ break;
+ case ID_XOR:
+ result->XOr(pStk1->GetVar(), pStk2->GetVar()); // OU exclusif
+ break;
+ case ID_ASR:
+ result->ASR(pStk1->GetVar(), pStk2->GetVar());
+ break;
+ case ID_SR:
+ result->SR(pStk1->GetVar(), pStk2->GetVar());
+ break;
+ case ID_SL:
+ result->SL(pStk1->GetVar(), pStk2->GetVar());
+ break;
+ default:
+ __asm int 3;
+ }
+ delete temp;
+
+ pStk2->SetVar(result); // met le résultat sur la pile
+ if ( err ) pStk2->SetError(err, &m_token); // et l'erreur éventuelle (division par zéro)
+
+ pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
+
diff --git a/src/CBot/CBotTwoOpExpr.cpp b/src/CBot/CBotTwoOpExpr.cpp
new file mode 100644
index 0000000..bc06873
--- /dev/null
+++ b/src/CBot/CBotTwoOpExpr.cpp
@@ -0,0 +1,552 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 + Opérande2
+// Opérande1 > Opérande2
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotTwoOpExpr::CBotTwoOpExpr()
+{
+ m_leftop =
+ m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
+ name = "CBotTwoOpExpr"; // debug
+}
+
+CBotTwoOpExpr::~CBotTwoOpExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+CBotLogicExpr::CBotLogicExpr()
+{
+ m_condition =
+ m_op1 =
+ m_op2 = NULL; // NULL pour pouvoir faire delete sans autre
+ name = "CBotLogicExpr"; // debug
+}
+
+CBotLogicExpr::~CBotLogicExpr()
+{
+ delete m_condition;
+ delete m_op1;
+ delete m_op2;
+}
+
+
+// type d'opérandes acceptés par les opérations
+#define ENTIER ((1<<CBotTypByte)|(1<<CBotTypShort)|(1<<CBotTypChar)|(1<<CBotTypInt)|(1<<CBotTypLong))
+#define FLOTANT ((1<<CBotTypFloat)|(1<<CBotTypDouble))
+#define BOOLEEN (1<<CBotTypBoolean)
+#define CHAINE (1<<CBotTypString)
+#define POINTER (1<<CBotTypPointer)
+#define INSTANCE (1<<CBotTypClass)
+
+// liste des opérations (précéance)
+// type acceptable, opérande
+// le zéro termine un niveau de précéance
+
+static int ListOp[] =
+{
+ BOOLEEN, ID_LOGIC, 0,
+ BOOLEEN, ID_TXT_OR,
+ BOOLEEN, ID_LOG_OR, 0,
+ BOOLEEN, ID_TXT_AND,
+ BOOLEEN, ID_LOG_AND, 0,
+ BOOLEEN|ENTIER, ID_OR, 0,
+ BOOLEEN|ENTIER, ID_XOR, 0,
+ BOOLEEN|ENTIER, ID_AND, 0,
+ BOOLEEN|ENTIER|FLOTANT
+ |CHAINE
+ |POINTER
+ |INSTANCE,ID_EQ,
+ BOOLEEN|ENTIER|FLOTANT
+ |CHAINE
+ |POINTER
+ |INSTANCE,ID_NE, 0,
+ ENTIER|FLOTANT|CHAINE, ID_HI,
+ ENTIER|FLOTANT|CHAINE, ID_LO,
+ ENTIER|FLOTANT|CHAINE, ID_HS,
+ ENTIER|FLOTANT|CHAINE, ID_LS, 0,
+ ENTIER, ID_SR,
+ ENTIER, ID_SL,
+ ENTIER, ID_ASR, 0,
+ ENTIER|FLOTANT|CHAINE, ID_ADD,
+ ENTIER|FLOTANT, ID_SUB, 0,
+ ENTIER|FLOTANT, ID_MUL,
+ ENTIER|FLOTANT, ID_DIV,
+ ENTIER|FLOTANT, ID_MODULO, 0,
+ ENTIER|FLOTANT, ID_POWER, 0,
+ 0,
+};
+
+BOOL IsInList( int val, int* list, int& typemasque )
+{
+ while (TRUE)
+ {
+ if ( *list == 0 ) return FALSE;
+ typemasque = *list++;
+ if ( *list++ == val ) return TRUE;
+ }
+}
+
+BOOL TypeOk( int type, int test )
+{
+ while (TRUE)
+ {
+ if ( type == 0 ) return (test & 1);
+ type--; test /= 2;
+ }
+}
+
+// compile une instruction de type A op B
+
+CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
+{
+ int typemasque;
+
+ if ( pOperations == NULL ) pOperations = ListOp;
+ int* pOp = pOperations;
+ while ( *pOp++ != 0 ); // suite de la table
+
+ CBotCStack* pStk = pStack->TokenStack(); // un bout de pile svp
+
+ // cherche des instructions qui peuvent convenir à gauche de l'opération
+ CBotInstr* left = (*pOp == 0) ?
+ CBotParExpr::Compile( p, pStk ) : // expression (...) à gauche
+ CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A * B à gauche
+
+ if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
+
+ // est-ce qu'on a l'opérande prévu ensuite ?
+ int TypeOp = p->GivType();
+ if ( IsInList( TypeOp, pOperations, typemasque ) )
+ {
+ CBotTypResult type1, type2;
+ type1 = pStk->GivTypResult(); // de quel type le premier opérande ?
+
+ if ( TypeOp == ID_LOGIC ) // cas spécial pour condition ? op1 : op2 ;
+ {
+ if ( !type1.Eq(CBotTypBoolean) )
+ {
+ pStk->SetError( TX_BADTYPE, p);
+ return pStack->Return(NULL, pStk);
+ }
+ CBotLogicExpr* inst = new CBotLogicExpr();
+ inst->m_condition = left;
+
+ p = p->GivNext(); // saute le token de l'opération
+ inst->m_op1 = CBotExpression::Compile(p, pStk);
+ CBotToken* pp = p;
+ if ( inst->m_op1 == NULL || !IsOfType( p, ID_DOTS ) )
+ {
+ pStk->SetError( TX_MISDOTS, p->GivStart());
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ type1 = pStk->GivTypResult();
+
+ inst->m_op2 = CBotExpression::Compile(p, pStk);
+ if ( inst->m_op2 == NULL )
+ {
+ pStk->SetError( TX_ENDOF, p->GivStart() );
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ type2 = pStk->GivTypResult();
+ if (!TypeCompatible(type1, type2))
+ {
+ pStk->SetError( TX_BAD2TYPE, pp );
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ pStk->SetType(type1); // le plus grand des 2 types
+
+ return pStack->Return(inst, pStk);
+ }
+
+ CBotTwoOpExpr* inst = new CBotTwoOpExpr(); // élément pour opération
+ inst->SetToken(p); // mémorise l'opération
+
+
+ p = p->GivNext(); // saute le token de l'opération
+
+ // cherche des instructions qui peuvent convenir à droite
+
+ if ( NULL != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp )) )
+ // expression (...) à droite
+ {
+ // il y a un second opérande acceptable
+
+ type2 = pStk->GivTypResult(); // de quel type le résultat ?
+
+ // quel est le type du résultat ?
+ int TypeRes = MAX( type1.GivType(3), type2.GivType(3) );
+ if ( TypeOp == ID_ADD && type1.Eq(CBotTypString) )
+ {
+ TypeRes = CBotTypString;
+ type2 = type1; // tout type convertible en chaîne
+ }
+ else if ( TypeOp == ID_ADD && type2.Eq(CBotTypString) )
+ {
+ TypeRes = CBotTypString;
+ type1 = type2; // tout type convertible en chaîne
+ }
+ else if (!TypeOk( TypeRes, typemasque )) type1.SetType(99);// erreur de type
+
+ switch ( TypeOp )
+ {
+ case ID_LOG_OR:
+ case ID_LOG_AND:
+ case ID_TXT_OR:
+ case ID_TXT_AND:
+ case ID_EQ:
+ case ID_NE:
+ case ID_HI:
+ case ID_LO:
+ case ID_HS:
+ case ID_LS:
+ TypeRes = CBotTypBoolean;
+ }
+ if ( TypeCompatible (type1, type2, TypeOp ) ) // les résultats sont-ils compatibles
+ {
+ // si ok, enregistre l'opérande dans l'objet
+ inst->m_leftop = left;
+
+ // spécial pour évaluer les opérations de même niveau de gauche à droite
+ while ( IsInList( p->GivType(), pOperations, typemasque ) ) // même(s) opération(s) suit ?
+ {
+ TypeOp = p->GivType();
+ CBotTwoOpExpr* i = new CBotTwoOpExpr(); // élément pour opération
+ i->SetToken(p); // mémorise l'opération
+ i->m_leftop = inst; // opérande de gauche
+ type1 = TypeRes;
+
+ p = p->GivNext(); // avance à la suite
+ i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
+ type2 = pStk->GivTypResult();
+
+ if ( !TypeCompatible (type1, type2, TypeOp) ) // les résultats sont-ils compatibles
+ {
+ pStk->SetError(TX_BAD2TYPE, &i->m_token);
+ delete i;
+ return pStack->Return(NULL, pStk);
+ }
+
+ if ( TypeRes != CBotTypString )
+ TypeRes = MAX(type1.GivType(), type2.GivType());
+ inst = i;
+ }
+
+ CBotTypResult t(type1);
+ t.SetType(TypeRes);
+ // met une variable sur la pile pour avoir le type de résultat
+ pStk->SetVar(CBotVar::Create((CBotToken*)NULL, t));
+
+ // et rend l'object à qui l'a demandé
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_BAD2TYPE, &inst->m_token);
+ }
+
+ // en cas d'erreur, libère les éléments
+ delete left;
+ delete inst;
+ // et transmet l'erreur qui se trouve sur la pile
+ return pStack->Return(NULL, pStk);
+ }
+
+ // si on n'a pas affaire à une opération + ou -
+ // rend à qui l'a demandé, l'opérande (de gauche) trouvé
+ // à la place de l'objet "addition"
+ return pStack->Return(left, pStk);
+}
+
+
+BOOL IsNan(CBotVar* left, CBotVar* right, int* err = NULL)
+{
+ if ( left ->GivInit() > IS_DEF || right->GivInit() > IS_DEF )
+ {
+ if ( err != NULL ) *err = TX_OPNAN ;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// fait l'opération sur 2 opérandes
+
+BOOL CBotTwoOpExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pStk1 == EOX ) return TRUE;
+
+ // selon la reprise, on peut être dans l'un des 2 états
+
+ if ( pStk1->GivState() == 0 ) // 1er état, évalue l'opérande de gauche
+ {
+ if (!m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ // pour les OU et ET logique, n'évalue pas la seconde expression si pas nécessaire
+ if ( (GivTokenType() == ID_LOG_AND || GivTokenType() == ID_TXT_AND ) && pStk1->GivVal() == FALSE )
+ {
+ CBotVar* res = CBotVar::Create( (CBotToken*)NULL, CBotTypBoolean);
+ res->SetValInt(FALSE);
+ pStk1->SetVar(res);
+ return pStack->Return(pStk1); // transmet le résultat
+ }
+ if ( (GivTokenType() == ID_LOG_OR||GivTokenType() == ID_TXT_OR) && pStk1->GivVal() == TRUE )
+ {
+ CBotVar* res = CBotVar::Create( (CBotToken*)NULL, CBotTypBoolean);
+ res->SetValInt(TRUE);
+ pStk1->SetVar(res);
+ return pStack->Return(pStk1); // transmet le résultat
+ }
+
+ // passe à l'étape suivante
+ pStk1->SetState(1); // prêt pour la suite
+ }
+
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ // qui se trouve sur la pile, justement.
+
+ CBotStack* pStk2 = pStk1->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // 2e état, évalue l'opérande de droite
+ if ( pStk2->GivState() == 0 )
+ {
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+ pStk2->IncState();
+ }
+
+ CBotTypResult type1 = pStk1->GivTypResult(); // de quels types les résultats ?
+ CBotTypResult type2 = pStk2->GivTypResult();
+
+ CBotStack* pStk3 = pStk2->AddStack(this); // ajoute un élément à la pile
+ if ( pStk3->IfStep() ) return FALSE; // montre l'opération si step by step
+
+ // crée une variable temporaire pour y mettre le résultat
+ // quel est le type du résultat ?
+ int TypeRes = MAX(type1.GivType(), type2.GivType());
+
+ if ( GivTokenType() == ID_ADD && type1.Eq(CBotTypString) )
+ {
+ TypeRes = CBotTypString;
+ }
+
+ switch ( GivTokenType() )
+ {
+ case ID_LOG_OR:
+ case ID_LOG_AND:
+ case ID_TXT_OR:
+ case ID_TXT_AND:
+ case ID_EQ:
+ case ID_NE:
+ case ID_HI:
+ case ID_LO:
+ case ID_HS:
+ case ID_LS:
+ TypeRes = CBotTypBoolean;
+ break;
+ case ID_DIV:
+ TypeRes = MAX(TypeRes, CBotTypFloat);
+ }
+
+ // crée une variable pour le résultat
+ CBotVar* result = CBotVar::Create( (CBotToken*)NULL, TypeRes);
+
+ // crée une variable pour effectuer le calcul dans le type adapté
+ TypeRes = MAX(type1.GivType(), type2.GivType());
+
+ if ( GivTokenType() == ID_ADD && type1.Eq(CBotTypString) )
+ {
+ TypeRes = CBotTypString;
+ }
+
+ CBotVar* temp;
+
+ if ( TypeRes == CBotTypPointer ) TypeRes = CBotTypNullPointer;
+ if ( TypeRes == CBotTypClass ) temp = CBotVar::Create( (CBotToken*)NULL, CBotTypResult(CBotTypIntrinsic, type1.GivClass() ) );
+ else temp = CBotVar::Create( (CBotToken*)NULL, TypeRes );
+
+ int err = 0;
+ // fait l'opération selon la demande
+ CBotVar* left = pStk1->GivVar();
+ CBotVar* right = pStk2->GivVar();
+
+ switch (GivTokenType())
+ {
+ case ID_ADD:
+ if ( !IsNan(left, right, &err) ) result->Add(left , right); // additionne
+ break;
+ case ID_SUB:
+ if ( !IsNan(left, right, &err) ) result->Sub(left , right); // soustrait
+ break;
+ case ID_MUL:
+ if ( !IsNan(left, right, &err) ) result->Mul(left , right); // multiplie
+ break;
+ case ID_POWER:
+ if ( !IsNan(left, right, &err) ) result->Power(left , right); // puissance
+ break;
+ case ID_DIV:
+ if ( !IsNan(left, right, &err) ) err = result->Div(left , right);// divise
+ break;
+ case ID_MODULO:
+ if ( !IsNan(left, right, &err) ) err = result->Modulo(left , right);// reste de division
+ break;
+ case ID_LO:
+ if ( !IsNan(left, right, &err) )
+ result->SetValInt(temp->Lo(left , right)); // inférieur
+ break;
+ case ID_HI:
+ if ( !IsNan(left, right, &err) )
+ result->SetValInt(temp->Hi(left , right)); // supérieur
+ break;
+ case ID_LS:
+ if ( !IsNan(left, right, &err) )
+ result->SetValInt(temp->Ls(left , right)); // inférieur ou égal
+ break;
+ case ID_HS:
+ if ( !IsNan(left, right, &err) )
+ result->SetValInt(temp->Hs(left , right)); // supérieur ou égal
+ break;
+ case ID_EQ:
+ if ( IsNan(left, right) )
+ result->SetValInt(left->GivInit() == right->GivInit()) ;
+ else
+ result->SetValInt(temp->Eq(left , right)); // égal
+ break;
+ case ID_NE:
+ if ( IsNan(left, right) )
+ result->SetValInt(left ->GivInit() != right->GivInit()) ;
+ else
+ result->SetValInt(temp->Ne(left , right)); // différent
+ break;
+ case ID_TXT_AND:
+ case ID_LOG_AND:
+ case ID_AND:
+ if ( !IsNan(left, right, &err) ) result->And(left , right); // ET
+ break;
+ case ID_TXT_OR:
+ case ID_LOG_OR:
+ case ID_OR:
+ if ( !IsNan(left, right, &err) ) result->Or(left , right); // OU
+ break;
+ case ID_XOR:
+ if ( !IsNan(left, right, &err) ) result->XOr(left , right); // OU exclusif
+ break;
+ case ID_ASR:
+ if ( !IsNan(left, right, &err) ) result->ASR(left , right);
+ break;
+ case ID_SR:
+ if ( !IsNan(left, right, &err) ) result->SR(left , right);
+ break;
+ case ID_SL:
+ if ( !IsNan(left, right, &err) ) result->SL(left , right);
+ break;
+ default:
+ __asm int 3;
+ }
+ delete temp;
+
+ pStk2->SetVar(result); // met le résultat sur la pile
+ if ( err ) pStk2->SetError(err, &m_token); // et l'erreur éventuelle (division par zéro)
+
+// pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk2); // transmet le résultat
+}
+
+void CBotTwoOpExpr::RestoreState(CBotStack* &pStack, BOOL bMain)
+{
+ if ( !bMain ) return;
+ CBotStack* pStk1 = pStack->RestoreStack(this); // ajoute un élément à la pile
+ if ( pStk1 == NULL ) return;
+
+ // selon la reprise, on peut être dans l'un des 2 états
+
+ if ( pStk1->GivState() == 0 ) // 1er état, évalue l'opérande de gauche
+ {
+ m_leftop->RestoreState(pStk1, bMain); // interrompu ici !
+ return;
+ }
+
+ CBotStack* pStk2 = pStk1->RestoreStack(); // ajoute un élément à la pile
+ if ( pStk2 == NULL ) return;
+
+ // 2e état, évalue l'opérande de droite
+ if ( pStk2->GivState() == 0 )
+ {
+ m_rightop->RestoreState(pStk2, bMain); // interrompu ici !
+ return;
+ }
+}
+
+
+BOOL CBotLogicExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pStk1 == EOX ) return TRUE;
+
+ if ( pStk1->GivState() == 0 )
+ {
+ if ( !m_condition->Execute(pStk1) ) return FALSE;
+ if (!pStk1->SetState(1)) return FALSE;
+ }
+
+ if ( pStk1->GivVal() == TRUE )
+ {
+ if ( !m_op1->Execute(pStk1) ) return FALSE;
+ }
+ else
+ {
+ if ( !m_op2->Execute(pStk1) ) return FALSE;
+ }
+
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
+void CBotLogicExpr::RestoreState(CBotStack* &pStack, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pStk1 = pStack->RestoreStack(this); // ajoute un élément à la pile
+ if ( pStk1 == NULL ) return;
+
+ if ( pStk1->GivState() == 0 )
+ {
+ m_condition->RestoreState(pStk1, bMain);
+ return;
+ }
+
+ if ( pStk1->GivVal() == TRUE )
+ {
+ m_op1->RestoreState(pStk1, bMain);
+ }
+ else
+ {
+ m_op2->RestoreState(pStk1, bMain);
+ }
+}
+
+#if 0
+void t()
+{
+ int x,y;
+ 1>0 ? x = 0 : y = 0;
+}
+#endif
+
+#if 01
+void t(BOOL t)
+{
+ int x;
+ x = 1 + t ? 1 : 3 + 4 * 2 ;
+ t ? 0 : "test";
+}
+#endif \ No newline at end of file
diff --git a/src/CBot/CBotVar.cpp b/src/CBot/CBotVar.cpp
new file mode 100644
index 0000000..bd5e889
--- /dev/null
+++ b/src/CBot/CBotVar.cpp
@@ -0,0 +1,2231 @@
+////////////////////////////////////////////////////////////////////
+// Définition pour la classe CBotVar
+// gestion des variables du langage CBot
+
+// on ne crée jamais d'instance de la class mère CBotVar
+
+
+#include "CBot.h"
+#include <math.h>
+#include <stdio.h>
+
+long CBotVar::m_identcpt = 0;
+
+CBotVar::CBotVar( )
+{
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+ m_InitExpr = NULL;
+ m_LimExpr = NULL;
+ m_type = -1;
+ m_binit = FALSE;
+ m_ident = 0;
+ m_bStatic = FALSE;
+ m_mPrivate = 0;
+}
+
+CBotVarInt::CBotVarInt( const CBotToken* name )
+{
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+ m_InitExpr = NULL;
+ m_LimExpr = NULL;
+ m_type = CBotTypInt;
+ m_binit = FALSE;
+ m_bStatic = FALSE;
+ m_mPrivate = 0;
+
+ m_val = 0;
+}
+
+CBotVarFloat::CBotVarFloat( const CBotToken* name )
+{
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+ m_InitExpr = NULL;
+ m_LimExpr = NULL;
+ m_type = CBotTypFloat;
+ m_binit = FALSE;
+ m_bStatic = FALSE;
+ m_mPrivate = 0;
+
+ m_val = 0;
+}
+
+CBotVarString::CBotVarString( const CBotToken* name )
+{
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+ m_InitExpr = NULL;
+ m_LimExpr = NULL;
+ m_type = CBotTypString;
+ m_binit = FALSE;
+ m_bStatic = FALSE;
+ m_mPrivate = 0;
+
+ m_val.Empty();
+}
+
+CBotVarBoolean::CBotVarBoolean( const CBotToken* name )
+{
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+ m_InitExpr = NULL;
+ m_LimExpr = NULL;
+ m_type = CBotTypBoolean;
+ m_binit = FALSE;
+ m_bStatic = FALSE;
+ m_mPrivate = 0;
+
+ m_val = 0;
+}
+
+CBotVarClass* CBotVarClass::m_ExClass = NULL;
+
+CBotVarClass::CBotVarClass( const CBotToken* name, CBotTypResult& type)
+{
+/*
+// int nIdent = 0;
+ InitCBotVarClass( name, type ) //, nIdent );
+}
+
+CBotVarClass::CBotVarClass( const CBotToken* name, CBotTypResult& type) //, int &nIdent )
+{
+ InitCBotVarClass( name, type ); //, nIdent );
+}
+
+void CBotVarClass::InitCBotVarClass( const CBotToken* name, CBotTypResult& type ) //, int &nIdent )
+{*/
+ if ( !type.Eq(CBotTypClass) &&
+ !type.Eq(CBotTypIntrinsic) && // par comodité accepte ces types
+ !type.Eq(CBotTypPointer) &&
+ !type.Eq(CBotTypArrayPointer) &&
+ !type.Eq(CBotTypArrayBody)) __asm int 3;
+
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = OBJECTCREATED;//NULL;
+ m_InitExpr = NULL;
+ m_LimExpr = NULL;
+ m_pVar = NULL;
+ m_type = type;
+ if ( type.Eq(CBotTypArrayPointer) ) m_type.SetType( CBotTypArrayBody );
+ else if ( !type.Eq(CBotTypArrayBody) ) m_type.SetType( CBotTypClass );
+ // type officel pour cet object
+
+ m_pClass = NULL;
+ m_pParent = NULL;
+ m_binit = FALSE;
+ m_bStatic = FALSE;
+ m_mPrivate = 0;
+ m_bConstructor = FALSE;
+ m_CptUse = 0;
+ m_ItemIdent = type.Eq(CBotTypIntrinsic) ? 0 : CBotVar::NextUniqNum();
+
+ // se place tout seul dans la liste
+ if (m_ExClass) m_ExClass->m_ExPrev = this;
+ m_ExNext = m_ExClass;
+ m_ExPrev = NULL;
+ m_ExClass = this;
+
+ CBotClass* pClass = type.GivClass();
+ CBotClass* pClass2 = pClass->GivParent();
+ if ( pClass2 != NULL )
+ {
+ // crée également une instance dans la classe père
+ m_pParent = new CBotVarClass(name, CBotTypResult(type.GivType(),pClass2) ); //, nIdent);
+ }
+
+ SetClass( pClass ); //, nIdent );
+
+}
+
+CBotVarClass::~CBotVarClass( )
+{
+ if ( m_CptUse != 0 )
+ __asm int 3;
+
+ if ( m_pParent ) delete m_pParent;
+ m_pParent = NULL;
+
+ // libère l'objet indirect s'il y a lieu
+// if ( m_Indirect != NULL )
+// m_Indirect->DecrementUse();
+
+ // retire la classe de la liste
+ if ( m_ExPrev ) m_ExPrev->m_ExNext = m_ExNext;
+ else m_ExClass = m_ExNext;
+
+ if ( m_ExNext ) m_ExNext->m_ExPrev = m_ExPrev;
+ m_ExPrev = NULL;
+ m_ExNext = NULL;
+
+ delete m_pVar;
+}
+
+void CBotVarClass::ConstructorSet()
+{
+ m_bConstructor = TRUE;
+}
+
+
+CBotVar::~CBotVar( )
+{
+ delete m_token;
+ delete m_next;
+}
+
+void CBotVar::debug()
+{
+ const char* p = (LPCTSTR) m_token->GivString();
+ CBotString s = (LPCTSTR) GivValString();
+ const char* v = (LPCTSTR) s;
+
+ if ( m_type.Eq(CBotTypClass) )
+ {
+ CBotVar* pv = ((CBotVarClass*)this)->m_pVar;
+ while (pv != NULL)
+ {
+ pv->debug();
+ pv = pv->GivNext();
+ }
+ }
+}
+
+void CBotVar::ConstructorSet()
+{
+ // nop
+}
+
+void CBotVar::SetUserPtr(void* pUser)
+{
+ m_pUserPtr = pUser;
+ if (m_type.Eq(CBotTypPointer) &&
+ ((CBotVarPointer*)this)->m_pVarClass != NULL )
+ ((CBotVarPointer*)this)->m_pVarClass->SetUserPtr(pUser);
+}
+
+void CBotVar::SetIdent(long n)
+{
+ if (m_type.Eq(CBotTypPointer) &&
+ ((CBotVarPointer*)this)->m_pVarClass != NULL )
+ ((CBotVarPointer*)this)->m_pVarClass->SetIdent(n);
+}
+
+void CBotVar::SetUniqNum(long n)
+{
+ m_ident = n;
+
+ if ( n == 0 ) __asm int 3;
+}
+
+long CBotVar::NextUniqNum()
+{
+ if (++m_identcpt < 10000) m_identcpt = 10000;
+ return m_identcpt;
+}
+
+long CBotVar::GivUniqNum()
+{
+ return m_ident;
+}
+
+
+void* CBotVar::GivUserPtr()
+{
+ return m_pUserPtr;
+}
+
+BOOL CBotVar::Save1State(FILE* pf)
+{
+ // cette routine "virtual" ne doit jamais être appellée,
+ // il doit y avoir une routine pour chaque classe fille (CBotVarInt, CBotVarFloat, etc)
+ // ( voir le type dans m_type )
+ __asm int 3;
+ return FALSE;
+}
+
+void CBotVar::Maj(void* pUser, BOOL bContinu)
+{
+/* if (!bContinu && m_pMyThis != NULL)
+ m_pMyThis->Maj(pUser, TRUE);*/
+}
+
+
+// crée une variable selon son type
+
+CBotVar* CBotVar::Create(const CBotToken* name, int type )
+{
+ CBotTypResult t(type);
+ return Create(name, t);
+}
+
+CBotVar* CBotVar::Create(const CBotToken* name, CBotTypResult type)
+{
+ switch (type.GivType())
+ {
+ case CBotTypShort:
+ case CBotTypInt:
+ return new CBotVarInt(name);
+ case CBotTypFloat:
+ return new CBotVarFloat(name);
+ case CBotTypBoolean:
+ return new CBotVarBoolean(name);
+ case CBotTypString:
+ return new CBotVarString(name);
+ case CBotTypPointer:
+ case CBotTypNullPointer:
+ return new CBotVarPointer(name, type);
+ case CBotTypIntrinsic:
+ return new CBotVarClass(name, type);
+
+ case CBotTypClass:
+ // crée une nouvelle instance d'une classe
+ // et retourne le POINTER sur cette instance
+ {
+ CBotVarClass* instance = new CBotVarClass(name, type);
+ CBotVarPointer* pointer = new CBotVarPointer(name, type);
+ pointer->SetPointer( instance );
+ return pointer;
+ }
+
+ case CBotTypArrayPointer:
+ return new CBotVarArray(name, type);
+
+ case CBotTypArrayBody:
+ {
+ CBotVarClass* instance = new CBotVarClass(name, type);
+ CBotVarArray* array = new CBotVarArray(name, type);
+ array->SetPointer( instance );
+
+ CBotVar* pv = array;
+ while (type.Eq(CBotTypArrayBody))
+ {
+ type = type.GivTypElem();
+ pv = ((CBotVarArray*)pv)->GivItem(0, TRUE); // crée au moins l'élément [0]
+ }
+
+ return array;
+ }
+ }
+
+ __asm int 3;
+ return NULL;
+}
+
+CBotVar* CBotVar::Create( CBotVar* pVar )
+{
+ CBotVar* p = Create(pVar->m_token->GivString(), pVar->GivTypResult(2));
+ return p;
+}
+
+
+CBotVar* CBotVar::Create( const char* n, CBotTypResult type)
+{
+ CBotToken name(n);
+
+ switch (type.GivType())
+ {
+ case CBotTypShort:
+ case CBotTypInt:
+ return new CBotVarInt(&name);
+ case CBotTypFloat:
+ return new CBotVarFloat(&name);
+ case CBotTypBoolean:
+ return new CBotVarBoolean(&name);
+ case CBotTypString:
+ return new CBotVarString(&name);
+ case CBotTypPointer:
+ case CBotTypNullPointer:
+ {
+ CBotVarPointer* p = new CBotVarPointer(&name, type);
+// p->SetClass(type.GivClass());
+ return p;
+ }
+ case CBotTypIntrinsic:
+ {
+ CBotVarClass* p = new CBotVarClass(&name, type);
+// p->SetClass(type.GivClass());
+ return p;
+ }
+
+ case CBotTypClass:
+ // crée une nouvelle instance d'une classe
+ // et retourne le POINTER sur cette instance
+ {
+ CBotVarClass* instance = new CBotVarClass(&name, type);
+ CBotVarPointer* pointer = new CBotVarPointer(&name, type);
+ pointer->SetPointer( instance );
+// pointer->SetClass( type.GivClass() );
+ return pointer;
+ }
+
+ case CBotTypArrayPointer:
+ return new CBotVarArray(&name, type);
+
+ case CBotTypArrayBody:
+ {
+ CBotVarClass* instance = new CBotVarClass(&name, type);
+ CBotVarArray* array = new CBotVarArray(&name, type);
+ array->SetPointer( instance );
+
+ CBotVar* pv = array;
+ while (type.Eq(CBotTypArrayBody))
+ {
+ type = type.GivTypElem();
+ pv = ((CBotVarArray*)pv)->GivItem(0, TRUE); // crée au moins l'élément [0]
+ }
+
+ return array;
+ }
+ }
+
+ __asm int 3;
+ return NULL;
+}
+
+CBotVar* CBotVar::Create( const char* name, int type, CBotClass* pClass)
+{
+ CBotToken token( name, "" );
+ CBotVar* pVar = Create( &token, type );
+
+ if ( type == CBotTypPointer && pClass == NULL ) // pointeur "null" ?
+ return pVar;
+
+ if ( type == CBotTypClass || type == CBotTypPointer ||
+ type == CBotTypIntrinsic )
+ {
+ if (pClass == NULL)
+ {
+ delete pVar;
+ return NULL;
+ }
+ pVar->SetClass( pClass );
+ }
+ return pVar;
+}
+
+CBotVar* CBotVar::Create( const char* name, CBotClass* pClass)
+{
+ CBotToken token( name, "" );
+ CBotVar* pVar = Create( &token, CBotTypResult( CBotTypClass, pClass ) );
+// pVar->SetClass( pClass );
+ return pVar;
+}
+
+CBotTypResult CBotVar::GivTypResult(int mode)
+{
+ CBotTypResult r = m_type;
+
+ if ( mode == 1 && m_type.Eq(CBotTypClass) )
+ r.SetType(CBotTypPointer);
+ if ( mode == 2 && m_type.Eq(CBotTypClass) )
+ r.SetType(CBotTypIntrinsic);
+
+ return r;
+}
+
+int CBotVar::GivType(int mode)
+{
+ if ( mode == 1 && m_type.Eq(CBotTypClass) )
+ return CBotTypPointer;
+ if ( mode == 2 && m_type.Eq(CBotTypClass) )
+ return CBotTypIntrinsic;
+ return m_type.GivType();
+}
+
+void CBotVar::SetType(CBotTypResult& type)
+{
+ m_type = type;
+}
+
+
+int CBotVar::GivInit()
+{
+ if ( m_type.Eq(CBotTypClass) ) return IS_DEF; // toujours défini !
+
+ return m_binit;
+}
+
+void CBotVar::SetInit(BOOL bInit)
+{
+ m_binit = bInit;
+ if ( bInit == 2 ) m_binit = IS_DEF; // cas spécial
+
+ if ( m_type.Eq(CBotTypPointer) && bInit == 2 )
+ {
+ CBotVarClass* instance = GivPointer();
+ if ( instance == NULL )
+ {
+ instance = new CBotVarClass(NULL, m_type);
+// instance->SetClass(((CBotVarPointer*)this)->m_pClass);
+ SetPointer(instance);
+ }
+ instance->SetInit(1);
+ }
+
+ if ( m_type.Eq(CBotTypClass) || m_type.Eq(CBotTypIntrinsic) )
+ {
+ CBotVar* p = ((CBotVarClass*)this)->m_pVar;
+ while( p != NULL )
+ {
+ p->SetInit( bInit );
+ p->m_pMyThis = (CBotVarClass*)this;
+ p = p->GivNext();
+ }
+ }
+}
+
+CBotString CBotVar::GivName()
+{
+ return m_token->GivString();
+}
+
+void CBotVar::SetName(const char* name)
+{
+ m_token->SetString(name);
+}
+
+CBotToken* CBotVar::GivToken()
+{
+ return m_token;
+}
+
+CBotVar* CBotVar::GivItem(const char* name)
+{
+ __asm int 3;
+ return NULL;
+}
+
+CBotVar* CBotVar::GivItemRef(int nIdent)
+{
+ __asm int 3;
+ return NULL;
+}
+
+CBotVar* CBotVar::GivItemList()
+{
+ __asm int 3;
+ return NULL;
+}
+
+CBotVar* CBotVar::GivItem(int row, BOOL bGrow)
+{
+ __asm int 3;
+ return NULL;
+}
+
+// dit si une variable appartient à une classe donnée
+BOOL CBotVar::IsElemOfClass(const char* name)
+{
+ CBotClass* pc = NULL;
+
+ if ( m_type.Eq(CBotTypPointer) )
+ {
+ pc = ((CBotVarPointer*)this)->m_pClass;
+ }
+ if ( m_type.Eq(CBotTypClass) )
+ {
+ pc = ((CBotVarClass*)this)->m_pClass;
+ }
+
+ while ( pc != NULL )
+ {
+ if ( pc->GivName() == name ) return TRUE;
+ pc = pc->GivParent();
+ }
+
+ return FALSE;
+}
+
+
+CBotVar* CBotVar::GivStaticVar()
+{
+ // rend le pointeur à la variable si elle est statique
+ if ( m_bStatic == 0 || m_pMyThis == NULL ) return this;
+
+ CBotClass* pClass = m_pMyThis->GivClass();
+ return pClass->GivItem( m_token->GivString() );
+}
+
+
+CBotVar* CBotVar::GivNext()
+{
+ return m_next;
+}
+
+void CBotVar::AddNext(CBotVar* pVar)
+{
+ CBotVar* p = this;
+ while (p->m_next != NULL) p = p->m_next;
+
+ p->m_next = pVar;
+}
+
+void CBotVar::SetVal(CBotVar* var)
+{
+ switch (/*var->*/GivType())
+ {
+ case CBotTypBoolean:
+ SetValInt(var->GivValInt());
+ break;
+ case CBotTypInt:
+ SetValInt(var->GivValInt(), ((CBotVarInt*)var)->m_defnum);
+ break;
+ case CBotTypFloat:
+ SetValFloat(var->GivValFloat());
+ break;
+ case CBotTypString:
+ SetValString(var->GivValString());
+ break;
+ case CBotTypPointer:
+ case CBotTypNullPointer:
+ case CBotTypArrayPointer:
+ SetPointer(var->GivPointer());
+ break;
+ case CBotTypClass:
+ {
+ delete ((CBotVarClass*)this)->m_pVar;
+ ((CBotVarClass*)this)->m_pVar = NULL;
+ Copy(var, FALSE);
+ }
+ break;
+ default:
+ __asm int 3;
+ }
+
+ m_binit = var->m_binit; // copie l'état nan s'il y a
+}
+
+void CBotVar::SetStatic(BOOL bStatic)
+{
+ m_bStatic = bStatic;
+}
+
+void CBotVar::SetPrivate(int mPrivate)
+{
+ m_mPrivate = mPrivate;
+}
+
+BOOL CBotVar::IsStatic()
+{
+ return m_bStatic;
+}
+
+BOOL CBotVar::IsPrivate(int mode)
+{
+ return m_mPrivate >= mode;
+}
+
+int CBotVar::GivPrivate()
+{
+ return m_mPrivate;
+}
+
+
+void CBotVar::SetPointer(CBotVar* pVarClass)
+{
+ __asm int 3;
+}
+
+CBotVarClass* CBotVar::GivPointer()
+{
+ __asm int 3;
+ return NULL;
+}
+
+// toutes ces fonctions doivent être définies dans les classes filles
+// dérivées de la classe CBotVar
+
+int CBotVar::GivValInt()
+{
+ __asm int 3;
+ return 0;
+}
+
+float CBotVar::GivValFloat()
+{
+ __asm int 3;
+ return 0;
+}
+
+void CBotVar::SetValInt(int c, const char* s)
+{
+ __asm int 3;
+}
+
+void CBotVar::SetValFloat(float c)
+{
+ __asm int 3;
+}
+
+void CBotVar::Mul(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::Power(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+int CBotVar::Div(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return 0;
+}
+
+int CBotVar::Modulo(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return 0;
+}
+
+void CBotVar::Add(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::Sub(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+BOOL CBotVar::Lo(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return FALSE;
+}
+
+BOOL CBotVar::Hi(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return FALSE;
+}
+
+BOOL CBotVar::Ls(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return FALSE;
+}
+
+BOOL CBotVar::Hs(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return FALSE;
+}
+
+BOOL CBotVar::Eq(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return FALSE;
+}
+
+BOOL CBotVar::Ne(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+ return FALSE;
+}
+
+void CBotVar::And(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::Or(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::XOr(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::ASR(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::SR(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::SL(CBotVar* left, CBotVar* right)
+{
+ __asm int 3;
+}
+
+void CBotVar::Neg()
+{
+ __asm int 3;
+}
+
+void CBotVar::Not()
+{
+ __asm int 3;
+}
+
+void CBotVar::Inc()
+{
+ __asm int 3;
+}
+void CBotVar::Dec()
+{
+ __asm int 3;
+}
+
+void CBotVar::Copy(CBotVar* pSrc, BOOL bName)
+{
+ __asm int 3;
+}
+
+void CBotVar::SetValString(const char* p)
+{
+ __asm int 3;
+}
+
+CBotString CBotVar::GivValString()
+{
+ __asm int 3;
+ return CBotString();
+}
+
+void CBotVar::SetClass(CBotClass* pClass)
+{
+ __asm int 3;
+}
+
+CBotClass* CBotVar::GivClass()
+{
+ __asm int 3;
+ return NULL;
+}
+
+/*
+void CBotVar::SetIndirection(CBotVar* pVar)
+{
+ // nop, uniquement pour CBotVarPointer::SetIndirection
+}
+*/
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// copie une variable dans une autre
+void CBotVarInt::Copy(CBotVar* pSrc, BOOL bName)
+{
+ CBotVarInt* p = (CBotVarInt*)pSrc;
+
+ if ( bName) *m_token = *p->m_token;
+ m_type = p->m_type;
+ m_val = p->m_val;
+ m_binit = p->m_binit;
+ m_pMyThis = NULL;
+ m_pUserPtr = p->m_pUserPtr;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+
+ m_defnum = p->m_defnum;
+}
+
+
+
+
+void CBotVarInt::SetValInt(int val, const char* defnum)
+{
+ m_val = val;
+ m_binit = TRUE;
+ m_defnum = defnum;
+}
+
+
+
+void CBotVarInt::SetValFloat(float val)
+{
+ m_val = (int)val;
+ m_binit = TRUE;
+}
+
+int CBotVarInt::GivValInt()
+{
+ return m_val;
+}
+
+float CBotVarInt::GivValFloat()
+{
+ return (float)m_val;
+}
+
+CBotString CBotVarInt::GivValString()
+{
+ if ( !m_defnum.IsEmpty() ) return m_defnum;
+
+ CBotString res;
+
+ if ( !m_binit )
+ {
+ res.LoadString(TX_UNDEF);
+ return res;
+ }
+ if ( m_binit == IS_NAN )
+ {
+ res.LoadString(TX_NAN);
+ return res;
+ }
+
+ char buffer[300];
+ sprintf(buffer, "%d", m_val);
+ res = buffer;
+
+ return res;
+}
+
+
+void CBotVarInt::Mul(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() * right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::Power(CBotVar* left, CBotVar* right)
+{
+ m_val = (int) pow( left->GivValInt() , right->GivValInt() );
+ m_binit = TRUE;
+}
+
+int CBotVarInt::Div(CBotVar* left, CBotVar* right)
+{
+ int r = right->GivValInt();
+ if ( r != 0 )
+ {
+ m_val = left->GivValInt() / r;
+ m_binit = TRUE;
+ }
+ return ( r == 0 ? TX_DIVZERO : 0 );
+}
+
+int CBotVarInt::Modulo(CBotVar* left, CBotVar* right)
+{
+ int r = right->GivValInt();
+ if ( r != 0 )
+ {
+ m_val = left->GivValInt() % r;
+ m_binit = TRUE;
+ }
+ return ( r == 0 ? TX_DIVZERO : 0 );
+}
+
+void CBotVarInt::Add(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() + right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::Sub(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() - right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::XOr(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() ^ right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::And(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() & right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::Or(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() | right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::SL(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() << right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::ASR(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() >> right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarInt::SR(CBotVar* left, CBotVar* right)
+{
+ int source = left->GivValInt();
+ int shift = right->GivValInt();
+ if (shift>=1) source &= 0x7fffffff;
+ m_val = source >> shift;
+ m_binit = TRUE;
+}
+
+void CBotVarInt::Neg()
+{
+ m_val = -m_val;
+}
+
+void CBotVarInt::Not()
+{
+ m_val = ~m_val;
+}
+
+void CBotVarInt::Inc()
+{
+ m_val++;
+ m_defnum.Empty();
+}
+
+void CBotVarInt::Dec()
+{
+ m_val--;
+ m_defnum.Empty();
+}
+
+BOOL CBotVarInt::Lo(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() < right->GivValInt();
+}
+
+BOOL CBotVarInt::Hi(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() > right->GivValInt();
+}
+
+BOOL CBotVarInt::Ls(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() <= right->GivValInt();
+}
+
+BOOL CBotVarInt::Hs(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() >= right->GivValInt();
+}
+
+BOOL CBotVarInt::Eq(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() == right->GivValInt();
+}
+
+BOOL CBotVarInt::Ne(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() != right->GivValInt();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// copie une variable dans une autre
+void CBotVarFloat::Copy(CBotVar* pSrc, BOOL bName)
+{
+ CBotVarFloat* p = (CBotVarFloat*)pSrc;
+
+ if (bName) *m_token = *p->m_token;
+ m_type = p->m_type;
+ m_val = p->m_val;
+ m_binit = p->m_binit;
+//- m_bStatic = p->m_bStatic;
+ m_next = NULL;
+ m_pMyThis = NULL;//p->m_pMyThis;
+ m_pUserPtr = p->m_pUserPtr;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+}
+
+
+
+
+void CBotVarFloat::SetValInt(int val, const char* s)
+{
+ m_val = (float)val;
+ m_binit = TRUE;
+}
+
+void CBotVarFloat::SetValFloat(float val)
+{
+ m_val = val;
+ m_binit = TRUE;
+}
+
+int CBotVarFloat::GivValInt()
+{
+ return (int)m_val;
+}
+
+float CBotVarFloat::GivValFloat()
+{
+ return m_val;
+}
+
+CBotString CBotVarFloat::GivValString()
+{
+ CBotString res;
+
+ if ( !m_binit )
+ {
+ res.LoadString(TX_UNDEF);
+ return res;
+ }
+ if ( m_binit == IS_NAN )
+ {
+ res.LoadString(TX_NAN);
+ return res;
+ }
+
+ char buffer[300];
+ sprintf(buffer, "%.2f", m_val);
+ res = buffer;
+
+ return res;
+}
+
+
+void CBotVarFloat::Mul(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValFloat() * right->GivValFloat();
+ m_binit = TRUE;
+}
+
+void CBotVarFloat::Power(CBotVar* left, CBotVar* right)
+{
+ m_val = (float)pow( left->GivValFloat() , right->GivValFloat() );
+ m_binit = TRUE;
+}
+
+int CBotVarFloat::Div(CBotVar* left, CBotVar* right)
+{
+ float r = right->GivValFloat();
+ if ( r != 0 )
+ {
+ m_val = left->GivValFloat() / r;
+ m_binit = TRUE;
+ }
+ return ( r == 0 ? TX_DIVZERO : 0 );
+}
+
+int CBotVarFloat::Modulo(CBotVar* left, CBotVar* right)
+{
+ float r = right->GivValFloat();
+ if ( r != 0 )
+ {
+ m_val = (float)fmod( left->GivValFloat() , r );
+ m_binit = TRUE;
+ }
+ return ( r == 0 ? TX_DIVZERO : 0 );
+}
+
+void CBotVarFloat::Add(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValFloat() + right->GivValFloat();
+ m_binit = TRUE;
+}
+
+void CBotVarFloat::Sub(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValFloat() - right->GivValFloat();
+ m_binit = TRUE;
+}
+
+void CBotVarFloat::Neg()
+{
+ m_val = -m_val;
+}
+
+void CBotVarFloat::Inc()
+{
+ m_val++;
+}
+
+void CBotVarFloat::Dec()
+{
+ m_val--;
+}
+
+
+BOOL CBotVarFloat::Lo(CBotVar* left, CBotVar* right)
+{
+ return left->GivValFloat() < right->GivValFloat();
+}
+
+BOOL CBotVarFloat::Hi(CBotVar* left, CBotVar* right)
+{
+ return left->GivValFloat() > right->GivValFloat();
+}
+
+BOOL CBotVarFloat::Ls(CBotVar* left, CBotVar* right)
+{
+ return left->GivValFloat() <= right->GivValFloat();
+}
+
+BOOL CBotVarFloat::Hs(CBotVar* left, CBotVar* right)
+{
+ return left->GivValFloat() >= right->GivValFloat();
+}
+
+BOOL CBotVarFloat::Eq(CBotVar* left, CBotVar* right)
+{
+ return left->GivValFloat() == right->GivValFloat();
+}
+
+BOOL CBotVarFloat::Ne(CBotVar* left, CBotVar* right)
+{
+ return left->GivValFloat() != right->GivValFloat();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// copie une variable dans une autre
+void CBotVarBoolean::Copy(CBotVar* pSrc, BOOL bName)
+{
+ CBotVarBoolean* p = (CBotVarBoolean*)pSrc;
+
+ if (bName) *m_token = *p->m_token;
+ m_type = p->m_type;
+ m_val = p->m_val;
+ m_binit = p->m_binit;
+//- m_bStatic = p->m_bStatic;
+ m_next = NULL;
+ m_pMyThis = NULL;//p->m_pMyThis;
+ m_pUserPtr = p->m_pUserPtr;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+}
+
+
+
+
+void CBotVarBoolean::SetValInt(int val, const char* s)
+{
+ m_val = (BOOL)val;
+ m_binit = TRUE;
+}
+
+void CBotVarBoolean::SetValFloat(float val)
+{
+ m_val = (BOOL)val;
+ m_binit = TRUE;
+}
+
+int CBotVarBoolean::GivValInt()
+{
+ return m_val;
+}
+
+float CBotVarBoolean::GivValFloat()
+{
+ return (float)m_val;
+}
+
+CBotString CBotVarBoolean::GivValString()
+{
+ CBotString ret;
+
+ CBotString res;
+
+ if ( !m_binit )
+ {
+ res.LoadString(TX_UNDEF);
+ return res;
+ }
+ if ( m_binit == IS_NAN )
+ {
+ res.LoadString(TX_NAN);
+ return res;
+ }
+
+ ret.LoadString( m_val > 0 ? ID_TRUE : ID_FALSE );
+ return ret;
+}
+
+void CBotVarBoolean::And(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() && right->GivValInt();
+ m_binit = TRUE;
+}
+void CBotVarBoolean::Or(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() || right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarBoolean::XOr(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValInt() ^ right->GivValInt();
+ m_binit = TRUE;
+}
+
+void CBotVarBoolean::Not()
+{
+ m_val = m_val ? FALSE : TRUE ;
+}
+
+BOOL CBotVarBoolean::Eq(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() == right->GivValInt();
+}
+
+BOOL CBotVarBoolean::Ne(CBotVar* left, CBotVar* right)
+{
+ return left->GivValInt() != right->GivValInt();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// copie une variable dans une autre
+void CBotVarString::Copy(CBotVar* pSrc, BOOL bName)
+{
+ CBotVarString* p = (CBotVarString*)pSrc;
+
+ if (bName) *m_token = *p->m_token;
+ m_type = p->m_type;
+ m_val = p->m_val;
+ m_binit = p->m_binit;
+//- m_bStatic = p->m_bStatic;
+ m_next = NULL;
+ m_pMyThis = NULL;//p->m_pMyThis;
+ m_pUserPtr = p->m_pUserPtr;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+}
+
+
+void CBotVarString::SetValString(const char* p)
+{
+ m_val = p;
+ m_binit = TRUE;
+}
+
+CBotString CBotVarString::GivValString()
+{
+ if ( !m_binit )
+ {
+ CBotString res;
+ res.LoadString(TX_UNDEF);
+ return res;
+ }
+ if ( m_binit == IS_NAN )
+ {
+ CBotString res;
+ res.LoadString(TX_NAN);
+ return res;
+ }
+
+ return m_val;
+}
+
+
+void CBotVarString::Add(CBotVar* left, CBotVar* right)
+{
+ m_val = left->GivValString() + right->GivValString();
+ m_binit = TRUE;
+}
+
+BOOL CBotVarString::Eq(CBotVar* left, CBotVar* right)
+{
+ return (left->GivValString() == right->GivValString());
+}
+
+BOOL CBotVarString::Ne(CBotVar* left, CBotVar* right)
+{
+ return (left->GivValString() != right->GivValString());
+}
+
+
+BOOL CBotVarString::Lo(CBotVar* left, CBotVar* right)
+{
+ return (left->GivValString() == right->GivValString());
+}
+
+BOOL CBotVarString::Hi(CBotVar* left, CBotVar* right)
+{
+ return (left->GivValString() == right->GivValString());
+}
+
+BOOL CBotVarString::Ls(CBotVar* left, CBotVar* right)
+{
+ return (left->GivValString() == right->GivValString());
+}
+
+BOOL CBotVarString::Hs(CBotVar* left, CBotVar* right)
+{
+ return (left->GivValString() == right->GivValString());
+}
+
+
+////////////////////////////////////////////////////////////////
+
+// copie une variable dans une autre
+void CBotVarClass::Copy(CBotVar* pSrc, BOOL bName)
+{
+ pSrc = pSrc->GivPointer(); // si source donné par un pointeur
+
+ if ( pSrc->GivType() != CBotTypClass )
+ __asm int 3;
+
+ CBotVarClass* p = (CBotVarClass*)pSrc;
+
+ if (bName) *m_token = *p->m_token;
+
+ m_type = p->m_type;
+ m_binit = p->m_binit;
+//- m_bStatic = p->m_bStatic;
+ m_pClass = p->m_pClass;
+ if ( p->m_pParent )
+ {
+__asm int 3; "que faire du pParent";
+ }
+
+// m_next = NULL;
+ m_pUserPtr = p->m_pUserPtr;
+ m_pMyThis = NULL;//p->m_pMyThis;
+ m_ItemIdent = p->m_ItemIdent;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+
+ delete m_pVar;
+ m_pVar = NULL;
+
+ CBotVar* pv = p->m_pVar;
+ while( pv != NULL )
+ {
+ CBotVar* pn = CBotVar::Create(pv);
+ pn->Copy( pv );
+ if ( m_pVar == NULL ) m_pVar = pn;
+ else m_pVar->AddNext(pn);
+
+ pv = pv->GivNext();
+ }
+}
+
+void CBotVarClass::SetItemList(CBotVar* pVar)
+{
+ delete m_pVar;
+ m_pVar = pVar; // remplace le pointeur existant
+}
+
+void CBotVarClass::SetIdent(long n)
+{
+ m_ItemIdent = n;
+}
+
+void CBotVarClass::SetClass(CBotClass* pClass)//, int &nIdent)
+{
+ m_type.m_pClass = pClass;
+
+ if ( m_pClass == pClass ) return;
+
+ m_pClass = pClass;
+
+ // initialise les variables associées à cette classe
+ delete m_pVar;
+ m_pVar = NULL;
+
+ if (pClass == NULL) return;
+
+ CBotVar* pv = pClass->GivVar(); // premier de la liste
+ while ( pv != NULL )
+ {
+ // cherche les dimensions max du tableau
+ CBotInstr* p = pv->m_LimExpr; // les différentes formules
+ if ( p != NULL )
+ {
+ CBotStack* pile = CBotStack::FirstStack(); // une pile indépendante
+ int n = 0;
+ int max[100];
+
+ while (p != NULL)
+ {
+ while( pile->IsOk() && !p->Execute(pile) ) ; // calcul de la taille sans interruptions
+ CBotVar* v = pile->GivVar(); // résultat
+ max[n] = v->GivValInt(); // valeur
+ n++;
+ p = p->GivNext3();
+ }
+ while (n<100) max[n++] = 0;
+
+ pv->m_type.SetArray( max ); // mémorise les limitations
+ pile->Delete();
+ }
+
+ CBotVar* pn = CBotVar::Create( pv ); // une copie
+ pn->SetStatic(pv->IsStatic());
+ pn->SetPrivate(pv->GivPrivate());
+
+ if ( pv->m_InitExpr != NULL ) // expression pour l'initialisation ?
+ {
+#if STACKMEM
+ CBotStack* pile = CBotStack::FirstStack(); // une pile indépendante
+
+ while(pile->IsOk() && !pv->m_InitExpr->Execute(pile, pn)); // évalue l'expression sans timer
+
+ pile->Delete();
+#else
+ CBotStack* pile = new CBotStack(NULL); // une pile indépendante
+ while(!pv->m_InitExpr->Execute(pile)); // évalue l'expression sans timer
+ pn->SetVal( pile->GivVar() ) ;
+ delete pile;
+#endif
+ }
+
+// pn->SetUniqNum(CBotVar::NextUniqNum()); // numérote les éléments
+ pn->SetUniqNum(pv->GivUniqNum()); //++nIdent
+ pn->m_pMyThis = this;
+
+ if ( m_pVar == NULL) m_pVar = pn;
+ else m_pVar->AddNext( pn );
+ pv = pv->GivNext();
+ }
+}
+
+CBotClass* CBotVarClass::GivClass()
+{
+ return m_pClass;
+}
+
+
+void CBotVarClass::Maj(void* pUser, BOOL bContinu)
+{
+/* if (!bContinu && m_pMyThis != NULL)
+ m_pMyThis->Maj(pUser, TRUE);*/
+
+ // une routine de mise à jour existe-elle ?
+
+ if ( m_pClass->m_rMaj == NULL ) return;
+
+ // récupère le pointeur user selon la classe
+ // ou selon le paramètre passé au CBotProgram::Run()
+
+ if ( m_pUserPtr != NULL) pUser = m_pUserPtr;
+ if ( pUser == OBJECTDELETED ||
+ pUser == OBJECTCREATED ) return;
+ m_pClass->m_rMaj( this, pUser );
+}
+
+CBotVar* CBotVarClass::GivItem(const char* name)
+{
+ CBotVar* p = m_pVar;
+
+ while ( p != NULL )
+ {
+ if ( p->GivName() == name ) return p;
+ p = p->GivNext();
+ }
+
+ if ( m_pParent != NULL ) return m_pParent->GivItem(name);
+ return NULL;
+}
+
+CBotVar* CBotVarClass::GivItemRef(int nIdent)
+{
+ CBotVar* p = m_pVar;
+
+ while ( p != NULL )
+ {
+ if ( p->GivUniqNum() == nIdent ) return p;
+ p = p->GivNext();
+ }
+
+ if ( m_pParent != NULL ) return m_pParent->GivItemRef(nIdent);
+ return NULL;
+}
+
+// pour la gestion d'un tableau
+// bExtend permet d'agrandir le tableau, mais pas au dela de la taille fixée par SetArray()
+
+CBotVar* CBotVarClass::GivItem(int n, BOOL bExtend)
+{
+ CBotVar* p = m_pVar;
+
+ if ( n < 0 ) return NULL;
+ if ( n > MAXARRAYSIZE ) return NULL;
+
+ if ( m_type.GivLimite() >= 0 && n >= m_type.GivLimite() ) return NULL;
+
+ if ( p == NULL && bExtend )
+ {
+ p = CBotVar::Create("", m_type.GivTypElem());
+ m_pVar = p;
+ }
+
+ if ( n == 0 ) return p;
+
+ while ( n-- > 0 )
+ {
+ if ( p->m_next == NULL )
+ {
+ if ( bExtend ) p->m_next = CBotVar::Create("", m_type.GivTypElem());
+ if ( p->m_next == NULL ) return NULL;
+ }
+ p = p->m_next;
+ }
+
+ return p;
+}
+
+CBotVar* CBotVarClass::GivItemList()
+{
+ return m_pVar;
+}
+
+
+CBotString CBotVarClass::GivValString()
+{
+// if ( m_Indirect != NULL) return m_Indirect->GivValString();
+
+ CBotString res;
+
+ if ( m_pClass != NULL ) // pas utilisé pour un array
+ {
+ res = m_pClass->GivName() + "( ";
+
+ CBotVarClass* my = this;
+ while ( my != NULL )
+ {
+ CBotVar* pv = my->m_pVar;
+ while ( pv != NULL )
+ {
+ res += pv->GivName() + "=";
+
+ if ( pv->IsStatic() )
+ {
+ CBotVar* pvv = my->m_pClass->GivItem(pv->GivName());
+ res += pvv->GivValString();
+ }
+ else
+ {
+ res += pv->GivValString();
+ }
+ pv = pv->GivNext();
+ if ( pv != NULL ) res += ", ";
+ }
+ my = my->m_pParent;
+ if ( my != NULL )
+ {
+ res += ") extends ";
+ res += my->m_pClass->GivName();
+ res += " (";
+ }
+ }
+ }
+ else
+ {
+ res = "( ";
+
+ CBotVar* pv = m_pVar;
+ while ( pv != NULL )
+ {
+ res += pv->GivValString();
+ if ( pv->GivNext() != NULL ) res += ", ";
+ pv = pv->GivNext();
+ }
+ }
+
+ res += " )";
+ return res;
+}
+
+void CBotVarClass::IncrementUse()
+{
+ m_CptUse++;
+}
+
+void CBotVarClass::DecrementUse()
+{
+ m_CptUse--;
+ if ( m_CptUse == 0 )
+ {
+ // s'il y en a un, appel le destructeur
+ // mais seulement si un constructeur avait été appelé.
+ if ( m_bConstructor )
+ {
+ m_CptUse++; // ne revient pas dans le destructeur
+
+ // m_error est static dans le stack
+ // sauve la valeur pour la remettre ensuite
+ int err, start, end;
+ CBotStack* pile = NULL;
+ err = pile->GivError(start,end); // pile == NULL ça ne derange pas !!
+
+ pile = CBotStack::FirstStack(); // efface l'erreur
+ CBotVar* ppVars[1];
+ ppVars[0] = NULL;
+
+ CBotVar* pThis = CBotVar::Create("this", CBotTypNullPointer);
+ pThis->SetPointer(this);
+ CBotVar* pResult = NULL;
+
+ CBotString nom = "~" + m_pClass->GivName();
+ long ident = 0;
+
+ while ( pile->IsOk() && !m_pClass->ExecuteMethode(ident, nom, pThis, ppVars, pResult, pile, NULL)) ; // attend la fin
+
+ pile->ResetError(err, start,end);
+
+ pile->Delete();
+ delete pThis;
+ m_CptUse--;
+ }
+
+ delete this; // s'auto-détruit !!
+ }
+}
+
+CBotVarClass* CBotVarClass::GivPointer()
+{
+ return this;
+}
+
+
+// trouve une instance selon son numéro unique
+
+CBotVarClass* CBotVarClass::Find(long id)
+{
+ CBotVarClass* p = m_ExClass;
+
+ while ( p != NULL )
+ {
+ if ( p->m_ItemIdent == id ) return p;
+ p = p->m_ExNext;
+ }
+
+ return NULL;
+}
+
+BOOL CBotVarClass::Eq(CBotVar* left, CBotVar* right)
+{
+ CBotVar* l = left->GivItemList();
+ CBotVar* r = right->GivItemList();
+
+ while ( l != NULL && r != NULL )
+ {
+ if ( l->Ne(l, r) ) return FALSE;
+ l = l->GivNext();
+ r = r->GivNext();
+ }
+
+ // devrait toujours arrivé simultanément au bout (mêmes classes)
+ return l == r;
+}
+
+BOOL CBotVarClass::Ne(CBotVar* left, CBotVar* right)
+{
+ CBotVar* l = left->GivItemList();
+ CBotVar* r = right->GivItemList();
+
+ while ( l != NULL && r != NULL )
+ {
+ if ( l->Ne(l, r) ) return TRUE;
+ l = l->GivNext();
+ r = r->GivNext();
+ }
+
+ // devrait toujours arrivé simultanément au bout (mêmes classes)
+ return l != r;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// gestion des tableaux de variables
+
+CBotVarArray::CBotVarArray(const CBotToken* name, CBotTypResult& type )
+{
+ if ( !type.Eq(CBotTypArrayPointer) &&
+ !type.Eq(CBotTypArrayBody)) __asm int 3;
+
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+
+ m_type = type;
+ m_type.SetType(CBotTypArrayPointer);
+ m_binit = FALSE;
+
+ m_pInstance = NULL; // la liste des éléments du tableau
+}
+
+CBotVarArray::~CBotVarArray()
+{
+ if ( m_pInstance != NULL ) m_pInstance->DecrementUse(); // une référence en moins
+}
+
+// copie une variable dans une autre
+void CBotVarArray::Copy(CBotVar* pSrc, BOOL bName)
+{
+ if ( pSrc->GivType() != CBotTypArrayPointer )
+ __asm int 3;
+
+ CBotVarArray* p = (CBotVarArray*)pSrc;
+
+ if ( bName) *m_token = *p->m_token;
+ m_type = p->m_type;
+ m_pInstance = p->GivPointer();
+
+ if ( m_pInstance != NULL )
+ m_pInstance->IncrementUse(); // une référence en plus
+
+ m_binit = p->m_binit;
+//- m_bStatic = p->m_bStatic;
+ m_pMyThis = NULL;//p->m_pMyThis;
+ m_pUserPtr = p->m_pUserPtr;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+}
+
+void CBotVarArray::SetPointer(CBotVar* pVarClass)
+{
+ m_binit = TRUE; // init, même sur un pointeur null
+
+ if ( m_pInstance == pVarClass) return; // spécial, ne pas décrémenter et réincrémenter
+ // car le décrément peut détruire l'object
+
+ if ( pVarClass != NULL )
+ {
+ if ( pVarClass->GivType() == CBotTypArrayPointer )
+ pVarClass = pVarClass->GivPointer(); // le vrai pointeur à l'objet
+
+ if ( !pVarClass->m_type.Eq(CBotTypClass) &&
+ !pVarClass->m_type.Eq(CBotTypArrayBody))
+ __asm int 3;
+
+ ((CBotVarClass*)pVarClass)->IncrementUse(); // une référence en plus
+ }
+
+ if ( m_pInstance != NULL ) m_pInstance->DecrementUse();
+ m_pInstance = (CBotVarClass*)pVarClass;
+}
+
+
+CBotVarClass* CBotVarArray::GivPointer()
+{
+ if ( m_pInstance == NULL ) return NULL;
+ return m_pInstance->GivPointer();
+}
+
+CBotVar* CBotVarArray::GivItem(int n, BOOL bExtend)
+{
+ if ( m_pInstance == NULL )
+ {
+ if ( !bExtend ) return NULL;
+ // crée une instance pour le tableau
+
+ CBotVarClass* instance = new CBotVarClass(NULL, m_type);
+ SetPointer( instance );
+ }
+ return m_pInstance->GivItem(n, bExtend);
+}
+
+CBotVar* CBotVarArray::GivItemList()
+{
+ if ( m_pInstance == NULL) return NULL;
+ return m_pInstance->GivItemList();
+}
+
+CBotString CBotVarArray::GivValString()
+{
+ if ( m_pInstance == NULL ) return ( CBotString( "Null pointer" ) ) ;
+ return m_pInstance->GivValString();
+}
+
+BOOL CBotVarArray::Save1State(FILE* pf)
+{
+ if ( !WriteType(pf, m_type) ) return FALSE;
+ return SaveVar(pf, m_pInstance); // sauve l'instance qui gère le tableau
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// gestion des pointeurs à une instance donnée
+
+CBotVarPointer::CBotVarPointer(const CBotToken* name, CBotTypResult& type )
+{
+ if ( !type.Eq(CBotTypPointer) &&
+ !type.Eq(CBotTypNullPointer) &&
+ !type.Eq(CBotTypClass) && // par commodité accepte Class et Intrinsic
+ !type.Eq(CBotTypIntrinsic) ) __asm int 3;
+
+ m_token = new CBotToken(name);
+ m_next = NULL;
+ m_pMyThis = NULL;
+ m_pUserPtr = NULL;
+
+ m_type = type;
+ if ( !type.Eq(CBotTypNullPointer) )
+ m_type.SetType(CBotTypPointer); // quoi qu'il en soit, c'est un pointeur
+ m_binit = FALSE;
+ m_pClass = NULL;
+ m_pVarClass = NULL; // sera défini par un SetPointer()
+
+ SetClass(type.GivClass() );
+}
+
+CBotVarPointer::~CBotVarPointer()
+{
+ if ( m_pVarClass != NULL ) m_pVarClass->DecrementUse(); // une référence en moins
+}
+
+
+void CBotVarPointer::Maj(void* pUser, BOOL bContinu)
+{
+/* if ( !bContinu && m_pMyThis != NULL )
+ m_pMyThis->Maj(pUser, FALSE);*/
+
+ if ( m_pVarClass != NULL) m_pVarClass->Maj(pUser, FALSE);
+}
+
+CBotVar* CBotVarPointer::GivItem(const char* name)
+{
+ if ( m_pVarClass == NULL) // pas d'instance existant ?
+ return m_pClass->GivItem(name); // rend le pointeur dans la classe elle-même
+
+ return m_pVarClass->GivItem(name);
+}
+
+CBotVar* CBotVarPointer::GivItemRef(int nIdent)
+{
+ if ( m_pVarClass == NULL) // pas d'instance existant ?
+ return m_pClass->GivItemRef(nIdent);// rend le pointeur dans la classe elle-même
+
+ return m_pVarClass->GivItemRef(nIdent);
+}
+
+CBotVar* CBotVarPointer::GivItemList()
+{
+ if ( m_pVarClass == NULL) return NULL;
+ return m_pVarClass->GivItemList();
+}
+
+CBotString CBotVarPointer::GivValString()
+{
+ CBotString s = "Pointer to ";
+ if ( m_pVarClass == NULL ) s = "Null pointer" ;
+ else s += m_pVarClass->GivValString();
+ return s;
+}
+
+
+void CBotVarPointer::ConstructorSet()
+{
+ if ( m_pVarClass != NULL) m_pVarClass->ConstructorSet();
+}
+
+// initialise le pointeur vers l'instance d'une classe
+
+void CBotVarPointer::SetPointer(CBotVar* pVarClass)
+{
+ m_binit = TRUE; // init, même sur un pointeur null
+
+ if ( m_pVarClass == pVarClass) return; // spécial, ne pas décrémenter et réincrémenter
+ // car le décrément peut détruire l'object
+
+ if ( pVarClass != NULL )
+ {
+ if ( pVarClass->GivType() == CBotTypPointer )
+ pVarClass = pVarClass->GivPointer(); // le vrai pointeur à l'objet
+
+// if ( pVarClass->GivType() != CBotTypClass )
+ if ( !pVarClass->m_type.Eq(CBotTypClass) )
+ __asm int 3;
+
+ ((CBotVarClass*)pVarClass)->IncrementUse(); // une référence en plus
+ m_pClass = ((CBotVarClass*)pVarClass)->m_pClass;
+ m_pUserPtr = pVarClass->m_pUserPtr; // pas vraiment indispensable
+ m_type = CBotTypResult(CBotTypPointer, m_pClass); // un pointeur de quel genre
+ }
+
+ if ( m_pVarClass != NULL ) m_pVarClass->DecrementUse();
+ m_pVarClass = (CBotVarClass*)pVarClass;
+
+}
+
+CBotVarClass* CBotVarPointer::GivPointer()
+{
+ if ( m_pVarClass == NULL ) return NULL;
+ return m_pVarClass->GivPointer();
+}
+
+void CBotVarPointer::SetIdent(long n)
+{
+ if ( m_pVarClass == NULL ) return;
+ m_pVarClass->SetIdent( n );
+}
+
+long CBotVarPointer::GivIdent()
+{
+ if ( m_pVarClass == NULL ) return 0;
+ return m_pVarClass->m_ItemIdent;
+}
+
+
+void CBotVarPointer::SetClass(CBotClass* pClass)
+{
+// int nIdent = 0;
+ m_type.m_pClass = m_pClass = pClass;
+ if ( m_pVarClass != NULL ) m_pVarClass->SetClass(pClass); //, nIdent);
+}
+
+CBotClass* CBotVarPointer::GivClass()
+{
+ if ( m_pVarClass != NULL ) return m_pVarClass->GivClass();
+
+ return m_pClass;
+}
+
+
+BOOL CBotVarPointer::Save1State(FILE* pf)
+{
+ if ( m_pClass )
+ {
+ if (!WriteString(pf, m_pClass->GivName())) return FALSE; // nom de la classe
+ }
+ else
+ {
+ if (!WriteString(pf, "")) return FALSE;
+ }
+
+ if (!WriteLong(pf, GivIdent())) return FALSE; // la référence unique
+
+ // sauve aussi une copie de l'instance
+ return SaveVar(pf, GivPointer());
+}
+
+// copie une variable dans une autre
+void CBotVarPointer::Copy(CBotVar* pSrc, BOOL bName)
+{
+ if ( pSrc->GivType() != CBotTypPointer &&
+ pSrc->GivType() != CBotTypNullPointer)
+ __asm int 3;
+
+ CBotVarPointer* p = (CBotVarPointer*)pSrc;
+
+ if ( bName) *m_token = *p->m_token;
+ m_type = p->m_type;
+// m_pVarClass = p->m_pVarClass;
+ m_pVarClass = p->GivPointer();
+
+ if ( m_pVarClass != NULL )
+ m_pVarClass->IncrementUse(); // une référence en plus
+
+ m_pClass = p->m_pClass;
+ m_binit = p->m_binit;
+//- m_bStatic = p->m_bStatic;
+ m_next = NULL;
+ m_pMyThis = NULL;//p->m_pMyThis;
+ m_pUserPtr = p->m_pUserPtr;
+
+ // garde le même idendificateur (par défaut)
+ if (m_ident == 0 ) m_ident = p->m_ident;
+}
+
+BOOL CBotVarPointer::Eq(CBotVar* left, CBotVar* right)
+{
+ CBotVarClass* l = left->GivPointer();
+ CBotVarClass* r = right->GivPointer();
+
+ if ( l == r ) return TRUE;
+ if ( l == NULL && r->GivUserPtr() == OBJECTDELETED ) return TRUE;
+ if ( r == NULL && l->GivUserPtr() == OBJECTDELETED ) return TRUE;
+ return FALSE;
+}
+
+BOOL CBotVarPointer::Ne(CBotVar* left, CBotVar* right)
+{
+ CBotVarClass* l = left->GivPointer();
+ CBotVarClass* r = right->GivPointer();
+
+ if ( l == r ) return FALSE;
+ if ( l == NULL && r->GivUserPtr() == OBJECTDELETED ) return FALSE;
+ if ( r == NULL && l->GivUserPtr() == OBJECTDELETED ) return FALSE;
+ return TRUE;
+}
+
+
+
+///////////////////////////////////////////////////////
+// gestion des types de résultats
+
+
+CBotTypResult::CBotTypResult(int type)
+{
+ m_type = type;
+ m_pNext = NULL;
+ m_pClass = NULL;
+ m_limite = -1;
+}
+
+CBotTypResult::CBotTypResult(int type, const char* name)
+{
+ m_type = type;
+ m_pNext = NULL;
+ m_pClass = NULL;
+ m_limite = -1;
+
+ if ( type == CBotTypPointer ||
+ type == CBotTypClass ||
+ type == CBotTypIntrinsic )
+ {
+ m_pClass = CBotClass::Find(name);
+ if ( m_pClass && m_pClass->IsIntrinsic() ) m_type = CBotTypIntrinsic;
+ }
+}
+
+CBotTypResult::CBotTypResult(int type, CBotClass* pClass)
+{
+ m_type = type;
+ m_pNext = NULL;
+ m_pClass = pClass;
+ m_limite = -1;
+
+ if ( m_pClass && m_pClass->IsIntrinsic() ) m_type = CBotTypIntrinsic;
+}
+
+CBotTypResult::CBotTypResult(int type, CBotTypResult elem)
+{
+ m_type = type;
+ m_pNext = NULL;
+ m_pClass = NULL;
+ m_limite = -1;
+
+ if ( type == CBotTypArrayPointer ||
+ type == CBotTypArrayBody )
+ m_pNext = new CBotTypResult( elem );
+}
+
+CBotTypResult::CBotTypResult(CBotTypResult& typ)
+{
+ m_type = typ.m_type;
+ m_pClass = typ.m_pClass;
+ m_pNext = NULL;
+ m_limite = typ.m_limite;
+
+ if ( typ.m_pNext )
+ m_pNext = new CBotTypResult( *typ.m_pNext );
+}
+
+CBotTypResult::CBotTypResult()
+{
+ m_type = 0;
+ m_limite = -1;
+ m_pNext = NULL;
+ m_pClass = NULL;
+}
+
+CBotTypResult::~CBotTypResult()
+{
+ delete m_pNext;
+}
+
+int CBotTypResult::GivType(int mode)
+{
+#ifdef _DEBUG
+ if ( m_type == CBotTypPointer ||
+ m_type == CBotTypClass ||
+ m_type == CBotTypIntrinsic )
+
+ if ( m_pClass == NULL ) __asm int 3;
+
+
+ if ( m_type == CBotTypArrayPointer )
+ if ( m_pNext == NULL ) __asm int 3;
+#endif
+ if ( mode == 3 && m_type == CBotTypNullPointer ) return CBotTypPointer;
+ return m_type;
+}
+
+void CBotTypResult::SetType(int n)
+{
+ m_type = n;
+}
+
+CBotClass* CBotTypResult::GivClass()
+{
+ return m_pClass;
+}
+
+CBotTypResult& CBotTypResult::GivTypElem()
+{
+ return *m_pNext;
+}
+
+int CBotTypResult::GivLimite()
+{
+ return m_limite;
+}
+
+void CBotTypResult::SetLimite(int n)
+{
+ m_limite = n;
+}
+
+void CBotTypResult::SetArray( int* max )
+{
+ m_limite = *max;
+ if (m_limite < 1) m_limite = -1;
+
+ if ( m_pNext != NULL ) // dernière dimension ?
+ {
+ m_pNext->SetArray( max+1 );
+ }
+}
+
+
+
+BOOL CBotTypResult::Compare(CBotTypResult& typ)
+{
+ if ( m_type != typ.m_type ) return FALSE;
+
+ if ( m_type == CBotTypArrayPointer ) return m_pNext->Compare(*typ.m_pNext);
+
+ if ( m_type == CBotTypPointer ||
+ m_type == CBotTypClass ||
+ m_type == CBotTypIntrinsic )
+ {
+ return m_pClass == typ.m_pClass;
+ }
+
+ return TRUE;
+}
+
+BOOL CBotTypResult::Eq(int type)
+{
+ return m_type == type;
+}
+
+CBotTypResult&
+ CBotTypResult::operator=(const CBotTypResult& src)
+{
+ m_type = src.m_type;
+ m_limite = src.m_limite;
+ m_pClass = src.m_pClass;
+ m_pNext = NULL;
+ if ( src.m_pNext != NULL )
+ {
+ m_pNext = new CBotTypResult(*src.m_pNext);
+ }
+ return *this;
+}
+
+
diff --git a/src/CBot/CBotWhile.cpp b/src/CBot/CBotWhile.cpp
new file mode 100644
index 0000000..7a1ca1f
--- /dev/null
+++ b/src/CBot/CBotWhile.cpp
@@ -0,0 +1,1413 @@
+///////////////////////////////////////////////////////////////////////
+// ce fichier défini les instructions suivantes:
+// CBotWhile "while (condition) {instructions}"
+// CBotDo "do {instructions} while (condition)"
+// CBotFor "for (init, condition, incr) {instructions}"
+// CBotSwitch "switch (val) {instructions}"
+// CBotCase "case val:"
+// CBotBreak "break", "break label", "continu", "continu label"
+// CBotTry "try {instructions}"
+// CBotCatch "catch (condition) {instructions}" ou "finally"
+// CBotThrow "throw execption"
+
+
+#include "CBot.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "while"
+
+CBotWhile::CBotWhile()
+{
+ m_Condition =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotWhile"; // debug
+}
+
+CBotWhile::~CBotWhile()
+{
+ delete m_Condition; // libère la condition
+ delete m_Block; // libère le bloc d'instruction
+}
+
+CBotInstr* CBotWhile::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotWhile* inst = new CBotWhile(); // crée l'objet
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ if ( IsOfType( p, TokenTypVar ) &&
+ IsOfType( p, ID_DOTS ) )
+ {
+ inst->m_label = pp->GivString(); // enregistre le nom du label
+ }
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_WHILE)) return NULL; // ne devrait jamais arriver
+
+ CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
+
+ if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
+ {
+ // la condition existe
+
+ IncLvl(inst->m_label);
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ DecLvl();
+
+ if ( pStk->IsOk() )
+ {
+ // le bloc d'instruction est ok (il peut être vide !
+
+ return pStack->Return(inst, pStk); // rend l'objet à qui le demande
+ }
+ }
+
+ delete inst; // erreur, libère la place
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute une instruction "while"
+
+BOOL CBotWhile :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ while( TRUE ) switch( pile->GivState() ) // exécute la boucle
+ { // il y a 2 états possibles (selon reprise)
+ case 0:
+ // évalue la condition
+ if ( !m_Condition->Execute(pile) ) return FALSE; // interrompu ici ?
+
+ // le résultat de la condition est sur la pile
+
+ // termine s'il y a une erreur ou si la condition est fausse
+ if ( !pile->IsOk() || pile->GivVal() != TRUE )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ // la condition est vrai, passe dans le second mode
+
+ if (!pile->SetState(1)) return FALSE; // prêt pour la suite
+
+ case 1:
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL &&
+ !m_Block->Execute(pile) )
+ {
+ if (pile->IfContinue(0, m_label)) continue; // si continue, repasse au test
+ return pj->BreakReturn(pile, m_label); // transmet le résultat et libère la pile
+ }
+
+ // termine s'il y a une erreur
+ if ( !pile->IsOk() )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ // repasse au test pour recommencer
+ if (!pile->SetState(0, 0)) return FALSE;
+ continue;
+ }
+}
+
+void CBotWhile :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+ CBotStack* pile = pj->RestoreStack(this); // ajoute un élément à la pile
+ if ( pile == NULL ) return;
+
+ switch( pile->GivState() )
+ { // il y a 2 états possibles (selon reprise)
+ case 0:
+ // évalue la condition
+ m_Condition->RestoreState(pile, bMain);
+ return;
+
+ case 1:
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL ) m_Block->RestoreState(pile, bMain);
+ return;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "repeat"
+
+CBotRepeat::CBotRepeat()
+{
+ m_NbIter =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotRepeat"; // debug
+}
+
+CBotRepeat::~CBotRepeat()
+{
+ delete m_NbIter; // libère la condition
+ delete m_Block; // libère le bloc d'instruction
+}
+
+CBotInstr* CBotRepeat::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotRepeat* inst = new CBotRepeat(); // crée l'objet
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ if ( IsOfType( p, TokenTypVar ) &&
+ IsOfType( p, ID_DOTS ) )
+ {
+ inst->m_label = pp->GivString(); // enregistre le nom du label
+ }
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_REPEAT)) return NULL; // ne devrait jamais arriver
+
+ CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
+
+ if ( IsOfType(p, ID_OPENPAR ) )
+ {
+ CBotToken* ppp = p; // conserve le ^au token (position début)
+ if ( NULL != (inst->m_NbIter = CBotExpression::Compile( p, pStk )) )
+ {
+ if ( pStk->GivType() < CBotTypLong )
+ {
+ if ( IsOfType(p, ID_CLOSEPAR ) )
+ {
+
+ IncLvl(inst->m_label);
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ DecLvl();
+
+ if ( pStk->IsOk() )
+ {
+ // le bloc d'instruction est ok (il peut être vide !
+
+ return pStack->Return(inst, pStk); // rend l'objet à qui le demande
+ }
+ }
+ pStack->SetError(TX_CLOSEPAR, p->GivStart());
+ }
+ pStk->SetStartError(ppp->GivStart());
+ pStk->SetError( TX_BADTYPE, p->GivStart() );
+ }
+ pStack->SetError(TX_ENDOF, p);
+ }
+ pStack->SetError(TX_OPENPAR, p->GivStart()); // manque la parenthèse
+
+ delete inst; // erreur, libère la place
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute une instruction "repeat"
+
+BOOL CBotRepeat :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ while( TRUE ) switch( pile->GivState() ) // exécute la boucle
+ { // il y a 2 états possibles (selon reprise)
+ case 0:
+ // évalue le nombre d'itération
+ if ( !m_NbIter->Execute(pile) ) return FALSE; // interrompu ici ?
+
+ // le résultat de la condition est sur la pile
+
+ // termine s'il y a une erreur ou si la condition est fausse
+ int n;
+ if ( !pile->IsOk() || ( n = pile->GivVal() ) < 1 )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ // met le nombre d'itération +1 dans le "state"
+
+ if (!pile->SetState(n+1)) return FALSE; // prêt pour la suite
+ continue; // passe à la suite
+
+ case 1:
+ // fin normale de la boucle
+ return pj->Return(pile); // transmet le résultat et libère la pile
+
+ default:
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL &&
+ !m_Block->Execute(pile) )
+ {
+ if (pile->IfContinue(pile->GivState()-1, m_label)) continue; // si continue, repasse au test
+ return pj->BreakReturn(pile, m_label); // transmet le résultat et libère la pile
+ }
+
+ // termine s'il y a une erreur
+ if ( !pile->IsOk() )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ // repasse au test pour recommencer
+ if (!pile->SetState(pile->GivState()-1, 0)) return FALSE;
+ continue;
+ }
+}
+
+void CBotRepeat :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+ CBotStack* pile = pj->RestoreStack(this); // ajoute un élément à la pile
+ if ( pile == NULL ) return;
+
+ switch( pile->GivState() )
+ { // il y a 2 états possibles (selon reprise)
+ case 0:
+ // évalue la condition
+ m_NbIter->RestoreState(pile, bMain);
+ return;
+
+ case 1:
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL ) m_Block->RestoreState(pile, bMain);
+ return;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "do"
+
+CBotDo::CBotDo()
+{
+ m_Condition =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotDo"; // debug
+}
+
+CBotDo::~CBotDo()
+{
+ delete m_Condition; // libère la condition
+ delete m_Block; // libère le bloc d'instruction
+}
+
+CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotDo* inst = new CBotDo(); // crée l'objet
+
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ if ( IsOfType( p, TokenTypVar ) &&
+ IsOfType( p, ID_DOTS ) )
+ {
+ inst->m_label = pp->GivString(); // enregistre le nom du label
+ }
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_DO)) return NULL; // ne devrait jamais arriver
+
+ CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
+
+
+ // cherche un bloc d'instruction après le do
+ IncLvl(inst->m_label);
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ DecLvl();
+
+ if ( pStk->IsOk() )
+ {
+ if (IsOfType(p, ID_WHILE))
+ {
+ if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
+ {
+ // la condition existe
+ if (IsOfType(p, ID_SEP))
+ {
+ return pStack->Return(inst, pStk); // rend l'objet à qui le demande
+ }
+ pStk->SetError(TX_ENDOF, p->GivStart());
+ }
+ }
+ pStk->SetError(TX_WHILE, p->GivStart());
+ }
+
+ delete inst; // erreur, libère la place
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute une instruction "do"
+
+BOOL CBotDo :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ while( TRUE ) switch( pile->GivState() ) // exécute la boucle
+ { // il y a 2 états possibles (selon reprise)
+ case 0:
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL &&
+ !m_Block->Execute(pile) )
+ {
+ if (pile->IfContinue(1, m_label)) continue; // si continue, repasse au test
+ return pj->BreakReturn(pile, m_label); // transmet le résultat et libère la pile
+ }
+
+ // termine s'il y a une erreur
+ if ( !pile->IsOk() )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ if (!pile->SetState(1)) return FALSE; // prêt pour la suite
+
+ case 1:
+ // évalue la condition
+ if ( !m_Condition->Execute(pile) ) return FALSE; // interrompu ici ?
+
+ // le résultat de la condition est sur la pile
+
+ // termine s'il y a une erreur ou si la condition est fausse
+ if ( !pile->IsOk() || pile->GivVal() != TRUE )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ // repasse au bloc d'instruction pour recommencer
+ if (!pile->SetState(0, 0)) return FALSE;
+ continue;
+ }
+}
+
+void CBotDo :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this); // ajoute un élément à la pile
+ if ( pile == NULL ) return;
+
+ switch( pile->GivState() )
+ { // il y a 2 états possibles (selon reprise)
+ case 0:
+ // restitue le bloc d'instruction associé
+ if ( m_Block != NULL ) m_Block->RestoreState(pile, bMain);
+ return;
+
+ case 1:
+ // restitue la condition
+ m_Condition->RestoreState(pile, bMain);
+ return;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "for"
+
+CBotFor::CBotFor()
+{
+ m_Init =
+ m_Test =
+ m_Incr =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotFor"; // debug
+}
+
+CBotFor::~CBotFor()
+{
+ delete m_Init;
+ delete m_Test;
+ delete m_Incr;
+ delete m_Block; // libère le bloc d'instruction
+}
+
+CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotFor* inst = new CBotFor(); // crée l'objet
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ if ( IsOfType( p, TokenTypVar ) &&
+ IsOfType( p, ID_DOTS ) )
+ {
+ inst->m_label = pp->GivString(); // enregistre le nom du label
+ }
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_FOR)) return NULL; // ne devrait jamais arriver
+
+ if ( !IsOfType(p, ID_OPENPAR)) // manque la parenthèse ?
+ {
+ pStack->SetError(TX_OPENPAR, p->GivStart());
+ return NULL;
+ }
+
+ CBotCStack* pStk = pStack->TokenStack(pp, TRUE); // un petit bout de pile svp
+
+ // compile les instructions pour initialisation
+ inst->m_Init = CBotListExpression::Compile( p, pStk );
+ if ( pStk->IsOk() )
+ {
+ if ( !IsOfType(p, ID_SEP)) // manque le point-virgule ?
+ {
+ pStack->SetError(TX_OPENPAR, p->GivStart());
+ delete inst;
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+ }
+ inst->m_Test = CBotBoolExpr::Compile( p, pStk );
+ if ( pStk->IsOk() )
+ {
+ if ( !IsOfType(p, ID_SEP)) // manque le point-virgule ?
+ {
+ pStack->SetError(TX_OPENPAR, p->GivStart());
+ delete inst;
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+ }
+ inst->m_Incr = CBotListExpression::Compile( p, pStk );
+ if ( pStk->IsOk() )
+ {
+ if ( IsOfType(p, ID_CLOSEPAR)) // manque la parenthèse ?
+ {
+ IncLvl(inst->m_label);
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ DecLvl();
+ if ( pStk->IsOk() )
+ return pStack->Return(inst, pStk);;
+ }
+ pStack->SetError(TX_CLOSEPAR, p->GivStart());
+ }
+ }
+ }
+
+ delete inst; // erreur, libère la place
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute l'instruction "for"
+
+BOOL CBotFor :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this, TRUE); // ajoute un élément à la pile (variables locales)
+ // ou le retrouve en cas de reprise
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ while( TRUE ) switch( pile->GivState() ) // exécute la boucle
+ { // il y a 4 états possibles (selon reprise)
+ case 0:
+ // évalue l'initialisation
+ if ( m_Init != NULL &&
+ !m_Init->Execute(pile) ) return FALSE; // interrompu ici ?
+ if (!pile->SetState(1)) return FALSE; // prêt pour la suite
+
+ case 1:
+ // évalue la condition
+ if ( m_Test != NULL ) // pas de condition ? -> vrai !
+ {
+ if (!m_Test->Execute(pile) ) return FALSE; // interrompu ici ?
+
+ // le résultat de la condition est sur la pile
+
+ // termine s'il y a une erreur ou si la condition est fausse
+ if ( !pile->IsOk() || pile->GivVal() != TRUE )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+ }
+
+ // la condition est vrai, passe à la suite
+ if (!pile->SetState(2)) return FALSE; // prêt pour la suite
+
+ case 2:
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL &&
+ !m_Block->Execute(pile) )
+ {
+ if (pile->IfContinue(3, m_label)) continue; // si continue, passe à l'incrémentation
+ return pj->BreakReturn(pile, m_label); // transmet le résultat et libère la pile
+ }
+
+ // termine s'il y a une erreur
+ if ( !pile->IsOk() )
+ {
+ return pj->Return(pile); // transmet le résultat et libère la pile
+ }
+
+ if (!pile->SetState(3)) return FALSE; // prêt pour la suite
+
+ case 3:
+ // évalue l'incrémentation
+ if ( m_Incr != NULL &&
+ !m_Incr->Execute(pile) ) return FALSE; // interrompu ici ?
+
+ // repasse au test pour recommencer
+ if (!pile->SetState(1, 0)) return FALSE; // revient au test
+ continue;
+ }
+}
+
+void CBotFor :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this); // ajoute un élément à la pile (variables locales)
+ if ( pile == NULL ) return;
+
+ switch( pile->GivState() )
+ { // il y a 4 états possibles (selon reprise)
+ case 0:
+ // évalue l'initialisation
+ if ( m_Init != NULL ) m_Init->RestoreState(pile, TRUE); // interrompu ici !
+ return;
+
+ case 1:
+ if ( m_Init != NULL ) m_Init->RestoreState(pile, FALSE); // définitions variables
+
+ // évalue la condition
+ if ( m_Test != NULL ) m_Test->RestoreState(pile, TRUE); // interrompu ici !
+ return;
+
+ case 2:
+ if ( m_Init != NULL ) m_Init->RestoreState(pile, FALSE); // définitions variables
+
+ // évalue le bloc d'instruction associé
+ if ( m_Block != NULL ) m_Block->RestoreState(pile, TRUE);
+ return;
+
+ case 3:
+ if ( m_Init != NULL ) m_Init->RestoreState(pile, FALSE); // définitions variables
+
+ // évalue l'incrémentation
+ if ( m_Incr != NULL ) m_Incr->RestoreState(pile, TRUE); // interrompu ici !
+ return;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// compile une liste d'expression
+// n'est utilisé que pour l'instruction for
+// dans l'intitialisation et dans l'incrémentation
+
+CBotListExpression::CBotListExpression()
+{
+ m_Expr = NULL;
+ name = "CBotListExpression";
+}
+
+CBotListExpression::~CBotListExpression()
+{
+ delete m_Expr;
+}
+
+// cherche une déclaration de variable ou une expression
+
+static CBotInstr* CompileInstrOrDefVar(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotInstr* i = CBotInt::Compile( p, pStack, FALSE, TRUE ); // est-ce une déclaration d'un entier ?
+ if ( i== NULL ) i = CBotFloat::Compile( p, pStack, FALSE, TRUE ); // ou d'un nombre réel ?
+ if ( i== NULL ) i = CBotBoolean::Compile( p, pStack, FALSE, TRUE ); // ou d'un booléen ?
+ if ( i== NULL ) i = CBotIString::Compile( p, pStack, FALSE, TRUE ); // ou d'une chaîne ?
+ if ( i== NULL ) i = CBotExpression::Compile( p, pStack ); // compile une expression
+ return i;
+}
+
+CBotInstr* CBotListExpression::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotListExpression* inst = new CBotListExpression();
+
+ inst->m_Expr = CompileInstrOrDefVar( p, pStack ); // compile la première expression de la liste
+ if (pStack->IsOk())
+ {
+ while ( IsOfType(p, ID_COMMA) ) // plusieurs instructions ?
+ {
+ CBotInstr* i = CompileInstrOrDefVar( p, pStack ); // est-ce une déclaration d'un entier ?
+ inst->m_Expr->AddNext(i); // ajoute à la suite
+ if ( !pStack->IsOk() )
+ {
+ delete inst;
+ return NULL; // pas d'objet, l'erreur est sur la pile
+ }
+ }
+ return inst;
+ }
+ delete inst;
+ return NULL;
+}
+
+BOOL CBotListExpression::Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack();// indispensable
+ CBotInstr* p = m_Expr; // la première expression
+
+ int state = pile->GivState();
+ while (state-->0) p = p->GivNext(); // revient sur l'opération interrompue
+
+ if ( p != NULL ) while (TRUE)
+ {
+ if ( !p->Execute(pile) ) return FALSE;
+ p = p->GivNext();
+ if ( p == NULL ) break;
+ if (!pile->IncState()) return FALSE; // prêt pour la suivante
+ }
+ return pj->Return(pile);
+}
+
+void CBotListExpression::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ CBotStack* pile = pj;
+ int state = 0x7000;
+
+ if ( bMain )
+ {
+ pile = pj->RestoreStack();
+ if ( pile == NULL ) return;
+ state = pile->GivState();
+ }
+
+ CBotInstr* p = m_Expr; // la première expression
+
+ while (p != NULL && state-->0)
+ {
+ p->RestoreState(pile, FALSE);
+ p = p->GivNext(); // revient sur l'opération interrompue
+ }
+
+ if ( p != NULL )
+ {
+ p->RestoreState(pile, bMain);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "switch"
+
+CBotSwitch::CBotSwitch()
+{
+ m_Value =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotSwitch"; // debug
+}
+
+CBotSwitch::~CBotSwitch()
+{
+ delete m_Value; // libère la valeur
+ delete m_Block; // libère le bloc d'instruction
+}
+
+
+CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotSwitch* inst = new CBotSwitch(); // crée l'objet
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_SWITCH)) return NULL; // ne devrait jamais arriver
+
+ CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
+
+ if ( IsOfType(p, ID_OPENPAR ) )
+ {
+ if ( NULL != (inst->m_Value = CBotExpression::Compile( p, pStk )) )
+ {
+ if ( pStk->GivType() < CBotTypLong )
+ {
+ if ( IsOfType(p, ID_CLOSEPAR ) )
+ {
+ if ( IsOfType(p, ID_OPBLK ) )
+ {
+ IncLvl();
+
+ while( !IsOfType( p, ID_CLBLK ) )
+ {
+ if ( p->GivType() == ID_CASE || p->GivType() == ID_DEFAULT)
+ {
+ CBotCStack* pStk2 = pStk->TokenStack(p); // un petit bout de pile svp
+
+ CBotInstr* i = CBotCase::Compile( p, pStk2 );
+ if (i == NULL)
+ {
+ delete inst;
+ return pStack->Return(NULL, pStk2);
+ }
+ delete pStk2;
+ if ( inst->m_Block == NULL ) inst->m_Block = i;
+ else inst->m_Block->AddNext(i);
+ continue;
+ }
+
+ if ( inst->m_Block == NULL )
+ {
+ pStk->SetError(TX_NOCASE, p->GivStart());
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ CBotInstr* i = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
+ if ( !pStk->IsOk() )
+ {
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ inst->m_Block->AddNext(i);
+
+ if ( p == NULL )
+ {
+ pStk->SetError(TX_CLOSEBLK, -1);
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ }
+ DecLvl();
+
+ if ( inst->m_Block == NULL )
+ {
+ pStk->SetError(TX_NOCASE, p->GivStart());
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+ // le bloc d'instruction est ok
+ return pStack->Return(inst, pStk); // rend l'objet à qui le demande
+ }
+ pStk->SetError( TX_OPENBLK, p->GivStart() );
+ }
+ pStk->SetError( TX_CLOSEPAR, p->GivStart() );
+ }
+ pStk->SetError( TX_BADTYPE, p->GivStart() );
+ }
+ }
+ pStk->SetError( TX_OPENPAR, p->GivStart());
+
+ delete inst; // erreur, libère la place
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute une instruction "switch"
+
+BOOL CBotSwitch :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile1 = pj->AddStack(this); // ajoute un élément à la pile
+// if ( pile1 == EOX ) return TRUE;
+
+ CBotInstr* p = m_Block; // la première expression
+
+ int state = pile1->GivState();
+ if (state == 0)
+ {
+ if ( !m_Value->Execute(pile1) ) return FALSE;
+ pile1->SetState(state = -1);
+ }
+
+ if ( pile1->IfStep() ) return FALSE;
+
+ if ( state == -1 )
+ {
+ state = 0;
+ int val = pile1->GivVal(); // résultat de la valeur
+
+ CBotStack* pile2 = pile1->AddStack();
+ while ( p != NULL ) // recherche le case correspondant dans la liste
+ {
+ state++;
+ if ( p->CompCase( pile2, val ) ) break; // trouvé le case
+ p = p->GivNext();
+ }
+ pile2->Delete();
+
+ if ( p == NULL ) return pj->Return(pile1); // terminé si plus rien
+
+ if ( !pile1->SetState(state) ) return FALSE;
+ }
+
+ p = m_Block; // revient au début
+ while (state-->0) p = p->GivNext(); // avance dans la liste
+
+ while( p != NULL )
+ {
+ if ( !p->Execute(pile1) ) return pj->BreakReturn(pile1);
+ if ( !pile1->IncState() ) return FALSE;
+ p = p->GivNext();
+ }
+ return pj->Return(pile1);
+}
+
+void CBotSwitch :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile1 = pj->RestoreStack(this); // ajoute un élément à la pile
+ if ( pile1 == NULL ) return;
+
+ CBotInstr* p = m_Block; // la première expression
+
+ int state = pile1->GivState();
+ if (state == 0)
+ {
+ m_Value->RestoreState(pile1, bMain);
+ return;
+ }
+
+ if ( state == -1 )
+ {
+ return;
+ }
+
+// p = m_Block; // revient au début
+ while ( p != NULL && state-- > 0 )
+ {
+ p->RestoreState(pile1, FALSE);
+ p = p->GivNext(); // avance dans la liste
+ }
+
+ if( p != NULL )
+ {
+ p->RestoreState(pile1, TRUE);
+ return;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "case"
+// on est forcément dans un bloc d'instruction "switch"
+
+CBotCase::CBotCase()
+{
+ m_Value = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotCase"; // debug
+}
+
+CBotCase::~CBotCase()
+{
+ delete m_Value; // libère la valeur
+}
+
+
+CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCase* inst = new CBotCase(); // crée l'objet
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_CASE, ID_DEFAULT)) return NULL; // ne devrait jamais arriver
+
+ if ( pp->GivType() == ID_CASE )
+ {
+ pp = p;
+ inst->m_Value = CBotExprNum::Compile(p, pStack);
+ if ( inst->m_Value == NULL )
+ {
+ pStack->SetError( TX_BADNUM, pp );
+ delete inst;
+ return NULL;
+ }
+ }
+ if ( !IsOfType( p, ID_DOTS ))
+ {
+ pStack->SetError( TX_MISDOTS, p->GivStart() );
+ delete inst;
+ return NULL;
+ }
+
+ return inst;
+}
+
+// exécution de l'instruction "case"
+
+BOOL CBotCase::Execute(CBotStack* &pj)
+{
+ return TRUE; // l'instruction "case" ne fait rien !
+}
+
+void CBotCase::RestoreState(CBotStack* &pj, BOOL bMain)
+{
+}
+
+// routine permettant de trouver le point d'entrée "case"
+// correspondant à la valeur cherchée
+
+BOOL CBotCase::CompCase(CBotStack* &pile, int val)
+{
+ if ( m_Value == NULL ) return TRUE; // cas pour "default"
+
+ while (!m_Value->Execute(pile)); // met sur la pile la valeur correpondant (sans interruption)
+ return (pile->GivVal() == val); // compare avec la valeur cherchée
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "break" ou "continu"
+
+CBotBreak::CBotBreak()
+{
+ name = "CBotBreak"; // debug
+}
+
+CBotBreak::~CBotBreak()
+{
+}
+
+CBotInstr* CBotBreak::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotToken* pp = p; // conserve le ^au token (position début)
+ int type = p->GivType();
+
+ if (!IsOfType(p, ID_BREAK, ID_CONTINUE)) return NULL; // ne devrait jamais arriver
+
+ if ( !ChkLvl(CBotString(), type ) )
+ {
+ pStack->SetError(TX_BREAK, pp);
+ return NULL; // pas d'objet, l'erreur est sur la pile
+ }
+
+ CBotBreak* inst = new CBotBreak(); // crée l'objet
+ inst->SetToken(pp); // garde l'opération
+
+ pp = p;
+ if ( IsOfType( p, TokenTypVar ) )
+ {
+ inst->m_label = pp->GivString(); // enregistre le nom du label
+ if ( !ChkLvl(inst->m_label, type ) )
+ {
+ delete inst;
+ pStack->SetError(TX_NOLABEL, pp);
+ return NULL; // pas d'objet, l'erreur est sur la pile
+ }
+ }
+
+ if (IsOfType(p, ID_SEP))
+ {
+ return inst; // et le donne à qui veux
+ }
+ delete inst;
+
+ pStack->SetError(TX_ENDOF, p->GivStart());
+ return NULL; // pas d'objet, l'erreur est sur la pile
+}
+
+// exécution l'instructino "break" ou "continu"
+
+BOOL CBotBreak :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->IfStep() ) return FALSE;
+
+ pile->SetBreak(m_token.GivType()==ID_BREAK ? 1 : 2, m_label);
+ return pj->Return(pile);
+}
+
+void CBotBreak :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain ) pj->RestoreStack(this);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "try"
+
+CBotTry::CBotTry()
+{
+ m_ListCatch = NULL;
+ m_FinalInst =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ name = "CBotTry"; // debug
+}
+
+CBotTry::~CBotTry()
+{
+ delete m_ListCatch; // libère la liste
+ delete m_Block; // libère le bloc d'instruction
+ delete m_FinalInst;
+}
+
+CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotTry* inst = new CBotTry(); // crée l'objet
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_TRY)) return NULL; // ne devrait jamais arriver
+
+ CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
+
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk );
+ CBotCatch** pn = &inst->m_ListCatch;
+
+ while (pStk->IsOk() && p->GivType() == ID_CATCH)
+ {
+ CBotCatch* i = CBotCatch::Compile(p, pStk);
+ *pn = i;
+ pn = &i->m_next;
+ }
+
+ if (pStk->IsOk() && IsOfType( p, ID_FINALLY) )
+ {
+ inst->m_FinalInst = CBotBlock::CompileBlkOrInst( p, pStk );
+ }
+
+ if (pStk->IsOk())
+ {
+ return pStack->Return(inst, pStk); // rend l'objet à qui le demande
+ }
+
+ delete inst; // erreur, libère la place
+ return pStack->Return(NULL, pStk); // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute l'instruction Try
+// gère le retour d'exceptions
+// les arrêts par suspension
+// et les "finaly"
+
+BOOL CBotTry :: Execute(CBotStack* &pj)
+{
+ int val;
+
+ CBotStack* pile1 = pj->AddStack(this); // ajoute un élément à la pile
+// if ( pile1 == EOX ) return TRUE;
+
+ if ( pile1->IfStep() ) return FALSE;
+ // ou le retrouve en cas de reprise
+ CBotStack* pile0 = pj->AddStack2(); // ajoute un élément à la pile secondaire
+ CBotStack* pile2 = pile0->AddStack();
+
+ if ( pile1->GivState() == 0 )
+ {
+ if ( m_Block->Execute(pile1) )
+ {
+ if ( m_FinalInst == NULL ) return pj->Return(pile1);
+ pile1->SetState(-2); // passe au final
+ }
+
+ val = pile1->GivError();
+ if ( val == 0 && CBotStack::m_initimer == 0 ) // en mode de step ?
+ return FALSE; // ne fait pas le catch
+
+ pile1->IncState();
+ pile2->SetState(val); // mémorise le numéro de l'erreur
+ pile1->SetError(0); // pour l'instant il n'y a plus d'erreur !
+
+ if ( val == 0 && CBotStack::m_initimer < 0 ) // en mode de step ?
+ return FALSE; // ne fait pas le catch
+ }
+
+ // il y a eu une interruption
+ // voir de quoi il en retourne
+
+ CBotCatch* pc = m_ListCatch;
+ int state = (short)pile1->GivState(); // où en étions-nous ?
+ val = pile2->GivState(); // pour quelle erreur ?
+ pile0->SetState(1); // marquage pour GetRunPos
+
+ if ( val >= 0 && state > 0 ) while ( pc != NULL )
+ {
+ if ( --state <= 0 )
+ {
+ // demande au bloc catch s'il se sent concerné
+ if ( !pc->TestCatch(pile2, val) ) return FALSE; // suspendu !
+ pile1->IncState();
+ }
+ if ( --state <= 0 )
+ {
+ if ( pile2->GivVal() == TRUE )
+ {
+// pile0->SetState(1);
+
+ if ( !pc->Execute(pile2) ) return FALSE; // exécute l'opération
+ if ( m_FinalInst == NULL )
+ return pj->Return(pile2); // termine le try
+
+ pile1->SetState(-2); // passe au final
+ break;
+ }
+ pile1->IncState();
+ }
+ pc = pc->m_next;
+ }
+ if ( m_FinalInst != NULL &&
+ pile1->GivState() > 0 && val != 0 ) pile1->SetState(-1);// si arret alors fait le final
+
+ if (pile1->GivState() <= -1)
+ {
+// pile0->SetState(1);
+
+ if (!m_FinalInst->Execute(pile2) && pile2->IsOk()) return FALSE;
+ if (!pile2->IsOk()) return pj->Return(pile2); // garde cette exception
+ pile2->SetError(pile1->GivState()==-1 ? val : 0); // remet l'erreur initiale
+ return pj->Return(pile2);
+ }
+
+ pile1->SetState(0); // revient à l'évaluation
+ pile0->SetState(0); // revient à l'évaluation
+ if ( val != 0 && m_ListCatch == NULL && m_FinalInst == NULL )
+ return pj->Return(pile2); // termine le try sans exception aucune
+
+ pile1->SetError(val); // remet l'erreur
+ return FALSE; // ce n'est pas pour nous
+}
+
+
+void CBotTry :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ int val;
+ CBotStack* pile1 = pj->RestoreStack(this); // ajoute un élément à la pile
+ if ( pile1 == NULL ) return;
+ // ou le retrouve en cas de reprise
+ CBotStack* pile0 = pj->AddStack2(); // ajoute un élément à la pile secondaire
+ if ( pile0 == NULL ) return;
+
+ CBotStack* pile2 = pile0->RestoreStack();
+ if ( pile2 == NULL ) return;
+
+ m_Block->RestoreState(pile1, bMain);
+ if ( pile0->GivState() == 0 )
+ {
+ return;
+ }
+
+ // il y a eu une interruption
+ // voir de quoi il en retourne
+
+ CBotCatch* pc = m_ListCatch;
+ int state = pile1->GivState(); // où en étions-nous ?
+ val = pile2->GivState(); // pour quelle erreur ?
+
+ if ( val >= 0 && state > 0 ) while ( pc != NULL )
+ {
+ if ( --state <= 0 )
+ {
+ // demande au bloc catch s'il se sent concerné
+ pc->RestoreCondState(pile2, bMain); // suspendu !
+ return;
+ }
+ if ( --state <= 0 )
+ {
+ if ( pile2->GivVal() == TRUE )
+ {
+ pc->RestoreState(pile2, bMain); // exécute l'opération
+ return;
+ }
+ }
+ pc = pc->m_next;
+ }
+
+ if (pile1->GivState() <= -1)
+ {
+ m_FinalInst->RestoreState(pile2, bMain);
+ return;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "catch"
+
+CBotCatch::CBotCatch()
+{
+ m_Cond =
+ m_Block = NULL; // NULL pour que delete soit possible sans autre
+ m_next = NULL;
+
+ name = "CBotCatch"; // debug
+}
+
+CBotCatch::~CBotCatch()
+{
+ delete m_Cond; // libère la liste
+ delete m_Block; // libère le bloc d'instruction
+ delete m_next; // et la suite
+}
+
+CBotCatch* CBotCatch::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCatch* inst = new CBotCatch(); // crée l'objet
+ pStack->SetStartError(p->GivStart());
+
+ inst->SetToken(p);
+ if (!IsOfType(p, ID_CATCH)) return NULL; // ne devrait jamais arriver
+
+ if (IsOfType(p, ID_OPENPAR))
+ {
+ inst->m_Cond = CBotExpression::Compile(p, pStack);
+ if (( pStack->GivType() < CBotTypLong ||
+ pStack->GivTypResult().Eq(CBotTypBoolean) )&& pStack->IsOk() )
+ {
+ if (IsOfType(p, ID_CLOSEPAR))
+ {
+ inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStack );
+ if ( pStack->IsOk() )
+ return inst; // rend l'objet à qui le demande
+ }
+ pStack->SetError(TX_CLOSEPAR, p->GivStart());
+ }
+ pStack->SetError(TX_BADTYPE, p->GivStart());
+ }
+ pStack->SetError(TX_OPENPAR, p->GivStart());
+ delete inst; // erreur, libère la place
+ return NULL; // pas d'objet, l'erreur est sur la pile
+}
+
+// exécution de "catch"
+
+BOOL CBotCatch :: Execute(CBotStack* &pj)
+{
+ if ( m_Block == NULL ) return TRUE;
+ return m_Block->Execute(pj); // exécute le bloc associé
+}
+
+void CBotCatch :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( bMain && m_Block != NULL ) m_Block->RestoreState(pj, bMain);
+}
+
+void CBotCatch :: RestoreCondState(CBotStack* &pj, BOOL bMain)
+{
+ m_Cond->RestoreState(pj, bMain);
+}
+
+// routine pour savoir si le catch est à faire ou non
+
+BOOL CBotCatch :: TestCatch(CBotStack* &pile, int val)
+{
+ if ( !m_Cond->Execute(pile) ) return FALSE;
+
+ if ( val > 0 || pile->GivType() != CBotTypBoolean )
+ {
+ CBotVar* var = CBotVar::Create((CBotToken*)NULL, CBotTypBoolean);
+ var->SetValInt( pile->GivVal() == val );
+ pile->SetVar(var); // remet sur la pile
+ }
+
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// compile une instruction "throw"
+
+CBotThrow::CBotThrow()
+{
+ m_Value = NULL; // NULL pour que delete soit possible sans autre
+
+ name = "CBotThrow"; // debug
+}
+
+CBotThrow::~CBotThrow()
+{
+ delete m_Value;
+}
+
+CBotInstr* CBotThrow::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ pStack->SetStartError(p->GivStart());
+
+ CBotThrow* inst = new CBotThrow(); // crée l'objet
+ inst->SetToken(p);
+
+ CBotToken* pp = p; // conserve le ^au token (position début)
+
+ if (!IsOfType(p, ID_THROW)) return NULL; // ne devrait jamais arriver
+
+ inst->m_Value = CBotExpression::Compile( p, pStack );
+
+ if (pStack->GivType() < CBotTypLong && pStack->IsOk())
+ {
+ return inst; // rend l'objet à qui le demande
+ }
+ pStack->SetError(TX_BADTYPE, pp);
+
+ delete inst; // erreur, libère la place
+ return NULL; // pas d'objet, l'erreur est sur la pile
+}
+
+// exécute l'instruction "throw"
+
+BOOL CBotThrow :: Execute(CBotStack* &pj)
+{
+ CBotStack* pile = pj->AddStack(this);
+// if ( pile == EOX ) return TRUE;
+
+ if ( pile->GivState() == 0 )
+ {
+ if ( !m_Value->Execute(pile) ) return FALSE;
+ pile->IncState();
+ }
+
+ if ( pile->IfStep() ) return FALSE;
+
+ int val = pile->GivVal();
+ if ( val < 0 ) val = TX_BADTHROW;
+ pile->SetError( val, &m_token );
+ return pj->Return( pile );
+}
+
+void CBotThrow :: RestoreState(CBotStack* &pj, BOOL bMain)
+{
+ if ( !bMain ) return;
+
+ CBotStack* pile = pj->RestoreStack(this);
+ if ( pile == NULL ) return;
+
+ if ( pile->GivState() == 0 )
+ {
+ m_Value->RestoreState(pile, bMain);
+ return;
+ }
+}
+
+
+
+////////////////////////////////////////////////////////////
+
+
+CBotStartDebugDD::CBotStartDebugDD()
+{
+ name = "CBotStartDebugDD"; // debug
+}
+
+CBotStartDebugDD::~CBotStartDebugDD()
+{
+}
+
+CBotInstr* CBotStartDebugDD::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+
+ if (!IsOfType(p, ID_DEBUGDD)) return NULL; // ne devrait jamais arriver
+
+ return new CBotStartDebugDD(); // crée l'objet
+
+}
+
+// exécute l'instruction "throw"
+
+BOOL CBotStartDebugDD :: Execute(CBotStack* &pj)
+{
+ CBotProgram* p = pj->GivBotCall();
+ p->m_bDebugDD = TRUE;
+
+ return TRUE;
+}
+
diff --git a/src/CBot/ClassFILE.cpp b/src/CBot/ClassFILE.cpp
new file mode 100644
index 0000000..21bd39e
--- /dev/null
+++ b/src/CBot/ClassFILE.cpp
@@ -0,0 +1,412 @@
+// ClassFile.cpp
+//
+// définition des méthodes pour la classe FILE
+
+
+
+// Variables statiques
+
+static CBotClass* m_pClassFILE;
+static CBotProgram* m_pFuncFile;
+static int m_CompteurFileOpen = 0;
+
+
+
+// Prépare un nom de fichier.
+
+void PrepareFilename(CBotString &filename) //DD!
+{
+ int pos;
+
+ pos = filename.ReverseFind('\\');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // enlève les dossiers
+ }
+
+ pos = filename.ReverseFind('/');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // aussi ceux avec /
+ }
+
+ pos = filename.ReverseFind(':');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // enlève aussi la lettre d'unité C:
+ }
+
+ filename = CBotString("files\\") + filename;
+}
+
+
+// constructeur de la classe
+// reçois le nom du fichier en paramètre
+
+// exécution
+BOOL rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ CBotString mode;
+
+ // accepte sans paramètre
+ if ( pVar == NULL ) return TRUE;
+
+ // qui doit être une chaîne de caractères
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
+
+ CBotString filename = pVar->GivValString();
+ PrepareFilename(filename); //DR
+
+ // il peut y avoir un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // récupère le mode
+ mode = pVar->GivValString();
+ if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return FALSE; }
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+ }
+
+ // enregistre le nom du fichier
+ pVar = pThis->GivItem("filename");
+ pVar->SetValString(filename);
+
+ if ( ! mode.IsEmpty() )
+ {
+ // ouvre le ficher demandé
+ FILE* pFile = fopen( filename, mode );
+ if ( pFile == NULL ) { Exception = CBotErrFileOpen; return FALSE; }
+
+ m_CompteurFileOpen ++;
+
+ // enregiste le canal du fichier
+ pVar = pThis->GivItem("handle");
+ pVar->SetValInt((long)pFile);
+ }
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar)
+{
+ // accepte sans paramètre
+ if ( pVar == NULL ) return CBotTypResult( 0 );
+
+ // qui doit être une chaine
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // il peut y avoir un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // qui doit être une chaine
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+ }
+
+ // le résultat est de type void (constructeur)
+ return CBotTypResult( 0 );
+}
+
+
+// destructeur de la classe
+
+// exécution
+BOOL rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // récupère l'élément "handle"
+ pVar = pThis->GivItem("handle");
+
+ // pas ouvert ? pas de problème
+ if ( pVar->GivInit() != IS_DEF) return TRUE;
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+ fclose(pFile);
+ m_CompteurFileOpen --;
+
+ pVar->SetInit(IS_NAN);
+
+ return TRUE;
+}
+
+
+// méthode FILE :: open
+// reçois le mode r/w en paramètre
+
+// exécution
+BOOL rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // il doit y avoir un paramètre
+ if ( pVar == NULL ) { Exception = CBotErrLowParam; return FALSE; }
+
+ // qui doit être une chaîne de caractères
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
+
+ // il peut y avoir un second paramètre
+ if ( pVar->GivNext() != NULL )
+ {
+ // dans ce cas le premier paramètre est le nom du fichier
+ CBotString filename = pVar->GivValString();
+ PrepareFilename(filename); //DR
+
+ // enregistre le nom du fichier
+ CBotVar* pVar2 = pThis->GivItem("filename");
+ pVar2->SetValString(filename);
+
+ // paramètre suivant est le mode
+ pVar = pVar -> GivNext();
+ }
+
+ CBotString mode = pVar->GivValString();
+ if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return FALSE; }
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+
+ // récupère l'élément "handle"
+ pVar = pThis->GivItem("handle");
+
+ // qui doit pas être initialisé
+ if ( pVar->GivInit() == IS_DEF) { Exception = CBotErrFileOpen; return FALSE; }
+
+ // reprend le nom du fichier
+ pVar = pThis->GivItem("filename");
+ CBotString filename = pVar->GivValString();
+
+ PrepareFilename(filename); //DD! (si le nom a été attribué par h.filename = "...";
+
+ // ouvre le ficher demandé
+ FILE* pFile = fopen( filename, mode );
+ if ( pFile == NULL ) //DR
+ {
+ pResult->SetValInt(FALSE); //DR
+ return TRUE; //DR
+ }
+
+ m_CompteurFileOpen ++;
+
+ // enregiste le canal du fichier
+ pVar = pThis->GivItem("handle");
+ pVar->SetValInt((long)pFile);
+
+ pResult->SetValInt(TRUE); //DR
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
+{
+ // il doit y avoir un paramètre
+ if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
+
+ // qui doit être une chaine
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // il peut y avoir un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // qui doit être une chaine
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+ }
+
+ // le résultat est de type bool
+ return CBotTypResult(CBotTypBoolean); //DR
+}
+
+
+// méthode FILE :: close
+
+// exécution
+BOOL rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // il ne doit pas y avoir de paramètre
+ if ( pVar != NULL ) return CBotErrOverParam;
+
+ // récupère l'élément "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+ fclose(pFile);
+ m_CompteurFileOpen --;
+
+ pVar->SetInit(IS_NAN);
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar)
+{
+ // il ne doit pas y avoir de paramètre
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // la fonction retourne un résultat "void"
+ return CBotTypResult( 0 );
+}
+
+// méthode FILE :: writeln
+
+// exécution
+BOOL rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // il doit y avoir un paramètre
+ if ( pVar == NULL ) { Exception = CBotErrLowParam; return FALSE; }
+
+ // qui doit être une chaîne de caractères
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return FALSE; }
+
+ CBotString param = pVar->GivValString();
+
+ // récupère l'élément "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ int res = fputs(param+"\n", pFile);
+
+ // en cas d'erreur génère une exception
+ if ( res < 0 ) { Exception = CBotErrWrite; return FALSE; }
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar)
+{
+ // il doit y avoir un paramètre
+ if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
+
+ // qui doit être une chaîne de caractères
+ if ( pVar->GivType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
+
+ // pas d'autre paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // la fonction retourne un résultat void
+ return CBotTypResult( 0 );
+}
+
+// méthode FILE :: readln
+
+// exécution
+BOOL rfread (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // il ne doit pas y avoir de paramètre
+ if ( pVar != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+
+ // récupère l'élément "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ char chaine[2000];
+ int i;
+ for ( i = 0 ; i < 2000 ; i++ ) chaine[i] = 0;
+
+ fgets(chaine, 1999, pFile);
+
+ for ( i = 0 ; i < 2000 ; i++ ) if (chaine[i] == '\n') chaine[i] = 0;
+
+ // en cas d'erreur génère une exception
+ if ( ferror(pFile) ) { Exception = CBotErrRead; return FALSE; }
+
+ pResult->SetValString( chaine );
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar)
+{
+ // il ne doit pas y avoir de paramètre
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // la fonction retourne un résultat "string"
+ return CBotTypResult( CBotTypString );
+}
+// méthode FILE :: readln
+
+
+// exécution
+BOOL rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // il ne doit pas y avoir de paramètre
+ if ( pVar != NULL ) { Exception = CBotErrOverParam; return FALSE; }
+
+ // récupère l'élément "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return FALSE; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ pResult->SetValInt( feof( pFile ) );
+
+ return TRUE;
+}
+
+// compilation
+CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar)
+{
+ // il ne doit pas y avoir de paramètre
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // la fonction retourne un résultat booleen
+ return CBotTypResult( CBotTypBoolean );
+}
+
+
+
+
+
+void InitClassFILE()
+{
+// crée une classe pour la gestion des fichiers
+// l'utilisation en est la suivante:
+// file canal( "NomFichier.txt" )
+// canal.open( "r" ); // ouvre en lecture
+// s = canal.readln( ); // lit une ligne
+// canal.close(); // referme le fichier
+
+ // crée la classe FILE
+ m_pClassFILE = new CBotClass("file", NULL);
+ // ajoute le composant ".filename"
+ m_pClassFILE->AddItem("filename", CBotTypString);
+ // ajoute le composant ".handle"
+ m_pClassFILE->AddItem("handle", CBotTypInt, PR_PRIVATE);
+
+ // défini un constructeur et un destructeur
+ m_pClassFILE->AddFunction("file", rfconstruct, cfconstruct );
+ m_pClassFILE->AddFunction("~file", rfdestruct, NULL );
+
+ // défini les méthodes associées
+ m_pClassFILE->AddFunction("open", rfopen, cfopen );
+ m_pClassFILE->AddFunction("close", rfclose, cfclose );
+ m_pClassFILE->AddFunction("writeln", rfwrite, cfwrite );
+ m_pClassFILE->AddFunction("readln", rfread, cfread );
+ m_pClassFILE->AddFunction("eof", rfeof, cfeof );
+
+ m_pFuncFile = new CBotProgram( );
+ CBotStringArray ListFonctions;
+ m_pFuncFile->Compile( "public file openfile(string name, string mode) {return new file(name, mode);}", ListFonctions);
+ m_pFuncFile->SetIdent(-2); // identificateur spécial pour RestoreState dans cette fonction
+}
+
diff --git a/src/CBot/Copie de CBot.rc b/src/CBot/Copie de CBot.rc
new file mode 100644
index 0000000..52ef23a
--- /dev/null
+++ b/src/CBot/Copie de CBot.rc
@@ -0,0 +1,184 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_IF "if"
+ ID_ELSE "else"
+ ID_WHILE "while"
+ ID_DO "do"
+ ID_ADD "+"
+ ID_SUB "-"
+ ID_MUL "*"
+ ID_DIV "/"
+ ID_OPENPAR "("
+ ID_CLOSEPAR ")"
+ ID_SEP ";"
+ ID_INT "int"
+ ID_ASS "="
+ ID_TRUE "true"
+ ID_FALSE "false"
+ ID_OPBLK "{"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_CLBLK "}"
+ ID_FOR "for"
+ ID_COMMA ","
+ ID_LO "<"
+ ID_HI ">"
+ ID_LS "<="
+ ID_HS ">="
+ ID_EQ "=="
+ ID_NE "!="
+ ID_FLOAT "float"
+ ID_STRING "String"
+ ID_BOOLEAN "boolean"
+ ID_AND "&"
+ ID_XOR "^"
+ ID_OR "|"
+ ID_LOG_AND "&&"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OPENPAR "Il manque une parenthèse ouvrante."
+ TX_CLOSEPAR "Il manque une parenthèse fermante."
+ TX_NOTBOOL "L'expression doit être un boolean."
+ TX_UNDEFVAR "Variable non déclarée."
+ TX_BADLEFT "Assignation impossible."
+ TX_ENDOF "Instruction non terminée."
+ TX_OUTCASE "Instruction ""case"" hors d'un bloc ""switch""."
+ TX_NOTERM "Instructions après la fin."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_CLOSEBLK "Il manque la fin du bloc."
+ TX_ELSEWITHOUTIF "Instruction ""else"" sans ""if"" correspondant."
+ TX_OPENBLK "Début d'un bloc attendu."
+ TX_BADTYPE "Mauvais type de résultat pour l'assignation."
+ TX_REDEFVAR "Redéfinition d'une variable."
+ TX_BAD2TYPE "Les deux opérandes ne sont pas de types compatibles."
+ TX_UNDEFCALL "Routine inconnue."
+ TX_MISDOTS "Séparateur "" : "" attendu."
+ TX_WHILE "Manque le mot ""while""."
+ TX_BREAK "Instruction ""break"" en dehors d'une boucle."
+ TX_LABEL "Un label ne peut se placer que devant un ""for"", un ""while"", un ""do"" ou un ""switch""."
+ TX_NOLABEL "Cette étiquette n'existe pas"
+ TX_NOCASE "Manque une instruction ""case""."
+ TX_BADNUM "Un nombre est attendu."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_DIVZERO "Division par zéro."
+ TX_NOTINIT "Variable non initialisée."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_LOG_OR "||"
+ ID_LOG_NOT "!"
+ ID_NOT "~"
+ ID_ASSADD "+="
+ ID_ASSSUB "-="
+ ID_ASSMUL "*="
+ ID_ASSDIV "/="
+ ID_ASSOR "|="
+ ID_ASSAND "&="
+ ID_ASSXOR "^="
+ ID_ASSSL "<<="
+ ID_ASSSR ">>>="
+ ID_ASSASR ">>="
+ ID_SL "<<"
+ ID_SR ">>>"
+ ID_ASR ">>"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_INC "++"
+ ID_DEC "--"
+ ID_MODULO "%"
+ ID_ASSMODULO "%="
+ ID_LOGIC "?"
+ ID_DOTS ":"
+ ID_BREAK "break"
+ ID_SWITCH "switch"
+ ID_CASE "case"
+ ID_CONTINUE "continue"
+ ID_TRY "try"
+ ID_CATCH "catch"
+ ID_THROW "throw"
+ ID_FINALLY "finally"
+ ID_DEFAULT "default"
+END
+
+#endif // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/CBot/Copie de CBotTwoOpExpr.cpp b/src/CBot/Copie de CBotTwoOpExpr.cpp
new file mode 100644
index 0000000..7a95b55
--- /dev/null
+++ b/src/CBot/Copie de CBotTwoOpExpr.cpp
@@ -0,0 +1,295 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 + Opérande2
+// Opérande1 > Opérande2
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotTwoOpExpr::CBotTwoOpExpr()
+{
+ m_leftop =
+ m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
+ name = "CBotTwoOpExpr"; // debug
+}
+
+CBotTwoOpExpr::~CBotTwoOpExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+// type d'opérandes acceptés par les opérations
+#define ENTIER ((1<<CBotTypByte)|(1<<CBotTypShort)|(1<<CBotTypChar)|(1<<CBotTypInt)|(1<<CBotTypLong))
+#define FLOTANT ((1<<CBotTypFloat)|(1<<CBotTypDouble))
+#define BOOLEEN (1<<CBotTypBoolean)
+#define CHAINE (1<<CBotTypString)
+#define CLASSE (1<<CBotTypClass)
+
+// liste des opérations (précéance)
+static int ListOp[] =
+{
+ BOOLEEN, ID_LOG_OR, 0,
+ BOOLEEN, ID_LOG_AND, 0,
+ BOOLEEN|ENTIER, ID_OR, 0,
+ ENTIER, ID_XOR, 0,
+ BOOLEEN|ENTIER, ID_AND, 0,
+ BOOLEEN|ENTIER|FLOTANT, ID_EQ,
+ BOOLEEN|ENTIER|FLOTANT, ID_NE, 0,
+ ENTIER|FLOTANT, ID_HI,
+ ENTIER|FLOTANT, ID_LO,
+ ENTIER|FLOTANT, ID_HS,
+ ENTIER|FLOTANT, ID_LS, 0,
+ ENTIER, ID_SR,
+ ENTIER, ID_SL,
+ ENTIER, ID_ASR, 0,
+ ENTIER|FLOTANT|CHAINE, ID_ADD,
+ ENTIER|FLOTANT, ID_SUB, 0,
+ ENTIER|FLOTANT, ID_MUL,
+ ENTIER|FLOTANT, ID_DIV,
+ ENTIER|FLOTANT, ID_MODULO, 0,
+ 0,
+};
+
+BOOL IsInList( int val, int* list, int& typemasque )
+{
+ while (TRUE)
+ {
+ if ( *list == 0 ) return FALSE;
+ typemasque = *list++;
+ if ( *list++ == val ) return TRUE;
+ }
+}
+
+BOOL TypeOk( int type, int test )
+{
+ while (TRUE)
+ {
+ if ( type == 0 ) return (test & 1);
+ type--; test /= 2;
+ }
+}
+
+// compile une instruction de type A op B
+
+CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
+{
+ int typemasque;
+
+ if ( pOperations == NULL ) pOperations = ListOp;
+ int* pOp = pOperations;
+ while ( *pOp++ != 0 ); // suite de la table
+
+ CBotCStack* pStk = pStack->TokenStack(); // un bout de pile svp
+
+ // cherche des instructions qui peuvent convenir à gauche de l'opération
+ CBotInstr* left = (*pOp == 0) ?
+ CBotParExpr::Compile( p, pStk ) : // expression (...) à gauche
+ CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A * B à gauche
+
+ if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
+
+ // est-ce qu'on a l'opérande prévu ensuite ?
+ int TypeOp = p->GetType();
+ if ( IsInList( TypeOp, pOperations, typemasque ) )
+ {
+ CBotTwoOpExpr* inst = new CBotTwoOpExpr(); // élément pour opération
+ inst->SetToken(p); // mémorise l'opération
+
+ int type1, type2;
+ type1 = pStk->GetType(); // de quel type le premier opérande ?
+
+ p = p->Next(); // saute le token de l'opération
+
+ // cherche des instructions qui peuvent convenir à droite
+
+ if ( NULL != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOperations )) )
+ // expression (...) à droite
+ {
+ // il y a un second opérande acceptable
+
+ type2 = pStk->GetType(); // de quel type le résultat ?
+
+ // quel est le type du résultat ?
+ int TypeRes = MAX( type1, type2 );
+ if (!TypeOk( TypeRes, typemasque )) type1 = 99; // erreur de type
+
+ switch ( TypeOp )
+ {
+ case ID_LOG_OR:
+ case ID_LOG_AND:
+ case ID_EQ:
+ case ID_NE:
+ case ID_HI:
+ case ID_LO:
+ case ID_HS:
+ case ID_LS:
+ TypeRes = CBotTypBoolean;
+ }
+ if ( TypeCompatible (type1, type2) || // les résultats sont-ils compatibles
+ // cas particulier pour les concaténation de chaînes
+ (TypeOp == ID_ADD && (type1 == CBotTypString || type2 == CBotTypString)))
+ {
+ // si ok, enregistre l'opérande dans l'objet
+ inst->m_leftop = left;
+ // met une variable sur la pile pour avoir le type de résultat
+ pStk->SetVar(new CBotVar(NULL, TypeRes));
+ // et rend l'object à qui l'a demandé
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_BAD2TYPE, &inst->m_token);
+ }
+
+ // en cas d'erreur, libère les éléments
+ delete left;
+ delete inst;
+ // et transmet l'erreur qui se trouve sur la pile
+ return pStack->Return(NULL, pStk);
+ }
+
+ // si on n'a pas affaire à une opération + ou -
+ // rend à qui l'a demandé, l'opérande (de gauche) trouvé
+ // à la place de l'objet "addition"
+ return pStack->Return(left, pStk);
+}
+
+
+
+
+// fait l'opération d'addition ou de soustraction
+
+BOOL CBotTwoOpExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // selon la reprise, on peut être dans l'un des 2 états
+
+ if ( pStk1->GetState() == 0 && // 1er état, évalue l'opérande de gauche
+ !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ // passe à l'étape suivante
+ pStk1->SetState(1); // prêt pour la suite
+
+ // pour les OU et ET logique, n'évalue pas la seconde expression si pas nécessaire
+ if ( GetTokenType() == ID_LOG_AND && pStk1->GetVal() == FALSE )
+ {
+ CBotVar* res = CBotVar::Create( NULL, CBotTypBoolean);
+ res->SetValInt(FALSE);
+ pStk1->SetVar(res);
+ return pStack->Return(pStk1); // transmet le résultat
+ }
+ if ( GetTokenType() == ID_LOG_OR && pStk1->GetVal() == TRUE )
+ {
+ CBotVar* res = CBotVar::Create( NULL, CBotTypBoolean);
+ res->SetValInt(TRUE);
+ pStk1->SetVar(res);
+ return pStack->Return(pStk1); // transmet le résultat
+ }
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ // qui se trouve sur la pile, justement.
+
+ CBotStack* pStk2 = pStk1->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // 2e état, évalue l'opérande de droite
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+
+ int type1 = pStk1->GetType(); // de quels types les résultats ?
+ int type2 = pStk2->GetType();
+
+ // crée une variable temporaire pour y mettre le résultat
+ // quel est le type du résultat ?
+ int TypeRes = MAX(type1, type2);
+ switch ( GetTokenType() )
+ {
+ case ID_LOG_OR:
+ case ID_LOG_AND:
+ case ID_EQ:
+ case ID_NE:
+ case ID_HI:
+ case ID_LO:
+ case ID_HS:
+ case ID_LS:
+ TypeRes = CBotTypBoolean;
+ }
+ CBotVar* result = CBotVar::Create( NULL, TypeRes);
+ CBotVar* temp = CBotVar::Create( NULL, MAX(type1, type2) );
+
+ int err = 0;
+ // fait l'opération selon la demande
+ switch (GetTokenType())
+ {
+ case ID_ADD:
+ result->Add(pStk1->GetVar(), pStk2->GetVar()); // additionne
+ break;
+ case ID_SUB:
+ result->Sub(pStk1->GetVar(), pStk2->GetVar()); // soustrait
+ break;
+ case ID_MUL:
+ result->Mul(pStk1->GetVar(), pStk2->GetVar()); // multiplie
+ break;
+ case ID_DIV:
+ err = result->Div(pStk1->GetVar(), pStk2->GetVar());// divise
+ break;
+ case ID_MODULO:
+ err = result->Modulo(pStk1->GetVar(), pStk2->GetVar());// reste de division
+ break;
+ case ID_LO:
+ temp->Lo(pStk1->GetVar(), pStk2->GetVar()); // inférieur
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_HI:
+ temp->Hi(pStk1->GetVar(), pStk2->GetVar()); // supérieur
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_LS:
+ temp->Ls(pStk1->GetVar(), pStk2->GetVar()); // inférieur ou égal
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_HS:
+ temp->Hs(pStk1->GetVar(), pStk2->GetVar()); // supérieur ou égal
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_EQ:
+ temp->Eq(pStk1->GetVar(), pStk2->GetVar()); // égal
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_NE:
+ temp->Ne(pStk1->GetVar(), pStk2->GetVar()); // différent
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ break;
+ case ID_LOG_AND:
+ case ID_AND:
+ result->And(pStk1->GetVar(), pStk2->GetVar()); // ET
+ break;
+ case ID_LOG_OR:
+ case ID_OR:
+ result->Or(pStk1->GetVar(), pStk2->GetVar()); // OU
+ break;
+ case ID_XOR:
+ result->XOr(pStk1->GetVar(), pStk2->GetVar()); // OU exclusif
+ break;
+ case ID_ASR:
+ result->ASR(pStk1->GetVar(), pStk2->GetVar());
+ break;
+ case ID_SR:
+ result->SR(pStk1->GetVar(), pStk2->GetVar());
+ break;
+ case ID_SL:
+ result->SL(pStk1->GetVar(), pStk2->GetVar());
+ break;
+ default:
+ __asm int 3;
+ }
+ delete temp;
+
+ pStk2->SetVar(result); // met le résultat sur la pile
+ if ( err ) pStk2->SetError(err, &m_token); // et l'erreur éventuelle (division par zéro)
+
+ pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
+
diff --git a/src/CBot/StringFunctions.cpp b/src/CBot/StringFunctions.cpp
new file mode 100644
index 0000000..803ffd9
--- /dev/null
+++ b/src/CBot/StringFunctions.cpp
@@ -0,0 +1,420 @@
+// définition des fonctions sur les chaînes
+
+
+// donne la longueur d'une chaîne
+// exécution
+
+BOOL rStrLen( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // pas de second paramètre
+ if ( pVar->GivNext() != NULL ) { ex = TX_OVERPARAM ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // met la longueur sur la pile
+ pResult->SetValInt( s.GivLength() );
+ return TRUE;
+}
+
+// int xxx ( string )
+// compilation
+
+CBotTypResult cIntStr( CBotVar* &pVar, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADPARAM );
+
+ // pas de second paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( TX_OVERPARAM );
+
+ // le résultat final est un nombre entier
+ return CBotTypResult( CBotTypInt );
+}
+
+
+// donne la partie gauche d'une chaîne
+// exécution
+
+BOOL rStrLeft( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble ) { ex = TX_BADNUM ; return TRUE; }
+
+ // récupère ce nombre
+ int n = pVar->GivValInt();
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) { ex = TX_OVERPARAM ; return TRUE; }
+
+ // prend la partie intéressante
+ s = s.Left( n );
+
+ // la met sur la pile
+ pResult->SetValString( s );
+ return TRUE;
+}
+
+// string xxx ( string, int )
+// compilation
+
+CBotTypResult cStrStrInt( CBotVar* &pVar, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADSTRING );
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble )
+ return CBotTypResult( TX_BADNUM );
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( TX_OVERPARAM );
+
+ // le résultat final est une string
+ return CBotTypResult( CBotTypString );
+}
+
+// donne la partie droite d'une chaîne
+// exécution
+
+BOOL rStrRight( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble ) { ex = TX_BADNUM ; return TRUE; }
+
+ // récupère ce nombre
+ int n = pVar->GivValInt();
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) { ex = TX_OVERPARAM ; return TRUE; }
+
+ // prend la partie intéressante
+ s = s.Right( n );
+
+ // la met sur la pile
+ pResult->SetValString( s );
+ return TRUE;
+}
+
+// donne la partie centrale d'une chaîne
+// exécution
+
+BOOL rStrMid( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble ) { ex = TX_BADNUM ; return TRUE; }
+
+ // récupère ce nombre
+ int n = pVar->GivValInt();
+
+ // 3e paramètre optionnel
+ if ( pVar->GivNext() != NULL )
+ {
+ pVar = pVar->GivNext();
+
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble ) { ex = TX_BADNUM ; return TRUE; }
+
+ // récupère ce nombre
+ int l = pVar->GivValInt();
+
+ // mais pas de 4e paramètre
+ if ( pVar->GivNext() != NULL ){ ex = TX_OVERPARAM ; return TRUE; }
+
+ // prend la partie intéressante
+ s = s.Mid( n, l );
+ }
+ else
+ {
+ // prend la partie intéressante
+ s = s.Mid( n );
+ }
+
+ // la met sur la pile
+ pResult->SetValString( s );
+ return TRUE;
+}
+
+// donne la partie centrale d'une chaîne
+// compilation
+
+CBotTypResult cStrStrIntInt( CBotVar* &pVar, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADSTRING );
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble )
+ return CBotTypResult( TX_BADNUM );
+
+ // 3e paramètre optionnel
+ if ( pVar->GivNext() != NULL )
+ {
+
+ pVar = pVar->GivNext();
+ // qui doit être un nombre
+ if ( pVar->GivType() > CBotTypDouble )
+ return CBotTypResult( TX_BADNUM );
+
+ // pas de 4e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( TX_OVERPARAM );
+ }
+
+ // le résultat final est une string
+ return CBotTypResult( CBotTypString );
+}
+
+
+// donne le nombre contenu dans une chaîne
+// exécution
+
+BOOL rStrVal( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // mais pas de 2e paramètre
+ if ( pVar->GivNext() != NULL ){ ex = TX_OVERPARAM ; return TRUE; }
+
+ float val = GivNumFloat(s);
+
+ // la met la valeur sur la pile
+ pResult->SetValFloat( val );
+ return TRUE;
+}
+
+// float xxx ( string )
+// compilation
+
+CBotTypResult cFloatStr( CBotVar* &pVar, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADSTRING );
+
+ // pas de 2e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( TX_OVERPARAM );
+
+ // le résultat final est un nombre
+ return CBotTypResult( CBotTypFloat );
+}
+
+
+// trouve une chaine dans une autre
+// exécution
+
+BOOL rStrFind( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // récupère ce nombre
+ CBotString s2 = pVar->GivValString();
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) { ex = TX_OVERPARAM ; return TRUE; }
+
+ // met le résultat sur la pile
+ int res = s.Find(s2);
+ pResult->SetValInt( res );
+ if ( res < 0 ) pResult->SetInit( IS_NAN );
+ return TRUE;
+}
+
+// int xxx ( string, string )
+// compilation
+
+CBotTypResult cIntStrStr( CBotVar* &pVar, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADSTRING );
+
+ // il faut un second paramètre
+ pVar = pVar->GivNext();
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADSTRING );
+
+ // pas de 3e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( TX_OVERPARAM );
+
+ // le résultat final est un nombre
+ return CBotTypResult( CBotTypInt );
+}
+
+// donne une chaine en majuscule
+// exécution
+
+BOOL rStrUpper( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // mais pas de 2e paramètre
+ if ( pVar->GivNext() != NULL ){ ex = TX_OVERPARAM ; return TRUE; }
+
+
+ s.MakeUpper();
+
+ // la met la valeur sur la pile
+ pResult->SetValString( s );
+ return TRUE;
+}
+
+// donne une chaine en minuscules
+// exécution
+
+BOOL rStrLower( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) { ex = TX_LOWPARAM ; return TRUE; }
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString ) { ex = TX_BADSTRING ; return TRUE; }
+
+ // recupére le contenu de la string
+ CBotString s = pVar->GivValString();
+
+ // mais pas de 2e paramètre
+ if ( pVar->GivNext() != NULL ){ ex = TX_OVERPARAM ; return TRUE; }
+
+
+ s.MakeLower();
+
+ // la met la valeur sur la pile
+ pResult->SetValString( s );
+ return TRUE;
+}
+
+// string xxx ( string )
+// compilation
+
+CBotTypResult cStrStr( CBotVar* &pVar, void* pUser )
+{
+ // il faut un paramètre
+ if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
+
+ // qui doit être une string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( TX_BADSTRING );
+
+ // pas de 2e paramètre
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( TX_OVERPARAM );
+
+ // le résultat final est une string
+ return CBotTypResult( CBotTypString );
+}
+
+
+void InitStringFunctions()
+{
+ CBotProgram::AddFunction("strlen", rStrLen, cIntStr );
+ CBotProgram::AddFunction("strleft", rStrLeft, cStrStrInt );
+ CBotProgram::AddFunction("strright", rStrRight, cStrStrInt );
+ CBotProgram::AddFunction("strmid", rStrMid, cStrStrIntInt );
+
+ CBotProgram::AddFunction("strval", rStrVal, cFloatStr );
+ CBotProgram::AddFunction("strfind", rStrFind, cIntStrStr );
+
+ CBotProgram::AddFunction("strupper", rStrUpper, cStrStr );
+ CBotProgram::AddFunction("strlower", rStrLower, cStrStr );
+}
diff --git a/src/CBot/TestCBot/B.txt b/src/CBot/TestCBot/B.txt
new file mode 100644
index 0000000..53715f8
--- /dev/null
+++ b/src/CBot/TestCBot/B.txt
@@ -0,0 +1,18 @@
+
+ float [ ] TEST2 ( int [ ] param )
+ {
+ float [ ] z;
+ for ( int i = 0 ; i < sizeof( param ) ; i++ ) try { z [i] = param [i] / 3; }
+ return z;
+ }
+
+extern public void T()
+{
+ int a [4];
+ for ( int i = 0 ; i < 3 ; i++ ) a[i] = 4*i;
+ a [2] = 22;
+
+ float [] b ;
+ b = TEST2 ( a ) ;
+ show ( a, b );
+}
diff --git a/src/CBot/TestCBot/BUG2.txt b/src/CBot/TestCBot/BUG2.txt
new file mode 100644
index 0000000..44de05a
--- /dev/null
+++ b/src/CBot/TestCBot/BUG2.txt
@@ -0,0 +1,107 @@
+object object :: TT ( int n )
+{
+ object XX = radar();
+ if ( n == 0 ) return null;
+
+ while ( null == XX ) XX = radar();
+ return XX;
+}
+
+extern void object::Attack( )
+{
+ show ( TT ( 0 ) ) ;
+ show ( TT ( 1 ) ) ;
+ return;
+
+ int list[];
+ int i;
+ object p;
+ float dist, prox;
+ point dest;
+ boolean advance = true;
+
+ TEST(0); // ne stoppe pas si erreur
+// while ( F () != 0 ) F(1);
+
+ i = 0;
+ list[i++] = WingedGrabber;
+ list[i++] = TrackedGrabber;
+ list[i++] = WheeledGrabber;
+ list[i++] = LeggedGrabber;
+ list[i++] = WingedShooter;
+ list[i++] = TrackedShooter;
+ list[i++] = WheeledShooter;
+ list[i++] = LeggedShooter;
+ list[i++] = WingedOrgaShooter;
+ list[i++] = TrackedOrgaShooter;
+ list[i++] = WheeledOrgaShooter;
+ list[i++] = LeggedOrgaShooter;
+ list[i++] = WingedSniffer;
+ list[i++] = TrackedSniffer;
+ list[i++] = WheeledSniffer;
+ list[i++] = LeggedSniffer;
+ list[i++] = Thumper;
+ list[i++] = PhazerShooter;
+ list[i++] = Recycler;
+ list[i++] = Shielder;
+ list[i++] = Subber;
+ list[i++] = Me;
+ list[i++] = 3333;
+ list[i++] = 3334;
+ list[i++] = 3335;
+ list[i++] = 3336;
+ list[i++] = 3337;
+ list[i++] = 3338;
+ list[i++] = 3339;
+ list[i++] = 3331;
+ list[i++] = 3332;
+ list[i++] = 3330;
+ list[i++] = 1111;
+ list[i++] = 1112;
+
+ F(F(0));
+
+ while ( true )
+ {
+ p = radar(list, 0, 360, 0, 1000);
+ if ( p == null )
+ {
+ F(2);
+ }
+ else
+ {
+ dist = F(p.position, position);
+ if ( dist <= 40 && !advance )
+ {
+ fire(p.position);
+ advance = true;
+ }
+ else
+ {
+//? if ( RetBaseDistance() > 20 )
+ {
+ prox = dist-(5+F()*5);
+ if ( prox < 5 ) prox = 5;
+ dest.x = (position.x-p.position.x)*prox/dist + p.position.x;
+ dest.y = (position.y-p.position.y)*prox/dist + p.position.y;
+ dest.z = (position.z-p.position.z)*prox/dist + p.position.z;
+ goto(dest);
+ advance = false;
+ }
+ }
+ }
+ }
+}
+
+// Calcule la distance jusqu'à la base.
+
+float object::RetBaseDistance()
+{
+ object p;
+ float dist;
+
+ p = radar(4444, 0, 360, 0, 1000);
+ if ( p == null ) return 1000;
+ dist = F(p.position, position);
+ return dist;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/CBotConsoleDlg.cpp b/src/CBot/TestCBot/CBotConsoleDlg.cpp
new file mode 100644
index 0000000..5f29e86
--- /dev/null
+++ b/src/CBot/TestCBot/CBotConsoleDlg.cpp
@@ -0,0 +1,205 @@
+// CBotConsoleDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "TestCBot.h"
+#include "CBotConsoleDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotConsoleDlg dialog
+
+
+CBotConsoleDlg::CBotConsoleDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CBotConsoleDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CBotConsoleDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ m_pProg = NULL;
+ m_threadinfo.m_bRun = FALSE;
+ m_code = 0;
+}
+
+
+void CBotConsoleDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBotConsoleDlg)
+ DDX_Control(pDX, IDOK, m_cOK);
+ DDX_Control(pDX, IDC_EDIT2, m_Edit2);
+ DDX_Control(pDX, IDC_EDIT1, m_Edit1);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CBotConsoleDlg, CDialog)
+ //{{AFX_MSG_MAP(CBotConsoleDlg)
+ ON_MESSAGE(WM_ENDPROG, EndProg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotConsoleDlg message handlers
+
+UINT ThreadProc(ThreadInfo *info)
+{
+ CTime t0 = CTime::GetCurrentTime();
+ int Cpt = 0;
+
+ info->m_pProg->Start("LaCommande");
+ while ( !info->m_bStop && !info->m_pProg->Run() )
+ {
+#if 0
+ const char* FunctionName;
+ const char* FN;
+ int start, end;
+
+ info->m_pProg->GetRunPos(FunctionName, start, end);
+
+ if ( FunctionName != NULL )
+ {
+ info->m_pEditx->SetSel(start, end);
+
+ char buffer[200];
+ sprintf( buffer, "step %s, %d, %d",FunctionName, start, end);
+ AfxMessageBox( buffer );
+
+ int level = 0;
+ do
+ {
+ CBotVar* t = info->m_pProg->GivStackVars(FN, level--);
+ if ( FN != FunctionName ) break;
+ if ( t != NULL )
+ {
+ CString s ;
+ while ( t != NULL )
+ {
+ if (s.IsEmpty()) s+= "Stack -> ";
+ else s+= " , ";
+ s += t->GivValString();
+ t = t->GivNext();
+ }
+ AfxMessageBox(s);
+ }
+ } while (TRUE);
+ }
+#endif
+ Cpt++;
+ if ( Cpt%50 == 0 ) info->m_pEdit1->ReplaceSel(".");
+ }
+
+ if ( info->m_bStop )
+ {
+ info->m_pEdit1->ReplaceSel("\r\nInterrompu\r\n");
+ }
+ else if (info->m_pProg->GivError() == 0)
+ {
+ CTime t = CTime::GetCurrentTime();
+ CTimeSpan ts = t - t0;
+
+ char buffer[200];
+ sprintf( buffer, "\r\nExécution terminée en %d secondes.\r\nInterrompue %d fois.\r\n",
+ ts.GetTotalSeconds(), Cpt);
+
+ info->m_pEdit1->ReplaceSel(buffer);
+ }
+
+ info->m_pWndMessage->SendMessage(WM_ENDPROG, 0, 0) ;
+ return 0 ;
+}
+
+LONG CBotConsoleDlg::EndProg(UINT wparam, LONG lparam)
+{
+ m_threadinfo.m_bRun = FALSE;
+
+ if (m_pProg->GetError(m_code, m_start, m_end))
+ {
+ CBotString TextError;
+ TextError = CBotProgram::GivErrorText(m_code);
+ AfxMessageBox(TextError);
+ CDialog::OnCancel();
+ return 1;
+ }
+ delete m_pProg;
+ m_pProg = NULL;
+
+ m_Edit2.EnableWindow(TRUE);
+ m_cOK.EnableWindow(TRUE);
+
+ m_Edit2.SetWindowText("");
+ m_Edit2.SetFocus();
+ return 0 ;
+}
+
+void CBotConsoleDlg::OnOK()
+{
+ CTestCBotApp* pApp = (CTestCBotApp*)AfxGetApp();
+ pApp->m_pConsole = &m_Edit1;
+ m_code = 0;
+
+ CString Commande;
+ m_Edit2.GetWindowText(Commande);
+
+ CString s = "void LaCommande() { " + Commande + " ;}";
+ m_pProg = new CBotProgram();
+ CBotStringArray liste;
+ m_pProg->Compile(s, liste);
+
+ int err, start, end;
+ if ( m_pProg->GetError(err, start, end) )
+ {
+ CBotString TextError;
+ TextError = CBotProgram::GivErrorText(err);
+ AfxMessageBox(TextError);
+ m_Edit2.SetSel(start-20, end-20);
+ return;
+ }
+
+ m_Edit1.ReplaceSel("\r\n" + Commande + " ->\r\n");
+
+ m_Edit2.SetWindowText("");
+ m_Edit1.SetFocus();
+ m_Edit2.EnableWindow(FALSE);
+ m_cOK.EnableWindow(FALSE);
+
+ // lance un processus paralèle pour l'exécution
+ m_threadinfo.m_pWndMessage = this ;
+
+ m_threadinfo.m_pEdit1 = &m_Edit1;
+ m_threadinfo.m_pEditx = m_pEditx;
+ m_threadinfo.m_pProg = m_pProg;
+ m_threadinfo.m_bStop = FALSE;
+ m_threadinfo.m_bRun = TRUE;
+
+ AfxBeginThread((AFX_THREADPROC)ThreadProc, &m_threadinfo) ;
+}
+
+void CBotConsoleDlg::OnCancel()
+{
+ if (!m_threadinfo.m_bRun) CDialog::OnCancel();
+ m_threadinfo.m_bStop = TRUE ;
+}
+
+
+BOOL CBotConsoleDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_Edit1.ReplaceSel("Les fonctions suivantes sont disponibles:\r\n");
+ for ( int i = 0; i < m_pListe->GivSize(); i++ )
+ {
+ CBotString x = (*m_pListe)[i] + "\r\n";
+ m_Edit1.ReplaceSel(x);
+ }
+ m_Edit1.ReplaceSel("Entrez une commande ci-dessous.\r\n\r\n");
+
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/src/CBot/TestCBot/CBotConsoleDlg.h b/src/CBot/TestCBot/CBotConsoleDlg.h
new file mode 100644
index 0000000..bae9793
--- /dev/null
+++ b/src/CBot/TestCBot/CBotConsoleDlg.h
@@ -0,0 +1,69 @@
+#if !defined(AFX_BOTCONSOLEDLG_H__A11450A2_8E09_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_BOTCONSOLEDLG_H__A11450A2_8E09_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// CBotConsoleDlg.h : header file
+//
+
+struct ThreadInfo
+{
+ CEdit* m_pEdit1 ;
+ CEdit* m_pEditx ;
+ CBotProgram* m_pProg;
+ CWnd* m_pWndMessage;
+ BOOL m_bStop;
+ BOOL m_bRun;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotConsoleDlg dialog
+
+class CBotConsoleDlg : public CDialog
+{
+// Construction
+public:
+ CBotConsoleDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CBotConsoleDlg)
+ enum { IDD = IDD_CONSOLE };
+ CButton m_cOK;
+ CEdit m_Edit2;
+ CEdit m_Edit1;
+ //}}AFX_DATA
+
+ CBotProgram* m_pProg;
+ ThreadInfo m_threadinfo;
+
+ CBotStringArray*
+ m_pListe;
+ int m_code, m_start, m_end;
+ CEdit* m_pEditx;
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBotConsoleDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CBotConsoleDlg)
+ virtual void OnOK();
+ virtual void OnCancel();
+ virtual BOOL OnInitDialog();
+ afx_msg LONG EndProg(UINT wparam, LONG lparam) ;
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_BOTCONSOLEDLG_H__A11450A2_8E09_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/ChildFrm.cpp b/src/CBot/TestCBot/ChildFrm.cpp
new file mode 100644
index 0000000..9005c72
--- /dev/null
+++ b/src/CBot/TestCBot/ChildFrm.cpp
@@ -0,0 +1,58 @@
+// ChildFrm.cpp : implementation of the CChildFrame class
+//
+
+#include "stdafx.h"
+#include "TestCBot.h"
+
+#include "ChildFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame
+
+IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)
+
+BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
+ //{{AFX_MSG_MAP(CChildFrame)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame construction/destruction
+
+CChildFrame::CChildFrame()
+{
+}
+
+CChildFrame::~CChildFrame()
+{
+}
+
+BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+ return CMDIChildWnd::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame diagnostics
+
+#ifdef _DEBUG
+void CChildFrame::AssertValid() const
+{
+ CMDIChildWnd::AssertValid();
+}
+
+void CChildFrame::Dump(CDumpContext& dc) const
+{
+ CMDIChildWnd::Dump(dc);
+}
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame message handlers
diff --git a/src/CBot/TestCBot/ChildFrm.h b/src/CBot/TestCBot/ChildFrm.h
new file mode 100644
index 0000000..ebcbeb2
--- /dev/null
+++ b/src/CBot/TestCBot/ChildFrm.h
@@ -0,0 +1,50 @@
+// ChildFrm.h : interface of the CChildFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CHILDFRM_H__4D1BB909_8E74_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_CHILDFRM_H__4D1BB909_8E74_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CChildFrame : public CMDIChildWnd
+{
+ DECLARE_DYNCREATE(CChildFrame)
+public:
+ CChildFrame();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CChildFrame)
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CChildFrame();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CChildFrame)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CHILDFRM_H__4D1BB909_8E74_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/Deleted.txt b/src/CBot/TestCBot/Deleted.txt
new file mode 100644
index 0000000..469a624
--- /dev/null
+++ b/src/CBot/TestCBot/Deleted.txt
@@ -0,0 +1,23 @@
+public extern void object :: ESSAI()
+{
+ while(true)
+ {
+ if ( true )
+ {
+ goto(12);
+ break;
+ }
+ }
+ object x = null ;
+
+ while ( x == null ) x = radar();
+
+ show ( x.position ) ;
+
+ TEST(5, x);
+
+ if ( x == null ) show ( "DELETED" );
+
+ show ( x.position ) ;
+
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/MaClass.txt b/src/CBot/TestCBot/MaClass.txt
new file mode 100644
index 0000000..ac472b4
--- /dev/null
+++ b/src/CBot/TestCBot/MaClass.txt
@@ -0,0 +1,16 @@
+
+class MaClass
+{
+ int a = 1 ;
+ MaClass pointeur ;
+ MaClass next = null ;
+ CPoint autre = new CPoint( 1 , 1 ) ;
+}
+
+extern public void Test ( )
+{
+ MaClass x () ;
+ x.next = new MaClass ( ) ;
+ println ( x ) ;
+}
+
diff --git a/src/CBot/TestCBot/MainFrm.cpp b/src/CBot/TestCBot/MainFrm.cpp
new file mode 100644
index 0000000..e151cce
--- /dev/null
+++ b/src/CBot/TestCBot/MainFrm.cpp
@@ -0,0 +1,100 @@
+// MainFrm.cpp : implementation of the CMainFrame class
+//
+
+#include "stdafx.h"
+#include "TestCBot.h"
+
+#include "MainFrm.h"
+#include "TestCBotDoc.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame
+
+IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
+
+BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
+ //{{AFX_MSG_MAP(CMainFrame)
+ ON_WM_CREATE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+static UINT indicators[] =
+{
+ ID_SEPARATOR, // status line indicator
+ ID_INDICATOR_CAPS,
+ ID_INDICATOR_NUM,
+ ID_INDICATOR_SCRL,
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame construction/destruction
+
+CMainFrame::CMainFrame()
+{
+}
+
+CMainFrame::~CMainFrame()
+{
+}
+
+int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ if (!m_wndToolBar.Create(this) ||
+ !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
+ {
+ TRACE0("Failed to create toolbar\n");
+ return -1; // fail to create
+ }
+
+ if (!m_wndStatusBar.Create(this) ||
+ !m_wndStatusBar.SetIndicators(indicators,
+ sizeof(indicators)/sizeof(UINT)))
+ {
+ TRACE0("Failed to create status bar\n");
+ return -1; // fail to create
+ }
+
+ m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
+ CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+
+ m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
+ EnableDocking(CBRS_ALIGN_ANY);
+ DockControlBar(&m_wndToolBar);
+
+ return 0;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+ return CMDIFrameWnd::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame diagnostics
+
+#ifdef _DEBUG
+void CMainFrame::AssertValid() const
+{
+ CMDIFrameWnd::AssertValid();
+}
+
+void CMainFrame::Dump(CDumpContext& dc) const
+{
+ CMDIFrameWnd::Dump(dc);
+}
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame message handlers
+
+
diff --git a/src/CBot/TestCBot/MainFrm.h b/src/CBot/TestCBot/MainFrm.h
new file mode 100644
index 0000000..b9d68db
--- /dev/null
+++ b/src/CBot/TestCBot/MainFrm.h
@@ -0,0 +1,56 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINFRM_H__4D1BB907_8E74_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_MAINFRM_H__4D1BB907_8E74_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CMainFrame : public CMDIFrameWnd
+{
+ DECLARE_DYNAMIC(CMainFrame)
+public:
+ CMainFrame();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CMainFrame)
+ public:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CMainFrame();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected: // control bar embedded members
+ CStatusBar m_wndStatusBar;
+ CToolBar m_wndToolBar;
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CMainFrame)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINFRM_H__4D1BB907_8E74_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/Mc2.txt b/src/CBot/TestCBot/Mc2.txt
new file mode 100644
index 0000000..172c259
--- /dev/null
+++ b/src/CBot/TestCBot/Mc2.txt
@@ -0,0 +1,4 @@
+class MaClass
+{
+ int t = 12;
+}
diff --git a/src/CBot/TestCBot/Mon fichier.txt b/src/CBot/TestCBot/Mon fichier.txt
new file mode 100644
index 0000000..6b35bf8
--- /dev/null
+++ b/src/CBot/TestCBot/Mon fichier.txt
@@ -0,0 +1,2 @@
+Voici encore du texte
+et une seconde ligne
diff --git a/src/CBot/TestCBot/Nop.txt b/src/CBot/TestCBot/Nop.txt
new file mode 100644
index 0000000..6a66f6f
--- /dev/null
+++ b/src/CBot/TestCBot/Nop.txt
@@ -0,0 +1,4 @@
+public extern void Nop()
+{
+ while ( true ) {}
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/POS.txt b/src/CBot/TestCBot/POS.txt
new file mode 100644
index 0000000..688e4fb
--- /dev/null
+++ b/src/CBot/TestCBot/POS.txt
@@ -0,0 +1,14 @@
+void object :: T ( )
+{
+ show ( position ) ;
+}
+
+public extern void object :: POS()
+{
+ for ( int i = 0; i < 10 ; i++ )
+ {
+ if ( i == 2 ) TEST ( 12 ) ;
+// show ( position );
+ T ( ) ;
+ }
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/PerformDlg.cpp b/src/CBot/TestCBot/PerformDlg.cpp
new file mode 100644
index 0000000..a541f0b
--- /dev/null
+++ b/src/CBot/TestCBot/PerformDlg.cpp
@@ -0,0 +1,161 @@
+// PerformDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "testcbot.h"
+#include "PerformDlg.h"
+
+//#include <stdio.h>
+#include <sys/timeb.h>
+//#include <time.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPerformDlg dialog
+
+
+CPerformDlg::CPerformDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CPerformDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CPerformDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CPerformDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CPerformDlg)
+ DDX_Control(pDX, IDC_EDIT3, m_Edit3);
+ DDX_Control(pDX, IDC_EDIT1, m_Edit1);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CPerformDlg, CDialog)
+ //{{AFX_MSG_MAP(CPerformDlg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPerformDlg message handlers
+
+/* Pauses for a specified number of milliseconds. */
+
+/*void sleep( double waitseconds )
+{
+ clock_t wait = (clock_t)(waitseconds * CLOCKS_PER_SEC);
+ clock_t goal;
+ goal = wait + clock();
+ while( goal > clock() )
+ ;
+}*/
+
+void sleep( clock_t wait )
+{
+ clock_t goal;
+ goal = wait + clock();
+ while( goal > clock() )
+ TRACE("%d \n", clock() );
+}
+
+void sleep2( clock_t wait )
+{
+ struct _timeb timebuffer;
+ char *timeline;
+
+ _ftime( &timebuffer );
+ timeline = ctime( & ( timebuffer.time ) );
+ long x = timebuffer.millitm;
+ while( x == timebuffer.millitm ) _ftime( &timebuffer );
+}
+
+#define NBLP 20
+
+UINT ThreadProc2(ThreadInfo2 *info)
+{
+ int lp = NBLP;
+ int i;
+ clock_t start = clock();
+
+ while ( !info->m_bStop )
+ {
+ for ( i = 0; i< info->m_nbscripts; i++ )
+ {
+ info->m_pProg[i]->Run();
+ }
+
+#ifdef _DEBUG
+ sleep2( 1 );
+#else
+ CString s ( "xx" );
+ for ( long z = 0x5000; z>0; z-- ) s = s.Left(1);
+#endif
+ if ( --lp == 0 )
+ {
+ clock_t finish = clock();
+ double n = (double)NBLP / (double)(finish-start) * CLOCKS_PER_SEC;
+ char b[30];
+ sprintf( b, "%f", n);
+ info->m_pEdit->SetWindowText(b);
+
+ n = n * 1100 / 200; // performances
+ sprintf( b, "%f", n);
+ info->m_pEdit3->SetWindowText(b);
+ start = finish;
+ lp = NBLP;
+ }
+ }
+
+ return 0 ;
+}
+
+BOOL CPerformDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+
+ CBotStringArray liste;
+ // crée les scripts pour les tests
+ for ( int i = 0; i < 100; i++ )
+ {
+ m_pProg[i] = new CBotProgram();
+ m_pProg[i]->Compile(m_Script, liste);
+ m_pProg[i]->Start(liste[0]);
+ }
+
+ // lance un processus paralèle pour l'exécution
+// m_threadinfo2.m_pWndMessage = this ;
+
+ m_threadinfo2.m_pEdit = &m_Edit1;
+ m_threadinfo2.m_pEdit3 = &m_Edit3;
+ m_threadinfo2.m_pProg = m_pProg;
+ m_threadinfo2.m_bStop = FALSE;
+ m_threadinfo2.m_nbscripts = 30;
+
+
+ AfxBeginThread((AFX_THREADPROC)ThreadProc2, &m_threadinfo2) ;
+ // TODO: Add extra initialization here
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CPerformDlg::OnCancel()
+{
+ m_threadinfo2.m_bStop = TRUE;
+ sleep ( 2000 );
+
+ CDialog::OnCancel();
+
+ for ( int i = 0; i < 100; i++ )
+ {
+ delete m_pProg[i];
+ }
+}
diff --git a/src/CBot/TestCBot/PerformDlg.h b/src/CBot/TestCBot/PerformDlg.h
new file mode 100644
index 0000000..77ca71a
--- /dev/null
+++ b/src/CBot/TestCBot/PerformDlg.h
@@ -0,0 +1,62 @@
+#if !defined(AFX_PERFORMDLG_H__EAF2D560_97D8_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_PERFORMDLG_H__EAF2D560_97D8_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// PerformDlg.h : header file
+//
+
+struct ThreadInfo2
+{
+ CEdit* m_pEdit ;
+ CEdit* m_pEdit3 ;
+
+ CBotProgram** m_pProg;
+ BOOL m_bStop;
+ int m_nbscripts;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CPerformDlg dialog
+
+class CPerformDlg : public CDialog
+{
+// Construction
+public:
+ CPerformDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CPerformDlg)
+ enum { IDD = IDD_DIALOG1 };
+ CEdit m_Edit3;
+ CEdit m_Edit1;
+ //}}AFX_DATA
+
+ CBotProgram* m_pProg[100];
+ ThreadInfo2 m_threadinfo2;
+ CString m_Script;
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPerformDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CPerformDlg)
+ virtual BOOL OnInitDialog();
+ virtual void OnCancel();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PERFORMDLG_H__EAF2D560_97D8_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/Routines.cpp b/src/CBot/TestCBot/Routines.cpp
new file mode 100644
index 0000000..cd3a32b
--- /dev/null
+++ b/src/CBot/TestCBot/Routines.cpp
@@ -0,0 +1,139 @@
+
+
+////////////////////////////////////////////////////////////////////
+// routine show()
+// utilisable depuis le programme écrit en CBot
+
+// exécution
+BOOL rShow( CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser )
+{
+ CString s;
+
+ while ( pVar != NULL )
+ {
+ CString ss;
+ ss.LoadString( TX_TYPENAMES + pVar->GivType() );
+ s += ss + " ";
+
+ ss = pVar->GivName();
+ if (ss.IsEmpty()) ss = "<sans nom>";
+ s += ss + " = ";
+
+ s += pVar->GivValString();
+ s += "\n";
+ pVar = pVar->GivNext();
+ }
+
+ AfxMessageBox(s, MB_OK|MB_ICONINFORMATION);
+
+ return TRUE; // pas d'interruption
+}
+
+CBotTypResult cShow( CBotVar* &pVar, void* pUser)
+{
+ if ( pVar == NULL ) return CBotTypResult(5028);
+ return CBotTypResult(0); // tous paramètres acceptés, void en retour
+}
+
+
+////////////////////////////////////////////////////////////////////
+// routine print()
+// utilisable depuis le programme écrit en CBot
+
+// exécution
+BOOL rPrintLn( CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser )
+{
+ CString s;
+
+ CTestCBotApp* pApp = (CTestCBotApp*)AfxGetApp();
+ CEdit* pEdit = pApp->m_pConsole;
+
+ if (pEdit == NULL) return TRUE;
+ pEdit->GetWindowText(s);
+
+ while ( pVar != NULL )
+ {
+ if ( !s.IsEmpty() ) s += " ";
+ s += pVar->GivValString();
+ pVar = pVar->GivNext();
+ }
+ s += "\r\n";
+
+ pEdit->SetWindowText(s);
+ pEdit->SetSel(s.GetLength(), s.GetLength());
+ pEdit->SetFocus();
+ return TRUE; // pas d'interruption
+}
+
+BOOL rPrint( CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser )
+{
+ CString s;
+
+ CTestCBotApp* pApp = (CTestCBotApp*)AfxGetApp();
+ CEdit* pEdit = pApp->m_pConsole;
+
+ if (pEdit == NULL) return TRUE;
+ pEdit->GetWindowText(s);
+
+ while ( pVar != NULL )
+ {
+ if ( !s.IsEmpty() ) s += " ";
+ s += pVar->GivValString();
+ pVar = pVar->GivNext();
+ }
+
+ pEdit->SetWindowText(s);
+ pEdit->SetSel(s.GetLength(), s.GetLength());
+ pEdit->SetFocus();
+ return TRUE; // pas d'interruption
+}
+
+CBotTypResult cPrint( CBotVar* &pVar, void* pUser)
+{
+ return CBotTypResult(0); // tous paramètres acceptés, un entier en retour
+}
+
+
+//////////////////////////////////////////////////////////////////
+// class CPoint pour essayer
+
+// exécution
+BOOL rCPoint( CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ CString s;
+
+ if ( pVar == NULL )return TRUE; // constructeur sans paramètres est ok
+
+ CBotVar* pX = pThis->GivItem("x");
+ pX->SetValFloat( pVar->GivValFloat() );
+ pVar = pVar->GivNext();
+
+ CBotVar* pY = pThis->GivItem("y");
+ pY->SetValFloat( pVar->GivValFloat() );
+ pVar = pVar->GivNext();
+
+ return TRUE; // pas d'interruption
+}
+
+CBotTypResult cCPoint( CBotVar* pThis, CBotVar* &pVar)
+{
+ // ok si aucun paramètres !
+ if ( pVar == NULL ) return CBotTypResult(0);
+
+ // paramètre de type numérique svp
+ if ( pVar->GivType() > CBotTypDouble ) return CBotTypResult(5011);
+ pVar = pVar->GivNext();
+
+ // il doit y avoir un second paramètre
+ if ( pVar == NULL ) return 5028;
+ // également de type numérique
+ if ( pVar->GivType() > CBotTypDouble )return CBotTypResult(5011);
+ pVar = pVar->GivNext();
+
+ // et pas plus de 2 paramètres svp
+ if ( pVar != NULL ) return CBotTypResult(5026);
+
+ return CBotTypResult(0); // cette fonction retourne void
+}
+
+
diff --git a/src/CBot/TestCBot/StdAfx.cpp b/src/CBot/TestCBot/StdAfx.cpp
new file mode 100644
index 0000000..b1dde8d
--- /dev/null
+++ b/src/CBot/TestCBot/StdAfx.cpp
@@ -0,0 +1,6 @@
+// stdafx.cpp : source file that includes just the standard includes
+// TestCBot.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/src/CBot/TestCBot/StdAfx.h b/src/CBot/TestCBot/StdAfx.h
new file mode 100644
index 0000000..7be8c40
--- /dev/null
+++ b/src/CBot/TestCBot/StdAfx.h
@@ -0,0 +1,26 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__4D1BB905_8E74_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_STDAFX_H__4D1BB905_8E74_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdisp.h> // MFC OLE automation classes
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__4D1BB905_8E74_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/T.txt b/src/CBot/TestCBot/T.txt
new file mode 100644
index 0000000..50a792b
--- /dev/null
+++ b/src/CBot/TestCBot/T.txt
@@ -0,0 +1,4 @@
+public extern int T ( float n )
+{
+ return n * 1.1;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/TESTALL.txt b/src/CBot/TestCBot/TESTALL.txt
new file mode 100644
index 0000000..82247a0
--- /dev/null
+++ b/src/CBot/TestCBot/TESTALL.txt
@@ -0,0 +1,161 @@
+int T ( int z )
+{
+ return 45 + z ;
+}
+
+class toto
+{
+ int val = 3 ;
+ int x = 3 * 3 ;
+ void toto( int n )
+ { val = n + 3 ; }
+ int retval ( int param )
+ { int r = val + param + x ;
+ val = param ;
+ return r ; }
+}
+
+public extern void object :: Chose( )
+{
+ int z [ 6 ];
+ for ( int i = 0 ; i < 6 ; ) z [ i++ ] = 3 - i ;
+ show ( z ) ;
+ return;
+
+ // test des tableaux
+ int [ ] a [ 3 ] ;
+// a = null;
+ if ( a == null ) show ( "NULL" );
+
+ a [ 2 / 2 ] [ 2 ]= 5 ;
+ int [ ] b ; b = a [1] ;
+ b [ 0 ] = -4;
+ a [ 4 / 2 ] [ 1 ]= 1 ;
+ show ( a , b ) ;
+ return ;
+ {
+ toto chose = new toto (5 ) ;
+ toto truc = chose ;
+ show ( chose, chose.retval( 100 ) ,
+ truc, truc.retval (40 ) ) ;
+
+ return;
+ }
+ {
+ point A = new
+ point ( 4 * 4 , 2 ) ;
+ show ( A ) ;
+ return;
+ }
+ {
+ show ( T ( 1 ) , T ( 3.7 ) ) ;
+ return;
+ }
+
+ {
+ point A ( 3, 4 ) ,
+ B = A ;
+
+ int n = -4;
+ show ( n );
+
+ show ( A, B ) ;
+
+ boolean a = false;
+ boolean b = a or true;
+ if ( not a and b ) ;
+ return;
+ }
+ {
+ // test try
+ float x = nan ; int z = 0 ;
+ try {
+// throw ( 3 * 4 + 33 ) ;
+ int zz ; goto ( 12 ) ; z = 1 ; z = 0 / 0 ; z = 2 ;
+ }
+ catch ( 45 + 0 * 6000 )
+ {
+ show( "Exception 6000", z ) ;
+ }
+ catch ( x == 0 ) { show( "x nul" ) ; }
+ finally { show ( "fini" ) ; }
+ show ( "continue" );
+ return;
+ }
+ {
+ // test des if
+ int a = 3;
+ if ( a == 3 ) show ( "33");
+ else show ( "44");
+ if ( a != 3 ) show ( "333");
+ else show ( "444");
+ return;
+ }
+ {
+ int a = 0;
+ // test break
+un:
+ while ( true )
+ {
+deux:
+ while ( true )
+ {
+ a++;
+ if ( a == 2 ) continue;
+ if ( a == 3 ) break deux;
+ show ( a ) ;
+ if ( a == 5 ) break un;
+ }
+ show ( "DEUX" );
+ }
+ return;
+ }
+ {
+ // test switch
+ int a = 0;
+
+ switch ( a )
+ {
+ case 1 : show( "un" ) ; break;
+ case 2 : show( "deux" ) ; // break;
+ case 3 : show( "trois" ) ; break;
+ case 4 : show( "quatre" ) ; // break;
+ default : show( "par défaut" ) ;
+ }
+ return;
+ }
+ {
+ // test boucle while
+ float z = 3.3;
+ while ( z > 0 )
+ { show ( z-- ) ; }
+ return;
+ }
+
+ {
+ // test boucle do
+ float y = 3.3;
+ do { int x = 0; show(y); y++; } while ( y < 7 ) ;
+ return;
+ }
+ // test boucle for
+ int j = -7; show ( j );
+ for ( int ii = 3, j = 31; ii < 6 ; ++ii, j = j -3 )
+ {
+ j = 10 * j;
+ show ( ii, j );
+ }
+ return;
+{
+ // déclarations de variables
+ int a; int b = 3; int c = 4*b, d = 1, e;
+ float x; float y = 3.3; float z = y / 2, u = 1, v;
+ boolean t; boolean tt = true or false; boolean ttt = false, tttt = true, t5;
+ string s; string ss = "hello"; string s2 = ss + " plus", s3 = "s3", s4;
+
+ show( b, c, d );
+ show( y, z, u );
+ show( tt, ttt, tttt );
+ show( ss, s2, s3 );
+}
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/TestCB1.txt b/src/CBot/TestCBot/TestCB1.txt
new file mode 100644
index 0000000..516db47
--- /dev/null
+++ b/src/CBot/TestCBot/TestCB1.txt
@@ -0,0 +1,18 @@
+extern public void toto()
+{
+ print( "hello" ) ;
+ print( fac(5) );
+ print( t() ) ;
+}
+
+public int fac(int n)
+{
+ if ( n<2 ) return 1;
+ return n * fac(n-1);
+}
+
+point t()
+{
+ point a(1,2);
+ return a;
+}
diff --git a/src/CBot/TestCBot/TestCBot.clw b/src/CBot/TestCBot/TestCBot.clw
new file mode 100644
index 0000000..13f20f4
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot.clw
@@ -0,0 +1,316 @@
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CPerformDlg
+LastTemplate=CDialog
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "testcbot.h"
+LastPage=0
+
+ClassCount=8
+Class1=CBotConsoleDlg
+Class2=CChildFrame
+Class3=CMainFrame
+Class4=CTestCBotApp
+Class5=CAboutDlg
+Class6=CTestCBotDoc
+Class7=CTestCBotView
+
+ResourceCount=12
+Resource1=IDD_CONSOLE
+Resource2=IDR_TESTCBTYPE (French (France))
+Resource3=IDD_ABOUTBOX (French (France))
+Resource4=IDR_MAINFRAME (French (France))
+Resource5=IDR_MAINFRAME
+Resource6=IDR_TESTCBTYPE
+Resource7=IDD_ABOUTBOX
+Resource8=IDD_CONSOLE (French (Switzerland))
+Class8=CPerformDlg
+Resource9=IDD_DIALOG1
+Resource10=IDD_DIALOG2
+Resource11=IDD_DIALOG1 (French (Switzerland))
+Resource12=IDD_DIALOG2 (French (France))
+
+[CLS:CBotConsoleDlg]
+Type=0
+BaseClass=CDialog
+HeaderFile=CBotConsoleDlg.h
+ImplementationFile=CBotConsoleDlg.cpp
+LastObject=IDC_EDIT1
+
+[CLS:CChildFrame]
+Type=0
+BaseClass=CMDIChildWnd
+HeaderFile=ChildFrm.h
+ImplementationFile=ChildFrm.cpp
+
+[CLS:CMainFrame]
+Type=0
+BaseClass=CMDIFrameWnd
+HeaderFile=MainFrm.h
+ImplementationFile=MainFrm.cpp
+Filter=T
+VirtualFilter=fWC
+LastObject=CMainFrame
+
+[CLS:CTestCBotApp]
+Type=0
+BaseClass=CWinApp
+HeaderFile=TestCBot.h
+ImplementationFile=TestCBot.cpp
+Filter=N
+VirtualFilter=AC
+LastObject=ID_TEST
+
+[CLS:CAboutDlg]
+Type=0
+BaseClass=CDialog
+HeaderFile=TestCBot.cpp
+ImplementationFile=TestCBot.cpp
+LastObject=CAboutDlg
+
+[CLS:CTestCBotDoc]
+Type=0
+BaseClass=CDocument
+HeaderFile=TestCBotDoc.h
+ImplementationFile=TestCBotDoc.cpp
+LastObject=CTestCBotDoc
+Filter=N
+VirtualFilter=DC
+
+[CLS:CTestCBotView]
+Type=0
+BaseClass=CView
+HeaderFile=TestCBotView.h
+ImplementationFile=TestCBotView.cpp
+LastObject=CTestCBotView
+Filter=C
+VirtualFilter=VWC
+
+[DLG:IDD_CONSOLE]
+Type=1
+Class=CBotConsoleDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDIT2,edit,1350631552
+Control3=IDOK,button,1342242817
+Control4=IDC_EDIT1,edit,1352734724
+
+[DLG:IDD_ABOUTBOX]
+Type=1
+Class=CAboutDlg
+ControlCount=7
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308480
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_STATIC,static,1342308352
+
+[TB:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_EDIT_CUT
+Command5=ID_EDIT_COPY
+Command6=ID_EDIT_PASTE
+Command7=ID_FILE_PRINT
+Command8=ID_RUN
+Command9=ID_APP_ABOUT
+CommandCount=9
+
+[MNU:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_MRU_FILE1
+Command4=ID_APP_EXIT
+Command5=ID_VIEW_TOOLBAR
+Command6=ID_VIEW_STATUS_BAR
+Command7=ID_APP_ABOUT
+CommandCount=7
+
+[MNU:IDR_TESTCBTYPE (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_CLOSE
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVE_AS
+Command6=ID_FILE_MRU_FILE1
+Command7=ID_APP_EXIT
+Command8=ID_EDIT_UNDO
+Command9=ID_EDIT_CUT
+Command10=ID_EDIT_COPY
+Command11=ID_EDIT_PASTE
+Command12=ID_VIEW_TOOLBAR
+Command13=ID_VIEW_STATUS_BAR
+Command14=ID_WINDOW_NEW
+Command15=ID_WINDOW_CASCADE
+Command16=ID_WINDOW_TILE_HORZ
+Command17=ID_WINDOW_ARRANGE
+Command18=ID_APP_ABOUT
+CommandCount=18
+
+[ACL:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_EDIT_COPY
+Command2=ID_FILE_NEW
+Command3=ID_FILE_OPEN
+Command4=ID_FILE_SAVE
+Command5=ID_EDIT_PASTE
+Command6=ID_EDIT_UNDO
+Command7=ID_EDIT_CUT
+Command8=ID_RUN
+Command9=ID_NEXT_PANE
+Command10=ID_PREV_PANE
+Command11=ID_RUN
+Command12=ID_TEST
+Command13=ID_EDIT_COPY
+Command14=ID_EDIT_PASTE
+Command15=ID_EDIT_CUT
+Command16=ID_EDIT_UNDO
+CommandCount=16
+
+[DLG:IDD_ABOUTBOX (French (France))]
+Type=1
+Class=CAboutDlg
+ControlCount=7
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308480
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_STATIC,static,1342308352
+
+[ACL:IDR_MAINFRAME]
+Type=1
+Command1=ID_EDIT_COPY
+Command2=ID_FILE_NEW
+Command3=ID_FILE_OPEN
+Command4=ID_FILE_SAVE
+Command5=ID_EDIT_PASTE
+Command6=ID_EDIT_UNDO
+Command7=ID_EDIT_CUT
+Command8=ID_RUN
+Command9=ID_NEXT_PANE
+Command10=ID_PREV_PANE
+Command11=ID_RUN
+Command12=ID_TEST
+Command13=ID_EDIT_COPY
+Command14=ID_EDIT_PASTE
+Command15=ID_EDIT_CUT
+Command16=ID_EDIT_UNDO
+CommandCount=16
+
+[TB:IDR_MAINFRAME]
+Type=1
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_EDIT_CUT
+Command5=ID_EDIT_COPY
+Command6=ID_EDIT_PASTE
+Command7=ID_FILE_PRINT
+Command8=ID_RUN
+Command9=ID_APP_ABOUT
+CommandCount=9
+
+[MNU:IDR_MAINFRAME]
+Type=1
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_MRU_FILE1
+Command4=ID_APP_EXIT
+Command5=ID_VIEW_TOOLBAR
+Command6=ID_VIEW_STATUS_BAR
+Command7=ID_APP_ABOUT
+CommandCount=7
+
+[MNU:IDR_TESTCBTYPE]
+Type=1
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_CLOSE
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVE_AS
+Command6=ID_FILE_MRU_FILE1
+Command7=ID_APP_EXIT
+Command8=ID_EDIT_UNDO
+Command9=ID_EDIT_CUT
+Command10=ID_EDIT_COPY
+Command11=ID_EDIT_PASTE
+Command12=ID_VIEW_TOOLBAR
+Command13=ID_VIEW_STATUS_BAR
+Command14=ID_WINDOW_NEW
+Command15=ID_WINDOW_CASCADE
+Command16=ID_WINDOW_TILE_HORZ
+Command17=ID_WINDOW_ARRANGE
+Command18=ID_APP_ABOUT
+CommandCount=18
+
+[DLG:IDD_CONSOLE (French (Switzerland))]
+Type=1
+Class=CBotConsoleDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDIT2,edit,1350631552
+Control3=IDOK,button,1342242817
+Control4=IDC_EDIT1,edit,1352734724
+
+[DLG:IDD_DIALOG1]
+Type=1
+Class=CPerformDlg
+ControlCount=9
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDIT1,edit,1350633600
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_EDIT2,edit,1350631552
+Control5=IDC_SPIN1,msctls_updown32,1342177312
+Control6=IDC_COMBO1,combobox,1344339971
+Control7=IDC_STATIC,static,1342308352
+Control8=IDC_STATIC,static,1342308352
+Control9=IDC_EDIT3,edit,1350633600
+
+[CLS:CPerformDlg]
+Type=0
+HeaderFile=PerformDlg.h
+ImplementationFile=PerformDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDC_EDIT3
+
+[DLG:IDD_DIALOG2]
+Type=1
+ControlCount=2
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+
+[DLG:IDD_DIALOG1 (French (Switzerland))]
+Type=1
+ControlCount=9
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDIT1,edit,1350633600
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_EDIT2,edit,1350631552
+Control5=IDC_SPIN1,msctls_updown32,1342177312
+Control6=IDC_COMBO1,combobox,1344339971
+Control7=IDC_STATIC,static,1342308352
+Control8=IDC_STATIC,static,1342308352
+Control9=IDC_EDIT3,edit,1350633600
+
+[DLG:IDD_DIALOG2 (French (France))]
+Type=1
+ControlCount=2
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+
diff --git a/src/CBot/TestCBot/TestCBot.cpp b/src/CBot/TestCBot/TestCBot.cpp
new file mode 100644
index 0000000..7e2aabb
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot.cpp
@@ -0,0 +1,253 @@
+// TestCBot.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "TestCBot.h"
+
+#include "MainFrm.h"
+#include "ChildFrm.h"
+#include "TestCBotDoc.h"
+#include "TestCBotView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotApp
+
+BEGIN_MESSAGE_MAP(CTestCBotApp, CWinApp)
+ //{{AFX_MSG_MAP(CTestCBotApp)
+ ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
+ //}}AFX_MSG_MAP
+ // Standard file based document commands
+ ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
+ ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotApp construction
+
+CTestCBotApp::CTestCBotApp()
+{
+ m_pConsole = NULL;
+ m_LastActive = NULL;
+ m_pClassPoint= NULL;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CTestCBotApp object
+
+CTestCBotApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotApp initialization
+
+#include "Routines.cpp"
+
+
+static char BASED_CODE szSection[] = "Recent File List";
+static char BASED_CODE szFilename[] = "File1";
+
+
+#include "../ClassFILE.cpp"
+
+// routine pour mettre à jour l'instance de la classe Bot courante
+void rMajObject( CBotVar* pThis, void* pUser )
+{
+ if (!pThis->IsElemOfClass("object"))
+ return ;
+ CBotVar* pPos = pThis->GivItem("position");
+ CBotVar* pX = pPos->GivItem("x");
+ CBotVar* pY = pPos->GivItem("y");
+ CBotVar* pZ = pPos->GivItem("z");
+// CBotVar* pPt = pThis->GivItem("transport");
+
+ CBotString p = pX->GivValString();
+
+// pX->SetValFloat( pUser == (void*)1 ? (float)12.5 : (float)44.4 );
+ pZ->SetValFloat( (float)0 );
+ pY->SetValFloat( (float)-3.33 );
+ pX->SetValFloat( pX->GivValFloat() + 10 ) ;
+
+// pX = pThis->GivItem( "xx" );
+// pX->SetValFloat( (float)22 );
+
+ // crée une instance sur une classe object
+// CBotVar* pAutre = CBotVar::Create("autre", CBotTypClass, "object");
+// pAutre->SetUserPtr( (void*)3 );
+// pPt->SetPointer( pAutre );
+// pPt->SetPointer( NULL );
+// delete pAutre;
+}
+
+
+BOOL CTestCBotApp::InitInstance()
+{
+//////////////////////////////////////////////
+// défini les mots clefs supplémentaires
+// -------------------------------------------
+
+ CBotProgram::Init();
+
+//////////////////////////////////////////////
+// défini les fonctions "show()" et "print()"
+// -------------------------------------------
+
+ CBotProgram::AddFunction("show", rShow, cShow);
+ CBotProgram::AddFunction("print", rPrint, cPrint);
+ CBotProgram::AddFunction("println", rPrintLn, cPrint);
+
+
+///////////////////////////////////
+// définie la classe globale CPoint
+// --------------------------------
+
+ m_pClassPoint = new CBotClass("CPoint", NULL);
+ // ajoute le composant ".x"
+ m_pClassPoint->AddItem("x", CBotTypFloat);
+ // ajoute le composant ".y"
+ m_pClassPoint->AddItem("y", CBotTypFloat);
+
+ // ajoute le constructeur pour cette classe
+ m_pClassPoint->AddFunction("CPoint", rCPoint, cCPoint);
+
+ m_pClassPointIntr = new CBotClass("point", NULL, TRUE);
+ // ajoute le composant ".x"
+ m_pClassPointIntr->AddItem("x", CBotTypFloat);
+ // ajoute le composant ".y"
+ m_pClassPointIntr->AddItem("y", CBotTypFloat);
+ // ajoute le composant ".z"
+ m_pClassPointIntr->AddItem("z", CBotTypFloat);
+
+ // ajoute le constructeur pour cette classe
+ m_pClassPointIntr->AddFunction("point", rCPoint, cCPoint);
+
+ // défini la classe "object"
+ CBotClass* pClassObject = new CBotClass( "object", NULL ) ;
+ pClassObject->AddItem( "xx", CBotTypFloat );
+ pClassObject->AddItem( "position", CBotTypResult( CBotTypIntrinsic, "point" ) );
+ pClassObject->AddItem( "transport", CBotTypResult( CBotTypPointer, "object" ) );
+ pClassObject->AddUpdateFunc( rMajObject );
+
+ InitClassFILE();
+
+ AfxEnableControlContainer();
+
+ // Standard initialization
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+ // Change the registry key under which our settings are stored.
+ SetRegistryKey(_T("Local AppWizard-Generated Applications"));
+
+ LoadStdProfileSettings(); // Load standard INI file options (including MRU)
+
+ // Register document templates
+
+ CMultiDocTemplate* pDocTemplate;
+ pDocTemplate = new CMultiDocTemplate(
+ IDR_TESTCBTYPE,
+ RUNTIME_CLASS(CTestCBotDoc),
+ RUNTIME_CLASS(CChildFrame), // custom MDI child frame
+ RUNTIME_CLASS(CTestCBotView));
+ AddDocTemplate(pDocTemplate);
+
+ // create main MDI Frame window
+ CMainFrame* pMainFrame = new CMainFrame;
+ if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
+ return FALSE;
+ m_pMainWnd = pMainFrame;
+
+ // Parse command line for standard shell commands, DDE, file open
+ CCommandLineInfo cmdInfo;
+ ParseCommandLine(cmdInfo);
+
+ if (m_lpCmdLine[0] == 0)
+ {
+ CString Filename = GetProfileString(szSection, szFilename);
+ if (Filename.IsEmpty()) Filename = "TstCbot.txt";
+ else OpenDocumentFile(Filename);
+ }
+ else
+ // Dispatch commands specified on the command line
+ if (!ProcessShellCommand(cmdInfo))
+ return FALSE;
+ pMainFrame->ShowWindow(m_nCmdShow);
+ pMainFrame->UpdateWindow();
+
+
+ return TRUE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDlg dialog used for App About
+
+class CAboutDlg : public CDialog
+{
+public:
+ CAboutDlg();
+
+// Dialog Data
+ //{{AFX_DATA(CAboutDlg)
+ enum { IDD = IDD_ABOUTBOX };
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CAboutDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ //{{AFX_MSG(CAboutDlg)
+ // No message handlers
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+ //{{AFX_DATA_INIT(CAboutDlg)
+ //}}AFX_DATA_INIT
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CAboutDlg)
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+ //{{AFX_MSG_MAP(CAboutDlg)
+ // No message handlers
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+// App command to run the dialog
+void CTestCBotApp::OnAppAbout()
+{
+ CAboutDlg aboutDlg;
+ aboutDlg.DoModal();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotApp commands
+
+int CTestCBotApp::ExitInstance()
+{
+ delete m_pFuncFile;
+
+ CBotProgram::Free();
+ return CWinApp::ExitInstance();
+}
diff --git a/src/CBot/TestCBot/TestCBot.dsp b/src/CBot/TestCBot/TestCBot.dsp
new file mode 100644
index 0000000..8ed9b11
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot.dsp
@@ -0,0 +1,201 @@
+# Microsoft Developer Studio Project File - Name="TestCBot" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=TestCBot - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "TestCBot.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "TestCBot.mak" CFG="TestCBot - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "TestCBot - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "TestCBot - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "TestCBot - Win32 Release"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x100c /d "NDEBUG"
+# ADD RSC /l 0x100c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "TestCBot - Win32 Debug"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x100c /d "_DEBUG"
+# ADD RSC /l 0x100c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /stack:0x7010 /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "TestCBot - Win32 Release"
+# Name "TestCBot - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\CBotConsoleDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChildFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\PerformDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBot.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBot.rc
+
+!IF "$(CFG)" == "TestCBot - Win32 Release"
+
+!ELSEIF "$(CFG)" == "TestCBot - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBotDoc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBotView.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\CBotConsoleDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChildFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\PerformDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBot.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBotDoc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TestCBotView.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\TestCBot.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\TestCBot.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\TestCBotDoc.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Toolbar.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\Debug\CBot.lib
+# End Source File
+# End Target
+# End Project
diff --git a/src/CBot/TestCBot/TestCBot.h b/src/CBot/TestCBot/TestCBot.h
new file mode 100644
index 0000000..f101fd1
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot.h
@@ -0,0 +1,64 @@
+// TestCBot.h : main header file for the TESTCBOT application
+//
+
+#if !defined(AFX_TESTCBOT_H__4D1BB903_8E74_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_TESTCBOT_H__4D1BB903_8E74_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+//#include "../CbotDll.h" // librairie CBot
+#include "../Cbot.h" // complet pour Browse
+
+class CTestCBotView;
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotApp:
+// See TestCBot.cpp for the implementation of this class
+//
+
+class CTestCBotApp : public CWinApp
+{
+public:
+ CTestCBotApp();
+
+ CEdit* m_pConsole;
+ CTestCBotView* m_LastActive;
+ CBotClass* m_pClassPoint;
+ CBotClass* m_pClassPointIntr;
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTestCBotApp)
+ public:
+ virtual BOOL InitInstance();
+ virtual int ExitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CTestCBotApp)
+ afx_msg void OnAppAbout();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TESTCBOT_H__4D1BB903_8E74_11D4_A439_00D059085115__INCLUDED_)
+
+
+#define WM_STARTPROG WM_APP + 0
+#define WM_ENDPROG WM_APP + 1
+#define WM_ACTWINDOW WM_APP + 2
diff --git a/src/CBot/TestCBot/TestCBot.rc b/src/CBot/TestCBot/TestCBot.rc
new file mode 100644
index 0000000..137458c
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot.rc
@@ -0,0 +1,564 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\TestCBot.ico"
+IDR_TESTCBTYPE ICON DISCARDABLE "res\\TestCBotDoc.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDR_MAINFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Toolbar
+//
+
+IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15
+BEGIN
+ BUTTON ID_FILE_NEW
+ BUTTON ID_FILE_OPEN
+ BUTTON ID_FILE_SAVE
+ SEPARATOR
+ BUTTON ID_EDIT_CUT
+ BUTTON ID_EDIT_COPY
+ BUTTON ID_EDIT_PASTE
+ SEPARATOR
+ BUTTON ID_FILE_PRINT
+ BUTTON ID_RUN
+ SEPARATOR
+ BUTTON ID_APP_ABOUT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MAINFRAME MENU PRELOAD DISCARDABLE
+BEGIN
+ POPUP "&Fichier"
+ BEGIN
+ MENUITEM "&Nouveau\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Ouvrir...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM SEPARATOR
+ MENUITEM "Fichier récent", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Quitter", ID_APP_EXIT
+ END
+ POPUP "&Affichage"
+ BEGIN
+ MENUITEM "&Barre d'outils", ID_VIEW_TOOLBAR
+ MENUITEM "Barre d'é&tat", ID_VIEW_STATUS_BAR
+ END
+ POPUP "&?"
+ BEGIN
+ MENUITEM "&A propos de TestCBot...", ID_APP_ABOUT
+ END
+END
+
+IDR_TESTCBTYPE MENU PRELOAD DISCARDABLE
+BEGIN
+ POPUP "&Fichier"
+ BEGIN
+ MENUITEM "&Nouveau\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Ouvrir...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM "&Fermer", ID_FILE_CLOSE
+ MENUITEM "&Enregistrer\tCtrl+S", ID_FILE_SAVE
+ MENUITEM "En&registrer sous...", ID_FILE_SAVE_AS
+ MENUITEM SEPARATOR
+ MENUITEM "Fichier récent", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Quitter", ID_APP_EXIT
+ END
+ POPUP "&Edition"
+ BEGIN
+ MENUITEM "&Annuler\tCtrl+Z", ID_EDIT_UNDO
+ MENUITEM SEPARATOR
+ MENUITEM "&Couper\tCtrl+X", ID_EDIT_CUT
+ MENUITEM "&Copier\tCtrl+C", ID_EDIT_COPY
+ MENUITEM "C&oller\tCtrl+V", ID_EDIT_PASTE
+ END
+ POPUP "&Affichage"
+ BEGIN
+ MENUITEM "&Barre d'outils", ID_VIEW_TOOLBAR
+ MENUITEM "Barre d'é&tat", ID_VIEW_STATUS_BAR
+ END
+ POPUP "Fe&nêtre"
+ BEGIN
+ MENUITEM "&Nouvelle fenêtre", ID_WINDOW_NEW
+ MENUITEM "&Cascade", ID_WINDOW_CASCADE
+ MENUITEM "&Mosaïque", ID_WINDOW_TILE_HORZ
+ MENUITEM "&Réorganiser les icônes", ID_WINDOW_ARRANGE
+ END
+ POPUP "&?"
+ BEGIN
+ MENUITEM "&A propos de TestCBot...", ID_APP_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
+BEGIN
+ "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
+ "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
+ VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
+ VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
+ VK_F5, ID_RUN, VIRTKEY, NOINVERT
+ VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT
+ VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT
+ VK_F7, ID_RUN, VIRTKEY, NOINVERT
+ VK_F9, ID_TEST, VIRTKEY, NOINVERT
+ VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
+ "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
+ "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 265, 206
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "A propos de TestCBot"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON IDR_MAINFRAME,IDC_STATIC,11,17,21,20
+ LTEXT "TestCBot version 1.0",IDC_STATIC,40,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Copyright D. Dumoulin (C) 2000",IDC_STATIC,40,25,119,8
+ DEFPUSHBUTTON "OK",IDOK,226,7,32,14,WS_GROUP
+ LTEXT "Programme de test pour la librairie CBot\n\nLes fonctions doivent être déclarées comme ""extern"" pour apparaître dans la liste lors de l'exécution.\n\n",
+ IDC_STATIC,39,43,191,41
+ LTEXT "Mais en fait, on peut accèder à toutes les fonctions marquées ""public"" quelles soient dans la fenêtre active ou non.",
+ IDC_STATIC,39,89,187,36
+ LTEXT "Les fonctions print( ... ) et println( ...) permettent d'afficher des résultats dans la console.\n\nLa fonction show( ... ) affiche les paramètres dans un dialogue, et suspend donc l'exécution.",
+ IDC_STATIC,39,130,187,54
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040C04B0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "Application MFC TestCBot\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "TestCBot\0"
+ VALUE "LegalCopyright", "Copyright (C) 1900\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "TestCBot.EXE\0"
+ VALUE "ProductName", "Application TestCBot\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Traduction", 0x40c, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 258
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 199
+ END
+
+ IDD_DIALOG2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ IDR_MAINFRAME "TestCBot"
+ IDR_TESTCBTYPE "\nTestCBot\nTestCBot\nCBot (*.txt)\n.txt\nTestCBot.Document\nTestCB Document"
+END
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ AFX_IDS_APP_TITLE "TestCBot"
+ AFX_IDS_IDLEMESSAGE "Prêt"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_INDICATOR_EXT "EXT"
+ ID_INDICATOR_CAPS "MAJ"
+ ID_INDICATOR_NUM "NUM"
+ ID_INDICATOR_SCRL "DEF"
+ ID_INDICATOR_OVR "ECR"
+ ID_INDICATOR_REC "ENR"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_NEW "Crée un nouveau document\nNouveau"
+ ID_FILE_OPEN "Ouvre un document existant\nOuvrir"
+ ID_FILE_CLOSE "Ferme le document actif\nFermer"
+ ID_FILE_SAVE "Enregistre le document actif\nEnregistrer"
+ ID_FILE_SAVE_AS "Enregistre le document actif sous un nouveau nom\nEnregistrer sous"
+ ID_FILE_PRINT "Imprime le document\nImprime"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_APP_ABOUT "Affiche des informations sur le programme\nA propos de"
+ ID_APP_EXIT "Ferme l'application ; propose d'enregistrer les documents\nQuitter"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_MRU_FILE1 "Ouvre ce document"
+ ID_FILE_MRU_FILE2 "Ouvre ce document"
+ ID_FILE_MRU_FILE3 "Ouvre ce document"
+ ID_FILE_MRU_FILE4 "Ouvre ce document"
+ ID_FILE_MRU_FILE5 "Ouvre ce document"
+ ID_FILE_MRU_FILE6 "Ouvre ce document"
+ ID_FILE_MRU_FILE7 "Ouvre ce document"
+ ID_FILE_MRU_FILE8 "Ouvre ce document"
+ ID_FILE_MRU_FILE9 "Ouvre ce document"
+ ID_FILE_MRU_FILE10 "Ouvre ce document"
+ ID_FILE_MRU_FILE11 "Ouvre ce document"
+ ID_FILE_MRU_FILE12 "Ouvre ce document"
+ ID_FILE_MRU_FILE13 "Ouvre ce document"
+ ID_FILE_MRU_FILE14 "Ouvre ce document"
+ ID_FILE_MRU_FILE15 "Ouvre ce document"
+ ID_FILE_MRU_FILE16 "Ouvre ce document"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_NEXT_PANE "Passe au volet de fenêtre suivant\nVolet suivant"
+ ID_PREV_PANE "Revient au volet précédent\nVolet précédent"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_WINDOW_NEW "Ouvre une nouvelle fenêtre pour le document actif\nNouvelle fenêtre"
+ ID_WINDOW_ARRANGE "Réorganise les icônes en bas de la fenêtre\nRéorganise les icônes"
+ ID_WINDOW_CASCADE "Réorganise les fenêtres en cascade\nCascade"
+ ID_WINDOW_TILE_HORZ "Réorganise les fenêtres en une mosaïque\nMosaïque"
+ ID_WINDOW_TILE_VERT "Réorganise les fenêtres en une mosaïque\nMosaïque"
+ ID_WINDOW_SPLIT "Fractionne la fenêtre active en deux volets\nFractionner"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_EDIT_CLEAR "Efface la sélection\nEffacer"
+ ID_EDIT_CLEAR_ALL "Efface tout\nEffacer tout"
+ ID_EDIT_COPY "Copie la sélection et la place dans le Presse-papiers\nCopier"
+ ID_EDIT_CUT "Supprime la sélection et la place dans le Presse-papiers\nCopier"
+ ID_EDIT_FIND "Recherche le texte spécifié\nRechercher"
+ ID_EDIT_PASTE "Insère le contenu du Presse-papiers\nColler"
+ ID_EDIT_REPEAT "Répète la dernière action\nRépéter"
+ ID_EDIT_REPLACE "Remplace le texte spécifique par un texte différent\nRemplacer"
+ ID_EDIT_SELECT_ALL "Sélectionne le document entier\nSélectionner tout"
+ ID_EDIT_UNDO "Annule la dernière action\nAnnuler"
+ ID_EDIT_REDO "Rétablit l'action précédemment annulée\nRétablir"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_TOOLBAR "Affiche ou masque la barre d'outils\nBarre d'outils"
+ ID_VIEW_STATUS_BAR "Affiche ou masque la barre d'état\nBarre d'état"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_SCSIZE "Change la taille de la fenêtre"
+ AFX_IDS_SCMOVE "Change la position de la fenêtre"
+ AFX_IDS_SCMINIMIZE "Réduit la fenêtre en icône"
+ AFX_IDS_SCMAXIMIZE "Agrandit la fenêtre au format de l'écran"
+ AFX_IDS_SCNEXTWINDOW "Passe à la fenêtre de document suivante"
+ AFX_IDS_SCPREVWINDOW "Passe à la fenêtre de document précédente"
+ AFX_IDS_SCCLOSE "Ferme la fenêtre active et propose l'enregistrement des documents"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_SCRESTORE "Restaure la fenêtre à sa taille d'origine"
+ AFX_IDS_SCTASKLIST "Active la liste des tâches"
+ AFX_IDS_MDICHILD "Active cette fenêtre"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_RUN "Execute le programme CBot\nExecute (F5)"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_TYPENAMES "les différents types"
+ 1001 "Byte"
+ 1002 "Short"
+ 1003 "Char"
+ 1004 "Int"
+ 1005 "Long"
+ 1006 "Real"
+ 1007 "Double"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ 1008 "Boolean"
+ 1009 "String"
+ 1010 "Array"
+ 1011 "Arraybody"
+ 1012 "Pointer"
+ 1013 "Nullpointer"
+ 1014 "nop"
+ 1015 "Class"
+ 1016 "Intrinsic"
+END
+
+#endif // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// French (Switzerland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRS)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_SWISS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_CONSOLE DIALOG DISCARDABLE 0, 0, 401, 210
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "CBot Console"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Commande :",IDC_STATIC,7,177,40,8
+ EDITTEXT IDC_EDIT2,7,189,329,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "Exécute",IDOK,344,189,50,14
+ EDITTEXT IDC_EDIT1,7,7,387,167,ES_MULTILINE | ES_READONLY |
+ ES_WANTRETURN | WS_VSCROLL
+END
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 177, 100
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Test performances"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Boucles par seconde",IDC_STATIC,7,9,68,8
+ EDITTEXT IDC_EDIT1,111,7,51,14,ES_AUTOHSCROLL | ES_READONLY
+ LTEXT "Nombre de scripts",IDC_STATIC,7,55,58,8
+ EDITTEXT IDC_EDIT2,111,52,40,14,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_ARROWKEYS,152,52,
+ 10,14
+ COMBOBOX IDC_COMBO1,111,74,52,111,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Timer",IDC_STATIC,7,77,18,8
+ LTEXT "Performance %",IDC_STATIC,7,28,48,8
+ EDITTEXT IDC_EDIT3,111,25,51,14,ES_AUTOHSCROLL | ES_READONLY
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_CONSOLE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 394
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 203
+ END
+
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 170
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 93
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 12, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\TestCBot.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""l.fra\\afxres.rc"" // Standard components\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_DIALOG1 DLGINIT
+BEGIN
+ IDC_COMBO1, 0x403, 2, 0
+0x0031,
+ IDC_COMBO1, 0x403, 3, 0
+0x3031, "\000"
+ IDC_COMBO1, 0x403, 4, 0
+0x3031, 0x0030,
+ IDC_COMBO1, 0x403, 5, 0
+0x3031, 0x3030, "\000"
+ 0
+END
+
+#endif // French (Switzerland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE 12, 1
+#pragma code_page(1252)
+#endif
+#include "res\TestCBot.rc2" // non-Microsoft Visual C++ edited resources
+#include "l.fra\afxres.rc" // Standard components
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/CBot/TestCBot/TestCBot1.txt b/src/CBot/TestCBot/TestCBot1.txt
new file mode 100644
index 0000000..d27b4f8
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot1.txt
@@ -0,0 +1,27 @@
+
+class CPoint2
+{
+ float x, y;
+ void CPoint2(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+}
+
+public extern void T ( )
+{
+ CPoint2 X( 12, 33 ), Y ( -4, 4/3 );
+ print ( X, Y ) ;
+}
+
+public extern void Hello ( )
+
+{
+ println ( "Hello" );
+}
+
+public extern void test ( int n )
+{
+ for ( int i = n; i>0 ; i--) print (i);
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/TestCBot3.txt b/src/CBot/TestCBot/TestCBot3.txt
new file mode 100644
index 0000000..b915f96
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBot3.txt
@@ -0,0 +1,24 @@
+public extern void Test ()
+{
+ for ( int x = 100000; x>0 ; x-- ) { }
+}
+
+float MaRoutine( CPoint A, CPoint B )
+{
+ A.x -= B.x ; // distance en x
+ A.y -= B.y ; // distance en y
+ A.x *= A.x; // carré de la distance
+ A.y += A.y; // carré de la distance
+ println ( A, B ) ;
+ return ( A.x + A.y ) ;
+}
+
+public extern void TestAB ( )
+{
+ CPoint A(3, 5) ;
+ CPoint B(4, -2);
+ println ( A, B ) ;
+ MaRoutine( A, B ) ;
+ println ( A, B ) ;
+}
+
diff --git a/src/CBot/TestCBot/TestCBotDoc.cpp b/src/CBot/TestCBot/TestCBotDoc.cpp
new file mode 100644
index 0000000..e033dd5
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBotDoc.cpp
@@ -0,0 +1,683 @@
+// TestCBotDoc.cpp : implementation of the CTestCBotDoc class
+//
+
+#include "stdafx.h"
+#include "TestCBot.h"
+
+#include "TestCBotDoc.h"
+#include "TestCBotView.h"
+#include "CBotConsoleDlg.h"
+#include "PerformDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotDoc
+
+IMPLEMENT_DYNCREATE(CTestCBotDoc, CDocument)
+
+BEGIN_MESSAGE_MAP(CTestCBotDoc, CDocument)
+ //{{AFX_MSG_MAP(CTestCBotDoc)
+ ON_COMMAND(ID_RUN, OnRun)
+ ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)
+ ON_COMMAND(ID_TEST, OnTest)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotDoc construction/destruction
+
+static BOOL test = FALSE;
+
+
+CTestCBotDoc::CTestCBotDoc()
+{
+ m_pEdit = NULL;
+ m_pProg = NULL;
+ m_bModified = FALSE;
+}
+
+CTestCBotDoc::~CTestCBotDoc()
+{
+ delete m_pEdit;
+ delete m_pProg;
+}
+
+BOOL CTestCBotDoc::OnNewDocument()
+{
+ if (!CDocument::OnNewDocument())
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotDoc serialization
+
+void CTestCBotDoc::Serialize(CArchive& ar)
+{
+ if (ar.IsStoring())
+ {
+ m_pEdit->GetWindowText(m_DocText);
+ int w = m_DocText.GetLength();
+ ar.Write((LPCTSTR)m_DocText, w);
+ }
+ else
+ {
+ int r;
+ char buf[10001];
+
+ r = ar.Read(buf, 10000);
+ buf[r] = 0;
+ m_DocText = buf;
+
+ if ( m_pProg == NULL ) m_pProg = new CBotProgram();
+
+ if (!m_pProg->Compile(m_DocText, m_Liste, NULL))
+ {
+ delete m_pProg;
+ m_pProg = NULL;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotDoc diagnostics
+
+#ifdef _DEBUG
+void CTestCBotDoc::AssertValid() const
+{
+ CDocument::AssertValid();
+}
+
+void CTestCBotDoc::Dump(CDumpContext& dc) const
+{
+ CDocument::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotDoc commands
+
+void CTestCBotDoc::OnRun()
+{
+ OnFileSave();
+
+ m_pEdit->GetWindowText(m_DocText);
+
+ CString TextError;
+ int code, start, end;
+
+ if ( m_pProg == NULL ) m_pProg = new CBotProgram();
+
+ CTestCBotApp* pApp = (CTestCBotApp*)AfxGetApp();
+
+ if (!m_pProg->Compile(m_DocText, m_Liste, NULL))
+ {
+ m_pProg->GetError(code, start, end);
+ delete m_pProg;
+ m_pProg = NULL;
+
+ m_pEdit->SetSel( start, end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ TextError = CBotProgram::GivErrorText( code );
+ AfxMessageBox( TextError );
+
+ m_pEdit->SetFocus();
+ return;
+ }
+
+ if( m_Liste.GivSize() == 0 )
+ {
+ AfxMessageBox("Aucune fonction marquée \"extern\" !");
+ return;
+ }
+
+ for ( int i = 0; i < m_Liste.GivSize(); i++ )
+ {
+ int start, stop;
+ m_pProg->GetPosition(m_Liste[i], start, stop, GetPosNom, GetPosParam);
+ m_Liste[i] = m_DocText.Mid( start, stop-start );
+ }
+
+ CBotConsoleDlg dlg;
+ dlg.m_pListe = &m_Liste;
+ dlg.m_pEditx = m_pEdit;
+
+ dlg.DoModal(); // dialogue pour faire la console
+
+ if ( dlg.m_code>0 )
+ {
+ CString TextError;
+
+ TextError = m_pProg->GivErrorText( dlg.m_code );
+
+ m_pEdit->SetSel( dlg.m_start, dlg.m_end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ AfxMessageBox(TextError);
+ }
+
+ m_pEdit->SetFocus();
+
+ return;
+}
+
+
+void CTestCBotDoc::OnChangeEdit1()
+{
+ SetModifiedFlag();
+ m_bModified = TRUE;
+}
+
+BOOL CTestCBotDoc::Compile()
+{
+ m_pEdit->GetWindowText(m_DocText);
+
+ CString TextError;
+ int code, start, end;
+
+ if ( m_pProg == NULL ) m_pProg = new CBotProgram();
+
+ char buffer[100];
+ strcpy(buffer, "le pointeur à passer pour voir");
+
+ if (m_bModified && !m_pProg->Compile(m_DocText, m_Liste, (void*)buffer))
+ {
+ m_pProg->GetError(code, start, end);
+ delete m_pProg;
+ m_pProg = NULL;
+
+ m_pEdit->SetSel( start, end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ TextError = CBotProgram::GivErrorText( code );
+ AfxMessageBox( TextError );
+
+ m_pEdit->SetFocus();
+ m_bModified = FALSE;
+ return FALSE;
+ }
+
+ if ( m_pProg->GetPosition( "TheTest", start, end) )
+ {
+ m_pEdit->SetSel( start, end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+ }
+
+ m_bModified = FALSE;
+ return TRUE;
+}
+
+
+
+static int compt = 0;
+// routine retournant le "pointeur" à un autre object
+BOOL rRetObject( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ pResult->SetPointer( NULL );
+ compt+=45671;
+ if (compt&0x11) return TRUE;
+
+ CBotVar* pAutre = CBotVar::Create("autre", CBotTypResult( CBotTypClass, "object" ));
+ pAutre->SetUserPtr( (void*)2 );
+ pResult->SetPointer( pAutre );
+
+ if (!pResult->IsElemOfClass("object"))
+ return TRUE;
+
+ delete pAutre;
+ return TRUE;
+}
+
+CBotTypResult cRetObject( CBotVar* &pVar, void* pUser )
+{
+ return CBotTypResult( CBotTypPointer, "object");
+}
+
+BOOL roRadar( CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ pResult->SetPointer( NULL );
+ compt+=45671;
+ if (compt&0x11) return TRUE;
+
+ CBotVar* pAutre = CBotVar::Create("autre", CBotTypResult( CBotTypClass, "object" ));
+ pAutre->SetUserPtr( (void*)2 );
+ pResult->SetPointer( pAutre );
+
+ if (!pResult->IsElemOfClass("object"))
+ return TRUE;
+
+ delete pAutre;
+ return TRUE;
+}
+
+CBotTypResult coRadar( CBotVar* pThis, CBotVar* &pVar )
+{
+ void* pUser = pThis->GivUserPtr();
+ return CBotTypResult( CBotTypPointer, "object");
+}
+
+BOOL rMove( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ if ( test < 12 )
+ {
+ test++;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+CBotTypResult cMove( CBotVar* &pVar, void* pUser )
+{
+ return CBotTypResult( 0 );
+}
+
+BOOL rTurn( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ return TRUE;
+}
+
+CBotTypResult cTurn( CBotVar* &pVar, void* pUser )
+{
+ return CBotTypResult( 0 );
+}
+
+BOOL rRadar( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ pResult->SetPointer( NULL );
+
+ if ( pVar ) pVar->debug();
+
+ compt+=45671;
+ if (compt&0x11)
+ {
+ return FALSE; // TRUE;
+ }
+
+ CBotVar* pAutre = CBotVar::Create("autre", CBotTypResult( CBotTypClass, "object" ));
+ pAutre->SetUserPtr( (void*)2 );
+ pResult->SetPointer( pAutre );
+
+ if (!pResult->IsElemOfClass("object"))
+ return TRUE;
+
+ delete pAutre;
+ return TRUE;
+}
+
+CBotTypResult cRadar( CBotVar* &pVar, void* pUser )
+{
+ return CBotTypResult( CBotTypPointer, "object");
+}
+
+// routine retournant le "pointeur" à un autre object
+BOOL rTEST( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ test = 1 ;
+ if ( pVar == NULL ) return TRUE;
+
+ test = pVar->GivValInt();
+ if ( test == 5 )
+ {
+ pVar = pVar->GivNext();
+ pVar->SetUserPtr( OBJECTDELETED );
+ }
+ return TRUE;
+}
+
+CBotTypResult cTEST( CBotVar* &pVar, void* pUser )
+{
+ return CBotTypResult( 0 );
+}
+
+// routine retournant le "pointeur" à un autre object
+BOOL rF( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
+{
+ if ( pResult == NULL ) return TRUE;
+ pResult->SetValInt(3);
+ return TRUE;
+}
+
+CBotTypResult cF( CBotVar* &pVar, void* pUser )
+{
+ return CBotTypResult( CBotTypFloat );
+}
+
+/////////////////////////////////////////////////////////////////
+
+// Compilation d'une procédure avec un "point".
+
+CBotTypResult cPoint(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult( CBotErrLowParam );
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult( CBotErrLowParam );
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult( CBotErrBadNum );
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult( CBotErrLowParam );
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult( CBotErrBadNum );
+ var = var->GivNext();
+ return CBotTypResult( 0 );
+ }
+
+ if ( var->GivType() == CBotTypClass )
+ {
+ if ( !var->IsElemOfClass("point") ) return CBotTypResult( CBotErrBadParam );
+ var = var->GivNext();
+ return CBotTypResult( 0 );
+ }
+
+ return CBotTypResult( CBotErrBadParam );
+}
+
+// Donne un paramètre de type "point".
+#define UNIT 1
+
+
+CBotTypResult cSpace(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult( CBotTypIntrinsic, "point" );
+ ret = cPoint(var, user);
+ if ( !ret.Eq(0) ) return ret;
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult( CBotErrBadNum );
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult( CBotErrBadNum );
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult( CBotErrBadNum );
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotErrOverParam;
+ return CBotTypResult( CBotTypIntrinsic, "point" );
+}
+
+// Instruction "space(center, rMin, rMax, dist)".
+
+BOOL rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CBotVar* pSub;
+ float rMin, rMax, dist;
+
+ rMin = 5.0f*UNIT;
+ rMax = 50.0f*UNIT;
+ dist = 4.0f*UNIT;
+
+ if ( var == 0 )
+ {
+// center = pThis->RetPosition(0);
+ }
+ else
+ {
+ if ( var != 0 )
+ {
+ rMin = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ rMax = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ dist = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+ }
+ }
+ }
+ }
+
+ if ( result != 0 )
+ {
+ pSub = result->GivItemList();
+ if ( pSub != 0 )
+ {
+ pSub->SetValFloat(1);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(2);
+ pSub = pSub->GivNext(); // "z"
+// pSub->SetValFloat(3);
+ }
+ }
+ return TRUE;
+}
+//////////////////////////////////////////////////////////////
+
+
+void CTestCBotDoc::OnTest()
+{
+ CBotProgram::DefineNum("WingedGrabber", 1);
+ CBotProgram::DefineNum("TrackedGrabber", 2);
+ CBotProgram::DefineNum("WheeledGrabber", 3);
+ CBotProgram::DefineNum("LeggedGrabber", 4);
+ CBotProgram::DefineNum("WingedShooter", 5);
+ CBotProgram::DefineNum("TrackedShooter", 6);
+ CBotProgram::DefineNum("WheeledShooter", 7);
+ CBotProgram::DefineNum("LeggedShooter", 8);
+ CBotProgram::DefineNum("WingedOrgaShooter", 9);
+ CBotProgram::DefineNum("TrackedOrgaShooter", 10);
+ CBotProgram::DefineNum("WheeledOrgaShooter", 11);
+ CBotProgram::DefineNum("LeggedOrgaShooter", 12);
+ CBotProgram::DefineNum("WingedSniffer", 13);
+ CBotProgram::DefineNum("TrackedSniffer", 14);
+ CBotProgram::DefineNum("WheeledSniffer", 14);
+ CBotProgram::DefineNum("LeggedSniffer", 15);
+ CBotProgram::DefineNum("Thumper", 16);
+ CBotProgram::DefineNum("PhazerShooter", 17);
+ CBotProgram::DefineNum("Recycler", 18);
+ CBotProgram::DefineNum("Shielder", 19);
+ CBotProgram::DefineNum("Subber", 20);
+ CBotProgram::DefineNum("Me", 21);
+
+ CBotProgram::DefineNum("TypeMarkPath", 111);
+
+ OnFileSave();
+
+// CPerformDlg dlg;
+// dlg.m_Script = m_DocText;
+// dlg.DoModal();
+
+ // défini la routine RetObject
+ CBotProgram::AddFunction( "Radar", rRetObject, cRetObject );
+
+ // ajoute une routine pour cette classe
+ CBotProgram::AddFunction("Space", rSpace, cSpace);
+
+ // défini la routine Test
+ CBotProgram::AddFunction( "TEST", rTEST, cTEST );
+ CBotProgram::AddFunction( "F", rF, cF );
+
+ CBotProgram::AddFunction( "goto", rMove, cMove );
+ CBotProgram::AddFunction( "fire", rTurn, cTurn );
+ CBotProgram::AddFunction( "radar", rRadar, cRadar );
+
+ // crée une instance de la classe "Bot" pour ce robot
+ CBotVar* pThisRobot = CBotVar::Create( "", CBotTypResult(CBotTypClass, "object") );
+ pThisRobot->SetUserPtr( (void*)1 );
+ pThisRobot->SetIdent( 1234 );
+
+ delete m_pProg;
+ // crée un objet programme associé à cette instance
+ m_pProg = new CBotProgram(pThisRobot);
+
+ // compile le programme
+ CString TextError;
+ int code, start, end;
+
+ m_pEdit->GetWindowText(m_DocText);
+ if (!m_pProg->Compile(m_DocText, m_Liste, (void*) 44))
+ {
+ m_pProg->GetError(code, start, end);
+ delete m_pProg;
+ m_pProg = NULL;
+
+ delete pThisRobot;
+
+ m_pEdit->SetSel( start, end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ TextError = CBotProgram::GivErrorText( code );
+ AfxMessageBox( TextError );
+
+ m_pEdit->SetFocus();
+ return;
+ }
+
+ // exécute pour voir
+ m_pProg->Start(m_Liste[0]);
+
+ int mode = -1;
+
+ if ( mode >= 0 ) {
+
+ // sauve et restore à chaque pas possible
+ while (!m_pProg->Run(NULL, 1))
+ {
+ const char* FunctionName;
+ int start1, end1;
+ m_pProg->GetRunPos(FunctionName, start1, end1);
+ if ( end1 <= 0 )
+ m_pProg->GetRunPos(FunctionName, start1, end1);
+ m_pEdit->SetSel(start1, end1);
+
+if ( mode == 0 ) continue;
+
+ FILE* pf;
+ pf = fOpen( "TEST.CBO", "wb" );
+ CBotClass::SaveStaticState(pf);
+ m_pProg->SaveState(pf);
+ fClose(pf);
+
+if ( mode == 2 ) if (!m_pProg->Compile(m_DocText, m_Liste, (void*) 44))
+ {
+ m_pProg->GetError(code, start, end);
+ delete m_pProg;
+ m_pProg = NULL;
+
+ delete pThisRobot;
+
+ m_pEdit->SetSel( start, end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ TextError = CBotProgram::GivErrorText( code );
+ AfxMessageBox( TextError );
+
+ m_pEdit->SetFocus();
+ return;
+ }
+
+ pf = fOpen( "TEST.CBO", "rb" );
+ CBotClass::RestoreStaticState(pf);
+ m_pProg->RestoreState(pf);
+ fClose(pf);
+
+ int start2, end2;
+ m_pProg->GetRunPos(FunctionName, start2, end2);
+ if ( end2 <= 0 )
+ m_pProg->GetRunPos(FunctionName, start2, end2);
+
+ if ( start1 != start2 || end1 != end2 )
+ m_pProg->GetRunPos(FunctionName, start2, end2);
+ m_pEdit->SetSel(start2, end2);
+ }
+
+ if (m_pProg->GetError(code, start, end))
+ {
+ m_pEdit->SetSel(start, end);
+ TextError = CBotProgram::GivErrorText(code);
+ AfxMessageBox(TextError);
+ }
+ return;}
+
+ while (!m_pProg->Run(NULL, 0))
+ {
+ const char* FunctionName;
+ int start, end;
+ m_pProg->GetRunPos(FunctionName, start, end);
+ m_pEdit->SetSel(start, end);
+
+ if ( FunctionName == NULL ) continue;
+ CString info (FunctionName);
+ CString sep (":\n");
+
+ int level = 0;
+ const char* Name;
+ while ( TRUE )
+ {
+ CBotVar* pVar = m_pProg->GivStackVars(Name, level--);
+ if ( Name != FunctionName ) break;
+ if ( pVar == NULL ) continue;
+// pVar->Maj(NULL, FALSE);
+ while ( pVar != NULL )
+ {
+ info += sep;
+ info += pVar->GivName() + " = " + pVar->GivValString();
+ sep = ", ";
+ pVar = pVar->GivNext();
+ }
+ sep = "\n";
+ }
+ if ( IDOK != AfxMessageBox(info, MB_OKCANCEL) ) break;
+
+ if ( test == 1 )
+ {
+ test = 0;
+ FILE* pf;
+ pf = fOpen( "TEST.CBO", "wb" );
+ m_pProg->SaveState(pf);
+ fClose(pf);
+ }
+
+ if ( test == 2 )
+ {
+ test = 0;
+ FILE* pf;
+ pf = fOpen( "TEST.CBO", "rb" );
+ m_pProg->RestoreState(pf);
+ fClose(pf);
+ }
+
+ if ( test == 12 )
+ {
+ test = 0;
+ FILE* pf;
+ pf = fOpen( "TEST.CBO", "wb" );
+ m_pProg->SaveState(pf);
+ fClose(pf);
+
+ pf = fOpen( "TEST.CBO", "rb" );
+ m_pProg->RestoreState(pf);
+ fClose(pf);
+
+ test = 13;
+ }
+ }
+
+ if (m_pProg->GetError(code, start, end))
+ {
+ m_pEdit->SetSel(start, end);
+ TextError = CBotProgram::GivErrorText(code);
+ AfxMessageBox(TextError);
+ }
+
+ delete pThisRobot;
+}
+
diff --git a/src/CBot/TestCBot/TestCBotDoc.h b/src/CBot/TestCBot/TestCBotDoc.h
new file mode 100644
index 0000000..d8275b5
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBotDoc.h
@@ -0,0 +1,64 @@
+// TestCBotDoc.h : interface of the CTestCBotDoc class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_TESTCBOTDOC_H__4D1BB90B_8E74_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_TESTCBOTDOC_H__4D1BB90B_8E74_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+class CTestCBotDoc : public CDocument
+{
+protected: // create from serialization only
+ CTestCBotDoc();
+ DECLARE_DYNCREATE(CTestCBotDoc)
+
+// Attributes
+public:
+ CEdit* m_pEdit; // pour mémoriser le texte, et l'afficher
+ CBotProgram* m_pProg; // le programme compilé
+ CString m_DocText;
+ CBotStringArray m_Liste;
+ BOOL m_bModified;
+
+// Operations
+public:
+ BOOL Compile();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTestCBotDoc)
+ public:
+ virtual BOOL OnNewDocument();
+ virtual void Serialize(CArchive& ar);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CTestCBotDoc();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CTestCBotDoc)
+ afx_msg void OnRun();
+ afx_msg void OnChangeEdit1();
+ afx_msg void OnTest();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TESTCBOTDOC_H__4D1BB90B_8E74_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/TestCBotView.cpp b/src/CBot/TestCBot/TestCBotView.cpp
new file mode 100644
index 0000000..052e756
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBotView.cpp
@@ -0,0 +1,126 @@
+// TestCBotView.cpp : implementation of the CTestCBotView class
+//
+
+#include "stdafx.h"
+#include "TestCBot.h"
+
+#include "TestCBotDoc.h"
+#include "TestCBotView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotView
+
+IMPLEMENT_DYNCREATE(CTestCBotView, CView)
+
+BEGIN_MESSAGE_MAP(CTestCBotView, CView)
+ //{{AFX_MSG_MAP(CTestCBotView)
+ ON_WM_SIZE()
+ ON_MESSAGE(WM_ACTWINDOW, ActWindow)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotView construction/destruction
+
+CTestCBotView::CTestCBotView()
+{
+}
+
+CTestCBotView::~CTestCBotView()
+{
+}
+
+BOOL CTestCBotView::PreCreateWindow(CREATESTRUCT& cs)
+{
+ return CView::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotView drawing
+
+void CTestCBotView::OnDraw(CDC* pDC)
+{
+ CTestCBotDoc* pDoc = GetDocument();
+ ASSERT_VALID(pDoc);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotView diagnostics
+
+#ifdef _DEBUG
+void CTestCBotView::AssertValid() const
+{
+ CView::AssertValid();
+}
+
+void CTestCBotView::Dump(CDumpContext& dc) const
+{
+ CView::Dump(dc);
+}
+
+CTestCBotDoc* CTestCBotView::GetDocument() // non-debug version is inline
+{
+ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestCBotDoc)));
+ return (CTestCBotDoc*)m_pDocument;
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CTestCBotView message handlers
+
+void CTestCBotView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
+{
+ CTestCBotDoc* pDoc = GetDocument();
+// CTestCBotApp* pApp = (CTestCBotApp*)AfxGetApp();
+
+ if ( pDoc->m_pEdit == NULL)
+ {
+ pDoc->m_pEdit = new CEdit();
+ CRect rect;
+ GetClientRect( rect );
+
+ pDoc->m_pEdit->Create( WS_VISIBLE|WS_BORDER|WS_TABSTOP|ES_MULTILINE|ES_WANTRETURN|ES_NOHIDESEL|ES_AUTOVSCROLL,
+ rect, this, IDC_EDIT1 );
+ pDoc->m_pEdit->SetTabStops(12);
+ pDoc->m_pEdit->SetWindowText(pDoc->m_DocText);
+ }
+
+ if ( !bActivate && !pDoc->Compile() )
+ {
+// comment faire pour réactiver l'ancien document
+ }
+
+ CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
+
+ if ( bActivate ) pDoc->m_pEdit->SetFocus();
+}
+
+
+void CTestCBotView::OnSize(UINT nType, int cx, int cy)
+{
+ CView::OnSize(nType, cx, cy);
+
+ CTestCBotDoc* pDoc = GetDocument();
+ if ( pDoc->m_pEdit != NULL )
+ {
+ CRect rect;
+ GetClientRect( rect );
+ pDoc->m_pEdit->MoveWindow( rect );
+ pDoc->m_pEdit->SetFocus();
+ }
+}
+
+
+
+LONG CTestCBotView::ActWindow(UINT wparam, LONG lparam)
+{
+// GetParentFrame()->SetActiveView( this, TRUE );
+// CMDIChildWnd::OnMDIActivate(1, this, this)
+ return 0;
+}
diff --git a/src/CBot/TestCBot/TestCBotView.h b/src/CBot/TestCBot/TestCBotView.h
new file mode 100644
index 0000000..bca156f
--- /dev/null
+++ b/src/CBot/TestCBot/TestCBotView.h
@@ -0,0 +1,64 @@
+// TestCBotView.h : interface of the CTestCBotView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_TESTCBOTVIEW_H__4D1BB90D_8E74_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_TESTCBOTVIEW_H__4D1BB90D_8E74_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CTestCBotView : public CView
+{
+protected: // create from serialization only
+ CTestCBotView();
+ DECLARE_DYNCREATE(CTestCBotView)
+
+// Attributes
+public:
+ CTestCBotDoc* GetDocument();
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTestCBotView)
+ public:
+ virtual void OnDraw(CDC* pDC); // overridden to draw this view
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ protected:
+ virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CTestCBotView();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CTestCBotView)
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg LONG ActWindow(UINT wparam, LONG lparam) ;
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#ifndef _DEBUG // debug version in TestCBotView.cpp
+inline CTestCBotDoc* CTestCBotView::GetDocument()
+ { return (CTestCBotDoc*)m_pDocument; }
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TESTCBOTVIEW_H__4D1BB90D_8E74_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/TestCBot/TestNull.txt b/src/CBot/TestCBot/TestNull.txt
new file mode 100644
index 0000000..f447245
--- /dev/null
+++ b/src/CBot/TestCBot/TestNull.txt
@@ -0,0 +1,15 @@
+extern public void TestNull ()
+{
+ CPoint pointeur = null;
+
+ try {
+ pointeur.x = 4; }
+ catch ( 6007 ) {}
+
+ pointeur = new CPoint(1,2);
+
+ print ( pointeur.x, pointeur.y,
+ pointeur );
+
+ pointeur.x = 5;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/TestRestoreState.txt b/src/CBot/TestCBot/TestRestoreState.txt
new file mode 100644
index 0000000..1e49e37
--- /dev/null
+++ b/src/CBot/TestCBot/TestRestoreState.txt
@@ -0,0 +1,67 @@
+// routine de Daniel qui plante après RestoreState
+
+extern void object::Attack( )
+{
+ int list[], i;
+ object p;
+ float dist, prox;
+ point nav1, nav2, dest;
+ boolean advance = true;
+
+ i = 0;
+ list[i++] = WingedGrabber;
+ list[i++] = TrackedGrabber;
+ list[i++] = WheeledGrabber;
+ list[i++] = LeggedGrabber;
+ list[i++] = WingedShooter;
+ list[i++] = TrackedShooter;
+ list[i++] = WheeledShooter;
+ list[i++] = LeggedShooter;
+ list[i++] = WingedOrgaShooter;
+ list[i++] = TrackedOrgaShooter;
+ list[i++] = WheeledOrgaShooter;
+ list[i++] = LeggedOrgaShooter;
+ list[i++] = WingedSniffer;
+ list[i++] = TrackedSniffer;
+ list[i++] = WheeledSniffer;
+ list[i++] = LeggedSniffer;
+ list[i++] = Thumper;
+ list[i++] = PhazerShooter;
+ list[i++] = Recycler;
+ list[i++] = Shielder;
+ list[i++] = Subber;
+ list[i++] = Me;
+
+ nav1.x = 1;//cmdline(0);
+ nav1.y = 1;//cmdline(1);
+ nav2.x = 2;//cmdline(2);
+ nav2.y = 2;//cmdline(3);
+
+ while ( true )
+ {
+ while ( true )
+ {
+ // ennemi à proximité ?
+ p = radar(list, 0, 360, 0, 40);
+ if ( p == null ) break;
+ // lui tire dessus
+ fire(p.position);
+ }
+
+ // se promène vers le point A
+ goto(nav1);
+
+ while ( true )
+ {
+ // ennemi à proximité ?
+ p = radar(list, 0, 360, 0, 40);
+ if ( p == null ) break;
+ // lui tire dessus
+ fire(p.position);
+ }
+
+ // se promène vers le point B
+ goto(nav2);
+ }
+}
+
diff --git a/src/CBot/TestCBot/TestStatic.txt b/src/CBot/TestCBot/TestStatic.txt
new file mode 100644
index 0000000..f501aa5
--- /dev/null
+++ b/src/CBot/TestCBot/TestStatic.txt
@@ -0,0 +1,31 @@
+class ESSAI
+{
+ int x = 0;
+ static int nb = 3;
+ static int [ ] array ;
+
+ void Put( int val)
+ {
+show(nb);
+ array[ nb ] = val;
+// this.nb++;
+ this.nb = this.nb + 1;
+show(nb, array);
+ }
+ int Get( )
+ {
+ nb--;
+show("out", nb, array);
+ return array[ nb ] ;
+ }
+}
+
+extern public void T()
+{
+ ESSAI t1 ( ) ;
+ ESSAI t2 ( ) ;
+ t1.nb++;
+ t1.Put( 11 ); t1.Put( 12 ); t2.Put( 13 );
+
+ show ( t1.Get(), t2.Get(), t2.Get() ) ;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/TestStr.txt b/src/CBot/TestCBot/TestStr.txt
new file mode 100644
index 0000000..683ec1b
--- /dev/null
+++ b/src/CBot/TestCBot/TestStr.txt
@@ -0,0 +1,17 @@
+extern public void TSTR()
+{
+ string s = "C'est un essai";
+
+ print ( s, strlen(s), strleft(s, 3), strright(s,3), strmid(s, 2), strmid(s,2,3), strfind(s, "un"), strfind(s, "sdgfld") );
+
+ show ( strupper(s), strlower(s) );
+
+ s = "123.45" ;
+ print ( strval(s) );
+
+
+ string sub = strright("abcdef", 2); // sub vaut "ef###", # étant un caractère bizarre quelconque
+ show (sub);
+ int pos = strfind("abcdef", "xy"); // pos vaut -1. Pourquoi pas nan ?
+ show(pos);
+}
diff --git a/src/CBot/TestCBot/Z.txt b/src/CBot/TestCBot/Z.txt
new file mode 100644
index 0000000..714119b
--- /dev/null
+++ b/src/CBot/TestCBot/Z.txt
@@ -0,0 +1,14 @@
+public extern void tp()
+{
+ int a [4], b[];
+ a [ 0 ] = 8 ;
+
+ b = T ( a ) ;
+ show ( a, b );
+}
+
+int[] T ( int[] Z )
+{
+ for ( int i = 0; i < 4 ; i++ ) Z[ i ] = i * i ;
+ return Z;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/array.txt b/src/CBot/TestCBot/array.txt
new file mode 100644
index 0000000..081b60e
--- /dev/null
+++ b/src/CBot/TestCBot/array.txt
@@ -0,0 +1,24 @@
+
+public extern void TestTableau ()
+{
+ int tableau [ 12 ] ;
+
+ point array[ 12 ] [ 14 ] ;
+
+ point zéro ( 1, 2 ) ;
+ point a = zéro ;
+
+ for ( int i = 0 ; i < 10 ; i++ ) array[ i ] [ i ]= zéro ;
+
+ array[ 5 ] [3 ] . x =1.5 ;
+
+ array[ 2 ] [ 2 ] . y = array[ 5 ] [ 5 ] . x ;
+
+ array[ 4 ] = array [ 2 ] ;
+
+ for ( int i = 0 ; i < 10 ; i++ ) for ( int j = 0 ; j < 4 ; j++ ) println ( i, j, array [ i ] [ j ] ) ;
+
+ show( zéro, a, array );
+
+}
+
diff --git a/src/CBot/TestCBot/a§1.txt b/src/CBot/TestCBot/a§1.txt
new file mode 100644
index 0000000..0c57950
--- /dev/null
+++ b/src/CBot/TestCBot/a§1.txt
@@ -0,0 +1,96 @@
+object radarGuepe(point orig, float dist)
+{
+ int i;
+ object pr, r;
+ float mindist;
+
+ i = 0;
+ mindist = 1000;
+ while (i<30)
+ {
+ pr = radar(i);
+ if (pr != null)
+ {
+
+ if (F(orig, pr.position) < mindist and pr.category == AlienWasp and pr.altitude > 3)
+ {
+ mindist = distance(orig, pr.position);
+ r = pr;
+ }
+ }
+ i = i+1;
+ }
+ if (mindist < dist) return(r); else return(null);
+}
+
+
+class Guepe
+{
+
+ point pos;
+
+
+ void cherche(point orig, float dist)
+ {
+ object p;
+ point o;
+
+ p = radarGuepe(orig, dist);
+ while (p == null)
+ {
+ wait(0.1);
+ p = radarGuepe(orig, dist);
+ }
+
+ pos.x = p.position.x;
+ pos.y = p.position.y;
+ pos.z = p.position.z;
+
+ //o = p.position;
+ //wait(0.1);
+
+ //vitessex = (p.position.x - o.x)/0.1;
+ //vitessey = (p.position.y - o.y)/0.1;
+ //vitessez = (p.position.z - o.z)/0.1;
+
+ }
+
+
+ void tire(point orig, float orient)
+ {
+ //float t = 3; //temps d'anticipation
+ float angle;
+ point cible;
+
+ cible.x = pos.x;// + t*vitessex;
+ cible.y = pos.y;// + t*vitessey;
+ cible.z = pos.z;// + t*vitessez;
+
+ if (cible.x == 0) angle = 90; else
+ angle = atan(cible.y / cible.x);
+ if (cible.x < 0) angle = angle + 180;
+ angle = angle - orient;
+ if (angle > 180) angle = angle - 360;
+ if (angle < -180) angle = angle + 360;
+ turn(angle);
+
+ angle = atan((cible.z-orig.z) / distance2d(orig, cible));
+ aim(angle);
+
+ fire(0.1);
+
+ }
+}
+
+extern void object::Fourmi6()
+{
+ //fps(1000);
+ Guepe guepe = new Guepe();
+
+ while (true)
+ {
+ guepe.cherche(position, 50);
+
+ guepe.tire(position, orientation);
+ }
+}
diff --git a/src/CBot/TestCBot/bug.txt b/src/CBot/TestCBot/bug.txt
new file mode 100644
index 0000000..4ec6eb3
--- /dev/null
+++ b/src/CBot/TestCBot/bug.txt
@@ -0,0 +1,12 @@
+public extern void object::Bug()
+{
+ point a;
+ a = position;
+ TEST();
+ float d=dist(a, position);
+}
+
+float dist(point a, point b)
+{
+ return a.x-b.x;
+}
diff --git a/src/CBot/TestCBot/bugmw.txt b/src/CBot/TestCBot/bugmw.txt
new file mode 100644
index 0000000..284ee43
--- /dev/null
+++ b/src/CBot/TestCBot/bugmw.txt
@@ -0,0 +1,9 @@
+extern public void main()
+{
+ show(fact(30)) ;
+}
+
+public int fact(int n)
+{
+ return (fact(n-1)*n) ;
+}
diff --git a/src/CBot/TestCBot/ccc.txt b/src/CBot/TestCBot/ccc.txt
new file mode 100644
index 0000000..dbcd1d5
--- /dev/null
+++ b/src/CBot/TestCBot/ccc.txt
@@ -0,0 +1,8 @@
+public extern void ccc()
+{
+ int a;
+ a = 0 ;
+
+ if ( a == 0 );
+
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/enum.txt b/src/CBot/TestCBot/enum.txt
new file mode 100644
index 0000000..a592a7f
--- /dev/null
+++ b/src/CBot/TestCBot/enum.txt
@@ -0,0 +1,9 @@
+
+enum JourDeLaSemaine {
+ lundi = 1,
+ mardi,
+ mercredi,
+ jeudi,
+ vendredi,
+ samedi,
+ dimanche = 0 } \ No newline at end of file
diff --git a/src/CBot/TestCBot/fibo.txt b/src/CBot/TestCBot/fibo.txt
new file mode 100644
index 0000000..88f5357
--- /dev/null
+++ b/src/CBot/TestCBot/fibo.txt
@@ -0,0 +1,25 @@
+
+extern public int Fibo( int n, boolean b )
+{
+ if ( n < 2 ) return n;
+ int a = Fibo(n-1, b) + Fibo(n-2, false);
+ if ( b ) print (n + "=" + a);
+ return a;
+}
+
+extern public void t()
+{
+ Fibo( 23, true);
+}
+
+extern public void tt()
+{
+ t();
+}
+
+// cette routine n'est évidemment pas du tout obtimisée
+// c'est même un très mauvais exemple de programmation récursive
+
+// pour un test de durée, Fibo(23, true) prend
+// en mode Debug 67 secondes
+// en mode Release 8 secondes
diff --git a/src/CBot/TestCBot/file.txt b/src/CBot/TestCBot/file.txt
new file mode 100644
index 0000000..2a22dd9
--- /dev/null
+++ b/src/CBot/TestCBot/file.txt
@@ -0,0 +1,70 @@
+class CLASS22
+{
+ static int nb = 2;
+ void T22 ( ) { nb = nb / 0 ; }
+}
+
+public extern void object :: TEST()
+{
+ switch ( 1 )
+ {
+ case 1:
+ {
+ file h();
+ h.open("Mon Fichier.txt", "r");
+show ( h.filename, h.handle );
+h.filename = "xx";
+h.handle = 1 ;
+ h.readln();
+ h.close();
+ }
+ case 2:
+ {
+ file h("Mon Fichier.txt");
+ h.open("r");
+ h.readln();
+ h.close();
+ }
+ case 3:
+ {
+ file h("Mon Fichier.txt", "r");
+ h.readln();
+ h.close();
+ }
+ case 4:
+ {
+ file h();
+ h.filename = "Mon Fichier.txt";
+ h.open("r");
+ h.readln();
+ h.close();
+ }
+ case 5:
+ {
+ file h = fileopen( "Mon 2Fichier.txt", "r" );
+ h.readln();
+ h.close();
+ }
+ }
+{
+ file h( ) ;
+ h.filename = "Test.h";
+ h.open ( "r" );
+
+
+ file pf ( "Mon Fichier.txt" ) ;
+ pf . open ( "w" ) ;
+ pf . writeln ( "Voici encore du texte" ) ;
+ pf . writeln ( "et une seconde ligne" ) ;
+ pf . close( );
+
+ pf . open ( "r" ) ;
+
+ while ( not pf . eof( ) )
+ {
+ string s = pf . readln ( );
+ show ( s );
+ }
+ pf.close( );
+}
+}
diff --git a/src/CBot/TestCBot/h.txt b/src/CBot/TestCBot/h.txt
new file mode 100644
index 0000000..c395319
--- /dev/null
+++ b/src/CBot/TestCBot/h.txt
@@ -0,0 +1,5 @@
+void tf()
+{
+ file h;
+ h.handle += 1 ;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/include.txt b/src/CBot/TestCBot/include.txt
new file mode 100644
index 0000000..e8f8cc9
--- /dev/null
+++ b/src/CBot/TestCBot/include.txt
@@ -0,0 +1,27 @@
+class Z
+{
+ static int x = 0;
+ private int y;
+
+ void T( )
+ {
+ // autorisé ici
+ y = x ;
+ this.y = this.x ;
+ x = y ;
+ this.x = this.y ;
+ }
+}
+
+extern public void test()
+{
+ Z a();
+ 3 * a.x; // autorisé
+//vu 3 * a.y; // interdit
+//vu a.y = 3; // interdit ici
+ a.x = 1; // autorisé
+
+ show ( a );
+ a.T();
+ show ( a );
+}
diff --git a/src/CBot/TestCBot/intrinsic.txt b/src/CBot/TestCBot/intrinsic.txt
new file mode 100644
index 0000000..f215791
--- /dev/null
+++ b/src/CBot/TestCBot/intrinsic.txt
@@ -0,0 +1,16 @@
+public extern void TestIntrinsic()
+{
+ point a ( 1, 2 );
+ print (a);
+
+ a.x = 3;
+ a.y = 4;
+
+ point b = a;
+
+ println ( b.x, b.y, b ) ;
+ if ( b == a ) b.y = 0;
+ println (a,b);
+ if ( b != a ) b.y = a.y;
+ println(a,b);
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/methode1.txt b/src/CBot/TestCBot/methode1.txt
new file mode 100644
index 0000000..080bba2
--- /dev/null
+++ b/src/CBot/TestCBot/methode1.txt
@@ -0,0 +1,57 @@
+class t {
+ point p;
+}
+
+void object :: toto()
+{
+ show ( Position ) ;
+}
+
+extern public void object :: XX()
+{
+ int test [];
+ test [ 9999 ] = 3;
+
+ toto () ;
+/*
+ Radar();
+
+ object test ;
+ test = this. Radar();
+
+ do {
+ test = this.Radar();
+ } while ( test == null );
+
+/*
+ t test [ 4 ];
+ for ( int i = 0 ; i < 4 ; i++ ) test [ i ] = new t();
+ test [ 3 ] .p.x = 2;
+ show ( test );
+/*
+ int a = nan;
+ show ( a ) ;
+
+ a = TypeMarkPath;
+ show ( a, a++, --a ) ;
+
+ if ( a != nan ) a += 1 ;
+
+ a = TypeMarkPath;
+ float q = a ;
+ show ( a, q ) ;
+
+return;
+
+ a += ++a;
+ show ( a ) ;
+
+ boolean i = false;
+
+ if ( i == true ) {}
+
+ object p;
+ if ( p == null) { p = p ; }
+*/
+}
+
diff --git a/src/CBot/TestCBot/methode2.txt b/src/CBot/TestCBot/methode2.txt
new file mode 100644
index 0000000..76ce7f4
--- /dev/null
+++ b/src/CBot/TestCBot/methode2.txt
@@ -0,0 +1,50 @@
+
+extern void Toto()
+{
+ TEST(12);
+
+ for ( int i = 0 ; i<1000; i++)
+ {
+ int j = 1;
+ if (i==55) TEST(12);
+ }
+
+ TEST(2);
+
+
+// Nouveau();
+ int toto[4];
+ point Z[3];
+
+ Z[1].x = 11; Z[1].y = 12;
+
+ toto[2] = 12;
+ toto[1] = nan;
+
+// point test, autre(2,3) ;
+// object titi = Radar();
+
+ TEST ( 1 ) ;
+
+ toto[0] = 11;
+
+ TEST ( 2 ) ;
+
+ toto[6] = 0;
+}
+
+extern void object::Nouveau()
+{
+ point a;
+ a = np(Position);
+}
+
+point np(point b)
+{
+ point c;
+ c.x = b.y;
+ c.y = b.x;
+ return c ;
+}
+
+
diff --git a/src/CBot/TestCBot/mp1.txt b/src/CBot/TestCBot/mp1.txt
new file mode 100644
index 0000000..599cfc4
--- /dev/null
+++ b/src/CBot/TestCBot/mp1.txt
@@ -0,0 +1,25 @@
+class Guepet
+{
+
+ float a;
+ float b;
+
+ void init()
+ {
+ a = 12.34;
+ b = 56.78;
+ }
+
+
+}
+
+extern void object::Fourmi6()
+{
+ Guepet guepe =new Guepet();
+
+ guepe.init();
+
+
+ show("test "+guepe.a+" "+guepe.b);
+
+}
diff --git a/src/CBot/TestCBot/mp2.txt b/src/CBot/TestCBot/mp2.txt
new file mode 100644
index 0000000..1c2972c
--- /dev/null
+++ b/src/CBot/TestCBot/mp2.txt
@@ -0,0 +1,28 @@
+class Guepet
+{
+
+ float a;
+ float b;
+
+ void init()
+ {
+ a = 12.34;
+ b = 56.78;
+
+ object x = radar(123);
+ show("radar "+x.position.x);
+ show("C'est fait");
+ }
+
+
+}
+
+extern void object::Fourmi6()
+{
+ Guepet guepe=new Guepet();
+
+ guepe.init();
+
+ show("test "+guepe.a+" "+guepe.b);
+
+}
diff --git a/src/CBot/TestCBot/mw.txt b/src/CBot/TestCBot/mw.txt
new file mode 100644
index 0000000..c237670
--- /dev/null
+++ b/src/CBot/TestCBot/mw.txt
@@ -0,0 +1,16 @@
+extern public void main()
+{
+// goto( 3, 4 );
+
+ while( true )
+ {
+ try { goto (12) ; }
+ catch( FF( ) )
+ { show( "ko"); }
+ }
+}
+
+boolean FF()
+{
+ return false;
+}
diff --git a/src/CBot/TestCBot/null.txt b/src/CBot/TestCBot/null.txt
new file mode 100644
index 0000000..ae76b74
--- /dev/null
+++ b/src/CBot/TestCBot/null.txt
@@ -0,0 +1,5 @@
+extern public void xxx ()
+{
+ CPoint test = null ;
+ if ( test == null ) show ( "NULL" );
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/opnew.txt b/src/CBot/TestCBot/opnew.txt
new file mode 100644
index 0000000..7d6838c
--- /dev/null
+++ b/src/CBot/TestCBot/opnew.txt
@@ -0,0 +1,20 @@
+extern public void xx ()
+{
+ CPoint pointeur, test = null ;
+ pointeur = new CPoint ( 3, 4 );
+
+ if ( test == null ) show ( "NULL" );
+
+ CPoint pp = pointeur;
+
+show( pointeur , pp );
+
+ pp.x = 33.3;
+ if ( pointeur.x != pp.x ) 0/0;
+
+ pp = new CPoint();
+// pointeur = pp;
+
+show( pointeur , pp );
+
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/plante.txt b/src/CBot/TestCBot/plante.txt
new file mode 100644
index 0000000..363461b
--- /dev/null
+++ b/src/CBot/TestCBot/plante.txt
@@ -0,0 +1,25 @@
+class Guepet
+{
+
+ point pos;
+ float t = 0.1;
+
+ void init()
+ {
+ pos.x = 12.123;
+ pos.y = 34.345;
+
+ F(t);
+ }
+
+
+}
+
+extern void object::Fourmi6()
+{
+ Guepet guepe=new Guepet();
+
+ guepe.init();
+
+ show ( guepe );
+}
diff --git a/src/CBot/TestCBot/pointer.txt b/src/CBot/TestCBot/pointer.txt
new file mode 100644
index 0000000..2d4d907
--- /dev/null
+++ b/src/CBot/TestCBot/pointer.txt
@@ -0,0 +1,41 @@
+extern public void x ()
+{
+ show ( 3 ** 4 );
+ float z = 1e-3;
+ show ( z );
+
+ CPoint b ( 4,5 );
+ show ( b );
+
+ CPoint a ( ) ;
+ a.x = 21; a.y = 12;
+ show ( a ) ;
+
+ CPoint test = new CPoint ( 1,1 );
+ test = new CPoint ( 2, 2 );
+ show ( test );
+}
+
+// crée un objet et retourne son pointeur
+CPoint newcpoint()
+{
+ CPoint p = new CPoint ( 3, 3 );
+ return p;
+}
+
+extern public void y ()
+{
+ CPoint test = newcpoint();
+ println ( test );
+ dontmodif( test );
+ println ( test );
+}
+
+// ne doit pas modifier l'objet en paramètre
+void dontmodif ( CPoint pp )
+{
+ pp.x = 5;
+ pp.y = 2;
+ println ( pp, pp.x, pp.y );
+}
+
diff --git a/src/CBot/TestCBot/postinc.txt b/src/CBot/TestCBot/postinc.txt
new file mode 100644
index 0000000..cdf6ab5
--- /dev/null
+++ b/src/CBot/TestCBot/postinc.txt
@@ -0,0 +1,7 @@
+extern public void X()
+{
+ point A [ ] ;
+ A[5] = new point (2,3);
+ int val = A[5].x++ + --A[5].y;
+ show ( A, val );
+}
diff --git a/src/CBot/TestCBot/radar.txt b/src/CBot/TestCBot/radar.txt
new file mode 100644
index 0000000..09d84a2
--- /dev/null
+++ b/src/CBot/TestCBot/radar.txt
@@ -0,0 +1,39 @@
+extern void object::Bug( )
+{
+ try{ int a = 44 ; a = 12 / 0 ; }
+ catch(6000) { int b = 4 ; }
+ finally { int z = 1 ; }
+
+// tp ( A, B );
+
+/* int a = 4, b = 2, c = nan;
+ float x, y = 3/2, z = nan;
+ boolean i, j = false, k = true;
+
+ string s, ss = "xyz";
+
+ while ( false )
+ {
+ object left, right;
+
+ left = Radar(TypeMarkPath, -45, 120, 100);
+ right = Radar(TypeMarkPath, 45, 120, 100);
+
+ if ( left == null && right == null )
+ {
+ }
+ }
+ int t = fact ( 4 ) ;*/
+}
+
+void tp( point a , point b )
+{
+ a.x += b.x;
+}
+
+
+int fact( int n )
+{
+ if ( n < 2 ) return n;
+ return n * fact ( n - 1 ) ;
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/res/TestCBot.ico b/src/CBot/TestCBot/res/TestCBot.ico
new file mode 100644
index 0000000..06a649d
--- /dev/null
+++ b/src/CBot/TestCBot/res/TestCBot.ico
Binary files differ
diff --git a/src/CBot/TestCBot/res/TestCBot.rc2 b/src/CBot/TestCBot/res/TestCBot.rc2
new file mode 100644
index 0000000..b55f0d9
--- /dev/null
+++ b/src/CBot/TestCBot/res/TestCBot.rc2
@@ -0,0 +1,13 @@
+//
+// TESTCBOT.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/CBot/TestCBot/res/TestCBotDoc.ico b/src/CBot/TestCBot/res/TestCBotDoc.ico
new file mode 100644
index 0000000..3545614
--- /dev/null
+++ b/src/CBot/TestCBot/res/TestCBotDoc.ico
Binary files differ
diff --git a/src/CBot/TestCBot/res/Toolbar.bmp b/src/CBot/TestCBot/res/Toolbar.bmp
new file mode 100644
index 0000000..04a71af
--- /dev/null
+++ b/src/CBot/TestCBot/res/Toolbar.bmp
Binary files differ
diff --git a/src/CBot/TestCBot/resource.h b/src/CBot/TestCBot/resource.h
new file mode 100644
index 0000000..bed36ca
--- /dev/null
+++ b/src/CBot/TestCBot/resource.h
@@ -0,0 +1,30 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by TestCBot.rc
+//
+#define IDD_ABOUTBOX 100
+#define IDR_MAINFRAME 128
+#define IDR_TESTCBTYPE 129
+#define IDD_DIALOG1 130
+#define IDD_CONSOLE 131
+#define IDD_DIALOG2 133
+#define IDC_EDIT1 1000
+#define TX_TYPENAMES 1000
+#define IDC_SPIN1 1001
+#define IDC_EDIT2 1002
+#define IDC_COMBO1 1003
+#define IDC_EDIT3 1004
+#define ID_RUN 32771
+#define ID_TEST 32772
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 135
+#define _APS_NEXT_COMMAND_VALUE 32773
+#define _APS_NEXT_CONTROL_VALUE 1004
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/CBot/TestCBot/solution.txt b/src/CBot/TestCBot/solution.txt
new file mode 100644
index 0000000..f78cf12
--- /dev/null
+++ b/src/CBot/TestCBot/solution.txt
@@ -0,0 +1,13 @@
+extern void object::Solution( )
+{
+show ( "Solution " + Position );
+ Carré(15);
+ Carré(25);
+}
+
+void object::Carré(float côté)
+{
+show ( "Carré " + Position );
+ Move(côté);
+ Turn(-90);
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/test.txt b/src/CBot/TestCBot/test.txt
new file mode 100644
index 0000000..a912415
--- /dev/null
+++ b/src/CBot/TestCBot/test.txt
@@ -0,0 +1,8 @@
+extern public void x()
+{
+ float a= 1, b = 2;
+ a = b * ( 2 + 2 );
+// print (a);
+ a += 4;
+// print (a);
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/test23.txt b/src/CBot/TestCBot/test23.txt
new file mode 100644
index 0000000..d6e1ddd
--- /dev/null
+++ b/src/CBot/TestCBot/test23.txt
@@ -0,0 +1,10 @@
+extern public void object::TEST23()
+{
+ CLASS22 T;
+ T.T22( ) ;
+
+ show( position );
+ show( this.position );
+
+// T22();
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/testmw.txt b/src/CBot/TestCBot/testmw.txt
new file mode 100644
index 0000000..6570f6d
--- /dev/null
+++ b/src/CBot/TestCBot/testmw.txt
@@ -0,0 +1,14 @@
+extern public int testmw( int a)
+{
+ boolean b = true ;
+
+ if (b)
+ return 1 ;
+ else
+ return a ; 0 * testmw(a-1) ;
+}
+
+public int Fibo2 ( int n )
+{
+ print ( " bof " );
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/this.txt b/src/CBot/TestCBot/this.txt
new file mode 100644
index 0000000..b8a9e04
--- /dev/null
+++ b/src/CBot/TestCBot/this.txt
@@ -0,0 +1,13 @@
+extern void object :: TEST22 ( )
+{
+ show( position );
+ show( this.position );
+
+ T();
+}
+
+public void object :: T22()
+{
+ show( position );
+ show( this.position );
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/tt.txt b/src/CBot/TestCBot/tt.txt
new file mode 100644
index 0000000..cd13c9d
--- /dev/null
+++ b/src/CBot/TestCBot/tt.txt
@@ -0,0 +1,12 @@
+extern public void T() { T1(); }
+
+public void T1()
+{
+ show( "T1" );
+ T2();
+}
+
+public void T2()
+{
+ show( "T2" );
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/tt2.txt b/src/CBot/TestCBot/tt2.txt
new file mode 100644
index 0000000..ad9dc1d
--- /dev/null
+++ b/src/CBot/TestCBot/tt2.txt
@@ -0,0 +1,5 @@
+extern public void TT()
+{
+ T1();
+ T2();
+} \ No newline at end of file
diff --git a/src/CBot/TestCBot/vide.txt b/src/CBot/TestCBot/vide.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/CBot/TestCBot/vide.txt
diff --git a/src/CBot/TestCBot/xTestCBot.clw b/src/CBot/TestCBot/xTestCBot.clw
new file mode 100644
index 0000000..5b84c16
--- /dev/null
+++ b/src/CBot/TestCBot/xTestCBot.clw
@@ -0,0 +1,245 @@
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CBotConsoleDlg
+LastTemplate=CDialog
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "TestCBot.h"
+LastPage=0
+
+ClassCount=7
+Class1=CTestCBotApp
+Class2=CTestCBotDoc
+Class3=CTestCBotView
+Class4=CMainFrame
+
+ResourceCount=7
+Resource1=IDD_ABOUTBOX
+Resource2=IDR_MAINFRAME
+Resource3=IDR_TESTCBTYPE
+Class5=CAboutDlg
+Class6=CChildFrame
+Resource4=IDD_ABOUTBOX (French (France))
+Resource5=IDR_TESTCBTYPE (French (France))
+Resource6=IDD_CONSOLE
+Class7=CBotConsoleDlg
+Resource7=IDR_MAINFRAME (French (France))
+
+[CLS:CTestCBotApp]
+Type=0
+HeaderFile=TestCBot.h
+ImplementationFile=TestCBot.cpp
+Filter=N
+
+[CLS:CTestCBotDoc]
+Type=0
+HeaderFile=TestCBotDoc.h
+ImplementationFile=TestCBotDoc.cpp
+Filter=N
+BaseClass=CDocument
+VirtualFilter=DC
+LastObject=IDC_EDIT2
+
+[CLS:CTestCBotView]
+Type=0
+HeaderFile=TestCBotView.h
+ImplementationFile=TestCBotView.cpp
+Filter=C
+BaseClass=CView
+VirtualFilter=VWC
+LastObject=CTestCBotView
+
+[CLS:CMainFrame]
+Type=0
+HeaderFile=MainFrm.h
+ImplementationFile=MainFrm.cpp
+Filter=T
+BaseClass=CMDIFrameWnd
+VirtualFilter=fWC
+LastObject=CMainFrame
+
+
+[CLS:CChildFrame]
+Type=0
+HeaderFile=ChildFrm.h
+ImplementationFile=ChildFrm.cpp
+Filter=M
+
+[CLS:CAboutDlg]
+Type=0
+HeaderFile=TestCBot.cpp
+ImplementationFile=TestCBot.cpp
+Filter=D
+
+[DLG:IDD_ABOUTBOX]
+Type=1
+ControlCount=4
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308352
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+Class=CAboutDlg
+
+[MNU:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command4=ID_APP_EXIT
+Command5=ID_VIEW_TOOLBAR
+Command6=ID_VIEW_STATUS_BAR
+Command7=ID_APP_ABOUT
+CommandCount=7
+Command3=ID_FILE_MRU_FILE1
+
+[TB:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_EDIT_CUT
+Command5=ID_EDIT_COPY
+Command6=ID_EDIT_PASTE
+Command7=ID_FILE_PRINT
+CommandCount=8
+Command8=ID_APP_ABOUT
+
+[MNU:IDR_TESTCBTYPE]
+Type=1
+Class=CTestCBotView
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_CLOSE
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVE_AS
+Command9=ID_EDIT_CUT
+Command10=ID_EDIT_COPY
+Command11=ID_EDIT_PASTE
+Command12=ID_VIEW_TOOLBAR
+Command13=ID_VIEW_STATUS_BAR
+Command14=ID_WINDOW_NEW
+CommandCount=18
+Command6=ID_FILE_MRU_FILE1
+Command7=ID_APP_EXIT
+Command8=ID_EDIT_UNDO
+Command15=ID_WINDOW_CASCADE
+Command16=ID_WINDOW_TILE_HORZ
+Command17=ID_WINDOW_ARRANGE
+Command18=ID_APP_ABOUT
+
+[ACL:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command5=ID_EDIT_CUT
+Command6=ID_EDIT_COPY
+Command7=ID_EDIT_PASTE
+Command8=ID_EDIT_UNDO
+Command9=ID_EDIT_CUT
+Command10=ID_EDIT_COPY
+Command11=ID_EDIT_PASTE
+Command12=ID_NEXT_PANE
+CommandCount=13
+Command4=ID_EDIT_UNDO
+Command13=ID_PREV_PANE
+
+
+[TB:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_EDIT_CUT
+Command5=ID_EDIT_COPY
+Command6=ID_EDIT_PASTE
+Command7=ID_FILE_PRINT
+Command8=ID_RUN
+Command9=ID_APP_ABOUT
+CommandCount=9
+
+[MNU:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_MRU_FILE1
+Command4=ID_APP_EXIT
+Command5=ID_VIEW_TOOLBAR
+Command6=ID_VIEW_STATUS_BAR
+Command7=ID_APP_ABOUT
+CommandCount=7
+
+[MNU:IDR_TESTCBTYPE (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_CLOSE
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVE_AS
+Command6=ID_FILE_MRU_FILE1
+Command7=ID_APP_EXIT
+Command8=ID_EDIT_UNDO
+Command9=ID_EDIT_CUT
+Command10=ID_EDIT_COPY
+Command11=ID_EDIT_PASTE
+Command12=ID_VIEW_TOOLBAR
+Command13=ID_VIEW_STATUS_BAR
+Command14=ID_WINDOW_NEW
+Command15=ID_WINDOW_CASCADE
+Command16=ID_WINDOW_TILE_HORZ
+Command17=ID_WINDOW_ARRANGE
+Command18=ID_APP_ABOUT
+CommandCount=18
+
+[ACL:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_EDIT_COPY
+Command2=ID_FILE_NEW
+Command3=ID_FILE_OPEN
+Command4=ID_FILE_SAVE
+Command5=ID_EDIT_PASTE
+Command6=ID_EDIT_UNDO
+Command7=ID_EDIT_CUT
+Command8=ID_RUN
+Command9=ID_NEXT_PANE
+Command10=ID_PREV_PANE
+Command11=ID_RUN
+Command12=ID_EDIT_COPY
+Command13=ID_EDIT_PASTE
+Command14=ID_EDIT_CUT
+Command15=ID_EDIT_UNDO
+CommandCount=15
+
+[DLG:IDD_ABOUTBOX (French (France))]
+Type=1
+Class=CAboutDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308480
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+
+[DLG:IDD_CONSOLE]
+Type=1
+Class=CBotConsoleDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDIT2,edit,1350631552
+Control3=IDOK,button,1342242817
+Control4=IDC_EDIT1,edit,1352734724
+
+[CLS:CBotConsoleDlg]
+Type=0
+HeaderFile=CBotConsoleDlg.h
+ImplementationFile=CBotConsoleDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+
diff --git a/src/CBot/TestCBot/zz.txt b/src/CBot/TestCBot/zz.txt
new file mode 100644
index 0000000..da764ac
--- /dev/null
+++ b/src/CBot/TestCBot/zz.txt
@@ -0,0 +1,6 @@
+extern public void zz()
+{
+ MaClass TOTO ();
+
+ show (TOTO);
+} \ No newline at end of file
diff --git a/src/CBot/_Copy.bat b/src/CBot/_Copy.bat
new file mode 100644
index 0000000..510dc5a
--- /dev/null
+++ b/src/CBot/_Copy.bat
@@ -0,0 +1,2 @@
+copy debug\cbot.dll "F:\Program Files\Ceebot\cbot.dll"
+cls \ No newline at end of file
diff --git a/src/CBot/colobot.ini b/src/CBot/colobot.ini
new file mode 100644
index 0000000..32163db
--- /dev/null
+++ b/src/CBot/colobot.ini
@@ -0,0 +1,49 @@
+[Directory]
+scene=scene
+savegame=savegame
+public=program
+user=user
+[Setup]
+TotoMode=1
+Tooltips=1
+InterfaceGlint=1
+NiceMouse=0
+Movies=1
+NiceReset=1
+HimselfDamage=1
+CameraScroll=1
+CameraInvertX=0
+InterfaceEffect=1
+GroundShadow=1
+GroundSpot=1
+ObjectDirty=1
+FogMode=1
+LensMode=1
+SkyMode=1
+PlanetMode=1
+LightMode=1
+UseJoystick=0
+ParticuleDensity=1.00
+ClippingDistance=1.00
+ObjectDetail=2.00
+GadgetQuantity=1.00
+TextureQuality=1
+AudioVolume=20
+MidiVolume=15
+Sound3D=0
+EditIndentMode=1
+EditIndentValue=4
+KeyMap=37+0 39+0 38+0 40+0 16+0 17+0 32+258 96+262 13+257 107+261 109+260 9+259 36+263 27+0 112+0 113+0 110+0 115+0 116+0 117+0
+[Engine]
+AlphaMode=1
+StateColor=-1
+BlackSrcBlend=0
+BlackDestBlend=0
+WhiteSrcBlend=0
+WhiteDestBlend=0
+DiffuseSrcBlend=0
+DiffuseDestBlend=0
+AlphaSrcBlend=0
+AlphaDestBlend=0
+[Gamer]
+LastName=Player
diff --git a/src/CBot/idees.txt b/src/CBot/idees.txt
new file mode 100644
index 0000000..7153789
--- /dev/null
+++ b/src/CBot/idees.txt
@@ -0,0 +1,39 @@
+pour la gestion des instances d'une classe.
+
+l'objet créé actuellement avec CBotVar::Create(nom, pClasse)
+est a conserver tel quel, en dehors des vars sur la pile
+
+il faut un autre type de variable pour garder les pointeurs
+CBotTypPtClass par exemple
+
+L'instance de la classe doit avoir un compteur d'utilisation
+qui est le nombre d'objet de classe CBotTypPtClass qui y réfèrent.
+Le compteur est décrémenté lorsque le pointeur est détruit,
+l'objet supprimé lorsqu'il n'y a plus de pointeurs.
+
+
+Dans le cas des robots, Daniel crée une instance de sa classe "Object"
+et peut retourner des pointeurs à cette instance par des routines genre FindRobot()
+
+Object FindRobot(int n) { }
+
+pResult dans ce cas est un pointeur CBotTypPtClass
+lorsqu'il a trouvé le robot concerné, il lui faudra faire
+
+pResult->SetPointeur(InstanceDeLaClassObject);
+
+cette opération incrémente le compteur des références
+
+--
+
+lorsque le robot est détruit, l'instance de la classe Object correspondant
+est détruit également.
+s'il reste des pointeurs à cet objet, et l'on risque la planté
+
+solution 1:
+ garder non pas le pointeur à l'objet directement, mais
+ un index dans une tables de pointeurs
+
+solution 2:
+ ne pas détruire l'objet imédiatement lorsqu'il reste des pointeurs
+ mais le marqué comme virtuellement détruit \ No newline at end of file
diff --git a/src/CBot/old CBotAddExpr.cpp b/src/CBot/old CBotAddExpr.cpp
new file mode 100644
index 0000000..85b7588
--- /dev/null
+++ b/src/CBot/old CBotAddExpr.cpp
@@ -0,0 +1,130 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 + Opérande2
+// Opérande1 - Opérande2
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotAddExpr::CBotAddExpr()
+{
+ m_leftop =
+ m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
+ name = "CBotAddExpr"; // debug
+}
+
+CBotAddExpr::~CBotAddExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+
+// compile une instruction de type A + B
+
+CBotInstr* CBotAddExpr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack(); // un bout de pile svp
+
+ // cherche des instructions qui peuvent convenir à gauche de l'opération + ou -
+
+ CBotInstr* left = CBotMulExpr::Compile( p, pStk ); // expression A * B à gauche
+ if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
+
+ // est-ce qu'on a le token + ou - ensuite ?
+
+ if ( p->GetType() == ID_ADD ||
+ p->GetType() == ID_SUB) // plus ou moins
+ {
+ CBotAddExpr* inst = new CBotAddExpr(); // élément pour opération
+ inst->SetToken(p); // mémorise l'opération
+
+ int type1, type2;
+ type1 = pStk->GetType(CBotTypChar); // de quel type le premier opérande ?
+
+ p = p->Next(); // saute le token de l'opération
+
+ // cherche des instructions qui peuvent convenir à droite
+
+ if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression (...) à droite
+ {
+ // il y a un second opérande acceptable
+
+ type2 = pStk->GetType(CBotTypChar); // de quel type le résultat ?
+
+ if ( type1 == type2 && // les résultats sont-ils compatibles
+ type1 != CBotTypBoolean &&
+ (inst->m_token.GetType() != ID_SUB ||
+ type1 < CBotTypBoolean )) // pas de soustraction de chaînes !
+ {
+ // si ok, enregistre l'opérande dans l'objet
+ inst->m_leftop = left;
+ // et rend l'object à qui l'a demandé
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_BAD2TYPE, &inst->m_token);
+ }
+
+ // en cas d'erreur, libère les éléments
+ delete left;
+ delete inst;
+ // et transmet l'erreur qui se trouve sur la pile
+ return pStack->Return(NULL, pStk);
+ }
+
+ // si on n'a pas affaire à une opération + ou -
+ // rend à qui l'a demandé, l'opérande (de gauche) trouvé
+ // à la place de l'objet "addition"
+ return pStack->Return(left, pStk);
+}
+
+
+
+
+// fait l'opération d'addition ou de soustraction
+
+BOOL CBotAddExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // selon la reprise, on peut être dans l'un des 2 états
+
+ if ( pStk1->GetState() == 0 && // 1er état, évalue l'opérande de gauche
+ !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ // passe à l'étape suivante
+ pStk1->SetState(1); // prêt pour la suite
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ // qui se trouve sur la pile, justement.
+
+ CBotStack* pStk2 = pStk1->AddStack(); // ajoute un élément à la pile
+ // ou le retrouve en cas de reprise
+
+ // 2e état, évalue l'opérande de droite
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+
+ int type1 = pStk1->GetType(); // de quels types les résultats ?
+ int type2 = pStk2->GetType();
+
+ // crée une variable temporaire pour y mettre le résultat
+ CBotVar* result = CBotVar::Create( NULL, MAX(type1, type2));
+
+ // fait l'opération selon la demande
+ switch (GetTokenType())
+ {
+ case ID_ADD:
+ result->Add(pStk1->GetVar(), pStk2->GetVar()); // additionne
+ break;
+ case ID_SUB:
+ result->Sub(pStk1->GetVar(), pStk2->GetVar()); // soustrait
+ break;
+ }
+ pStk2->SetVar(result); // met le résultat sur la pile
+
+ pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
+
diff --git a/src/CBot/old CBotCompExpr.cpp b/src/CBot/old CBotCompExpr.cpp
new file mode 100644
index 0000000..e7439b7
--- /dev/null
+++ b/src/CBot/old CBotCompExpr.cpp
@@ -0,0 +1,120 @@
+///////////////////////////////////////////////////
+// expression du genre Opérande1 > Opérande2
+// Opérande1 != Opérande2
+// etc.
+
+#include "CBot.h"
+
+// divers constructeurs
+
+CBotCompExpr::CBotCompExpr()
+{
+ m_leftop =
+ m_rightop = NULL;
+ name = "CBotCompExpr";
+}
+
+CBotCompExpr::~CBotCompExpr()
+{
+ delete m_leftop;
+ delete m_rightop;
+}
+
+
+// compile une instruction de type A < B
+
+CBotInstr* CBotCompExpr::Compile(CBotToken* &p, CBotCStack* pStack)
+{
+ CBotCStack* pStk = pStack->TokenStack();
+
+ CBotInstr* left = CBotAddExpr::Compile( p, pStk ); // expression A + B à gauche
+ if (left == NULL) return pStack->Return(NULL, pStk); // erreur
+
+ if ( p->GetType() == ID_HI ||
+ p->GetType() == ID_LO ||
+ p->GetType() == ID_HS ||
+ p->GetType() == ID_LS ||
+ p->GetType() == ID_EQ ||
+ p->GetType() == ID_NE) // les diverses comparaisons
+ {
+ CBotCompExpr* inst = new CBotCompExpr(); // élément pour opération
+ inst->SetToken(p); // mémorise l'opération
+
+ int type1, type2;
+ type1 = pStk->GetType(CBotTypChar);
+
+ p = p->Next();
+ if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression A + B à droite
+ {
+ type2 = pStk->GetType(CBotTypChar);
+ // les résultats sont-ils compatibles
+ if ( type1 == type2 && type1 != CBotTypBoolean && type1 != CBotTypClass)
+ {
+ inst->m_leftop = left;
+ pStk->SetVar(new CBotVar(NULL, CBotTypBoolean));
+ // le résultat est un boolean
+ return pStack->Return(inst, pStk);
+ }
+ pStk->SetError(TX_BAD2TYPE, &inst->m_token);
+ }
+
+ delete left;
+ delete inst;
+ return pStack->Return(NULL, pStk);
+ }
+
+ return pStack->Return(left, pStk);
+}
+
+
+// fait l'opération
+
+BOOL CBotCompExpr::Execute(CBotStack* &pStack)
+{
+ CBotStack* pStk1 = pStack->AddStack();
+
+ if ( pStk1->GetState() == 0 && !m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
+
+ pStk1->SetState(1); // opération terminée
+
+ // demande un peu plus de stack pour ne pas toucher le résultat de gauche
+ CBotStack* pStk2 = pStk1->AddStack();
+
+ if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
+
+ int type1 = pStk1->GetType();
+ int type2 = pStk2->GetType();
+
+ CBotVar* temp = CBotVar::Create( NULL, MAX(type1, type2) );
+ CBotVar* result = CBotVar::Create( NULL, CBotTypBoolean );
+
+ switch (GetTokenType())
+ {
+ case ID_LO:
+ temp->Lo(pStk1->GetVar(), pStk2->GetVar()); // inférieur
+ break;
+ case ID_HI:
+ temp->Hi(pStk1->GetVar(), pStk2->GetVar()); // supérieur
+ break;
+ case ID_LS:
+ temp->Ls(pStk1->GetVar(), pStk2->GetVar()); // inférieur ou égal
+ break;
+ case ID_HS:
+ temp->Hs(pStk1->GetVar(), pStk2->GetVar()); // supérieur ou égal
+ break;
+ case ID_EQ:
+ temp->Eq(pStk1->GetVar(), pStk2->GetVar()); // égal
+ break;
+ case ID_NE:
+ temp->Ne(pStk1->GetVar(), pStk2->GetVar()); // différent
+ break;
+ }
+ result->SetValInt(temp->GetValInt()); // converti le résultat
+ delete temp;
+
+ pStk2->SetVar(result); // met le résultat sur la pile
+
+ pStk1->Return(pStk2); // libère la pile
+ return pStack->Return(pStk1); // transmet le résultat
+}
+
diff --git a/src/CBot/old TstCBot/BotConsoleDlg.cpp b/src/CBot/old TstCBot/BotConsoleDlg.cpp
new file mode 100644
index 0000000..077f080
--- /dev/null
+++ b/src/CBot/old TstCBot/BotConsoleDlg.cpp
@@ -0,0 +1,164 @@
+// BotConsoleDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+#include "BotConsoleDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotConsoleDlg dialog
+
+
+CBotConsoleDlg::CBotConsoleDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CBotConsoleDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CBotConsoleDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ m_pProg = NULL;
+ m_threadinfo.m_bRun = FALSE;
+}
+
+
+void CBotConsoleDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBotConsoleDlg)
+ DDX_Control(pDX, IDOK, m_cOK);
+ DDX_Control(pDX, IDC_EDIT2, m_Edit2);
+ DDX_Control(pDX, IDC_EDIT1, m_Edit1);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CBotConsoleDlg, CDialog)
+ //{{AFX_MSG_MAP(CBotConsoleDlg)
+ ON_MESSAGE(WM_ENDPROG, EndProg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotConsoleDlg message handlers
+
+UINT ThreadProc(ThreadInfo *info)
+{
+ CTime t0 = CTime::GetCurrentTime();
+ int Cpt = 0;
+
+ info->m_pProg->Start("LaCommande");
+ while ( !info->m_bStop && !info->m_pProg->Run() )
+ {
+ Cpt++;
+ if ( Cpt%20 == 0 ) info->m_pEdit1->ReplaceSel(".");
+ }
+
+ if ( info->m_bStop )
+ {
+ info->m_pEdit1->ReplaceSel("\r\nInterrompu\r\n");
+ }
+ else if (info->m_pProg->GivError() == 0)
+ {
+ CTime t = CTime::GetCurrentTime();
+ CTimeSpan ts = t - t0;
+
+ char buffer[200];
+ sprintf( buffer, "\r\nExécution terminée en %d secondes.\r\nInterrompue %d fois.\r\n",
+ ts.GetTotalSeconds(), Cpt);
+
+ info->m_pEdit1->ReplaceSel(buffer);
+ }
+
+ info->m_pWndMessage->SendMessage(WM_ENDPROG, 0, 0) ;
+ return 0 ;
+}
+
+LONG CBotConsoleDlg::EndProg(UINT wparam, LONG lparam)
+{
+ m_threadinfo.m_bRun = FALSE;
+
+ if (m_pProg->GetError(m_code, m_start, m_end))
+ {
+ AfxMessageBox(m_code);
+ CDialog::OnCancel();
+ return 1;
+ }
+ delete m_pProg;
+ m_pProg = NULL;
+
+ m_Edit2.EnableWindow(TRUE);
+ m_cOK.EnableWindow(TRUE);
+
+ m_Edit2.SetWindowText("");
+ m_Edit2.SetFocus();
+ return 0 ;
+}
+
+void CBotConsoleDlg::OnOK()
+{
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+ pApp->m_pConsole = &m_Edit1;
+
+ CString Commande;
+ m_Edit2.GetWindowText(Commande);
+
+ CString s = "void LaCommande() { " + Commande + " ;}";
+ m_pProg = new CBotProgram();
+ CBotStringArray liste;
+ m_pProg->Compile(s, liste);
+ int err, start, end;
+ if ( m_pProg->GetError(err, start, end) )
+ {
+ AfxMessageBox(err);
+ m_Edit2.SetSel(start-20, end-20);
+ return;
+ }
+
+ m_Edit1.ReplaceSel(Commande + " ->\r\n");
+
+ m_Edit2.SetWindowText("");
+ m_Edit1.SetFocus();
+ m_Edit2.EnableWindow(FALSE);
+ m_cOK.EnableWindow(FALSE);
+
+ // lance un processus paralèle pour l'exécution
+ m_threadinfo.m_pWndMessage = this ;
+
+ m_threadinfo.m_pEdit1 = &m_Edit1;
+ m_threadinfo.m_pProg = m_pProg;
+ m_threadinfo.m_bStop = FALSE;
+ m_threadinfo.m_bRun = TRUE;
+
+ AfxBeginThread((AFX_THREADPROC)ThreadProc, &m_threadinfo) ;
+}
+
+void CBotConsoleDlg::OnCancel()
+{
+ if (!m_threadinfo.m_bRun) CDialog::OnCancel();
+ m_threadinfo.m_bStop = TRUE ;
+}
+
+
+BOOL CBotConsoleDlg::OnInitDialog()
+{
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+
+ CDialog::OnInitDialog();
+
+ m_Edit1.ReplaceSel("Les fonctions suivantes sont disponibles:\r\n");
+ for ( int i = 0; i < pApp->m_Liste.RetSize(); i++ )
+ {
+ CBotString x = CString(pApp->m_Liste[i]) + "\r\n";
+ m_Edit1.ReplaceSel(x);
+ }
+ m_Edit1.ReplaceSel("Entrez une commande ci-dessous.\r\n\r\n");
+
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/src/CBot/old TstCBot/BotConsoleDlg.h b/src/CBot/old TstCBot/BotConsoleDlg.h
new file mode 100644
index 0000000..9b54ff2
--- /dev/null
+++ b/src/CBot/old TstCBot/BotConsoleDlg.h
@@ -0,0 +1,65 @@
+#if !defined(AFX_BOTCONSOLEDLG_H__A11450A2_8E09_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_BOTCONSOLEDLG_H__A11450A2_8E09_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// BotConsoleDlg.h : header file
+//
+
+struct ThreadInfo
+{
+ CEdit* m_pEdit1 ;
+ CBotProgram* m_pProg;
+ CWnd* m_pWndMessage;
+ BOOL m_bStop;
+ BOOL m_bRun;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotConsoleDlg dialog
+
+class CBotConsoleDlg : public CDialog
+{
+// Construction
+public:
+ CBotConsoleDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CBotConsoleDlg)
+ enum { IDD = IDD_CONSOLE };
+ CButton m_cOK;
+ CEdit m_Edit2;
+ CEdit m_Edit1;
+ //}}AFX_DATA
+
+ CBotProgram* m_pProg;
+ ThreadInfo m_threadinfo;
+
+ int m_code, m_start, m_end;
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBotConsoleDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CBotConsoleDlg)
+ virtual void OnOK();
+ virtual void OnCancel();
+ virtual BOOL OnInitDialog();
+ afx_msg LONG EndProg(UINT wparam, LONG lparam) ;
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_BOTCONSOLEDLG_H__A11450A2_8E09_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/old TstCBot/BotErrorDlg.cpp b/src/CBot/old TstCBot/BotErrorDlg.cpp
new file mode 100644
index 0000000..87d56f0
--- /dev/null
+++ b/src/CBot/old TstCBot/BotErrorDlg.cpp
@@ -0,0 +1,56 @@
+// BotErrorDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+#include "BotErrorDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotErrorDlg dialog
+
+
+CBotErrorDlg::CBotErrorDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CBotErrorDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CBotErrorDlg)
+ m_TextProgram = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CBotErrorDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBotErrorDlg)
+ DDX_Control(pDX, IDC_EDIT1, m_eProgram);
+ DDX_Control(pDX, IDC_STATIC1, m_sMessage);
+ DDX_Text(pDX, IDC_EDIT1, m_TextProgram);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CBotErrorDlg, CDialog)
+ //{{AFX_MSG_MAP(CBotErrorDlg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotErrorDlg message handlers
+
+BOOL CBotErrorDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_sMessage.SetWindowText(m_TextError);
+ m_eProgram.SetFocus();
+ m_eProgram.SetSel(m_start, m_end);
+
+ return FALSE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/src/CBot/old TstCBot/BotErrorDlg.h b/src/CBot/old TstCBot/BotErrorDlg.h
new file mode 100644
index 0000000..522afad
--- /dev/null
+++ b/src/CBot/old TstCBot/BotErrorDlg.h
@@ -0,0 +1,51 @@
+#if !defined(AFX_BOTERRORDLG_H__80E73D20_7454_11D4_A439_00D059085115__INCLUDED_)
+#define AFX_BOTERRORDLG_H__80E73D20_7454_11D4_A439_00D059085115__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// BotErrorDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CBotErrorDlg dialog
+
+class CBotErrorDlg : public CDialog
+{
+// Construction
+public:
+ CBotErrorDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CBotErrorDlg)
+ enum { IDD = IDD_DIALOG1 };
+ CEdit m_eProgram;
+ CStatic m_sMessage;
+ CString m_TextProgram;
+ //}}AFX_DATA
+
+
+ CString m_TextError;
+ int m_start, m_end;
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBotErrorDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CBotErrorDlg)
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_BOTERRORDLG_H__80E73D20_7454_11D4_A439_00D059085115__INCLUDED_)
diff --git a/src/CBot/old TstCBot/CBotTest.txt b/src/CBot/old TstCBot/CBotTest.txt
new file mode 100644
index 0000000..ce20e26
--- /dev/null
+++ b/src/CBot/old TstCBot/CBotTest.txt
@@ -0,0 +1,36 @@
+
+extern void TheTest()
+{
+ for (int x = 130; x>0; x--) print (x);
+}
+
+extern void Test()
+{
+ int var = 10000 ;
+ while (var > 0) var = var -1;
+}
+// exécuté en 30 secondes
+
+extern void Autre()
+{
+ int var = 10000 ;
+ while (var > 0) if ( var > 0 ) var = var -1;
+}
+// exécuté en 45 secondes
+
+int Y ( int n )
+{
+ if ( n < 2 ) return n;
+ int a = Y(n-1) + Y(n-2);
+ return a;
+}
+
+extern int X ( int n )
+{
+ if ( n < 2 ) { print(n); return n; }
+ int a = X(n-1) + Y(n-2);
+ print (a);
+ return a;
+}
+
+
diff --git a/src/CBot/old TstCBot/CMyThread.cpp b/src/CBot/old TstCBot/CMyThread.cpp
new file mode 100644
index 0000000..ca92c77
--- /dev/null
+++ b/src/CBot/old TstCBot/CMyThread.cpp
@@ -0,0 +1,107 @@
+// CMyThread.cpp : pour créer un processus pour la console
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+#include "CMyThread.h"
+#include "BotConsoleDlg.h"
+
+
+//IMPLEMENT_DYNAMIC (CMyThread, CWinThread)
+IMPLEMENT_DYNCREATE (CMyThread, CWinThread)
+
+/////////////////////////////////////////////////////////////////////////////
+// CMyThread
+
+BEGIN_MESSAGE_MAP(CMyThread, CWinThread)
+ //{{AFX_MSG_MAP(CMyThread)
+ //}}AFX_MSG_MAP
+ // Standard file based document commands
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CMyThread construction
+
+CMyThread::CMyThread()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CMyThread initialization
+/*
+BOOL CMyThread::InitInstance()
+{
+ AfxEnableControlContainer();
+
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+
+ // ouvre une fenêtre pour afficher les sorties
+ CRect rect;
+ AfxGetMainWnd()->GetClientRect( rect );
+ rect += CPoint(30,30);
+
+ CWnd* pWnd = new CWnd();
+ pWnd->CreateEx( 0,
+ AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
+ "CBot console", WS_POPUPWINDOW|WS_CAPTION|WS_VISIBLE,
+ rect,
+ AfxGetMainWnd()->GetParent(), NULL, NULL);
+ m_pMainWnd = pWnd;
+
+ pApp->m_pEdit2 = new CEdit();
+
+ m_pMainWnd->GetClientRect( rect );
+ rect.bottom -= 40;
+ pApp->m_pEdit2->Create( WS_VISIBLE|WS_BORDER|WS_TABSTOP|ES_MULTILINE|ES_WANTRETURN|
+ ES_AUTOVSCROLL|ES_READONLY,
+ rect, m_pMainWnd, IDC_EDIT2 );
+
+ pApp->m_pEdit2->ReplaceSel("Les fonctions suivantes sont disponibles:\n\r");
+ for ( int i = 0; i < pApp->m_Liste.RetSize(); i++ )
+ {
+ pApp->m_pEdit2->ReplaceSel(pApp->m_Liste[i] + "\r\n");
+ }
+ pApp->m_pEdit2->ReplaceSel("Entrez une commande ci-dessous.\r\r");
+
+
+// pApp->m_pEdit2->SetFocus();
+
+ pApp->m_pEdit3 = new CEdit();
+ m_pMainWnd->GetClientRect( rect );
+ rect.top = rect.bottom-40;
+ pApp->m_pEdit3->Create( WS_VISIBLE|WS_BORDER|WS_TABSTOP,
+ rect, m_pMainWnd, IDC_EDIT1 );
+ pApp->m_pEdit3->SetFocus();
+
+ return TRUE;
+}*/
+
+BOOL CMyThread::InitInstance()
+{
+ CBotConsoleDlg dlg;
+ m_pMainWnd = &dlg; // cela ferme l'application avec la DBOX !
+
+ int nResponse = dlg.DoModal();
+
+ return TRUE;
+}
+
+
+int CMyThread::ExitInstance()
+{
+ return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CMyThread message handlers
+
+
+void CMyThread::OnReturn()
+{
+ // TODO: Add your command handler code here
+ __asm int 3;
+}
diff --git a/src/CBot/old TstCBot/CMyThread.h b/src/CBot/old TstCBot/CMyThread.h
new file mode 100644
index 0000000..1134077
--- /dev/null
+++ b/src/CBot/old TstCBot/CMyThread.h
@@ -0,0 +1,44 @@
+// CMyThread.h : pour créer un processus pour la console
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINFRM_H__20B3756C_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+#define AFX_MAINFRM_H__20B3756C_5DFD_11D4_A15E_00E0189013DF__INCLUDED_
+
+
+#include "stdafx.h"
+#include "TstCBot.h"
+
+class CMyThread : public CWinThread
+{
+// DECLARE_DYNAMIC(CMyThread)
+ DECLARE_DYNCREATE(CMyThread)
+
+public:
+
+
+// Constructor
+ CMyThread();
+ virtual BOOL InitInstance();
+ virtual int ExitInstance(); // return app exit code
+
+// Implementation
+
+ //{{AFX_MSG(CTstCBotApp)
+ afx_msg void OnAppAbout();
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CMainFrame)
+ afx_msg void OnReturn();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINFRM_H__20B3756C_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
diff --git a/src/CBot/old TstCBot/MainFrm.cpp b/src/CBot/old TstCBot/MainFrm.cpp
new file mode 100644
index 0000000..6c0962c
--- /dev/null
+++ b/src/CBot/old TstCBot/MainFrm.cpp
@@ -0,0 +1,91 @@
+// MainFrm.cpp : implementation of the CMainFrame class
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+
+#include "MainFrm.h"
+#include "BotErrorDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame
+
+IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
+
+BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
+ //{{AFX_MSG_MAP(CMainFrame)
+ ON_WM_CREATE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+static UINT indicators[] =
+{
+ ID_SEPARATOR, // status line indicator
+ ID_INDICATOR_CAPS,
+ ID_INDICATOR_NUM,
+ ID_INDICATOR_SCRL,
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame construction/destruction
+
+CMainFrame::CMainFrame()
+{
+ // TODO: add member initialization code here
+
+}
+
+CMainFrame::~CMainFrame()
+{
+}
+
+int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ if (!m_wndStatusBar.Create(this) ||
+ !m_wndStatusBar.SetIndicators(indicators,
+ sizeof(indicators)/sizeof(UINT)))
+ {
+ TRACE0("Failed to create status bar\n");
+ return -1; // fail to create
+ }
+
+ return 0;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+ // TODO: Modify the Window class or styles here by modifying
+ // the CREATESTRUCT cs
+
+ return CFrameWnd::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame diagnostics
+
+#ifdef _DEBUG
+void CMainFrame::AssertValid() const
+{
+ CFrameWnd::AssertValid();
+}
+
+void CMainFrame::Dump(CDumpContext& dc) const
+{
+ CFrameWnd::Dump(dc);
+}
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame message handlers
+
+
diff --git a/src/CBot/old TstCBot/MainFrm.h b/src/CBot/old TstCBot/MainFrm.h
new file mode 100644
index 0000000..56b9c41
--- /dev/null
+++ b/src/CBot/old TstCBot/MainFrm.h
@@ -0,0 +1,55 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINFRM_H__70B3756C_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+#define AFX_MAINFRM_H__70B3756C_5DFD_11D4_A15E_00E0189013DF__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CMainFrame : public CFrameWnd
+{
+protected: // create from serialization only
+ CMainFrame();
+ DECLARE_DYNCREATE(CMainFrame)
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CMainFrame)
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CMainFrame();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected: // control bar embedded members
+ CStatusBar m_wndStatusBar;
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CMainFrame)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnCp1();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINFRM_H__70B3756C_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
diff --git a/src/CBot/old TstCBot/ReadMe.txt b/src/CBot/old TstCBot/ReadMe.txt
new file mode 100644
index 0000000..67dc05b
--- /dev/null
+++ b/src/CBot/old TstCBot/ReadMe.txt
@@ -0,0 +1,93 @@
+========================================================================
+ MICROSOFT FOUNDATION CLASS LIBRARY : TstCBot
+========================================================================
+
+
+AppWizard has created this TstCBot application for you. This application
+not only demonstrates the basics of using the Microsoft Foundation classes
+but is also a starting point for writing your application.
+
+This file contains a summary of what you will find in each of the files that
+make up your TstCBot application.
+
+TstCBot.h
+ This is the main header file for the application. It includes other
+ project specific headers (including Resource.h) and declares the
+ CTstCBotApp application class.
+
+TstCBot.cpp
+ This is the main application source file that contains the application
+ class CTstCBotApp.
+
+TstCBot.rc
+ This is a listing of all of the Microsoft Windows resources that the
+ program uses. It includes the icons, bitmaps, and cursors that are stored
+ in the RES subdirectory. This file can be directly edited in Microsoft
+ Developer Studio.
+
+res\TstCBot.ico
+ This is an icon file, which is used as the application's icon. This
+ icon is included by the main resource file TstCBot.rc.
+
+res\TstCBot.rc2
+ This file contains resources that are not edited by Microsoft
+ Developer Studio. You should place all resources not
+ editable by the resource editor in this file.
+
+TstCBot.clw
+ This file contains information used by ClassWizard to edit existing
+ classes or add new classes. ClassWizard also uses this file to store
+ information needed to create and edit message maps and dialog data
+ maps and to create prototype member functions.
+
+/////////////////////////////////////////////////////////////////////////////
+
+For the main frame window:
+
+MainFrm.h, MainFrm.cpp
+ These files contain the frame class CMainFrame, which is derived from
+ CFrameWnd and controls all SDI frame features.
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+AppWizard creates one document type and one view:
+
+TstCBotDoc.h, TstCBotDoc.cpp - the document
+ These files contain your CTstCBotDoc class. Edit these files to
+ add your special document data and to implement file saving and loading
+ (via CTstCBotDoc::Serialize).
+
+TstCBotView.h, TstCBotView.cpp - the view of the document
+ These files contain your CTstCBotView class.
+ CTstCBotView objects are used to view CTstCBotDoc objects.
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named TstCBot.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+ This is the standard header file, which defines new resource IDs.
+ Microsoft Developer Studio reads and updates this file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" to indicate parts of the source code you
+should add to or customize.
+
+If your application uses MFC in a shared DLL, and your application is
+in a language other than the operating system's current language, you
+will need to copy the corresponding localized resources MFC40XXX.DLL
+from the Microsoft Visual C++ CD-ROM onto the system or system32 directory,
+and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation.
+For example, MFC40DEU.DLL contains resources translated to German.) If you
+don't do this, some of the UI elements of your application will remain in the
+language of the operating system.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/CBot/old TstCBot/Resource.h b/src/CBot/old TstCBot/Resource.h
new file mode 100644
index 0000000..6863fd8
--- /dev/null
+++ b/src/CBot/old TstCBot/Resource.h
@@ -0,0 +1,68 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by TstCBot.rc
+//
+#define IDD_ABOUTBOX 100
+#define IDR_MAINFRAME 128
+#define IDR_TSTCBOTYPE 129
+#define IDD_DIALOG1 130
+#define IDD_CONSOLE 131
+#define IDC_EDIT1 1000
+#define TX_TYPENAMES 1000
+#define IDC_STATIC1 1001
+#define IDC_EDIT2 1002
+#define TX_OPENPAR 5000
+#define TX_CLOSEPAR 5001
+#define TX_NOTBOOL 5002
+#define TX_UNDEFVAR 5003
+#define TX_BADLEFT 5004
+#define TX_ENDOF 5005
+#define TX_OUTCASE 5006
+#define TX_NOTERM 5007
+#define TX_CLOSEBLK 5008
+#define TX_ELSEWITHOUTIF 5009
+#define TX_OPENBLK 5010
+#define TX_BADTYPE 5011
+#define TX_REDEFVAR 5012
+#define TX_BAD2TYPE 5013
+#define TX_UNDEFCALL 5014
+#define TX_MISDOTS 5015
+#define TX_WHILE 5016
+#define TX_BREAK 5017
+#define TX_LABEL 5018
+#define TX_NOLABEL 5019
+#define TX_NOCASE 5020
+#define TX_BADNUM 5021
+#define TX_VOID 5022
+#define TX_NOTYP 5023
+#define TX_NOVAR 5024
+#define TX_NOFONC 5025
+#define TX_OVERPARAM 5026
+#define TX_REDEF 5027
+#define TX_LOWPARAM 5028
+#define TX_BADPARAM 5029
+#define TX_NUMPARAM 5030
+#define TX_NOITEM 5031
+#define TX_DOT 5032
+#define TX_NOCONST 5033
+#define TX_REDEFCLASS 5034
+#define TX_DIVZERO 6000
+#define TX_NOTINIT 6001
+#define TX_BADTHROW 6002
+#define TX_NORETVAL 6003
+#define TX_NORUN 6004
+#define TX_NOCALL 6005
+#define ID_CP1 32771
+#define ID_EXE 32772
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 132
+#define _APS_NEXT_COMMAND_VALUE 32775
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/CBot/old TstCBot/StdAfx.cpp b/src/CBot/old TstCBot/StdAfx.cpp
new file mode 100644
index 0000000..ae0ec93
--- /dev/null
+++ b/src/CBot/old TstCBot/StdAfx.cpp
@@ -0,0 +1,6 @@
+// stdafx.cpp : source file that includes just the standard includes
+// TstCBot.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/src/CBot/old TstCBot/StdAfx.h b/src/CBot/old TstCBot/StdAfx.h
new file mode 100644
index 0000000..7d46ace
--- /dev/null
+++ b/src/CBot/old TstCBot/StdAfx.h
@@ -0,0 +1,26 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__70B3756A_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+#define AFX_STDAFX_H__70B3756A_5DFD_11D4_A15E_00E0189013DF__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdisp.h> // MFC OLE automation classes
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__70B3756A_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
diff --git a/src/CBot/old TstCBot/TstCBot.clw b/src/CBot/old TstCBot/TstCBot.clw
new file mode 100644
index 0000000..4c54168
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBot.clw
@@ -0,0 +1,189 @@
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CTstCBotView
+LastTemplate=CDialog
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "TstCBot.h"
+LastPage=0
+
+ClassCount=7
+Class1=CTstCBotApp
+Class2=CTstCBotDoc
+Class3=CTstCBotView
+Class4=CMainFrame
+
+ResourceCount=6
+Resource1=IDD_ABOUTBOX
+Resource2=IDR_MAINFRAME
+Class5=CAboutDlg
+Resource3=IDD_ABOUTBOX (French (France))
+Resource4=IDD_CONSOLE
+Class6=CBotErrorDlg
+Resource5=IDD_DIALOG1 (French (Switzerland))
+Class7=CBotConsoleDlg
+Resource6=IDR_MAINFRAME (French (France))
+
+[CLS:CTstCBotApp]
+Type=0
+HeaderFile=TstCBot.h
+ImplementationFile=TstCBot.cpp
+Filter=N
+
+[CLS:CTstCBotDoc]
+Type=0
+HeaderFile=TstCBotDoc.h
+ImplementationFile=TstCBotDoc.cpp
+Filter=N
+BaseClass=CDocument
+VirtualFilter=DC
+LastObject=CTstCBotDoc
+
+[CLS:CTstCBotView]
+Type=0
+HeaderFile=TstCBotView.h
+ImplementationFile=TstCBotView.cpp
+Filter=C
+BaseClass=CView
+VirtualFilter=VWC
+LastObject=CTstCBotView
+
+[CLS:CMainFrame]
+Type=0
+HeaderFile=MainFrm.h
+ImplementationFile=MainFrm.cpp
+Filter=T
+BaseClass=CFrameWnd
+VirtualFilter=fWC
+LastObject=CMainFrame
+
+
+
+[CLS:CAboutDlg]
+Type=0
+HeaderFile=TstCBot.cpp
+ImplementationFile=TstCBot.cpp
+Filter=D
+
+[DLG:IDD_ABOUTBOX]
+Type=1
+Class=CAboutDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308480
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+
+[MNU:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_FILE_SAVE_AS
+Command5=ID_FILE_MRU_FILE1
+Command6=ID_APP_EXIT
+Command7=ID_EDIT_UNDO
+Command8=ID_EDIT_CUT
+Command9=ID_EDIT_COPY
+Command10=ID_EDIT_PASTE
+Command11=ID_VIEW_STATUS_BAR
+Command12=ID_CP1
+Command13=ID_EXE
+Command14=ID_APP_ABOUT
+CommandCount=14
+
+[ACL:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_CP1
+Command2=ID_FILE_NEW
+Command3=ID_FILE_OPEN
+Command4=ID_FILE_SAVE
+Command5=ID_EXE
+Command6=ID_EDIT_UNDO
+Command7=ID_EDIT_CUT
+Command8=ID_EXE
+Command9=ID_CP1
+Command10=ID_EXE
+CommandCount=10
+
+[MNU:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_FILE_SAVE_AS
+Command5=ID_FILE_MRU_FILE1
+Command6=ID_APP_EXIT
+Command7=ID_EDIT_UNDO
+Command8=ID_EDIT_CUT
+Command9=ID_EDIT_COPY
+Command10=ID_EDIT_PASTE
+Command11=ID_VIEW_STATUS_BAR
+Command12=ID_CP1
+Command13=ID_EXE
+Command14=ID_APP_ABOUT
+CommandCount=14
+
+[ACL:IDR_MAINFRAME (French (France))]
+Type=1
+Class=?
+Command1=ID_CP1
+Command2=ID_FILE_NEW
+Command3=ID_FILE_OPEN
+Command4=ID_FILE_SAVE
+Command5=ID_EXE
+Command6=ID_EDIT_UNDO
+Command7=ID_EDIT_CUT
+Command8=ID_EXE
+Command9=ID_CP1
+Command10=ID_EXE
+CommandCount=10
+
+[DLG:IDD_ABOUTBOX (French (France))]
+Type=1
+Class=CAboutDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342177283
+Control2=IDC_STATIC,static,1342308480
+Control3=IDC_STATIC,static,1342308352
+Control4=IDOK,button,1342373889
+
+[CLS:CBotErrorDlg]
+Type=0
+HeaderFile=BotErrorDlg.h
+ImplementationFile=BotErrorDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CBotErrorDlg
+
+[DLG:IDD_DIALOG1 (French (Switzerland))]
+Type=1
+ControlCount=4
+Control1=IDOK,button,1342242817
+Control2=IDC_EDIT1,edit,1352728708
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC1,static,1342308352
+
+[DLG:IDD_CONSOLE]
+Type=1
+Class=CBotConsoleDlg
+ControlCount=4
+Control1=IDC_STATIC,static,1342308352
+Control2=IDC_EDIT2,edit,1350631552
+Control3=IDOK,button,1342242817
+Control4=IDC_EDIT1,edit,1352734724
+
+[CLS:CBotConsoleDlg]
+Type=0
+HeaderFile=BotConsoleDlg.h
+ImplementationFile=BotConsoleDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDOK
+
diff --git a/src/CBot/old TstCBot/TstCBot.cpp b/src/CBot/old TstCBot/TstCBot.cpp
new file mode 100644
index 0000000..8ac4557
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBot.cpp
@@ -0,0 +1,412 @@
+// TstCBot.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+
+#include "MainFrm.h"
+#include "TstCBotDoc.h"
+#include "TstCBotView.h"
+#include "CMyThread.h"
+
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+////////////////////////////////////////////////////////////////////
+// routine show()
+// utilisable depuis le programme écrit en CBot
+
+// exécution
+BOOL rShow( CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ CString s;
+
+ if ( pVar == NULL )
+ {
+ Exception = 22; return FALSE;
+ }
+
+ while ( pVar != NULL )
+ {
+ CString ss;
+ ss.LoadString( TX_TYPENAMES + pVar->RetType() );
+ s += ss + " ";
+
+ ss = pVar->RetName();
+ if (ss.IsEmpty()) ss = "<sans nom>";
+ s += ss + " = ";
+
+ s += pVar->RetValString();
+ s += "\n";
+ pVar = pVar->RetNext();
+ }
+
+ AfxMessageBox(s, MB_OK|MB_ICONINFORMATION);
+
+// if ( pResult && pResult->RetType() == CBotTypInt) pResult->SetValInt(123);
+
+ return TRUE; // pas d'interruption
+}
+
+int cShow( CBotVar* &pVar, CBotString& RetClass)
+{
+ if ( pVar == NULL ) return 22;
+ return CBotTypInt; // tous paramètres acceptés, un entier en retour
+}
+
+int cErr( CBotVar* &pVar, CBotString& RetClass)
+{
+ pVar = pVar->RetNext(); // avance le pointeur sur l'erreur
+ return 6666;
+}
+
+////////////////////////////////////////////////////////////////////
+// routine print()
+// utilisable depuis le programme écrit en CBot
+
+// exécution
+BOOL rPrintLn( CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ CString s;
+
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+ CEdit* pEdit = pApp->m_pConsole;
+
+ if (pEdit == NULL) return TRUE;
+ pEdit->GetWindowText(s);
+
+ while ( pVar != NULL )
+ {
+ if ( !s.IsEmpty() ) s += "\r\n";
+ s += pVar->RetValString();
+ pVar = pVar->RetNext();
+ }
+
+ pEdit->SetWindowText(s);
+ pEdit->SetSel(s.GetLength(), s.GetLength());
+ pEdit->SetFocus();
+ return TRUE; // pas d'interruption
+}
+
+BOOL rPrint( CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ CString s;
+
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+ CEdit* pEdit = pApp->m_pConsole;
+
+ if (pEdit == NULL) return TRUE;
+ pEdit->GetWindowText(s);
+
+ while ( pVar != NULL )
+ {
+ if ( !s.IsEmpty() ) s += " ";
+ s += pVar->RetValString();
+ pVar = pVar->RetNext();
+ }
+
+ pEdit->SetWindowText(s);
+ pEdit->SetSel(s.GetLength(), s.GetLength());
+ pEdit->SetFocus();
+ return TRUE; // pas d'interruption
+}
+
+int cPrint( CBotVar* &pVar, CBotString& RetClass)
+{
+ return 0; // tous paramètres acceptés, un entier en retour
+}
+
+
+//////////////////////////////////////////////////////////////////
+// class CPoint pour essayer
+
+// exécution
+BOOL rCPoint( CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ CString s;
+
+ if ( pVar == NULL )return TRUE; // constructeur sans paramètres est ok
+
+ if ( pVar->RetType() > CBotTypDouble )
+ {
+ Exception = 6023; return FALSE;
+ }
+
+ CBotVar* pX = pThis->RetItem("x");
+ if ( pX == NULL )
+ {
+ Exception = 6024; return FALSE;
+ }
+
+ pX->SetValFloat( pVar->RetValFloat() );
+ pVar = pVar->RetNext();
+
+ if ( pVar == NULL )
+ {
+ Exception = 6022; return FALSE;
+ }
+
+ if ( pVar->RetType() > CBotTypDouble )
+ {
+ Exception = 6023; return FALSE;
+ }
+
+ CBotVar* pY = pThis->RetItem("y");
+ if ( pY == NULL )
+ {
+ Exception = 6024; return FALSE;
+ }
+
+ pY->SetValFloat( pVar->RetValFloat() );
+ pVar = pVar->RetNext();
+
+ if ( pVar != NULL )
+ {
+ Exception = 6025; return FALSE;
+ }
+
+ return TRUE; // pas d'interruption
+}
+
+int cCPoint( CBotVar* pThis, CBotVar* &pVar, CBotString& RetClass)
+{
+ // l'objet doit être de la classe CPoint
+ if ( !pThis->IsElemOfClass("CPoint") ) return 6021;
+
+ // ok si aucun paramètres !
+ if ( pVar == NULL ) return 0;
+
+ // paramètre de type numérique svp
+ if ( pVar->RetType() > CBotTypDouble ) return 6023;
+ pVar = pVar->RetNext();
+
+ // il doit y avoir un second paramètre
+ if ( pVar == NULL ) return 6022;
+ // également de type numérique
+ if ( pVar->RetType() > CBotTypDouble )return 6023;
+ pVar = pVar->RetNext();
+
+ // et pas plus de 2 paramètres svp
+ if ( pVar != NULL ) return 6025;
+
+ return 0; // cette fonction retourne void
+}
+
+// méthode déterminant l'opposé
+BOOL rOppose( CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception )
+{
+ CString s;
+
+ if ( pVar != NULL ) // pas de paramètre
+ {
+ Exception = 6025; return FALSE;
+ }
+
+ CBotVar* pvar = pThis->RetItemList(); // demande la chaîne des items
+
+ // tous les paramètres sont des nombres
+ while (pvar != NULL)
+ {
+ pvar->SetValFloat( -pvar->RetValFloat() );
+ pvar = pvar->RetNext();
+ }
+
+ pResult->Copy(pThis);
+ return TRUE; // pas d'interruption
+}
+
+int cOppose( CBotVar* pThis, CBotVar* &pVar, CBotString& RetClass)
+{
+ // l'objet doit être de la classe CPoint
+ if ( !pThis->IsElemOfClass("CPoint") ) return 6021;
+
+ RetClass = "CPoint"; // l'objet rendu est de cette class
+
+ // ok si aucun paramètres !
+ if ( pVar == NULL ) return CBotTypClass; // le paramètre retourné est une instance de la classe
+
+ return TX_OVERPARAM; // ça va pas
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotApp
+
+BEGIN_MESSAGE_MAP(CTstCBotApp, CWinApp)
+ //{{AFX_MSG_MAP(CTstCBotApp)
+ ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG_MAP
+ // Standard file based document commands
+ ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
+ ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotApp construction
+
+CTstCBotApp::CTstCBotApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CTstCBotApp object
+
+CTstCBotApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotApp initialization
+
+BOOL CTstCBotApp::InitInstance()
+{
+ AfxEnableControlContainer();
+
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+ // Change the registry key under which our settings are stored.
+ // You should modify this string to be something appropriate
+ // such as the name of your company or organization.
+ SetRegistryKey(_T("Local AppWizard-Generated Applications"));
+
+ LoadStdProfileSettings(); // Load standard INI file options (including MRU)
+
+ // Register the application's document templates. Document templates
+ // serve as the connection between documents, frame windows and views.
+
+ CSingleDocTemplate* pDocTemplate;
+ pDocTemplate = new CSingleDocTemplate(
+ IDR_MAINFRAME,
+ RUNTIME_CLASS(CTstCBotDoc),
+ RUNTIME_CLASS(CMainFrame), // main SDI frame window
+ RUNTIME_CLASS(CTstCBotView));
+ AddDocTemplate(pDocTemplate);
+
+ // Parse command line for standard shell commands, DDE, file open
+ CCommandLineInfo cmdInfo;
+ ParseCommandLine(cmdInfo);
+
+ // Dispatch commands specified on the command line
+ if (!ProcessShellCommand(cmdInfo))
+ return FALSE;
+
+ // The one and only window has been initialized, so show and update it.
+ m_pMainWnd->ShowWindow(SW_SHOW);
+ m_pMainWnd->UpdateWindow();
+
+
+
+///////////////////////////////////
+// défini la fonction "show()"
+// --------------------------------
+
+ CBotProgram::AddFunction("show", rShow, cShow);
+ CBotProgram::AddFunction("err", rShow, cErr);
+ CBotProgram::AddFunction("print", rPrint, cPrint);
+ CBotProgram::AddFunction("println", rPrintLn, cPrint);
+
+
+///////////////////////////////////
+// définie la classe globale CPoint
+// --------------------------------
+
+ CBotClass* m_pClassPoint;
+
+ m_pClassPoint = new CBotClass("CPoint", NULL);
+ // ajoute le composant ".x"
+ m_pClassPoint->AddItem("x", CBotTypFloat);
+ // ajoute le composant ".y"
+ m_pClassPoint->AddItem("y", CBotTypFloat);
+
+ // ajoute le constructeur pour cette classe
+ m_pClassPoint->AddFunction("CPoint", rCPoint, cCPoint);
+ // ajoute la méthode Opposé
+ m_pClassPoint->AddFunction("Opposé", rOppose, cOppose);
+
+
+//////////////////////////////////////////////////////////////////
+// compile un bout de programme pour voir s'il est bien accessible
+// depuis un autre "module"
+
+ CBotProgram* p = new CBotProgram;
+ CBotStringArray Liste;
+ p->Compile(" public void MonProgram( ) { show (\"mon programme\") ;}", Liste );
+
+ // l'objet n'est pas détruit et plus référencé
+ // je sais c'est pas bien
+
+
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDlg dialog used for App About
+
+class CAboutDlg : public CDialog
+{
+public:
+ CAboutDlg();
+
+// Dialog Data
+ //{{AFX_DATA(CAboutDlg)
+ enum { IDD = IDD_ABOUTBOX };
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CAboutDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ //{{AFX_MSG(CAboutDlg)
+ // No message handlers
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+ //{{AFX_DATA_INIT(CAboutDlg)
+ //}}AFX_DATA_INIT
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CAboutDlg)
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+ //{{AFX_MSG_MAP(CAboutDlg)
+ // No message handlers
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+// App command to run the dialog
+void CTstCBotApp::OnAppAbout()
+{
+ CAboutDlg aboutDlg;
+ aboutDlg.DoModal();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotApp commands
diff --git a/src/CBot/old TstCBot/TstCBot.dsp b/src/CBot/old TstCBot/TstCBot.dsp
new file mode 100644
index 0000000..35e5c0b
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBot.dsp
@@ -0,0 +1,180 @@
+# Microsoft Developer Studio Project File - Name="TstCBot" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=TstCBot - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "TstCBot.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "TstCBot.mak" CFG="TstCBot - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "TstCBot - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "TstCBot - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "TstCBot - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /FR /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x40c /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x40c /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "TstCBot - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /FR /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x40c /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x40c /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "TstCBot - Win32 Release"
+# Name "TstCBot - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\BotConsoleDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBot.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBot.rc
+
+!IF "$(CFG)" == "TstCBot - Win32 Release"
+
+!ELSEIF "$(CFG)" == "TstCBot - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBotDoc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBotView.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\BotConsoleDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBot.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBotDoc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TstCBotView.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\TstCBot.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\TstCBot.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\TstCBotDoc.ico
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/src/CBot/old TstCBot/TstCBot.h b/src/CBot/old TstCBot/TstCBot.h
new file mode 100644
index 0000000..616db43
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBot.h
@@ -0,0 +1,62 @@
+// TstCBot.h : main header file for the TSTCBOT application
+//
+
+#if !defined(AFX_TSTCBOT_H__70B37568_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+#define AFX_TSTCBOT_H__70B37568_5DFD_11D4_A15E_00E0189013DF__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+#include "..\CBotDll.h"
+
+
+class CMyThread;
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotApp:
+// See TstCBot.cpp for the implementation of this class
+//
+
+class CTstCBotApp : public CWinApp
+{
+public:
+ CTstCBotApp();
+
+ CMyThread* m_pThread;
+ CWnd* m_pView;
+ CEdit* m_pConsole;
+ CBotStringArray m_Liste;
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTstCBotApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CTstCBotApp)
+ afx_msg void OnAppAbout();
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TSTCBOT_H__70B37568_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+
+#define WM_STARTPROG WM_APP + 0
+#define WM_ENDPROG WM_APP + 1
diff --git a/src/CBot/old TstCBot/TstCBot.rc b/src/CBot/old TstCBot/TstCBot.rc
new file mode 100644
index 0000000..9e91c76
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBot.rc
@@ -0,0 +1,471 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 12, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\TstCBot.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""l.fra\\afxres.rc"" // Standard components\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\TstCBot.ico"
+IDR_TSTCBOTYPE ICON DISCARDABLE "res\\TstCBotDoc.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MAINFRAME MENU PRELOAD DISCARDABLE
+BEGIN
+ POPUP "&Fichier"
+ BEGIN
+ MENUITEM "&Nouveau\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Ouvrir...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM "&Enregistrer\tCtrl+S", ID_FILE_SAVE
+ MENUITEM "En&registrer sous...", ID_FILE_SAVE_AS
+ MENUITEM SEPARATOR
+ MENUITEM "Fichier récent", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Quitter", ID_APP_EXIT
+ END
+ POPUP "&Edition"
+ BEGIN
+ MENUITEM "&Annuler\tCtrl+Z", ID_EDIT_UNDO
+ MENUITEM SEPARATOR
+ MENUITEM "&Couper\tCtrl+X", ID_EDIT_CUT
+ MENUITEM "&Copier\tCtrl+C", ID_EDIT_COPY
+ MENUITEM "C&oller\tCtrl+V", ID_EDIT_PASTE
+ END
+ POPUP "&Affichage"
+ BEGIN
+ MENUITEM "Barre d'é&tat", ID_VIEW_STATUS_BAR
+ END
+ POPUP "&Tests"
+ BEGIN
+ MENUITEM "&Compile\tAlt+C", ID_CP1
+ MENUITEM "&Execute\tAlt+V", ID_EXE
+ END
+ POPUP "&?"
+ BEGIN
+ MENUITEM "&A propos de TstCBot...", ID_APP_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
+BEGIN
+ "C", ID_CP1, VIRTKEY, ALT, NOINVERT
+ "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
+ "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ "V", ID_EXE, VIRTKEY, ALT, NOINVERT
+ VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
+ VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
+ VK_F5, ID_EXE, VIRTKEY, NOINVERT
+ VK_F7, ID_CP1, VIRTKEY, NOINVERT
+ "X", ID_EXE, VIRTKEY, ALT, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 217, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "A propos de TstCBot"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
+ LTEXT "TstCBot version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX
+ LTEXT "Copyright (C) 1900",IDC_STATIC,40,25,119,8
+ DEFPUSHBUTTON "OK",IDOK,178,7,32,14,WS_GROUP
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040C04B0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "Application MFC TstCBot\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "TstCBot\0"
+ VALUE "LegalCopyright", "Copyright (C) 1900\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "TstCBot.EXE\0"
+ VALUE "ProductName", "Application TstCBot\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Traduction", 0x40c, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 210
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 48
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ IDR_MAINFRAME "TstCBot\n\nTstCBo\n\n\nTstCBot.Document\nTstCBo Document"
+END
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ AFX_IDS_APP_TITLE "TstCBot"
+ AFX_IDS_IDLEMESSAGE "Prêt"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_INDICATOR_EXT "EXT"
+ ID_INDICATOR_CAPS "MAJ"
+ ID_INDICATOR_NUM "NUM"
+ ID_INDICATOR_SCRL "DEF"
+ ID_INDICATOR_OVR "ECR"
+ ID_INDICATOR_REC "ENR"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_NEW "Crée un nouveau document\nNouveau"
+ ID_FILE_OPEN "Ouvre un document existant\nOuvrir"
+ ID_FILE_CLOSE "Ferme le document actif\nFermer"
+ ID_FILE_SAVE "Enregistre le document actif\nEnregistrer"
+ ID_FILE_SAVE_AS "Enregistre le document actif sous un nouveau nom\nEnregistrer sous"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_APP_ABOUT "Affiche des informations sur le programme, le numéro de version et le copyright\nA propos de"
+ ID_APP_EXIT "Ferme l'application ; propose d'enregistrer les documents\nQuitter"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_MRU_FILE1 "Ouvre ce document"
+ ID_FILE_MRU_FILE2 "Ouvre ce document"
+ ID_FILE_MRU_FILE3 "Ouvre ce document"
+ ID_FILE_MRU_FILE4 "Ouvre ce document"
+ ID_FILE_MRU_FILE5 "Ouvre ce document"
+ ID_FILE_MRU_FILE6 "Ouvre ce document"
+ ID_FILE_MRU_FILE7 "Ouvre ce document"
+ ID_FILE_MRU_FILE8 "Ouvre ce document"
+ ID_FILE_MRU_FILE9 "Ouvre ce document"
+ ID_FILE_MRU_FILE10 "Ouvre ce document"
+ ID_FILE_MRU_FILE11 "Ouvre ce document"
+ ID_FILE_MRU_FILE12 "Ouvre ce document"
+ ID_FILE_MRU_FILE13 "Ouvre ce document"
+ ID_FILE_MRU_FILE14 "Ouvre ce document"
+ ID_FILE_MRU_FILE15 "Ouvre ce document"
+ ID_FILE_MRU_FILE16 "Ouvre ce document"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_NEXT_PANE "Passe au volet de fenêtre suivant\nVolet suivant"
+ ID_PREV_PANE "Revient au volet précédent\nVolet précédent"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_WINDOW_SPLIT "Fractionne la fenêtre active en deux volets\nFractionner"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_EDIT_CLEAR "Efface la sélection\nEffacer"
+ ID_EDIT_CLEAR_ALL "Efface tout\nEffacer tout"
+ ID_EDIT_COPY "Copie la sélection et la place dans le Presse-papiers\nCopier"
+ ID_EDIT_CUT "Supprime la sélection et la place dans le Presse-papiers\nCopier"
+ ID_EDIT_FIND "Recherche le texte spécifié\nRechercher"
+ ID_EDIT_PASTE "Insère le contenu du Presse-papiers\nColler"
+ ID_EDIT_REPEAT "Répète la dernière action\nRépéter"
+ ID_EDIT_REPLACE "Remplace le texte spécifique par un texte différent\nRemplacer"
+ ID_EDIT_SELECT_ALL "Sélectionne le document entier\nSélectionner tout"
+ ID_EDIT_UNDO "Annule la dernière action\nAnnuler"
+ ID_EDIT_REDO "Rétablit l'action précédemment annulée\nRétablir"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_STATUS_BAR "Affiche ou masque la barre d'état\nBarre d'état"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_SCSIZE "Change la taille de la fenêtre"
+ AFX_IDS_SCMOVE "Change la position de la fenêtre"
+ AFX_IDS_SCMINIMIZE "Réduit la fenêtre en icône"
+ AFX_IDS_SCMAXIMIZE "Agrandit la fenêtre au format de l'écran"
+ AFX_IDS_SCNEXTWINDOW "Passe à la fenêtre de document suivante"
+ AFX_IDS_SCPREVWINDOW "Passe à la fenêtre de document précédente"
+ AFX_IDS_SCCLOSE "Ferme la fenêtre active et propose l'enregistrement des documents"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_SCRESTORE "Restaure la fenêtre à sa taille d'origine"
+ AFX_IDS_SCTASKLIST "Active la liste des tâches"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_TYPENAMES "les différents types"
+ 1001 "Byte"
+ 1002 "Short"
+ 1003 "Char"
+ 1004 "Int"
+ 1005 "Long"
+ 1006 "Real"
+ 1007 "Double"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ 1008 "Boolean"
+ 1009 "Class"
+ 1010 "String"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OPENPAR "Il manque une parenthèse ouvrante."
+ TX_CLOSEPAR "Il manque une parenthèse fermante."
+ TX_NOTBOOL "L'expression doit être un boolean."
+ TX_UNDEFVAR "Variable non déclarée."
+ TX_BADLEFT "Assignation impossible."
+ TX_ENDOF "Instruction non terminée."
+ TX_OUTCASE "Instruction ""case"" hors d'un bloc ""switch""."
+ TX_NOTERM "Instructions après la fin."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_CLOSEBLK "Il manque la fin du bloc."
+ TX_ELSEWITHOUTIF "Instruction ""else"" sans ""if"" correspondant."
+ TX_OPENBLK "Début d'un bloc attendu."
+ TX_BADTYPE "Mauvais type de résultat pour l'assignation."
+ TX_REDEFVAR "Redéfinition d'une variable."
+ TX_BAD2TYPE "Les deux opérandes ne sont pas de types compatibles."
+ TX_UNDEFCALL "Routine inconnue."
+ TX_MISDOTS "Séparateur "" : "" attendu."
+ TX_WHILE "Manque le mot ""while""."
+ TX_BREAK "Instruction ""break"" en dehors d'une boucle."
+ TX_LABEL "Un label ne peut se placer que devant un ""for"", un ""while"", un ""do"" ou un ""switch""."
+ TX_NOLABEL "Cette étiquette n'existe pas"
+ TX_NOCASE "Manque une instruction ""case""."
+ TX_BADNUM "Un nombre est attendu."
+ TX_VOID "Paramètre void."
+ TX_NOTYP "Déclaration de type attendu"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_DIVZERO "Division par zéro."
+ TX_NOTINIT "Variable non initialisée."
+ TX_BADTHROW "Valeur négative refusée pour ""throw""."
+ TX_NORETVAL "La fonction n'a pas retourné de résultat"
+ TX_NORUN "Pas de fonction en exécution"
+ TX_NOCALL "Appel d'une fonction inexistante"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_NOVAR "Nom d'une variable attendu"
+ TX_NOFONC "Nom de la fonction attendu."
+ TX_OVERPARAM "Trop de paramètres"
+ TX_REDEF "Cette fonction existe déjà."
+ TX_LOWPARAM "Pas assez de paramètres"
+ TX_BADPARAM "Aucune fonction de ce nom n'accepte ce(s) type(s) de paramètre(s)"
+ TX_NUMPARAM "Aucune fonction de ce nom n'accepte ce nombre de paramètres"
+ TX_NOITEM "Cet élément n'exite pas dans cette classe."
+ TX_DOT "L'objet n'est pas une instance d'une classe."
+ TX_NOCONST "Il n'y a pas de constructeur approprié."
+ TX_REDEFCLASS "Cette classe existe déjà."
+END
+
+#endif // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// French (Switzerland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRS)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_SWISS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_CONSOLE DIALOG DISCARDABLE 0, 0, 401, 210
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "CBot Console"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Commande :",IDC_STATIC,7,177,40,8
+ EDITTEXT IDC_EDIT2,7,189,329,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "Exécute",IDOK,344,189,50,14
+ EDITTEXT IDC_EDIT1,7,7,387,167,ES_MULTILINE | ES_READONLY |
+ ES_WANTRETURN | WS_VSCROLL
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_CONSOLE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 394
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 203
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // French (Switzerland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE 12, 1
+#pragma code_page(1252)
+#endif
+#include "res\TstCBot.rc2" // non-Microsoft Visual C++ edited resources
+#include "l.fra\afxres.rc" // Standard components
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/CBot/old TstCBot/TstCBotDoc.cpp b/src/CBot/old TstCBot/TstCBotDoc.cpp
new file mode 100644
index 0000000..7d7e2ef
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBotDoc.cpp
@@ -0,0 +1,83 @@
+// TstCBotDoc.cpp : implementation of the CTstCBotDoc class
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+
+#include "TstCBotDoc.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotDoc
+
+IMPLEMENT_DYNCREATE(CTstCBotDoc, CDocument)
+
+BEGIN_MESSAGE_MAP(CTstCBotDoc, CDocument)
+ //{{AFX_MSG_MAP(CTstCBotDoc)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotDoc construction/destruction
+
+CTstCBotDoc::CTstCBotDoc()
+{
+ // TODO: add one-time construction code here
+
+}
+
+CTstCBotDoc::~CTstCBotDoc()
+{
+}
+
+BOOL CTstCBotDoc::OnNewDocument()
+{
+ if (!CDocument::OnNewDocument())
+ return FALSE;
+
+ // TODO: add reinitialization code here
+ // (SDI documents will reuse this document)
+
+ return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotDoc serialization
+
+void CTstCBotDoc::Serialize(CArchive& ar)
+{
+ if (ar.IsStoring())
+ {
+ // TODO: add storing code here
+ }
+ else
+ {
+ // TODO: add loading code here
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotDoc diagnostics
+
+#ifdef _DEBUG
+void CTstCBotDoc::AssertValid() const
+{
+ CDocument::AssertValid();
+}
+
+void CTstCBotDoc::Dump(CDumpContext& dc) const
+{
+ CDocument::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotDoc commands
+
diff --git a/src/CBot/old TstCBot/TstCBotDoc.h b/src/CBot/old TstCBot/TstCBotDoc.h
new file mode 100644
index 0000000..ae1d0f7
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBotDoc.h
@@ -0,0 +1,55 @@
+// TstCBotDoc.h : interface of the CTstCBotDoc class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_TSTCBOTDOC_H__70B3756E_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+#define AFX_TSTCBOTDOC_H__70B3756E_5DFD_11D4_A15E_00E0189013DF__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+class CTstCBotDoc : public CDocument
+{
+protected: // create from serialization only
+ CTstCBotDoc();
+ DECLARE_DYNCREATE(CTstCBotDoc)
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTstCBotDoc)
+ public:
+ virtual BOOL OnNewDocument();
+ virtual void Serialize(CArchive& ar);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CTstCBotDoc();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CTstCBotDoc)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TSTCBOTDOC_H__70B3756E_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
diff --git a/src/CBot/old TstCBot/TstCBotView.cpp b/src/CBot/old TstCBot/TstCBotView.cpp
new file mode 100644
index 0000000..3ee9094
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBotView.cpp
@@ -0,0 +1,291 @@
+// TstCBotView.cpp : implementation of the CTstCBotView class
+//
+
+#include "stdafx.h"
+#include "TstCBot.h"
+
+#include "TstCBotDoc.h"
+#include "TstCBotView.h"
+#include "BotConsoleDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotView
+
+IMPLEMENT_DYNCREATE(CTstCBotView, CView)
+
+BEGIN_MESSAGE_MAP(CTstCBotView, CView)
+ //{{AFX_MSG_MAP(CTstCBotView)
+ ON_WM_SIZE()
+ ON_COMMAND(ID_CP1, OnCp1)
+ ON_COMMAND(ID_EXE, OnExe)
+ ON_COMMAND(ID_FILE_SAVE, OnFileSave)
+ ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotView construction/destruction
+
+CTstCBotView::CTstCBotView()
+{
+ // TODO: add construction code here
+ m_pEdit = NULL;
+ m_pProg = NULL;
+}
+
+CTstCBotView::~CTstCBotView()
+{
+}
+
+BOOL CTstCBotView::PreCreateWindow(CREATESTRUCT& cs)
+{
+ // TODO: Modify the Window class or styles here by modifying
+ // the CREATESTRUCT cs
+
+ return CView::PreCreateWindow(cs);
+}
+
+void CTstCBotView::OnActivateView( BOOL bActivate, CView* pActivateView, CView* pDeactiveView )
+{
+ if ( m_pEdit == NULL)
+ {
+ m_pEdit = new CEdit();
+ CRect rect;
+ GetClientRect( rect );
+
+ m_pEdit->Create( WS_VISIBLE|WS_BORDER|WS_TABSTOP|ES_MULTILINE|ES_WANTRETURN|ES_NOHIDESEL|ES_AUTOVSCROLL,
+ rect, this, IDC_EDIT1 );
+ m_pEdit->SetTabStops(12);
+ LoadEdition("CBotTest.txt");
+ m_pEdit->SetFocus();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotView drawing
+
+void CTstCBotView::OnDraw(CDC* pDC)
+{
+ CTstCBotDoc* pDoc = GetDocument();
+ ASSERT_VALID(pDoc);
+
+ // TODO: add draw code for native data here
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotView diagnostics
+
+#ifdef _DEBUG
+void CTstCBotView::AssertValid() const
+{
+ CView::AssertValid();
+}
+
+void CTstCBotView::Dump(CDumpContext& dc) const
+{
+ CView::Dump(dc);
+}
+
+CTstCBotDoc* CTstCBotView::GetDocument() // non-debug version is inline
+{
+ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTstCBotDoc)));
+ return (CTstCBotDoc*)m_pDocument;
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CTstCBotView message handlers
+
+void CTstCBotView::OnSize(UINT nType, int cx, int cy)
+{
+ CView::OnSize(nType, cx, cy);
+
+ if ( m_pEdit != NULL )
+ {
+ CRect rect;
+ GetClientRect( rect );
+ m_pEdit->MoveWindow( rect );
+ m_pEdit->SetFocus();
+ }
+}
+
+void CTstCBotView::SaveEdition(const char* filename)
+{
+ CString program;
+
+ m_pEdit->GetWindowText(program);
+
+ FILE* pf = fopen(filename, "wb");
+ if (pf==NULL) return;
+
+ fputs (program, pf);
+ fclose(pf);
+}
+
+void CTstCBotView::LoadEdition(const char* filename)
+{
+ CString program("{ int x = 10000; while (x > 0) x = x-1; }");
+
+ FILE* pf = fopen(filename, "r");
+ if (pf!=NULL)
+ {
+ char buffer[10000];
+ program.Empty();
+
+ while (NULL != fgets (buffer, 100000, pf))
+ {
+ program += buffer;
+ program = program.Left(program.GetLength()-1) + "\r\n";
+ }
+
+ fclose(pf);
+ }
+
+ m_pEdit->SetWindowText(program);
+}
+
+
+
+// compile le programme
+#include <stdio.h>
+
+void CTstCBotView::OnCp1()
+{
+ CString program;
+
+ SaveEdition("CBotTest.txt");
+
+ m_pEdit->GetWindowText(program);
+
+ CString TextError;
+ int code, start, end;
+
+ if ( m_pProg == NULL ) m_pProg = new CBotProgram();
+
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+
+ if (m_pProg->Compile(program, pApp->m_Liste))
+ {
+ CString done = "Compilation sans erreur.\nLes fonctions suivantes sont externes:\n";
+
+ for ( int i = 0; i < pApp->m_Liste.RetSize(); i++)
+ {
+ done += CString(pApp->m_Liste[i]) + "\n";
+ }
+
+ AfxMessageBox( done );
+ }
+ else
+ {
+ m_pProg->GetError(code, start, end);
+ delete m_pProg;
+ m_pProg = NULL;
+
+ m_pEdit->SetSel( start, end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ TextError.LoadString( code );
+ if (TextError.IsEmpty())
+ {
+ char buf[100];
+ sprintf(buf, "Erreur numéro %d.", code);
+ TextError = buf;
+ }
+ AfxMessageBox( TextError );
+ }
+
+ m_pEdit->SetFocus();
+}
+
+
+//////////////////////////////////////////////////////
+
+
+void CTstCBotView::OnExe()
+{
+ CTstCBotApp* pApp = (CTstCBotApp*)AfxGetApp();
+
+ if( m_pProg == NULL)
+ {
+ AfxMessageBox("Pas de programme compilé !");
+ return;
+ }
+
+ if( pApp->m_Liste.RetSize() == 0 )
+ {
+ AfxMessageBox("Aucune fonction marquée \"extern\" !");
+ return;
+ }
+
+
+
+ CBotConsoleDlg dlg;
+ dlg.DoModal(); // dialogue pour faire la console
+
+ if ( dlg.m_code>0 )
+ {
+ CString TextError;
+
+ m_pEdit->SetSel( dlg.m_start, dlg.m_end );
+ m_pEdit->SetFocus(); // met en évidence la partie avec problème
+
+ TextError.LoadString( dlg.m_code );
+ if (TextError.IsEmpty())
+ {
+ char buf[100];
+ sprintf(buf, "Erreur numéro %d.", dlg.m_code);
+ TextError = buf;
+ }
+// AfxMessageBox( TextError );
+ }
+
+ m_pEdit->SetFocus();
+
+ return;
+}
+
+
+
+void CTstCBotView::OnFileSave()
+{
+ // TODO: Add your command handler code here
+ SaveEdition("CBotTest.txt");
+}
+
+void CTstCBotView::OnFileSaveAs()
+{
+ CFileDialog *pDlg;
+ CString s;
+
+ pDlg = new CFileDialog(FALSE, "TXT", NULL,
+ OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY,
+ "cboxtest|*.txt", this);
+ if ( pDlg == NULL ) return;
+
+ if ( pDlg->DoModal() == IDOK ) // choix du fichier ...
+ {
+ SaveEdition(pDlg->GetPathName());
+ }
+
+ delete pDlg;
+}
+
+#if 0
+void test()
+{
+ int y,z;
+
+ for (;;);
+ for (x = 0; y = 1; z = 3) int q = 6;
+ for (int x = 0; int y = 1; int z = 3) int q = 6;
+ // pour voir
+}
+#endif
+
diff --git a/src/CBot/old TstCBot/TstCBotView.h b/src/CBot/old TstCBot/TstCBotView.h
new file mode 100644
index 0000000..d5aede5
--- /dev/null
+++ b/src/CBot/old TstCBot/TstCBotView.h
@@ -0,0 +1,81 @@
+// TstCBotView.h : interface of the CTstCBotView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_TSTCBOTVIEW_H__70B37570_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+#define AFX_TSTCBOTVIEW_H__70B37570_5DFD_11D4_A15E_00E0189013DF__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+class CBotProgram;
+class CBotClass;
+
+
+class CTstCBotView : public CView
+{
+protected: // create from serialization only
+ CTstCBotView();
+ DECLARE_DYNCREATE(CTstCBotView)
+
+ CEdit* m_pEdit; // texte en édition
+ CWnd* m_pWnd;
+ CBotProgram* m_pProg; // programme compilé
+
+// Attributes
+public:
+ CTstCBotDoc* GetDocument();
+
+// Operations
+public:
+ void LoadEdition(const char* name);
+ void SaveEdition(const char* name);
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTstCBotView)
+ public:
+ virtual void OnDraw(CDC* pDC); // overridden to draw this view
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ virtual void OnActivateView( BOOL bActivate, CView* pActivateView, CView* pDeactiveView );
+ protected:
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CTstCBotView();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CTstCBotView)
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnCp1();
+ afx_msg void OnExe();
+ afx_msg void OnFileSave();
+ afx_msg void OnFileSaveAs();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#ifndef _DEBUG // debug version in TstCBotView.cpp
+inline CTstCBotDoc* CTstCBotView::GetDocument()
+ { return (CTstCBotDoc*)m_pDocument; }
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TSTCBOTVIEW_H__70B37570_5DFD_11D4_A15E_00E0189013DF__INCLUDED_)
+
+
+
diff --git a/src/CBot/old TstCBot/res/TstCBot.ico b/src/CBot/old TstCBot/res/TstCBot.ico
new file mode 100644
index 0000000..7eef0bc
--- /dev/null
+++ b/src/CBot/old TstCBot/res/TstCBot.ico
Binary files differ
diff --git a/src/CBot/old TstCBot/res/TstCBot.rc2 b/src/CBot/old TstCBot/res/TstCBot.rc2
new file mode 100644
index 0000000..2186272
--- /dev/null
+++ b/src/CBot/old TstCBot/res/TstCBot.rc2
@@ -0,0 +1,13 @@
+//
+// TSTCBOT.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/src/CBot/old TstCBot/res/TstCBotDoc.ico b/src/CBot/old TstCBot/res/TstCBotDoc.ico
new file mode 100644
index 0000000..2a1f1ae
--- /dev/null
+++ b/src/CBot/old TstCBot/res/TstCBotDoc.ico
Binary files differ
diff --git a/src/CBot/old TstCBot/test complet 1.txt b/src/CBot/old TstCBot/test complet 1.txt
new file mode 100644
index 0000000..0fd4fa5
--- /dev/null
+++ b/src/CBot/old TstCBot/test complet 1.txt
@@ -0,0 +1,213 @@
+// test de l'interpréteur CBot, (c) D. Dumoulin 2000
+
+Int Somme ( Int x, Int y )
+{
+ return x + y;
+}
+
+Real Somme ( Real x, Real y )
+{
+ return x + y;
+}
+
+void A_Faire()
+{
+ CPoint position; // utilise une classe externe
+ position.x = 123.5;
+ position.y = -45.1;
+
+ show ( position );
+}
+
+/* Les nouveautés sont les suivantes
+ __________________________________________________
+
+ On peut définir des fonctions, avec la syntaxe habituelle au C
+ void MaFonction( Int x, Real y ) { ... }
+
+ Les caractéristiques sont pour l'instant les suivantes:
+
+ - ce programme TstCBot exécute la dernière fonction définie
+
+ - on peut définir deux fonctions du même nom,
+ si la liste de paramètres est différente.
+ Par exemple
+ Int Somme( Int x, Int y )
+ Real Somme( Real x, Real y );
+ Note: si la seconde n'existait pas, Somme ( 1.3, 4.8 )
+ serait fait sur les nombres entier 1 + 4
+ La priorité est donnée à la routine qui ne pert pas
+ de bits dans la conversion des paramètres.
+
+ - il n'y a pas d'erreur de compilation si une routine
+ ne retourne pas de valeur alors qu'elle devrait,
+ par contre il y a une erreur "correcte" à l'exécution
+
+ - il est possible d'utiliser une fonction qui est définie
+ plus bas dans le programme.
+ __________________________________________________
+
+ Tous les blocs d'instructions existent maintenant, à savoir
+
+ label :
+ while (condition) { instructions; break label; continue label; }
+
+ label :
+ do { instructions; break label; continue label; } while (condition)
+
+ label:
+ for (initial; condition; incrément) { instructions; break; continue }
+
+ switch ( valeur ) { case 1: instructions; case 2: break ; }
+
+ try {instructions; throw exception; } catch (exception) {instructions;}
+ catch (testlogique) {instructions;}
+ finally {instructions;}
+ // le bloc finally est exécuter dans tous les cas
+ // qu'il y ait eu exception ou non, et aussi en cas de break, continue ou return
+ __________________________________________________
+
+ Les "exceptions" sont juste des numéros (31 bits)
+ 6000 = division par zéro
+ 6001 = variable non initialisée
+ 6002 = valeur négative pour un throw
+ 6003 = la fonction n'a pas retourné de valeur
+
+ les autres numéros sont à disposition
+ (COLOBOT aura surement des numéros d'exception propre)
+ l'association d'un mot clef pour ces exceptions est à venir.
+ __________________________________________________
+
+ L'interpréteur a été un peu optimiser, une boucle de un millon de décrément
+ ne prend plus que
+*/
+
+void Test ()
+{ // début du bloc d'instructions
+
+ Int z = 1000000;
+ while ( z>0 ) z--;
+
+ return;
+ {
+ // test la préséance pour les assignations
+ Int a = 9;
+ a += (a = 3);
+ if ( a != 12 ) 1/0; // le résultat correct est 12
+
+ Int b = 9;
+ b = b + (b = 3);
+ if (b != 12) 1/0; // même chose
+
+ // la fonction show est une fonction externe
+ // définie par TstCBot
+ // elle peut prendre un nombre quelconque de paramètres
+ show ( a, b );
+ }
+
+ {
+ // petit test sur les chaînes
+ String x = "ch." ;
+ String y ;
+ x += y = x + " de la brume.";
+
+ // concaténation de chaînes, accepte des autres types
+ String s = 1 + 2 + " test " + 3 + 4 ;
+
+ show( x, y, s );
+
+ // les tests sur les chaînes ne sont pas standard en Java
+ // mais c'est si pratique :
+
+ if ( s != "3 test 34" ) 1/0; // le résultat correct est "3 test 34"
+ // car 1+2 est évalué en premier entre 2 nombres
+ // et ensuite on additionne des chaînes "3" "4"
+ }
+
+ {
+ // teste toutes les opérations avec les entiers (32 bits)
+ Int a = 4;
+ Int b = 4;
+
+ Int c = a++ * --b; // post incrément, pré décrément
+ if ( c != 12 ) 1/0;
+
+ c = ++a * b--; // pré incrément, post décrément
+ if ( c!=18 ) 1/0;
+
+ a = a+b-a*b/a%3; // 6 + 2 - ( 6 * 2 / 6 % 3 ) -> 6
+ if ( a != 6 ) 1/0;
+
+ a += 2; a-=1; a*=3; a/=4; a%=3; // (6+2 -1) *3 /4 modulo 3 = 21 / 4 modulo 3 = 2
+ if ( a!= 2) 0/0;
+
+ if (-5 << 3 != -40) 0/0; // shift à gauche
+ if ( -5 >> 1 != -3) 0/0; // shift arithmétique à droite 11111011 -> 11111101 = -3
+ if ( -5 >>> 1 != 0x3ffffffd) 0/0; // shift non signé à droite
+
+ a = -10; // fait la même chose en assignation
+ a <<= 1; // -20
+ a >>= 2; // -5
+ a >>>= 1; // pert le signe
+ if ( a != 0x3ffffffd) 0/0; //
+
+ Int x = 5/3; // division d'entiers
+ if ( x != 1 ) 0/0;
+ Int xx = 5.0/3.0; // division de réels, assigné à un entier
+ if ( xx != 1 ) 0/0;
+
+ Int y = 0xF0035678;
+ if ( ~y != 0x0FFCA987 ) 0/0; // NOT bit à bit
+ if ( (0x3456 ^ 0x54f0) != 0x60A6) // XOR bit à bit
+ 0/0;
+ if ( (0x23 | 0x83) != 0xA3 ) 0/0; // OR bit à bit
+ if ( (0x23 & 0x83) != 0x03 ) 0/0; // AND bit à bit
+
+ Int z = 0x0123;
+ z |= 0x8010; if ( z != 0x8133) 0/0;
+ z &= 0xF018; if ( z != 0x8010) 0/0;
+ z ^= 0xFF17; if ( z != 0x7F07) 0/0;
+ }
+
+ {
+ // test pour les booléens
+ Boolean a, b= true, c = false;
+ a = b | c & b;
+ if ( a != b ) 0/0;
+ if ( !a ) 0/0;
+ if ( b ^ a ) 0/0; // XOR
+ if ( true || 0/0<1 ) {};
+ if ( false && 0/0<1) {};
+ // a ? "vrai" : "faux";
+ }
+
+ {
+ // petit test sur les nombres réels
+ Real x = 1. / 3, y = 0;
+
+ if ( 3 * x != 1 ) x = x / y; // provoque une division par zéro
+ else y = 1.123;
+ }
+
+
+ // test de durée
+ // attention, le programme de test ne stoppe qu'à la fin d'exécution
+ // bien que la boucle est interrompue plusieures fois
+
+ // la boucle est plus rapide si elle est au début du programme !
+ {
+ Int z = 10000;
+ while ( z > 0 ) z = z - 1;
+ }
+
+}
+
+void t()
+{
+ A_Faire();
+
+ show ( Somme ( 1, 2 ) );
+ show ( Somme ( 1., 2 ) );
+ show ( Somme ( 4.5, 2.7 ) );
+}
+
diff --git a/src/CBot/old TstCBot/x.txt b/src/CBot/old TstCBot/x.txt
new file mode 100644
index 0000000..95856e0
--- /dev/null
+++ b/src/CBot/old TstCBot/x.txt
@@ -0,0 +1,43 @@
+// test de l'interpréteur CBot, (c) D. Dumoulin 2000
+
+// pour l'instant, seule les primitives suivantes sont implémentées
+
+// { ... ; ... ; ... } un bloc d'instructions
+// int x, y = 12, z; // déclaration de nombre entier
+// float a, b= 2/3, c=b+1; // déclaration de nombres réels
+// boolean tst = true; // déclaration d'un booléen
+// String x = "hello"; // déclaration d'une chaînes
+
+// z = x = x * y / ( z + 1 - x ); // assignation en chaîne et les 4 opérations
+
+// while ( x >= 0 ) x = x - 1; // boucle while, et test > >= < <= == !=
+// if ( x < y ) x = x + 1; // test si
+// else y = y + 1; // sinon
+
+/* et les opérations suivantes:
+ + plus unaire x = +y;
+ - moins unaire x = -y;
+
+ || OU logique
+ && ET logique
+ ! NOT logique
+ | OU bit à bit
+ & ET bit à bit
+ ^ XOR bit à bit
+ ~ NON bit à bit
+
+// les commentaires sont acceptés
+/* y compris les commentaires
+ sur plusieures lignes */
+
+
+{
+String str ;
+
+str = "abc" ;
+
+show (str) ;
+
+show( str = str + "+++" , ) ;
+
+}
diff --git a/src/CBot/resource.h b/src/CBot/resource.h
new file mode 100644
index 0000000..659ee69
--- /dev/null
+++ b/src/CBot/resource.h
@@ -0,0 +1,166 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by CBot.rc
+//
+#define ID_KEYWORDS 2000
+#define ID_IF 2000
+#define ID_ELSE 2001
+#define ID_WHILE 2002
+#define ID_DO 2003
+#define ID_FOR 2004
+#define ID_BREAK 2005
+#define ID_CONTINUE 2006
+#define ID_SWITCH 2007
+#define ID_CASE 2008
+#define ID_DEFAULT 2009
+#define ID_TRY 2010
+#define ID_THROW 2011
+#define ID_CATCH 2012
+#define ID_FINALLY 2013
+#define ID_TXT_AND 2014
+#define ID_TXT_OR 2015
+#define ID_TXT_NOT 2016
+#define ID_RETURN 2017
+#define ID_CLASS 2018
+#define ID_EXTENDS 2019
+#define ID_SYNCHO 2020
+#define ID_NEW 2021
+#define ID_PUBLIC 2022
+#define ID_EXTERN 2023
+#define ID_FINAL 2024
+#define ID_STATIC 2025
+#define ID_PROTECTED 2026
+#define ID_PRIVATE 2027
+#define ID_REPEAT 2028
+#define ID_DEBUGDD 2099
+#define ID_INT 2100
+#define ID_FLOAT 2101
+#define ID_BOOLEAN 2102
+#define ID_STRING 2103
+#define ID_VOID 2104
+#define ID_BOOL 2105
+#define ID_TRUE 2200
+#define ID_FALSE 2201
+#define ID_NULL 2202
+#define ID_NAN 2203
+#define ID_OPENPAR 2300
+#define ID_CLOSEPAR 2301
+#define ID_OPBLK 2302
+#define ID_CLBLK 2303
+#define ID_SEP 2304
+#define ID_COMMA 2305
+#define ID_DOTS 2306
+#define ID_DOT 2307
+#define ID_OPBRK 2308
+#define ID_CLBRK 2309
+#define ID_DBLDOTS 2310
+#define ID_LOGIC 2311
+#define ID_ADD 2312
+#define ID_SUB 2313
+#define ID_MUL 2314
+#define ID_DIV 2315
+#define ID_ASS 2316
+#define ID_ASSADD 2317
+#define ID_ASSSUB 2318
+#define ID_ASSMUL 2319
+#define ID_ASSDIV 2320
+#define ID_ASSOR 2321
+#define ID_ASSAND 2322
+#define ID_ASSXOR 2323
+#define ID_ASSSL 2324
+#define ID_ASSSR 2325
+#define ID_ASSASR 2326
+#define ID_SL 2327
+#define ID_SR 2328
+#define ID_ASR 2329
+#define ID_INC 2330
+#define ID_DEC 2331
+#define ID_LO 2332
+#define ID_HI 2333
+#define ID_LS 2334
+#define ID_HS 2335
+#define ID_EQ 2336
+#define ID_NE 2337
+#define ID_AND 2338
+#define ID_XOR 2339
+#define ID_OR 2340
+#define ID_LOG_AND 2341
+#define ID_LOG_OR 2342
+#define ID_LOG_NOT 2343
+#define ID_NOT 2344
+#define ID_MODULO 2345
+#define ID_POWER 2346
+#define ID_ASSMODULO 2347
+#define TX_UNDEF 4000
+#define TX_NAN 4001
+#define TX_OPENPAR 5000
+#define TX_CLOSEPAR 5001
+#define TX_NOTBOOL 5002
+#define TX_UNDEFVAR 5003
+#define TX_BADLEFT 5004
+#define TX_ENDOF 5005
+#define TX_OUTCASE 5006
+#define TX_NOTERM 5007
+#define TX_CLOSEBLK 5008
+#define TX_ELSEWITHOUTIF 5009
+#define TX_OPENBLK 5010
+#define TX_BADTYPE 5011
+#define TX_REDEFVAR 5012
+#define TX_BAD2TYPE 5013
+#define TX_UNDEFCALL 5014
+#define TX_MISDOTS 5015
+#define TX_WHILE 5016
+#define TX_BREAK 5017
+#define TX_LABEL 5018
+#define TX_NOLABEL 5019
+#define TX_NOCASE 5020
+#define TX_BADNUM 5021
+#define TX_VOID 5022
+#define TX_NOTYP 5023
+#define TX_NOVAR 5024
+#define TX_NOFONC 5025
+#define TX_OVERPARAM 5026
+#define TX_REDEF 5027
+#define TX_LOWPARAM 5028
+#define TX_BADPARAM 5029
+#define TX_NUMPARAM 5030
+#define TX_NOITEM 5031
+#define TX_DOT 5032
+#define TX_NOCONST 5033
+#define TX_REDEFCLASS 5034
+#define TX_CLBRK 5035
+#define TX_RESERVED 5036
+#define TX_BADNEW 5037
+#define TX_OPBRK 5038
+#define TX_BADSTRING 5039
+#define TX_BADINDEX 5040
+#define TX_PRIVATE 5041
+#define TX_NOPUBLIC 5042
+#define TX_DIVZERO 6000
+#define TX_NOTINIT 6001
+#define TX_BADTHROW 6002
+#define TX_NORETVAL 6003
+#define TX_NORUN 6004
+#define TX_NOCALL 6005
+#define TX_NOCLASS 6006
+#define TX_NULLPT 6007
+#define TX_OPNAN 6008
+#define TX_OUTARRAY 6009
+#define TX_STACKOVER 6010
+#define TX_DELETEDPT 6011
+#define TX_FILEOPEN 6012
+#define TX_NOTOPEN 6013
+#define TX_ERRREAD 6014
+#define TX_ERRWRITE 6015
+#define ID_SUPER 62020
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif