Changeset View
Changeset View
Standalone View
Standalone View
debuggers/common/mi/micommand.h
- This file was moved from debuggers/gdb/gdbcommand.h.
1 | /*************************************************************************** | 1 | /*************************************************************************** | ||
---|---|---|---|---|---|
2 | begin : Sun Aug 8 1999 | 2 | begin : Sun Aug 8 1999 | ||
3 | copyright : (C) 1999 by John Birch | 3 | copyright : (C) 1999 by John Birch | ||
4 | email : jbb@kdevelop.org | 4 | email : jbb@kdevelop.org | ||
5 | copyright : (C) 2016 by Aetf | ||||
6 | email : aetf@unlimitedcodeworks.xyz | ||||
5 | ***************************************************************************/ | 7 | ***************************************************************************/ | ||
6 | 8 | | |||
7 | /*************************************************************************** | 9 | /*************************************************************************** | ||
8 | * * | 10 | * * | ||
9 | * This program is free software; you can redistribute it and/or modify * | 11 | * This program is free software; you can redistribute it and/or modify * | ||
10 | * it under the terms of the GNU General Public License as published by * | 12 | * it under the terms of the GNU General Public License as published by * | ||
11 | * the Free Software Foundation; either version 2 of the License, or * | 13 | * the Free Software Foundation; either version 2 of the License, or * | ||
12 | * (at your option) any later version. * | 14 | * (at your option) any later version. * | ||
13 | * * | 15 | * * | ||
14 | ***************************************************************************/ | 16 | ***************************************************************************/ | ||
15 | 17 | | |||
16 | #ifndef _GDBCOMMAND_H_ | 18 | #ifndef _MICOMMAND_H_ | ||
17 | #define _GDBCOMMAND_H_ | 19 | #define _MICOMMAND_H_ | ||
18 | 20 | | |||
19 | #include <functional> | 21 | #include "mi/mi.h" | ||
20 | 22 | | |||
21 | #include <QString> | 23 | #include <QString> | ||
22 | #include <QStringList> | 24 | #include <QStringList> | ||
23 | #include <QPointer> | 25 | #include <QPointer> | ||
24 | 26 | | |||
25 | #include "mi/gdbmi.h" | 27 | #include <functional> | ||
26 | | ||||
27 | namespace GDBDebugger | | |||
28 | { | | |||
29 | 28 | | |||
29 | namespace KDevMI { namespace MI { | ||||
30 | 30 | | |||
31 | class VarItem; | 31 | class VarItem; | ||
32 | class ValueCallback; | 32 | class ValueCallback; | ||
33 | 33 | | |||
34 | enum CommandFlag { | 34 | enum CommandFlag { | ||
35 | /// The command handler also wishes to receive an error responses, overriding the default error handler | 35 | /// The command handler also wishes to receive an error responses, overriding the default error handler | ||
36 | CmdHandlesError = 1 << 0, | 36 | CmdHandlesError = 1 << 0, | ||
37 | 37 | | |||
Show All 18 Lines | |||||
56 | CmdImmediately = 1 << 3, | 56 | CmdImmediately = 1 << 3, | ||
57 | 57 | | |||
58 | /// This is a command that should interrupt a running program, without resuming. | 58 | /// This is a command that should interrupt a running program, without resuming. | ||
59 | CmdInterrupt = 1 << 4, | 59 | CmdInterrupt = 1 << 4, | ||
60 | }; | 60 | }; | ||
61 | Q_DECLARE_FLAGS(CommandFlags, CommandFlag) | 61 | Q_DECLARE_FLAGS(CommandFlags, CommandFlag) | ||
62 | 62 | | |||
63 | //base class for handlers | 63 | //base class for handlers | ||
64 | class GDBCommandHandler | 64 | class MICommandHandler | ||
65 | { | 65 | { | ||
66 | public: | 66 | public: | ||
67 | virtual ~GDBCommandHandler() {} | 67 | virtual ~MICommandHandler() {} | ||
68 | virtual void handle(const GDBMI::ResultRecord&) = 0; | 68 | virtual void handle(const ResultRecord&) = 0; | ||
69 | virtual bool handlesError() { return false; } | 69 | virtual bool handlesError() { return false; } | ||
70 | 70 | | |||
71 | /** | 71 | /** | ||
72 | * If the handler object should be deleted after the handle() call. | 72 | * If the handler object should be deleted after the handle() call. | ||
73 | */ | 73 | */ | ||
74 | virtual bool autoDelete() { return true; } | 74 | virtual bool autoDelete() { return true; } | ||
75 | }; | 75 | }; | ||
76 | 76 | | |||
77 | class FunctionCommandHandler : public GDBCommandHandler { | 77 | class FunctionCommandHandler : public MICommandHandler { | ||
78 | public: | 78 | public: | ||
79 | typedef std::function<void (const GDBMI::ResultRecord&)> Function; | 79 | typedef std::function<void (const ResultRecord&)> Function; | ||
80 | 80 | | |||
81 | FunctionCommandHandler(const Function& callback, CommandFlags flags = 0); | 81 | FunctionCommandHandler(const Function& callback, CommandFlags flags = 0); | ||
82 | 82 | | |||
83 | virtual void handle(const GDBMI::ResultRecord&) override; | 83 | virtual void handle(const ResultRecord&) override; | ||
84 | virtual bool handlesError() override; | 84 | virtual bool handlesError() override; | ||
85 | 85 | | |||
86 | private: | 86 | private: | ||
87 | CommandFlags _flags; | 87 | CommandFlags _flags; | ||
88 | Function _callback; | 88 | Function _callback; | ||
89 | }; | 89 | }; | ||
90 | 90 | | |||
91 | /** | 91 | /** | ||
92 | * @author John Birch | 92 | * @author John Birch | ||
93 | */ | 93 | */ | ||
94 | 94 | | |||
95 | class GDBCommand | 95 | class MICommand | ||
96 | { | 96 | { | ||
97 | public: | 97 | public: | ||
98 | GDBCommand(GDBMI::CommandType type, const QString& arguments = QString(), CommandFlags flags = 0); | 98 | MICommand(CommandType type, const QString& arguments = QString(), CommandFlags flags = 0); | ||
99 | 99 | | |||
100 | template<class Handler> | 100 | template<class Handler> | ||
101 | GDBCommand(GDBMI::CommandType type, const QString& arguments, | 101 | MICommand(CommandType type, const QString& arguments, | ||
102 | Handler* handler_this, | 102 | Handler* handler_this, | ||
103 | void (Handler::* handler_method)(const GDBMI::ResultRecord&), | 103 | void (Handler::* handler_method)(const ResultRecord&), | ||
104 | CommandFlags flags = 0); | 104 | CommandFlags flags = 0); | ||
105 | 105 | | |||
106 | GDBCommand(GDBMI::CommandType type, const QString& arguments, GDBCommandHandler* handler, | 106 | MICommand(CommandType type, const QString& arguments, MICommandHandler* handler, | ||
107 | CommandFlags flags = 0); | 107 | CommandFlags flags = 0); | ||
108 | 108 | | |||
109 | GDBCommand( | 109 | MICommand(CommandType type, const QString& arguments, | ||
110 | GDBMI::CommandType type, const QString& arguments, | | |||
111 | const FunctionCommandHandler::Function& callback, | 110 | const FunctionCommandHandler::Function& callback, | ||
112 | CommandFlags flags = 0); | 111 | CommandFlags flags = 0); | ||
113 | 112 | | |||
114 | virtual ~GDBCommand(); | 113 | virtual ~MICommand(); | ||
115 | 114 | | |||
116 | GDBMI::CommandType type() const; | 115 | CommandType type() const; | ||
117 | QString gdbCommand() const; | 116 | QString miCommand() const; | ||
118 | 117 | | |||
119 | CommandFlags flags() const {return flags_;} | 118 | CommandFlags flags() const {return flags_;} | ||
120 | 119 | | |||
121 | /** | 120 | /** | ||
122 | * Returns the MI token with which the command is sent, allowing the parser to match up | 121 | * Returns the MI token with which the command is sent, allowing the parser to match up | ||
123 | * the result message with the command. | 122 | * the result message with the command. | ||
124 | */ | 123 | */ | ||
125 | uint32_t token() const {return token_;} | 124 | uint32_t token() const {return token_;} | ||
126 | 125 | | |||
127 | /** | 126 | /** | ||
128 | * Set the MI token. This is done by \ref GDBCommandQueue. | 127 | * Set the MI token. This is done by \ref MICommandQueue. | ||
129 | */ | 128 | */ | ||
130 | void setToken(uint32_t token) {token_ = token;} | 129 | void setToken(uint32_t token) {token_ = token;} | ||
131 | 130 | | |||
132 | /** | 131 | /** | ||
133 | * Returns the thread that needs to be currently selected when this command is executed, | 132 | * Returns the thread that needs to be currently selected when this command is executed, | ||
134 | * or -1 if there is no requirement. | 133 | * or -1 if there is no requirement. | ||
135 | */ | 134 | */ | ||
136 | int thread() const; | 135 | int thread() const; | ||
Show All 14 Lines | |||||
151 | */ | 150 | */ | ||
152 | void setFrame(int frame); | 151 | void setFrame(int frame); | ||
153 | 152 | | |||
154 | /** | 153 | /** | ||
155 | * Sets the handler for results. | 154 | * Sets the handler for results. | ||
156 | * | 155 | * | ||
157 | * The command object assumes ownership of @p handler. | 156 | * The command object assumes ownership of @p handler. | ||
158 | */ | 157 | */ | ||
159 | void setHandler(GDBCommandHandler* handler); | 158 | void setHandler(MICommandHandler* handler); | ||
160 | 159 | | |||
161 | /* The command that should be sent to gdb. | 160 | /* The command that should be sent to debugger. | ||
162 | This method is virtual so the command can compute this | 161 | This method is virtual so the command can compute this | ||
163 | dynamically, possibly using results of the previous | 162 | dynamically, possibly using results of the previous | ||
164 | commands. | 163 | commands. | ||
165 | If the empty string is returned, nothing is sent. */ | 164 | If the empty string is returned, nothing is sent. */ | ||
166 | virtual QString cmdToSend(); | 165 | virtual QString cmdToSend(); | ||
167 | 166 | | |||
168 | /* Returns the initial string that was specified in | 167 | /* Returns the initial string that was specified in | ||
169 | ctor invocation. The actual command will be | 168 | ctor invocation. The actual command will be | ||
170 | determined by cmdToSend above and the return | 169 | determined by cmdToSend above and the return | ||
171 | value of this method is only used in various | 170 | value of this method is only used in various | ||
172 | diagnostic messages emitted before actually | 171 | diagnostic messages emitted before actually | ||
173 | sending the command. */ | 172 | sending the command. */ | ||
174 | QString initialString() const; | 173 | QString initialString() const; | ||
175 | 174 | | |||
176 | /* Returns true if this is command entered by the user | 175 | /* Returns true if this is command entered by the user | ||
177 | and so should be always shown in the gdb output window. */ | 176 | and so should be always shown in the gdb output window. */ | ||
178 | virtual bool isUserCommand() const; | 177 | virtual bool isUserCommand() const; | ||
179 | 178 | | |||
180 | // If there's a handler for this command, invokes it and returns true. | 179 | // If there's a handler for this command, invokes it and returns true. | ||
181 | // Otherwise, returns false. | 180 | // Otherwise, returns false. | ||
182 | bool invokeHandler(const GDBMI::ResultRecord& r); | 181 | bool invokeHandler(const ResultRecord& r); | ||
183 | 182 | | |||
184 | // Returns 'true' if 'invokeHandler' should be invoked even | 183 | // Returns 'true' if 'invokeHandler' should be invoked even | ||
185 | // on MI errors. | 184 | // on MI errors. | ||
186 | bool handlesError() const; | 185 | bool handlesError() const; | ||
187 | 186 | | |||
188 | // Called by gdbcontroller for each new output string | 187 | // Called by debuggercontroller for each new output string | ||
189 | // gdb emits for this command. In MI mode, this includes | 188 | // debugger emits for this command. In MI mode, this includes | ||
190 | // all "stream" messages, but does not include MI responses. | 189 | // all "stream" messages, but does not include MI responses. | ||
191 | void newOutput(const QString&); | 190 | void newOutput(const QString&); | ||
192 | 191 | | |||
193 | const QStringList& allStreamOutput() const; | 192 | const QStringList& allStreamOutput() const; | ||
194 | 193 | | |||
195 | QString command() const; | 194 | QString command() const; | ||
196 | 195 | | |||
197 | void setStateReloading(bool f); | 196 | void setStateReloading(bool f); | ||
198 | 197 | | |||
199 | bool stateReloading() const; | 198 | bool stateReloading() const; | ||
200 | 199 | | |||
201 | private: | 200 | private: | ||
202 | GDBMI::CommandType type_; | 201 | CommandType type_; | ||
203 | CommandFlags flags_; | 202 | CommandFlags flags_; | ||
204 | uint32_t token_ = 0; | 203 | uint32_t token_ = 0; | ||
205 | QString command_; | 204 | QString command_; | ||
206 | GDBCommandHandler *commandHandler_; | 205 | MICommandHandler *commandHandler_; | ||
207 | QStringList lines; | 206 | QStringList lines; | ||
208 | bool stateReloading_; | 207 | bool stateReloading_; | ||
209 | 208 | | |||
210 | private: | 209 | private: | ||
211 | int m_thread; | 210 | int m_thread; | ||
212 | int m_frame; | 211 | int m_frame; | ||
213 | }; | 212 | }; | ||
214 | 213 | | |||
215 | class UserCommand : public GDBCommand | 214 | class UserCommand : public MICommand | ||
216 | { | 215 | { | ||
217 | public: | 216 | public: | ||
218 | UserCommand(GDBMI::CommandType type, const QString& s); | 217 | UserCommand(CommandType type, const QString& s); | ||
219 | 218 | | |||
220 | bool isUserCommand() const override; | 219 | bool isUserCommand() const override; | ||
221 | }; | 220 | }; | ||
222 | 221 | | |||
223 | /** This is a class for raw CLI commands. Instead of invoking | 222 | /** This is a class for raw CLI commands. Instead of invoking | ||
224 | user provided hook with MI response, it invokes the a hook | 223 | user provided hook with MI response, it invokes the a hook | ||
225 | with lists of strings. | 224 | with lists of strings. | ||
226 | */ | 225 | */ | ||
227 | class CliCommand : public GDBCommand | 226 | class CliCommand : public MICommand | ||
228 | { | 227 | { | ||
229 | public: | 228 | public: | ||
230 | template<class Handler> | 229 | template<class Handler> | ||
231 | CliCommand(GDBMI::CommandType type, const QString& command, | 230 | CliCommand(CommandType type, const QString& command, | ||
232 | Handler* handler_this, | 231 | Handler* handler_this, | ||
233 | void (Handler::* handler_method)(const QStringList&), | 232 | void (Handler::* handler_method)(const QStringList&), | ||
234 | CommandFlags flags = 0); | 233 | CommandFlags flags = 0); | ||
235 | }; | 234 | }; | ||
236 | 235 | | |||
237 | /** Command that does nothing and can be just used to invoke | 236 | /** Command that does nothing and can be just used to invoke | ||
238 | a user provided handler when all preceeding commands are | 237 | a user provided handler when all preceeding commands are | ||
239 | executed. | 238 | executed. | ||
240 | */ | 239 | */ | ||
241 | class SentinelCommand : public GDBCommand | 240 | class SentinelCommand : public MICommand | ||
242 | { | 241 | { | ||
243 | public: | 242 | public: | ||
244 | typedef std::function<void ()> Function; | 243 | typedef std::function<void ()> Function; | ||
245 | 244 | | |||
246 | template<class Handler> | 245 | template<class Handler> | ||
247 | SentinelCommand(Handler* handler_this, | 246 | SentinelCommand(Handler* handler_this, | ||
248 | void (Handler::* handler_method)(), | 247 | void (Handler::* handler_method)(), | ||
249 | CommandFlags flags = 0) | 248 | CommandFlags flags = 0) | ||
250 | : GDBCommand(GDBMI::NonMI, QString(), flags) | 249 | : MICommand(NonMI, QString(), flags) | ||
251 | { | 250 | { | ||
252 | QPointer<Handler> guarded_this(handler_this); | 251 | QPointer<Handler> guarded_this(handler_this); | ||
253 | handler = [guarded_this, handler_method]() { | 252 | handler = [guarded_this, handler_method]() { | ||
254 | if (guarded_this) { | 253 | if (guarded_this) { | ||
255 | (guarded_this.data()->*handler_method)(); | 254 | (guarded_this.data()->*handler_method)(); | ||
256 | } | 255 | } | ||
257 | }; | 256 | }; | ||
258 | } | 257 | } | ||
259 | 258 | | |||
260 | SentinelCommand(const Function& handler, CommandFlags flags = 0) | 259 | SentinelCommand(const Function& handler, CommandFlags flags = 0) | ||
261 | : GDBCommand(GDBMI::NonMI, QString(), flags) | 260 | : MICommand(NonMI, QString(), flags) | ||
262 | , handler(handler) | 261 | , handler(handler) | ||
263 | { | 262 | { | ||
264 | } | 263 | } | ||
265 | 264 | | |||
266 | using GDBCommand::invokeHandler; | 265 | using MICommand::invokeHandler; | ||
267 | void invokeHandler() | 266 | void invokeHandler() | ||
268 | { | 267 | { | ||
269 | handler(); | 268 | handler(); | ||
270 | } | 269 | } | ||
271 | 270 | | |||
272 | QString cmdToSend() override | 271 | QString cmdToSend() override | ||
273 | { | 272 | { | ||
274 | return ""; | 273 | return ""; | ||
275 | } | 274 | } | ||
276 | 275 | | |||
277 | private: | 276 | private: | ||
278 | Function handler; | 277 | Function handler; | ||
279 | }; | 278 | }; | ||
280 | 279 | | |||
281 | class ExpressionValueCommand : public QObject, public GDBCommand | 280 | class ExpressionValueCommand : public QObject, public MICommand | ||
282 | { | 281 | { | ||
283 | public: | 282 | public: | ||
284 | typedef void (QObject::*handler_method_t)(const QString&); | 283 | typedef void (QObject::*handler_method_t)(const QString&); | ||
285 | 284 | | |||
286 | template<class Handler> | 285 | template<class Handler> | ||
287 | ExpressionValueCommand( | 286 | ExpressionValueCommand( | ||
288 | const QString& expression, | 287 | const QString& expression, | ||
289 | Handler* handler_this, | 288 | Handler* handler_this, | ||
290 | void (Handler::* handler_method)(const QString&)) | 289 | void (Handler::* handler_method)(const QString&)) | ||
291 | : GDBCommand(GDBMI::DataEvaluateExpression, expression, this, | 290 | : MICommand(DataEvaluateExpression, expression, this, | ||
292 | &ExpressionValueCommand::handleResponse), | 291 | &ExpressionValueCommand::handleResponse), | ||
293 | handler_this(handler_this), | 292 | handler_this(handler_this), | ||
294 | handler_method(static_cast<handler_method_t>(handler_method)) | 293 | handler_method(static_cast<handler_method_t>(handler_method)) | ||
295 | {} | 294 | {} | ||
296 | 295 | | |||
297 | void handleResponse(const GDBMI::ResultRecord& r) | 296 | void handleResponse(const ResultRecord& r) | ||
298 | { | 297 | { | ||
299 | (handler_this.data()->*handler_method)(r["value"].literal()); | 298 | (handler_this.data()->*handler_method)(r["value"].literal()); | ||
300 | } | 299 | } | ||
301 | 300 | | |||
302 | private: | 301 | private: | ||
303 | QPointer<QObject> handler_this; | 302 | QPointer<QObject> handler_this; | ||
304 | handler_method_t handler_method; | 303 | handler_method_t handler_method; | ||
305 | }; | 304 | }; | ||
306 | 305 | | |||
307 | 306 | | |||
308 | template<class Handler> | 307 | template<class Handler> | ||
309 | GDBCommand::GDBCommand( | 308 | MICommand::MICommand( | ||
310 | GDBMI::CommandType type, | 309 | CommandType type, | ||
311 | const QString& command, | 310 | const QString& command, | ||
312 | Handler* handler_this, | 311 | Handler* handler_this, | ||
313 | void (Handler::* handler_method)(const GDBMI::ResultRecord&), | 312 | void (Handler::* handler_method)(const ResultRecord&), | ||
314 | CommandFlags flags) | 313 | CommandFlags flags) | ||
315 | : type_(type), | 314 | : type_(type), | ||
316 | flags_(flags & ~CmdHandlesError), | 315 | flags_(flags & ~CmdHandlesError), | ||
317 | command_(command), | 316 | command_(command), | ||
318 | commandHandler_(nullptr), | 317 | commandHandler_(nullptr), | ||
319 | stateReloading_(false), | 318 | stateReloading_(false), | ||
320 | m_thread(-1), | 319 | m_thread(-1), | ||
321 | m_frame(-1) | 320 | m_frame(-1) | ||
322 | { | 321 | { | ||
323 | QPointer<Handler> guarded_this(handler_this); | 322 | QPointer<Handler> guarded_this(handler_this); | ||
324 | setHandler(new FunctionCommandHandler([guarded_this, handler_method](const GDBMI::ResultRecord& r) { | 323 | setHandler(new FunctionCommandHandler([guarded_this, handler_method](const ResultRecord& r) { | ||
325 | if (guarded_this) { | 324 | if (guarded_this) { | ||
326 | (guarded_this.data()->*handler_method)(r); | 325 | (guarded_this.data()->*handler_method)(r); | ||
327 | } | 326 | } | ||
328 | }, flags)); | 327 | }, flags)); | ||
329 | } | 328 | } | ||
330 | 329 | | |||
331 | template<class Handler> | 330 | template<class Handler> | ||
332 | CliCommand::CliCommand( | 331 | CliCommand::CliCommand( | ||
333 | GDBMI::CommandType type, | 332 | CommandType type, | ||
334 | const QString& command, | 333 | const QString& command, | ||
335 | Handler* handler_this, | 334 | Handler* handler_this, | ||
336 | void (Handler::* handler_method)(const QStringList&), | 335 | void (Handler::* handler_method)(const QStringList&), | ||
337 | CommandFlags flags) | 336 | CommandFlags flags) | ||
338 | : GDBCommand(type, command) | 337 | : MICommand(type, command) | ||
339 | { | 338 | { | ||
340 | QPointer<Handler> guarded_this(handler_this); | 339 | QPointer<Handler> guarded_this(handler_this); | ||
341 | setHandler(new FunctionCommandHandler([this, guarded_this, handler_method](const GDBMI::ResultRecord&) { | 340 | setHandler(new FunctionCommandHandler([this, guarded_this, handler_method](const ResultRecord&) { | ||
342 | if (guarded_this) { | 341 | if (guarded_this) { | ||
343 | (guarded_this.data()->*handler_method)(this->allStreamOutput()); | 342 | (guarded_this.data()->*handler_method)(this->allStreamOutput()); | ||
344 | } | 343 | } | ||
345 | }, flags)); | 344 | }, flags)); | ||
346 | } | 345 | } | ||
347 | 346 | | |||
348 | } | 347 | } // end of namespace MI | ||
348 | } // end of namespace KDevMI | ||||
349 | 349 | | |||
350 | Q_DECLARE_OPERATORS_FOR_FLAGS(GDBDebugger::CommandFlags) | 350 | Q_DECLARE_OPERATORS_FOR_FLAGS(KDevMI::MI::CommandFlags) | ||
351 | 351 | | |||
352 | #endif | 352 | #endif |