OSDN Git Service

Debugger/CDB: Windows 64 integer handling.
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Wed, 25 Nov 2009 15:32:44 +0000 (16:32 +0100)
committercon <qtc-committer@nokia.com>
Wed, 25 Nov 2009 15:57:22 +0000 (16:57 +0100)
Convert CDB unsigned integer values should they appear in hex,
make format flexible.
Use int64 for reformatting integers to be able to accommodate
64 bit values on Windows 64. Add some more integer types.
Do not save decimal type formats. Add menu option to clear
individual formatting. Do not use map[] to query the type formats
(inserting 0 everywhere as a side effect).

Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
(cherry picked from commit 2b23ea2a8ac8166820b76476b18fd7fd7014e695)

src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
src/plugins/debugger/watchhandler.cpp
src/plugins/debugger/watchutils.cpp
src/plugins/debugger/watchwindow.cpp

index feb7353..2589046 100644 (file)
@@ -402,16 +402,20 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
 }
 
 // Return hexadecimal pointer value from a CDB pointer value
-// which look like "0x000032a" or "0x00000000`0250124a" on 64-bit systems.
-static bool inline getPointerValue(QString stringValue, quint64 *value)
+// which look like "0x000032a" or "0x00000000`0250124a" or
+// "0x1`0250124a" on 64-bit systems.
+static bool inline getUnsignedHexValue(QString stringValue, quint64 *value)
 {
     *value = 0;
     if (!stringValue.startsWith(QLatin1String("0x")))
         return false;
     stringValue.remove(0, 2);
     // Remove 64bit separator
-    if (stringValue.size() > 8 && stringValue.at(8) == QLatin1Char('`'))
-        stringValue.remove(8, 1);
+    if (stringValue.size() > 9) {       
+        const int sepPos = stringValue.size() - 9;
+        if (stringValue.at(sepPos) == QLatin1Char('`'))
+            stringValue.remove(sepPos, 1);
+    }
     bool ok;
     *value = stringValue.toULongLong(&ok, 16);
     return ok;
@@ -427,7 +431,7 @@ static inline bool isNullPointer(const WatchData &wd)
     if (blankPos != -1)
         stringValue.truncate(blankPos);
     quint64 value;
-    return getPointerValue(stringValue, &value) && value == 0u;
+    return getUnsignedHexValue(stringValue, &value) && value == 0u;
 }
 
 // Fix a symbol group value. It is set to the class type for
@@ -445,11 +449,21 @@ static inline QString removeInnerTemplateType(QString value)
     return value;
 }
 
-static inline QString fixValue(const QString &value)
+// Fix display values: Pass through strings, convert unsigned integers
+// to decimal ('0x5454`fedf'), remove inner templates from
+// "0x4343 class list<>".
+static inline QString fixValue(const QString &value, const QString &type)
 {
-    if (value.size() < 20 || value.endsWith(QLatin1Char('"')))
+    if (value.endsWith(QLatin1Char('"'))) // Pass through strings
         return value;
-    return removeInnerTemplateType(value);
+    const int size = value.size();
+    // Unsigned hex numbers
+    if (isIntType(type) && (size > 2 && value.at(1) == QLatin1Char('x'))) {
+        quint64 intValue;
+        if (getUnsignedHexValue(value, &intValue))
+            return QString::number(intValue);
+    }
+    return size < 20 ? value : removeInnerTemplateType(value);
 }
 
 WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
@@ -481,7 +495,7 @@ WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
         return wd;
     }
     const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
-    wd.setValue(fixValue(value));
+    wd.setValue(fixValue(value, type));
     wd.setChildrenNeeded(); // compensate side effects of above setters
     // Figure out children. The SubElement is only a guess unless the symbol,
     // is expanded, so, we leave this as a guess for later updates.
@@ -729,10 +743,10 @@ static inline bool getIntValue(CIDebugSymbolGroup *sg, int index, int *value)
 
 // Get pointer value of symbol group ("0xAAB")
 // Note that this is on "00000000`0250124a" on 64bit systems.
