qttypes.py 99.3 KB
Newer Older
hjk's avatar
hjk committed
1
2
3
4
5
6
7

#######################################################################
#
# Dumper Implementations
#
#######################################################################

8
9
from __future__ import with_statement

10
11
12
13
14
15
16
17
18
19
movableTypes = set([
    "QBrush", "QBitArray", "QByteArray", "QCustomTypeInfo", "QChar", "QDate",
    "QDateTime", "QFileInfo", "QFixed", "QFixedPoint", "QFixedSize",
    "QHashDummyValue", "QIcon", "QImage", "QLine", "QLineF", "QLatin1Char",
    "QLocale", "QMatrix", "QModelIndex", "QPoint", "QPointF", "QPen",
    "QPersistentModelIndex", "QResourceRoot", "QRect", "QRectF", "QRegExp",
    "QSize", "QSizeF", "QString", "QTime", "QTextBlock", "QUrl", "QVariant",
    "QXmlStreamAttribute", "QXmlStreamNamespaceDeclaration",
    "QXmlStreamNotationDeclaration", "QXmlStreamEntityDeclaration"
])
20

hjk's avatar
hjk committed
21
22
23
24
def qByteArrayDataData(d, value):
    checkRef(value['ref'])
    size = int(value['size'])
    alloc = int(value['alloc'])
25
26
    try:
        # Qt 5. Will fail on Qt 4 due to the missing 'offset' member.
hjk's avatar
hjk committed
27
        addr = d.addressOf(value) + int(value['offset'])
28
29
    except:
        # Qt 4:
hjk's avatar
hjk committed
30
        addr = value['data']
hjk's avatar
hjk committed
31
    return createPointerValue(value, addr, d.charType()), size, alloc
32

hjk's avatar
hjk committed
33
34
def qByteArrayData(d, value):
    return d.byteArrayDataData(value['d'].dereference())
35
36

def qEncodeByteArray(d, value, limit = None):
hjk's avatar
hjk committed
37
    data, size, alloc = d.byteArrayData(value)
38
39
40
41
42
43
44
45
46
    if alloc != 0:
        check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
    limit = d.computeLimit(size, limit)
    s = d.readRawMemory(data, limit)
    if limit < size:
        s += "2e2e2e"
    return s

def qEncodeString(d, value, limit = 0):
hjk's avatar
hjk committed
47
    data, size, alloc = d.stringData(value)
48
49
50
51
52
53
54
55
    if alloc != 0:
        check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
    limit = d.computeLimit(size, limit)
    s = d.readRawMemory(data, 2 * limit)
    if limit < size:
        s += "2e002e002e00"
    return s

hjk's avatar
hjk committed
56
57
58
59
60
61
62
63
def mapForms():
    return "Normal,Compact"

def arrayForms():
    if hasPlot():
        return "Normal,Plot"
    return "Normal"

hjk's avatar
hjk committed
64
def qMapCompact(format, keyType, valueType):
hjk's avatar
hjk committed
65
66
67
68
    if format == 2:
        return True # Compact.
    return isSimpleType(keyType) and isSimpleType(valueType)

hjk's avatar
hjk committed
69
def qPutMapName(d, value):
hjk's avatar
hjk committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    if str(value.type) == d.ns + "QString":
        d.put('key="%s",' % d.encodeString(value))
        d.put('keyencoded="%s",' % Hex4EncodedLittleEndian)
    elif str(value.type) == d.ns + "QByteArray":
        d.put('key="%s",' % d.encodeByteArray(value))
        d.put('keyencoded="%s",' % Hex2EncodedLatin1)
    else:
        if lldbLoaded:
            d.put('name="%s",' % value.GetValue())
        else:
            d.put('name="%s",' % value)

Dumper.encodeByteArray = qEncodeByteArray
Dumper.byteArrayData = qByteArrayData
hjk's avatar
hjk committed
84
85
86
87
88
89
Dumper.byteArrayDataData = qByteArrayDataData
Dumper.putByteArrayValue = \
    lambda d, value: d.putValue(d.encodeByteArray(value), Hex2EncodedLatin1)
Dumper.putStringValue = \
    lambda d, value: d.putValue(d.encodeString(value), Hex4EncodedLittleEndian)

hjk's avatar
hjk committed
90
Dumper.encodeString = qEncodeString
hjk's avatar
hjk committed
91
Dumper.stringData = Dumper.byteArrayData
hjk's avatar
hjk committed
92
Dumper.putMapName = qPutMapName
hjk's avatar
hjk committed
93
94

Dumper.isMapCompact = \
hjk's avatar
hjk committed
95
    lambda d, keyType, valueType: qMapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144


def tryPutObjectNameValue(d, value):
    try:
        # Is this derived from QObject?
        dd = value["d_ptr"]["d"]
        privateType = d.lookupType(d.ns + "QObjectPrivate")
        staticMetaObject = value["staticMetaObject"]
        d_ptr = dd.cast(privateType.pointer()).dereference()
        objectName = None
        try:
            objectName = d_ptr["objectName"]
        except: # Qt 5
            p = d_ptr["extraData"]
            if not isNull(p):
                objectName = p.dereference()["objectName"]
        if not objectName is None:
            data, size, alloc = d.stringData(objectName)
            if size > 0:
                str = d.readRawMemory(data, 2 * size)
                d.putValue(str, Hex4EncodedLittleEndian, 1)
    except:
        pass

