forked from qt-creator/qt-creator
Debugger[New CDB]: Fix flag handling and expanding of list children.
Suppress repetitive invocation of dumper evaluation. Use parseWatchData() as does gdb.
This commit is contained in:
@@ -73,4 +73,12 @@ ULONG currentThreadId(CIDebugClient *client);
|
|||||||
ULONG currentProcessId(IDebugSystemObjects *sysObjects);
|
ULONG currentProcessId(IDebugSystemObjects *sysObjects);
|
||||||
ULONG currentProcessId(CIDebugClient *client);
|
ULONG currentProcessId(CIDebugClient *client);
|
||||||
|
|
||||||
|
#ifdef QTC_TRACE
|
||||||
|
# define QTC_TRACE_IN dprintf(">%s\n", __FUNCTION__);
|
||||||
|
# define QTC_TRACE_OUT dprintf("<%s\n", __FUNCTION__);
|
||||||
|
#else
|
||||||
|
# define QTC_TRACE_IN
|
||||||
|
# define QTC_TRACE_OUT
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // COMMON_H
|
#endif // COMMON_H
|
||||||
|
|||||||
@@ -39,9 +39,12 @@ typedef AbstractSymbolGroupNode::AbstractSymbolGroupNodePtrVector AbstractSymbol
|
|||||||
// Return size of container or -1
|
// Return size of container or -1
|
||||||
int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx)
|
int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx)
|
||||||
{
|
{
|
||||||
|
QTC_TRACE_IN
|
||||||
if ((kt & KT_ContainerType) == 0)
|
if ((kt & KT_ContainerType) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
return containerSize(kt, SymbolGroupValue(n, ctx));
|
const int ct = containerSize(kt, SymbolGroupValue(n, ctx));
|
||||||
|
QTC_TRACE_OUT
|
||||||
|
return ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return size from an STL vector (last/first iterators).
|
// Return size from an STL vector (last/first iterators).
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ static inline std::string msgNotFound(const std::string &nodeName)
|
|||||||
std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
|
std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
|
||||||
const DumpParameters &p) const
|
const DumpParameters &p) const
|
||||||
{
|
{
|
||||||
|
QTC_TRACE_IN
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "<SymbolGroup::dump()";
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
|
DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
|
||||||
if (p.humanReadable())
|
if (p.humanReadable())
|
||||||
@@ -192,6 +195,9 @@ std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
|
|||||||
str << '[';
|
str << '[';
|
||||||
accept(visitor);
|
accept(visitor);
|
||||||
str << ']';
|
str << ']';
|
||||||
|
QTC_TRACE_OUT
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "<SymbolGroup::dump()";
|
||||||
return str.str();
|
return str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +207,9 @@ std::string SymbolGroup::dump(const std::string &iname,
|
|||||||
const DumpParameters &p,
|
const DumpParameters &p,
|
||||||
std::string *errorMessage)
|
std::string *errorMessage)
|
||||||
{
|
{
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << ">SymbolGroup::dump(" << iname << ")";
|
||||||
|
QTC_TRACE_IN
|
||||||
AbstractSymbolGroupNode *const aNode = find(iname);
|
AbstractSymbolGroupNode *const aNode = find(iname);
|
||||||
if (!aNode) {
|
if (!aNode) {
|
||||||
*errorMessage = msgNotFound(iname);
|
*errorMessage = msgNotFound(iname);
|
||||||
@@ -208,7 +217,7 @@ std::string SymbolGroup::dump(const std::string &iname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Real nodes: Expand and complex dumpers
|
// Real nodes: Expand and complex dumpers
|
||||||
if (SymbolGroupNode *node = aNode->asSymbolGroupNode()) {
|
if (SymbolGroupNode *node = aNode->resolveReference()->asSymbolGroupNode()) {
|
||||||
if (node->isExpanded()) { // Mark expand request by watch model
|
if (node->isExpanded()) { // Mark expand request by watch model
|
||||||
node->clearFlags(SymbolGroupNode::ExpandedByDumper);
|
node->clearFlags(SymbolGroupNode::ExpandedByDumper);
|
||||||
} else {
|
} else {
|
||||||
@@ -227,6 +236,9 @@ std::string SymbolGroup::dump(const std::string &iname,
|
|||||||
str << '[';
|
str << '[';
|
||||||
aNode->accept(visitor, SymbolGroupNodeVisitor::parentIname(iname), 0, 0);
|
aNode->accept(visitor, SymbolGroupNodeVisitor::parentIname(iname), 0, 0);
|
||||||
str << ']';
|
str << ']';
|
||||||
|
QTC_TRACE_OUT
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "<SymbolGroup::dump(" << iname << ")";
|
||||||
return str.str();
|
return str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +303,8 @@ static inline InamePathEntrySet expandEntrySet(const std::vector<std::string> &n
|
|||||||
// Expand a node list "locals.i1,locals.i2"
|
// Expand a node list "locals.i1,locals.i2"
|
||||||
unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::string *errorMessage)
|
unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::string *errorMessage)
|
||||||
{
|
{
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << ">SymbolGroup::expandList" << nodes.size();
|
||||||
if (nodes.empty())
|
if (nodes.empty())
|
||||||
return 0;
|
return 0;
|
||||||
// Create a set with a key <level, name>. Also required for 1 node (see above).
|
// Create a set with a key <level, name>. Also required for 1 node (see above).
|
||||||
@@ -307,6 +321,8 @@ unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::str
|
|||||||
errorMessage->append(", ");
|
errorMessage->append(", ");
|
||||||
errorMessage->append(nodeError);
|
errorMessage->append(nodeError);
|
||||||
}
|
}
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "<SymbolGroup::expandList returns " << succeeded;
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +330,9 @@ unsigned SymbolGroup::expandListRunComplexDumpers(const std::vector<std::string>
|
|||||||
const SymbolGroupValueContext &ctx,
|
const SymbolGroupValueContext &ctx,
|
||||||
std::string *errorMessage)
|
std::string *errorMessage)
|
||||||
{
|
{
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << ">SymbolGroup::expandListRunComplexDumpers" << nodes.size();
|
||||||
|
QTC_TRACE_IN
|
||||||
if (nodes.empty())
|
if (nodes.empty())
|
||||||
return 0;
|
return 0;
|
||||||
// Create a set with a key <level, name>. Also required for 1 node (see above).
|
// Create a set with a key <level, name>. Also required for 1 node (see above).
|
||||||
@@ -330,6 +349,9 @@ unsigned SymbolGroup::expandListRunComplexDumpers(const std::vector<std::string>
|
|||||||
errorMessage->append(", ");
|
errorMessage->append(", ");
|
||||||
errorMessage->append(nodeError);
|
errorMessage->append(nodeError);
|
||||||
}
|
}
|
||||||
|
QTC_TRACE_OUT
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "<SymbolGroup::expandListRunComplexDumpers returns " << succeeded;
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
enum { debug = 0 };
|
|
||||||
|
|
||||||
typedef std::vector<int>::size_type VectorIndexType;
|
typedef std::vector<int>::size_type VectorIndexType;
|
||||||
typedef std::vector<std::string> StringVector;
|
typedef std::vector<std::string> StringVector;
|
||||||
|
|
||||||
@@ -49,6 +47,43 @@ static inline void indentStream(std::ostream &str, unsigned depth)
|
|||||||
str << " ";
|
str << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void debugNodeFlags(std::ostream &str, unsigned f)
|
||||||
|
{
|
||||||
|
if (!f)
|
||||||
|
return;
|
||||||
|
str << " node-flags=" << f;
|
||||||
|
if (f & SymbolGroupNode::Uninitialized)
|
||||||
|
str << " UNINITIALIZED";
|
||||||
|
if (f & SymbolGroupNode::SimpleDumperNotApplicable)
|
||||||
|
str << " DumperNotApplicable";
|
||||||
|
if (f & SymbolGroupNode::SimpleDumperOk)
|
||||||
|
str << " DumperOk";
|
||||||
|
if (f & SymbolGroupNode::SimpleDumperFailed)
|
||||||
|
str << " DumperFailed";
|
||||||
|
if (f & SymbolGroupNode::ExpandedByDumper)
|
||||||
|
str << " ExpandedByDumper";
|
||||||
|
if (f & SymbolGroupNode::AdditionalSymbol)
|
||||||
|
str << " AdditionalSymbol";
|
||||||
|
if (f & SymbolGroupNode::Obscured)
|
||||||
|
str << " Obscured";
|
||||||
|
if (f & SymbolGroupNode::ComplexDumperOk)
|
||||||
|
str << " ComplexDumperOk";
|
||||||
|
str << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some helper to conveniently dump flags to a stream
|
||||||
|
struct DebugNodeFlags
|
||||||
|
{
|
||||||
|
DebugNodeFlags(unsigned f) : m_f(f) {}
|
||||||
|
const unsigned m_f;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &str, const DebugNodeFlags &f)
|
||||||
|
{
|
||||||
|
debugNodeFlags(str, f.m_f);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
// -------------- AbstractSymbolGroupNode
|
// -------------- AbstractSymbolGroupNode
|
||||||
|
|
||||||
AbstractSymbolGroupNode::AbstractSymbolGroupNode(const std::string &name,
|
AbstractSymbolGroupNode::AbstractSymbolGroupNode(const std::string &name,
|
||||||
@@ -704,9 +739,13 @@ std::wstring SymbolGroupNode::symbolGroupFixedValue() const
|
|||||||
// Complex dumpers: Get container/fake children
|
// Complex dumpers: Get container/fake children
|
||||||
void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx)
|
void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx)
|
||||||
{
|
{
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "SymbolGroupNode::runComplexDumpers " << name() << '/'
|
||||||
|
<< absoluteFullIName() << ' ' << m_index << DebugNodeFlags(flags());
|
||||||
|
|
||||||
if (m_dumperContainerSize <= 0 || (testFlags(ComplexDumperOk) || !testFlags(SimpleDumperOk)))
|
if (m_dumperContainerSize <= 0 || (testFlags(ComplexDumperOk) || !testFlags(SimpleDumperOk)))
|
||||||
return;
|
return;
|
||||||
setFlags(ComplexDumperOk);
|
addFlags(ComplexDumperOk);
|
||||||
const AbstractSymbolGroupNodePtrVector ctChildren =
|
const AbstractSymbolGroupNodePtrVector ctChildren =
|
||||||
containerChildren(this, m_dumperType, m_dumperContainerSize, ctx);
|
containerChildren(this, m_dumperType, m_dumperContainerSize, ctx);
|
||||||
m_dumperContainerSize = int(ctChildren.size()); // Just in case...
|
m_dumperContainerSize = int(ctChildren.size()); // Just in case...
|
||||||
@@ -726,19 +765,31 @@ void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run dumpers, format simple in-line dumper value and retrieve fake children
|
// Run dumpers, format simple in-line dumper value and retrieve fake children
|
||||||
|
bool SymbolGroupNode::runSimpleDumpers(const SymbolGroupValueContext &ctx)
|
||||||
|
{
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "SymbolGroupNode::runSimpleDumpers " << name() << '/'
|
||||||
|
<< absoluteFullIName() << ' ' << m_index << DebugNodeFlags(flags());
|
||||||
|
if (testFlags(Uninitialized))
|
||||||
|
return false;
|
||||||
|
if (testFlags(SimpleDumperOk))
|
||||||
|
return true;
|
||||||
|
if (testFlags(SimpleDumperMask))
|
||||||
|
return false;
|
||||||
|
addFlags(dumpSimpleType(this , ctx, &m_dumperValue,
|
||||||
|
&m_dumperType, &m_dumperContainerSize));
|
||||||
|
if (symbolGroupDebug)
|
||||||
|
DebugPrint() << "-> '" << wStringToString(m_dumperValue) << "' Type="
|
||||||
|
<< m_dumperType << ' ' << DebugNodeFlags(flags());
|
||||||
|
return testFlags(SimpleDumperOk);
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx)
|
std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx)
|
||||||
{
|
{
|
||||||
if (testFlags(Uninitialized))
|
if (testFlags(Uninitialized))
|
||||||
return L"<not in scope>";
|
return L"<not in scope>";
|
||||||
if (testFlags(SimpleDumperOk))
|
if (runSimpleDumpers(ctx))
|
||||||
return m_dumperValue;
|
return m_dumperValue;
|
||||||
if ((flags() & SimpleDumperMask) == 0) {
|
|
||||||
const unsigned dumperFlags = dumpSimpleType(this , ctx, &m_dumperValue,
|
|
||||||
&m_dumperType, &m_dumperContainerSize);
|
|
||||||
setFlags(dumperFlags);
|
|
||||||
if (testFlags(SimpleDumperOk))
|
|
||||||
return m_dumperValue;
|
|
||||||
}
|
|
||||||
return symbolGroupFixedValue();
|
return symbolGroupFixedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,28 +865,7 @@ void SymbolGroupNode::debug(std::ostream &str,
|
|||||||
str << "\",index=" << m_index;
|
str << "\",index=" << m_index;
|
||||||
if (const VectorIndexType childCount = children().size())
|
if (const VectorIndexType childCount = children().size())
|
||||||
str << ", Children=" << childCount;
|
str << ", Children=" << childCount;
|
||||||
str << ' ' << m_parameters;
|
str << ' ' << m_parameters << DebugNodeFlags(flags());
|
||||||
const unsigned f = flags();
|
|
||||||
if (f) {
|
|
||||||
str << " node-flags=" << f;
|
|
||||||
if (f & Uninitialized)
|
|
||||||
str << " UNINITIALIZED";
|
|
||||||
if (f & SimpleDumperNotApplicable)
|
|
||||||
str << " DumperNotApplicable";
|
|
||||||
if (f & SimpleDumperOk)
|
|
||||||
str << " DumperOk";
|
|
||||||
if (f & SimpleDumperFailed)
|
|
||||||
str << " DumperFailed";
|
|
||||||
if (f & ExpandedByDumper)
|
|
||||||
str << " ExpandedByDumper";
|
|
||||||
if (f & AdditionalSymbol)
|
|
||||||
str << " AdditionalSymbol";
|
|
||||||
if (f & Obscured)
|
|
||||||
str << " Obscured";
|
|
||||||
if (f & ComplexDumperOk)
|
|
||||||
str << " ComplexDumperOk";
|
|
||||||
str << ' ';
|
|
||||||
}
|
|
||||||
if (verbosity) {
|
if (verbosity) {
|
||||||
str << ",name=\"" << name() << "\", Address=0x" << std::hex << address() << std::dec
|
str << ",name=\"" << name() << "\", Address=0x" << std::hex << address() << std::dec
|
||||||
<< " Type=\"" << type() << '"';
|
<< " Type=\"" << type() << '"';
|
||||||
@@ -848,7 +878,7 @@ void SymbolGroupNode::debug(std::ostream &str,
|
|||||||
if (m_dumperType & KT_ContainerType)
|
if (m_dumperType & KT_ContainerType)
|
||||||
str << " container(" << m_dumperContainerSize << ')';
|
str << " container(" << m_dumperContainerSize << ')';
|
||||||
}
|
}
|
||||||
if (!(f & Uninitialized))
|
if (!testFlags(Uninitialized))
|
||||||
str << " Value=\"" << gdbmiWStringFormat(symbolGroupRawValue()) << '"';
|
str << " Value=\"" << gdbmiWStringFormat(symbolGroupRawValue()) << '"';
|
||||||
str << '\n'; // Potentially multiline
|
str << '\n'; // Potentially multiline
|
||||||
}
|
}
|
||||||
@@ -869,8 +899,10 @@ static inline std::string msgCannotCast(const std::string &nodeName,
|
|||||||
// Expand!
|
// Expand!
|
||||||
bool SymbolGroupNode::expand(std::string *errorMessage)
|
bool SymbolGroupNode::expand(std::string *errorMessage)
|
||||||
{
|
{
|
||||||
if (::debug > 1)
|
if (symbolGroupDebug)
|
||||||
DebugPrint() << "SymbolGroupNode::expand " << name() << ' ' << m_index;
|
DebugPrint() << "SymbolGroupNode::expand " << name()
|
||||||
|
<<'/' << absoluteFullIName() << ' '
|
||||||
|
<< m_index << DebugNodeFlags(flags());
|
||||||
if (isExpanded()) {
|
if (isExpanded()) {
|
||||||
// Clear the flag indication dumper expansion on a second, explicit request
|
// Clear the flag indication dumper expansion on a second, explicit request
|
||||||
clearFlags(ExpandedByDumper);
|
clearFlags(ExpandedByDumper);
|
||||||
@@ -912,8 +944,8 @@ bool SymbolGroupNode::expandRunComplexDumpers(const SymbolGroupValueContext &ctx
|
|||||||
return true;
|
return true;
|
||||||
if (!expand(errorMessage))
|
if (!expand(errorMessage))
|
||||||
return false;
|
return false;
|
||||||
simpleDumpValue(ctx); // Run simple dumpers to obtain type and run complex dumpers
|
// Run simple dumpers to obtain type and run complex dumpers
|
||||||
if (testFlags(SimpleDumperOk))
|
if (runSimpleDumpers(ctx) && testFlags(SimpleDumperOk))
|
||||||
runComplexDumpers(ctx);
|
runComplexDumpers(ctx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
|
enum { symbolGroupDebug = 0 };
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
|
std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
|
||||||
|
|
||||||
class SymbolGroupNodeVisitor;
|
class SymbolGroupNodeVisitor;
|
||||||
@@ -100,7 +102,6 @@ public:
|
|||||||
|
|
||||||
unsigned flags() const { return m_flags; }
|
unsigned flags() const { return m_flags; }
|
||||||
bool testFlags(unsigned f) const { return (m_flags & f) != 0; }
|
bool testFlags(unsigned f) const { return (m_flags & f) != 0; }
|
||||||
void setFlags(unsigned f) { m_flags = f; }
|
|
||||||
void addFlags(unsigned f) { m_flags |= f; }
|
void addFlags(unsigned f) { m_flags |= f; }
|
||||||
void clearFlags(unsigned f) { m_flags &= ~f; }
|
void clearFlags(unsigned f) { m_flags &= ~f; }
|
||||||
|
|
||||||
@@ -249,6 +250,7 @@ private:
|
|||||||
bool isArrayElement() const;
|
bool isArrayElement() const;
|
||||||
// Notify about expansion of a node, shift indexes
|
// Notify about expansion of a node, shift indexes
|
||||||
bool notifyExpanded(ULONG index, ULONG insertedCount);
|
bool notifyExpanded(ULONG index, ULONG insertedCount);
|
||||||
|
bool runSimpleDumpers(const SymbolGroupValueContext &ctx);
|
||||||
std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
|
std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
|
||||||
|
|
||||||
SymbolGroup *const m_symbolGroup;
|
SymbolGroup *const m_symbolGroup;
|
||||||
|
|||||||
@@ -1086,6 +1086,7 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
|
|||||||
std::wstring *s, int *knownTypeIn /* = 0 */,
|
std::wstring *s, int *knownTypeIn /* = 0 */,
|
||||||
int *containerSizeIn /* = 0 */)
|
int *containerSizeIn /* = 0 */)
|
||||||
{
|
{
|
||||||
|
QTC_TRACE_IN
|
||||||
if (containerSizeIn)
|
if (containerSizeIn)
|
||||||
*containerSizeIn = -1;
|
*containerSizeIn = -1;
|
||||||
// Check for class types and strip pointer types (references appear as pointers as well)
|
// Check for class types and strip pointer types (references appear as pointers as well)
|
||||||
@@ -1094,8 +1095,10 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
|
|||||||
if (knownTypeIn)
|
if (knownTypeIn)
|
||||||
*knownTypeIn = kt;
|
*knownTypeIn = kt;
|
||||||
|
|
||||||
if (kt == KT_Unknown)
|
if (kt == KT_Unknown) {
|
||||||
|
QTC_TRACE_OUT
|
||||||
return SymbolGroupNode::SimpleDumperNotApplicable;
|
return SymbolGroupNode::SimpleDumperNotApplicable;
|
||||||
|
}
|
||||||
|
|
||||||
const SymbolGroupValue v(n, ctx);
|
const SymbolGroupValue v(n, ctx);
|
||||||
// Simple dump of size for containers
|
// Simple dump of size for containers
|
||||||
@@ -1175,5 +1178,6 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
|
|||||||
}
|
}
|
||||||
if (rc == SymbolGroupNode::SimpleDumperOk)
|
if (rc == SymbolGroupNode::SimpleDumperOk)
|
||||||
*s = str.str();
|
*s = str.str();
|
||||||
|
QTC_TRACE_OUT
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1189,21 +1189,27 @@ void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
|
|||||||
{
|
{
|
||||||
if (reply->success) {
|
if (reply->success) {
|
||||||
QList<Debugger::Internal::WatchData> watchData;
|
QList<Debugger::Internal::WatchData> watchData;
|
||||||
if (Debugger::Internal::QtDumperHelper::parseValue(reply->reply.constData(), &watchData)) {
|
GdbMi root;
|
||||||
for (int i = 0; i < watchData.size(); i++)
|
root.fromString(reply->reply);
|
||||||
watchData[i].setAllUnneeded();
|
QTC_ASSERT(root.isList(), return ; )
|
||||||
if (debug > 1) {
|
if (debugLocals) {
|
||||||
|
qDebug() << root.toString(true, 4);
|
||||||
|
}
|
||||||
|
// Courtesy of GDB engine
|
||||||
|
foreach (const GdbMi &child, root.children()) {
|
||||||
|
WatchData dummy;
|
||||||
|
dummy.iname = child.findChild("iname").data();
|
||||||
|
dummy.name = QLatin1String(child.findChild("name").data());
|
||||||
|
parseWatchData(watchHandler()->expandedINames(), dummy, child, &watchData);
|
||||||
|
}
|
||||||
|
watchHandler()->insertBulkData(watchData);
|
||||||
|
watchHandler()->endCycle();
|
||||||
|
if (debugLocals) {
|
||||||
QDebug nsp = qDebug().nospace();
|
QDebug nsp = qDebug().nospace();
|
||||||
nsp << "Obtained " << watchData.size() << " items:\n";
|
nsp << "Obtained " << watchData.size() << " items:\n";
|
||||||
foreach (const Debugger::Internal::WatchData &wd, watchData)
|
foreach (const Debugger::Internal::WatchData &wd, watchData)
|
||||||
nsp << wd.toString() <<'\n';
|
nsp << wd.toString() <<'\n';
|
||||||
}
|
}
|
||||||
watchHandler()->insertBulkData(watchData);
|
|
||||||
watchHandler()->endCycle();
|
|
||||||
} else {
|
|
||||||
showMessage(QString::fromLatin1("Parse error in locals response."), LogError);
|
|
||||||
qWarning("Parse error in locals response:\n%s", reply->reply.constData());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
showMessage(QString::fromLatin1(reply->errorMessage), LogError);
|
showMessage(QString::fromLatin1(reply->errorMessage), LogError);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user