From d5d25b0e89faebe4b1c5961d7b1ab872339e4a03 Mon Sep 17 00:00:00 2001 From: Tobia Tesan Date: Mon, 29 Feb 2016 15:48:59 +0100 Subject: WINTERMUTE: Add print and set commands to debugger --- engines/wintermute/debugger.cpp | 36 ++++++++++++ engines/wintermute/debugger.h | 4 ++ .../wintermute/debugger/debugger_controller.cpp | 65 ++++++++++++++++++++++ engines/wintermute/debugger/debugger_controller.h | 8 +++ 4 files changed, 113 insertions(+) diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp index 760a852c97..6a349c070f 100644 --- a/engines/wintermute/debugger.cpp +++ b/engines/wintermute/debugger.cpp @@ -46,6 +46,8 @@ Console::Console(WintermuteEngine *vm) : GUI::Debugger(), _engineRef(vm) { registerCmd(REMOVE_BREAKPOINT_CMD, WRAP_METHOD(Console, Cmd_RemoveBreakpoint)); registerCmd(DISABLE_BREAKPOINT_CMD, WRAP_METHOD(Console, Cmd_DisableBreakpoint)); registerCmd(ENABLE_BREAKPOINT_CMD, WRAP_METHOD(Console, Cmd_EnableBreakpoint)); + registerCmd(PRINT_CMD, WRAP_METHOD(Console, Cmd_Print)); + registerCmd(SET_CMD, WRAP_METHOD(Console, Cmd_Set)); registerCmd(INFO_CMD, WRAP_METHOD(Console, Cmd_Info)); registerCmd(SET_PATH_CMD, WRAP_METHOD(Console, Cmd_SourcePath)); registerCmd(TOP_CMD, WRAP_METHOD(Console, Cmd_Top)); @@ -194,6 +196,40 @@ bool Console::Cmd_List(int argc, const char **argv) { return true; } +bool Console::Cmd_Print(int argc, const char **argv) { + if (argc == 2) { + Error error = Error(SUCCESS, OK, 0); + Common::String temp = CONTROLLER->readValue(argv[1], &error); + if (error.getErrorLevel() == SUCCESS) { + debugPrintf("%s = %s \n", argv[1], temp.c_str()); + return true; + } else { + printError(argv[0], error); + return true; + } + } else { + printUsage(argv[0]); + return true; + } +} + + +bool Console::Cmd_Set(int argc, const char **argv) { + if (argc == 4 && !strncmp("=", argv[2], 1)) { + ScValue *val = nullptr; + Error error = CONTROLLER->setValue(argv[1], argv[3], val); + if (error.getErrorLevel() == SUCCESS) { + assert(val); + debugPrintf("%s = %s\n", argv[1], val->getString()); + } else { + printError(argv[0], error); + } + } else { + printUsage(argv[0]); + } + return true; +} + bool Console::Cmd_ShowFps(int argc, const char **argv) { if (argc == 2) { if (Common::String(argv[1]) == "true") { diff --git a/engines/wintermute/debugger.h b/engines/wintermute/debugger.h index 2e427d35db..542403c6ea 100644 --- a/engines/wintermute/debugger.h +++ b/engines/wintermute/debugger.h @@ -44,6 +44,8 @@ #define DISABLE_BREAKPOINT_CMD "disable" #define ENABLE_BREAKPOINT_CMD "enable" #define INFO_CMD "info" +#define SET_CMD "set" +#define PRINT_CMD "print" #define SET_PATH_CMD "set_path" #define TOP_CMD "top" @@ -78,6 +80,8 @@ public: * (activation record is popped) */ bool Cmd_Finish(int argc, const char **argv); + bool Cmd_Print(int argc, const char **argv); + bool Cmd_Set(int argc, const char **argv); // Breakpoints bool Cmd_AddBreakpoint(int argc, const char **argv); bool Cmd_RemoveBreakpoint(int argc, const char **argv); diff --git a/engines/wintermute/debugger/debugger_controller.cpp b/engines/wintermute/debugger/debugger_controller.cpp index c7c88be034..6fe49f2af2 100644 --- a/engines/wintermute/debugger/debugger_controller.cpp +++ b/engines/wintermute/debugger/debugger_controller.cpp @@ -142,6 +142,71 @@ void DebuggerController::clear() { _lastLine = -1; } +Common::String DebuggerController::readValue(const Common::String &name, Error *error) { + if (!_lastScript) { + delete error; + error = new Error(ERROR, NOT_ALLOWED); + return Common::String(); + } + char cstr[256]; // TODO not pretty + Common::strlcpy(cstr, name.c_str(), name.size() + 1); + cstr[255] = '\0'; // We 0-terminate it just in case it's longer than 255. + return _lastScript->resolveName(cstr)->getString(); +} + +Error DebuggerController::setValue(const Common::String &name, const Common::String &value, ScValue *&var) { + if (!_lastScript) { + return Error(ERROR, NOT_ALLOWED); + } + + Common::String trimmed = value; + trimmed.trim(); + char cstr[256]; + Common::strlcpy(cstr, name.c_str(), name.size() + 1); // TODO not pretty + + var = _lastScript->getVar(cstr); + if (var->_type == VAL_INT) { + char *endptr; + int res = strtol(trimmed.c_str(), &endptr, 10); // TODO: Hex too? + if (endptr == trimmed.c_str()) { + return Error(ERROR, PARSE_ERROR); + } else if (endptr == trimmed.c_str() + trimmed.size()) { + // We've parsed all of it, have we? + var->setInt(res); + } else { + assert(false); + return Error(ERROR, PARSE_ERROR); + // Something funny happened here. + } + } else if (var->_type == VAL_FLOAT) { + char *endptr; + float res = (float)strtod(trimmed.c_str(), &endptr); + if (endptr == trimmed.c_str()) { + return Error(ERROR, PARSE_ERROR); + } else if (endptr == trimmed.c_str() + trimmed.size()) { + // We've parsed all of it, have we? + var->setFloat(res); + } else { + return Error(ERROR, PARSE_ERROR); + assert(false); + // Something funny happened here. + } + } else if (var->_type == VAL_BOOL) { + Common::String str = Common::String(trimmed); + bool valAsBool; + if (Common::parseBool(trimmed, valAsBool)) { + var->setBool(valAsBool); + } else { + return Error(ERROR, PARSE_ERROR); + } + } else if (var->_type == VAL_STRING) { + var->setString(trimmed); + } else { + return Error(ERROR, NOT_YET_IMPLEMENTED); + } + return Error(SUCCESS, OK); +} + void DebuggerController::showFps(bool show) { _engine->_game->setShowFPS(show); } diff --git a/engines/wintermute/debugger/debugger_controller.h b/engines/wintermute/debugger/debugger_controller.h index 7af2a039b1..87b4945f27 100644 --- a/engines/wintermute/debugger/debugger_controller.h +++ b/engines/wintermute/debugger/debugger_controller.h @@ -83,6 +83,14 @@ public: * @brief continue execution and don't step until the current activation record is popped */ Error stepFinish(); + /** + * @brief read value for a variable accessible from within the current scope. + */ + Common::String readValue(const Common::String &name, Error *error); + /** + * @brief set value for a variable accessible from within the current scope. + */ + Error setValue(const Common::String &name, const Common::String &value, ScValue*&var); Error setSourcePath(const Common::String &sourcePath); Common::String getSourcePath() const; Listing *getListing(Error* &err); -- cgit v1.2.3