-static inline bool getPointerValue(CIDebugSymbolGroup *sg, int index, quint64 *value)
+static inline bool getUnsignedHexValue(CIDebugSymbolGroup *sg, int index, quint64 *value)
 {
     const QString stringValue = getSymbolString(sg, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
-    return getPointerValue(stringValue, value);
+    return getUnsignedHexValue(stringValue, value);
 }
 
 int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
@@ -756,7 +770,7 @@ int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
     if (!getIntValue(m_symbolGroup, sizeIndex, &size))
         return 4;
     quint64 array;
-    if (!getPointerValue(m_symbolGroup, arrayIndex, &array))
+    if (!getUnsignedHexValue(m_symbolGroup, arrayIndex, &array))
         return 5;
     // Fetch
     const bool truncated = size > maxLength;
index 82c6948..c6ea415 100644 (file)
@@ -588,21 +588,32 @@ QString niceType(const QString typeIn)
     return type;
 }
 
+template <class IntType> QString reformatInteger(IntType value, int format)
+{
+    switch (format) {
+    case HexadecimalFormat:
+        return ("(hex) ") + QString::number(value, 16);
+    case BinaryFormat:
+        return ("(bin) ") + QString::number(value, 2);
+    case OctalFormat:
+        return ("(oct) ") + QString::number(value, 8);
+    }
+    return QString::number(value); // not reached
+}
+
 static QString formattedValue(const WatchData &data,
     int individualFormat, int typeFormat)
 {
     if (isIntType(data.type)) {
-        int format = individualFormat == -1 ? typeFormat : individualFormat;
-        int value = data.value.toInt();
-        if (format == HexadecimalFormat)
-            return ("(hex) ") + QString::number(value, 16);
-        if (format == BinaryFormat)
-            return ("(bin) ") + QString::number(value, 2);
-        if (format == OctalFormat)
-            return ("(oct) ") + QString::number(value, 8);
-        return data.value;
+        const int format = individualFormat == -1 ? typeFormat : individualFormat;
+        if (format <= 0)
+            return data.value;
+        if (data.type.contains(QLatin1String("unsigned"))) {            
+            return reformatInteger(data.value.toULongLong(), format);
+        } else {
+            return reformatInteger(data.value.toLongLong(), format);
+        }
     }
-
     return data.value;
 }
 
@@ -769,15 +780,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
             break;
 
         case TypeFormatRole:
-            return m_handler->m_typeFormats[data.type];
-
-        case IndividualFormatRole: {
-            int format = m_handler->m_individualFormats[data.iname];
-            if (format == -1)
-                return m_handler->m_typeFormats[data.type];
-            return format;
-        }
-        
+            return m_handler->m_typeFormats.value(data.type, -1);
+        case IndividualFormatRole:
+            return m_handler->m_individualFormats.value(data.iname, -1);
         case AddressRole: {
             if (!data.addr.isEmpty())
                 return data.addr;
@@ -807,8 +812,13 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
         }
     } else if (role == TypeFormatRole) {
         m_handler->setFormat(data.type, value.toInt());
-    } else if (role == IndividualFormatRole) {
-        m_handler->m_individualFormats[data.iname] = value.toInt();
+    } else if (role == IndividualFormatRole) {        
+        const int format = value.toInt();
+        if (format == -1) {
+            m_handler->m_individualFormats.remove(data.iname);
+        } else {
+            m_handler->m_individualFormats[data.iname] = format;
+        }
     }
     emit dataChanged(index, index);
     return true;
@@ -1373,9 +1383,12 @@ void WatchHandler::saveTypeFormats()
     QHashIterator<QString, int> it(m_typeFormats);
     while (it.hasNext()) {
         it.next();
-        QString key = it.key().trimmed();
-        if (!key.isEmpty())
-            typeFormats.insert(key, it.value());
+        const int format = it.value();
+        if (format != DecimalFormat) {
+            const QString key = it.key().trimmed();
+            if (!key.isEmpty())
+                typeFormats.insert(key, format);
+        }
     }
     m_manager->setSessionValue("DefaultFormats", QVariant(typeFormats));
 }
