aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2006-09-16 16:58:27 +0000
committerMax Horn2006-09-16 16:58:27 +0000
commit919092e5fcd0389b4cbd862e9e8cceab202e6741 (patch)
tree7d9c8f643191812bb1eb24f2e7cc2e67586149d5 /common
parent1add07becae0179e026a90924b419b74ffb1078f (diff)
downloadscummvm-rg350-919092e5fcd0389b4cbd862e9e8cceab202e6741.tar.gz
scummvm-rg350-919092e5fcd0389b4cbd862e9e8cceab202e6741.tar.bz2
scummvm-rg350-919092e5fcd0389b4cbd862e9e8cceab202e6741.zip
Overhaul of the debugger code
* Moved Common::Debuggger to GUI::Debugger (mainly to satisfy linker restrictions) * Change the base Debugger class to *not* be a template class anymore; instead, a thin (template based) wrapper class is used to hook up debugger commands * Removed duplicate Cmd_Exit and Cmd_Help methods in favor of a single version of each in GUI::Debugger * New Cmd_Help doesn't word wrap after 39/78 chars, but rather queries the console to determine when to wrap * Debugger::preEnter and postEnter aren't pure virtual anymore svn-id: r23890
Diffstat (limited to 'common')
-rw-r--r--common/debugger.cpp411
-rw-r--r--common/debugger.h110
2 files changed, 0 insertions, 521 deletions
diff --git a/common/debugger.cpp b/common/debugger.cpp
deleted file mode 100644
index e0ad40eea9..0000000000
--- a/common/debugger.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001-2006 The ScummVM project
- *
- * 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.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "common/debugger.h"
-#include "common/system.h"
-
-#if USE_CONSOLE
- #include "gui/console.h"
-#endif
-
-namespace Common {
-
-template <class T>
-Debugger<T>::Debugger() {
- _frame_countdown = 0;
- _dvar_count = 0;
- _dcmd_count = 0;
- _detach_now = false;
- _isAttached = false;
- _errStr = NULL;
- _firstTime = true;
- _debuggerDialog = new GUI::ConsoleDialog(1.0, 0.67F);
- _debuggerDialog->setInputCallback(debuggerInputCallback, this);
- _debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
-
- DCmd_Register("debugflag_list", &Debugger<T>::Cmd_DebugFlagsList);
- DCmd_Register("debugflag_enable", &Debugger<T>::Cmd_DebugFlagEnable);
- DCmd_Register("debugflag_disable", &Debugger<T>::Cmd_DebugFlagDisable);
-}
-
-template <class T>
-Debugger<T>::~Debugger() {
- delete _debuggerDialog;
-}
-
-
-// Initialisation Functions
-template <class T>
-int Debugger<T>::DebugPrintf(const char *format, ...) {
- va_list argptr;
-
- va_start(argptr, format);
- int count;
-#if USE_CONSOLE
- count = _debuggerDialog->vprintf(format, argptr);
-#else
- count = ::vprintf(format, argptr);
-#endif
- va_end (argptr);
- return count;
-}
-
-#ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :)
-template <class T>
-void Debugger<T>::attach(const char *entry) {
-
- g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
-
- if (entry) {
- _errStr = strdup(entry);
- }
-
- _frame_countdown = 1;
- _detach_now = false;
- _isAttached = true;
-}
-
-template <class T>
-void Debugger<T>::detach() {
- g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
-
- _detach_now = false;
- _isAttached = false;
-}
-
-// Temporary execution handler
-template <class T>
-void Debugger<T>::onFrame() {
- if (_frame_countdown == 0)
- return;
- --_frame_countdown;
-
- if (!_frame_countdown) {
-
- preEnter();
- enter();
- postEnter();
-
- // Detach if we're finished with the debugger
- if (_detach_now)
- detach();
- }
-}
-#endif // of ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :)
-
-// Main Debugger Loop
-template <class T>
-void Debugger<T>::enter() {
-#if USE_CONSOLE
- if (_firstTime) {
- DebugPrintf("Debugger started, type 'exit' to return to the game.\n");
- DebugPrintf("Type 'help' to see a little list of commands and variables.\n");
- _firstTime = false;
- }
-
- if (_errStr) {
- DebugPrintf("ERROR: %s\n\n", _errStr);
- free(_errStr);
- _errStr = NULL;
- }
-
- _debuggerDialog->runModal();
-#else
- // TODO: compared to the console input, this here is very bare bone.
- // For example, no support for tab completion and no history. At least
- // we should re-add (optional) support for the readline library.
- // Or maybe instead of choosing between a console dialog and stdio,
- // we should move that choice into the ConsoleDialog class - that is,
- // the console dialog code could be #ifdef'ed to not print to the dialog
- // but rather to stdio. This way, we could also reuse the command history
- // and tab completion of the console. It would still require a lot of
- // work, but at least no dependency on a 3rd party library...
-
- printf("Debugger entered, please switch to this console for input.\n");
-
- int i;
- char buf[256];
-
- do {
- printf("debug> ");
- if (!fgets(buf, sizeof(buf), stdin))
- return;
-
- i = strlen(buf);
- while (i > 0 && buf[i - 1] == '\n')
- buf[--i] = 0;
-
- if (i == 0)
- continue;
- } while (RunCommand(buf));
-
-#endif
-}
-
-// Command execution loop
-template <class T>
-bool Debugger<T>::RunCommand(const char *inputOrig) {
- int i = 0, num_params = 0;
- const char *param[256];
- char *input = strdup(inputOrig); // One of the rare occasions using strdup is OK (although avoiding strtok might be more elegant here).
-
- // Parse out any params
- char *tok = strtok(input, " ");
- if (tok) {
- do {
- param[num_params++] = tok;
- } while ((tok = strtok(NULL, " ")) != NULL);
- } else {
- param[num_params++] = input;
- }
-
- for (i=0; i < _dcmd_count; i++) {
- if (!strcmp(_dcmds[i].name, param[0])) {
- bool result = (((T *)this)->*_dcmds[i].function)(num_params, param);
- free(input);
- return result;
- }
- }
-
- // It's not a command, so things get a little tricky for variables. Do fuzzy matching to ignore things like subscripts.
- for (i = 0; i < _dvar_count; i++) {
- if (!strncmp(_dvars[i].name, param[0], strlen(_dvars[i].name))) {
- if (num_params > 1) {
- // Alright, we need to check the TYPE of the variable to deref and stuff... the array stuff is a bit ugly :)
- switch (_dvars[i].type) {
- // Integer
- case DVAR_BYTE:
- *(byte *)_dvars[i].variable = atoi(param[1]);
- DebugPrintf("byte%s = %d\n", param[0], *(byte *)_dvars[i].variable);
- break;
- case DVAR_INT:
- *(int32 *)_dvars[i].variable = atoi(param[1]);
- DebugPrintf("(int)%s = %d\n", param[0], *(int32 *)_dvars[i].variable);
- break;
- // Integer Array
- case DVAR_INTARRAY: {
- char *chr = (char *)strchr(param[0], '[');
- if (!chr) {
- DebugPrintf("You must access this array as %s[element]\n", param[0]);
- } else {
- int element = atoi(chr+1);
- int32 *var = *(int32 **)_dvars[i].variable;
- if (element >= _dvars[i].optional) {
- DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional);
- } else {
- var[element] = atoi(param[1]);
- DebugPrintf("(int)%s = %d\n", param[0], var[element]);
- }
- }
- }
- break;
- default:
- DebugPrintf("Failed to set variable %s to %s - unknown type\n", _dvars[i].name, param[1]);
- break;
- }
- } else {
- // And again, type-dependent prints/defrefs. The array one is still ugly.
- switch (_dvars[i].type) {
- // Integer
- case DVAR_BYTE:
- DebugPrintf("(byte)%s = %d\n", param[0], *(const byte *)_dvars[i].variable);
- break;
- case DVAR_INT:
- DebugPrintf("(int)%s = %d\n", param[0], *(const int32 *)_dvars[i].variable);
- break;
- // Integer array
- case DVAR_INTARRAY: {
- const char *chr = strchr(param[0], '[');
- if (!chr) {
- DebugPrintf("You must access this array as %s[element]\n", param[0]);
- } else {
- int element = atoi(chr+1);
- const int32 *var = *(const int32 **)_dvars[i].variable;
- if (element >= _dvars[i].optional) {
- DebugPrintf("%s is out of range (array is %d elements big)\n", param[0], _dvars[i].optional);
- } else {
- DebugPrintf("(int)%s = %d\n", param[0], var[element]);
- }
- }
- }
- break;
- // String
- case DVAR_STRING:
- DebugPrintf("(string)%s = %s\n", param[0], ((Common::String *)_dvars[i].variable)->c_str());
- break;
- default:
- DebugPrintf("%s = (unknown type)\n", param[0]);
- break;
- }
- }
-
- free(input);
- return true;
- }
- }
-
- DebugPrintf("Unknown command or variable\n");
- free(input);
- return true;
-}
-
-// returns true if something has been completed
-// completion has to be delete[]-ed then
-template <class T>
-bool Debugger<T>::TabComplete(const char *input, char*& completion) {
- // very basic tab completion
- // for now it just supports command completions
-
- // adding completions of command parameters would be nice (but hard) :-)
- // maybe also give a list of possible command completions?
- // (but this will require changes to console)
-
- if (strchr(input, ' '))
- return false; // already finished the first word
-
- unsigned int inputlen = strlen(input);
-
- unsigned int matchlen = 0;
- char match[30]; // the max. command name is 30 chars
-
- for (int i = 0; i < _dcmd_count; i++) {
- if (!strncmp(_dcmds[i].name, input, inputlen)) {
- unsigned int commandlen = strlen(_dcmds[i].name);
- if (commandlen == inputlen) { // perfect match
- return false;
- }
- if (commandlen > inputlen) { // possible match
- // no previous match
- if (matchlen == 0) {
- strcpy(match, _dcmds[i].name + inputlen);
- matchlen = commandlen - inputlen;
- } else {
- // take common prefix of previous match and this command
- unsigned int j;
- for (j = 0; j < matchlen; j++) {
- if (match[j] != _dcmds[i].name[inputlen + j]) break;
- }
- matchlen = j;
- }
- if (matchlen == 0)
- return false;
- }
- }
- }
- if (matchlen == 0)
- return false;
-
- completion = new char[matchlen + 1];
- memcpy(completion, match, matchlen);
- completion[matchlen] = 0;
- return true;
-}
-
-// Variable registration function
-template <class T>
-void Debugger<T>::DVar_Register(const char *varname, void *pointer, int type, int optional) {
- assert(_dvar_count < ARRAYSIZE(_dvars));
- strcpy(_dvars[_dvar_count].name, varname);
- _dvars[_dvar_count].type = type;
- _dvars[_dvar_count].variable = pointer;
- _dvars[_dvar_count].optional = optional;
-
- _dvar_count++;
-}
-
-// Command registration function
-template <class T>
-void Debugger<T>::DCmd_Register(const char *cmdname, DebugProc pointer) {
- assert(_dcmd_count < ARRAYSIZE(_dcmds));
- strcpy(_dcmds[_dcmd_count].name, cmdname);
- _dcmds[_dcmd_count].function = pointer;
-
- _dcmd_count++;
-}
-
-template <class T>
-bool Debugger<T>::Cmd_DebugFlagsList(int argc, const char **argv) {
- const Common::Array<Common::EngineDebugLevel> &debugLevels = Common::listSpecialDebugLevels();
-
- DebugPrintf("Engine debug levels:\n");
- DebugPrintf("--------------------\n");
- if (!debugLevels.size()) {
- DebugPrintf("No engine debug levels\n");
- return true;
- }
- for (uint i = 0; i < debugLevels.size(); ++i) {
- DebugPrintf("'%s' - Description: %s\n", debugLevels[i].option.c_str(), debugLevels[i].description.c_str());
- }
- DebugPrintf("\n");
- return true;
-}
-
-template <class T>
-bool Debugger<T>::Cmd_DebugFlagEnable(int argc, const char **argv) {
- if (argc < 2) {
- DebugPrintf("debugflag_enable <flag>\n");
- } else {
- if (Common::enableSpecialDebugLevel(argv[1])) {
- DebugPrintf("Enabled debug flag '%s'\n", argv[1]);
- } else {
- DebugPrintf("Failed to enable debug flag '%s'\n", argv[1]);
- }
- }
- return true;
-}
-
-template <class T>
-bool Debugger<T>::Cmd_DebugFlagDisable(int argc, const char **argv) {
- if (argc < 2) {
- DebugPrintf("debugflag_disable <flag>\n");
- } else {
- if (Common::disableSpecialDebugLevel(argv[1])) {
- DebugPrintf("Disabled debug flag '%s'\n", argv[1]);
- } else {
- DebugPrintf("Failed to disable debug flag '%s'\n", argv[1]);
- }
- }
- return true;
-}
-
-// Console handler
-#if USE_CONSOLE
-template <class T>
-bool Debugger<T>::debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon) {
- Debugger *debugger = (Debugger *)refCon;
-
- return debugger->RunCommand(input);
-}
-
-
-template <class T>
-bool Debugger<T>::debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon) {
- Debugger *debugger = (Debugger *)refCon;
-
- return debugger->TabComplete(input, completion);
-}
-
-#endif
-
-} // End of namespace Common
diff --git a/common/debugger.h b/common/debugger.h
deleted file mode 100644
index 25ddff8ac2..0000000000
--- a/common/debugger.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2002-2006 The ScummVM project
- *
- * 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.
- *
- * $URL$
- * $Id$
- */
-
-#ifndef COMMON_DEBUGGER_H
-#define COMMON_DEBUGGER_H
-
-namespace GUI {
- class ConsoleDialog;
-}
-
-namespace Common {
-
-// Choose between text console or ScummConsole
-#define USE_CONSOLE 1
-
-template <class T>
-class Debugger {
-public:
- Debugger();
- virtual ~Debugger();
-
- int DebugPrintf(const char *format, ...);
-
-#ifndef __SYMBIAN32__ // gcc/UIQ doesn't like the debugger code for some reason? Actually get a cc1plus core dump here :)
- virtual void onFrame();
-
- virtual void attach(const char *entry = 0);
-#else
- void onFrame() {}
- void attach(const char *entry = 0) {}
-#endif
- bool isAttached() const { return _isAttached; }
-
-protected:
- typedef bool (T::*DebugProc)(int argc, const char **argv);
-
- enum {
- DVAR_BYTE,
- DVAR_INT,
- DVAR_BOOL,
- DVAR_INTARRAY,
- DVAR_STRING
- };
-
- struct DVar {
- char name[30];
- void *variable;
- int type, optional;
- };
-
- struct DCmd {
- char name[30];
- DebugProc function;
- };
-
- int _frame_countdown, _dvar_count, _dcmd_count;
- DVar _dvars[256];
- DCmd _dcmds[256];
- bool _detach_now;
-
-private:
- bool _isAttached;
- char *_errStr;
- bool _firstTime;
- GUI::ConsoleDialog *_debuggerDialog;
-
-protected:
- void detach();
- void enter();
-
- virtual void preEnter() = 0;
- virtual void postEnter() = 0;
-
- bool RunCommand(const char *input);
- bool TabComplete(const char *input, char*& completion);
-
- void DVar_Register(const char *varname, void *pointer, int type, int optional);
- void DCmd_Register(const char *cmdname, DebugProc pointer);
-
- bool Cmd_DebugFlagsList(int argc, const char **argv);
- bool Cmd_DebugFlagEnable(int argc, const char **argv);
- bool Cmd_DebugFlagDisable(int argc, const char **argv);
-
-#if USE_CONSOLE
- static bool debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon);
- static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, char*& completion, void *refCon);
-#endif
-};
-
-} // End of namespace Common
-
-#endif