aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/debugger/watchutils.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <[email protected]>2009-07-03 13:56:27 +0200
committerFriedemann Kleint <[email protected]>2009-07-03 13:56:27 +0200
commit5a8b61b2ee6a9ebcb91f351bb0212f6ad40f9064 (patch)
tree3e26c4664a1870c64743c4da501db3bfa404160f /src/plugins/debugger/watchutils.cpp
parent89d49e3b2052ef96245e5e786d5f509ba4ac818b (diff)
Great debugger helper bug fixing spree.
- Fix extractTemplate() not to kill blanks in case there is no blank after a comma, fix hardcoded types accordingly. - Make niceType()'s regexps ignore blanks after commas, add unsigned short as char_type and cache the mappings, making them work for CDB. - CDB: Parse map output of dumpers correctly, generally don't confuse the parser by unknown keywords encountered when parsing children, thus enabling simple QMap types. - Make dumpInnerValueHelper output std::string types.
Diffstat (limited to 'src/plugins/debugger/watchutils.cpp')
-rw-r--r--src/plugins/debugger/watchutils.cpp128
1 files changed, 92 insertions, 36 deletions
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 0263ca51a83..5ef9523ed45 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -266,30 +266,43 @@ bool extractTemplate(const QString &type, QString *tmplate, QString *inner)
// Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in
// 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates
// whether parsing was successful
+ // Gdb inserts a blank after each comma which we would like to avoid
+ tmplate->clear();
+ inner->clear();
+ if (!type.contains(QLatin1Char('<')))
+ return false;
int level = 0;
bool skipSpace = false;
+ const int size = type.size();
- for (int i = 0; i != type.size(); ++i) {
+ for (int i = 0; i != size; ++i) {
const QChar c = type.at(i);
- if (c == QLatin1Char(' ') && skipSpace) {
- skipSpace = false;
- } else if (c == QLatin1Char('<')) {
+ const char asciiChar = c.toAscii();
+ switch (asciiChar) {
+ case '<':
*(level == 0 ? tmplate : inner) += c;
++level;
- } else if (c == QLatin1Char('>')) {
+ break;
+ case '>':
--level;
*(level == 0 ? tmplate : inner) += c;
- } else if (c == QLatin1Char(',')) {
+ break;
+ case ',':
*inner += (level == 1) ? QLatin1Char('@') : QLatin1Char(',');
skipSpace = true;
- } else {
- *(level == 0 ? tmplate : inner) += c;
+ break;
+ default:
+ if (!skipSpace || asciiChar != ' ') {
+ *(level == 0 ? tmplate : inner) += c;
+ skipSpace = false;
+ }
+ break;
}
}
*tmplate = tmplate->trimmed();
*tmplate = tmplate->remove(QLatin1String("<>"));
*inner = inner->trimmed();
- //qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
+ // qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
return !inner->isEmpty();
}
@@ -408,7 +421,7 @@ bool isCppEditor(Core::IEditor *editor)
// Find the function the cursor is in to use a scope.
-
+
// Return the Cpp expression, and, if desired, the function
@@ -442,7 +455,7 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
const QTextCursor tc = plaintext->textCursor();
*column = tc.columnNumber();
*line = tc.blockNumber();
- }
+ }
if (function && !expr.isEmpty())
if (const Core::IFile *file = editor->file())
@@ -455,6 +468,7 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
// --------------- QtDumperResult
QtDumperResult::Child::Child() :
+ keyEncoded(0),
valueEncoded(0),
childCount(0),
valuedisabled(false)
@@ -475,6 +489,7 @@ void QtDumperResult::clear()
value.clear();
address.clear();
type.clear();
+ extra.clear();
displayedType.clear();
valueEncoded = 0;
valuedisabled = false;
@@ -509,8 +524,17 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
wchild.source = source;
wchild.iname = iname;
wchild.iname += dot;
- wchild.iname += dchild.name;
- wchild.name = dchild.name;
+ wchild.iname += dchild.name;
+ // Use key entry as name (which is used for map nodes)
+ if (dchild.key.isEmpty()) {
+ wchild.name = dchild.name;
+ } else {
+ wchild.name = decodeData(dchild.key, dchild.keyEncoded);
+ if (wchild.name.size() > 13) {
+ wchild.name.truncate(12);
+ wchild.name += QLatin1String("...");
+ }
+ }
wchild.exp = dchild.exp;
wchild.valuedisabled = dchild.valuedisabled;
wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
@@ -533,18 +557,21 @@ QDebug operator<<(QDebug in, const QtDumperResult &d)
<< " address=" << d.address
<< " value=" << d.value
<< " disabled=" << d.valuedisabled
- << " encoded=" << d.valueEncoded << " internal=" << d.internal;
+ << " encoded=" << d.valueEncoded << " internal=" << d.internal
+ << " extra='" << d.extra << "'\n";
const int realChildCount = d.children.size();
if (d.childCount || realChildCount) {
- nospace << " childCount=" << d.childCount << '/' << realChildCount
+ nospace << "childCount=" << d.childCount << '/' << realChildCount
<< " childType=" << d.childType << '\n';
for (int i = 0; i < realChildCount; i++) {
const QtDumperResult::Child &c = d.children.at(i);
nospace << " #" << i << " addr=" << c.address
<< " disabled=" << c.valuedisabled
<< " type=" << c.type << " exp=" << c.exp
- << " name=" << c.name << " encoded=" << c.valueEncoded
- << " value=" << c.value
+ << " name=" << c.name;
+ if (!c.key.isEmpty())
+ nospace << " keyencoded=" << c.keyEncoded << " key=" << c.key;
+ nospace << " valueencoded=" << c.valueEncoded << " value=" << c.value
<< "childcount=" << c.childCount << '\n';
}
}
@@ -770,6 +797,7 @@ class DumperParser
public:
explicit DumperParser(const char *s) : m_s(s) {}
bool run();
+ virtual ~DumperParser() {}
protected:
// handle 'key="value"'
@@ -833,9 +861,9 @@ bool DumperParser::parseHash(int level, const char *&pos)
return false;
pos = equalsPtr + 1;
if (!*pos)
- return false;
+ return false;
if (!parseValue(level + 1, pos))
- return false;
+ return false;
if (*pos == ',')
pos++;
}
@@ -871,7 +899,7 @@ bool DumperParser::parseValue(int level, const char *&pos)
if (*pos == ',')
pos++;
}
- }
+ }
return false;
// A hash '{a="b",b="c"}'
case '{': {
@@ -879,7 +907,7 @@ bool DumperParser::parseValue(int level, const char *&pos)
return false;
pos++;
if (!parseHash(level + 1, pos))
- return false;
+ return false;
return handleHashEnd();
}
return false;
@@ -952,7 +980,7 @@ public:
protected:
virtual bool handleKeyword(const char *k, int size);
- virtual bool handleListStart();
+ virtual bool handleListStart();
virtual bool handleListEnd();
virtual bool handleHashEnd();
virtual bool handleValue(const char *k, int size);
@@ -972,7 +1000,7 @@ QueryDumperParser::QueryDumperParser(const char *s) :
{
}
-bool QueryDumperParser::handleKeyword(const char *k, int size)
+bool QueryDumperParser::handleKeyword(const char *k, int size)
{
switch (m_mode) {
case ExpectingSizes:
@@ -1064,7 +1092,6 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
addSize(se.first, se.second);
m_expressionCache = parser.data().expressionCache;
- qDebug() << m_expressionCache;
return true;
}
@@ -1081,13 +1108,15 @@ void QtDumperHelper::addSize(const QString &name, int size)
return;
}
do {
+ // CDB helpers
if (name == QLatin1String("std::string")) {
- m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char>>"), size);
+ m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), size);
+ m_sizeCache.insert(QLatin1String("basic_string<char,char_traits<char>,allocator<char> >"), size);
break;
}
if (name == QLatin1String("std::wstring")) {
- // FIXME: check space between > > below?
- m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsignedshort>,std::allocator<unsignedshort> >"), size);
+ m_sizeCache.insert(QLatin1String("basic_string<unsigned short,char_traits<unsignedshort>,allocator<unsignedshort> >"), size);
+ m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"), size);
break;
}
} while (false);
@@ -1297,10 +1326,16 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
// But we need the offset of the second item in the value pair.
// We read the type of the pair from the allocator argument because
// that gets the constness "right" (in the sense that gdb can
- // read it back;
+ // read it back: "std::allocator<std::pair<Key,Value> >"
+ // -> "std::pair<Key,Value>". Different debuggers have varying
+ // amounts of terminating blanks...
QString pairType = inners.at(3);
- // remove 'std::allocator<...>':
- pairType = pairType.mid(15, pairType.size() - 15 - 2);
+ int bracketPos = pairType.indexOf(QLatin1Char('<'));
+ if (bracketPos != -1)
+ pairType.remove(0, bracketPos + 1);
+ bracketPos = pairType.indexOf(QLatin1Char('>'));
+ if (bracketPos != -1)
+ pairType.truncate(bracketPos + 1);
extraArgs[2] = QLatin1String("(size_t)&(('");
extraArgs[2] += pairType;
extraArgs[2] += QLatin1String("'*)0)->second");
@@ -1377,12 +1412,15 @@ private:
ExpectingType, ExpectingDisplayedType, ExpectingInternal,
ExpectingValueDisabled, ExpectingValueEncoded,
ExpectingCommonChildType, ExpectingChildCount,
+ ExpectingExtra,
IgnoreNext,
ChildModeStart,
ExpectingChildren,ExpectingChildName, ExpectingChildAddress,
ExpectingChildExpression, ExpectingChildType,
+ ExpectingChildKey, ExpectingChildKeyEncoded,
ExpectingChildValue, ExpectingChildValueEncoded,
- ExpectingChildValueDisabled, ExpectingChildChildCount
+ ExpectingChildValueDisabled, ExpectingChildChildCount,
+ IgnoreNextChildMode
};
static inline Mode nextMode(Mode in, const char *keyword, int size);
@@ -1405,6 +1443,8 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
case 3:
if (!qstrncmp(keyword, "exp", size))
return ExpectingChildExpression;
+ if (!qstrncmp(keyword, "key", size))
+ return ExpectingChildKey;
break;
case 4:
if (!qstrncmp(keyword, "addr", size))
@@ -1419,6 +1459,8 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
return ExpectingIName;
if (!qstrncmp(keyword, "value", size))
return in > ChildModeStart ? ExpectingChildValue : ExpectingValue;
+ if (!qstrncmp(keyword, "extra", size))
+ return ExpectingExtra;
break;
case 8:
if (!qstrncmp(keyword, "children", size))
@@ -1431,7 +1473,11 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
case 9:
if (!qstrncmp(keyword, "childtype", size))
return ExpectingCommonChildType;
- break;
+ break;
+ case 10:
+ if (!qstrncmp(keyword, "keyencoded", size))
+ return ExpectingChildKeyEncoded;
+ break;
case 12:
if (!qstrncmp(keyword, "valueencoded", size))
return in > ChildModeStart ? ExpectingChildValueEncoded : ExpectingValueEncoded;
@@ -1442,10 +1488,10 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
if (!qstrncmp(keyword, "displayedtype", size))
return ExpectingDisplayedType;
if (!qstrncmp(keyword, "childnumchild", size))
- return IgnoreNext;
+ return IgnoreNextChildMode;
break;
}
- return IgnoreNext;
+ return in > ChildModeStart ? IgnoreNextChildMode : IgnoreNext;
}
bool ValueDumperParser::handleKeyword(const char *k, int size)
@@ -1491,6 +1537,9 @@ bool ValueDumperParser::handleValue(const char *k, int size)
case ExpectingDisplayedType:
m_result.displayedType = QString::fromLatin1(valueBA);
break;
+ case ExpectingExtra:
+ m_result.extra = valueBA;
+ break;
case ExpectingInternal:
m_result.internal = valueBA == "true";
break;
@@ -1501,6 +1550,7 @@ bool ValueDumperParser::handleValue(const char *k, int size)
m_result.childCount = QString::fromLatin1(valueBA).toInt();
break;
case ExpectingChildren:
+ case IgnoreNextChildMode:
case IgnoreNext:
break;
case ExpectingChildName:
@@ -1509,6 +1559,12 @@ bool ValueDumperParser::handleValue(const char *k, int size)
case ExpectingChildAddress:
m_result.children.back().address = QString::fromLatin1(valueBA);
break;
+ case ExpectingChildKeyEncoded:
+ m_result.children.back().keyEncoded = QString::fromLatin1(valueBA).toInt();
+ break;
+ case ExpectingChildKey:
+ m_result.children.back().key = valueBA;
+ break;
case ExpectingChildValue:
m_result.children.back().value = valueBA;
break;
@@ -1532,7 +1588,7 @@ bool ValueDumperParser::handleValue(const char *k, int size)
}
bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
-{
+{
ValueDumperParser parser(data);
if (!parser.run())
return false;
@@ -1541,7 +1597,7 @@ bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
if (r->childCount < r->children.size())
r->childCount = r->children.size();
if (debug)
- qDebug() << '\n' << data << *r;
+ qDebug() << '\n' << data << '\n' << *r;
return true;
}