forked from qt-creator/qt-creator
Debugger: Use a class for GdbMI parser parameters
Currently only the previous from/to pair, but can be extended by codec state. Task-number: QTCREATORBUG-24462 Change-Id: I3d101e74d1fef65bb75ddaab1dc2eaf77201dcde Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -46,7 +46,7 @@
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
uchar fromhex(uchar c)
|
static uchar fromhex(uchar c)
|
||||||
{
|
{
|
||||||
if (c >= '0' && c <= '9')
|
if (c >= '0' && c <= '9')
|
||||||
return c - '0';
|
return c - '0';
|
||||||
@@ -57,84 +57,122 @@ uchar fromhex(uchar c)
|
|||||||
return UCHAR_MAX;
|
return UCHAR_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skipCommas(const QChar *&from, const QChar *to)
|
// DebuggerOutputParser
|
||||||
|
|
||||||
|
DebuggerOutputParser::DebuggerOutputParser(const QString &output)
|
||||||
|
: from(output.begin()), to(output.end())
|
||||||
{
|
{
|
||||||
while (*from == ',' && from != to)
|
}
|
||||||
|
|
||||||
|
void DebuggerOutputParser::skipCommas()
|
||||||
|
{
|
||||||
|
while (from != to && *from == ',')
|
||||||
++from;
|
++from;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbMi::parseResultOrValue(const QChar *&from, const QChar *to)
|
void DebuggerOutputParser::skipSpaces()
|
||||||
{
|
{
|
||||||
while (from != to && isspace(from->unicode()))
|
while (from != to && isspace(from->unicode()))
|
||||||
++from;
|
++from;
|
||||||
|
}
|
||||||
|
|
||||||
//qDebug() << "parseResultOrValue: " << QString(from, to - from);
|
QString DebuggerOutputParser::readString(const std::function<bool(char)> &isValidChar)
|
||||||
parseValue(from, to);
|
{
|
||||||
|
QString res;
|
||||||
|
while (from != to && isValidChar(from->unicode()))
|
||||||
|
res += *from++;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DebuggerOutputParser::readInt()
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
while (from != to && *from >= '0' && *from <= '9') {
|
||||||
|
res *= 10;
|
||||||
|
res += (*from++).unicode() - '0';
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
QChar DebuggerOutputParser::readChar()
|
||||||
|
{
|
||||||
|
return *from++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isNameChar(char c)
|
||||||
|
{
|
||||||
|
return c != '=' && c != ':' && !isspace(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbMi::parseResultOrValue(DebuggerOutputParser &parser)
|
||||||
|
{
|
||||||
|
parser.skipSpaces();
|
||||||
|
|
||||||
|
//qDebug() << "parseResultOrValue: " << parser.buffer();
|
||||||
|
parseValue(parser);
|
||||||
|
parser.skipSpaces();
|
||||||
if (isValid()) {
|
if (isValid()) {
|
||||||
//qDebug() << "no valid result in " << QString(from, to - from);
|
//qDebug() << "no valid result in " << parser.buffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (from == to || *from == '(')
|
if (parser.isAtEnd() || parser.isCurrent('('))
|
||||||
return;
|
return;
|
||||||
const QChar *ptr = from;
|
|
||||||
while (ptr < to && *ptr != '=' && *ptr != ':') {
|
m_name = parser.readString(isNameChar);
|
||||||
//qDebug() << "adding" << QChar(*ptr) << "to name";
|
|
||||||
++ptr;
|
if (!parser.isAtEnd() && parser.isCurrent('=')) {
|
||||||
}
|
parser.advance();
|
||||||
m_name = QString(from, ptr - from);
|
parseValue(parser);
|
||||||
from = ptr;
|
|
||||||
if (from < to && *from == '=') {
|
|
||||||
++from;
|
|
||||||
parseValue(from, to);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads one \ooo entity.
|
// Reads one \ooo entity.
|
||||||
static bool parseOctalEscapedHelper(const QChar *&from, const QChar *to, QByteArray &buffer)
|
static bool parseOctalEscapedHelper(DebuggerOutputParser &parser, QByteArray &buffer)
|
||||||
{
|
{
|
||||||
if (to - from < 4)
|
if (parser.remainingChars() < 4)
|
||||||
return false;
|
return false;
|
||||||
if (*from != '\\')
|
if (!parser.isCurrent('\\'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char c1 = from[1].unicode();
|
const char c1 = parser.lookAhead(1).unicode();
|
||||||
const char c2 = from[2].unicode();
|
const char c2 = parser.lookAhead(2).unicode();
|
||||||
const char c3 = from[3].unicode();
|
const char c3 = parser.lookAhead(3).unicode();
|
||||||
if (!isdigit(c1) || !isdigit(c2) || !isdigit(c3))
|
if (!isdigit(c1) || !isdigit(c2) || !isdigit(c3))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
buffer += char((c1 - '0') * 64 + (c2 - '0') * 8 + (c3 - '0'));
|
buffer += char((c1 - '0') * 64 + (c2 - '0') * 8 + (c3 - '0'));
|
||||||
from += 4;
|
parser.advance(4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseHexEscapedHelper(const QChar *&from, const QChar *to, QByteArray &buffer)
|
static bool parseHexEscapedHelper(DebuggerOutputParser &parser, QByteArray &buffer)
|
||||||
{
|
{
|
||||||
if (to - from < 4)
|
if (parser.remainingChars() < 4)
|
||||||
return false;
|
return false;
|
||||||
if (from[0]!= '\\')
|
if (!parser.isCurrent('\\'))
|
||||||
return false;
|
return false;
|
||||||
if (from[1] != 'x')
|
if (parser.lookAhead(1) != 'x')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char c1 = from[2].unicode();
|
const char c1 = parser.lookAhead(2).unicode();
|
||||||
const char c2 = from[3].unicode();
|
const char c2 = parser.lookAhead(3).unicode();
|
||||||
if (!isxdigit(c1) || !isxdigit(c2))
|
if (!isxdigit(c1) || !isxdigit(c2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
buffer += char(16 * fromhex(c1) + fromhex(c2));
|
buffer += char(16 * fromhex(c1) + fromhex(c2));
|
||||||
from += 4;
|
parser.advance(4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseSimpleEscape(const QChar *&from, const QChar *to, QString &result)
|
static void parseSimpleEscape(DebuggerOutputParser &parser, QString &result)
|
||||||
{
|
{
|
||||||
if (from == to) {
|
if (parser.isAtEnd()) {
|
||||||
qDebug() << "MI Parse Error, unterminated backslash escape";
|
qDebug() << "MI Parse Error, unterminated backslash escape";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QChar c = *from++;
|
const QChar c = parser.current();
|
||||||
|
parser.advance();
|
||||||
switch (c.unicode()) {
|
switch (c.unicode()) {
|
||||||
case 'a': result += '\a'; break;
|
case 'a': result += '\a'; break;
|
||||||
case 'b': result += '\b'; break;
|
case 'b': result += '\b'; break;
|
||||||
@@ -153,28 +191,29 @@ static void parseSimpleEscape(const QChar *&from, const QChar *to, QString &resu
|
|||||||
|
|
||||||
// Reads subsequent \123 or \x12 entities and converts to Utf8,
|
// Reads subsequent \123 or \x12 entities and converts to Utf8,
|
||||||
// *or* one escaped char, *or* one unescaped char.
|
// *or* one escaped char, *or* one unescaped char.
|
||||||
static void parseCharOrEscape(const QChar *&from, const QChar *to, QString &result)
|
static void parseCharOrEscape(DebuggerOutputParser &parser, QString &result)
|
||||||
{
|
{
|
||||||
QByteArray buffer;
|
QByteArray buffer;
|
||||||
while (parseOctalEscapedHelper(from, to, buffer))
|
while (parseOctalEscapedHelper(parser, buffer))
|
||||||
;
|
;
|
||||||
while (parseHexEscapedHelper(from, to, buffer))
|
while (parseHexEscapedHelper(parser, buffer))
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!buffer.isEmpty())
|
if (!buffer.isEmpty()) {
|
||||||
result.append(QString::fromUtf8(buffer));
|
result.append(QString::fromUtf8(buffer));
|
||||||
else if (*from == '\\')
|
} else if (parser.isCurrent('\\')) {
|
||||||
parseSimpleEscape(++from, to, result);
|
parser.advance();
|
||||||
else
|
parseSimpleEscape(parser, result);
|
||||||
result += *from++;
|
} else {
|
||||||
|
result += parser.readChar();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GdbMi::parseCString(const QChar *&from, const QChar *to)
|
QString DebuggerOutputParser::readCString()
|
||||||
{
|
{
|
||||||
if (to == from)
|
if (isAtEnd())
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
//qDebug() << "parseCString: " << QString(from, to - from);
|
|
||||||
if (*from != '"') {
|
if (*from != '"') {
|
||||||
qDebug() << "MI Parse Error, double quote expected";
|
qDebug() << "MI Parse Error, double quote expected";
|
||||||
++from; // So we don't hang
|
++from; // So we don't hang
|
||||||
@@ -189,82 +228,83 @@ QString GdbMi::parseCString(const QChar *&from, const QChar *to)
|
|||||||
++from;
|
++from;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
parseCharOrEscape(from, to, result);
|
parseCharOrEscape(*this, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "MI Parse Error, unfinished string";
|
qDebug() << "MI Parse Error, unfinished string";
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbMi::parseValue(const QChar *&from, const QChar *to)
|
void GdbMi::parseValue(DebuggerOutputParser &parser)
|
||||||
{
|
{
|
||||||
if (from == to)
|
if (parser.isAtEnd())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//qDebug() << "parseValue: " << QString(from, to - from);
|
//qDebug() << "parseValue: " << parser;
|
||||||
switch (from->unicode()) {
|
switch (parser.current().unicode()) {
|
||||||
case '{':
|
case '{':
|
||||||
parseTuple(from, to);
|
parseTuple(parser);
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
parseList(from, to);
|
parseList(parser);
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
m_type = Const;
|
m_type = Const;
|
||||||
m_data = parseCString(from, to);
|
m_data = parser.readCString();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbMi::parseTuple(const QChar *&from, const QChar *to)
|
void GdbMi::parseTuple(DebuggerOutputParser &parser)
|
||||||
{
|
{
|
||||||
//qDebug() << "parseTuple: " << QString(from, to - from);
|
//qDebug() << "parseTuple: " << parser.buffer();
|
||||||
//QTC_CHECK(*from == '{');
|
QTC_CHECK(parser.isCurrent('{'));
|
||||||
++from;
|
parser.advance();
|
||||||
parseTuple_helper(from, to);
|
parseTuple_helper(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbMi::parseTuple_helper(const QChar *&from, const QChar *to)
|
void GdbMi::parseTuple_helper(DebuggerOutputParser &parser)
|
||||||
{
|
{
|
||||||
skipCommas(from, to);
|
parser.skipCommas();
|
||||||
//qDebug() << "parseTuple_helper: " << QString(from, to - from);
|
//qDebug() << "parseTuple_helper: " << parser.buffer();
|
||||||
|
QString buf = parser.buffer();
|
||||||
m_type = Tuple;
|
m_type = Tuple;
|
||||||
while (from < to) {
|
while (!parser.isAtEnd()) {
|
||||||
if (*from == '}') {
|
if (parser.isCurrent('}')) {
|
||||||
++from;
|
parser.advance();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GdbMi child;
|
GdbMi child;
|
||||||
child.parseResultOrValue(from, to);
|
child.parseResultOrValue(parser);
|
||||||
//qDebug() << "\n=======\n" << qPrintable(child.toString()) << "\n========\n";
|
//qDebug() << "\n=======\n" << qPrintable(child.toString()) << "\n========\n";
|
||||||
if (!child.isValid())
|
if (!child.isValid())
|
||||||
return;
|
return;
|
||||||
m_children.push_back(child);
|
m_children.push_back(child);
|
||||||
skipCommas(from, to);
|
parser.skipCommas();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbMi::parseList(const QChar *&from, const QChar *to)
|
void GdbMi::parseList(DebuggerOutputParser &parser)
|
||||||
{
|
{
|
||||||
//qDebug() << "parseList: " << QString(from, to - from);
|
//qDebug() << "parseList: " << parser.buffer();
|
||||||
//QTC_CHECK(*from == '[');
|
QTC_CHECK(parser.isCurrent('['));
|
||||||
++from;
|
parser.advance();
|
||||||
m_type = List;
|
m_type = List;
|
||||||
skipCommas(from, to);
|
parser.skipCommas();
|
||||||
while (from < to) {
|
while (!parser.isAtEnd()) {
|
||||||
if (*from == ']') {
|
if (parser.isCurrent(']')) {
|
||||||
++from;
|
parser.advance();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GdbMi child;
|
GdbMi child;
|
||||||
child.parseResultOrValue(from, to);
|
child.parseResultOrValue(parser);
|
||||||
if (child.isValid()) {
|
if (child.isValid()) {
|
||||||
m_children.push_back(child);
|
m_children.push_back(child);
|
||||||
skipCommas(from, to);
|
parser.skipCommas();
|
||||||
} else {
|
} else {
|
||||||
++from;
|
parser.advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,16 +409,14 @@ QString GdbMi::toString(bool multiline, int indent) const
|
|||||||
|
|
||||||
void GdbMi::fromString(const QString &ba)
|
void GdbMi::fromString(const QString &ba)
|
||||||
{
|
{
|
||||||
const QChar *from = ba.constBegin();
|
DebuggerOutputParser parser(ba);
|
||||||
const QChar *to = ba.constEnd();
|
parseResultOrValue(parser);
|
||||||
parseResultOrValue(from, to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbMi::fromStringMultiple(const QString &ba)
|
void GdbMi::fromStringMultiple(const QString &ba)
|
||||||
{
|
{
|
||||||
const QChar *from = ba.constBegin();
|
DebuggerOutputParser parser(ba);
|
||||||
const QChar *to = ba.constEnd();
|
parseTuple_helper(parser);
|
||||||
parseTuple_helper(from, to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const GdbMi &GdbMi::operator[](const char *name) const
|
const GdbMi &GdbMi::operator[](const char *name) const
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
namespace Utils { class ProcessHandle; }
|
namespace Utils { class ProcessHandle; }
|
||||||
@@ -125,7 +124,35 @@ public:
|
|||||||
bool m_continue = false;
|
bool m_continue = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: rename into GdbMiValue
|
class DebuggerOutputParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DebuggerOutputParser(const QString &output);
|
||||||
|
|
||||||
|
QChar current() const { return *from; }
|
||||||
|
bool isCurrent(QChar c) const { return *from == c; }
|
||||||
|
bool isAtEnd() const { return from == to; }
|
||||||
|
|
||||||
|
void advance() { ++from; }
|
||||||
|
void advance(int n) { from += n; }
|
||||||
|
QChar lookAhead(int offset) const { return from[offset]; }
|
||||||
|
|
||||||
|
int readInt();
|
||||||
|
QChar readChar();
|
||||||
|
QString readCString();
|
||||||
|
QString readString(const std::function<bool(char)> &isValidChar);
|
||||||
|
|
||||||
|
QString buffer() const { return QString(from, to - from); }
|
||||||
|
int remainingChars() const { return int(to - from); }
|
||||||
|
|
||||||
|
void skipCommas();
|
||||||
|
void skipSpaces();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QChar *from = nullptr;
|
||||||
|
const QChar *to = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class GdbMi
|
class GdbMi
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -163,13 +190,12 @@ public:
|
|||||||
void fromString(const QString &str);
|
void fromString(const QString &str);
|
||||||
void fromStringMultiple(const QString &str);
|
void fromStringMultiple(const QString &str);
|
||||||
|
|
||||||
static QString parseCString(const QChar *&from, const QChar *to);
|
|
||||||
static QString escapeCString(const QString &ba);
|
static QString escapeCString(const QString &ba);
|
||||||
void parseResultOrValue(const QChar *&from, const QChar *to);
|
void parseResultOrValue(DebuggerOutputParser &state);
|
||||||
void parseValue(const QChar *&from, const QChar *to);
|
void parseValue(DebuggerOutputParser &state);
|
||||||
void parseTuple(const QChar *&from, const QChar *to);
|
void parseTuple(DebuggerOutputParser &state);
|
||||||
void parseTuple_helper(const QChar *&from, const QChar *to);
|
void parseTuple_helper(DebuggerOutputParser &state);
|
||||||
void parseList(const QChar *&from, const QChar *to);
|
void parseList(DebuggerOutputParser &state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void dumpChildren(QString *str, bool multiline, int indent) const;
|
void dumpChildren(QString *str, bool multiline, int indent) const;
|
||||||
|
|||||||
@@ -259,45 +259,27 @@ void GdbEngine::handleResponse(const QString &buff)
|
|||||||
if (buff.isEmpty() || buff == "(gdb) ")
|
if (buff.isEmpty() || buff == "(gdb) ")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QChar *from = buff.constData();
|
DebuggerOutputParser parser(buff);
|
||||||
const QChar *to = from + buff.size();
|
|
||||||
const QChar *inner;
|
|
||||||
|
|
||||||
int token = -1;
|
const int token = parser.readInt();
|
||||||
// Token is a sequence of numbers.
|
|
||||||
for (inner = from; inner != to; ++inner)
|
|
||||||
if (*inner < '0' || *inner > '9')
|
|
||||||
break;
|
|
||||||
if (from != inner) {
|
|
||||||
token = QString(from, inner - from).toInt();
|
|
||||||
from = inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next char decides kind of response.
|
// Next char decides kind of response.
|
||||||
const QChar c = *from++;
|
switch (parser.readChar().unicode()) {
|
||||||
switch (c.unicode()) {
|
|
||||||
case '*':
|
case '*':
|
||||||
case '+':
|
case '+':
|
||||||
case '=': {
|
case '=': {
|
||||||
QString asyncClass;
|
const QString asyncClass = parser.readString(isNameChar);
|
||||||
for (; from != to; ++from) {
|
|
||||||
const QChar c = *from;
|
|
||||||
if (!isNameChar(c.unicode()))
|
|
||||||
break;
|
|
||||||
asyncClass += *from;
|
|
||||||
}
|
|
||||||
|
|
||||||
GdbMi result;
|
GdbMi result;
|
||||||
while (from != to) {
|
while (!parser.isAtEnd()) {
|
||||||
GdbMi data;
|
GdbMi data;
|
||||||
if (*from != ',') {
|
if (!parser.isCurrent(',')) {
|
||||||
// happens on archer where we get
|
// happens on archer where we get
|
||||||
// 23^running <NL> *running,thread-id="all" <NL> (gdb)
|
// 23^running <NL> *running,thread-id="all" <NL> (gdb)
|
||||||
result.m_type = GdbMi::Tuple;
|
result.m_type = GdbMi::Tuple;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++from; // skip ','
|
parser.advance(); // skip ','
|
||||||
data.parseResultOrValue(from, to);
|
data.parseResultOrValue(parser);
|
||||||
if (data.isValid()) {
|
if (data.isValid()) {
|
||||||
//qDebug() << "parsed result:" << data.toString();
|
//qDebug() << "parsed result:" << data.toString();
|
||||||
result.addChild(data);
|
result.addChild(data);
|
||||||
@@ -309,7 +291,7 @@ void GdbEngine::handleResponse(const QString &buff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case '~': {
|
case '~': {
|
||||||
QString data = GdbMi::parseCString(from, to);
|
QString data = parser.readCString();
|
||||||
if (data.startsWith("bridgemessage={")) {
|
if (data.startsWith("bridgemessage={")) {
|
||||||
// It's already logged.
|
// It's already logged.
|
||||||
break;
|
break;
|
||||||
@@ -374,14 +356,14 @@ void GdbEngine::handleResponse(const QString &buff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case '@': {
|
case '@': {
|
||||||
QString data = GdbMi::parseCString(from, to);
|
QString data = parser.readCString();
|
||||||
QString msg = data.left(data.size() - 1);
|
QString msg = data.left(data.size() - 1);
|
||||||
showMessage(msg, AppOutput);
|
showMessage(msg, AppOutput);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case '&': {
|
case '&': {
|
||||||
QString data = GdbMi::parseCString(from, to);
|
QString data = parser.readCString();
|
||||||
// On Windows, the contents seem to depend on the debugger
|
// On Windows, the contents seem to depend on the debugger
|
||||||
// version and/or OS version used.
|
// version and/or OS version used.
|
||||||
if (data.startsWith("warning:"))
|
if (data.startsWith("warning:"))
|
||||||
@@ -402,11 +384,8 @@ void GdbEngine::handleResponse(const QString &buff)
|
|||||||
|
|
||||||
response.token = token;
|
response.token = token;
|
||||||
|
|
||||||
for (inner = from; inner != to; ++inner)
|
QString resultClass = parser.readString(isNameChar);
|
||||||
if (*inner < 'a' || *inner > 'z')
|
|
||||||
break;
|
|
||||||
|
|
||||||
QString resultClass = QString::fromRawData(from, inner - from);
|
|
||||||
if (resultClass == "done")
|
if (resultClass == "done")
|
||||||
response.resultClass = ResultDone;
|
response.resultClass = ResultDone;
|
||||||
else if (resultClass == "running")
|
else if (resultClass == "running")
|
||||||
@@ -420,11 +399,10 @@ void GdbEngine::handleResponse(const QString &buff)
|
|||||||
else
|
else
|
||||||
response.resultClass = ResultUnknown;
|
response.resultClass = ResultUnknown;
|
||||||
|
|
||||||
from = inner;
|
if (!parser.isAtEnd()) {
|
||||||
if (from != to) {
|
if (parser.isCurrent(',')) {
|
||||||
if (*from == ',') {
|
parser.advance();
|
||||||
++from;
|
response.data.parseTuple_helper(parser);
|
||||||
response.data.parseTuple_helper(from, to);
|
|
||||||
response.data.m_type = GdbMi::Tuple;
|
response.data.m_type = GdbMi::Tuple;
|
||||||
response.data.m_name = "data";
|
response.data.m_name = "data";
|
||||||
} else {
|
} else {
|
||||||
@@ -446,7 +424,8 @@ void GdbEngine::handleResponse(const QString &buff)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
qDebug() << "UNKNOWN RESPONSE TYPE '" << c << "'. REST: " << from;
|
qDebug() << "UNKNOWN RESPONSE TYPE '" << parser.current() << "'. BUFFER: "
|
||||||
|
<< parser.buffer();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,9 +46,8 @@ void tst_protocol::parseCString()
|
|||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(QString, expected);
|
QFETCH(QString, expected);
|
||||||
|
|
||||||
const QChar *from = input.begin();
|
Debugger::Internal::DebuggerOutputParser parser(input);
|
||||||
const QChar *to = input.end();
|
QString parsed = parser.readCString();
|
||||||
QString parsed = Debugger::Internal::GdbMi::parseCString(from, to);
|
|
||||||
|
|
||||||
QCOMPARE(parsed, expected);
|
QCOMPARE(parsed, expected);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user