std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
const DumpParameters &p) const
{
+ QTC_TRACE_IN
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::dump()";
std::ostringstream str;
DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
if (p.humanReadable())
str << '[';
accept(visitor);
str << ']';
+ QTC_TRACE_OUT
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::dump()";
return str.str();
}
const DumpParameters &p,
std::string *errorMessage)
{
+ if (symbolGroupDebug)
+ DebugPrint() << ">SymbolGroup::dump(" << iname << ")";
+ QTC_TRACE_IN
AbstractSymbolGroupNode *const aNode = find(iname);
if (!aNode) {
*errorMessage = msgNotFound(iname);
}
// 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
node->clearFlags(SymbolGroupNode::ExpandedByDumper);
} else {
str << '[';
aNode->accept(visitor, SymbolGroupNodeVisitor::parentIname(iname), 0, 0);
str << ']';
+ QTC_TRACE_OUT
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::dump(" << iname << ")";
return str.str();
}
// Expand a node list "locals.i1,locals.i2"
unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::string *errorMessage)
{
+ if (symbolGroupDebug)
+ DebugPrint() << ">SymbolGroup::expandList" << nodes.size();
if (nodes.empty())
return 0;
// Create a set with a key <level, name>. Also required for 1 node (see above).
errorMessage->append(", ");
errorMessage->append(nodeError);
}
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::expandList returns " << succeeded;
return succeeded;
}
const SymbolGroupValueContext &ctx,
std::string *errorMessage)
{
+ if (symbolGroupDebug)
+ DebugPrint() << ">SymbolGroup::expandListRunComplexDumpers" << nodes.size();
+ QTC_TRACE_IN
if (nodes.empty())
return 0;
// Create a set with a key <level, name>. Also required for 1 node (see above).
errorMessage->append(", ");
errorMessage->append(nodeError);
}
+ QTC_TRACE_OUT
+ if (symbolGroupDebug)
+ DebugPrint() << "<SymbolGroup::expandListRunComplexDumpers returns " << succeeded;
return succeeded;
}
#include <algorithm>
-enum { debug = 0 };
-
typedef std::vector<int>::size_type VectorIndexType;
typedef std::vector<std::string> StringVector;
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(const std::string &name,
// Complex dumpers: Get container/fake children
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)))
return;
- setFlags(ComplexDumperOk);
+ addFlags(ComplexDumperOk);
const AbstractSymbolGroupNodePtrVector ctChildren =
containerChildren(this, m_dumperType, m_dumperContainerSize, ctx);
m_dumperContainerSize = int(ctChildren.size()); // Just in case...
}
// 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)
{
if (testFlags(Uninitialized))
return L"<not in scope>";
- if (testFlags(SimpleDumperOk))
+ if (runSimpleDumpers(ctx))
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();
}
str << "\",index=" << m_index;
if (const VectorIndexType childCount = children().size())
str << ", Children=" << childCount;
- str << ' ' << m_parameters;
- 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 << ' ';
- }
+ str << ' ' << m_parameters << DebugNodeFlags(flags());
if (verbosity) {
str << ",name=\"" << name() << "\", Address=0x" << std::hex << address() << std::dec
<< " Type=\"" << type() << '"';
if (m_dumperType & KT_ContainerType)
str << " container(" << m_dumperContainerSize << ')';
}
- if (!(f & Uninitialized))
+ if (!testFlags(Uninitialized))
str << " Value=\"" << gdbmiWStringFormat(symbolGroupRawValue()) << '"';
str << '\n'; // Potentially multiline
}
// Expand!
bool SymbolGroupNode::expand(std::string *errorMessage)
{
- if (::debug > 1)
- DebugPrint() << "SymbolGroupNode::expand " << name() << ' ' << m_index;
+ if (symbolGroupDebug)
+ DebugPrint() << "SymbolGroupNode::expand " << name()
+ <<'/' << absoluteFullIName() << ' '
+ << m_index << DebugNodeFlags(flags());
if (isExpanded()) {
// Clear the flag indication dumper expansion on a second, explicit request
clearFlags(ExpandedByDumper);
return true;
if (!expand(errorMessage))
return false;
- simpleDumpValue(ctx); // Run simple dumpers to obtain type and run complex dumpers
- if (testFlags(SimpleDumperOk))
+ // Run simple dumpers to obtain type and run complex dumpers
+ if (runSimpleDumpers(ctx) && testFlags(SimpleDumperOk))
runComplexDumpers(ctx);
return true;
}
{
if (reply->success) {
QList<Debugger::Internal::WatchData> watchData;
- if (Debugger::Internal::QtDumperHelper::parseValue(reply->reply.constData(), &watchData)) {
- for (int i = 0; i < watchData.size(); i++)
- watchData[i].setAllUnneeded();
- if (debug > 1) {
- QDebug nsp = qDebug().nospace();
- nsp << "Obtained " << watchData.size() << " items:\n";
- foreach (const Debugger::Internal::WatchData &wd, watchData)
- 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());
+ GdbMi root;
+ root.fromString(reply->reply);
+ QTC_ASSERT(root.isList(), return ; )
+ 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();
+ nsp << "Obtained " << watchData.size() << " items:\n";
+ foreach (const Debugger::Internal::WatchData &wd, watchData)
+ nsp << wd.toString() <<'\n';
}
} else {
showMessage(QString::fromLatin1(reply->errorMessage), LogError);