index 1e11376..f5ef925 100644 (file)
@@ -542,8 +542,13 @@ bool isIntType(const QString &type)
         << QLatin1String("long") << QLatin1String("bool")
         << QLatin1String("signed char") << QLatin1String("unsigned")
         << QLatin1String("unsigned char") << QLatin1String("unsigned long")
-        << QLatin1String("long long")  << QLatin1String("unsigned long long");
-    return type.endsWith(QLatin1String(" int")) || types.contains(type);
+        << QLatin1String("long long")  << QLatin1String("unsigned long long")
+        << QLatin1String("qint16") << QLatin1String("quint16")
+        << QLatin1String("qint32") << QLatin1String("quint32")
+        << QLatin1String("qint64") << QLatin1String("quint64");
+    return type.endsWith(QLatin1String(" int"))
+            || type.endsWith(QLatin1String(" int64"))
+            || types.contains(type);
 }
 
 bool isSymbianIntType(const QString &type)
index b4c7a55..005aa59 100644 (file)
@@ -210,36 +210,40 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QStringList alternativeFormats = 
         model()->data(mi0, TypeFormatListRole).toStringList();
-    int typeFormat = 
-        model()->data(mi0, TypeFormatRole).toInt();
-    int individualFormat = 
-        model()->data(mi0, IndividualFormatRole).toInt();
+    const int typeFormat = qMax(int(DecimalFormat), model()->data(mi0, TypeFormatRole).toInt());
+    const int individualFormat = model()->data(mi0, IndividualFormatRole).toInt();
+    const int effectiveIndividualFormat = individualFormat == -1 ? typeFormat : individualFormat;
 
     QMenu typeFormatMenu;
     QMenu individualFormatMenu;
     QList<QAction *> typeFormatActions;
     QList<QAction *> individualFormatActions;
+    QAction *clearIndividualFormatAction = 0;
     if (idx.isValid()) {
         typeFormatMenu.setTitle(tr("Change format for type '%1'").arg(type));
         individualFormatMenu.setTitle(tr("Change format for expression '%1'").arg(exp));
-        for (int i = 0; i != alternativeFormats.size(); ++i) {
-            const QString format = alternativeFormats.at(i);
-            QAction *act = new QAction(format, &typeFormatMenu);
-            act->setCheckable(true);
-            if (i == typeFormat)
-                act->setChecked(true);
-            typeFormatMenu.addAction(act);
-            typeFormatActions.append(act);
-            act = new QAction(format, &individualFormatMenu);
-            act->setCheckable(true);
-            if (i == individualFormat)
-                act->setChecked(true);
-            individualFormatMenu.addAction(act);
-            individualFormatActions.append(act);
-        }
         if (alternativeFormats.isEmpty()) {
             typeFormatMenu.setEnabled(false);
             individualFormatMenu.setEnabled(false);
+        } else {
+            clearIndividualFormatAction = individualFormatMenu.addAction(tr("Clear"));
+            clearIndividualFormatAction->setEnabled(individualFormat != -1);
+            individualFormatMenu.addSeparator();
+            for (int i = 0; i != alternativeFormats.size(); ++i) {
+                const QString format = alternativeFormats.at(i);
+                QAction *act = new QAction(format, &typeFormatMenu);
+                act->setCheckable(true);
+                if (i == typeFormat)
+                    act->setChecked(true);
+                typeFormatMenu.addAction(act);
+                typeFormatActions.append(act);
+                act = new QAction(format, &individualFormatMenu);
+                act->setCheckable(true);
+                if (i == effectiveIndividualFormat)
+                    act->setChecked(true);
+                individualFormatMenu.addAction(act);
+                individualFormatActions.append(act);
+            }
         }
     } else {
         typeFormatMenu.setTitle(tr("Change format for type"));
@@ -316,6 +320,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
         m_grabbing = true;
     } else if (act == actClearCodeModelSnapshot) {
         m_manager->clearCppCodeModelSnapshot();
+    } else if (clearIndividualFormatAction && act == clearIndividualFormatAction) {
+        model()->setData(mi1, -1, IndividualFormatRole);
     } else { 
         for (int i = 0; i != alternativeFormats.size(); ++i) {
             if (act == typeFormatActions.at(i))