diff options
author | Friedemann Kleint <[email protected]> | 2009-07-03 13:56:27 +0200 |
---|---|---|
committer | Friedemann Kleint <[email protected]> | 2009-07-03 13:56:27 +0200 |
commit | 5a8b61b2ee6a9ebcb91f351bb0212f6ad40f9064 (patch) | |
tree | 3e26c4664a1870c64743c4da501db3bfa404160f /src/plugins/debugger/watchutils.cpp | |
parent | 89d49e3b2052ef96245e5e786d5f509ba4ac818b (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.cpp | 128 |
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; } |