Dumper.tryPutObjectNameValue = tryPutObjectNameValue

############################################################################################


def qdump__QAtomicInt(d, value):
    d.putValue(value["_q_value"])
    d.putNumChild(0)


def qdump__QBasicAtomicInt(d, value):
    d.putValue(value["_q_value"])
    d.putNumChild(0)


def qdump__QBasicAtomicPointer(d, value):
    d.putType(value.type)
    p = cleanAddress(value["_q_value"])
    d.putValue(p)
    d.putPointerValue(value.address)
    d.putNumChild(p)
    if d.isExpanded():
        with Children(d):
           d.putItem(value["_q_value"])

hjk's avatar
hjk committed
145
146
147
148
149
150
151
def qdump__QByteArrayData(d, value):
    data, size, alloc = d.byteArrayDataData(value)
    d.putValue(d.readRawMemory(data, size), Hex2EncodedLatin1)
    d.putNumChild(size)
    if d.isExpanded():
        d.putArrayData(d.charType(), data, size)

152
153
154
def qform__QByteArray():
    return "Inline,As Latin1 in Separate Window,As UTF-8 in Separate Window"

hjk's avatar
hjk committed
155
156
def qdump__QByteArray(d, value):
    d.putByteArrayValue(value)
hjk's avatar
hjk committed
157
    data, size, alloc = d.byteArrayData(value)
158
    d.putNumChild(size)
159
160
161
162
    format = d.currentItemFormat()
    if format == 1:
        d.putDisplay(StopDisplay)
    elif format == 2:
163
        d.putField("editformat", DisplayLatin1String)
hjk's avatar
hjk committed
164
        d.putField("editvalue", d.encodeByteArray(value, None))
165
    elif format == 3:
166
        d.putField("editformat", DisplayUtf8String)
hjk's avatar
hjk committed
167
        d.putField("editvalue", d.encodeByteArray(value, None))
hjk's avatar
hjk committed
168
    if d.isExpanded():
169
        d.putArrayData(d.charType(), data, size)
hjk's avatar
hjk committed
170
171


172
173
174
175
176
177
178
179
180
181
182
183
184
# Fails on Windows.
try:
    import curses.ascii
    def printableChar(ucs):
        if curses.ascii.isprint(ucs):
            return ucs
        return '?'
except:
    def printableChar(ucs):
        if ucs >= 32 and ucs <= 126:
            return ucs
        return '?'

hjk's avatar
hjk committed
185
186
def qdump__QChar(d, value):
    ucs = int(value["ucs"])
187
    d.putValue("'%c' (%d)" % (printableChar(ucs), ucs))
hjk's avatar
hjk committed
188
189
190
    d.putNumChild(0)


hjk's avatar
hjk committed
191
def qform__QAbstractItemModel():
192
    return "Normal,Enhanced"
193

hjk's avatar
hjk committed
194
def qdump__QAbstractItemModel(d, value):
195
196
197
198
199
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
    #format == 2:
200
    # Create a default-constructed QModelIndex on the stack.
201
    try:
202
        ri = makeValue(d.ns + "QModelIndex", "-1, -1, 0, 0")
hjk's avatar
hjk committed
203
        this_ = makeExpression(value)
204
        ri_ = makeExpression(ri)
205
206
207
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (this_, ri_)))
    except:
hjk's avatar
hjk committed
208
        d.putPlainChildren(value)
209
        return
210
211
    d.putValue("%d x %d" % (rowCount, columnCount))
    d.putNumChild(rowCount * columnCount)
hjk's avatar
hjk committed
212
213
    if d.isExpanded():
        with Children(d, numChild=rowCount * columnCount, childType=ri.type):
214
215
216
            i = 0
            for row in xrange(rowCount):
                for column in xrange(columnCount):
hjk's avatar
hjk committed
217
                    with SubItem(d, i):
218
219
220
221
222
223
                        d.putName("[%s, %s]" % (row, column))
                        mi = parseAndEvaluate("%s.index(%d,%d,%s)"
                            % (this_, row, column, ri_))
                        #warn("MI: %s " % mi)
                        #name = "[%d,%d]" % (row, column)
                        #d.putValue("%s" % mi)
hjk's avatar
hjk committed
224
                        d.putItem(mi)
225
226
227
228
229
230
231
232
                        i = i + 1
                        #warn("MI: %s " % mi)
                        #d.putName("[%d,%d]" % (row, column))
                        #d.putValue("%s" % mi)
                        #d.putNumChild(0)
                        #d.putType(mi.type)
    #gdb.execute("call free($ri)")

233
234
235
def qform__QModelIndex():
    return "Normal,Enhanced"

hjk's avatar
hjk committed
236
def qdump__QModelIndex(d, value):
237
238
239
240
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
hjk's avatar
hjk committed
241
242
    r = value["r"]
    c = value["c"]
243
244
245
246
    try:
        p = value["p"]
    except:
        p = value["i"]
