/* * This file is part of the Colobot: Gold Edition source code * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://gnu.org/licenses */ //////////////////////////////////////////////////////////////////////// /** * \file CBotDll.h * \brief Library for interpretation of CBOT language */ #pragma once // Modules inlcude #include "resource.h" #include "CBotEnums.h" // Local include // Global include #include #include #include #define CBOTVERSION 104 //////////////////////////////////////////////////////////////////////// // forward declaration of needed classes class CBotToken; // program turned into "tokens class CBotStack; // for the execution stack class CBotClass; // class of object class CBotInstr; // instruction to be executed class CBotFunction; // user functions class CBotVar; // variables class CBotVarClass; // instance of class class CBotVarPointer; // pointer to an instance of class class CBotCall; // functions class CBotCallMethode; // methods class CBotDefParam; // parameter list class CBotCStack; // stack //////////////////////////////////////////////////////////////////////// // Variables management //////////////////////////////////////////////////////////////////////// //n = not implemented yet // for SetUserPtr when deleting an object // \TODO define own types to distinct between different states of objects #define OBJECTDELETED (reinterpret_cast(-1)) // value set before initialization #define OBJECTCREATED (reinterpret_cast(-2)) /** \brief CBotTypResult class to define the complete type of a result*/ class CBotTypResult { public: /** * \brief CBotTypResult constructor for simple types (CBotTypInt to CBotTypString) * \param type type of created result, see CBotType */ CBotTypResult(int type); // for simple types (CBotTypInt à CBotTypString) CBotTypResult(int type, const char* name); // for pointer types and intrinsic classes CBotTypResult(int type, CBotClass* pClass); // for the instance of a class CBotTypResult(int type, CBotTypResult elem); // for arrays of variables CBotTypResult(const CBotTypResult& typ); // for assignments CBotTypResult(); // for default ~CBotTypResult(); int GetType(int mode = 0) const; // returns type CBotType* as a result void SetType(int n); // modifies a type CBotClass* GetClass() const; // makes the pointer to the class (for CBotTypClass, CBotTypPointer) int GetLimite() const; // returns limit size of table (CBotTypArray) void SetLimite(int n); // set limit to the table void SetArray(int* max ); // set limits for a list of dimensions (arrays of arrays) CBotTypResult& GetTypElem() const; // returns type of array elements (CBotTypArray) // rend le type des éléments du tableau (CBotTypArray) bool Compare(const CBotTypResult& typ) const; // compares whether the types are compatible bool Eq(int type) const; // compare type CBotTypResult& operator=(const CBotTypResult& src); // copy a complete type in another private: int m_type; CBotTypResult* m_pNext; // for the types of type CBotClass* m_pClass; // for the derivatives of class int m_limite; // limits of tables friend class CBotVarClass; friend class CBotVarPointer; }; /* // to define a result as output, using for example // to return a simple Float return CBotTypResult( CBotTypFloat ); // to return a string array return CBotTypResult( CBotTypArray, CBotTypResult( CBotTypString ) ); // to return un array of array of "point" class CBotTypResult typPoint( CBotTypIntrinsic, "point" ); CBotTypResult arrPoint( CBotTypArray, typPoint ); return CBotTypResult( CBotTypArray, arrPoint ); */ //////////////////////////////////////////////////////////////////////// // Error Handling of compilation and execution //////////////////////////////////////////////////////////////////////// // Here are the list of errors that can be returned by the module // for compilation #define CBotErrOpenPar 5000 // missing the opening parenthesis #define CBotErrClosePar 5001 // missing the closing parenthesis #define CBotErrNotBoolean 5002 // expression must be a boolean #define CBotErrUndefVar 5003 // undeclared variable #define CBotErrBadLeft 5004 // assignment impossible ( 5 = ... ) #define CBotErrNoTerminator 5005 // semicolon expected #define CBotErrCaseOut 5006 // case outside a switch // CBotErrNoTerm 5007, plus utile #define CBotErrCloseBlock 5008 // missing " } " #define CBotErrElseWhitoutIf 5009 // else without matching if #define CBotErrOpenBlock 5010 // missing " { " #define CBotErrBadType1 5011 // wrong type for the assignment #define CBotErrRedefVar 5012 // redefinition of the variable #define CBotErrBadType2 5013 // Two operands are incompatible #define CBotErrUndefCall 5014 // routine undefined #define CBotErrNoDoubleDots 5015 // " : " expected // CBotErrWhile 5016, plus utile #define CBotErrBreakOutside 5017 // break outside of a loop #define CBotErrUndefLabel 5019 // label udnefined #define CBotErrLabel 5018 // label ne peut se mettre ici (label can not get here) #define CBotErrNoCase 5020 // missing " case " #define CBotErrBadNum 5021 // expected number #define CBotErrVoid 5022 // " void " not possible here #define CBotErrNoType 5023 // type declaration expected #define CBotErrNoVar 5024 // variable name expected #define CBotErrNoFunc 5025 // expected function name #define CBotErrOverParam 5026 // too many parameters #define CBotErrRedefFunc 5027 // this function already exists #define CBotErrLowParam 5028 // not enough parameters #define CBotErrBadParam 5029 // wrong types of parameters #define CBotErrNbParam 5030 // wrong number of parameters #define CBotErrUndefItem 5031 // element does not exist in the class #define CBotErrUndefClass 5032 // variable is not a class #define CBotErrNoConstruct 5033 // no appropriate constructor #define CBotErrRedefClass 5034 // class already exists #define CBotErrCloseIndex 5035 // " ] " expected #define CBotErrReserved 5036 // reserved word (for a DefineNum) #define CBotErrBadNew 5037 // wrong setting for new #define CBotErrOpenIndex 5038 // " [ " expected #define CBotErrBadString 5039 // expected string #define CBotErrBadIndex 5040 // wrong index type "[ false ]" #define CBotErrPrivate 5041 // protected item #define CBotErrNoPublic 5042 // missing word "public" // here is the list of errors that can be returned by the module // for the execution #define CBotErrZeroDiv 6000 // division by zero #define CBotErrNotInit 6001 // uninitialized variable #define CBotErrBadThrow 6002 // throw a negative value #define CBotErrNoRetVal 6003 // function did not return results #define CBotErrNoRun 6004 // Run() without active function #define CBotErrUndefFunc 6005 // calling a function that no longer exists #define CBotErrNotClass 6006 // this class does not exist #define CBotErrNull 6007 // null pointer #define CBotErrNan 6008 // calculation with a NAN #define CBotErrOutArray 6009 // index out of array #define CBotErrStackOver 6010 // stack overflow #define CBotErrDeletedPtr 6011 // pointer to an object destroyed #define CBotErrFileOpen 6012 // cannot open the file #define CBotErrNotOpen 6013 // channel not open #define CBotErrRead 6014 // error while reading #define CBotErrWrite 6015 // writing error // other values ​​may be returned // for example exceptions returned by external routines // and " throw " with any number. //////////////////////////////////////////////////////////////////////// /** * \brief CBotString Class used to work on strings */ class CBotString { public: /** * \brief CBotString Default constructor. */ CBotString(); /** * \brief CBotString * \param p */ CBotString(const char* p); /** * \brief CBotString * \param p */ CBotString(const CBotString& p); /** * \brief CBotString Destructor. */ ~CBotString(); /** * \brief Empty Clear the internal string. */ void Empty(); /** * \brief IsEmpty Check if the string is empty. * \return True if the sting is empty false otherwise. */ bool IsEmpty() const; /** * \brief GetLength Get the string length. * \return The size of the string. */ int GetLength(); /** * \brief Find Find the position of a character in a string starting from * the beginning of the string. * \param c The character to find. * \return The position of the character or -1 if the character was not * found. * \see ReverseFind(const char c) */ int Find(const char c); /** * \brief Find Find the position of a string in a string starting from the * beginning of the string. * \param lpsz The string to find. * \return The position of the string or -1 if the string was not * found. * \see ReverseFind(const char* lpsz) */ int Find(const char* lpsz); /** * \brief Find Find the position of a character in a string starting from * the end of the string. * \param c The character to find. * \return The position of the character or -1 if the character was not * found. * \see Find(const char c) */ int ReverseFind(const char c); /** * \brief Find Find the position of a string in a string starting from the * end of the string. * \param lpsz The string to find. * \return The string of the character or -1 if the string was not * found. * \see Find(const char* lpsz) */ int ReverseFind(const char* lpsz); /** * \brief LoadString Load the string associate with the id. * \param id The id to load. * \return True if the id exist false otherwise. */ bool LoadString(unsigned int id); /** * \brief Mid Return a part of a string from a starting index and until * the end of the string with a limited size. * \param nFirst The start index of the character in the string. * \param lg The size limit. Default value is 2000. * \return The exctracted string. */ CBotString Mid(int start, int lg=-1); /** * \brief Left Return a part of a string starting from the left. * \param nCount The number of character to retreive. * \return The exctracted string. */ CBotString Left(int nCount) const; /** * \brief Right Return a part of a string starting from the right. * \param nCount The number of character to retreive. * \return The exctracted string. */ CBotString Right(int nCount) const; /** * \brief Compare Compare a given string to an other. * \param lpsz The string to compare. * \return 0 if the two string matches. Less than 0 if the current * string is less than lpsz. Greater than 0 if the current * string is greater than lpsz. */ int Compare(const char* lpsz) const; /** * \brief MakeUpper Uppercase the string. */ void MakeUpper(); /** * \brief MakeLower Lowercase the string. */ void MakeLower(); /** * @brief CStr Convert the CBotString to a C string. * @return A C string string. */ const char* CStr() const; /** * \brief Overloaded oprators to work on CBotString classes */ const CBotString& operator=(const CBotString& stringSrc); const CBotString& operator=(const char ch); const CBotString& operator=(const char* pString); CBotString operator+(const CBotString& str); const CBotString& operator+=(const char ch); const CBotString& operator+=(const CBotString& str); bool operator==(const CBotString& str); bool operator==(const char* p); bool operator!=(const CBotString& str); bool operator!=(const char* p); bool operator>(const CBotString& str); bool operator>(const char* p); bool operator>=(const CBotString& str); bool operator>=(const char* p); bool operator<(const CBotString& str); bool operator<(const char* p); bool operator<=(const CBotString& str); bool operator<=(const char* p); operator const char*() const; // as a C string private: //! \brief Pointer to string char* m_ptr; //! \brief Length of the string int m_lg; //! \brief Keeps the string corresponding to keyword ID static const std::map s_keywordString; /** * \brief MapIdToString Maps given ID to its string equivalent. * \param id Provided identifier. * \return String if found, else NullString. */ static const char * MapIdToString(EID id); }; // Class used to array management class CBotStringArray : public CBotString { private: int m_nSize; // number of elements int m_nMaxSize; // reserved size CBotString* m_pData; // ^data public: CBotStringArray(); ~CBotStringArray(); void SetSize(int nb); int GetSize(); void Add(const CBotString& str); CBotString& operator[](int nIndex); CBotString& ElementAt(int nIndex); }; /////////////////////////////////////////////////////////////////////////////// // routines for file management (* FILE) FILE* fOpen(const char* name, const char* mode); int fClose(FILE* filehandle); size_t fWrite(const void *buffer, size_t elemsize, size_t length, FILE* filehandle); size_t fRead(void *buffer, size_t elemsize, size_t length, FILE* filehandle); #if 0 /* (**) Note: To define an external function, proceed as follows: a) define a routine for compilation this routine receive list of parameters (no values) and either returns a result type (CBotTyp... or 0 = void) or an error number b) define a routine for the execution this routine receive list of parameters (with valeurs), a variable to store the result (according to the given type at compile time) For example, a routine which calculates the mean of a parameter list */ int cMean(CBotVar* &pVar, CBotString& ClassName) { if ( pVar == nullptr ) return 6001; // there is no parameter! while ( pVar != nullptr ) { if ( pVar->GetType() > CBotTypDouble ) return 6002; // this is not a number pVar = pVar -> GetNext(); } return CBotTypFloat; // the type of the result may depend on the parameters! } bool rMean(CBotVar* pVar, CBotVar* pResult, int& Exception) { float total = 0; int nb = 0; while (pVar != nullptr) { total += pVar->GetValFloat(); pVar = pVar->GetNext(); nb++; } pResult->SetValFloat(total/nb); // returns the mean value return true; // operation fully completed } #endif /* //////////////////////////////////////////////////////////////////////// // Examples of use // Definition classes and functions // define the global class CPoint // -------------------------------- m_pClassPoint = new CBotClass("CPoint", nullptr); // adds the component ".x" m_pClassPoint->AddItem("x", CBotTypResult(CBotTypFloat)); // adds the component ".y" m_pClassPoint->AddItem("y", CBotTypResult(CBotTypFloat)); // the player can then use the instructions // CPoint position; position.x = 12; position.y = -13.6 // define class CColobotObject // -------------------------------- // This class manages all the objects in the world of COLOBOT // the "main" user program belongs to this class m_pClassObject = new CBotClass("CColobotObject", m_pClassBase); // adds the component ".position" m_pClassObject->AddItem("position", m_pClassPoint); // adds the component ".type" m_pClassObject->AddItem("type", CBotTypResult(CBotTypShort)); // adds a definition of constant m_pClassObject->AddConst("ROBOT", CBotTypShort, 1); // ROBOT equivalent to the value 1 // adds the FIND routine m_pClassObject->AddFunction( rCompFind, rDoFind ); // the player can now use the instructions // CColobotObject chose; chose = FIND( ROBOT ) // define class CColobotRobot derived from CColobotObject // --------------------------------------------------------- // programs "main" associated with robots as a part of this class m_pClassRobot = new CBotClass("CColobotRobot", m_pClassObject); // add routine GOTO m_pClassRobot->AddFunction( rCompGoto, rDoGoto ); // the player can now use // GOTO( FIND ( ROBOT ) ); // creates an instance of the class Robot // ------------------------------------ // for example a new robot which has just been manufactured CBotVar* m_pMonRobot = new CBotVar("MonRobot", m_pClassRobot); // compiles the program by hand for this robot // ------------------------------------------ CString LeProgramme( "void main() {GOTO(0, 0); return 0;}" ); if ( !m_pMonRobot->Compile( LeProgramme ) ) {error handling ...}; // build a stack for interpreter // -------------------------------------- CBotStack* pStack = new CBotStack(nullptr); // executes the main program // ------------------------- while( false = m_pMonRobot->Execute( "main", pStack )) { // program suspended // could be pass a handle to another (safeguarding pstack for the robot one) }; // programme "main" finished ! // routine that implements the GOTO (CPoint pos) bool rDoGoto( CBotVar* pVar, CBotVar* pResult, int& exception ) { if (pVar->GetType() != CBotTypeClass || pVar->IsElemOfClas("CPoint") ) { exception = 6522; return false; ) // the parameter is not the right class? // in fact the control is done to the routine of compilation m_PosToGo.Copy( pVar ); // keeps the target position (object type CBotVar) // or so CBotVar* temp; temp = pVar->GetItem("x"); // is necessary for the object of type CPoint ASSERT (temp != nullptr && temp->GetType() == CBotTypFloat); m_PosToGo.x = temp->GetValFloat(); temp = pVar->GetItem("y"); // is necessary for the object of type CPoint ASSERT (temp != nullptr && temp->GetType() == CBotTypFloat); m_PosToGo.y = temp->GetValFloat(); return (m_CurentPos == m_PosToGo); // makes true if the position is reached // returns false if one had wait yet } */