forked from qt-creator/qt-creator
debugger: make a 'type' a QByteArray, not a QString
Saves lots of conversion.
This commit is contained in:
@@ -683,7 +683,7 @@ void CdbEngine::evaluateWatcher(WatchData *wd)
|
|||||||
exp.remove(0, 6);
|
exp.remove(0, 6);
|
||||||
if (m_d->evaluateExpression(exp, &value, &type, &errorMessage)) {
|
if (m_d->evaluateExpression(exp, &value, &type, &errorMessage)) {
|
||||||
wd->setValue(value);
|
wd->setValue(value);
|
||||||
wd->setType(type);
|
wd->setType(type.toUtf8());
|
||||||
} else {
|
} else {
|
||||||
wd->setValue(errorMessage);
|
wd->setValue(errorMessage);
|
||||||
wd->setTypeUnneeded();
|
wd->setTypeUnneeded();
|
||||||
|
|||||||
@@ -343,14 +343,14 @@ CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix,
|
|||||||
// Fix display values: Pass through strings, convert unsigned integers
|
// Fix display values: Pass through strings, convert unsigned integers
|
||||||
// to decimal ('0x5454`fedf'), remove inner templates from
|
// to decimal ('0x5454`fedf'), remove inner templates from
|
||||||
// "0x4343 class list<>".
|
// "0x4343 class list<>".
|
||||||
static inline QString fixValue(const QString &value, const QString &type)
|
static inline QString fixValue(const QString &value, const QLatin1String &type)
|
||||||
{
|
{
|
||||||
// Pass through strings
|
// Pass through strings
|
||||||
if (value.endsWith(QLatin1Char('"')))
|
if (value.endsWith(QLatin1Char('"')))
|
||||||
return value;
|
return value;
|
||||||
const int size = value.size();
|
const int size = value.size();
|
||||||
// Real Integer numbers Unsigned hex numbers (0x)/decimal numbers (0n)
|
// Real Integer numbers Unsigned hex numbers (0x)/decimal numbers (0n)
|
||||||
if (type != QLatin1String("bool") && isIntType(type)) {
|
if (type != "bool" && isIntType(type)) {
|
||||||
const QVariant intValue = CdbCore::SymbolGroupContext::getIntValue(value);
|
const QVariant intValue = CdbCore::SymbolGroupContext::getIntValue(value);
|
||||||
if (intValue.isValid())
|
if (intValue.isValid())
|
||||||
return intValue.toString();
|
return intValue.toString();
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ public:
|
|||||||
virtual unsigned debuggerCapabilities() const { return 0; }
|
virtual unsigned debuggerCapabilities() const { return 0; }
|
||||||
|
|
||||||
virtual bool isSynchronous() const { return false; }
|
virtual bool isSynchronous() const { return false; }
|
||||||
virtual QString qtNamespace() const { return QString(); }
|
virtual QByteArray qtNamespace() const { return QByteArray(); }
|
||||||
|
|
||||||
virtual void createSnapshot() {}
|
virtual void createSnapshot() {}
|
||||||
virtual void updateAll() {}
|
virtual void updateAll() {}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ static inline QString msgRetrievingWatchData(int pending)
|
|||||||
void GdbEngine::runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren)
|
void GdbEngine::runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren)
|
||||||
{
|
{
|
||||||
Q_UNUSED(dumpChildren)
|
Q_UNUSED(dumpChildren)
|
||||||
QByteArray type = data.type.toLatin1();
|
QByteArray type = data.type;
|
||||||
QByteArray cmd;
|
QByteArray cmd;
|
||||||
|
|
||||||
if (type == "QString" || type.endsWith("::QString"))
|
if (type == "QString" || type.endsWith("::QString"))
|
||||||
@@ -172,7 +172,7 @@ void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChild
|
|||||||
m_processedNames.insert(processedName);
|
m_processedNames.insert(processedName);
|
||||||
|
|
||||||
QByteArray params;
|
QByteArray params;
|
||||||
QStringList extraArgs;
|
QList<QByteArray> extraArgs;
|
||||||
const QtDumperHelper::TypeData td = m_dumperHelper.typeData(data0.type);
|
const QtDumperHelper::TypeData td = m_dumperHelper.typeData(data0.type);
|
||||||
m_dumperHelper.evaluationParameters(data, td, QtDumperHelper::GdbDebugger, ¶ms, &extraArgs);
|
m_dumperHelper.evaluationParameters(data, td, QtDumperHelper::GdbDebugger, ¶ms, &extraArgs);
|
||||||
|
|
||||||
@@ -191,12 +191,17 @@ void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChild
|
|||||||
|
|
||||||
sendWatchParameters(params);
|
sendWatchParameters(params);
|
||||||
|
|
||||||
QString cmd;
|
QByteArray cmd = "call (void*)qDumpObjectData440("
|
||||||
QTextStream(&cmd) << "call " << "(void*)qDumpObjectData440(" <<
|
+ QByteArray::number(protocol)
|
||||||
protocol << ",0," << addr << ',' << (dumpChildren ? '1' : '0')
|
+ ",0,"
|
||||||
<< ',' << extraArgs.join(QString(_c(','))) << ')';
|
+ addr
|
||||||
|
+ ','
|
||||||
|
+ (dumpChildren ? '1' : '0');
|
||||||
|
foreach (const QByteArray &ex, extraArgs)
|
||||||
|
cmd + ',' + ex;
|
||||||
|
cmd += ')';
|
||||||
|
|
||||||
postCommand(cmd.toLatin1(), WatchUpdate | NonCriticalResponse);
|
postCommand(cmd, WatchUpdate | NonCriticalResponse);
|
||||||
|
|
||||||
showStatusMessage(msgRetrievingWatchData(m_pendingWatchRequests + 1), 10000);
|
showStatusMessage(msgRetrievingWatchData(m_pendingWatchRequests + 1), 10000);
|
||||||
|
|
||||||
@@ -269,7 +274,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
|
|||||||
if (theDebuggerBoolSetting(AutoDerefPointers)) {
|
if (theDebuggerBoolSetting(AutoDerefPointers)) {
|
||||||
// Try automatic dereferentiation
|
// Try automatic dereferentiation
|
||||||
data.exp = "(*(" + data.exp + "))";
|
data.exp = "(*(" + data.exp + "))";
|
||||||
data.type = data.type + _("."); // FIXME: fragile HACK to avoid recursion
|
data.type = data.type + "."; // FIXME: fragile HACK to avoid recursion
|
||||||
insertData(data);
|
insertData(data);
|
||||||
} else {
|
} else {
|
||||||
data.setChildrenUnneeded();
|
data.setChildrenUnneeded();
|
||||||
@@ -439,8 +444,8 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
|||||||
data.setError(WatchData::msgNotInScope());
|
data.setError(WatchData::msgNotInScope());
|
||||||
data.setAllUnneeded();
|
data.setAllUnneeded();
|
||||||
insertData(data);
|
insertData(data);
|
||||||
} else if (data.type == __("QString")
|
} else if (data.type == "QString"
|
||||||
|| data.type.endsWith(__("::QString"))) {
|
|| data.type.endsWith("::QString")) {
|
||||||
QList<QByteArray> list = out.split(' ');
|
QList<QByteArray> list = out.split(' ');
|
||||||
QString str;
|
QString str;
|
||||||
int l = out.isEmpty() ? 0 : list.size();
|
int l = out.isEmpty() ? 0 : list.size();
|
||||||
@@ -450,8 +455,8 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
|||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
data.setAllUnneeded();
|
data.setAllUnneeded();
|
||||||
insertData(data);
|
insertData(data);
|
||||||
} else if (data.type == __("QStringList")
|
} else if (data.type == "QStringList"
|
||||||
|| data.type.endsWith(__("::QStringList"))) {
|
|| data.type.endsWith("::QStringList")) {
|
||||||
if (out.isEmpty()) {
|
if (out.isEmpty()) {
|
||||||
data.setValue(tr("<0 items>"));
|
data.setValue(tr("<0 items>"));
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
@@ -731,7 +736,7 @@ void GdbEngine::handleQueryDebuggingHelperClassic(const GdbResponse &response)
|
|||||||
showStatusMessage(successMsg);
|
showStatusMessage(successMsg);
|
||||||
|
|
||||||
// Sanity check for Qt version of dumpers and debuggee.
|
// Sanity check for Qt version of dumpers and debuggee.
|
||||||
QByteArray ns = m_dumperHelper.qtNamespace().toLatin1();
|
QByteArray ns = m_dumperHelper.qtNamespace();
|
||||||
postCommand("-var-create A@ * '" + ns + "qVersion'()",
|
postCommand("-var-create A@ * '" + ns + "qVersion'()",
|
||||||
CB(handleDebuggingHelperVersionCheckClassic));
|
CB(handleDebuggingHelperVersionCheckClassic));
|
||||||
postCommand("-var-delete A@");
|
postCommand("-var-delete A@");
|
||||||
@@ -855,7 +860,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
|
|||||||
data.exp = parent.exp;
|
data.exp = parent.exp;
|
||||||
data.name = tr("<n/a>");
|
data.name = tr("<n/a>");
|
||||||
data.iname = parent.iname + ".@";
|
data.iname = parent.iname + ".@";
|
||||||
data.type = tr("<anonymous union>");
|
data.type = tr("<anonymous union>").toUtf8();
|
||||||
} else {
|
} else {
|
||||||
// A structure. Hope there's nothing else...
|
// A structure. Hope there's nothing else...
|
||||||
data.exp = '(' + parent.exp + ")." + data.name.toLatin1();
|
data.exp = '(' + parent.exp + ")." + data.name.toLatin1();
|
||||||
|
|||||||
@@ -3267,15 +3267,15 @@ void GdbEngine::setAutoDerefPointers(const QVariant &on)
|
|||||||
updateLocals();
|
updateLocals();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GdbEngine::hasDebuggingHelperForType(const QString &type) const
|
bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const
|
||||||
{
|
{
|
||||||
if (!theDebuggerBoolSetting(UseDebuggingHelpers))
|
if (!theDebuggerBoolSetting(UseDebuggingHelpers))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
||||||
// "call" is not possible in gdb when looking at core files
|
// "call" is not possible in gdb when looking at core files
|
||||||
return type == __("QString") || type.endsWith(__("::QString"))
|
return type == "QString" || type.endsWith("::QString")
|
||||||
|| type == __("QStringList") || type.endsWith(__("::QStringList"));
|
|| type == "QStringList" || type.endsWith("::QStringList");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theDebuggerBoolSetting(DebugDebuggingHelpers)
|
if (theDebuggerBoolSetting(DebugDebuggingHelpers)
|
||||||
@@ -3429,7 +3429,7 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
|
|||||||
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||||
if (data.isWatcher()) {
|
if (data.isWatcher()) {
|
||||||
data.value = WatchData::msgNotInScope();
|
data.value = WatchData::msgNotInScope();
|
||||||
data.type = _(" ");
|
data.type = " ";
|
||||||
data.setAllUnneeded();
|
data.setAllUnneeded();
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
data.valueEnabled = false;
|
data.valueEnabled = false;
|
||||||
@@ -3496,7 +3496,7 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
|||||||
//: Type of local variable or parameter shadowed by another
|
//: Type of local variable or parameter shadowed by another
|
||||||
//: variable of the same name in a nested block.
|
//: variable of the same name in a nested block.
|
||||||
setWatchDataValue(data, item);
|
setWatchDataValue(data, item);
|
||||||
data.setType(GdbEngine::tr("<shadowed>"));
|
data.setType(GdbEngine::tr("<shadowed>").toUtf8());
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -3576,9 +3576,9 @@ void GdbEngine::handleWatchPoint(const GdbResponse &response)
|
|||||||
QString str = _(parsePlainConsoleStream(response));
|
QString str = _(parsePlainConsoleStream(response));
|
||||||
// "(void *) 0xbfa7ebfc"
|
// "(void *) 0xbfa7ebfc"
|
||||||
QString addr = str.mid(9);
|
QString addr = str.mid(9);
|
||||||
QString ns = m_dumperHelper.qtNamespace();
|
QByteArray ns = m_dumperHelper.qtNamespace();
|
||||||
QString type = ns.isEmpty() ? _("QWidget*") : _("'%1QWidget'*").arg(ns);
|
QByteArray type = ns.isEmpty() ? "QWidget*" : ("'" + ns + "QWidget'*");
|
||||||
QString exp = _("(*(%1)%2)").arg(type).arg(addr);
|
QString exp = _("(*(%1)%2)").arg(_(type)).arg(addr);
|
||||||
watchHandler()->watchExpression(exp);
|
watchHandler()->watchExpression(exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ private: ////////// General Interface //////////
|
|||||||
virtual void notifyInferiorSetupFailed();
|
virtual void notifyInferiorSetupFailed();
|
||||||
|
|
||||||
virtual void executeDebuggerCommand(const QString &command);
|
virtual void executeDebuggerCommand(const QString &command);
|
||||||
virtual QString qtNamespace() const { return m_dumperHelper.qtNamespace(); }
|
virtual QByteArray qtNamespace() const { return m_dumperHelper.qtNamespace(); }
|
||||||
|
|
||||||
private: ////////// General State //////////
|
private: ////////// General State //////////
|
||||||
|
|
||||||
@@ -471,7 +471,7 @@ private: ////////// View & Data Stuff //////////
|
|||||||
|
|
||||||
void runDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
|
void runDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
|
||||||
void runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
|
void runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
|
||||||
bool hasDebuggingHelperForType(const QString &type) const;
|
bool hasDebuggingHelperForType(const QByteArray &type) const;
|
||||||
|
|
||||||
void handleVarListChildrenClassic(const GdbResponse &response);
|
void handleVarListChildrenClassic(const GdbResponse &response);
|
||||||
void handleVarListChildrenHelperClassic(const GdbMi &child,
|
void handleVarListChildrenHelperClassic(const GdbMi &child,
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ bool QmlCppEngine::isSynchronous() const
|
|||||||
return m_activeEngine->isSynchronous();
|
return m_activeEngine->isSynchronous();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlCppEngine::qtNamespace() const
|
QByteArray QmlCppEngine::qtNamespace() const
|
||||||
{
|
{
|
||||||
return m_cppEngine->qtNamespace();
|
return m_cppEngine->qtNamespace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
virtual unsigned debuggerCapabilities() const;
|
virtual unsigned debuggerCapabilities() const;
|
||||||
|
|
||||||
virtual bool isSynchronous() const;
|
virtual bool isSynchronous() const;
|
||||||
virtual QString qtNamespace() const;
|
virtual QByteArray qtNamespace() const;
|
||||||
|
|
||||||
virtual void createSnapshot();
|
virtual void createSnapshot();
|
||||||
virtual void updateAll();
|
virtual void updateAll();
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ QDataStream& operator>>(QDataStream& s, WatchData &data)
|
|||||||
QString type;
|
QString type;
|
||||||
bool hasChildren;
|
bool hasChildren;
|
||||||
s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId;
|
s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId;
|
||||||
data.setType(type, false);
|
data.setType(type.toUtf8(), false);
|
||||||
data.setValue(value);
|
data.setValue(value);
|
||||||
data.setHasChildren(hasChildren);
|
data.setHasChildren(hasChildren);
|
||||||
data.setAllUnneeded();
|
data.setAllUnneeded();
|
||||||
|
|||||||
@@ -746,55 +746,55 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
|
|||||||
if (data.isTypeNeeded() || data.isValueNeeded()) {
|
if (data.isTypeNeeded() || data.isValueNeeded()) {
|
||||||
const QScriptValue &ob = data.scriptValue;
|
const QScriptValue &ob = data.scriptValue;
|
||||||
if (ob.isArray()) {
|
if (ob.isArray()) {
|
||||||
data.setType(QLatin1String("Array"), false);
|
data.setType("Array", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isBool()) {
|
} else if (ob.isBool()) {
|
||||||
data.setType(QLatin1String("Bool"), false);
|
data.setType("Bool", false);
|
||||||
data.setValue(ob.toBool() ? QLatin1String("true") : QLatin1String("false"));
|
data.setValue(ob.toBool() ? QLatin1String("true") : QLatin1String("false"));
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
} else if (ob.isDate()) {
|
} else if (ob.isDate()) {
|
||||||
data.setType(QLatin1String("Date"), false);
|
data.setType("Date", false);
|
||||||
data.setValue(ob.toDateTime().toString());
|
data.setValue(ob.toDateTime().toString());
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
} else if (ob.isError()) {
|
} else if (ob.isError()) {
|
||||||
data.setType(QLatin1String("Error"), false);
|
data.setType("Error", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isFunction()) {
|
} else if (ob.isFunction()) {
|
||||||
data.setType(QLatin1String("Function"), false);
|
data.setType("Function", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isNull()) {
|
} else if (ob.isNull()) {
|
||||||
const QString nullValue = QLatin1String("<null>");
|
const QString nullValue = QLatin1String("<null>");
|
||||||
data.setType(nullValue, false);
|
data.setType("<null>", false);
|
||||||
data.setValue(nullValue);
|
data.setValue(nullValue);
|
||||||
} else if (ob.isNumber()) {
|
} else if (ob.isNumber()) {
|
||||||
data.setType(QLatin1String("Number"), false);
|
data.setType("Number", false);
|
||||||
data.setValue(QString::number(ob.toNumber()));
|
data.setValue(QString::number(ob.toNumber()));
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
} else if (ob.isObject()) {
|
} else if (ob.isObject()) {
|
||||||
data.setType(QLatin1String("Object"), false);
|
data.setType("Object", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isQMetaObject()) {
|
} else if (ob.isQMetaObject()) {
|
||||||
data.setType(QLatin1String("QMetaObject"), false);
|
data.setType("QMetaObject", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isQObject()) {
|
} else if (ob.isQObject()) {
|
||||||
data.setType(QLatin1String("QObject"), false);
|
data.setType("QObject", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isRegExp()) {
|
} else if (ob.isRegExp()) {
|
||||||
data.setType(QLatin1String("RegExp"), false);
|
data.setType("RegExp", false);
|
||||||
data.setValue(ob.toRegExp().pattern());
|
data.setValue(ob.toRegExp().pattern());
|
||||||
} else if (ob.isString()) {
|
} else if (ob.isString()) {
|
||||||
data.setType(QLatin1String("String"), false);
|
data.setType("String", false);
|
||||||
data.setValue(ob.toString());
|
data.setValue(ob.toString());
|
||||||
} else if (ob.isVariant()) {
|
} else if (ob.isVariant()) {
|
||||||
data.setType(QLatin1String("Variant"), false);
|
data.setType("Variant", false);
|
||||||
data.setValue(QString(QLatin1Char(' ')));
|
data.setValue(QString(QLatin1Char(' ')));
|
||||||
} else if (ob.isUndefined()) {
|
} else if (ob.isUndefined()) {
|
||||||
data.setType(QLatin1String("<undefined>"), false);
|
data.setType("<undefined>", false);
|
||||||
data.setValue(QLatin1String("<unknown>"));
|
data.setValue(QLatin1String("<unknown>"));
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
} else {
|
} else {
|
||||||
const QString unknown = QLatin1String("<unknown>");
|
const QString unknown = QLatin1String("<unknown>");
|
||||||
data.setType(unknown, false);
|
data.setType("<unknown>", false);
|
||||||
data.setValue(unknown);
|
data.setValue(unknown);
|
||||||
data.setHasChildren(false);
|
data.setHasChildren(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void WatchData::setValue(const QString &value0)
|
|||||||
hasChildren = true; // at least one...
|
hasChildren = true; // at least one...
|
||||||
}
|
}
|
||||||
// strip off quoted characters for chars.
|
// strip off quoted characters for chars.
|
||||||
if (value.endsWith(QLatin1Char('\'')) && type.endsWith(QLatin1String("char"))) {
|
if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) {
|
||||||
const int blankPos = value.indexOf(QLatin1Char(' '));
|
const int blankPos = value.indexOf(QLatin1Char(' '));
|
||||||
if (blankPos != -1)
|
if (blankPos != -1)
|
||||||
value.truncate(blankPos);
|
value.truncate(blankPos);
|
||||||
@@ -105,26 +105,26 @@ void WatchData::setValueToolTip(const QString &tooltip)
|
|||||||
valuetooltip = tooltip;
|
valuetooltip = tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchData::setType(const QString &str, bool guessChildrenFromType)
|
void WatchData::setType(const QByteArray &str, bool guessChildrenFromType)
|
||||||
{
|
{
|
||||||
type = str.trimmed();
|
type = str.trimmed();
|
||||||
bool changed = true;
|
bool changed = true;
|
||||||
while (changed) {
|
while (changed) {
|
||||||
if (type.endsWith(QLatin1String("const")))
|
if (type.endsWith("const"))
|
||||||
type.chop(5);
|
type.chop(5);
|
||||||
else if (type.endsWith(QLatin1Char(' ')))
|
else if (type.endsWith(' '))
|
||||||
type.chop(1);
|
type.chop(1);
|
||||||
else if (type.endsWith(QLatin1Char('&')))
|
else if (type.endsWith('&'))
|
||||||
type.chop(1);
|
type.chop(1);
|
||||||
else if (type.startsWith(QLatin1String("const ")))
|
else if (type.startsWith("const "))
|
||||||
type = type.mid(6);
|
type = type.mid(6);
|
||||||
else if (type.startsWith(QLatin1String("volatile ")))
|
else if (type.startsWith("volatile "))
|
||||||
type = type.mid(9);
|
type = type.mid(9);
|
||||||
else if (type.startsWith(QLatin1String("class ")))
|
else if (type.startsWith("class "))
|
||||||
type = type.mid(6);
|
type = type.mid(6);
|
||||||
else if (type.startsWith(QLatin1String("struct ")))
|
else if (type.startsWith("struct "))
|
||||||
type = type.mid(6);
|
type = type.mid(6);
|
||||||
else if (type.startsWith(QLatin1Char(' ')))
|
else if (type.startsWith(' '))
|
||||||
type = type.mid(1);
|
type = type.mid(1);
|
||||||
else
|
else
|
||||||
changed = false;
|
changed = false;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void setValue(const QString &);
|
void setValue(const QString &);
|
||||||
void setType(const QString &, bool guessChildrenFromType = true);
|
void setType(const QByteArray &, bool guessChildrenFromType = true);
|
||||||
void setValueToolTip(const QString &);
|
void setValueToolTip(const QString &);
|
||||||
void setError(const QString &);
|
void setError(const QString &);
|
||||||
void setAddress(const QByteArray &);
|
void setAddress(const QByteArray &);
|
||||||
@@ -116,7 +116,7 @@ public:
|
|||||||
int editformat; // Format of displayed value
|
int editformat; // Format of displayed value
|
||||||
QString valuetooltip; // Tooltip in value column
|
QString valuetooltip; // Tooltip in value column
|
||||||
QString typeFormats; // Selection of formats of displayed value
|
QString typeFormats; // Selection of formats of displayed value
|
||||||
QString type; // Type for further processing
|
QByteArray type; // Type for further processing
|
||||||
QString displayedType;// Displayed type (optional)
|
QString displayedType;// Displayed type (optional)
|
||||||
QByteArray variable; // Name of internal Gdb variable if created
|
QByteArray variable; // Name of internal Gdb variable if created
|
||||||
QByteArray addr; // Displayed address
|
QByteArray addr; // Displayed address
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ static inline QString formattedValue(const WatchData &data, int format)
|
|||||||
if (!firstChar.isDigit() && firstChar != QLatin1Char('-'))
|
if (!firstChar.isDigit() && firstChar != QLatin1Char('-'))
|
||||||
return data.value;
|
return data.value;
|
||||||
// Append quoted, printable character also for decimal.
|
// Append quoted, printable character also for decimal.
|
||||||
if (data.type.endsWith(QLatin1String("char"))) {
|
if (data.type.endsWith("char")) {
|
||||||
bool ok;
|
bool ok;
|
||||||
const int code = data.value.toInt(&ok);
|
const int code = data.value.toInt(&ok);
|
||||||
return ok ? reformatCharacter(code, format) : data.value;
|
return ok ? reformatCharacter(code, format) : data.value;
|
||||||
@@ -444,7 +444,7 @@ static inline QString formattedValue(const WatchData &data, int format)
|
|||||||
if (format <= 0)
|
if (format <= 0)
|
||||||
return data.value;
|
return data.value;
|
||||||
// Evil hack, covers 'unsigned' as well as quint64.
|
// Evil hack, covers 'unsigned' as well as quint64.
|
||||||
if (data.type.contains(QLatin1Char('u')))
|
if (data.type.contains('u'))
|
||||||
return reformatInteger(data.value.toULongLong(), format);
|
return reformatInteger(data.value.toULongLong(), format);
|
||||||
return reformatInteger(data.value.toLongLong(), format);
|
return reformatInteger(data.value.toLongLong(), format);
|
||||||
}
|
}
|
||||||
@@ -653,7 +653,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
bool ok;
|
bool ok;
|
||||||
const quint64 addr = data.addr.toULongLong(&ok, 16);
|
const quint64 addr = data.addr.toULongLong(&ok, 16);
|
||||||
if (ok && addr)
|
if (ok && addr)
|
||||||
return QString("*(%1*)%2").arg(data.type).arg(addr);
|
return QString("*(%1*)%2").arg(QLatin1String(data.type)).arg(addr);
|
||||||
}
|
}
|
||||||
WatchItem *parent = item->parent;
|
WatchItem *parent = item->parent;
|
||||||
if (parent && !parent->exp.isEmpty())
|
if (parent && !parent->exp.isEmpty())
|
||||||
@@ -669,10 +669,10 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
return m_handler->m_expandedINames.contains(data.iname);
|
return m_handler->m_expandedINames.contains(data.iname);
|
||||||
|
|
||||||
case LocalsTypeFormatListRole: {
|
case LocalsTypeFormatListRole: {
|
||||||
if (isIntType(data.type) && data.type != QLatin1String("bool"))
|
if (isIntType(data.type) && data.type != "bool")
|
||||||
return QStringList() << tr("decimal") << tr("hexadecimal")
|
return QStringList() << tr("decimal") << tr("hexadecimal")
|
||||||
<< tr("binary") << tr("octal");
|
<< tr("binary") << tr("octal");
|
||||||
if (data.type.endsWith(QLatin1Char('*')))
|
if (data.type.endsWith('*'))
|
||||||
return QStringList()
|
return QStringList()
|
||||||
<< tr("Raw pointer")
|
<< tr("Raw pointer")
|
||||||
<< tr("Latin1 string")
|
<< tr("Latin1 string")
|
||||||
|
|||||||
@@ -227,6 +227,13 @@ bool isLeavableFunction(const QString &funcName, const QString &fileName)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isLetterOrNumber(char c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z')
|
||||||
|
|| (c >= 'A' && c <= 'Z')
|
||||||
|
|| (c >= '0' && c <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
bool hasLetterOrNumber(const QString &exp)
|
bool hasLetterOrNumber(const QString &exp)
|
||||||
{
|
{
|
||||||
const QChar underscore = QLatin1Char('_');
|
const QChar underscore = QLatin1Char('_');
|
||||||
@@ -266,16 +273,14 @@ bool isKeyWord(const QString &exp)
|
|||||||
|| exp == QLatin1String("while");
|
|| exp == QLatin1String("while");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPointerType(const QString &type)
|
bool isPointerType(const QByteArray &type)
|
||||||
{
|
{
|
||||||
return type.endsWith(QLatin1Char('*')) || type.endsWith(QLatin1String("* const"));
|
return type.endsWith('*') || type.endsWith("* const");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCharPointerType(const QString &type)
|
bool isCharPointerType(const QByteArray &type)
|
||||||
{
|
{
|
||||||
return type == QLatin1String("char *")
|
return type == "char *" || type == "const char *" || type == "char const *";
|
||||||
|| type == QLatin1String("const char *")
|
|
||||||
|| type == QLatin1String("char const *");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startsWithDigit(const QString &str)
|
bool startsWithDigit(const QString &str)
|
||||||
@@ -283,13 +288,13 @@ bool startsWithDigit(const QString &str)
|
|||||||
return !str.isEmpty() && str.at(0).isDigit();
|
return !str.isEmpty() && str.at(0).isDigit();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString stripPointerType(QString type)
|
QByteArray stripPointerType(QByteArray type)
|
||||||
{
|
{
|
||||||
if (type.endsWith(QLatin1Char('*')))
|
if (type.endsWith('*'))
|
||||||
type.chop(1);
|
type.chop(1);
|
||||||
if (type.endsWith(QLatin1String("* const")))
|
if (type.endsWith("* const"))
|
||||||
type.chop(7);
|
type.chop(7);
|
||||||
if (type.endsWith(QLatin1Char(' ')))
|
if (type.endsWith(' '))
|
||||||
type.chop(1);
|
type.chop(1);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -423,7 +428,7 @@ bool getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
|
|||||||
return rc == 0;
|
return rc == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString gdbQuoteTypes(const QString &type)
|
QByteArray gdbQuoteTypes(const QByteArray &type)
|
||||||
{
|
{
|
||||||
// gdb does not understand sizeof(Core::IFile*).
|
// gdb does not understand sizeof(Core::IFile*).
|
||||||
// "sizeof('Core::IFile*')" is also not acceptable,
|
// "sizeof('Core::IFile*')" is also not acceptable,
|
||||||
@@ -439,19 +444,19 @@ QString gdbQuoteTypes(const QString &type)
|
|||||||
// (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable
|
// (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable
|
||||||
// (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable
|
// (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable
|
||||||
if (isPointerType(type))
|
if (isPointerType(type))
|
||||||
return gdbQuoteTypes(stripPointerType(type)) + QLatin1Char('*');
|
return gdbQuoteTypes(stripPointerType(type)) + '*';
|
||||||
|
|
||||||
QString accu;
|
QByteArray accu;
|
||||||
QString result;
|
QByteArray result;
|
||||||
int templateLevel = 0;
|
int templateLevel = 0;
|
||||||
|
|
||||||
const QChar colon = QLatin1Char(':');
|
const char colon = ':';
|
||||||
const QChar singleQuote = QLatin1Char('\'');
|
const char singleQuote = '\'';
|
||||||
const QChar lessThan = QLatin1Char('<');
|
const char lessThan = '<';
|
||||||
const QChar greaterThan = QLatin1Char('>');
|
const char greaterThan = '>';
|
||||||
for (int i = 0; i != type.size(); ++i) {
|
for (int i = 0; i != type.size(); ++i) {
|
||||||
const QChar c = type.at(i);
|
const char c = type.at(i);
|
||||||
if (c.isLetterOrNumber() || c == QLatin1Char('_') || c == colon || c == QLatin1Char(' ')) {
|
if (isLetterOrNumber(c) || c == '_' || c == colon || c == ' ') {
|
||||||
accu += c;
|
accu += c;
|
||||||
} else if (c == lessThan) {
|
} else if (c == lessThan) {
|
||||||
++templateLevel;
|
++templateLevel;
|
||||||
@@ -479,7 +484,7 @@ QString gdbQuoteTypes(const QString &type)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extractTemplate(const QString &type, QString *tmplate, QString *inner)
|
bool extractTemplate(const QByteArray &type, QByteArray *tmplate, QByteArray *inner)
|
||||||
{
|
{
|
||||||
// Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in
|
// Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in
|
||||||
// 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates
|
// 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates
|
||||||
@@ -487,16 +492,15 @@ bool extractTemplate(const QString &type, QString *tmplate, QString *inner)
|
|||||||
// Gdb inserts a blank after each comma which we would like to avoid
|
// Gdb inserts a blank after each comma which we would like to avoid
|
||||||
tmplate->clear();
|
tmplate->clear();
|
||||||
inner->clear();
|
inner->clear();
|
||||||
if (!type.contains(QLatin1Char('<')))
|
if (!type.contains('<'))
|
||||||
return false;
|
return false;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
bool skipSpace = false;
|
bool skipSpace = false;
|
||||||
const int size = type.size();
|
const int size = type.size();
|
||||||
|
|
||||||
for (int i = 0; i != size; ++i) {
|
for (int i = 0; i != size; ++i) {
|
||||||
const QChar c = type.at(i);
|
const char c = type.at(i);
|
||||||
const char asciiChar = c.toAscii();
|
switch (c) {
|
||||||
switch (asciiChar) {
|
|
||||||
case '<':
|
case '<':
|
||||||
*(level == 0 ? tmplate : inner) += c;
|
*(level == 0 ? tmplate : inner) += c;
|
||||||
++level;
|
++level;
|
||||||
@@ -506,11 +510,11 @@ bool extractTemplate(const QString &type, QString *tmplate, QString *inner)
|
|||||||
*(level == 0 ? tmplate : inner) += c;
|
*(level == 0 ? tmplate : inner) += c;
|
||||||
break;
|
break;
|
||||||
case ',':
|
case ',':
|
||||||
*inner += (level == 1) ? QLatin1Char('@') : QLatin1Char(',');
|
*inner += (level == 1) ? '@' : ',';
|
||||||
skipSpace = true;
|
skipSpace = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!skipSpace || asciiChar != ' ') {
|
if (!skipSpace || c != ' ') {
|
||||||
*(level == 0 ? tmplate : inner) += c;
|
*(level == 0 ? tmplate : inner) += c;
|
||||||
skipSpace = false;
|
skipSpace = false;
|
||||||
}
|
}
|
||||||
@@ -518,7 +522,7 @@ bool extractTemplate(const QString &type, QString *tmplate, QString *inner)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*tmplate = tmplate->trimmed();
|
*tmplate = tmplate->trimmed();
|
||||||
*tmplate = tmplate->remove(QLatin1String("<>"));
|
tmplate->replace("<>", "");
|
||||||
*inner = inner->trimmed();
|
*inner = inner->trimmed();
|
||||||
// qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
|
// qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type;
|
||||||
return !inner->isEmpty();
|
return !inner->isEmpty();
|
||||||
@@ -536,42 +540,50 @@ QString extractTypeFromPTypeOutput(const QString &str)
|
|||||||
return res.simplified();
|
return res.simplified();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isIntType(const QString &type)
|
bool isIntType(const QByteArray &type)
|
||||||
{
|
{
|
||||||
static const QStringList types = QStringList()
|
switch (type.at(0)) {
|
||||||
<< QLatin1String("char") << QLatin1String("int") << QLatin1String("short")
|
case 'b':
|
||||||
<< QLatin1String("long") << QLatin1String("bool")
|
return type == "bool";
|
||||||
<< QLatin1String("signed char") << QLatin1String("unsigned")
|
case 'c':
|
||||||
<< QLatin1String("unsigned char") << QLatin1String("unsigned long")
|
return type == "char";
|
||||||
<< QLatin1String("short") << QLatin1String("unsigned short")
|
case 'i':
|
||||||
<< QLatin1String("long long") << QLatin1String("unsigned long long")
|
return type == "int";
|
||||||
<< QLatin1String("qint16") << QLatin1String("quint16")
|
case 'l':
|
||||||
<< QLatin1String("qint32") << QLatin1String("quint32")
|
return type == "long"
|
||||||
<< QLatin1String("qint64") << QLatin1String("quint64")
|
|| type == "long long";
|
||||||
<< QLatin1String("size_t")
|
case 'p':
|
||||||
<< QLatin1String("ptrdiff_t")
|
return type == "ptrdiff_t";
|
||||||
<< QLatin1String("std::size_t")
|
case 'q':
|
||||||
<< QLatin1String("std::ptrdiff_t");
|
return type == "qint16" || type == "quint16"
|
||||||
return type.endsWith(QLatin1String(" int"))
|
|| type == "qint32" || type == "quint32"
|
||||||
|| type.endsWith(QLatin1String(" int64"))
|
|| type == "qint64" || type == "quint64";
|
||||||
|| types.contains(type);
|
case 's':
|
||||||
|
return type == "short"
|
||||||
|
|| type == "signed"
|
||||||
|
|| type == "size_t"
|
||||||
|
|| type == "std::size_t"
|
||||||
|
|| type == "std::ptrdiff_t"
|
||||||
|
|| type.startsWith("signed ");
|
||||||
|
case 'u':
|
||||||
|
return type == "unsigned"
|
||||||
|
|| type.startsWith("unsigned ");
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSymbianIntType(const QString &type)
|
bool isSymbianIntType(const QByteArray &type)
|
||||||
{
|
{
|
||||||
static const QStringList types = QStringList()
|
return type == "TInt" || type == "TBool";
|
||||||
<< QLatin1String("TInt") << QLatin1String("TBool");
|
|
||||||
return types.contains(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isIntOrFloatType(const QString &type)
|
bool isIntOrFloatType(const QByteArray &type)
|
||||||
{
|
{
|
||||||
static const QStringList types = QStringList()
|
return isIntType(type) || type == "float" || type == "double";
|
||||||
<< QLatin1String("float") << QLatin1String("double");
|
|
||||||
return isIntType(type) || types.contains(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuessChildrenResult guessChildren(const QString &type)
|
GuessChildrenResult guessChildren(const QByteArray &type)
|
||||||
{
|
{
|
||||||
if (isIntOrFloatType(type))
|
if (isIntOrFloatType(type))
|
||||||
return HasNoChildren;
|
return HasNoChildren;
|
||||||
@@ -579,18 +591,18 @@ GuessChildrenResult guessChildren(const QString &type)
|
|||||||
return HasNoChildren;
|
return HasNoChildren;
|
||||||
if (isPointerType(type))
|
if (isPointerType(type))
|
||||||
return HasChildren;
|
return HasChildren;
|
||||||
if (type.endsWith(QLatin1String("QString")))
|
if (type.endsWith("QString"))
|
||||||
return HasNoChildren;
|
return HasNoChildren;
|
||||||
return HasPossiblyChildren;
|
return HasPossiblyChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString sizeofTypeExpression(const QString &type, QtDumperHelper::Debugger debugger)
|
QByteArray sizeofTypeExpression(const QByteArray &type, QtDumperHelper::Debugger debugger)
|
||||||
{
|
{
|
||||||
if (type.endsWith(QLatin1Char('*')))
|
if (type.endsWith('*'))
|
||||||
return QLatin1String("sizeof(void*)");
|
return "sizeof(void*)";
|
||||||
if (debugger != QtDumperHelper::GdbDebugger || type.endsWith(QLatin1Char('>')))
|
if (debugger != QtDumperHelper::GdbDebugger || type.endsWith('>'))
|
||||||
return QLatin1String("sizeof(") + type + QLatin1Char(')');
|
return "sizeof(" + type + ')';
|
||||||
return QLatin1String("sizeof(") + gdbQuoteTypes(type) + QLatin1Char(')');
|
return "sizeof(" + gdbQuoteTypes(type) + ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utilities to decode string data returned by the dumper helpers.
|
// Utilities to decode string data returned by the dumper helpers.
|
||||||
@@ -732,7 +744,7 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
|
|||||||
|
|
||||||
const QPlainTextEdit *plaintext = qobject_cast<QPlainTextEdit*>(editor->widget());
|
const QPlainTextEdit *plaintext = qobject_cast<QPlainTextEdit*>(editor->widget());
|
||||||
if (!plaintext)
|
if (!plaintext)
|
||||||
return QString();
|
return QByteArray();
|
||||||
|
|
||||||
QString expr = plaintext->textCursor().selectedText();
|
QString expr = plaintext->textCursor().selectedText();
|
||||||
CppModelManagerInterface *modelManager =
|
CppModelManagerInterface *modelManager =
|
||||||
@@ -763,7 +775,7 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
|
|||||||
*function = AbstractEditorSupport::functionAt(modelManager,
|
*function = AbstractEditorSupport::functionAt(modelManager,
|
||||||
file->fileName(), *line, *column);
|
file->fileName(), *line, *column);
|
||||||
|
|
||||||
return expr;
|
return expr.toUtf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -788,7 +800,7 @@ QtDumperHelper::QtDumperHelper() :
|
|||||||
m_dumperVersion(1.0)
|
m_dumperVersion(1.0)
|
||||||
{
|
{
|
||||||
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
|
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
|
||||||
setQClassPrefixes(QString());
|
setQClassPrefixes(QByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtDumperHelper::clear()
|
void QtDumperHelper::clear()
|
||||||
@@ -800,7 +812,7 @@ void QtDumperHelper::clear()
|
|||||||
m_sizeCache.clear();
|
m_sizeCache.clear();
|
||||||
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
|
qFill(m_specialSizes, m_specialSizes + SpecialSizeCount, 0);
|
||||||
m_expressionCache.clear();
|
m_expressionCache.clear();
|
||||||
setQClassPrefixes(QString());
|
setQClassPrefixes(QByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtDumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion)
|
QString QtDumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion)
|
||||||
@@ -837,8 +849,8 @@ QString QtDumperHelper::toString(bool debug) const
|
|||||||
str << ' ' << it.key() << '=' << it.value() << '\n';
|
str << ' ' << it.key() << '=' << it.value() << '\n';
|
||||||
}
|
}
|
||||||
str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
|
str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
|
||||||
const QMap<QString, QString>::const_iterator excend = m_expressionCache.constEnd();
|
const ExpressionCache::const_iterator excend = m_expressionCache.constEnd();
|
||||||
for (QMap<QString, QString>::const_iterator it = m_expressionCache.constBegin(); it != excend; ++it)
|
for (ExpressionCache::const_iterator it = m_expressionCache.constBegin(); it != excend; ++it)
|
||||||
str << " " << it.key() << ' ' << it.value() << '\n';
|
str << " " << it.key() << ' ' << it.value() << '\n';
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -850,7 +862,7 @@ QString QtDumperHelper::toString(bool debug) const
|
|||||||
m_nameTypeMap.size()).arg(qtVersionString(), nameSpace).arg(m_dumperVersion);
|
m_nameTypeMap.size()).arg(qtVersionString(), nameSpace).arg(m_dumperVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDumperHelper::Type QtDumperHelper::simpleType(const QString &simpleType) const
|
QtDumperHelper::Type QtDumperHelper::simpleType(const QByteArray &simpleType) const
|
||||||
{
|
{
|
||||||
return m_nameTypeMap.value(simpleType, UnknownType);
|
return m_nameTypeMap.value(simpleType, UnknownType);
|
||||||
}
|
}
|
||||||
@@ -860,7 +872,7 @@ int QtDumperHelper::qtVersion() const
|
|||||||
return m_qtVersion;
|
return m_qtVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtDumperHelper::qtNamespace() const
|
QByteArray QtDumperHelper::qtNamespace() const
|
||||||
{
|
{
|
||||||
return m_qtNamespace;
|
return m_qtNamespace;
|
||||||
}
|
}
|
||||||
@@ -929,28 +941,28 @@ static QtDumperHelper::Type specialType(QByteArray type)
|
|||||||
return QtDumperHelper::UnknownType;
|
return QtDumperHelper::UnknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtDumperHelper::qtVersionString() const
|
QByteArray QtDumperHelper::qtVersionString() const
|
||||||
{
|
{
|
||||||
QString rc;
|
QString rc;
|
||||||
QTextStream str(&rc);
|
QTextStream str(&rc);
|
||||||
formatQtVersion(m_qtVersion, str);
|
formatQtVersion(m_qtVersion, str);
|
||||||
return rc;
|
return rc.toLatin1();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a list of types.
|
// Parse a list of types.
|
||||||
typedef QList<QByteArray> QByteArrayList;
|
typedef QList<QByteArray> QByteArrayList;
|
||||||
|
|
||||||
static inline QString qClassName(const QString &qtNamespace, const char *className)
|
static inline QByteArray qClassName(const QByteArray &qtNamespace, const char *className)
|
||||||
{
|
{
|
||||||
if (qtNamespace.isEmpty())
|
if (qtNamespace.isEmpty())
|
||||||
return QString::fromAscii(className);
|
return className;
|
||||||
QString rc = qtNamespace;
|
QByteArray rc = qtNamespace;
|
||||||
rc += QLatin1String("::");
|
rc += "::";
|
||||||
rc += QString::fromAscii(className);
|
rc += className;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtDumperHelper::setQClassPrefixes(const QString &qNamespace)
|
void QtDumperHelper::setQClassPrefixes(const QByteArray &qNamespace)
|
||||||
{
|
{
|
||||||
// Prefixes with namespaces
|
// Prefixes with namespaces
|
||||||
m_qPointerPrefix = qClassName(qNamespace, "QPointer");
|
m_qPointerPrefix = qClassName(qNamespace, "QPointer");
|
||||||
@@ -982,7 +994,7 @@ bool QtDumperHelper::parseQuery(const GdbMi &contents)
|
|||||||
qDebug() << "parseQuery" << contents.toString(true, 2);
|
qDebug() << "parseQuery" << contents.toString(true, 2);
|
||||||
|
|
||||||
// Common info, dumper version, etc
|
// Common info, dumper version, etc
|
||||||
m_qtNamespace = QLatin1String(contents.findChild("namespace").data());
|
m_qtNamespace = contents.findChild("namespace").data();
|
||||||
int qtv = 0;
|
int qtv = 0;
|
||||||
const GdbMi qtversion = contents.findChild("qtversion");
|
const GdbMi qtversion = contents.findChild("qtversion");
|
||||||
if (qtversion.children().size() == 3) {
|
if (qtversion.children().size() == 3) {
|
||||||
@@ -1010,14 +1022,14 @@ bool QtDumperHelper::parseQuery(const GdbMi &contents)
|
|||||||
if (childCount > 1) {
|
if (childCount > 1) {
|
||||||
const int size = sizesList.childAt(0).data().toInt();
|
const int size = sizesList.childAt(0).data().toInt();
|
||||||
for (int c = 1; c < childCount; c++)
|
for (int c = 1; c < childCount; c++)
|
||||||
addSize(QLatin1String(sizesList.childAt(c).data()), size);
|
addSize(sizesList.childAt(c).data(), size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Parse expressions
|
// Parse expressions
|
||||||
foreach (const GdbMi &exprList, contents.findChild("expressions").children())
|
foreach (const GdbMi &exprList, contents.findChild("expressions").children())
|
||||||
if (exprList.childCount() == 2)
|
if (exprList.childCount() == 2)
|
||||||
m_expressionCache.insert(QLatin1String(exprList.childAt(0).data()),
|
m_expressionCache.insert(exprList.childAt(0).data(),
|
||||||
QLatin1String(exprList.childAt(1).data()));
|
exprList.childAt(1).data());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,10 +1043,10 @@ bool QtDumperHelper::parseQuery(const char *data)
|
|||||||
return parseQuery(root);
|
return parseQuery(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtDumperHelper::addSize(const QString &name, int size)
|
void QtDumperHelper::addSize(const QByteArray &name, int size)
|
||||||
{
|
{
|
||||||
// Special interest cases
|
// Special interest cases
|
||||||
if (name == QLatin1String("char*")) {
|
if (name == "char*") {
|
||||||
m_specialSizes[PointerSize] = size;
|
m_specialSizes[PointerSize] = size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1045,27 +1057,27 @@ void QtDumperHelper::addSize(const QString &name, int size)
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
// CDB helpers
|
// CDB helpers
|
||||||
if (name == QLatin1String("std::string")) {
|
if (name == "std::string") {
|
||||||
m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), size);
|
m_sizeCache.insert("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);
|
m_sizeCache.insert("basic_string<char,char_traits<char>,allocator<char> >", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (name == QLatin1String("std::wstring")) {
|
if (name == "std::wstring") {
|
||||||
m_sizeCache.insert(QLatin1String("basic_string<unsigned short,char_traits<unsignedshort>,allocator<unsignedshort> >"), size);
|
m_sizeCache.insert("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);
|
m_sizeCache.insert("std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (false);
|
} while (false);
|
||||||
m_sizeCache.insert(name, size);
|
m_sizeCache.insert(name, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDumperHelper::Type QtDumperHelper::type(const QString &typeName) const
|
QtDumperHelper::Type QtDumperHelper::type(const QByteArray &typeName) const
|
||||||
{
|
{
|
||||||
const QtDumperHelper::TypeData td = typeData(typeName);
|
const QtDumperHelper::TypeData td = typeData(typeName);
|
||||||
return td.type;
|
return td.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDumperHelper::TypeData QtDumperHelper::typeData(const QString &typeName) const
|
QtDumperHelper::TypeData QtDumperHelper::typeData(const QByteArray &typeName) const
|
||||||
{
|
{
|
||||||
TypeData td;
|
TypeData td;
|
||||||
td.type = UnknownType;
|
td.type = UnknownType;
|
||||||
@@ -1086,32 +1098,30 @@ QtDumperHelper::TypeData QtDumperHelper::typeData(const QString &typeName) const
|
|||||||
|
|
||||||
// Format an expression to have the debugger query the
|
// Format an expression to have the debugger query the
|
||||||
// size. Use size cache if possible
|
// size. Use size cache if possible
|
||||||
QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName,
|
QByteArray QtDumperHelper::evaluationSizeofTypeExpression(const QByteArray &typeName,
|
||||||
Debugger debugger) const
|
Debugger debugger) const
|
||||||
{
|
{
|
||||||
// Look up special size types
|
// Look up special size types
|
||||||
const SpecialSizeType st = specialSizeType(typeName);
|
const SpecialSizeType st = specialSizeType(typeName);
|
||||||
if (st != SpecialSizeCount) {
|
if (st != SpecialSizeCount) {
|
||||||
if (const int size = m_specialSizes[st])
|
if (const int size = m_specialSizes[st])
|
||||||
return QString::number(size);
|
return QByteArray::number(size);
|
||||||
}
|
}
|
||||||
// Look up size cache
|
// Look up size cache
|
||||||
const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName);
|
const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName);
|
||||||
if (sit != m_sizeCache.constEnd())
|
if (sit != m_sizeCache.constEnd())
|
||||||
return QString::number(sit.value());
|
return QByteArray::number(sit.value());
|
||||||
// Finally have the debugger evaluate
|
// Finally have the debugger evaluate
|
||||||
return sizeofTypeExpression(typeName, debugger);
|
return sizeofTypeExpression(typeName, debugger);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDumperHelper::SpecialSizeType QtDumperHelper::specialSizeType(const QString &typeName) const
|
QtDumperHelper::SpecialSizeType QtDumperHelper::specialSizeType(const QByteArray &typeName) const
|
||||||
{
|
{
|
||||||
if (isPointerType(typeName))
|
if (isPointerType(typeName))
|
||||||
return PointerSize;
|
return PointerSize;
|
||||||
static const QString intType = QLatin1String("int");
|
if (typeName == "int")
|
||||||
static const QString stdAllocatorPrefix = QLatin1String("std::allocator");
|
|
||||||
if (typeName == intType)
|
|
||||||
return IntSize;
|
return IntSize;
|
||||||
if (typeName.startsWith(stdAllocatorPrefix))
|
if (typeName.startsWith("std::allocator"))
|
||||||
return StdAllocatorSize;
|
return StdAllocatorSize;
|
||||||
if (typeName.startsWith(m_qPointerPrefix))
|
if (typeName.startsWith(m_qPointerPrefix))
|
||||||
return QPointerSize;
|
return QPointerSize;
|
||||||
@@ -1147,14 +1157,14 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
const TypeData &td,
|
const TypeData &td,
|
||||||
Debugger debugger,
|
Debugger debugger,
|
||||||
QByteArray *inBuffer,
|
QByteArray *inBuffer,
|
||||||
QStringList *extraArgsIn) const
|
QByteArrayList *extraArgsIn) const
|
||||||
{
|
{
|
||||||
enum { maxExtraArgCount = 4 };
|
enum { maxExtraArgCount = 4 };
|
||||||
|
|
||||||
QStringList &extraArgs = *extraArgsIn;
|
QByteArrayList &extraArgs = *extraArgsIn;
|
||||||
|
|
||||||
// See extractTemplate for parameters
|
// See extractTemplate for parameters
|
||||||
QStringList inners = td.inner.split(QLatin1Char('@'));
|
QByteArrayList inners = td.inner.split('@');
|
||||||
if (inners.at(0).isEmpty())
|
if (inners.at(0).isEmpty())
|
||||||
inners.clear();
|
inners.clear();
|
||||||
for (int i = 0; i != inners.size(); ++i)
|
for (int i = 0; i != inners.size(); ++i)
|
||||||
@@ -1162,10 +1172,11 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
|
|
||||||
QString outertype = td.isTemplate ? td.tmplate : data.type;
|
QString outertype = td.isTemplate ? td.tmplate : data.type;
|
||||||
// adjust the data extract
|
// adjust the data extract
|
||||||
if (outertype == m_qtNamespace + QLatin1String("QWidget"))
|
if (outertype == m_qtNamespace + "QWidget")
|
||||||
outertype = m_qtNamespace + QLatin1String("QObject");
|
outertype = m_qtNamespace + "QObject";
|
||||||
|
|
||||||
QString inner = td.inner;
|
QString inner = td.inner;
|
||||||
|
const QByteArray zero = "0";
|
||||||
|
|
||||||
extraArgs.clear();
|
extraArgs.clear();
|
||||||
|
|
||||||
@@ -1178,10 +1189,9 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
}
|
}
|
||||||
int extraArgCount = extraArgs.size();
|
int extraArgCount = extraArgs.size();
|
||||||
// Pad with zeros
|
// Pad with zeros
|
||||||
const QString zero = QString(QLatin1Char('0'));
|
|
||||||
const int extraPad = maxExtraArgCount - extraArgCount;
|
const int extraPad = maxExtraArgCount - extraArgCount;
|
||||||
for (int i = 0; i < extraPad; i++)
|
for (int i = 0; i < extraPad; i++)
|
||||||
extraArgs.push_back(zero);
|
extraArgs.push_back("0");
|
||||||
|
|
||||||
// in rare cases we need more or less:
|
// in rare cases we need more or less:
|
||||||
switch (td.type) {
|
switch (td.type) {
|
||||||
@@ -1193,20 +1203,20 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
// we need the number out of something like
|
// we need the number out of something like
|
||||||
// iname="local.ob.slots.2" // ".deleteLater()"?
|
// iname="local.ob.slots.2" // ".deleteLater()"?
|
||||||
const int pos = data.iname.lastIndexOf('.');
|
const int pos = data.iname.lastIndexOf('.');
|
||||||
const QString slotNumber = data.iname.mid(pos + 1);
|
const QByteArray slotNumber = data.iname.mid(pos + 1);
|
||||||
QTC_ASSERT(slotNumber.toInt() != -1, /**/);
|
QTC_ASSERT(slotNumber.toInt() != -1, /**/);
|
||||||
extraArgs[0] = slotNumber;
|
extraArgs[0] = slotNumber;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QMapType:
|
case QMapType:
|
||||||
case QMultiMapType: {
|
case QMultiMapType: {
|
||||||
QString nodetype;
|
QByteArray nodetype;
|
||||||
if (m_qtVersion >= 0x040500) {
|
if (m_qtVersion >= 0x040500) {
|
||||||
nodetype = m_qtNamespace + QLatin1String("QMapNode");
|
nodetype = m_qtNamespace + "QMapNode";
|
||||||
nodetype += data.type.mid(outertype.size());
|
nodetype += data.type.mid(outertype.size());
|
||||||
} else {
|
} else {
|
||||||
// FIXME: doesn't work for QMultiMap
|
// FIXME: doesn't work for QMultiMap
|
||||||
nodetype = data.type + QLatin1String("::Node");
|
nodetype = data.type + "::Node";
|
||||||
}
|
}
|
||||||
//qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
|
//qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
|
||||||
// << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
|
// << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
|
||||||
@@ -1220,22 +1230,21 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
break;
|
break;
|
||||||
case StdVectorType:
|
case StdVectorType:
|
||||||
//qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
|
//qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
|
||||||
if (inners.at(0) == QLatin1String("bool")) {
|
if (inners.at(0) == "bool")
|
||||||
outertype = QLatin1String("std::vector::bool");
|
outertype = "std::vector::bool";
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case StdDequeType:
|
case StdDequeType:
|
||||||
extraArgs[1] = zero;
|
extraArgs[1] = "0";
|
||||||
break;
|
break;
|
||||||
case StdStackType:
|
case StdStackType:
|
||||||
// remove 'std::allocator<...>':
|
// remove 'std::allocator<...>':
|
||||||
extraArgs[1] = zero;
|
extraArgs[1] = "0";
|
||||||
break;
|
break;
|
||||||
case StdSetType:
|
case StdSetType:
|
||||||
// remove 'std::less<...>':
|
// remove 'std::less<...>':
|
||||||
extraArgs[1] = zero;
|
extraArgs[1] = "0";
|
||||||
// remove 'std::allocator<...>':
|
// remove 'std::allocator<...>':
|
||||||
extraArgs[2] = zero;
|
extraArgs[2] = "0";
|
||||||
break;
|
break;
|
||||||
case StdMapType: {
|
case StdMapType: {
|
||||||
// We need the offset of the second item in the value pair.
|
// We need the offset of the second item in the value pair.
|
||||||
@@ -1245,42 +1254,40 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
// -> "std::pair<Key,Value>". Different debuggers have varying
|
// -> "std::pair<Key,Value>". Different debuggers have varying
|
||||||
// amounts of terminating blanks...
|
// amounts of terminating blanks...
|
||||||
extraArgs[2].clear();
|
extraArgs[2].clear();
|
||||||
extraArgs[3] = zero;
|
extraArgs[3] = "0";
|
||||||
QString pairType = inners.at(3);
|
QByteArray pairType = inners.at(3);
|
||||||
int bracketPos = pairType.indexOf(QLatin1Char('<'));
|
int bracketPos = pairType.indexOf('<');
|
||||||
if (bracketPos != -1)
|
if (bracketPos != -1)
|
||||||
pairType.remove(0, bracketPos + 1);
|
pairType.remove(0, bracketPos + 1);
|
||||||
// We don't want the comparator and the allocator confuse gdb.
|
// We don't want the comparator and the allocator confuse gdb.
|
||||||
const QChar closingBracket = QLatin1Char('>');
|
const char closingBracket = '>';
|
||||||
bracketPos = pairType.lastIndexOf(closingBracket);
|
bracketPos = pairType.lastIndexOf(closingBracket);
|
||||||
if (bracketPos != -1)
|
if (bracketPos != -1)
|
||||||
bracketPos = pairType.lastIndexOf(closingBracket, bracketPos - pairType.size() - 1);
|
bracketPos = pairType.lastIndexOf(closingBracket, bracketPos - pairType.size() - 1);
|
||||||
if (bracketPos != -1)
|
if (bracketPos != -1)
|
||||||
pairType.truncate(bracketPos + 1);
|
pairType.truncate(bracketPos + 1);
|
||||||
if (debugger == GdbDebugger) {
|
if (debugger == GdbDebugger) {
|
||||||
extraArgs[2] = QLatin1String("(size_t)&(('");
|
extraArgs[2] = "(size_t)&(('";
|
||||||
extraArgs[2] += pairType;
|
extraArgs[2] += pairType;
|
||||||
extraArgs[2] += QLatin1String("'*)0)->second");
|
extraArgs[2] += "'*)0)->second";
|
||||||
} else {
|
} else {
|
||||||
// Cdb: The std::pair is usually in scope. Still, this expression
|
// Cdb: The std::pair is usually in scope. Still, this expression
|
||||||
// occasionally fails for complex types (std::string).
|
// occasionally fails for complex types (std::string).
|
||||||
// We need an address as CDB cannot do the 0-trick.
|
// We need an address as CDB cannot do the 0-trick.
|
||||||
// Use data address or try at least cache if missing.
|
// Use data address or try at least cache if missing.
|
||||||
const QString address = data.addr.isEmpty() ? QString::fromLatin1("DUMMY_ADDRESS") : data.addr;
|
const QByteArray address = data.addr.isEmpty() ? "DUMMY_ADDRESS" : data.addr;
|
||||||
QString offsetExpr;
|
QByteArray offsetExpr = "(size_t)&(((" + pairType + " *)" + address
|
||||||
QTextStream str(&offsetExpr);
|
+ ")->second)" + '-' + address;
|
||||||
str << "(size_t)&(((" << pairType << " *)" << address << ")->second)" << '-' << address;
|
|
||||||
extraArgs[2] = lookupCdbDummyAddressExpression(offsetExpr, address);
|
extraArgs[2] = lookupCdbDummyAddressExpression(offsetExpr, address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StdStringType:
|
case StdStringType:
|
||||||
//qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
|
//qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
|
||||||
if (inners.at(0) == QLatin1String("char")) {
|
if (inners.at(0) == "char")
|
||||||
outertype = QLatin1String("std::string");
|
outertype = "std::string";
|
||||||
} else if (inners.at(0) == QLatin1String("wchar_t")) {
|
else if (inners.at(0) == "wchar_t")
|
||||||
outertype = QLatin1String("std::wstring");
|
outertype = "std::wstring";
|
||||||
}
|
|
||||||
qFill(extraArgs, zero);
|
qFill(extraArgs, zero);
|
||||||
break;
|
break;
|
||||||
case UnknownType:
|
case UnknownType:
|
||||||
@@ -1296,12 +1303,12 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
|
|
||||||
// Look up expressions in the cache
|
// Look up expressions in the cache
|
||||||
if (!m_expressionCache.empty()) {
|
if (!m_expressionCache.empty()) {
|
||||||
const QMap<QString, QString>::const_iterator excCend = m_expressionCache.constEnd();
|
const ExpressionCache::const_iterator excCend = m_expressionCache.constEnd();
|
||||||
const QStringList::iterator eend = extraArgs.end();
|
const QByteArrayList::iterator eend = extraArgs.end();
|
||||||
for (QStringList::iterator it = extraArgs.begin(); it != eend; ++it) {
|
for (QByteArrayList::iterator it = extraArgs.begin(); it != eend; ++it) {
|
||||||
QString &e = *it;
|
QByteArray &e = *it;
|
||||||
if (!e.isEmpty() && e != zero && !isInteger(e)) {
|
if (!e.isEmpty() && e != zero && !isInteger(e)) {
|
||||||
const QMap<QString, QString>::const_iterator eit = m_expressionCache.constFind(e);
|
const ExpressionCache::const_iterator eit = m_expressionCache.constFind(e);
|
||||||
if (eit != excCend)
|
if (eit != excCend)
|
||||||
e = eit.value();
|
e = eit.value();
|
||||||
}
|
}
|
||||||
@@ -1325,25 +1332,23 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return debugger expression to get the offset of a map node.
|
// Return debugger expression to get the offset of a map node.
|
||||||
QString QtDumperHelper::qMapNodeValueOffsetExpression(const QString &type,
|
QByteArray QtDumperHelper::qMapNodeValueOffsetExpression
|
||||||
const QString &addressIn,
|
(const QByteArray &type, const QByteArray &addressIn, Debugger debugger) const
|
||||||
Debugger debugger) const
|
|
||||||
{
|
{
|
||||||
switch (debugger) {
|
switch (debugger) {
|
||||||
case GdbDebugger:
|
case GdbDebugger:
|
||||||
return QLatin1String("(size_t)&(('") + type + QLatin1String("'*)0)->value");
|
return "(size_t)&(('" + type + "'*)0)->value";
|
||||||
case CdbDebugger: {
|
case CdbDebugger: {
|
||||||
// Cdb: This will only work if a QMapNode is in scope.
|
// Cdb: This will only work if a QMapNode is in scope.
|
||||||
// We need an address as CDB cannot do the 0-trick.
|
// We need an address as CDB cannot do the 0-trick.
|
||||||
// Use data address or try at least cache if missing.
|
// Use data address or try at least cache if missing.
|
||||||
const QString address = addressIn.isEmpty() ? QString::fromLatin1("DUMMY_ADDRESS") : addressIn;
|
const QByteArray address = addressIn.isEmpty() ? "DUMMY_ADDRESS" : addressIn;
|
||||||
QString offsetExpression;
|
QByteArray offsetExpression = "(size_t)&(((" + type
|
||||||
QTextStream(&offsetExpression) << "(size_t)&(((" << type
|
+ " *)" + address + ")->value)-" + address;
|
||||||
<< " *)" << address << ")->value)-" << address;
|
|
||||||
return lookupCdbDummyAddressExpression(offsetExpression, address);
|
return lookupCdbDummyAddressExpression(offsetExpression, address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QString();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cdb cannot do tricks like ( "&(std::pair<int,int>*)(0)->second)",
|
/* Cdb cannot do tricks like ( "&(std::pair<int,int>*)(0)->second)",
|
||||||
@@ -1352,12 +1357,12 @@ QString QtDumperHelper::qMapNodeValueOffsetExpression(const QString &type,
|
|||||||
* "memory access error". As a trick, use the address of the watch item
|
* "memory access error". As a trick, use the address of the watch item
|
||||||
* to do this. However, in the expression cache, 0 is still used, so,
|
* to do this. However, in the expression cache, 0 is still used, so,
|
||||||
* for cache lookups, use '0' as address. */
|
* for cache lookups, use '0' as address. */
|
||||||
QString QtDumperHelper::lookupCdbDummyAddressExpression(const QString &expr,
|
QByteArray QtDumperHelper::lookupCdbDummyAddressExpression
|
||||||
const QString &address) const
|
(const QByteArray &expr, const QByteArray &address) const
|
||||||
{
|
{
|
||||||
QString nullExpr = expr;
|
QByteArray nullExpr = expr;
|
||||||
nullExpr.replace(address, QString(QLatin1Char('0')));
|
nullExpr.replace(address, "0");
|
||||||
const QString rc = m_expressionCache.value(nullExpr, expr);
|
const QByteArray rc = m_expressionCache.value(nullExpr, expr);
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << "lookupCdbDummyAddressExpression" << expr << rc;
|
qDebug() << "lookupCdbDummyAddressExpression" << expr << rc;
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1365,9 +1370,7 @@ QString QtDumperHelper::lookupCdbDummyAddressExpression(const QString &expr,
|
|||||||
|
|
||||||
// GdbMi parsing helpers for parsing dumper value results
|
// GdbMi parsing helpers for parsing dumper value results
|
||||||
|
|
||||||
static bool gdbMiGetIntValue(int *target,
|
static bool gdbMiGetIntValue(int *target, const GdbMi &node, const char *child)
|
||||||
const GdbMi &node,
|
|
||||||
const char *child)
|
|
||||||
{
|
{
|
||||||
*target = -1;
|
*target = -1;
|
||||||
const GdbMi childNode = node.findChild(child);
|
const GdbMi childNode = node.findChild(child);
|
||||||
@@ -1497,9 +1500,9 @@ static void gbdMiToWatchData(const GdbMi &root,
|
|||||||
// Type from context or self
|
// Type from context or self
|
||||||
if (ctx.childType.isEmpty()) {
|
if (ctx.childType.isEmpty()) {
|
||||||
if (gdbMiGetStringValue(&v, root, "type"))
|
if (gdbMiGetStringValue(&v, root, "type"))
|
||||||
w.setType(v);
|
w.setType(v.toUtf8());
|
||||||
} else {
|
} else {
|
||||||
w.setType(ctx.childType);
|
w.setType(ctx.childType.toUtf8());
|
||||||
}
|
}
|
||||||
// child count?
|
// child count?
|
||||||
int numChild = -1;
|
int numChild = -1;
|
||||||
@@ -1616,14 +1619,14 @@ void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr)
|
|||||||
{
|
{
|
||||||
data.addr = addr;
|
data.addr = addr;
|
||||||
if (data.exp.isEmpty() && !data.addr.startsWith("$"))
|
if (data.exp.isEmpty() && !data.addr.startsWith("$"))
|
||||||
data.exp = "*(" + gdbQuoteTypes(data.type).toLatin1() + "*)" + data.addr;
|
data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" + data.addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the "type" and "displayedtype" children of root and set up type.
|
// Find the "type" and "displayedtype" children of root and set up type.
|
||||||
void setWatchDataType(WatchData &data, const GdbMi &item)
|
void setWatchDataType(WatchData &data, const GdbMi &item)
|
||||||
{
|
{
|
||||||
if (item.isValid())
|
if (item.isValid())
|
||||||
data.setType(_(item.data()));
|
data.setType(item.data());
|
||||||
else if (data.type.isEmpty())
|
else if (data.type.isEmpty())
|
||||||
data.setTypeNeeded();
|
data.setTypeNeeded();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,19 +70,19 @@ inline bool isNameChar(char c)
|
|||||||
bool hasLetterOrNumber(const QString &exp);
|
bool hasLetterOrNumber(const QString &exp);
|
||||||
bool hasSideEffects(const QString &exp);
|
bool hasSideEffects(const QString &exp);
|
||||||
bool isKeyWord(const QString &exp);
|
bool isKeyWord(const QString &exp);
|
||||||
bool isPointerType(const QString &type);
|
bool isPointerType(const QByteArray &type);
|
||||||
bool isCharPointerType(const QString &type);
|
bool isCharPointerType(const QByteArray &type);
|
||||||
bool startsWithDigit(const QString &str);
|
bool startsWithDigit(const QString &str);
|
||||||
QString stripPointerType(QString type);
|
QByteArray stripPointerType(QByteArray type);
|
||||||
QString gdbQuoteTypes(const QString &type);
|
QString gdbQuoteTypes(const QString &type);
|
||||||
bool extractTemplate(const QString &type, QString *tmplate, QString *inner);
|
bool extractTemplate(const QString &type, QString *tmplate, QString *inner);
|
||||||
QString extractTypeFromPTypeOutput(const QString &str);
|
QString extractTypeFromPTypeOutput(const QString &str);
|
||||||
bool isIntOrFloatType(const QString &type);
|
bool isIntOrFloatType(const QByteArray &type);
|
||||||
bool isIntType(const QString &type);
|
bool isIntType(const QByteArray &type);
|
||||||
bool isSymbianIntType(const QString &type);
|
bool isSymbianIntType(const QByteArray &type);
|
||||||
|
|
||||||
enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
|
enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
|
||||||
GuessChildrenResult guessChildren(const QString &type);
|
GuessChildrenResult guessChildren(const QByteArray &type);
|
||||||
|
|
||||||
QString quoteUnprintableLatin1(const QByteArray &ba);
|
QString quoteUnprintableLatin1(const QByteArray &ba);
|
||||||
|
|
||||||
@@ -144,8 +144,8 @@ public:
|
|||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
bool isTemplate;
|
bool isTemplate;
|
||||||
QString tmplate;
|
QByteArray tmplate;
|
||||||
QString inner;
|
QByteArray inner;
|
||||||
};
|
};
|
||||||
|
|
||||||
QtDumperHelper();
|
QtDumperHelper();
|
||||||
@@ -155,28 +155,28 @@ public:
|
|||||||
|
|
||||||
int typeCount() const;
|
int typeCount() const;
|
||||||
// Look up a simple, non-template type
|
// Look up a simple, non-template type
|
||||||
Type simpleType(const QString &simpleType) const;
|
Type simpleType(const QByteArray &simpleType) const;
|
||||||
// Look up a (potentially) template type and fill parameter struct
|
// Look up a (potentially) template type and fill parameter struct
|
||||||
TypeData typeData(const QString &typeName) const;
|
TypeData typeData(const QByteArray &typeName) const;
|
||||||
Type type(const QString &typeName) const;
|
Type type(const QByteArray &typeName) const;
|
||||||
|
|
||||||
int qtVersion() const;
|
int qtVersion() const;
|
||||||
QString qtVersionString() const;
|
QByteArray qtVersionString() const;
|
||||||
QString qtNamespace() const;
|
QByteArray qtNamespace() const;
|
||||||
|
|
||||||
// Complete parse of "query" (protocol 1) response from debuggee buffer.
|
// Complete parse of "query" (protocol 1) response from debuggee buffer.
|
||||||
// 'data' excludes the leading indicator character.
|
// 'data' excludes the leading indicator character.
|
||||||
bool parseQuery(const char *data);
|
bool parseQuery(const char *data);
|
||||||
bool parseQuery(const GdbMi &data);
|
bool parseQuery(const GdbMi &data);
|
||||||
// Sizes can be added as the debugger determines them
|
// Sizes can be added as the debugger determines them
|
||||||
void addSize(const QString &name, int size);
|
void addSize(const QByteArray &type, int size);
|
||||||
|
|
||||||
// Determine the parameters required for an "evaluate" (protocol 2) call
|
// Determine the parameters required for an "evaluate" (protocol 2) call
|
||||||
void evaluationParameters(const WatchData &data,
|
void evaluationParameters(const WatchData &data,
|
||||||
const TypeData &td,
|
const TypeData &td,
|
||||||
Debugger debugger,
|
Debugger debugger,
|
||||||
QByteArray *inBuffer,
|
QByteArray *inBuffer,
|
||||||
QStringList *extraParameters) const;
|
QList<QByteArray> *extraParameters) const;
|
||||||
|
|
||||||
// Parse the value response (protocol 2) from debuggee buffer.
|
// Parse the value response (protocol 2) from debuggee buffer.
|
||||||
// 'data' excludes the leading indicator character.
|
// 'data' excludes the leading indicator character.
|
||||||
@@ -188,15 +188,15 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
typedef QMap<QString, Type> NameTypeMap;
|
typedef QMap<QString, Type> NameTypeMap;
|
||||||
typedef QMap<QString, int> SizeCache;
|
typedef QMap<QByteArray, int> SizeCache;
|
||||||
|
|
||||||
// Look up a simple (namespace) type
|
// Look up a simple (namespace) type
|
||||||
QString evaluationSizeofTypeExpression(const QString &typeName, Debugger d) const;
|
QByteArray evaluationSizeofTypeExpression(const QByteArray &typeName, Debugger d) const;
|
||||||
QString qMapNodeValueOffsetExpression(const QString &type,
|
QByteArray qMapNodeValueOffsetExpression(const QByteArray &type,
|
||||||
const QString &addressIn,
|
const QByteArray &addressIn, Debugger debugger) const;
|
||||||
Debugger debugger) const;
|
|
||||||
|
|
||||||
QString lookupCdbDummyAddressExpression(const QString &expr, const QString &address) const;
|
QByteArray lookupCdbDummyAddressExpression
|
||||||
|
(const QByteArray &expr, const QByteArray &address) const;
|
||||||
|
|
||||||
NameTypeMap m_nameTypeMap;
|
NameTypeMap m_nameTypeMap;
|
||||||
SizeCache m_sizeCache;
|
SizeCache m_sizeCache;
|
||||||
@@ -211,25 +211,26 @@ private:
|
|||||||
SpecialSizeCount };
|
SpecialSizeCount };
|
||||||
|
|
||||||
// Resolve name to enumeration or SpecialSizeCount (invalid)
|
// Resolve name to enumeration or SpecialSizeCount (invalid)
|
||||||
SpecialSizeType specialSizeType(const QString &t) const;
|
SpecialSizeType specialSizeType(const QByteArray &type) const;
|
||||||
|
|
||||||
int m_specialSizes[SpecialSizeCount];
|
int m_specialSizes[SpecialSizeCount];
|
||||||
|
|
||||||
QMap<QString, QString> m_expressionCache;
|
typedef QMap<QByteArray, QByteArray> ExpressionCache;
|
||||||
|
ExpressionCache m_expressionCache;
|
||||||
int m_qtVersion;
|
int m_qtVersion;
|
||||||
double m_dumperVersion;
|
double m_dumperVersion;
|
||||||
QString m_qtNamespace;
|
QByteArray m_qtNamespace;
|
||||||
|
|
||||||
void setQClassPrefixes(const QString &qNamespace);
|
void setQClassPrefixes(const QByteArray &qNamespace);
|
||||||
|
|
||||||
QString m_qPointerPrefix;
|
QByteArray m_qPointerPrefix;
|
||||||
QString m_qSharedPointerPrefix;
|
QByteArray m_qSharedPointerPrefix;
|
||||||
QString m_qSharedDataPointerPrefix;
|
QByteArray m_qSharedDataPointerPrefix;
|
||||||
QString m_qWeakPointerPrefix;
|
QByteArray m_qWeakPointerPrefix;
|
||||||
QString m_qListPrefix;
|
QByteArray m_qListPrefix;
|
||||||
QString m_qLinkedListPrefix;
|
QByteArray m_qLinkedListPrefix;
|
||||||
QString m_qVectorPrefix;
|
QByteArray m_qVectorPrefix;
|
||||||
QString m_qQueuePrefix;
|
QByteArray m_qQueuePrefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d);
|
QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d);
|
||||||
|
|||||||
Reference in New Issue
Block a user