hjk's avatar
hjk committed
247
    m = value["m"]
248
249
250
251
252
    if isNull(m) or r < 0 or c < 0:
        d.putValue("(invalid)")
        d.putPlainChildren(value)
        return

253
254
    mm = m.dereference()
    mm = mm.cast(mm.type.unqualified())
255
    try:
256
257
258
        mi = makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
        mm_ = makeExpression(mm)
        mi_ = makeExpression(mi)
259
260
261
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
    except:
262
        d.putEmptyValue()
hjk's avatar
hjk committed
263
        d.putPlainChildren(value)
264
        return
265
266
267

    try:
        # Access DisplayRole as value
hjk's avatar
hjk committed
268
269
        val = parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_))
        v = val["d"]["data"]["ptr"]
270
271
272
273
        d.putStringValue(makeValue(d.ns + 'QString', v))
    except:
        d.putValue("(invalid)")

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    d.putNumChild(rowCount * columnCount)
    if d.isExpanded():
        with Children(d):
            i = 0
            for row in xrange(rowCount):
                for column in xrange(columnCount):
                    with UnnamedSubItem(d, i):
                        d.putName("[%s, %s]" % (row, column))
                        mi2 = parseAndEvaluate("%s.index(%d,%d,%s)"
                            % (mm_, row, column, mi_))
                        d.putItem(mi2)
                        i = i + 1
            #d.putCallItem("parent", val, "parent")
            #with SubItem(d, "model"):
            #    d.putValue(m)
            #    d.putType(d.ns + "QAbstractItemModel*")
            #    d.putNumChild(1)
291
292
    #gdb.execute("call free($mi)")

hjk's avatar
hjk committed
293

hjk's avatar
hjk committed
294
def qdump__QDate(d, value):
295
    jd = int(value["jd"])
296
297
298
299
300
    if int(jd):
        d.putValue(jd, JulianDate)
        d.putNumChild(1)
        if d.isExpanded():
            qt = d.ns + "Qt::"
301
302
            if lldbLoaded:
                qt += "DateFormat::" # FIXME: Bug?...
303
304
305
306
307
308
309
310
311
312
            # FIXME: This improperly uses complex return values.
            with Children(d):
                d.putCallItem("toString", value, "toString", qt + "TextDate")
                d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
                d.putCallItem("(SystemLocale)", value, "toString",
                    qt + "SystemLocaleDate")
                d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
313
314


hjk's avatar
hjk committed
315
def qdump__QTime(d, value):
316
317
318
319
320
321
    mds = value["mds"]
    if int(mds) >= 0:
        d.putValue(value["mds"], MillisecondsSinceMidnight)
        d.putNumChild(1)
        if d.isExpanded():
            qt = d.ns + "Qt::"
322
323
            if lldbLoaded:
                qt += "DateFormat::" # FIXME: Bug?...
324
325
326
327
328
329
330
331
332
333
334
            # FIXME: This improperly uses complex return values.
            with Children(d):
                d.putCallItem("toString", value, "toString", qt + "TextDate")
                d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
                d.putCallItem("(SystemLocale)", value, "toString",
                     qt + "SystemLocaleDate")
                d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
                d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
335
336


hjk's avatar
hjk committed
337
def qdump__QDateTime(d, value):
338
339
    try:
        # Fails without debug info.
340
        p = value["d"]["d"].dereference()
341
    except:
hjk's avatar
hjk committed
342
        d.putPlainChildren(value)
343
        return
344
345
346
    mds = int(p["time"]["mds"])
    if mds >= 0:
        d.putValue("%s/%s" % (int(p["date"]["jd"]), mds),
347
348
349
350
351
352
            JulianDateAndMillisecondsSinceMidnight)
        d.putNumChild(1)
        if d.isExpanded():
            # FIXME: This improperly uses complex return values.
            with Children(d):
                qt = d.ns + "Qt::"
353
354
                if lldbLoaded:
                    qt += "DateFormat::" # FIXME: Bug?...
355
356
357
358
359
360
361
362
363
364
                d.putCallItem("toTime_t", value, "toTime_t")
                d.putCallItem("toString", value, "toString", qt + "TextDate")
                d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
                d.putCallItem("(SystemLocale)", value, "toString", qt + "SystemLocaleDate")
                d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
                d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
                d.putCallItem("toLocalTime", value, "toTimeSpec", qt + "LocalTime")
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
365
366
367


def qdump__QDir(d, value):
hjk's avatar
hjk committed
368
    d.putNumChild(1)
369
370
371
372
373
374
375
    data = value["d_ptr"]["d"].dereference()
    try:
        # Up to Qt 4.7
        d.putStringValue(data["path"])
    except:
        # Qt 4.8 and later.
        d.putStringValue(data["dirEntry"]["m_filePath"])
hjk's avatar
hjk committed
376
377
    if d.isExpanded():
        with Children(d):
378
            qdir = d.ns + "QDir::"
hjk's avatar
hjk committed
379
380
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
hjk's avatar
hjk committed
381
382
            d.putSubItem("entryList", data["files"])
            d.putSubItem("entryInfoList", data["fileInfos"])
hjk's avatar
hjk committed
383
384


