diff options
Diffstat (limited to 'languages/cpp/debugger/mi/gdbmi.h')
-rw-r--r-- | languages/cpp/debugger/mi/gdbmi.h | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/languages/cpp/debugger/mi/gdbmi.h b/languages/cpp/debugger/mi/gdbmi.h new file mode 100644 index 00000000..7a193e91 --- /dev/null +++ b/languages/cpp/debugger/mi/gdbmi.h @@ -0,0 +1,221 @@ +/*************************************************************************** + * Copyright (C) 2004 by Roberto Raggi * + * [email protected] * + * Copyright (C) 2005-2006 by Vladimir Prus * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library 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 Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef GDBMI_H +#define GDBMI_H + +#include <qstring.h> +#include <qvaluelist.h> +#include <qmap.h> + +#include <stdexcept> + +/** +@author Roberto Raggi +@author Vladimir Prus +*/ +namespace GDBMI +{ + /** Exception that is thrown when we're trying to invoke an + operation that is not supported by specific MI value. For + example, trying to index a string literal. + + Such errors are conceptually the same as assert, but in GUI + we can't use regular assert, and Q_ASSERT, which only prints + a message, is not suitable either. We need to break processing, + and the higher-level code can report "Internal parsing error", + or something. + + Being glorified assert, this exception does not cary any + useful information. + */ + class type_error : public std::logic_error + { + public: + type_error(); + }; + + /** Base class for all MI values. + MI values are of three kinds: + - String literals + - Lists (indexed by integer) + - Tuple (set of named values, indexed by name) + + The structure of response to a specific gdb command is fixed. + While any tuples in response may omit certain named fields, the + kind of each item never changes. That is, response to specific + command can't contains sometimes string and sometimes tuple in + specific position. + + Because of that static structure, it's almost never needed to query + dynamic type of a MI value. Most often we know it's say, tuple, and + can subscripts it. + + So, the Value class has methods for accessing all kinds of values. + Attempting to call a method that is not applicable to specific value + will result in exception. The client code will almost never need to + cast from 'Value' to its derived classes. + + Note also that all methods in this class are const and return + const Value&. That's by design -- there's no need to modify gdb + responses in GUI. + */ + struct Value + { + Value() {} + private: // Copy disabled to prevent slicing. + Value(const Value&); + Value& operator=(const Value&); + + public: + + virtual ~Value() {} + + enum { StringLiteral, Tuple, List } kind; + + /** If this value is a string literals, returns the string value. + Othewise, throws type_error. + */ + virtual QString literal() const; + + /** If the value is a string literal, converts it to int and + returns. If conversion fails, or the value cannot be + converted to int, throws type_error. + */ + virtual int toInt(int base = 10) const; + + /** If this value is a tuple, returns true if the tuple + has a field named 'variable'. Otherwise, + throws type_error. + */ + virtual bool hasField(const QString& variable) const; + + /** If this value is a tuple, and contains named field 'variable', + returns it. Otherwise, throws 'type_error'. + This method is virtual, and derived in base class, so that + we can save on casting, when we know for sure that instance + is TupleValue, or ListValue. + */ + virtual const Value& operator[](const QString& variable) const; + + /** If this value is a list, returns true if the list is empty. + If this value is not a list, throws 'type_error'. + */ + virtual bool empty() const; + + /** If this value is a list, returns it's size. + Otherwise, throws 'type_error'. + */ + virtual unsigned size() const; + + /** If this value is a list, returns the element at + 'index'. Otherwise, throws 'type_error'. + */ + virtual const Value& operator[](unsigned index) const; + }; + + /** @internal + Internal class to represent name-value pair in tuples. + */ + struct Result + { + Result() : value(0) {} + ~Result() { delete value; value = 0; } + + QString variable; + Value *value; + }; + + struct StringLiteralValue : public Value + { + StringLiteralValue(const QString &lit) + : literal_(lit) { Value::kind = StringLiteral; } + + public: // Value overrides + + QString literal() const; + int toInt(int base) const; + + private: + QString literal_; + }; + + struct TupleValue : public Value + { + TupleValue() { Value::kind = Tuple; } + ~TupleValue(); + + bool hasField(const QString&) const; + const Value& operator[](const QString& variable) const; + + + QValueList<Result*> results; + QMap<QString, GDBMI::Result*> results_by_name; + }; + + struct ListValue : public Value + { + ListValue() { Value::kind = List; } + ~ListValue(); + + bool empty() const; + + unsigned size() const; + + const Value& operator[](unsigned index) const; + + QValueList<Result*> results; + + }; + + struct Record + { + virtual ~Record() {} + virtual QString toString() const { Q_ASSERT( 0 ); return QString::null; } + + enum { Prompt, Stream, Result } kind; + }; + + struct ResultRecord : public Record, public TupleValue + { + ResultRecord() { Record::kind = Result; } + + QString reason; + }; + + struct PromptRecord : public Record + { + inline PromptRecord() { Record::kind = Prompt; } + + virtual QString toString() const + { return "(prompt)\n"; } + }; + + struct StreamRecord : public Record + { + inline StreamRecord() : reason(0) { Record::kind = Stream; } + + char reason; + QString message; + }; +} + +#endif |