From 6590652d9e99f124b171ec78e83222efafd85949 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sat, 21 Nov 2015 16:31:22 +0100 Subject: [PATCH] Added commandline CBot interpreter (for testing purposes) --- .gitignore | 3 +- src/CBot/.gitignore | 1 - test/CMakeLists.txt | 3 + test/cbot/CMakeLists.txt | 1 + test/cbot/console/CMakeLists.txt | 22 ++++++++ test/cbot/console/main.cpp | 94 ++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 2 deletions(-) delete mode 100644 src/CBot/.gitignore create mode 100644 test/cbot/CMakeLists.txt create mode 100644 test/cbot/console/CMakeLists.txt create mode 100644 test/cbot/console/main.cpp diff --git a/.gitignore b/.gitignore index 885f5fe8..65c0087a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,10 +16,11 @@ Makefile # Ignore targets /colobot +/src/CBot/libCBot.so # Ignore local data /colobot.ini -/savegame +/saves # Standard build directory /build diff --git a/src/CBot/.gitignore b/src/CBot/.gitignore deleted file mode 100644 index 4c80252f..00000000 --- a/src/CBot/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libCBot.so diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c30abe89..cd4c320b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,6 +6,9 @@ set(CMAKE_CXX_FLAGS_DEBUG ${COLOBOT_CXX_FLAGS_DEBUG}) # Unit tests add_subdirectory(unit) +# CBot tests +add_subdirectory(cbot) + if(COLOBOT_LINT_BUILD) add_fake_header_sources("test") diff --git a/test/cbot/CMakeLists.txt b/test/cbot/CMakeLists.txt new file mode 100644 index 00000000..d5de1f4e --- /dev/null +++ b/test/cbot/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(console) \ No newline at end of file diff --git a/test/cbot/console/CMakeLists.txt b/test/cbot/console/CMakeLists.txt new file mode 100644 index 00000000..e33a1085 --- /dev/null +++ b/test/cbot/console/CMakeLists.txt @@ -0,0 +1,22 @@ +# Sources +set(CBOT_CONSOLE_SOURCES + main.cpp +) + +# Includes +include_directories( + ${COLOBOT_LOCAL_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +# Libraries +set(LIBS + CBot + colobotbase # Needed for error strings (TODO: why are they on Colobot side? :/) + ${COLOBOT_LIBS} # Needed for colobotbase +) +# Targets + +add_executable(CBot_console ${CBOT_CONSOLE_SOURCES}) +target_link_libraries(CBot_console ${LIBS}) \ No newline at end of file diff --git a/test/cbot/console/main.cpp b/test/cbot/console/main.cpp new file mode 100644 index 00000000..83e06dea --- /dev/null +++ b/test/cbot/console/main.cpp @@ -0,0 +1,94 @@ +#include +#include + +#include "common/restext.h" +#include "CBot/CBotDll.h" + +CBotTypResult cMessage(CBotVar* &var, void* user) +{ + if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); + if ( var->GetType() != CBotTypString && + var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GetNext(); + + if ( var == nullptr ) return CBotTypResult(CBotTypFloat); + return CBotTypResult(CBotErrOverParam); +} + +bool rMessage(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CBotString cbs = var->GetValString(); + const char* message = cbs; // Don't ask me why, but it doesn't work if you write it on a single line + + std::cout << message << std::endl; + + return true; +} + +int main(int argc, char* argv[]) +{ + // Read program code from stdin + std::string code = ""; + std::string line; + while (std::getline(std::cin, line)) + { + code += line; + code += "\n"; + } + + // Error message strings are stored on Colobot side (meh!) so let's initialize that + InitializeRestext(); + + // Initialize the CBot engine, add standard library functions + CBotProgram::AddFunction("message", rMessage, cMessage); + + // Compile the program + CBotStringArray externFunctions; + std::unique_ptr program{new CBotProgram(nullptr)}; + if (!program->Compile(code.c_str(), externFunctions, nullptr)) + { + int error, cursor1, cursor2; + program->GetError(error, cursor1, cursor2); + std::string errorStr; + GetResource(RES_CBOT, error, errorStr); + std::cerr << "COMPILE ERROR: " << errorStr << " (code: " << error << ") @ " << cursor1 << " - " << cursor2 << std::endl; + return 1; + } + + // Execute all compiled functions marked as "extern" + if (externFunctions.GetSize() == 0) + { + std::cerr << "NO EXTERN FUNCTIONS FOUND"; + return 2; + } + bool runErrors = false; + for (int i = 0; i < externFunctions.GetSize(); i++) + { + const char* func = externFunctions[i]; + if (!program->Start(func)) + { + std::cerr << "FAILED TO START: " << func << std::endl; + continue; + } + + std::cerr << "Running program: " << func << std::endl; + + while (!program->Run(nullptr)); // Run the program + + int error, cursor1, cursor2; + program->GetError(error, cursor1, cursor2); + if (error != 0) + { + std::string errorStr; + GetResource(RES_CBOT, error, errorStr); + std::cerr << "RUNTIME ERROR: " << errorStr << " (code: " << error << ") @ " << cursor1 << " - " << cursor2 << std::endl; + runErrors = true; + } + else + { + std::cerr << "Program finished." << std::endl; + } + } + + return runErrors ? 3 : 0; +} \ No newline at end of file