hjk's avatar
hjk committed
385
def qdump__QFile(d, value):
hjk's avatar
hjk committed
386
    try:
387
        ptype = d.lookupType(d.ns + "QFilePrivate").pointer()
hjk's avatar
hjk committed
388
389
390
391
392
        d_ptr = value["d_ptr"]["d"]
        d.putStringValue(d_ptr.cast(ptype).dereference()["fileName"])
    except:
        d.putPlainChildren(value)
        return
393
    d.putNumChild(1)
hjk's avatar
hjk committed
394
395
    if d.isExpanded():
        with Children(d):
hjk's avatar
hjk committed
396
            base = fieldAt(value.type, 0).type
397
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
398
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
399
400


hjk's avatar
hjk committed
401
def qdump__QFileInfo(d, value):
402
    try:
hjk's avatar
hjk committed
403
        d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3])
404
    except:
hjk's avatar
hjk committed
405
        d.putPlainChildren(value)
406
        return
hjk's avatar
hjk committed
407
    d.putNumChild(1)
hjk's avatar
hjk committed
408
    if d.isExpanded():
409
        with Children(d, childType=d.lookupType(d.ns + "QString")):
hjk's avatar
hjk committed
410
411
412
413
414
415
416
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("absoluteFilePath", value, "absoluteFilePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
            d.putCallItem("canonicalFilePath", value, "canonicalFilePath")
            d.putCallItem("completeBaseName", value, "completeBaseName")
            d.putCallItem("completeSuffix", value, "completeSuffix")
            d.putCallItem("baseName", value, "baseName")
417
418
            if False:
                #ifdef Q_OS_MACX
hjk's avatar
hjk committed
419
420
421
422
                d.putCallItem("isBundle", value, "isBundle")
                d.putCallItem("bundleName", value, "bundleName")
            d.putCallItem("fileName", value, "fileName")
            d.putCallItem("filePath", value, "filePath")
423
            # Crashes gdb (archer-tromey-python, at dad6b53fe)
hjk's avatar
hjk committed
424
425
426
            #d.putCallItem("group", value, "group")
            #d.putCallItem("owner", value, "owner")
            d.putCallItem("path", value, "path")
427

hjk's avatar
hjk committed
428
429
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
430
431

            #QFile::Permissions permissions () const
hjk's avatar
hjk committed
432
            perms = call(value, "permissions")
433
434
435
            if perms is None:
                d.putValue("<not available>")
            else:
hjk's avatar
hjk committed
436
                with SubItem(d, "permissions"):
437
                    d.putEmptyValue()
438
439
                    d.putType(d.ns + "QFile::Permissions")
                    d.putNumChild(10)
hjk's avatar
hjk committed
440
                    if d.isExpanded():
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
                        with Children(d, 10):
                            perms = perms['i']
                            d.putBoolItem("ReadOwner",  perms & 0x4000)
                            d.putBoolItem("WriteOwner", perms & 0x2000)
                            d.putBoolItem("ExeOwner",   perms & 0x1000)
                            d.putBoolItem("ReadUser",   perms & 0x0400)
                            d.putBoolItem("WriteUser",  perms & 0x0200)
                            d.putBoolItem("ExeUser",    perms & 0x0100)
                            d.putBoolItem("ReadGroup",  perms & 0x0040)
                            d.putBoolItem("WriteGroup", perms & 0x0020)
                            d.putBoolItem("ExeGroup",   perms & 0x0010)
                            d.putBoolItem("ReadOther",  perms & 0x0004)
                            d.putBoolItem("WriteOther", perms & 0x0002)
                            d.putBoolItem("ExeOther",   perms & 0x0001)

            #QDir absoluteDir () const
            #QDir dir () const
hjk's avatar
hjk committed
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
            d.putCallItem("caching", value, "caching")
            d.putCallItem("exists", value, "exists")
            d.putCallItem("isAbsolute", value, "isAbsolute")
            d.putCallItem("isDir", value, "isDir")
            d.putCallItem("isExecutable", value, "isExecutable")
            d.putCallItem("isFile", value, "isFile")
            d.putCallItem("isHidden", value, "isHidden")
            d.putCallItem("isReadable", value, "isReadable")
            d.putCallItem("isRelative", value, "isRelative")
            d.putCallItem("isRoot", value, "isRoot")
            d.putCallItem("isSymLink", value, "isSymLink")
            d.putCallItem("isWritable", value, "isWritable")
            d.putCallItem("created", value, "created")
            d.putCallItem("lastModified", value, "lastModified")
            d.putCallItem("lastRead", value, "lastRead")


def qdump__QFixed(d, value):
    v = int(value["val"])
hjk's avatar
hjk committed
477
478
479
480
    d.putValue("%s/64 = %s" % (v, v/64.0))
    d.putNumChild(0)


hjk's avatar
hjk committed
481
def qdump__QFiniteStack(d, value):
hjk's avatar
hjk committed
482
483
    alloc = int(value["_alloc"])
    size = int(value["_size"])
hjk's avatar
hjk committed
484
485
486
487
    check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
    d.putItemCount(size)
    d.putNumChild(size)
    if d.isExpanded():
488
        innerType = d.templateArgument(value.type, 0)
hjk's avatar
hjk committed
489
490
        d.putArrayData(innerType, value["_array"], size)

491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
# Stock gdb 7.2 seems to have a problem with types here:
#
#  echo -e "namespace N { struct S { enum E { zero, one, two }; }; }\n"\
#      "int main() { N::S::E x = N::S::one;\n return x; }" >> main.cpp
#  g++ -g main.cpp
#  gdb-7.2 -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \
#     -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q'
#  gdb-7.1 -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \
#     -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q'
#  gdb-cvs -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \
#     -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q'
#
# gives as of 2010-11-02
#
#  type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n
hjk's avatar
hjk committed
506
507
#    Traceback (most recent call last): File "<string>", line 1,
#      in <module> RuntimeError: No type named N::S::E.
508
509
510
511
512
#  type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n  N::S::E
#  type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n  N::S::E
#
# i.e. there's something broken in stock 7.2 that is was ok in 7.1 and is ok later.

hjk's avatar
hjk committed
513
514
def qdump__QFlags(d, value):
    i = value["i"]
515
    try:
516
        enumType = d.templateArgument(value.type.unqualified(), 0)
517
518
519
        d.putValue("%s (%s)" % (i.cast(enumType), i))
    except:
        d.putValue("%s" % i)
hjk's avatar
hjk committed
520
521
522
    d.putNumChild(0)


523
524
525
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
526
def qdump__QHash(d, value):
hjk's avatar
hjk committed
527
528

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
529
530
531
        val = value.cast(hashDataType)
        bucket = val["buckets"]
        e = val.cast(hashNodeType)
hjk's avatar
hjk committed
532
        for n in xrange(int(val["numBuckets"]) - 1, -1, -1):
hjk's avatar
hjk committed
533
534
535
536
537
538
539
540
541
542
543
544
545
            n = n - 1
            if n < 0:
                break
            if bucket.dereference() != e:
                return bucket.dereference()
            bucket = bucket + 1
        return e;

    def hashDataNextNode(node):
        next = node["next"]
        if next["next"]:
            return next
        d = node.cast(hashDataType.pointer()).dereference()
hjk's avatar
hjk committed
546
547
        numBuckets = int(d["numBuckets"])
        start = (int(node["h"]) % numBuckets) + 1
hjk's avatar
hjk committed
548
        bucket = d["buckets"] + start
549
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
550
551
552
553
554
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

555
556
    keyType = d.templateArgument(value.type, 0)
    valueType = d.templateArgument(value.type, 1)
hjk's avatar
hjk committed
557

hjk's avatar
hjk committed
558
559
    d_ptr = value["d"]
    e_ptr = value["e"]
hjk's avatar
hjk committed
560
    size = int(d_ptr["size"])
hjk's avatar
hjk committed
561
562
563
564

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

565
    check(0 <= size and size <= 100 * 1000 * 1000)
566
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
567

568
569
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
570
    if d.isExpanded():
hjk's avatar
hjk committed
571
        isCompact = d.isMapCompact(keyType, valueType)
hjk's avatar
hjk committed
572
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
573
        innerType = e_ptr.dereference().type
574
        childType = innerType
575
        if isCompact:
576
            childType = valueType
hjk's avatar
hjk committed
577
        with Children(d, size, maxNumChild=1000, childType=childType):
578
579
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
580
                with SubItem(d, i):
581
582
583
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
584
585
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
586
                        d.putItem(it)
587
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
588
589


hjk's avatar
hjk committed
590
def qdump__QHashNode(d, value):
591
592
    keyType = d.templateArgument(value.type, 0)
    valueType = d.templateArgument(value.type, 1)
hjk's avatar
hjk committed
593
594
    key = value["key"]
    val = value["value"]
hjk's avatar
hjk committed
595

596
597
598
599
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
600
    d.putEmptyValue()
hjk's avatar
hjk committed
601

602
    d.putNumChild(2)
hjk's avatar
hjk committed
603
    if d.isExpanded():
604
        with Children(d):
hjk's avatar
hjk committed
605
606
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
607
608


609
610
def qHashIteratorHelper(d, value):
    typeName = str(value.type)
611
    hashType = d.lookupType(typeName[0:typeName.rfind("::")])
612
613
    keyType = d.templateArgument(hashType, 0)
    valueType = d.templateArgument(hashType, 1)
614
    d.putNumChild(1)
615
    d.putEmptyValue()
616
617
618
    if d.isExpanded():
        with Children(d):
            typeName = "%sQHash<%s,%s>::Node" % (d.ns, keyType, valueType)
619
            node = value["i"].cast(d.lookupType(typeName).pointer())
620
621
622
623
624
625
626
627
628
629
            d.putSubItem("key", node["key"])
            d.putSubItem("value", node["value"])

def qdump__QHash__const_iterator(d, value):
    qHashIteratorHelper(d, value)

def qdump__QHash__iterator(d, value):
    qHashIteratorHelper(d, value)


hjk's avatar
hjk committed
630
631
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
632
633
634
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
635
636
637
638
639
640
        a = long(data["a"])
        a, n4 = divmod(a, 256)
        a, n3 = divmod(a, 256)
        a, n2 = divmod(a, 256)
        a, n1 = divmod(a, 256)
        d.putValue("%d.%d.%d.%d" % (n1, n2, n3, n4));
hjk's avatar
hjk committed
641
    d.putNumChild(1)
hjk's avatar
hjk committed
642
    if d.isExpanded():
hjk's avatar
hjk committed
643
        with Children(d):
hjk's avatar
hjk committed
644
           d.putFields(data)
hjk's avatar
hjk committed
645

hjk's avatar
hjk committed
646
def qdump__QList(d, value):
647
648
649
650
651
    dptr = childAt(value, 0)["d"]
    private = dptr.dereference()
    begin = int(private["begin"])
    end = int(private["end"])
    array = private["array"]
hjk's avatar
hjk committed
652
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
653
654
    size = end - begin
    check(size >= 0)
655
    checkRef(private["ref"])
hjk's avatar
hjk committed
656

657
    innerType = d.templateArgument(value.type, 0)
hjk's avatar
hjk committed
658

659
660
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
661
    if d.isExpanded():
hjk's avatar
hjk committed
662
663
664
665
666
667
        innerSize = innerType.sizeof
        # The exact condition here is:
        #  QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
        # but this data is available neither in the compiled binary nor
        # in the frontend.
        # So as first approximation only do the 'isLarge' check:
668
669
670
671
672
673
674
675
676
677
678
679
        stepSize = dptr.type.sizeof
        isInternal = innerSize <= stepSize and d.isMovableType(innerType)
        addr = d.addressOf(array) + begin * stepSize
        if isInternal:
            if innerSize == stepSize:
                p = createPointerValue(value, addr, innerType)
                d.putArrayData(innerType, p, size)
            else:
                with Children(d, size, childType=innerType):
                    for i in d.childRange():
                        p = createPointerValue(value, addr + i * stepSize, innerType)
                        d.putSubItem(i, p.dereference())
680
        else:
681
682
683
684
685
686
            p = createPointerValue(value, addr, innerType.pointer())
            # about 0.5s / 1000 items
            with Children(d, size, maxNumChild=2000, childType=innerType):
                for i in d.childRange():
                    d.putSubItem(i, p.dereference().dereference())
                    p += 1
hjk's avatar
hjk committed
687

hjk's avatar
hjk committed
688
689
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
690

hjk's avatar
hjk committed
691
def qdump__QImage(d, value):
692
    try:
hjk's avatar
hjk committed
693
        painters = int(value["painters"])
694
    except:
hjk's avatar
hjk committed
695
        d.putPlainChildren(value)
696
        return
hjk's avatar
hjk committed
697
    check(0 <= painters and painters < 1000)
hjk's avatar
hjk committed
698
    d_ptr = value["d"]
hjk's avatar
hjk committed
699
    if isNull(d_ptr):
700
        d.putValue("(null)")
hjk's avatar
hjk committed
701
    else:
702
        checkSimpleRef(d_ptr["ref"])
703
        d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
704
705
    bits = d_ptr["data"]
    nbytes = d_ptr["nbytes"]
706
    d.putNumChild(0)
hjk's avatar
hjk committed
707
    #d.putNumChild(1)
hjk's avatar
hjk committed
708
    if d.isExpanded():
709
        with Children(d):
hjk's avatar
hjk committed
710
            with SubItem(d, "data"):
711
                d.putNoType()
712
713
                d.putNumChild(0)
                d.putValue("size: %s bytes" % nbytes);
hjk's avatar
hjk committed
714
    format = d.currentItemFormat()
715
    if format == 1:
716
        d.putDisplay(StopDisplay)
717
    elif format == 2:
hjk's avatar
hjk committed
718
719
720
        if False:
            # Take four bytes at a time, this is critical for performance.
            # In fact, even four at a time is too slow beyond 100x100 or so.
721
            d.putField("editformat", DisplayImageData)
722
            d.put('%s="' % name)
hjk's avatar
hjk committed
723
724
725
            d.put("%08x" % int(d_ptr["width"]))
            d.put("%08x" % int(d_ptr["height"]))
            d.put("%08x" % int(d_ptr["format"]))
726
            p = bits.cast(d.intType().pointer())
hjk's avatar
hjk committed
727
728
729
            for i in xrange(nbytes / 4):
                d.put("%08x" % int(p.dereference()))
                p += 1
730
            d.put('",')
hjk's avatar
hjk committed
731
732
733
        else:
            # Write to an external file. Much faster ;-(
            file = tempfile.mkstemp(prefix="gdbpy_")
734
            filename = file[1].replace("\\", "\\\\")
735
            p = bits.cast(d.charType().pointer())
hjk's avatar
hjk committed
736
737
            gdb.execute("dump binary memory %s %s %s" %
                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
738
            d.putDisplay(DisplayImageFile, " %d %d %d %s"
739
                % (d_ptr["width"], d_ptr["height"], d_ptr["format"], filename))
hjk's avatar
hjk committed
740
741


hjk's avatar
hjk committed
742
743
744
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
hjk's avatar
hjk committed
745
    n = int(d_ptr["size"])
hjk's avatar
hjk committed
746
    check(0 <= n and n <= 100*1000*1000)
747
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
748
    d.putItemCount(n)
749
    d.putNumChild(n)
hjk's avatar
hjk committed
750
    if d.isExpanded():
751
        innerType = d.templateArgument(value.type, 0)
hjk's avatar
hjk committed
752
        with Children(d, n, maxNumChild=1000, childType=innerType):
753
754
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
755
                d.putSubItem(i, p["t"])
756
                p = p["n"]
hjk's avatar
hjk committed
757

758
qqLocalesCount = None
hjk's avatar
hjk committed
759

hjk's avatar
hjk committed
760
def qdump__QLocale(d, value):
761
762
763
764
    # Check for uninitialized 'index' variable. Retrieve size of
    # QLocale data array from variable in qlocale.cpp.
    # Default is 368 in Qt 4.8, 438 in Qt 5.0.1, the last one
    # being 'System'.
hjk's avatar
hjk committed
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
    #global qqLocalesCount
    #if qqLocalesCount is None:
    #    #try:
    #        qqLocalesCount = int(value(d.ns + 'locale_data_size'))
    #    #except:
    #        qqLocalesCount = 438
    #try:
    #    index = int(value["p"]["index"])
    #except:
    #    try:
    #        index = int(value["d"]["d"]["m_index"])
    #    except:
    #        index = int(value["d"]["d"]["m_data"]...)
    #check(index >= 0)
    #check(index <= qqLocalesCount)
hjk's avatar
hjk committed
780
    d.putStringValue(call(value, "name"))
781
782
783
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
784
    if d.isExpanded():
785
        with Children(d, childType=d.lookupType(d.ns + "QChar"), childNumChild=0):
hjk's avatar
hjk committed
786
787
788
789
790
            d.putCallItem("country", value, "country")
            d.putCallItem("language", value, "language")
            d.putCallItem("measurementSystem", value, "measurementSystem")
            d.putCallItem("numberOptions", value, "numberOptions")
            d.putCallItem("timeFormat_(short)", value,
hjk's avatar
hjk committed
791
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
792
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
793
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
794
795
796
797
798
799
            d.putCallItem("decimalPoint", value, "decimalPoint")
            d.putCallItem("exponential", value, "exponential")
            d.putCallItem("percent", value, "percent")
            d.putCallItem("zeroDigit", value, "zeroDigit")
            d.putCallItem("groupSeparator", value, "groupSeparator")
            d.putCallItem("negativeSign", value, "negativeSign")
hjk's avatar
hjk committed
800
801


hjk's avatar
hjk committed
802
def qdump__QMapNode(d, value):
803
    d.putEmptyValue()
804
    d.putNumChild(2)
hjk's avatar
hjk committed
805
806
807
808
809
810
    if d.isExpanded():
        with Children(d):
            d.putSubItem("key", value["key"])
            d.putSubItem("value", value["value"])


811
def qdumpHelper__Qt4_QMap(d, value, forceLong):
hjk's avatar
hjk committed
812
813
    d_ptr = value["d"].dereference()
    e_ptr = value["e"].dereference()
hjk's avatar
hjk committed
814
    n = int(d_ptr["size"])
hjk's avatar
hjk committed
815
    check(0 <= n and n <= 100*1000*1000)
816
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
817
818

    d.putItemCount(n)
819
    d.putNumChild(n)
hjk's avatar
hjk committed
820
    if d.isExpanded():
821
822
        if n > 10000:
            n = 10000
hjk's avatar
hjk committed
823

824
825
        keyType = d.templateArgument(value.type, 0)
        valueType = d.templateArgument(value.type, 1)
hjk's avatar
hjk committed
826
        isCompact = d.isMapCompact(keyType, valueType)
hjk's avatar
hjk committed
827
828
829
830
831
832

        it = e_ptr["forward"].dereference()

        # QMapPayloadNode is QMapNode except for the 'forward' member, so
        # its size is most likely the offset of the 'forward' member therein.
        # Or possibly 2 * sizeof(void *)
833
        nodeType = d.lookupType(d.ns + "QMapNode<%s, %s>" % (keyType, valueType))
hjk's avatar
hjk committed
834
835
        nodePointerType = nodeType.pointer()
        payloadSize = nodeType.sizeof - 2 * nodePointerType.sizeof
hjk's avatar
hjk committed
836

837
        if isCompact:
838
839
840
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
841

hjk's avatar
hjk committed
842
        with Children(d, n, childType=innerType):
843
            for i in xrange(n):
hjk's avatar
hjk committed
844
845
                base = it.cast(d.charPtrType()) - payloadSize
                node = base.cast(nodePointerType).dereference()
hjk's avatar
hjk committed
846
                with SubItem(d, i):
847
                    d.putField("iname", d.currentIName)
848
                    if isCompact:
849
                        #d.putType(valueType)
hjk's avatar
hjk committed
850
                        if forceLong:
851
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
852
                        else:
853
854
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
855
                    else:
hjk's avatar
hjk committed
856
                        d.putItem(node)
857
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
858
859


860
861
def qdumpHelper__Qt5_QMap(d, value, forceLong):
    d_ptr = value["d"].dereference()
hjk's avatar
hjk committed
862
    n = int(d_ptr["size"])
863
864
865
866
867
868
869
870
871
    check(0 <= n and n <= 100*1000*1000)
    checkRef(d_ptr["ref"])

    d.putItemCount(n)
    d.putNumChild(n)
    if d.isExpanded():
        if n > 10000:
            n = 10000

872
873
        keyType = d.templateArgument(value.type, 0)
        valueType = d.templateArgument(value.type, 1)
hjk's avatar
hjk committed
874
        isCompact = d.isMapCompact(keyType, valueType)
875
        nodeType = d.lookupType(d.ns + "QMapNode<%s, %s>" % (keyType, valueType))
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
        if isCompact:
            innerType = valueType
        else:
            innerType = nodeType

        with Children(d, n, childType=innerType):
            toDo = []
            i = -1
            node = d_ptr["header"]
            left = node["left"]
            if not isNull(left):
                toDo.append(left.dereference())
            right = node["right"]
            if not isNull(right):
                toDo.append(right.dereference())

            while len(toDo):
                node = toDo[0].cast(nodeType)
                toDo = toDo[1:]
                left = node["left"]
                if not isNull(left):
                    toDo.append(left.dereference())
                right = node["right"]
                if not isNull(right):
                    toDo.append(right.dereference())
                i += 1

                with SubItem(d, i):
904
                    d.putField("iname", d.currentIName)
905
906
907
908
909
910
911
912
913
914
915
                    if isCompact:
                        if forceLong:
                            d.putName("[%s] %s" % (i, node["key"]))
                        else:
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
                    else:
                        qdump__QMapNode(d, node)


def qdumpHelper__QMap(d, value, forceLong):
hjk's avatar
hjk committed
916
    if fieldAt(value["d"].dereference().type, 0).name == "backward":
917
918
919
920
        qdumpHelper__Qt4_QMap(d, value, forceLong)
    else:
        qdumpHelper__Qt5_QMap(d, value, forceLong)

921
922
923
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
924
925
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
926

927
928
929
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
930
931
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
932
933
934
935
936
937
938
939
940
941
942
943
944


def extractCString(table, offset):
    result = ""
    while True:
        d = table[offset]
        if d == 0:
            break
        result += "%c" % d
        offset += 1
    return result


hjk's avatar
hjk committed
945
946
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
hjk's avatar
hjk committed
947
948
    d.tryPutObjectNameValue(value)

949
    try:
hjk's avatar
hjk committed
950
        privateTypeName = d.ns + "QObjectPrivate"
951
        privateType = d.lookupType(privateTypeName)
hjk's avatar
hjk committed
952
        staticMetaObject = value["staticMetaObject"]
953
    except:
hjk's avatar
hjk committed
954
        d.putPlainChildren(value)
955
        return
hjk's avatar
hjk committed
956
    #warn("SMO: %s " % staticMetaObject)
957
958
959
960
961
962
963
    #warn("SMO DATA: %s " % staticMetaObject["d"]["stringdata"])
    superData = staticMetaObject["d"]["superdata"]
    #warn("SUPERDATA: %s" % superData)
    #while not isNull(superData):
    #    superData = superData.dereference()["d"]["superdata"]
    #    warn("SUPERDATA: %s" % superData)

964
965
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
966
        #d.putValue(cleanAddress(value.address))
967
        d.putPlainChildren(value)
hjk's avatar
hjk committed
968
        if d.isExpanded():
969
            with Children(d):
hjk's avatar
hjk committed
970
                d.putFields(value)
971
        return
972

hjk's avatar
hjk committed
973
    #warn("OBJECTNAME: %s " % objectName)
974
975
    dd = value["d_ptr"]["d"]
    d_ptr = dd.cast(privateType.pointer()).dereference()
976
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
977
    mo = d_ptr["metaObject"]
978
979
980
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
981
982
983
984
985
986
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
987
988
989
990
    # This is char * in Qt 4 and ByteArrayData * in Qt 5.
    # Force it to the char * data in the Qt 5 case.
    try:
        offset = metaStringData["offset"]
991
        metaStringData = metaStringData.cast(d.charPtrType()) + int(offset)
992
993
994
    except:
        pass

995
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
996
997
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
998
    #warn("TYPE: %s " % value.type)
999
1000
    #warn("INAME: %s " % d.currentIName)
    d.putEmptyValue()
hjk's avatar
hjk committed
1001
    #QSignalMapper::staticMetaObject
1002
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
1003
    d.putNumChild(4)
hjk's avatar
hjk committed
1004
    if d.isExpanded():
1005
      with Children(d):
1006

hjk's avatar
hjk committed
1007
        # Local data.
1008
1009
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
1010
              with SubItem(d, "data"):
1011
                d.putEmptyValue()
1012
                d.putNoType()
1013
                d.putNumChild(1)
hjk's avatar
hjk committed
1014
                if d.isExpanded():
1015
                    with Children(d):
hjk's avatar
hjk committed
1016
                        d.putFields(d_ptr, False)
1017
1018


hjk's avatar
hjk committed
1019
        d.putFields(value)