aboutsummaryrefslogtreecommitdiff
path: root/gui/debugger.h
blob: 568c4e3bc9d6a90d63c857b60243ba2615e8d077 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* 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 GUI_DEBUGGER_H
#define GUI_DEBUGGER_H

namespace GUI {

// Choose between text console or ScummConsole
#define USE_CONSOLE	1

#ifdef USE_CONSOLE
class ConsoleDialog;
#endif

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 :)
	// FIXME: Fingolfin asks: This code *used* to be a problem when GUI::Debugger
	// was a template class. But is it really still causing problems, or can
	// this hack go away now?
	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:
	class Debuglet {
	public:
		virtual ~Debuglet() {}
		virtual bool operator()(int argc, const char **argv) = 0;
	};
	
	template <class T>
	class DelegateDebuglet : public Debuglet {
		typedef bool (T::*Method)(int argc, const char **argv);

		T *_delegate;
		const Method _method;
	public:
		DelegateDebuglet(T *delegate, Method method)
			: _delegate(delegate), _method(method) {
			assert(delegate != 0);
		}
		virtual bool operator()(int argc, const char **argv) {
			return (_delegate->*_method)(argc, argv);
		};
	};
	
	// Convenicence macro for registering a method of a debugger class
	// as the current command.
	#define WRAP_METHOD(cls, method) \
		new DelegateDebuglet<cls>(this, &cls::method)

	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];
		Debuglet *debuglet;
	};

	int _frame_countdown;
	bool _detach_now;
	
private:
	// TODO: Consider replacing the following two arrays by a Hashmap
	int _dvar_count;
	DVar _dvars[256];

	int _dcmd_count;
	DCmd _dcmds[256];

	bool _isAttached;
	char *_errStr;
	bool _firstTime;
	GUI::ConsoleDialog *_debuggerDialog;

protected:
	// Hook for subclasses: Called just before enter() is run
	virtual void preEnter() {}

	// Hook for subclasses: Called just after enter() was run
	virtual void postEnter() {}

	// Hook for subclasses: Process the given command line.
	// Should return true if and only if argv[0] is a known command and was
	// handled, false otherwise.
	virtual bool handleCommand(int argc, const char **argv, bool &keepRunning);

	
private:
	void detach();
	void enter();

	bool parseCommand(const char *input);
	bool tabComplete(const char *input, char*& completion);

protected:
	void DVar_Register(const char *varname, void *pointer, int type, int optional);
	void DCmd_Register(const char *cmdname, Debuglet *debuglet);

	bool Cmd_Exit(int argc, const char **argv);
	bool Cmd_Help(int argc, const char **argv);
	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
private:
	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 GUI

#endif