File indexing completed on 2024-05-12 04:39:43
0001 /* 0002 SPDX-FileCopyrightText: 2004 Roberto Raggi <roberto@kdevelop.org> 0003 SPDX-FileCopyrightText: 2005-2006 Vladimir Prus <ghost@cs.msu.su> 0004 SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef GDBMI_H 0010 #define GDBMI_H 0011 0012 #include <QString> 0013 #include <QMap> 0014 0015 #include <stdexcept> 0016 0017 /** 0018 @author Roberto Raggi 0019 @author Vladimir Prus 0020 */ 0021 namespace KDevMI { namespace MI { 0022 enum CommandType { 0023 NonMI, 0024 0025 BreakAfter, 0026 BreakCommands, 0027 BreakCondition, 0028 BreakDelete, 0029 BreakDisable, 0030 BreakEnable, 0031 BreakInfo, 0032 BreakInsert, 0033 BreakList, 0034 BreakWatch, 0035 0036 DataDisassemble, 0037 DataEvaluateExpression, 0038 DataListChangedRegisters, 0039 DataListRegisterNames, 0040 DataListRegisterValues, 0041 DataReadMemory, 0042 DataWriteMemory, 0043 DataWriteRegisterVariables, 0044 0045 EnablePrettyPrinting, 0046 EnableTimings, 0047 0048 EnvironmentCd, 0049 EnvironmentDirectory, 0050 EnvironmentPath, 0051 EnvironmentPwd, 0052 0053 ExecAbort, 0054 ExecArguments, 0055 ExecContinue, 0056 ExecFinish, 0057 ExecInterrupt, 0058 ExecNext, 0059 ExecNextInstruction, 0060 ExecRun, 0061 ExecStep, 0062 ExecStepInstruction, 0063 ExecUntil, 0064 0065 FileExecAndSymbols, 0066 FileExecFile, 0067 FileListExecSourceFile, 0068 FileListExecSourceFiles, 0069 FileSymbolFile, 0070 0071 GdbExit, 0072 GdbSet, 0073 GdbShow, 0074 GdbVersion, 0075 0076 InferiorTtySet, 0077 InferiorTtyShow, 0078 0079 InterpreterExec, 0080 0081 ListFeatures, 0082 0083 SignalHandle, 0084 0085 StackInfoDepth, 0086 StackInfoFrame, 0087 StackListArguments, 0088 StackListFrames, 0089 StackListLocals, 0090 StackSelectFrame, 0091 0092 SymbolListLines, 0093 0094 TargetAttach, 0095 TargetDetach, 0096 TargetDisconnect, 0097 TargetDownload, 0098 TargetSelect, 0099 0100 ThreadInfo, 0101 ThreadListIds, 0102 ThreadSelect, 0103 0104 TraceFind, 0105 TraceStart, 0106 TraceStop, 0107 0108 VarAssign, 0109 VarCreate, 0110 VarDelete, 0111 VarEvaluateExpression, 0112 VarInfoPathExpression, 0113 VarInfoNumChildren, 0114 VarInfoType, 0115 VarListChildren, 0116 VarSetFormat, 0117 VarSetFrozen, 0118 VarShowAttributes, 0119 VarShowFormat, 0120 VarUpdate 0121 }; 0122 0123 /** Exception that is thrown when we're trying to invoke an 0124 operation that is not supported by specific MI value. For 0125 example, trying to index a string literal. 0126 0127 Such errors are conceptually the same as assert, but in GUI 0128 we can't use regular assert, and Q_ASSERT, which only prints 0129 a message, is not suitable either. We need to break processing, 0130 and the higher-level code can report "Internal parsing error", 0131 or something. 0132 0133 Being glorified assert, this exception does not cary any 0134 useful information. 0135 */ 0136 class type_error : public std::logic_error 0137 { 0138 public: 0139 type_error(); 0140 }; 0141 0142 /** Base class for all MI values. 0143 MI values are of three kinds: 0144 - String literals 0145 - Lists (indexed by integer) 0146 - Tuple (set of named values, indexed by name) 0147 0148 The structure of response to a specific gdb command is fixed. 0149 While any tuples in response may omit certain named fields, the 0150 kind of each item never changes. That is, response to specific 0151 command can't contains sometimes string and sometimes tuple in 0152 specific position. 0153 0154 Because of that static structure, it's almost never needed to query 0155 dynamic type of a MI value. Most often we know it's say, tuple, and 0156 can subscripts it. 0157 0158 So, the Value class has methods for accessing all kinds of values. 0159 Attempting to call a method that is not applicable to specific value 0160 will result in exception. The client code will almost never need to 0161 cast from 'Value' to its derived classes. 0162 0163 Note also that all methods in this class are const and return 0164 const Value&. That's by design -- there's no need to modify gdb 0165 responses in GUI. 0166 */ 0167 struct Value 0168 { 0169 enum Kind { 0170 StringLiteral, 0171 Tuple, 0172 List 0173 }; 0174 0175 protected: 0176 constexpr explicit Value(Kind k) : kind(k) {} 0177 0178 public: 0179 virtual ~Value() = default; 0180 0181 Value() = delete; 0182 // Copy disabled to prevent slicing. 0183 Value(const Value&) = delete; 0184 Value& operator=(const Value&) = delete; 0185 0186 const Kind kind = StringLiteral; 0187 0188 /** If this value is a string literals, returns the string value. 0189 Otherwise, throws type_error. 0190 */ 0191 virtual QString literal() const; 0192 0193 //NOTE: Wouldn't it be better to use literal().toInt and get rid of that? 0194 /** If the value is a string literal, converts it to int and 0195 returns. If conversion fails, or the value cannot be 0196 converted to int, throws type_error. 0197 */ 0198 virtual int toInt(int base = 10) const; 0199 0200 /** If this value is a tuple, returns true if the tuple 0201 has a field named 'variable'. Otherwise, 0202 throws type_error. 0203 */ 0204 virtual bool hasField(const QString& variable) const; 0205 0206 /** If this value is a tuple, and contains named field 'variable', 0207 returns it. Otherwise, throws 'type_error'. 0208 This method is virtual, and derived in base class, so that 0209 we can save on casting, when we know for sure that instance 0210 is TupleValue, or ListValue. 0211 */ 0212 virtual const Value& operator[](const QString& variable) const; 0213 0214 /** If this value is a list, returns true if the list is empty. 0215 If this value is not a list, throws 'type_error'. 0216 */ 0217 virtual bool empty() const; 0218 0219 /** If this value is a list, returns it's size. 0220 Otherwise, throws 'type_error'. 0221 */ 0222 virtual int size() const; 0223 0224 /** If this value is a list, returns the element at 0225 'index'. Otherwise, throws 'type_error'. 0226 */ 0227 virtual const Value& operator[](int index) const; 0228 }; 0229 0230 /** @internal 0231 Internal class to represent name-value pair in tuples. 0232 */ 0233 struct Result 0234 { 0235 Result() = default; 0236 ~Result() { delete value; value = nullptr; } 0237 0238 QString variable; 0239 Value *value = nullptr; 0240 0241 private: 0242 Q_DISABLE_COPY(Result) 0243 }; 0244 0245 struct StringLiteralValue : public Value 0246 { 0247 explicit StringLiteralValue(const QString &lit) 0248 : Value(StringLiteral) 0249 , literal_(lit) 0250 {} 0251 0252 public: // Value overrides 0253 0254 QString literal() const override; 0255 int toInt(int base) const override; 0256 0257 private: 0258 QString literal_; 0259 }; 0260 0261 struct TupleValue : public Value 0262 { 0263 TupleValue() : Value(Tuple) {} 0264 ~TupleValue() override; 0265 0266 bool hasField(const QString&) const override; 0267 0268 using Value::operator[]; 0269 const Value& operator[](const QString& variable) const override; 0270 0271 QList<Result*> results; 0272 QMap<QString, Result*> results_by_name; 0273 }; 0274 0275 struct ListValue : public Value 0276 { 0277 ListValue() : Value(List) {} 0278 ~ListValue() override; 0279 0280 bool empty() const override; 0281 0282 int size() const override; 0283 0284 using Value::operator[]; 0285 const Value& operator[](int index) const override; 0286 0287 QList<Result*> results; 0288 }; 0289 0290 struct Record 0291 { 0292 enum Kind { 0293 Prompt, 0294 Stream, 0295 Result, 0296 Async 0297 }; 0298 0299 protected: 0300 constexpr explicit Record(Kind k) : kind(k) {} 0301 0302 public: 0303 Record() = delete; 0304 Record(const Record&) = delete; 0305 Record& operator=(const Record&) = delete; 0306 0307 virtual ~Record() = default; 0308 virtual QString toString() const { Q_ASSERT( 0 ); return QString(); } 0309 0310 const Kind kind; 0311 }; 0312 0313 struct TupleRecord : public Record, public TupleValue 0314 { 0315 protected: 0316 explicit TupleRecord(Record::Kind k) : Record(k) {} 0317 }; 0318 0319 struct ResultRecord : public TupleRecord 0320 { 0321 explicit ResultRecord(const QString& reason) 0322 : TupleRecord(Result) 0323 , reason(reason) 0324 { 0325 } 0326 0327 uint32_t token = 0; 0328 QString reason; 0329 }; 0330 0331 struct AsyncRecord : public TupleRecord 0332 { 0333 enum Subkind { 0334 Exec, 0335 Status, 0336 Notify 0337 }; 0338 0339 AsyncRecord(Subkind subkind, const QString& reason) 0340 : TupleRecord(Async) 0341 , subkind(subkind) 0342 , reason(reason) 0343 { 0344 } 0345 0346 Subkind subkind; 0347 QString reason; 0348 }; 0349 0350 struct PromptRecord : public Record 0351 { 0352 PromptRecord() : Record(Prompt) {} 0353 0354 QString toString() const override 0355 { return QStringLiteral("(prompt)\n"); } 0356 }; 0357 0358 struct StreamRecord : public Record 0359 { 0360 enum Subkind { 0361 /// Console stream: usual CLI output of GDB in response to non-MI commands 0362 Console, 0363 0364 /// Target output stream (stdout/stderr of the inferior process, only in some 0365 /// scenarios - usually we get stdout/stderr via other means) 0366 Target, 0367 0368 /// Log stream: GDB internal messages that should be displayed as part of an error log 0369 Log 0370 }; 0371 0372 explicit StreamRecord(Subkind subkind) 0373 : Record(Stream) 0374 , subkind(subkind) 0375 { 0376 } 0377 0378 Subkind subkind; 0379 QString message; 0380 }; 0381 } // end of namespace MI 0382 } // end of namespace KDevMI 0383 0384 #endif