OXYGENHUB
◆ main openmsx / src / cpu / BreakPointBase.hh
2.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#ifndef BREAKPOINTBASE_HH
2
#define BREAKPOINTBASE_HH
3
4
#include "CommandException.hh"
5
#include "GlobalCliComm.hh"
6
#include "TclObject.hh"
7
8
#include "ScopedAssign.hh"
9
#include "strCat.hh"
10
11
namespace openmsx {
12
13
class Interpreter;
14
15
/** CRTP base class for CPU break and watch points.
16
 */
17
template<typename Derived>
18
class BreakPointBase
19
{
20
public:
21
	[[nodiscard]] unsigned getId() const { return id; }
22
	[[nodiscard]] std::string getIdStr() const { return strCat(Derived::prefix, id); }
23
24
	[[nodiscard]] TclObject getCondition() const { return condition; }
25
	[[nodiscard]] TclObject getCommand()   const { return command; }
26
	[[nodiscard]] bool isEnabled() const { return enabled; }
27
	[[nodiscard]] bool onlyOnce() const { return once; }
28
29
	void setCondition(const TclObject& c) { condition = c; }
30
	void setCommand(const TclObject& c) { command = c; }
31
	void setEnabled(Interpreter& interp, const TclObject& e) {
32
		setEnabled(e.getBoolean(interp)); // may throw
33
	}
34
	void setEnabled(bool e) { enabled = e; }
35
	void setOnce(Interpreter& interp, const TclObject& o) {
36
		setOnce(o.getBoolean(interp)); // may throw
37
	}
38
	void setOnce(bool o) { once = o; }
39
40
	bool checkAndExecute(GlobalCliComm& cliComm, Interpreter& interp) {
41
		if (!enabled) return false;
42
		if (executing) {
43
			// no recursive execution
44
			return false;
45
		}
46
		ScopedAssign sa(executing, true);
47
		if (isTrue(cliComm, interp)) {
48
			try {
49
				command.executeCommand(interp, true); // compile command
50
			} catch (CommandException& e) {
51
				cliComm.printWarning(e.getMessage());
52
			}
53
			return onlyOnce();
54
		}
55
		return false;
56
	}
57
58
protected:
59
	BreakPointBase() : id(++lastId) {}
60
	unsigned id;
61
62
private:
63
	// Note: we require GlobalCliComm here because breakpoint objects can
64
	// be transferred to different MSX machines, and so the MSXCliComm
65
	// object won't remain valid.
66
	[[nodiscard]] bool isTrue(GlobalCliComm& cliComm, Interpreter& interp) const {
67
		if (condition.getString().empty()) {
68
			// unconditional bp
69
			return true;
70
		}
71
		try {
72
			return condition.evalBool(interp);
73
		} catch (CommandException& e) {
74
			cliComm.printWarning(e.getMessage());
75
			return false;
76
		}
77
	}
78
79
private:
80
	TclObject command{"debug break"};
81
	TclObject condition;
82
	bool enabled = true;
83
	bool once = false;
84
	bool executing = false;
85
86
	static inline unsigned lastId = 0;
87
};
88
89
} // namespace openmsx
90
91
#endif