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