diff options
Diffstat (limited to 'engines/wintermute/debugger')
26 files changed, 1752 insertions, 0 deletions
diff --git a/engines/wintermute/debugger/breakpoint.cpp b/engines/wintermute/debugger/breakpoint.cpp new file mode 100644 index 0000000000..7f2a02b0ea --- /dev/null +++ b/engines/wintermute/debugger/breakpoint.cpp @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "breakpoint.h" +#include "engines/wintermute/base/scriptables/debuggable/debuggable_script.h" +#include "script_monitor.h" + +namespace Wintermute { + +Breakpoint::Breakpoint(const Common::String &filename, uint line, ScriptMonitor *monitor) : + _filename(filename), _line(line), _monitor(monitor), _enabled(0), _hits(0) {} + +void Breakpoint::hit(DebuggableScript *script) { + _hits++; + _monitor->onBreakpoint(this, script); +} + +Common::String Breakpoint::getFilename() const { + return _filename; +} +int Breakpoint::getLine() const { + return _line; +} +int Breakpoint::getHits() const { + return _hits; +} +bool Breakpoint::isEnabled() const { + return _enabled; +} +void Breakpoint::enable() { + _enabled = true; +} +void Breakpoint::disable() { + _enabled = false; +} + +void Breakpoint::evaluate(DebuggableScript *script) { + if (isEnabled() && + getLine() == script->_currentLine && + !getFilename().compareTo(script->_filename)) { + hit(script); + } +} + +Breakpoint::~Breakpoint() { + // Nothing to take care of in here +} + +} // End of namespace Wintermute diff --git a/engines/wintermute/debugger/breakpoint.h b/engines/wintermute/debugger/breakpoint.h new file mode 100644 index 0000000000..3757791ba3 --- /dev/null +++ b/engines/wintermute/debugger/breakpoint.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BREAKPOINT_H_ +#define BREAKPOINT_H_ +#include "common/str.h" + +namespace Wintermute { + +class ScriptMonitor; +class DebuggableScript; + +class Breakpoint { + const Common::String _filename; + const uint _line; + uint _hits; + bool _enabled; + ScriptMonitor *_monitor; + void hit(DebuggableScript *script); +public: + Breakpoint(const Common::String &filename, uint line, ScriptMonitor *monitor); + /** + * This should be called inside the interpreter; the breakpoint is evaluated + * in the context of script, and, if it is enabled and filename & line match, + * the attached ScriptMonitor is notified. + */ + void evaluate(DebuggableScript* script); + Common::String getFilename() const; + int getLine() const; + int getHits() const; + bool isEnabled() const; + void enable(); + void disable(); + virtual ~Breakpoint(); +}; + +} // End of namespace Wintermute + +#endif /* BREAKPOINT_H_ */ diff --git a/engines/wintermute/debugger/debugger_controller.cpp b/engines/wintermute/debugger/debugger_controller.cpp new file mode 100644 index 0000000000..2e021530f8 --- /dev/null +++ b/engines/wintermute/debugger/debugger_controller.cpp @@ -0,0 +1,325 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/algorithm.h" +#include "common/str.h" +#include "common/tokenizer.h" +#include "engines/wintermute/debugger.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/base_engine.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/debugger/breakpoint.h" +#include "engines/wintermute/debugger/debugger_controller.h" +#include "engines/wintermute/debugger/watch.h" +#include "engines/wintermute/debugger/listing_providers/blank_listing_provider.h" +#include "engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h" +#include "engines/wintermute/debugger/listing_providers/source_listing.h" +#define SCENGINE _engine->_game->_scEngine +#define DEBUGGER _engine->_debugger + +namespace Wintermute { + +DebuggerController::~DebuggerController() { + delete _sourceListingProvider; +} + +DebuggerController::DebuggerController(WintermuteEngine *vm) : _engine(vm) { + _sourceListingProvider = new CachedSourceListingProvider(); + clear(); +} + +bool DebuggerController::bytecodeExists(const Common::String &filename) { + uint32 compSize; + byte *compBuffer = SCENGINE->getCompiledScript(filename.c_str(), &compSize); + if (!compBuffer) { + return false; + } else { + return true; + } +} + +Error DebuggerController::addBreakpoint(const char *filename, int line) { + assert(SCENGINE); + if (bytecodeExists(filename)) { + SCENGINE->_breakpoints.push_back(new Breakpoint(filename, line, this)); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BYTECODE); + } +} + +Error DebuggerController::removeBreakpoint(uint id) { + assert(SCENGINE); + if (SCENGINE->_breakpoints.size() > id) { + SCENGINE->_breakpoints.remove_at(id); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BREAKPOINT, id); + } +} + +Error DebuggerController::disableBreakpoint(uint id) { + assert(SCENGINE); + if (SCENGINE->_breakpoints.size() > id) { + SCENGINE->_breakpoints[id]->disable(); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BREAKPOINT, id); + } +} + +Error DebuggerController::enableBreakpoint(uint id) { + assert(SCENGINE); + if (SCENGINE->_breakpoints.size() > id) { + SCENGINE->_breakpoints[id]->enable(); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BREAKPOINT, id); + } +} + +Error DebuggerController::removeWatchpoint(uint id) { + assert(SCENGINE); + if (SCENGINE->_watches.size() > id) { + SCENGINE->_watches.remove_at(id); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BREAKPOINT, id); + } +} + + +Error DebuggerController::disableWatchpoint(uint id) { + assert(SCENGINE); + if (SCENGINE->_watches.size() > id) { + SCENGINE->_watches[id]->disable(); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BREAKPOINT, id); + } +} + +Error DebuggerController::enableWatchpoint(uint id) { + assert(SCENGINE); + if (SCENGINE->_watches.size() > id) { + SCENGINE->_watches[id]->enable(); + return Error(SUCCESS, OK); + } else { + return Error(ERROR, NO_SUCH_BREAKPOINT, id); + } + +} + +Error DebuggerController::addWatch(const char *filename, const char *symbol) { + assert(SCENGINE); + if (!bytecodeExists(filename)) { + return Error(ERROR, NO_SUCH_BYTECODE, filename); + } + SCENGINE->_watches.push_back(new Watch(filename, symbol, this)); + return Error(SUCCESS, OK, "Watchpoint added"); +} + +void DebuggerController::onBreakpoint(const Breakpoint *breakpoint, DebuggableScript *script) { + _lastScript = script; + _lastLine = script->_currentLine; + DEBUGGER->notifyBreakpoint(script->dbgGetFilename().c_str(), script->_currentLine); +} + +void DebuggerController::notifyStep(DebuggableScript *script) override { + _lastScript = script; + _lastLine = script->_currentLine; + DEBUGGER->notifyStep(script->dbgGetFilename().c_str(), script->_currentLine); +} + +void DebuggerController::onWatch(const Watch *watch, DebuggableScript *script) { + _lastScript = script; // If script has changed do we still care? + _lastLine = script->_currentLine; + Common::String symbol = watch->getSymbol(); + DEBUGGER->notifyWatch(script->dbgGetFilename().c_str(), symbol.c_str(), script->resolveName(symbol)->getString()); +} + +Error DebuggerController::step() { + if (!_lastScript) { + return Error(ERROR, NOT_ALLOWED); + } + _lastScript->step(); + clear(); + return Error(SUCCESS, OK); +} + +Error DebuggerController::stepContinue() { + if (!_lastScript) { + return Error(ERROR, NOT_ALLOWED); + } + _lastScript->stepContinue(); + return Error(SUCCESS, OK); +} + +Error DebuggerController::stepFinish() { + if (!_lastScript) { + return Error(ERROR, NOT_ALLOWED); + } + _lastScript->stepFinish(); + clear(); + return Error(SUCCESS, OK); +} + +void DebuggerController::clear() { + _lastScript = nullptr; + _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); +} + +Common::Array<BreakpointInfo> DebuggerController::getBreakpoints() const { + assert(SCENGINE); + Common::Array<BreakpointInfo> breakpoints; + for (uint i = 0; i < SCENGINE->_breakpoints.size(); i++) { + BreakpointInfo bpInfo; + bpInfo._filename = SCENGINE->_breakpoints[i]->getFilename(); + bpInfo._line = SCENGINE->_breakpoints[i]->getLine(); + bpInfo._hits = SCENGINE->_breakpoints[i]->getHits(); + bpInfo._enabled = SCENGINE->_breakpoints[i]->isEnabled(); + breakpoints.push_back(bpInfo); + } + return breakpoints; +} + +Common::Array<WatchInfo> DebuggerController::getWatchlist() const { + Common::Array<WatchInfo> watchlist; + for (uint i = 0; i < SCENGINE->_watches.size(); i++) { + WatchInfo watchInfo; + watchInfo._filename = SCENGINE->_watches[i]->getFilename(); + watchInfo._symbol = SCENGINE->_watches[i]->getSymbol(); + watchlist.push_back(watchInfo); + } + return watchlist; +} + +uint32 DebuggerController::getLastLine() const { + return _lastLine; +} + +Common::String DebuggerController::getSourcePath() const { + return _sourceListingProvider->getPath(); +} + +Error DebuggerController::setSourcePath(const Common::String &sourcePath) { + ErrorCode err = _sourceListingProvider->setPath(sourcePath); + return Error((err == OK ? SUCCESS : ERROR), err); +} + +Listing* DebuggerController::getListing(Error* &error) { + delete (error); + if (_lastScript == nullptr) { + error = new Error(ERROR, NOT_ALLOWED); + return nullptr; + } + ErrorCode err; + Listing* res = _sourceListingProvider->getListing(SCENGINE->_currentScript->_filename, err); + error = new Error(err == OK ? SUCCESS : ERROR, err); + return res; +} + +Common::Array<TopEntry> DebuggerController::getTop() const { + Common::Array<TopEntry> res; + assert(SCENGINE); + for (uint i = 0; i < SCENGINE->_scripts.size(); i++) { + TopEntry entry; + entry.filename = SCENGINE->_scripts[i]->_filename; + entry.current = (SCENGINE->_scripts[i] == SCENGINE->_currentScript); + res.push_back(entry); + } + return res; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/debugger/debugger_controller.h b/engines/wintermute/debugger/debugger_controller.h new file mode 100644 index 0000000000..8c720281db --- /dev/null +++ b/engines/wintermute/debugger/debugger_controller.h @@ -0,0 +1,119 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef WINTERMUTE_DEBUGGER_ADAPTER_H +#define WINTERMUTE_DEBUGGER_ADAPTER_H + +#include "common/str.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/wintermute.h" +#include "engines/wintermute/debugger/listing_providers/source_listing_provider.h" +#include "script_monitor.h" +#include "error.h" +#include "listing.h" +namespace Wintermute { + +class ScScript; +class DebuggableScript; +class ScValue; + +struct BreakpointInfo { + Common::String _filename; + int _line; + int _hits; + bool _enabled; +}; + +struct WatchInfo { + Common::String _filename; + Common::String _symbol; + int _hits; + bool _enabled; +}; + +struct TopEntry { + bool current; + Common::String filename; + int watches; + int breakpointInfo; +}; + +class DebuggerController : public ScriptMonitor { + SourceListingProvider *_sourceListingProvider; + const WintermuteEngine *_engine; + DebuggableScript *_lastScript; + uint32 _lastDepth; + uint32 _lastLine; + void clear(); + bool bytecodeExists(const Common::String &filename); +public: + DebuggerController(WintermuteEngine *vm); + ~DebuggerController(); + Common::Array<TopEntry> getTop() const; + /** + * Get the last line # we've stopped at + */ + uint32 getLastLine() const; + Error addBreakpoint(const char *filename, int line); + Error removeBreakpoint(uint id); + Error disableBreakpoint(uint id); + Error enableBreakpoint(uint id); + Error addWatch(const char *filename, const char *symbol); + Error removeWatchpoint(uint id); + Error disableWatchpoint(uint id); + Error enableWatchpoint(uint id); + Common::Array<BreakpointInfo> getBreakpoints() const; + Common::Array<WatchInfo> getWatchlist() const; + /** + * @brief step one instruction + */ + Error step(); + /** + * @brief continue execution and don't step until next breakpoint + */ + Error stepContinue(); + /** + * @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); + void showFps(bool show); + /** + * Inherited from ScriptMonitor + */ + void onBreakpoint(const Breakpoint *breakpoint, DebuggableScript *script); + void onWatch(const Watch *watch, DebuggableScript *script); + void notifyStep(DebuggableScript *script); +}; +} + +#endif // WINTERMUTE_DEBUGGER_H diff --git a/engines/wintermute/debugger/error.cpp b/engines/wintermute/debugger/error.cpp new file mode 100644 index 0000000000..dd6e41c7bc --- /dev/null +++ b/engines/wintermute/debugger/error.cpp @@ -0,0 +1,137 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "error.h" +#include "engines/wintermute/debugger.h" + +namespace Wintermute { + +Error::Error(ErrorLevel errorLevel, + ErrorCode errorCode, + Common::String errorExtraString, + int errorExtraInt) : + _errorLevel(errorLevel), + _errorCode(errorCode), + _errorExtraInt(errorExtraInt), + _errorExtraString(errorExtraString){} + +Error::Error(ErrorLevel errorLevel, + ErrorCode errorCode, + int errorExtraInt) : + _errorLevel(errorLevel), + _errorCode(errorCode), + _errorExtraInt(errorExtraInt), + _errorExtraString(""){} + +Error::Error(ErrorLevel errorLevel, + ErrorCode errorCode) : + _errorLevel(errorLevel), + _errorCode(errorCode), + _errorExtraInt(0), + _errorExtraString(""){} + +Error::Error(ErrorLevel errorLevel, + ErrorCode errorCode, + Common::String errorExtraString) : + _errorLevel(errorLevel), + _errorCode(errorCode), + _errorExtraInt(0), + _errorExtraString(errorExtraString){} + +ErrorLevel Error::getErrorLevel() const { + return _errorLevel; +} + +ErrorCode Error::getErrorCode() const { + return _errorCode; +} + +Common::String Error::getErrorLevelStr() const { + switch (this->_errorLevel) { + case SUCCESS: + return "SUCCESS"; + break; + case NOTICE: + return "NOTICE"; + break; + case WARNING: + return "WARNING"; + break; + case ERROR: + return "ERROR"; + break; + } + return "SUCCESS"; +} + +Common::String Error::getErrorDisplayStr() const { + + Common::String errorStr; + + switch (this->_errorLevel) { + case SUCCESS: + errorStr += "OK!"; + break; + case WARNING: + errorStr += "WARNING: "; + break; + case ERROR: + errorStr += "ERROR: "; + break; + case NOTICE: + errorStr += "NOTICE: "; + break; + default: + // Um... + break; + } + + switch (this->_errorCode) { + case OK: + break; + case NOT_ALLOWED: + errorStr += "Could not execute requested operation. This is allowed only after a break."; + break; + case NO_SUCH_SOURCE: + errorStr += Common::String::format("Can't find source for %s. Double check you source path.", this->_errorExtraString.c_str()); + break; + case NO_SUCH_BYTECODE: + errorStr += Common::String::format("No such script: %s. Can't find bytecode; double check the script path.", this->_errorExtraString.c_str()); + break; + case SOURCE_PATH_NOT_SET: + errorStr += Common::String("Source path not set. Source won't be displayed. Try 'help " + Common::String(SET_PATH_CMD) + "'."); + break; + case NO_SUCH_BREAKPOINT: + errorStr += Common::String::format("No such breakpoint %d.", this->_errorExtraInt); + break; + case WRONG_TYPE: + errorStr += Common::String::format("Incompatible type: %s.", this->_errorExtraString.c_str()); + break; + default: + errorStr += Common::String::format("Unknown condition %d", this->_errorCode); + break; + } + + return errorStr; +} + +} // End namespace Wintermute diff --git a/engines/wintermute/debugger/error.h b/engines/wintermute/debugger/error.h new file mode 100644 index 0000000000..4e5b973445 --- /dev/null +++ b/engines/wintermute/debugger/error.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ERROR_H_ +#define ERROR_H_ + +#include "common/str.h" + +namespace Wintermute { + +enum ErrorLevel { + SUCCESS, + NOTICE, + WARNING, + ERROR +}; + +enum ErrorCode { + OK, + NO_SUCH_SOURCE, + COULD_NOT_OPEN, + NO_SUCH_LINE, + NOT_ALLOWED, + NO_SUCH_BYTECODE, + DUPLICATE_BREAKPOINT, + NO_SUCH_BREAKPOINT, + WRONG_TYPE, + PARSE_ERROR, + NOT_YET_IMPLEMENTED, + SOURCE_PATH_NOT_SET, + ILLEGAL_PATH, + UNKNOWN_ERROR +}; + + +class Error { + const ErrorLevel _errorLevel; + const ErrorCode _errorCode; + const int _errorExtraInt; + const Common::String _errorExtraString; +public: + Error(ErrorLevel, ErrorCode); + Error(ErrorLevel, ErrorCode, int errorExtraInt); + Error(ErrorLevel, ErrorCode, Common::String errorExtraString); + Error(ErrorLevel, ErrorCode, Common::String errorExtraString, int errorExtraInt); + ErrorLevel getErrorLevel() const; + ErrorCode getErrorCode() const; + Common::String getErrorLevelStr() const; + Common::String getErrorDisplayStr() const; +}; + +} // End of namespace Wintermute + +#endif /* ERROR_H_ */ diff --git a/engines/wintermute/debugger/listing.cpp b/engines/wintermute/debugger/listing.cpp new file mode 100644 index 0000000000..b8707fb842 --- /dev/null +++ b/engines/wintermute/debugger/listing.cpp @@ -0,0 +1,46 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "listing.h" +#include "common/array.h" + +namespace Wintermute { + +Common::Array<ListingLine> Listing::getLines(uint begin, uint end) { + assert(begin <= end); + Common::Array<ListingLine> ret; + for (uint i = begin; i <= end; i++) { + ListingLine listingline; + listingline.number = i; + listingline.text = getLine(i); + ret.push_back(listingline); + } + return ret; +} + +Common::Array<ListingLine> Listing::getLines(uint centre, uint before, uint after) { + uint begin = MAX(centre - before, (uint)1); // Line numbers start from 1 + uint end = MIN(centre + after, (uint)(getLength() - 1)); // Line numbers start from 1 + return getLines(begin, end); +} + +} // End of namespace Wintermute diff --git a/engines/wintermute/debugger/listing.h b/engines/wintermute/debugger/listing.h new file mode 100644 index 0000000000..2ef21b702d --- /dev/null +++ b/engines/wintermute/debugger/listing.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LISTING_H_ +#define LISTING_H_ + +#include "common/array.h" + + +namespace Common { + +class String; + +} + +namespace Wintermute { + +struct ListingLine { + uint number; + Common::String text; +}; + +class Listing { +public: + virtual ~Listing() {}; + /** + * @brief get the listing length (in lines) + */ + virtual uint getLength() const = 0; + /** + * @brief return a specific line from a listing + * @param n line number + */ + virtual Common::String getLine(uint n) = 0; + /** + * @brief shorthand to get a lump of lines instead of calling getLine a number of times + * Generally you won't need to redefine these + */ + virtual Common::Array<ListingLine> getLines(uint centre, uint before, uint after); + virtual Common::Array<ListingLine> getLines(uint beginning, uint end); +}; + +} // End of namespace Wintermute + +#endif /* LISTING_H_ */ diff --git a/engines/wintermute/debugger/listing_provider.h b/engines/wintermute/debugger/listing_provider.h new file mode 100644 index 0000000000..b5ea23e49b --- /dev/null +++ b/engines/wintermute/debugger/listing_provider.h @@ -0,0 +1,42 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LISTING_PROVIDER_H_ +#define LISTING_PROVIDER_H_ + +#include "listing.h" +#include "engines/wintermute/debugger/error.h" + +namespace Wintermute { + +class ListingProvider { +public: + virtual ~ListingProvider() {}; + /** + * Get a listing. When implementing this, the result should be safe to delete for the caller. + */ + virtual Listing *getListing(const Common::String &filename, ErrorCode &error) = 0; +}; + +} // End of namespace Wintermute + +#endif /* LISTING_PROVIDER_H_ */ diff --git a/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp new file mode 100644 index 0000000000..30d29ee23e --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp @@ -0,0 +1,92 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "basic_source_listing_provider.h" +#include "engines/wintermute/base/base_file_manager.h" + +namespace Wintermute { +BasicSourceListingProvider::BasicSourceListingProvider() : _fsDirectory(nullptr) { +} + +BasicSourceListingProvider::~BasicSourceListingProvider() { +} + +SourceListing *BasicSourceListingProvider::getListing(const Common::String &filename, ErrorCode &_err) { + _err = OK; + if (!_fsDirectory) { + _err = SOURCE_PATH_NOT_SET; + return nullptr; + }; + + Common::String unixFilename; + + for (uint i = 0; i < filename.size(); i++) { + if (filename[i] == '\\') { + unixFilename.insertChar('/', unixFilename.size()); + } else { + unixFilename.insertChar(filename[i], unixFilename.size()); + } + } + + Common::SeekableReadStream *file = _fsDirectory->createReadStreamForMember(unixFilename); + Common::Array<Common::String> strings; + + if (!file) { + _err = NO_SUCH_SOURCE; + } else { + if (file->err()) { + _err = UNKNOWN_ERROR; + } + while (!file->eos()) { + strings.push_back(file->readLine()); + if (file->err()) { + _err = UNKNOWN_ERROR; + } + } + } + + if (_err == OK) { + return new SourceListing(strings); + } else { + return nullptr; + } +} + +ErrorCode BasicSourceListingProvider::setPath(const Common::String &path) { + if (path == "") + return ILLEGAL_PATH; + delete _fsDirectory; + Common::FSNode node(path); + if (node.exists() && node.isDirectory()) { + _fsDirectory = new Common::FSDirectory(node, 64); + return OK; + } else { + return COULD_NOT_OPEN; + } +} + +Common::String BasicSourceListingProvider::getPath() const { + if (!_fsDirectory) return ""; + return _fsDirectory->getFSNode().getPath(); +} + +} diff --git a/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h new file mode 100644 index 0000000000..e242205578 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BASIC_SOURCE_LISTING_PROVIDER_H_ +#define BASIC_SOURCE_LISTING_PROVIDER_H_ + +#include "engines/wintermute/debugger/listing_provider.h" +#include "source_listing_provider.h" +#include "source_listing.h" +#include "common/fs.h" + +namespace Wintermute { + +class BasicSourceListingProvider : public SourceListingProvider { + Common::FSDirectory *_fsDirectory; +public: + BasicSourceListingProvider(); + virtual ~BasicSourceListingProvider(); + SourceListing *getListing(const Common::String &filename, ErrorCode &err); + ErrorCode setPath(const Common::String &path); + Common::String getPath() const; +}; + +} +#endif /* BASIC_SOURCE_LISTING_PROVIDER_H_ */ diff --git a/engines/wintermute/debugger/listing_providers/blank_listing.cpp b/engines/wintermute/debugger/listing_providers/blank_listing.cpp new file mode 100644 index 0000000000..928c91dc7f --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/blank_listing.cpp @@ -0,0 +1,38 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "blank_listing.h" +#include "limits.h" + +namespace Wintermute { + +BlankListing::BlankListing(const Common::String filename) : _filename(filename) {} + +uint BlankListing::getLength() const { return UINT_MAX; } + +Common::String BlankListing::getLine(uint n) { + return "<no source for " + _filename + " ~~~ line: " + Common::String::format("%d", n) + ">"; +} +BlankListing::~BlankListing() {} + +} + diff --git a/engines/wintermute/debugger/listing_providers/blank_listing.h b/engines/wintermute/debugger/listing_providers/blank_listing.h new file mode 100644 index 0000000000..8c5ea19aa7 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/blank_listing.h @@ -0,0 +1,39 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BLANK_LISTING_H_ +#define BLANK_LISTING_H_ +#include "engines/wintermute/debugger/listing.h" + +namespace Wintermute { +class BlankListing : public Listing { + const Common::String _filename; +public: + BlankListing(const Common::String filename); + virtual ~BlankListing(); + virtual uint getLength() const; + virtual Common::String getLine(uint n); +}; + +} // End of namespace Wintermute + +#endif diff --git a/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp b/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp new file mode 100644 index 0000000000..58e9e7e156 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp @@ -0,0 +1,35 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "blank_listing_provider.h" +#include "blank_listing.h" +namespace Wintermute { +BlankListingProvider::BlankListingProvider() {} + +BlankListingProvider::~BlankListingProvider() {} + +Listing *BlankListingProvider::getListing(const Common::String &filename, ErrorCode &error) { + Listing *l = new BlankListing(filename); + error = OK; + return l; // Delete this sometime please. +} +} // End of namespace Wintermute diff --git a/engines/wintermute/debugger/listing_providers/blank_listing_provider.h b/engines/wintermute/debugger/listing_providers/blank_listing_provider.h new file mode 100644 index 0000000000..e583455c92 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/blank_listing_provider.h @@ -0,0 +1,38 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BLANK_LISTING_PROVIDER_H_ +#define BLANK_LISTING_PROVIDER_H_ + +#include "engines/wintermute/debugger/listing.h" +#include "engines/wintermute/debugger/listing_provider.h" +#include "engines/wintermute/debugger/error.h" + +namespace Wintermute { +class BlankListingProvider : public ListingProvider { +public: + BlankListingProvider(); + ~BlankListingProvider(); + Listing *getListing(const Common::String &filename, ErrorCode &error); +}; +} // End of namespace Wintermute +#endif diff --git a/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp new file mode 100644 index 0000000000..20fe708380 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "cached_source_listing_provider.h" +#include "basic_source_listing_provider.h" +#include "blank_listing_provider.h" +#include "source_listing.h" + +namespace Wintermute { + +CachedSourceListingProvider::CachedSourceListingProvider() { + _sourceListingProvider = new BasicSourceListingProvider(); + _fallbackListingProvider = new BlankListingProvider(); +} + +CachedSourceListingProvider::~CachedSourceListingProvider() { + delete _sourceListingProvider; + delete _fallbackListingProvider; + for (Common::HashMap<Common::String, SourceListing*>::iterator it = _cached.begin(); + it != _cached.end(); it++) { + delete (it->_value); + } +} + +Listing *CachedSourceListingProvider::getListing(const Common::String &filename, Wintermute::ErrorCode &error) { + if (_cached.contains(filename)) { + error = OK; + SourceListing *copy = new SourceListing(*_cached.getVal(filename)); + return copy; + } else { + ErrorCode inner; + SourceListing *res = _sourceListingProvider->getListing(filename, inner); + if (inner == OK) { + SourceListing *copy = new SourceListing(*res); + _cached.setVal(filename, copy); // The cached copy is deleted on destruction + return res; + } else { + delete res; + return _fallbackListingProvider->getListing(filename, error); + } + } +} + +void CachedSourceListingProvider::invalidateCache() { + for (Common::HashMap<Common::String, SourceListing*>::iterator it = _cached.begin(); + it != _cached.end(); it++) { + delete (it->_value); + } + _cached.clear(); +} + +ErrorCode CachedSourceListingProvider::setPath(const Common::String &path) { + invalidateCache(); + return _sourceListingProvider->setPath(path); +} + +Common::String CachedSourceListingProvider::getPath() const { + return _sourceListingProvider->getPath(); +} + +} // End of namespace Wintermute diff --git a/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h new file mode 100644 index 0000000000..6e4925f2b4 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef CACHED_LISTING_PROVIDER_H_ +#define CACHED_LISTING_PROVIDER_H_ + +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "engines/wintermute/debugger/error.h" +#include "source_listing_provider.h" + +namespace Wintermute { + +class BasicSourceListingProvider; +class BlankListingProvider; +class Listing; + +class CachedSourceListingProvider : public SourceListingProvider { + BasicSourceListingProvider *_sourceListingProvider; + BlankListingProvider *_fallbackListingProvider; + Common::HashMap<Common::String, SourceListing *> _cached; + void invalidateCache(); +public: + CachedSourceListingProvider(); + virtual ~CachedSourceListingProvider(); + ErrorCode setPath(const Common::String &path); + Common::String getPath() const; + Listing *getListing(const Common::String &filename, ErrorCode &err); +}; + +} // End of namespace Wintermute + +#endif /* CACHED_LISTING_PROVIDER_H_ */ diff --git a/engines/wintermute/debugger/listing_providers/source_listing.cpp b/engines/wintermute/debugger/listing_providers/source_listing.cpp new file mode 100644 index 0000000000..ff81e20f02 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/source_listing.cpp @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "source_listing.h" + +namespace Wintermute { + +SourceListing::SourceListing(const Common::Array<Common::String> &strings) : _strings(strings) {} + +SourceListing::~SourceListing() {} + +uint SourceListing::getLength() const { + return _strings.size(); +} + +Common::String SourceListing::getLine(uint n) { + uint index = n - 1; // Line numbers start from 1, arrays from 0 + /* + * Clients should not ask for a line number that + * is not in the source file. + * 0 is undefined, n - 1 is undefined. + * It is easy for the client to check that n > 0 + * and n < getLength(), so it should just not happen. + * We return '^', after vim, to misbehaving clients. + */ + if (n == 0) { + return Common::String("^"); + } + if (index < getLength()) { + return _strings[index]; + } else { + return Common::String("^"); + } +} + +} // End of namespace Wintermute + + diff --git a/engines/wintermute/debugger/listing_providers/source_listing.h b/engines/wintermute/debugger/listing_providers/source_listing.h new file mode 100644 index 0000000000..bf08578218 --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/source_listing.h @@ -0,0 +1,37 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SOURCE_LISTING_H_ +#define SOURCE_LISTING_H_ +#include "engines/wintermute/debugger/listing.h" + +namespace Wintermute { +class SourceListing : public Listing { + const Common::Array<Common::String> _strings; +public: + SourceListing(const Common::Array<Common::String> &strings); + virtual ~SourceListing(); + virtual uint getLength() const; + virtual Common::String getLine(uint n); +}; +} +#endif /* DUMMY_LISTING_H_ */ diff --git a/engines/wintermute/debugger/listing_providers/source_listing_provider.h b/engines/wintermute/debugger/listing_providers/source_listing_provider.h new file mode 100644 index 0000000000..18f05e56ed --- /dev/null +++ b/engines/wintermute/debugger/listing_providers/source_listing_provider.h @@ -0,0 +1,49 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SOURCE_LISTING_PROVIDER_H_ +#define SOURCE_LISTING_PROVIDER_H_ + +#include "engines/wintermute/debugger/error.h" +#include "engines/wintermute/debugger/listing_provider.h" +#include "common/str.h" + +namespace Wintermute { + +class SourceListing; +class Listing; + +class SourceListingProvider : ListingProvider { +public: + virtual ~SourceListingProvider() {}; + /** + * Get a listing. When implementing this, the result should be safe to delete for the caller. + */ + virtual Listing *getListing(const Common::String &filename, ErrorCode &err) = 0; + virtual ErrorCode setPath(const Common::String &path) = 0; + virtual Common::String getPath() const = 0; + +}; + +} // End of namespace Wintermute + +#endif /* SOURCE_LISTING_PROVIDER_H_ */ diff --git a/engines/wintermute/debugger/script_monitor.cpp b/engines/wintermute/debugger/script_monitor.cpp new file mode 100644 index 0000000000..2e9370c923 --- /dev/null +++ b/engines/wintermute/debugger/script_monitor.cpp @@ -0,0 +1,26 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "script_monitor.h" + +namespace Wintermute { +} diff --git a/engines/wintermute/debugger/script_monitor.h b/engines/wintermute/debugger/script_monitor.h new file mode 100644 index 0000000000..e9559e2ade --- /dev/null +++ b/engines/wintermute/debugger/script_monitor.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCRIPTMONITOR_H_ +#define SCRIPTMONITOR_H_ + +namespace Wintermute { + +class DebuggableScript; +class Breakpoint; +class Watch; + +class ScriptMonitor { +public: + + virtual ~ScriptMonitor() {}; + virtual void notifyStep(DebuggableScript* script) = 0; + virtual void onBreakpoint(const Breakpoint* breakpoint, DebuggableScript* script) = 0; + virtual void onWatch(const Watch* watch, DebuggableScript* script) = 0; +}; + +} // End of namespace Wintermute + +#endif /* SCRIPTMONITOR_H_ */ diff --git a/engines/wintermute/debugger/watch.cpp b/engines/wintermute/debugger/watch.cpp new file mode 100644 index 0000000000..410756fdc8 --- /dev/null +++ b/engines/wintermute/debugger/watch.cpp @@ -0,0 +1,42 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "watch.h" +#include "watch_instance.h" +#include "script_monitor.h" + +namespace Wintermute { + +Watch::Watch(const Common::String &filename, const Common::String &symbol, ScriptMonitor* monitor) : _enabled(false), _filename(filename), _symbol(symbol), _monitor(monitor) {} + +Watch::~Watch() { /* Nothing to take care of in here */ } + +void Watch::trigger(WatchInstance* instance) { + _monitor->onWatch(this, instance->_script); +} + +Common::String Watch::getFilename() const { return _filename; } +Common::String Watch::getSymbol() const { return _symbol; } +bool Watch::isEnabled() const { return _enabled; } +void Watch::enable() { _enabled = true; } +void Watch::disable() { _enabled = false; } +} diff --git a/engines/wintermute/debugger/watch.h b/engines/wintermute/debugger/watch.h new file mode 100644 index 0000000000..cbffe43b41 --- /dev/null +++ b/engines/wintermute/debugger/watch.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef WATCH_H_ +#define WATCH_H_ + +#include "common/str.h" + +namespace Wintermute { + +class ScValue; +class ScScript; +class WatchInstance; +class ScriptMonitor; + +class Watch { + const Common::String _filename; + const Common::String _symbol; + int _enabled; + ScriptMonitor *_monitor; +public: + Watch(const Common::String &filename, const Common::String &symbol, ScriptMonitor*); + Common::String getFilename() const; + Common::String getSymbol() const; + bool isEnabled() const; + void enable(); + void disable(); + void trigger(WatchInstance*); + virtual ~Watch(); +}; +} +#endif /* WATCH_H_ */ diff --git a/engines/wintermute/debugger/watch_instance.cpp b/engines/wintermute/debugger/watch_instance.cpp new file mode 100644 index 0000000000..2d31221ad4 --- /dev/null +++ b/engines/wintermute/debugger/watch_instance.cpp @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "watch_instance.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/debuggable/debuggable_script.h" +#include "engines/wintermute/debugger/watch.h" + +namespace Wintermute { + +WatchInstance::WatchInstance(Watch* watch, DebuggableScript* script) : _watch(watch), _script(script), _lastValue(nullptr) {} +WatchInstance::~WatchInstance() { delete _lastValue; } + +void WatchInstance::evaluate() { + if (_watch->isEnabled()) { + if (!_watch->getFilename().compareTo(_script->_filename)) { + + if(_lastValue == nullptr) { + _lastValue = new ScValue(_script->_gameRef); + // ^^ This here is NULL by default + } + ScValue* currentValue = _script->resolveName(_watch->getSymbol()); + if(ScValue::compare( + currentValue, + _lastValue + )) { + _lastValue->copy(currentValue); + _watch->trigger(this); + } + delete currentValue; + } + } +} +} // End of namespace Wintermute diff --git a/engines/wintermute/debugger/watch_instance.h b/engines/wintermute/debugger/watch_instance.h new file mode 100644 index 0000000000..84fb62968d --- /dev/null +++ b/engines/wintermute/debugger/watch_instance.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef WATCH_INSTANCE_H_ +#define WATCH_INSTANCE_H_ + +namespace Wintermute { +class Watch; +class ScValue; +class DebuggableScript; + +class WatchInstance { + Watch* _watch; + ScValue *_lastValue; + DebuggableScript* _script; +public: + WatchInstance (Watch* watch, DebuggableScript* script); + ~WatchInstance(); + void evaluate(); +friend class DebuggableScript; +friend class Watch; +}; +} // End of namespace Wintermute + +#endif /* WATCH_INSTANCE_H_ */ |