initial import
[vym] / qtc-gdbmacros / gdbmacros.cpp
diff --git a/qtc-gdbmacros/gdbmacros.cpp b/qtc-gdbmacros/gdbmacros.cpp
new file mode 100644 (file)
index 0000000..bd681a6
--- /dev/null
@@ -0,0 +1,2567 @@
+/**************************************************************************\r
+**\r
+** This file is part of Qt Creator\r
+**\r
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).\r
+**\r
+** Contact:  Qt Software Information (qt-info@nokia.com)\r
+**\r
+** Commercial Usage\r
+**\r
+** Licensees holding valid Qt Commercial licenses may use this file in\r
+** accordance with the Qt Commercial License Agreement provided with the\r
+** Software or, alternatively, in accordance with the terms contained in\r
+** a written agreement between you and Nokia.\r
+**\r
+** GNU Lesser General Public License Usage\r
+**\r
+** Alternatively, this file may be used under the terms of the GNU Lesser\r
+** General Public License version 2.1 as published by the Free Software\r
+** Foundation and appearing in the file LICENSE.LGPL included in the\r
+** packaging of this file.  Please review the following information to\r
+** ensure the GNU Lesser General Public License version 2.1 requirements\r
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\r
+**\r
+** If you are unsure which license is appropriate for your use, please\r
+** contact the sales department at qt-sales@nokia.com.\r
+**\r
+**************************************************************************/\r
+\r
+#include <qglobal.h>\r
+\r
+// this relies on contents copied from qobject_p.h\r
+#define PRIVATE_OBJECT_ALLOWED 1\r
+\r
+#include <QtCore/QDateTime>\r
+#include <QtCore/QDebug>\r
+#include <QtCore/QDir>\r
+#include <QtCore/QFile>\r
+#include <QtCore/QFileInfo>\r
+#include <QtCore/QHash>\r
+#include <QtCore/QLinkedList>\r
+#include <QtCore/QLocale>\r
+#include <QtCore/QMap>\r
+#include <QtCore/QMetaObject>\r
+#include <QtCore/QMetaProperty>\r
+#include <QtCore/QModelIndex>\r
+#include <QtCore/QObject>\r
+#include <QtCore/QPointer>\r
+#include <QtCore/QString>\r
+#include <QtCore/QTextCodec>\r
+#include <QtCore/QVector>\r
+\r
+int qtGhVersion = QT_VERSION;\r
+\r
+#ifdef QT_GUI_LIB\r
+#   include <QtGui/QPixmap>\r
+#   include <QtGui/QImage>\r
+#endif\r
+\r
+#include <list>\r
+#include <map>\r
+#include <string>\r
+#include <vector>\r
+\r
+#include <ctype.h>\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+\r
+/*!\r
+  \class QDumper\r
+  \brief Helper class for producing "nice" output in Qt Creator's debugger.\r
+\r
+  \internal\r
+\r
+  The whole "custom dumper" implementation is currently far less modular\r
+  than it could be. But as the code is still in a flux, making it nicer\r
+  from a pure archtectural point of view seems still be a waste of resources.\r
+\r
+  Some hints:\r
+\r
+  New dumpers for non-templated classes should be mentioned in\r
+  \c{qDumpObjectData440()} in the  \c{protocolVersion == 1} branch.\r
+\r
+  Templated classes need extra support on the IDE level\r
+  (see plugins/debugger/gdbengine.cpp) and should not be mentiond in\r
+  \c{qDumpObjectData440()}.\r
+\r
+  In any case, dumper processesing should end up in \r
+  \c{handleProtocolVersion2and3()} and needs an entry in the bis switch there.\r
+\r
+  Next step is to create a suitable \c{static void qDumpFoo(QDumper &d)}\r
+  function. At the bare minimum it should contain something like:\r
+\r
+\r
+  \c{\r
+    const Foo &foo = *reinterpret_cast<const Foo *>(d.data);\r
+\r
+    P(d, "value", ...);\r
+    P(d, "type", "Foo");\r
+    P(d, "numchild", "0");\r
+  }\r
+\r
+\r
+  'P(d, name, value)' roughly expands to:\r
+        d << (name) << "=\"" << value << "\"";\r
+\r
+  Useful (i.e. understood by the IDE) names include:\r
+\r
+  \list\r
+    \o "name" shows up in the first column in the Locals&Watchers view.\r
+    \o "value" shows up in the second column.\r
+    \o "valueencoded" should be set to "1" if the value is base64 encoded.\r
+        Always base64-encode values that might use unprintable or otherwise\r
+        "confuse" the protocol (like spaces and quotes). [A-Za-z0-9] is "safe".\r
+        A value of "3" is used for base64-encoded UCS4, "2" denotes \r
+        base64-encoded UTF16.\r
+    \o "numchild" return the number of children in the view. Effectively, only\r
+        0 and != 0 will be used, so don't try too hard to get the number right.\r
+  \endlist\r
+\r
+  If the current item has children, it might be queried to produce information\r
+  about thes children. In this case the dumper should use something like\r
+\r
+  \c{\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+   }\r
+\r
+  */\r
+\r
+#undef NS\r
+#ifdef QT_NAMESPACE\r
+#   define STRINGIFY0(s) #s\r
+#   define STRINGIFY1(s) STRINGIFY0(s)\r
+#   define NS STRINGIFY1(QT_NAMESPACE) "::"\r
+#   define NSX "'" STRINGIFY1(QT_NAMESPACE) "::"\r
+#   define NSY "'"\r
+#else\r
+#   define NS ""\r
+#   define NSX ""\r
+#   define NSY ""\r
+#endif\r
+\r
+\r
+#if PRIVATE_OBJECT_ALLOWED\r
+\r
+#if defined(QT_BEGIN_NAMESPACE)\r
+QT_BEGIN_NAMESPACE\r
+#endif\r
+\r
+class QVariant;\r
+class QThreadData;\r
+class QObjectConnectionListVector;\r
+\r
+class QObjectPrivate : public QObjectData\r
+{\r
+    Q_DECLARE_PUBLIC(QObject)\r
+\r
+public:\r
+    QObjectPrivate() {}\r
+    virtual ~QObjectPrivate() {}\r
+\r
+    // preserve binary compatibility with code compiled without Qt 3 support\r
+    QList<QObject *> pendingChildInsertedEvents; // unused\r
+\r
+    // id of the thread that owns the object\r
+    QThreadData *threadData;\r
+\r
+    struct Sender\r
+    {\r
+        QObject *sender;\r
+        int signal;\r
+        int ref;\r
+    };\r
+\r
+    Sender *currentSender; // object currently activating the object\r
+    QObject *currentChildBeingDeleted;\r
+\r
+    QList<QPointer<QObject> > eventFilters;\r
+\r
+    struct ExtraData;\r
+    ExtraData *extraData;\r
+    mutable quint32 connectedSignals;\r
+\r
+    QString objectName;\r
+\r
+    struct Connection\r
+    {\r
+        QObject *receiver;\r
+        int method;\r
+        uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking\r
+        QBasicAtomicPointer<int> argumentTypes;\r
+    };\r
+    typedef QList<Connection> ConnectionList;\r
+\r
+    QObjectConnectionListVector *connectionLists;\r
+    QList<Sender> senders;\r
+    int *deleteWatch;\r
+};\r
+\r
+#if defined(QT_BEGIN_NAMESPACE)\r
+QT_END_NAMESPACE\r
+#endif\r
+\r
+#endif // PRIVATE_OBJECT_ALLOWED\r
+\r
+\r
+// this can be mangled typenames of nested templates, each char-by-char\r
+// comma-separated integer list\r
+static char qDumpInBuffer[10000];\r
+static char qDumpOutBuffer[100000];\r
+//static char qDumpSize[20];\r
+\r
+namespace {\r
+\r
+static bool isPointerType(const QByteArray &type)\r
+{\r
+    return type.endsWith("*") || type.endsWith("* const");\r
+}\r
+\r
+static QByteArray stripPointerType(QByteArray type)\r
+{\r
+    if (type.endsWith("*"))\r
+        type.chop(1);\r
+    if (type.endsWith("* const"))\r
+        type.chop(7);\r
+    if (type.endsWith(' '))\r
+        type.chop(1);\r
+    return type;\r
+}\r
+\r
+// This is used to abort evaluation of custom data dumpers in a "coordinated"\r
+// way. Abortion will happen anyway when we try to access a non-initialized\r
+// non-trivial object, so there is no way to prevent this from occuring at all\r
+// conceptionally.  Gdb will catch SIGSEGV and return to the calling frame.\r
+// This is just fine provided we only _read_ memory in the custom handlers\r
+// below.\r
+\r
+volatile int qProvokeSegFaultHelper;\r
+\r
+static const void *addOffset(const void *p, int offset)\r
+{\r
+    return offset + reinterpret_cast<const char *>(p);\r
+}\r
+\r
+static const void *skipvtable(const void *p)\r
+{\r
+    return sizeof(void*) + reinterpret_cast<const char *>(p);\r
+}\r
+\r
+static const void *deref(const void *p)\r
+{\r
+    return *reinterpret_cast<const char* const*>(p);\r
+}\r
+\r
+static const void *dfunc(const void *p)\r
+{\r
+    return deref(skipvtable(p));\r
+}\r
+\r
+static bool isEqual(const char *s, const char *t)\r
+{\r
+    return qstrcmp(s, t) == 0;\r
+}\r
+\r
+static bool startsWith(const char *s, const char *t)\r
+{\r
+    return qstrncmp(s, t, strlen(t)) == 0;\r
+}\r
+\r
+// provoke segfault when address is not readable\r
+#define qCheckAccess(d) do { qProvokeSegFaultHelper = *(char*)d; } while (0)\r
+#define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)\r
+// provoke segfault unconditionally\r
+#define qCheck(b) do { if (!(b)) qProvokeSegFaultHelper = *(char*)0; } while (0)\r
+\r
+const char *stripNamespace(const char *type)\r
+{\r
+    static const size_t nslen = strlen(NS);\r
+    return startsWith(type, NS) ? type + nslen : type;\r
+}\r
+\r
+static bool isSimpleType(const char *type)\r
+{\r
+    switch (type[0]) {\r
+        case 'c':\r
+            return isEqual(type, "char");\r
+        case 'd':\r
+            return isEqual(type, "double");\r
+        case 'f':\r
+            return isEqual(type, "float");\r
+        case 'i':\r
+            return isEqual(type, "int");\r
+        case 'l':\r
+            return isEqual(type, "long") || startsWith(type, "long ");\r
+        case 's':\r
+            return isEqual(type, "short") || isEqual(type, "signed")\r
+                || startsWith(type, "signed ");\r
+        case 'u':\r
+            return isEqual(type, "unsigned") || startsWith(type, "unsigned ");\r
+    }\r
+    return false;\r
+}\r
+\r
+#if 0\r
+static bool isStringType(const char *type)\r
+{\r
+    return isEqual(type, NS"QString")\r
+        || isEqual(type, NS"QByteArray")\r
+        || isEqual(type, "std::string")\r
+        || isEqual(type, "std::wstring")\r
+        || isEqual(type, "wstring");\r
+}\r
+#endif\r
+\r
+static bool isMovableType(const char *type)\r
+{\r
+    if (isPointerType(type))\r
+        return true;\r
+\r
+    if (isSimpleType(type))\r
+        return true;\r
+\r
+    type = stripNamespace(type);\r
+\r
+    switch (type[1]) {  \r
+        case 'B':\r
+            return isEqual(type, "QBrush")\r
+                || isEqual(type, "QBitArray")\r
+                || isEqual(type, "QByteArray") ;\r
+        case 'C':\r
+            return isEqual(type, "QCustomTypeInfo");\r
+        case 'D':\r
+            return isEqual(type, "QDate")\r
+                || isEqual(type, "QDateTime");\r
+        case 'F':\r
+            return isEqual(type, "QFileInfo")\r
+                || isEqual(type, "QFixed")\r
+                || isEqual(type, "QFixedPoint")\r
+                || isEqual(type, "QFixedSize");\r
+        case 'H':\r
+            return isEqual(type, "QHashDummyValue");\r
+        case 'I':\r
+            return isEqual(type, "QIcon")\r
+                || isEqual(type, "QImage");\r
+        case 'L':\r
+            return isEqual(type, "QLine")\r
+                || isEqual(type, "QLineF")\r
+                || isEqual(type, "QLocal");\r
+        case 'M':\r
+            return isEqual(type, "QMatrix")\r
+                || isEqual(type, "QModelIndex");\r
+        case 'P':\r
+            return isEqual(type, "QPoint")\r
+                || isEqual(type, "QPointF")\r
+                || isEqual(type, "QPen")\r
+                || isEqual(type, "QPersistentModelIndex");\r
+        case 'R':\r
+            return isEqual(type, "QResourceRoot")\r
+                || isEqual(type, "QRect")\r
+                || isEqual(type, "QRectF")\r
+                || isEqual(type, "QRegExp");\r
+        case 'S':\r
+            return isEqual(type, "QSize")\r
+                || isEqual(type, "QSizeF")\r
+                || isEqual(type, "QString");\r
+        case 'T':\r
+            return isEqual(type, "QTime")\r
+                || isEqual(type, "QTextBlock");\r
+        case 'U':\r
+            return isEqual(type, "QUrl");\r
+        case 'V':\r
+            return isEqual(type, "QVariant");\r
+        case 'X':\r
+            return isEqual(type, "QXmlStreamAttribute")\r
+                || isEqual(type, "QXmlStreamNamespaceDeclaration")\r
+                || isEqual(type, "QXmlStreamNotationDeclaration")\r
+                || isEqual(type, "QXmlStreamEntityDeclaration");\r
+    }\r
+    return false;\r
+}\r
+\r
+struct QDumper\r
+{\r
+    explicit QDumper();\r
+    ~QDumper();\r
+    void checkFill();\r
+    QDumper &operator<<(long c);\r
+    QDumper &operator<<(int i);\r
+    QDumper &operator<<(double d);\r
+    QDumper &operator<<(float d);\r
+    QDumper &operator<<(unsigned long c);\r
+    QDumper &operator<<(unsigned int i);\r
+    QDumper &operator<<(const void *p);\r
+    QDumper &operator<<(qulonglong c);\r
+    QDumper &operator<<(const char *str);\r
+    QDumper &operator<<(const QByteArray &ba);\r
+    QDumper &operator<<(const QString &str);\r
+    void put(char c);\r
+    void addCommaIfNeeded();\r
+    void putBase64Encoded(const char *buf, int n);\r
+    void putEllipsis();\r
+    void disarm();\r
+\r
+    void beginHash(); // start of data hash output\r
+    void endHash(); // start of data hash output\r
+\r
+    // the dumper arguments\r
+    int protocolVersion;   // dumper protocol version\r
+    int token;             // some token to show on success\r
+    const char *outertype; // object type\r
+    const char *iname;     // object name used for display\r
+    const char *exp;       // object expression\r
+    const char *innertype; // 'inner type' for class templates\r
+    const void *data;      // pointer to raw data\r
+    bool dumpChildren;     // do we want to see children?\r
+\r
+    // handling of nested templates\r
+    void setupTemplateParameters();\r
+    enum { maxTemplateParameters = 10 };\r
+    const char *templateParameters[maxTemplateParameters + 1];\r
+    int templateParametersCount;\r
+\r
+    // internal state\r
+    bool success;          // are we finished?\r
+    bool full;\r
+    int pos;\r
+\r
+    int extraInt[4];\r
+};\r
+\r
+\r
+QDumper::QDumper()\r
+{\r
+    success = false;\r
+    full = false;\r
+    qDumpOutBuffer[0] = 'f'; // marks output as 'wrong' \r
+    pos = 1;\r
+}\r
+\r
+QDumper::~QDumper()\r
+{\r
+    qDumpOutBuffer[pos++] = '\0';\r
+    if (success)\r
+        qDumpOutBuffer[0] = (full ? '+' : 't');\r
+}\r
+\r
+void QDumper::setupTemplateParameters()\r
+{\r
+    char *s = const_cast<char *>(innertype);\r
+\r
+    templateParametersCount = 1;\r
+    templateParameters[0] = s;\r
+    for (int i = 1; i != maxTemplateParameters + 1; ++i)\r
+        templateParameters[i] = 0;\r
+\r
+    while (*s) {\r
+        while (*s && *s != '@')\r
+            ++s;\r
+        if (*s) {\r
+            *s = '\0';\r
+            ++s;\r
+            templateParameters[templateParametersCount++] = s;\r
+        }\r
+    }\r
+}\r
+\r
+QDumper &QDumper::operator<<(unsigned long long c)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%llu", c);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(unsigned long c)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%lu", c);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(float d)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%f", d);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(double d)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%f", d);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(unsigned int i)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%u", i);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(long c)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%ld", c);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(int i)\r
+{\r
+    checkFill();\r
+    pos += sprintf(qDumpOutBuffer + pos, "%d", i);\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(const void *p)\r
+{\r
+    static char buf[100];\r
+    if (p) {\r
+        sprintf(buf, "%p", p);\r
+        // we get a '0x' prefix only on some implementations.\r
+        // if it isn't there, write it out manually.\r
+        if (buf[1] != 'x') {\r
+            put('0');\r
+            put('x');\r
+        }\r
+        *this << buf;\r
+    } else {\r
+        *this << "<null>";\r
+    }\r
+    return *this;\r
+}\r
+\r
+void QDumper::checkFill()\r
+{\r
+    if (pos >= int(sizeof(qDumpOutBuffer)) - 100)\r
+        full = true;\r
+}\r
+\r
+void QDumper::put(char c)\r
+{\r
+    checkFill();\r
+    if (!full)\r
+        qDumpOutBuffer[pos++] = c;\r
+}\r
+\r
+void QDumper::addCommaIfNeeded()\r
+{\r
+    if (pos == 0)\r
+        return;\r
+    char c = qDumpOutBuffer[pos - 1];\r
+    if (c == '}' || c == '"' || c == ']')\r
+        put(',');\r
+}\r
+\r
+void QDumper::putBase64Encoded(const char *buf, int n)\r
+{\r
+    const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"\r
+                            "ghijklmn" "opqrstuv" "wxyz0123" "456789+/";\r
+    const char padchar = '=';\r
+    int padlen = 0;\r
+\r
+    //int tmpsize = ((n * 4) / 3) + 3;\r
+\r
+    int i = 0;\r
+    while (i < n) {\r
+        int chunk = 0;\r
+        chunk |= int(uchar(buf[i++])) << 16;\r
+        if (i == n) {\r
+            padlen = 2;\r
+        } else {\r
+            chunk |= int(uchar(buf[i++])) << 8;\r
+            if (i == n)\r
+                padlen = 1;\r
+            else\r
+                chunk |= int(uchar(buf[i++]));\r
+        }\r
+\r
+        int j = (chunk & 0x00fc0000) >> 18;\r
+        int k = (chunk & 0x0003f000) >> 12;\r
+        int l = (chunk & 0x00000fc0) >> 6;\r
+        int m = (chunk & 0x0000003f);\r
+        put(alphabet[j]);\r
+        put(alphabet[k]);\r
+        put(padlen > 1 ? padchar : alphabet[l]);\r
+        put(padlen > 0 ? padchar : alphabet[m]);\r
+    }\r
+}\r
+\r
+QDumper &QDumper::operator<<(const char *str)\r
+{\r
+    if (!str)\r
+        return *this << "<null>";\r
+    while (*str)\r
+        put(*(str++));\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(const QByteArray &ba)\r
+{\r
+    putBase64Encoded(ba.constData(), ba.size());\r
+    return *this;\r
+}\r
+\r
+QDumper &QDumper::operator<<(const QString &str)\r
+{\r
+    QByteArray ba = str.toUtf8();\r
+    putBase64Encoded(ba.constData(), ba.size());\r
+    return *this;\r
+}\r
+\r
+void QDumper::disarm()\r
+{\r
+    success = true;\r
+}\r
+\r
+void QDumper::beginHash()\r
+{\r
+    addCommaIfNeeded();\r
+    put('{');\r
+}\r
+\r
+void QDumper::endHash()\r
+{\r
+    put('}');\r
+}\r
+\r
+void QDumper::putEllipsis()\r
+{\r
+    addCommaIfNeeded();\r
+    *this << "{name=\"<incomplete>\",value=\"\",type=\"" << innertype << "\"}";\r
+}\r
+\r
+//\r
+// Some helpers to keep the dumper code short\r
+//\r
+\r
+// dump property=value pair\r
+#undef P\r
+#define P(dumper,name,value) \\r
+    do { \\r
+        dumper.addCommaIfNeeded(); \\r
+        dumper << (name) << "=\"" << value << "\""; \\r
+    } while (0)\r
+\r
+// simple string property\r
+#undef S\r
+#define S(dumper, name, value) \\r
+    dumper.beginHash(); \\r
+    P(dumper, "name", name); \\r
+    P(dumper, "value", value); \\r
+    P(dumper, "type", NS"QString"); \\r
+    P(dumper, "numchild", "0"); \\r
+    P(dumper, "valueencoded", "1"); \\r
+    dumper.endHash();\r
+\r
+// simple integer property\r
+#undef I\r
+#define I(dumper, name, value) \\r
+    dumper.beginHash(); \\r
+    P(dumper, "name", name); \\r
+    P(dumper, "value", value); \\r
+    P(dumper, "type", "int"); \\r
+    P(dumper, "numchild", "0"); \\r
+    dumper.endHash();\r
+\r
+// simple boolean property\r
+#undef BL\r
+#define BL(dumper, name, value) \\r
+    dumper.beginHash(); \\r
+    P(dumper, "name", name); \\r
+    P(dumper, "value", (value ? "true" : "false")); \\r
+    P(dumper, "type", "bool"); \\r
+    P(dumper, "numchild", "0"); \\r
+    dumper.endHash();\r
+\r
+\r
+// a single QChar\r
+#undef QC\r
+#define QC(dumper, name, value) \\r
+    dumper.beginHash(); \\r
+    P(dumper, "name", name); \\r
+    P(dumper, "value", QString(QLatin1String("'%1' (%2, 0x%3)")) \\r
+        .arg(value).arg(value.unicode()).arg(value.unicode(), 0, 16)); \\r
+    P(dumper, "valueencoded", "1"); \\r
+    P(dumper, "type", NS"QChar"); \\r
+    P(dumper, "numchild", "0"); \\r
+    dumper.endHash();\r
+\r
+#undef TT\r
+#define TT(type, value) \\r
+    "<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"\r
+\r
+static void qDumpUnknown(QDumper &d)\r
+{\r
+    P(d, "iname", d.iname);\r
+    P(d, "addr", d.data);\r
+    P(d, "value", "<internal error>");\r
+    P(d, "type", d.outertype);\r
+    P(d, "numchild", "0");\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,\r
+    const char *field = "value")\r
+{\r
+    type = stripNamespace(type);\r
+    switch (type[1]) {\r
+        case 'l':\r
+            if (isEqual(type, "float"))\r
+                P(d, field, *(float*)addr);\r
+            return;\r
+        case 'n':\r
+            if (isEqual(type, "int"))\r
+                P(d, field, *(int*)addr);\r
+            else if (isEqual(type, "unsigned"))\r
+                P(d, field, *(unsigned int*)addr);\r
+            else if (isEqual(type, "unsigned int"))\r
+                P(d, field, *(unsigned int*)addr);\r
+            else if (isEqual(type, "unsigned long"))\r
+                P(d, field, *(unsigned long*)addr);\r
+            else if (isEqual(type, "unsigned long long"))\r
+                P(d, field, *(qulonglong*)addr);\r
+            return;\r
+        case 'o':\r
+            if (isEqual(type, "bool"))\r
+                switch (*(bool*)addr) {\r
+                    case 0: P(d, field, "false"); break;\r
+                    case 1: P(d, field, "true"); break;\r
+                    default: P(d, field, *(bool*)addr); break;\r
+                }\r
+            else if (isEqual(type, "double"))\r
+                P(d, field, *(double*)addr);\r
+            else if (isEqual(type, "long"))\r
+                P(d, field, *(long*)addr);\r
+            else if (isEqual(type, "long long"))\r
+                P(d, field, *(qulonglong*)addr);\r
+            return;\r
+        case 'B':\r
+            if (isEqual(type, "QByteArray")) {\r
+                d.addCommaIfNeeded();\r
+                d << field << "encoded=\"1\",";\r
+                P(d, field, *(QByteArray*)addr);\r
+            }\r
+            return;\r
+        case 'L':\r
+            if (startsWith(type, "QList<")) {\r
+                const QListData *ldata = reinterpret_cast<const QListData*>(addr);\r
+                P(d, "value", "<" << ldata->size() << " items>");\r
+                P(d, "valuedisabled", "true");\r
+                P(d, "numchild", ldata->size());\r
+            }\r
+            return;\r
+        case 'O':\r
+            if (isEqual(type, "QObject *")) {\r
+                if (addr) {\r
+                    const QObject *ob = reinterpret_cast<const QObject *>(addr);\r
+                    P(d, "addr", ob);\r
+                    P(d, "value", ob->objectName());\r
+                    P(d, "valueencoded", "1");\r
+                    P(d, "type", NS"QObject");\r
+                    P(d, "displayedtype", ob->metaObject()->className());\r
+                } else {\r
+                    P(d, "value", "0x0");\r
+                    P(d, "type", NS"QObject *");\r
+                }\r
+            }\r
+            return;\r
+        case 'S':\r
+            if (isEqual(type, "QString")) {\r
+                d.addCommaIfNeeded();\r
+                d << field << "encoded=\"1\",";\r
+                P(d, field, *(QString*)addr);\r
+            }\r
+            return;\r
+        default:\r
+            return;\r
+    }\r
+}\r
+\r
+static void qDumpInnerValue(QDumper &d, const char *type, const void *addr)\r
+{\r
+    P(d, "addr", addr);\r
+    P(d, "type", type);\r
+\r
+    if (!type[0])\r
+        return;\r
+\r
+    qDumpInnerValueHelper(d, type, addr);\r
+}\r
+\r
+\r
+static void qDumpInnerValueOrPointer(QDumper &d,\r
+    const char *type, const char *strippedtype, const void *addr)\r
+{\r
+    if (strippedtype) {\r
+        if (deref(addr)) {\r
+            P(d, "addr", deref(addr));\r
+            P(d, "type", strippedtype);\r
+            qDumpInnerValueHelper(d, strippedtype, deref(addr));\r
+        } else {\r
+            P(d, "addr", addr);\r
+            P(d, "type", strippedtype);\r
+            P(d, "value", "<null>");\r
+            P(d, "numchild", "0");\r
+        }\r
+    } else {\r
+        P(d, "addr", addr);\r
+        P(d, "type", type);\r
+        qDumpInnerValueHelper(d, type, addr);\r
+    }\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////////////\r
+\r
+static void qDumpQByteArray(QDumper &d)\r
+{\r
+    const QByteArray &ba = *reinterpret_cast<const QByteArray *>(d.data);\r
+\r
+    if (!ba.isEmpty()) {\r
+        qCheckAccess(ba.constData());\r
+        qCheckAccess(ba.constData() + ba.size());\r
+    }\r
+\r
+    if (ba.size() <= 100)\r
+        P(d, "value", ba);\r
+    else\r
+        P(d, "value", ba.left(100) << " <size: " << ba.size() << ", cut...>");\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QByteArray");\r
+    P(d, "numchild", ba.size());\r
+    P(d, "childtype", "char");\r
+    P(d, "childnumchild", "0");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        char buf[20];\r
+        for (int i = 0; i != ba.size(); ++i) {\r
+            unsigned char c = ba.at(i);\r
+            unsigned char u = (isprint(c) && c != '\'' && c != '"') ? c : '?';\r
+            sprintf(buf, "%02x  (%u '%c')", c, c, u);\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            P(d, "value", buf);\r
+            d.endHash();\r
+        }\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQDateTime(QDumper &d)\r
+{\r
+#ifdef QT_NO_DATESTRING\r
+    qDumpUnknown(d);\r
+#else\r
+    const QDateTime &date = *reinterpret_cast<const QDateTime *>(d.data);\r
+    if (date.isNull()) {\r
+        P(d, "value", "(null)");\r
+    } else {\r
+        P(d, "value", date.toString());\r
+        P(d, "valueencoded", "1");\r
+    }\r
+    P(d, "type", NS"QDateTime");\r
+    P(d, "numchild", "3");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        BL(d, "isNull", date.isNull());\r
+        I(d, "toTime_t", (long)date.toTime_t());\r
+        S(d, "toString", date.toString());\r
+        S(d, "toString_(ISO)", date.toString(Qt::ISODate));\r
+        S(d, "toString_(SystemLocale)", date.toString(Qt::SystemLocaleDate));\r
+        S(d, "toString_(Locale)", date.toString(Qt::LocaleDate));\r
+        S(d, "toString", date.toString());\r
+\r
+        #if 0\r
+        d.beginHash();\r
+        P(d, "name", "toUTC");\r
+        P(d, "exp", "(("NSX"QDateTime"NSY"*)" << d.data << ")"\r
+                    "->toTimeSpec('"NS"Qt::UTC')");\r
+        P(d, "type", NS"QDateTime");\r
+        P(d, "numchild", "1");\r
+        d.endHash();\r
+        #endif\r
+\r
+        #if 0\r
+        d.beginHash();\r
+        P(d, "name", "toLocalTime");\r
+        P(d, "exp", "(("NSX"QDateTime"NSY"*)" << d.data << ")"\r
+                    "->toTimeSpec('"NS"Qt::LocalTime')");\r
+        P(d, "type", NS"QDateTime");\r
+        P(d, "numchild", "1");\r
+        d.endHash();\r
+        #endif\r
+\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+#endif // ifdef QT_NO_DATESTRING\r
+}\r
+\r
+static void qDumpQDir(QDumper &d)\r
+{\r
+    const QDir &dir = *reinterpret_cast<const QDir *>(d.data);\r
+    P(d, "value", dir.path());\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QDir");\r
+    P(d, "numchild", "3");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        S(d, "absolutePath", dir.absolutePath());\r
+        S(d, "canonicalPath", dir.canonicalPath());\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQFile(QDumper &d)\r
+{\r
+    const QFile &file = *reinterpret_cast<const QFile *>(d.data);\r
+    P(d, "value", file.fileName());\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QFile");\r
+    P(d, "numchild", "2");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        S(d, "fileName", file.fileName());\r
+        BL(d, "exists", file.exists());\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQFileInfo(QDumper &d)\r
+{\r
+    const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data);\r
+    P(d, "value", info.filePath());\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QFileInfo");\r
+    P(d, "numchild", "3");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        S(d, "absolutePath", info.absolutePath());\r
+        S(d, "absoluteFilePath", info.absoluteFilePath());\r
+        S(d, "canonicalPath", info.canonicalPath());\r
+        S(d, "canonicalFilePath", info.canonicalFilePath());\r
+        S(d, "completeBaseName", info.completeBaseName());\r
+        S(d, "completeSuffix", info.completeSuffix());\r
+        S(d, "baseName", info.baseName());\r
+#ifdef Q_OS_MACX\r
+        BL(d, "isBundle", info.isBundle());\r
+        S(d, "bundleName", info.bundleName());\r
+#endif\r
+        S(d, "completeSuffix", info.completeSuffix());\r
+        S(d, "fileName", info.fileName());\r
+        S(d, "filePath", info.filePath());\r
+        S(d, "group", info.group());\r
+        S(d, "owner", info.owner());\r
+        S(d, "path", info.path());\r
+\r
+        I(d, "groupid", (long)info.groupId());\r
+        I(d, "ownerid", (long)info.ownerId());\r
+        //QFile::Permissions permissions () const\r
+        I(d, "permissions", info.permissions());\r
+\r
+        //QDir absoluteDir () const\r
+        //QDir dir () const\r
+\r
+        BL(d, "caching", info.caching());\r
+        BL(d, "exists", info.exists());\r
+        BL(d, "isAbsolute", info.isAbsolute());\r
+        BL(d, "isDir", info.isDir());\r
+        BL(d, "isExecutable", info.isExecutable());\r
+        BL(d, "isFile", info.isFile());\r
+        BL(d, "isHidden", info.isHidden());\r
+        BL(d, "isReadable", info.isReadable());\r
+        BL(d, "isRelative", info.isRelative());\r
+        BL(d, "isRoot", info.isRoot());\r
+        BL(d, "isSymLink", info.isSymLink());\r
+        BL(d, "isWritable", info.isWritable());\r
+\r
+        d.beginHash();\r
+        P(d, "name", "created");\r
+        P(d, "value", info.created().toString());\r
+        P(d, "valueencoded", "1");\r
+        P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->created()");\r
+        P(d, "type", NS"QDateTime");\r
+        P(d, "numchild", "1");\r
+        d.endHash();\r
+\r
+        d.beginHash();\r
+        P(d, "name", "lastModified");\r
+        P(d, "value", info.lastModified().toString());\r
+        P(d, "valueencoded", "1");\r
+        P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->lastModified()");\r
+        P(d, "type", NS"QDateTime");\r
+        P(d, "numchild", "1");\r
+        d.endHash();\r
+\r
+        d.beginHash();\r
+        P(d, "name", "lastRead");\r
+        P(d, "value", info.lastRead().toString());\r
+        P(d, "valueencoded", "1");\r
+        P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->lastRead()");\r
+        P(d, "type", NS"QDateTime");\r
+        P(d, "numchild", "1");\r
+        d.endHash();\r
+\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+bool isOptimizedIntKey(const char *keyType)\r
+{\r
+    return isEqual(keyType, "int")\r
+#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN\r
+        || isEqual(keyType, "short")\r
+        || isEqual(keyType, "ushort")\r
+#endif\r
+        || isEqual(keyType, "uint");\r
+}\r
+\r
+int hashOffset(bool optimizedIntKey, bool forKey, unsigned keySize, unsigned valueSize)\r
+{\r
+    // int-key optimization, small value\r
+    struct NodeOS { void *next; uint k; uint  v; } nodeOS;\r
+    // int-key optimiatzion, large value\r
+    struct NodeOL { void *next; uint k; void *v; } nodeOL;\r
+    // no optimization, small value\r
+    struct NodeNS { void *next; uint h; uint  k; uint  v; } nodeNS;\r
+    // no optimization, large value\r
+    struct NodeNL { void *next; uint h; uint  k; void *v; } nodeNL;\r
+    // complex key\r
+    struct NodeL  { void *next; uint h; void *k; void *v; } nodeL;\r
+\r
+    if (forKey) {\r
+        // offsetof(...,...) not yet in Standard C++\r
+        const ulong nodeOSk ( (char *)&nodeOS.k - (char *)&nodeOS );\r
+        const ulong nodeOLk ( (char *)&nodeOL.k - (char *)&nodeOL );\r
+        const ulong nodeNSk ( (char *)&nodeNS.k - (char *)&nodeNS );\r
+        const ulong nodeNLk ( (char *)&nodeNL.k - (char *)&nodeNL );\r
+        const ulong nodeLk  ( (char *)&nodeL.k  - (char *)&nodeL );\r
+        if (optimizedIntKey)\r
+            return valueSize > sizeof(int) ? nodeOLk : nodeOSk;\r
+        if (keySize > sizeof(int))\r
+            return nodeLk;\r
+        return valueSize > sizeof(int) ? nodeNLk : nodeNSk;\r
+    } else {\r
+        const ulong nodeOSv ( (char *)&nodeOS.v - (char *)&nodeOS );\r
+        const ulong nodeOLv ( (char *)&nodeOL.v - (char *)&nodeOL );\r
+        const ulong nodeNSv ( (char *)&nodeNS.v - (char *)&nodeNS );\r
+        const ulong nodeNLv ( (char *)&nodeNL.v - (char *)&nodeNL );\r
+        const ulong nodeLv  ( (char *)&nodeL.v  - (char *)&nodeL );\r
+        if (optimizedIntKey)\r
+            return valueSize > sizeof(int) ? nodeOLv : nodeOSv;\r
+        if (keySize > sizeof(int))\r
+            return nodeLv;\r
+        return valueSize > sizeof(int) ? nodeNLv : nodeNSv;\r
+    }\r
+}\r
+\r
+\r
+static void qDumpQHash(QDumper &d)\r
+{\r
+    QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);\r
+    const char *keyType   = d.templateParameters[0];\r
+    const char *valueType = d.templateParameters[1];\r
+\r
+    qCheckPointer(h->fakeNext);\r
+    qCheckPointer(h->buckets);\r
+\r
+    unsigned keySize = d.extraInt[0];\r
+    unsigned valueSize = d.extraInt[1];\r
+\r
+    int n = h->size;\r
+\r
+    if (n < 0)\r
+        qCheck(false);\r
+    if (n > 0) {\r
+        qCheckPointer(h->fakeNext);\r
+        qCheckPointer(*h->buckets);\r
+    }\r
+\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "numchild", n);\r
+    if (d.dumpChildren) {\r
+        if (n > 1000)\r
+            n = 1000;\r
+        bool isSimpleKey = isSimpleType(keyType);\r
+        bool isSimpleValue = isSimpleType(valueType);\r
+        bool opt = isOptimizedIntKey(keyType);\r
+        int keyOffset = hashOffset(opt, true, keySize, valueSize);\r
+        int valueOffset = hashOffset(opt, false, keySize, valueSize);\r
+\r
+        P(d, "extra", "isSimpleKey: " << isSimpleKey\r
+            << " isSimpleValue: " << isSimpleValue\r
+            << " valueType: '" << isSimpleValue\r
+            << " keySize: " << keyOffset << " valueOffset: " << valueOffset\r
+            << " opt: " << opt);\r
+\r
+        QHashData::Node *node = h->firstNode();\r
+        QHashData::Node *end = reinterpret_cast<QHashData::Node *>(h);\r
+        int i = 0;\r
+\r
+        d << ",children=[";\r
+        while (node != end) {\r
+            d.beginHash();\r
+                P(d, "name", i);\r
+                qDumpInnerValueHelper(d, keyType, addOffset(node, keyOffset), "key");\r
+                qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));\r
+                if (isSimpleKey && isSimpleValue) {\r
+                    P(d, "type", valueType);\r
+                    P(d, "addr", addOffset(node, valueOffset));\r
+                } else {\r
+                    P(d, "exp", "*('"NS"QHashNode<" << keyType << ","\r
+                        << valueType << " >'*)" << node);\r
+                    P(d, "type", "'"NS"QHashNode<" << keyType << ","\r
+                        << valueType << " >'");\r
+                }\r
+            d.endHash();\r
+            ++i;\r
+            node = QHashData::nextNode(node);\r
+        }\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQHashNode(QDumper &d)\r
+{\r
+    const QHashData *h = reinterpret_cast<const QHashData *>(d.data);\r
+    const char *keyType   = d.templateParameters[0];\r
+    const char *valueType = d.templateParameters[1];\r
+\r
+    unsigned keySize = d.extraInt[0];\r
+    unsigned valueSize = d.extraInt[1];\r
+    bool opt = isOptimizedIntKey(keyType);\r
+    int keyOffset = hashOffset(opt, true, keySize, valueSize);\r
+    int valueOffset = hashOffset(opt, false, keySize, valueSize);\r
+    if (isSimpleType(valueType)) \r
+        qDumpInnerValueHelper(d, valueType, addOffset(h, valueOffset));\r
+    else\r
+        P(d, "value", "");\r
+\r
+    P(d, "numchild", 2);\r
+    if (d.dumpChildren) {\r
+        // there is a hash specialization in cast the key are integers or shorts\r
+        d << ",children=[";\r
+        d.beginHash();\r
+            P(d, "name", "key");\r
+            P(d, "type", keyType);\r
+            P(d, "addr", addOffset(h, keyOffset));\r
+        d.endHash();\r
+        d.beginHash();\r
+            P(d, "name", "value");\r
+            P(d, "type", valueType);\r
+            P(d, "addr", addOffset(h, valueOffset));\r
+        d.endHash();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQImage(QDumper &d)\r
+{\r
+#ifdef QT_GUI_LIB\r
+    const QImage &im = *reinterpret_cast<const QImage *>(d.data);\r
+    P(d, "value", "(" << im.width() << "x" << im.height() << ")");\r
+    P(d, "type", NS"QImage");\r
+    P(d, "numchild", "0");\r
+    d.disarm();\r
+#else\r
+    Q_UNUSED(d);\r
+#endif\r
+}\r
+\r
+static void qDumpQList(QDumper &d)\r
+{\r
+    // This uses the knowledge that QList<T> has only a single member\r
+    // of type  union { QListData p; QListData::Data *d; };\r
+    const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);\r
+    const QListData::Data *pdata =\r
+        *reinterpret_cast<const QListData::Data* const*>(d.data);\r
+    int nn = ldata.size();\r
+    if (nn < 0)\r
+        qCheck(false);\r
+    if (nn > 0) {\r
+        qCheckAccess(ldata.d->array);\r
+        //qCheckAccess(ldata.d->array[0]);\r
+        //qCheckAccess(ldata.d->array[nn - 1]);\r
+#if QT_VERSION >= 0x040400\r
+        if (ldata.d->ref._q_value <= 0)\r
+            qCheck(false);\r
+#endif\r
+    }\r
+\r
+    int n = nn;\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "numchild", n);\r
+    P(d, "childtype", d.innertype);\r
+    if (d.dumpChildren) {\r
+        unsigned innerSize = d.extraInt[0];\r
+        bool innerTypeIsPointer = isPointerType(d.innertype);\r
+        QByteArray strippedInnerType = stripPointerType(d.innertype);\r
+\r
+        // The exact condition here is:\r
+        //  QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic\r
+        // but this data is available neither in the compiled binary nor\r
+        // in the frontend.\r
+        // So as first approximation only do the 'isLarge' check:\r
+        bool isInternal = innerSize <= int(sizeof(void*))\r
+            && isMovableType(d.innertype);\r
+\r
+        P(d, "internal", (int)isInternal);\r
+        P(d, "childtype", d.innertype);\r
+        if (n > 1000)\r
+            n = 1000;\r
+        d << ",children=[";\r
+        for (int i = 0; i != n; ++i) {\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            if (innerTypeIsPointer) {\r
+                void *p = ldata.d->array + i + pdata->begin;\r
+                if (p) {\r
+                    //P(d, "value","@" << p);\r
+                    qDumpInnerValue(d, strippedInnerType.data(), deref(p));\r
+                } else {\r
+                    P(d, "value", "<null>");\r
+                    P(d, "numchild", "0");\r
+                }\r
+            } else {\r
+                void *p = ldata.d->array + i + pdata->begin;\r
+                if (isInternal) {\r
+                    //qDumpInnerValue(d, d.innertype, p);\r
+                    P(d, "addr", p);\r
+                    qDumpInnerValueHelper(d, d.innertype, p);\r
+                } else {\r
+                    //qDumpInnerValue(d, d.innertype, deref(p));\r
+                    P(d, "addr", deref(p));\r
+                    qDumpInnerValueHelper(d, d.innertype, deref(p));\r
+                }\r
+            }\r
+            d.endHash();\r
+        }\r
+        if (n < nn)\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQLinkedList(QDumper &d)\r
+{\r
+    // This uses the knowledge that QLinkedList<T> has only a single member\r
+    // of type  union { QLinkedListData *d; QLinkedListNode<T> *e; };\r
+    const QLinkedListData *ldata =\r
+        reinterpret_cast<const QLinkedListData*>(deref(d.data));\r
+    int nn = ldata->size;\r
+    if (nn < 0)\r
+        qCheck(false);\r
+\r
+    int n = nn;\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "numchild", n);\r
+    P(d, "childtype", d.innertype);\r
+    if (d.dumpChildren) {\r
+        //unsigned innerSize = d.extraInt[0];\r
+        //bool innerTypeIsPointer = isPointerType(d.innertype);\r
+        QByteArray strippedInnerType = stripPointerType(d.innertype);\r
+        const char *stripped =\r
+            isPointerType(d.innertype) ? strippedInnerType.data() : 0;\r
+\r
+        P(d, "childtype", d.innertype);\r
+        if (n > 1000)\r
+            n = 1000;\r
+        d << ",children=[";\r
+        const void *p = deref(ldata);\r
+        for (int i = 0; i != n; ++i) {\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            const void *addr = addOffset(p, 2 * sizeof(void*));\r
+            qDumpInnerValueOrPointer(d, d.innertype, stripped, addr);\r
+            p = deref(p);\r
+            d.endHash();\r
+        }\r
+        if (n < nn)\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQLocale(QDumper &d)\r
+{\r
+    const QLocale &locale = *reinterpret_cast<const QLocale *>(d.data);\r
+    P(d, "value", locale.name());\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QLocale");\r
+    P(d, "numchild", "8");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+\r
+        d.beginHash();\r
+        P(d, "name", "country");\r
+        P(d, "exp",  "(("NSX"QLocale"NSY"*)" << d.data << ")->country()");\r
+        d.endHash();\r
+\r
+        d.beginHash();\r
+        P(d, "name", "language");\r
+        P(d, "exp",  "(("NSX"QLocale"NSY"*)" << d.data << ")->language()");\r
+        d.endHash();\r
+\r
+        d.beginHash();\r
+        P(d, "name", "measurementSystem");\r
+        P(d, "exp",  "(("NSX"QLocale"NSY"*)" << d.data << ")->measurementSystem()");\r
+        d.endHash();\r
+\r
+        d.beginHash();\r
+        P(d, "name", "numberOptions");\r
+        P(d, "exp",  "(("NSX"QLocale"NSY"*)" << d.data << ")->numberOptions()");\r
+        d.endHash();\r
+\r
+        S(d, "timeFormat_(short)", locale.timeFormat(QLocale::ShortFormat));\r
+        S(d, "timeFormat_(long)", locale.timeFormat(QLocale::LongFormat));\r
+\r
+        QC(d, "decimalPoint", locale.decimalPoint());\r
+        QC(d, "exponential", locale.exponential());\r
+        QC(d, "percent", locale.percent());\r
+        QC(d, "zeroDigit", locale.zeroDigit());\r
+        QC(d, "groupSeparator", locale.groupSeparator());\r
+        QC(d, "negativeSign", locale.negativeSign());\r
+\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQMapNode(QDumper &d)\r
+{\r
+    const QMapData *h = reinterpret_cast<const QMapData *>(d.data);\r
+    const char *keyType   = d.templateParameters[0];\r
+    const char *valueType = d.templateParameters[1];\r
+\r
+    qCheckAccess(h->backward);\r
+    qCheckAccess(h->forward[0]);\r
+\r
+    P(d, "value", "");\r
+    P(d, "numchild", 2);\r
+    if (d.dumpChildren) {\r
+        //unsigned keySize = d.extraInt[0];\r
+        //unsigned valueSize = d.extraInt[1];\r
+        unsigned mapnodesize = d.extraInt[2];\r
+        unsigned valueOff = d.extraInt[3];\r
+\r
+        unsigned keyOffset = 2 * sizeof(void*) - mapnodesize;\r
+        unsigned valueOffset = 2 * sizeof(void*) - mapnodesize + valueOff;\r
+\r
+        d << ",children=[";\r
+        d.beginHash();\r
+        P(d, "name", "key");\r
+        qDumpInnerValue(d, keyType, addOffset(h, keyOffset));\r
+\r
+        d.endHash();\r
+        d.beginHash();\r
+        P(d, "name", "value");\r
+        qDumpInnerValue(d, valueType, addOffset(h, valueOffset));\r
+        d.endHash();\r
+        d << "]";\r
+    }\r
+\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQMap(QDumper &d)\r
+{\r
+    QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);\r
+    const char *keyType   = d.templateParameters[0];\r
+    const char *valueType = d.templateParameters[1];\r
+\r
+    int n = h->size;\r
+\r
+    if (n < 0)\r
+        qCheck(false);\r
+    if (n > 0) {\r
+        qCheckAccess(h->backward);\r
+        qCheckAccess(h->forward[0]);\r
+        qCheckPointer(h->backward->backward);\r
+        qCheckPointer(h->forward[0]->backward);\r
+    }\r
+\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "numchild", n);\r
+    if (d.dumpChildren) {\r
+        if (n > 1000)\r
+            n = 1000;\r
+\r
+        //unsigned keySize = d.extraInt[0];\r
+        //unsigned valueSize = d.extraInt[1];\r
+        unsigned mapnodesize = d.extraInt[2];\r
+        unsigned valueOff = d.extraInt[3];\r
+\r
+        bool isSimpleKey = isSimpleType(keyType);\r
+        bool isSimpleValue = isSimpleType(valueType);\r
+        // both negative:\r
+        int keyOffset = 2 * sizeof(void*) - int(mapnodesize);\r
+        int valueOffset = 2 * sizeof(void*) - int(mapnodesize) + valueOff;\r
+\r
+        P(d, "extra", "simplekey: " << isSimpleKey << " isSimpleValue: " << isSimpleValue\r
+            << " keyOffset: " << keyOffset << " valueOffset: " << valueOffset\r
+            << " mapnodesize: " << mapnodesize);\r
+        d << ",children=[";\r
+\r
+        QMapData::Node *node = reinterpret_cast<QMapData::Node *>(h->forward[0]);\r
+        QMapData::Node *end = reinterpret_cast<QMapData::Node *>(h);\r
+        int i = 0;\r
+\r
+        while (node != end) {\r
+            d.beginHash();\r
+                P(d, "name", i);\r
+                qDumpInnerValueHelper(d, keyType, addOffset(node, keyOffset), "key");\r
+                qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));\r
+                if (isSimpleKey && isSimpleValue) {\r
+                    P(d, "type", valueType);\r
+                    P(d, "addr", addOffset(node, valueOffset));\r
+                } else {\r
+#if QT_VERSION >= 0x040500\r
+                    // actually, any type (even 'char') will do...\r
+                    P(d, "type", NS"QMapNode<"\r
+                        << keyType << "," << valueType << " >");\r
+                    P(d, "exp", "*('"NS"QMapNode<"\r
+                        << keyType << "," << valueType << " >'*)" << node);\r
+\r
+                    //P(d, "exp", "*('"NS"QMapData'*)" << (void*)node);\r
+                    //P(d, "exp", "*(char*)" << (void*)node);\r
+                    // P(d, "addr", node);  does not work as gdb fails to parse\r
+#else \r
+                    P(d, "type", NS"QMapData::Node<"\r
+                        << keyType << "," << valueType << " >");\r
+                    P(d, "exp", "*('"NS"QMapData::Node<"\r
+                        << keyType << "," << valueType << " >'*)" << node);\r
+#endif\r
+                }\r
+            d.endHash();\r
+\r
+            ++i;\r
+            node = node->forward[0];\r
+        }\r
+        d << "]";\r
+    }\r
+\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQMultiMap(QDumper &d)\r
+{\r
+    qDumpQMap(d);\r
+}\r
+\r
+static void qDumpQModelIndex(QDumper &d)\r
+{\r
+    const QModelIndex *mi = reinterpret_cast<const QModelIndex *>(d.data);\r
+\r
+    P(d, "type", NS"QModelIndex");\r
+    if (mi->isValid()) {\r
+        P(d, "value", "(" << mi->row() << ", " << mi->column() << ")");\r
+        P(d, "numchild", 5);\r
+        if (d.dumpChildren) {\r
+            d << ",children=[";\r
+            I(d, "row", mi->row());\r
+            I(d, "column", mi->column());\r
+\r
+            d.beginHash();\r
+            P(d, "name", "parent");\r
+            const QModelIndex parent = mi->parent();\r
+            if (parent.isValid())\r
+                P(d, "value", "(" << mi->row() << ", " << mi->column() << ")");\r
+            else\r
+                P(d, "value", "<invalid>");\r
+            P(d, "exp", "(("NSX"QModelIndex"NSY"*)" << d.data << ")->parent()");\r
+            P(d, "type", NS"QModelIndex");\r
+            P(d, "numchild", "1");\r
+            d.endHash();\r
+\r
+            S(d, "internalId", QString::number(mi->internalId(), 10));\r
+\r
+            d.beginHash();\r
+            P(d, "name", "model");\r
+            P(d, "value", static_cast<const void *>(mi->model()));\r
+            P(d, "type", NS"QAbstractItemModel*");\r
+            P(d, "numchild", "1");\r
+            d.endHash();\r
+\r
+            d << "]";\r
+        }\r
+    } else {\r
+        P(d, "value", "<invalid>");\r
+        P(d, "numchild", 0);\r
+    }\r
+\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQObject(QDumper &d)\r
+{\r
+    const QObject *ob = reinterpret_cast<const QObject *>(d.data);\r
+    const QMetaObject *mo = ob->metaObject();\r
+    unsigned childrenOffset = d.extraInt[0];\r
+    P(d, "value", ob->objectName());\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QObject");\r
+    P(d, "displayedtype", mo->className());\r
+    P(d, "numchild", 4);\r
+    if (d.dumpChildren) {\r
+        const QObjectList &children = ob->children();\r
+        int slotCount = 0;\r
+        int signalCount = 0;\r
+        for (int i = mo->methodCount(); --i >= 0; ) {\r
+            QMetaMethod::MethodType mt = mo->method(i).methodType();\r
+            signalCount += (mt == QMetaMethod::Signal);\r
+            slotCount += (mt == QMetaMethod::Slot);\r
+        }\r
+        d << ",children=[";\r
+        d.beginHash();\r
+            P(d, "name", "properties");\r
+            // FIXME: Note that when simply using '(QObject*)'\r
+            // in the cast below, Gdb/MI _sometimes_ misparses\r
+            // expressions further down in the tree.\r
+            P(d, "exp", "*(class '"NS"QObject'*)" << d.data);\r
+            P(d, "type", NS"QObjectPropertyList");\r
+            P(d, "value", "<" << mo->propertyCount() << " items>");\r
+            P(d, "numchild", mo->propertyCount());\r
+        d.endHash();\r
+#if 0\r
+        d.beginHash();\r
+            P(d, "name", "methods");\r
+            P(d, "exp", "*(class '"NS"QObject'*)" << d.data);\r
+            P(d, "value", "<" << mo->methodCount() << " items>");\r
+            P(d, "numchild", mo->methodCount());\r
+        d.endHash();\r
+#endif\r
+#if 0\r
+        d.beginHash();\r
+            P(d, "name", "senders");\r
+            P(d, "exp", "(*(class '"NS"QObjectPrivate'*)" << dfunc(ob) << ")->senders");\r
+            P(d, "type", NS"QList<"NS"QObjectPrivateSender>");\r
+        d.endHash();\r
+#endif\r
+#if PRIVATE_OBJECT_ALLOWED\r
+        d.beginHash();\r
+            P(d, "name", "signals");\r
+            P(d, "exp", "*(class '"NS"QObject'*)" << d.data);\r
+            P(d, "type", NS"QObjectSignalList");\r
+            P(d, "value", "<" << signalCount << " items>");\r
+            P(d, "numchild", signalCount);\r
+        d.endHash();\r
+        d.beginHash();\r
+            P(d, "name", "slots");\r
+            P(d, "exp", "*(class '"NS"QObject'*)" << d.data);\r
+            P(d, "type", NS"QObjectSlotList");\r
+            P(d, "value", "<" << slotCount << " items>");\r
+            P(d, "numchild", slotCount);\r
+        d.endHash();\r
+#endif\r
+        d.beginHash();\r
+            P(d, "name", "children");\r
+            // works always, but causes additional traffic on the list\r
+            //P(d, "exp", "((class '"NS"QObject'*)" << d.data << ")->children()");\r
+            //\r
+            //P(d, "addr", addOffset(dfunc(ob), childrenOffset));\r
+            //P(d, "type", NS"QList<QObject *>");\r
+            //P(d, "value", "<" << children.size() << " items>");\r
+            qDumpInnerValue(d, NS"QList<"NS"QObject *>",\r
+                addOffset(dfunc(ob), childrenOffset));\r
+            P(d, "numchild", children.size());\r
+        d.endHash();\r
+#if 0\r
+        // Unneeded (and not working): Connections are listes as childen\r
+        // of the signal or slot they are connected to.\r
+        // d.beginHash();\r
+        //     P(d, "name", "connections");\r
+        //     P(d, "exp", "*(*(class "NS"QObjectPrivate*)" << dfunc(ob) << ")->connectionLists");\r
+        //     P(d, "type", NS"QVector<"NS"QList<"NS"QObjectPrivate::Connection> >");\r
+        // d.endHash();\r
+#endif\r
+#if 0\r
+        d.beginHash();\r
+            P(d, "name", "objectprivate");\r
+            P(d, "type", NS"QObjectPrivate");\r
+            P(d, "addr", dfunc(ob));\r
+            P(d, "value", "");\r
+            P(d, "numchild", "1");\r
+        d.endHash();\r
+#endif\r
+        d.beginHash();\r
+            P(d, "name", "parent");\r
+            qDumpInnerValueHelper(d, NS"QObject *", ob->parent());\r
+        d.endHash();\r
+#if 1\r
+        d.beginHash();\r
+            P(d, "name", "className");\r
+            P(d, "value",ob->metaObject()->className());\r
+            P(d, "type", "");\r
+            P(d, "numchild", "0");\r
+        d.endHash();\r
+#endif\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQObjectPropertyList(QDumper &d)\r
+{\r
+    const QObject *ob = (const QObject *)d.data;\r
+    const QMetaObject *mo = ob->metaObject();\r
+    P(d, "addr", "<synthetic>");\r
+    P(d, "type", NS"QObjectPropertyList");\r
+    P(d, "numchild", mo->propertyCount());\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        for (int i = mo->propertyCount(); --i >= 0; ) {\r
+            const QMetaProperty & prop = mo->property(i);\r
+            d.beginHash();\r
+            P(d, "name", prop.name());\r
+            P(d, "exp", "((" << mo->className() << "*)" << ob\r
+                        << ")->" << prop.name() << "()");\r
+            if (isEqual(prop.typeName(), "QString")) {\r
+                P(d, "value", prop.read(ob).toString());\r
+                P(d, "valueencoded", "1");\r
+                P(d, "type", NS"QString");\r
+                P(d, "numchild", "0");\r
+            } else if (isEqual(prop.typeName(), "bool")) {\r
+                P(d, "value", (prop.read(ob).toBool() ? "true" : "false"));\r
+                P(d, "numchild", "0");\r
+            } else if (isEqual(prop.typeName(), "int")) {\r
+                P(d, "value", prop.read(ob).toInt());\r
+                P(d, "numchild", "0");\r
+            }\r
+            P(d, "type", prop.typeName());\r
+            P(d, "numchild", "1");\r
+            d.endHash();\r
+        }\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQObjectMethodList(QDumper &d)\r
+{\r
+    const QObject *ob = (const QObject *)d.data;\r
+    const QMetaObject *mo = ob->metaObject();\r
+    P(d, "addr", "<synthetic>");\r
+    P(d, "type", NS"QObjectMethodList");\r
+    P(d, "numchild", mo->methodCount());\r
+    P(d, "childtype", "QMetaMethod::Method");\r
+    P(d, "childnumchild", "0");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        for (int i = 0; i != mo->methodCount(); ++i) {\r
+            const QMetaMethod & method = mo->method(i);\r
+            int mt = method.methodType();\r
+            d.beginHash();\r
+            P(d, "name", i << " " << mo->indexOfMethod(method.signature())\r
+                << " " << method.signature());\r
+            P(d, "value", (mt == QMetaMethod::Signal ? "<Signal>" : "<Slot>") << " (" << mt << ")");\r
+            d.endHash();\r
+        }\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+#if PRIVATE_OBJECT_ALLOWED\r
+const char * qConnectionTypes[] ={\r
+    "auto",\r
+    "direct",\r
+    "queued",\r
+    "autocompat",\r
+    "blockingqueued"\r
+};\r
+\r
+#if QT_VERSION >= 0x040400\r
+static const QObjectPrivate::ConnectionList &qConnectionList(const QObject *ob, int signalNumber)\r
+{\r
+    static const QObjectPrivate::ConnectionList emptyList;\r
+    const QObjectPrivate *p = reinterpret_cast<const QObjectPrivate *>(dfunc(ob));\r
+    if (!p->connectionLists)\r
+        return emptyList;\r
+    typedef QVector<QObjectPrivate::ConnectionList> ConnLists;\r
+    const ConnLists *lists = reinterpret_cast<const ConnLists *>(p->connectionLists);\r
+    // there's an optimization making the lists only large enough to hold the\r
+    // last non-empty item\r
+    if (signalNumber >= lists->size())\r
+        return emptyList;\r
+    return lists->at(signalNumber);\r
+}\r
+#endif\r
+\r
+static void qDumpQObjectSignal(QDumper &d)\r
+{\r
+    unsigned signalNumber = d.extraInt[0];\r
+\r
+    P(d, "addr", "<synthetic>");\r
+    P(d, "numchild", "1");\r
+    P(d, "type", NS"QObjectSignal");\r
+\r
+#if QT_VERSION >= 0x040400\r
+    if (d.dumpChildren) {\r
+        const QObject *ob = reinterpret_cast<const QObject *>(d.data);\r
+        d << ",children=[";\r
+        const QObjectPrivate::ConnectionList &connList = qConnectionList(ob, signalNumber);\r
+        for (int i = 0; i != connList.size(); ++i) {\r
+            const QObjectPrivate::Connection &conn = connList.at(i);\r
+            d.beginHash();\r
+                P(d, "name", i << " receiver");\r
+                qDumpInnerValueHelper(d, NS"QObject *", conn.receiver);\r
+            d.endHash();\r
+            d.beginHash();\r
+                P(d, "name", i << " slot");\r
+                P(d, "type", "");\r
+                if (conn.receiver) \r
+                    P(d, "value", conn.receiver->metaObject()->method(conn.method).signature());\r
+                else\r
+                    P(d, "value", "<invalid receiver>");\r
+                P(d, "numchild", "0");\r
+            d.endHash();\r
+            d.beginHash();\r
+                P(d, "name", i << " type");\r
+                P(d, "type", "");\r
+                P(d, "value", "<" << qConnectionTypes[conn.method] << " connection>");\r
+                P(d, "numchild", "0");\r
+            d.endHash();\r
+        }\r
+        d << "]";\r
+        P(d, "numchild", connList.size());\r
+    }\r
+#endif\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQObjectSignalList(QDumper &d)\r
+{\r
+    const QObject *ob = reinterpret_cast<const QObject *>(d.data);\r
+    const QMetaObject *mo = ob->metaObject();\r
+    int count = 0;\r
+    for (int i = mo->methodCount(); --i >= 0; )\r
+        count += (mo->method(i).methodType() == QMetaMethod::Signal);\r
+    P(d, "addr", d.data);\r
+    P(d, "numchild", count);\r
+#if QT_VERSION >= 0x040400\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        for (int i = 0; i != mo->methodCount(); ++i) {\r
+            const QMetaMethod & method = mo->method(i);\r
+            if (method.methodType() == QMetaMethod::Signal) {\r
+                int k = mo->indexOfSignal(method.signature());\r
+                const QObjectPrivate::ConnectionList &connList = qConnectionList(ob, k);\r
+                d.beginHash();\r
+                P(d, "name", k);\r
+                P(d, "value", method.signature());\r
+                P(d, "numchild", connList.size());\r
+                //P(d, "numchild", "1");\r
+                P(d, "exp", "*(class '"NS"QObject'*)" << d.data);\r
+                P(d, "type", NS"QObjectSignal");\r
+                d.endHash();\r
+            }\r
+        }\r
+        d << "]";\r
+    }\r
+#endif\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQObjectSlot(QDumper &d)\r
+{\r
+    int slotNumber = d.extraInt[0];\r
+\r
+    P(d, "addr", d.data);\r
+    P(d, "numchild", "1");\r
+    P(d, "type", NS"QObjectSlot");\r
+\r
+#if QT_VERSION >= 0x040400\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        int numchild = 0;\r
+        const QObject *ob = reinterpret_cast<const QObject *>(d.data);\r
+        const QObjectPrivate *p = reinterpret_cast<const QObjectPrivate *>(dfunc(ob));\r
+        for (int s = 0; s != p->senders.size(); ++s) {\r
+            const QObjectPrivate::Sender &sender = p->senders.at(s);\r
+            const QObjectPrivate::ConnectionList &connList\r
+                = qConnectionList(sender.sender, sender.signal);\r
+            for (int i = 0; i != connList.size(); ++i) {\r
+                const QObjectPrivate::Connection &conn = connList.at(i);\r
+                if (conn.receiver == ob && conn.method == slotNumber) {\r
+                    ++numchild;\r
+                    const QMetaMethod & method =\r
+                        sender.sender->metaObject()->method(sender.signal);\r
+                    d.beginHash();\r
+                        P(d, "name", s << " sender");\r
+                        qDumpInnerValueHelper(d, NS"QObject *", sender.sender);\r
+                    d.endHash();\r
+                    d.beginHash();\r
+                        P(d, "name", s << " signal");\r
+                        P(d, "type", "");\r
+                        P(d, "value", method.signature());\r
+                        P(d, "numchild", "0");\r
+                    d.endHash();\r
+                    d.beginHash();\r
+                        P(d, "name", s << " type");\r
+                        P(d, "type", "");\r
+                        P(d, "value", "<" << qConnectionTypes[conn.method] << " connection>");\r
+                        P(d, "numchild", "0");\r
+                    d.endHash();\r
+                }\r
+            }\r
+        }\r
+        d << "]";\r
+        P(d, "numchild", numchild);\r
+    }\r
+#endif\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQObjectSlotList(QDumper &d)\r
+{\r
+    const QObject *ob = reinterpret_cast<const QObject *>(d.data);\r
+#if QT_VERSION >= 0x040400\r
+    const QObjectPrivate *p = reinterpret_cast<const QObjectPrivate *>(dfunc(ob));\r
+#endif\r
+    const QMetaObject *mo = ob->metaObject();\r
+\r
+    int count = 0;\r
+    for (int i = mo->methodCount(); --i >= 0; )\r
+        count += (mo->method(i).methodType() == QMetaMethod::Slot);\r
+\r
+    P(d, "addr", d.data);\r
+    P(d, "numchild", count);\r
+#if QT_VERSION >= 0x040400\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        for (int i = 0; i != mo->methodCount(); ++i) {\r
+            const QMetaMethod & method = mo->method(i);\r
+            if (method.methodType() == QMetaMethod::Slot) {\r
+                d.beginHash();\r
+                int k = mo->indexOfSlot(method.signature());\r
+                P(d, "name", k);\r
+                P(d, "value", method.signature());\r
+\r
+                // count senders. expensive...\r
+                int numchild = 0;\r
+                for (int s = 0; s != p->senders.size(); ++s) {\r
+                    const QObjectPrivate::Sender & sender = p->senders.at(s);\r
+                    const QObjectPrivate::ConnectionList &connList\r
+                        = qConnectionList(sender.sender, sender.signal);\r
+                    for (int c = 0; c != connList.size(); ++c) {\r
+                        const QObjectPrivate::Connection &conn = connList.at(c);\r
+                        if (conn.receiver == ob && conn.method == k)\r
+                            ++numchild;\r
+                    }\r
+                }\r
+                P(d, "numchild", numchild);\r
+                P(d, "exp", "*(class '"NS"QObject'*)" << d.data);\r
+                P(d, "type", NS"QObjectSlot");\r
+                d.endHash();\r
+            }\r
+        }\r
+        d << "]";\r
+    }\r
+#endif\r
+    d.disarm();\r
+}\r
+#endif // PRIVATE_OBJECT_ALLOWED\r
+\r
+\r
+static void qDumpQPixmap(QDumper &d)\r
+{\r
+#ifdef QT_GUI_LIB\r
+    const QPixmap &im = *reinterpret_cast<const QPixmap *>(d.data);\r
+    P(d, "value", "(" << im.width() << "x" << im.height() << ")");\r
+    P(d, "type", NS"QPixmap");\r
+    P(d, "numchild", "0");\r
+    d.disarm();\r
+#else\r
+    Q_UNUSED(d);\r
+#endif\r
+}\r
+\r
+static void qDumpQSet(QDumper &d)\r
+{\r
+    // This uses the knowledge that QHash<T> has only a single member\r
+    // of  union { QHashData *d; QHashNode<Key, T> *e; };\r
+    QHashData *hd = *(QHashData**)d.data;\r
+    QHashData::Node *node = hd->firstNode();\r
+\r
+    int n = hd->size;\r
+    if (n < 0)\r
+        qCheck(false);\r
+    if (n > 0) {\r
+        qCheckAccess(node);\r
+        qCheckPointer(node->next);\r
+    }\r
+\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "numchild", 2 * n);\r
+    if (d.dumpChildren) {\r
+        if (n > 100)\r
+            n = 100;\r
+        d << ",children=[";\r
+        int i = 0;\r
+        for (int bucket = 0; bucket != hd->numBuckets && i <= 10000; ++bucket) {\r
+            for (node = hd->buckets[bucket]; node->next; node = node->next) {\r
+                d.beginHash();\r
+                P(d, "name", i);\r
+                P(d, "type", d.innertype);\r
+                P(d, "exp", "(('"NS"QHashNode<" << d.innertype\r
+                    << ","NS"QHashDummyValue>'*)"\r
+                    << static_cast<const void*>(node) << ")->key"\r
+                );\r
+                d.endHash();\r
+                ++i;\r
+                if (i > 10000) {\r
+                    d.putEllipsis();\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQString(QDumper &d)\r
+{\r
+    const QString &str = *reinterpret_cast<const QString *>(d.data);\r
+\r
+    if (!str.isEmpty()) {\r
+        qCheckAccess(str.unicode());\r
+        qCheckAccess(str.unicode() + str.size());\r
+    }\r
+\r
+    P(d, "value", str);\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QString");\r
+    //P(d, "editvalue", str);  // handled generically below\r
+    P(d, "numchild", "0");\r
+\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQStringList(QDumper &d)\r
+{\r
+    const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);\r
+    int n = list.size();\r
+    if (n < 0)\r
+        qCheck(false);\r
+    if (n > 0) {\r
+        qCheckAccess(&list.front());\r
+        qCheckAccess(&list.back());\r
+    }\r
+\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "numchild", n);\r
+    P(d, "childtype", NS"QString");\r
+    P(d, "childnumchild", "0");\r
+    if (d.dumpChildren) {\r
+        if (n > 1000)\r
+            n = 1000;\r
+        d << ",children=[";\r
+        for (int i = 0; i != n; ++i) {\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            P(d, "value", list[i]);\r
+            P(d, "valueencoded", "1");\r
+            d.endHash();\r
+        }\r
+        if (n < list.size())\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQTextCodec(QDumper &d)\r
+{\r
+    const QTextCodec &codec = *reinterpret_cast<const QTextCodec *>(d.data);\r
+    P(d, "value", codec.name());\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", NS"QTextCodec");\r
+    P(d, "numchild", "2");\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        S(d, "name", codec.name());\r
+        I(d, "mibEnum", codec.mibEnum());\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQVariantHelper(const void *data, QString *value,\r
+    QString *exp, int *numchild)\r
+{\r
+    const QVariant &v = *reinterpret_cast<const QVariant *>(data);\r
+    switch (v.type()) {\r
+    case QVariant::Invalid:\r
+        *value = QLatin1String("<invalid>");\r
+        *numchild = 0;\r
+        break;\r
+    case QVariant::String:\r
+        *value = QLatin1Char('"') + v.toString() + QLatin1Char('"');\r
+        *numchild = 0;\r
+        break;\r
+    case QVariant::StringList:\r
+        *exp = QString(QLatin1String("((QVariant*)%1)->d.data.c"))\r
+                    .arg((quintptr)data);\r
+        *numchild = v.toStringList().size();\r
+        break;\r
+    case QVariant::Int:\r
+        *value = QString::number(v.toInt());\r
+        *numchild= 0;\r
+        break;\r
+    case QVariant::Double:\r
+        *value = QString::number(v.toDouble());\r
+        *numchild = 0;\r
+        break;\r
+    default: {\r
+        char buf[1000];\r
+        const char *format = (v.typeName()[0] == 'Q')\r
+            ?  "'"NS"%s "NS"qVariantValue<"NS"%s >'(*('"NS"QVariant'*)%p)"\r
+            :  "'%s "NS"qVariantValue<%s >'(*('"NS"QVariant'*)%p)";\r
+        qsnprintf(buf, sizeof(buf) - 1, format, v.typeName(), v.typeName(), data);\r
+        *exp = QLatin1String(buf);\r
+        *numchild = 1;\r
+        break;\r
+        }\r
+    }\r
+}\r
+\r
+static void qDumpQVariant(QDumper &d)\r
+{\r
+    const QVariant &v = *reinterpret_cast<const QVariant *>(d.data);\r
+    QString value;\r
+    QString exp;\r
+    int numchild = 0;\r
+    qDumpQVariantHelper(d.data, &value, &exp, &numchild);\r
+    bool isInvalid = (v.typeName() == 0);\r
+    if (isInvalid) {\r
+        P(d, "value", "(invalid)");\r
+    } else if (value.isEmpty()) {\r
+        P(d, "value", "(" << v.typeName() << ") " << qPrintable(value));\r
+    } else {\r
+        QByteArray ba;\r
+        ba += '(';\r
+        ba += v.typeName();\r
+        ba += ") ";\r
+        ba += qPrintable(value);\r
+        P(d, "value", ba);\r
+        P(d, "valueencoded", "1");\r
+    }\r
+    P(d, "type", NS"QVariant");\r
+    P(d, "numchild", (isInvalid ? "0" : "1"));\r
+    if (d.dumpChildren) {\r
+        d << ",children=[";\r
+        d.beginHash();\r
+        P(d, "name", "value");\r
+        if (!exp.isEmpty())\r
+            P(d, "exp", qPrintable(exp));\r
+        if (!value.isEmpty()) {\r
+            P(d, "value", value);\r
+            P(d, "valueencoded", "1");\r
+        }\r
+        P(d, "type", v.typeName());\r
+        P(d, "numchild", numchild);\r
+        d.endHash();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpQVector(QDumper &d)\r
+{\r
+    QVectorData *v = *reinterpret_cast<QVectorData *const*>(d.data);\r
+\r
+    // Try to provoke segfaults early to prevent the frontend\r
+    // from asking for unavailable child details\r
+    int nn = v->size;\r
+    if (nn < 0)\r
+        qCheck(false);\r
+    if (nn > 0) {\r
+        //qCheckAccess(&vec.front());\r
+        //qCheckAccess(&vec.back());\r
+    }\r
+\r
+    unsigned innersize = d.extraInt[0];\r
+    unsigned typeddatasize = d.extraInt[1];\r
+\r
+    int n = nn;\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "numchild", n);\r
+    if (d.dumpChildren) {\r
+        QByteArray strippedInnerType = stripPointerType(d.innertype);\r
+        const char *stripped =\r
+            isPointerType(d.innertype) ? strippedInnerType.data() : 0;\r
+        if (n > 1000)\r
+            n = 1000;\r
+        d << ",children=[";\r
+        for (int i = 0; i != n; ++i) {\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            qDumpInnerValueOrPointer(d, d.innertype, stripped,\r
+                addOffset(v, i * innersize + typeddatasize));\r
+            d.endHash();\r
+        }\r
+        if (n < nn)\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpStdList(QDumper &d)\r
+{\r
+    const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data);\r
+    const void *p = d.data;\r
+    qCheckAccess(p);\r
+    p = deref(p);\r
+    qCheckAccess(p);\r
+    p = deref(p);\r
+    qCheckAccess(p);\r
+    p = deref(addOffset(d.data, sizeof(void*)));\r
+    qCheckAccess(p);\r
+    p = deref(addOffset(p, sizeof(void*)));\r
+    qCheckAccess(p);\r
+    p = deref(addOffset(p, sizeof(void*)));\r
+    qCheckAccess(p);\r
+\r
+    int nn = 0;\r
+    std::list<int>::const_iterator it = list.begin();\r
+    for (; nn < 101 && it != list.end(); ++nn, ++it)\r
+        qCheckAccess(it.operator->());\r
+\r
+    if (nn > 100)\r
+        P(d, "value", "<more than 100 items>");\r
+    else\r
+        P(d, "value", "<" << nn << " items>");\r
+    P(d, "numchild", nn);\r
+\r
+    P(d, "valuedisabled", "true");\r
+    if (d.dumpChildren) {\r
+        QByteArray strippedInnerType = stripPointerType(d.innertype);\r
+        const char *stripped =\r
+            isPointerType(d.innertype) ? strippedInnerType.data() : 0;\r
+        d << ",children=[";\r
+        it = list.begin();\r
+        for (int i = 0; i < 1000 && it != list.end(); ++i, ++it) {\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            qDumpInnerValueOrPointer(d, d.innertype, stripped, it.operator->());\r
+            d.endHash();\r
+        }\r
+        if (it != list.end())\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpStdMap(QDumper &d)\r
+{\r
+    typedef std::map<int, int> DummyType;\r
+    const DummyType &map = *reinterpret_cast<const DummyType*>(d.data);\r
+    const char *keyType   = d.templateParameters[0];\r
+    const char *valueType = d.templateParameters[1];\r
+    const void *p = d.data;\r
+    qCheckAccess(p);\r
+    p = deref(p);\r
+\r
+    int nn = map.size();\r
+    qCheck(nn >= 0);\r
+    DummyType::const_iterator it = map.begin();\r
+    for (int i = 0; i < nn && i < 10 && it != map.end(); ++i, ++it)\r
+        qCheckAccess(it.operator->());\r
+\r
+    QByteArray strippedInnerType = stripPointerType(d.innertype);\r
+    P(d, "numchild", nn);\r
+    P(d, "value", "<" << nn << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "valueoffset", d.extraInt[2]);\r
+\r
+    // HACK: we need a properly const qualified version of the\r
+    // std::pair used. We extract it from the allocator parameter\r
+    // (#4, "std::allocator<std::pair<key, value> >")\r
+    // as it is there, and, equally importantly, in an order that\r
+    // gdb accepts when fed with it.\r
+    char *pairType = (char *)(d.templateParameters[3]) + 15;\r
+    pairType[strlen(pairType) - 2] = 0;\r
+    P(d, "pairtype", pairType);\r
+    \r
+    if (d.dumpChildren) {\r
+        bool isSimpleKey = isSimpleType(keyType);\r
+        bool isSimpleValue = isSimpleType(valueType);\r
+        int valueOffset = d.extraInt[2];\r
+\r
+        P(d, "extra", "isSimpleKey: " << isSimpleKey\r
+            << " isSimpleValue: " << isSimpleValue\r
+            << " valueType: '" << valueType\r
+            << " valueOffset: " << valueOffset);\r
+\r
+        d << ",children=[";\r
+        it = map.begin();\r
+        for (int i = 0; i < 1000 && it != map.end(); ++i, ++it) {\r
+            d.beginHash();\r
+                const void *node = it.operator->();\r
+                P(d, "name", i);\r
+                qDumpInnerValueHelper(d, keyType, node, "key");\r
+                qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset));\r
+                if (isSimpleKey && isSimpleValue) {\r
+                    P(d, "type", valueType);\r
+                    P(d, "addr", addOffset(node, valueOffset));\r
+                    P(d, "numchild", 0);\r
+                } else {\r
+                    P(d, "addr", node);\r
+                    P(d, "type", pairType);\r
+                    P(d, "numchild", 2);\r
+                }\r
+            d.endHash();\r
+        }\r
+        if (it != map.end())\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpStdString(QDumper &d)\r
+{\r
+    const std::string &str = *reinterpret_cast<const std::string *>(d.data);\r
+\r
+    if (!str.empty()) {\r
+        qCheckAccess(str.c_str());\r
+        qCheckAccess(str.c_str() + str.size() - 1);\r
+    }\r
+\r
+    d << ",value=\"";\r
+    d.putBase64Encoded(str.c_str(), str.size());\r
+    d << "\"";\r
+    P(d, "valueencoded", "1");\r
+    P(d, "type", "std::string");\r
+    P(d, "numchild", "0");\r
+\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpStdWString(QDumper &d)\r
+{\r
+    const std::wstring &str = *reinterpret_cast<const std::wstring *>(d.data);\r
+\r
+    if (!str.empty()) {\r
+        qCheckAccess(str.c_str());\r
+        qCheckAccess(str.c_str() + str.size() - 1);\r
+    }\r
+\r
+    d << "value='";\r
+    d.putBase64Encoded((const char *)str.c_str(), str.size() * sizeof(wchar_t));\r
+    d << "'";\r
+    P(d, "valueencoded", (sizeof(wchar_t) == 2 ? "2" : "3"));\r
+    P(d, "type", "std::wstring");\r
+    P(d, "numchild", "0");\r
+\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpStdVector(QDumper &d)\r
+{\r
+    // Correct type would be something like:\r
+    // std::_Vector_base<int,std::allocator<int, std::allocator<int> >>::_Vector_impl\r
+    struct VectorImpl {\r
+        char *start;\r
+        char *finish;\r
+        char *end_of_storage;\r
+    };\r
+    const VectorImpl *v = static_cast<const VectorImpl *>(d.data);\r
+\r
+    // Try to provoke segfaults early to prevent the frontend\r
+    // from asking for unavailable child details\r
+    int nn = (v->finish - v->start) / d.extraInt[0];\r
+    if (nn < 0)\r
+        qCheck(false);\r
+    if (nn > 0) {\r
+        qCheckAccess(v->start);\r
+        qCheckAccess(v->finish);\r
+        qCheckAccess(v->end_of_storage);\r
+    }\r
+\r
+    int n = nn;\r
+    P(d, "value", "<" << n << " items>");\r
+    P(d, "valuedisabled", "true");\r
+    P(d, "numchild", n);\r
+    if (d.dumpChildren) {\r
+        unsigned innersize = d.extraInt[0];\r
+        QByteArray strippedInnerType = stripPointerType(d.innertype);\r
+        const char *stripped =\r
+            isPointerType(d.innertype) ? strippedInnerType.data() : 0;\r
+        if (n > 1000)\r
+            n = 1000;\r
+        d << ",children=[";\r
+        for (int i = 0; i != n; ++i) {\r
+            d.beginHash();\r
+            P(d, "name", i);\r
+            qDumpInnerValueOrPointer(d, d.innertype, stripped,\r
+                addOffset(v->start, i * innersize));\r
+            d.endHash();\r
+        }\r
+        if (n < nn)\r
+            d.putEllipsis();\r
+        d << "]";\r
+    }\r
+    d.disarm();\r
+}\r
+\r
+static void qDumpStdVectorBool(QDumper &d)\r
+{\r
+    // FIXME\r
+    return qDumpStdVector(d);\r
+}\r
+\r
+static void handleProtocolVersion2and3(QDumper & d)\r
+{\r
+    if (!d.outertype[0]) {\r
+        qDumpUnknown(d);\r
+        return;\r
+    }\r
+\r
+    d.setupTemplateParameters();\r
+    P(d, "iname", d.iname);\r
+    P(d, "addr", d.data);\r
+\r
+#ifdef QT_NO_QDATASTREAM\r
+    if (d.protocolVersion == 3) {\r
+        QVariant::Type type = QVariant::nameToType(d.outertype);\r
+        if (type != QVariant::Invalid) {\r
+            QVariant v(type, d.data);\r
+            QByteArray ba;\r
+            QDataStream ds(&ba, QIODevice::WriteOnly);\r
+            ds << v;\r
+            P(d, "editvalue", ba);\r
+        }\r
+    }\r
+#endif\r
+\r
+    const char *type = stripNamespace(d.outertype);\r
+    // type[0] is usally 'Q', so don't use it\r
+    switch (type[1]) {\r
+        case 'B':\r
+            if (isEqual(type, "QByteArray"))\r
+                qDumpQByteArray(d);\r
+            break;\r
+        case 'D':\r
+            if (isEqual(type, "QDateTime"))\r
+                qDumpQDateTime(d);\r
+            else if (isEqual(type, "QDir"))\r
+                qDumpQDir(d);\r
+            break;\r
+        case 'F':\r
+            if (isEqual(type, "QFile"))\r
+                qDumpQFile(d);\r
+            else if (isEqual(type, "QFileInfo"))\r
+                qDumpQFileInfo(d);\r
+            break;\r
+        case 'H':\r
+            if (isEqual(type, "QHash"))\r
+                qDumpQHash(d);\r
+            else if (isEqual(type, "QHashNode"))\r
+                qDumpQHashNode(d);\r
+            break;\r
+        case 'I':\r
+            if (isEqual(type, "QImage"))\r
+                qDumpQImage(d);\r
+            break;\r
+        case 'L':\r
+            if (isEqual(type, "QList"))\r
+                qDumpQList(d);\r
+            else if (isEqual(type, "QLinkedList"))\r
+                qDumpQLinkedList(d);\r
+            else if (isEqual(type, "QLocale"))\r
+                qDumpQLocale(d);\r
+            break;\r
+        case 'M':\r
+            if (isEqual(type, "QMap"))\r
+                qDumpQMap(d);\r
+            else if (isEqual(type, "QMapNode"))\r
+                qDumpQMapNode(d);\r
+            else if (isEqual(type, "QModelIndex"))\r
+                qDumpQModelIndex(d);\r
+            else if (isEqual(type, "QMultiMap"))\r
+                qDumpQMultiMap(d);\r
+            break;\r
+        case 'O':\r
+            if (isEqual(type, "QObject"))\r
+                qDumpQObject(d);\r
+            else if (isEqual(type, "QObjectPropertyList"))\r
+                qDumpQObjectPropertyList(d);\r
+            else if (isEqual(type, "QObjectMethodList"))\r
+                qDumpQObjectMethodList(d);\r
+            #if PRIVATE_OBJECT_ALLOWED\r
+            else if (isEqual(type, "QObjectSignal"))\r
+                qDumpQObjectSignal(d);\r
+            else if (isEqual(type, "QObjectSignalList"))\r
+                qDumpQObjectSignalList(d);\r
+            else if (isEqual(type, "QObjectSlot"))\r
+                qDumpQObjectSlot(d);\r
+            else if (isEqual(type, "QObjectSlotList"))\r
+                qDumpQObjectSlotList(d);\r
+            #endif\r
+            break;\r
+        case 'P':\r
+            if (isEqual(type, "QPixmap"))\r
+                qDumpQPixmap(d);\r
+            break;\r
+        case 'S':\r
+            if (isEqual(type, "QSet"))\r
+                qDumpQSet(d);\r
+            else if (isEqual(type, "QString"))\r
+                qDumpQString(d);\r
+            else if (isEqual(type, "QStringList"))\r
+                qDumpQStringList(d);\r
+            break;\r
+        case 'T':\r
+            if (isEqual(type, "QTextCodec"))\r
+                qDumpQTextCodec(d);\r
+            break;\r
+        case 'V':\r
+            if (isEqual(type, "QVariant"))\r
+                qDumpQVariant(d);\r
+            else if (isEqual(type, "QVector"))\r
+                qDumpQVector(d);\r
+            break;\r
+        case 's':\r
+            if (isEqual(type, "wstring"))\r
+                qDumpStdWString(d);\r
+            break;\r
+        case 't':\r
+            if (isEqual(type, "std::vector"))\r
+                qDumpStdVector(d);\r
+            else if (isEqual(type, "std::vector::bool"))\r
+                qDumpStdVectorBool(d);\r
+            else if (isEqual(type, "std::list"))\r
+                qDumpStdList(d);\r
+            else if (isEqual(type, "std::map"))\r
+                qDumpStdMap(d);\r
+            else if (isEqual(type, "std::string") || isEqual(type, "string"))\r
+                qDumpStdString(d);\r
+            else if (isEqual(type, "std::wstring"))\r
+                qDumpStdWString(d);\r
+            break;\r
+    }\r
+\r
+    if (!d.success)\r
+        qDumpUnknown(d);\r
+}\r
+\r
+} // anonymous namespace\r
+\r
+\r
+extern "C" Q_DECL_EXPORT\r
+void qDumpObjectData440(\r
+    int protocolVersion,\r
+    int token,\r
+    void *data,\r
+    bool dumpChildren,\r
+    int extraInt0,\r
+    int extraInt1,\r
+    int extraInt2,\r
+    int extraInt3)\r
+{\r
+    //sleep(20);\r
+    if (protocolVersion == 1) {\r
+        QDumper d;\r
+        d.protocolVersion = protocolVersion;\r
+        d.token           = token;\r
+\r
+        // This is a list of all available dumpers. Note that some templates\r
+        // currently require special hardcoded handling in the debugger plugin.\r
+        // They are mentioned here nevertheless. For types that not listed\r
+        // here, dumpers won't be used.\r
+        d << "dumpers=["\r
+            "\""NS"QByteArray\","\r
+            "\""NS"QDateTime\","\r
+            "\""NS"QDir\","\r
+            "\""NS"QFile\","\r
+            "\""NS"QFileInfo\","\r
+            "\""NS"QHash\","\r
+            "\""NS"QHashNode\","\r
+            "\""NS"QImage\","\r
+            "\""NS"QLinkedList\","\r
+            "\""NS"QList\","\r
+            "\""NS"QLocale\","\r
+            "\""NS"QMap\","\r
+            "\""NS"QMapNode\","\r
+            "\""NS"QModelIndex\","\r
+            #if QT_VERSION >= 0x040500\r
+            "\""NS"QMultiMap\","\r
+            #endif\r
+            "\""NS"QObject\","\r
+            "\""NS"QObjectMethodList\","   // hack to get nested properties display\r
+            "\""NS"QObjectPropertyList\","\r
+            #if PRIVATE_OBJECT_ALLOWED\r
+            "\""NS"QObjectSignal\","\r
+            "\""NS"QObjectSignalList\","\r
+            "\""NS"QObjectSlot\","\r
+            "\""NS"QObjectSlotList\","\r
+            #endif // PRIVATE_OBJECT_ALLOWED\r
+            // << "\""NS"QRegion\","\r
+            "\""NS"QSet\","\r
+            "\""NS"QString\","\r
+            "\""NS"QStringList\","\r
+            "\""NS"QTextCodec\","\r
+            "\""NS"QVariant\","\r
+            "\""NS"QVector\","\r
+            "\""NS"QWidget\","\r
+            "\"string\","\r
+            "\"wstring\","\r
+            "\"std::basic_string\","\r
+            "\"std::list\","\r
+            "\"std::map\","\r
+            "\"std::string\","\r
+            "\"std::vector\","\r
+            "\"std::wstring\","\r
+            "]";\r
+        d << ",qtversion=["\r
+            "\"" << ((QT_VERSION >> 16) & 255) << "\","\r
+            "\"" << ((QT_VERSION >> 8)  & 255) << "\","\r
+            "\"" << ((QT_VERSION)       & 255) << "\"]";\r
+        d << ",namespace=\""NS"\"";\r
+        d.disarm();\r
+    }\r
+\r
+    else if (protocolVersion == 2 || protocolVersion == 3) {\r
+        QDumper d;\r
+\r
+        d.protocolVersion = protocolVersion;\r
+        d.token           = token;\r
+        d.data            = data;\r
+        d.dumpChildren    = dumpChildren;\r
+        d.extraInt[0]     = extraInt0;\r
+        d.extraInt[1]     = extraInt1;\r
+        d.extraInt[2]     = extraInt2;\r
+        d.extraInt[3]     = extraInt3;\r
+\r
+        const char *inbuffer = qDumpInBuffer;\r
+        d.outertype = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;\r
+        d.iname     = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;\r
+        d.exp       = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;\r
+        d.innertype = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;\r
+        d.iname     = inbuffer; while (*inbuffer) ++inbuffer; ++inbuffer;\r
+\r
+        handleProtocolVersion2and3(d);\r
+    }\r
+\r
+    else {\r
+        qDebug() << "Unsupported protocol version" << protocolVersion;\r
+    }\r
+}\r