qttypes.py 89.4 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

def mapForms():
    return "Normal,Compact"

14
15
16
17
18
def arrayForms():
    if hasPlot():
        return "Normal,Plot"
    return "Normal"

19
20
21
22
23
24
def mapCompact(format, keyType, valueType):
    if format == 2:
        return True # Compact.
    return isSimpleType(keyType) and isSimpleType(valueType)


hjk's avatar
hjk committed
25
26
def qdump__QAtomicInt(d, value):
    d.putValue(value["_q_value"])
hjk's avatar
hjk committed
27
28
29
    d.putNumChild(0)


hjk's avatar
hjk committed
30
31
def qdump__QBasicAtomicInt(d, value):
    d.putValue(value["_q_value"])
32
33
34
    d.putNumChild(0)


hjk's avatar
hjk committed
35
36
37
def qdump__QBasicAtomicPointer(d, value):
    d.putType(value.type)
    p = cleanAddress(value["_q_value"])
38
    d.putValue(p)
hjk's avatar
hjk committed
39
    d.putPointerValue(value.address)
40
    d.putNumChild(p)
hjk's avatar
hjk committed
41
    if d.isExpanded():
42
        with Children(d):
hjk's avatar
hjk committed
43
           d.putItem(value["_q_value"])
44
45


hjk's avatar
hjk committed
46
47
48
def qdump__QByteArray(d, value):
    d.putByteArrayValue(value)
    data, size, alloc = qByteArrayData(value)
49
    d.putNumChild(size)
hjk's avatar
hjk committed
50
    if d.isExpanded():
51
        d.putArrayData(lookupType("char"), data, size)
hjk's avatar
hjk committed
52
53


hjk's avatar
hjk committed
54
55
def qdump__QChar(d, value):
    ucs = int(value["ucs"])
56
    d.putValue("'%c' (%d)" % (printableChar(ucs), ucs))
hjk's avatar
hjk committed
57
58
59
    d.putNumChild(0)


hjk's avatar
hjk committed
60
def qform__QAbstractItemModel():
61
    return "Normal,Enhanced"
62

hjk's avatar
hjk committed
63
def qdump__QAbstractItemModel(d, value):
64
65
66
67
68
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
    #format == 2:
69
    # Create a default-constructed QModelIndex on the stack.
70
    try:
71
        ri = makeValue(d.ns + "QModelIndex", "-1, -1, 0, 0")
hjk's avatar
hjk committed
72
        this_ = makeExpression(value)
73
        ri_ = makeExpression(ri)
74
75
76
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (this_, ri_)))
    except:
hjk's avatar
hjk committed
77
        d.putPlainChildren(value)
78
        return
79
80
    d.putValue("%d x %d" % (rowCount, columnCount))
    d.putNumChild(rowCount * columnCount)
hjk's avatar
hjk committed
81
82
    if d.isExpanded():
        with Children(d, numChild=rowCount * columnCount, childType=ri.type):
83
84
85
            i = 0
            for row in xrange(rowCount):
                for column in xrange(columnCount):
hjk's avatar
hjk committed
86
                    with SubItem(d, i):
87
88
89
90
91
92
                        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
93
                        d.putItem(mi)
94
95
96
97
98
99
100
101
                        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)")

102
103
104
def qform__QModelIndex():
    return "Normal,Enhanced"

hjk's avatar
hjk committed
105
def qdump__QModelIndex(d, value):
106
107
108
109
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
hjk's avatar
hjk committed
110
111
112
113
    r = value["r"]
    c = value["c"]
    p = value["p"]
    m = value["m"]
114
115
    mm = m.dereference()
    mm = mm.cast(mm.type.unqualified())
116
    try:
117
118
119
        mi = makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
        mm_ = makeExpression(mm)
        mi_ = makeExpression(mi)
120
121
122
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
    except:
hjk's avatar
hjk committed
123
        d.putPlainChildren(value)
124
        return
125
126
127

    try:
        # Access DisplayRole as value
hjk's avatar
hjk committed
128
129
        val = parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_))
        v = val["d"]["data"]["ptr"]
130
131
132
133
134
135
        d.putStringValue(makeValue(d.ns + 'QString', v))
    except:
        d.putValue("(invalid)")

    if r >= 0 and c >= 0 and not isNull(m):
        d.putNumChild(rowCount * columnCount)
hjk's avatar
hjk committed
136
        if d.isExpanded():
137
138
139
140
            with Children(d):
                i = 0
                for row in xrange(rowCount):
                    for column in xrange(columnCount):
hjk's avatar
hjk committed
141
                        with UnnamedSubItem(d, i):
142
143
144
                            d.putName("[%s, %s]" % (row, column))
                            mi2 = parseAndEvaluate("%s.index(%d,%d,%s)"
                                % (mm_, row, column, mi_))
hjk's avatar
hjk committed
145
                            d.putItem(mi2)
146
                            i = i + 1
hjk's avatar
hjk committed
147
148
                #d.putCallItem("parent", val, "parent")
                #with SubItem(d, "model"):
149
150
151
152
153
154
                #    d.putValue(m)
                #    d.putType(d.ns + "QAbstractItemModel*")
                #    d.putNumChild(1)
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
155
        if d.isExpanded():
156
157
158
159
            with Children(d):
                pass
    #gdb.execute("call free($mi)")

hjk's avatar
hjk committed
160

hjk's avatar
hjk committed
161
def qdump__QDate(d, value):
162
    d.putValue(value["jd"], JulianDate)
163
    d.putNumChild(1)
hjk's avatar
hjk committed
164
    if d.isExpanded():
165
        qt = d.ns + "Qt::"
166
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
167
168
169
170
        with Children(d):
            d.putCallItem("toString", value, "toString", qt + "TextDate")
            d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
            d.putCallItem("(SystemLocale)", value, "toString",
hjk's avatar
hjk committed
171
                qt + "SystemLocaleDate")
hjk's avatar
hjk committed
172
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
hjk's avatar
hjk committed
173
174


hjk's avatar
hjk committed
175
def qdump__QTime(d, value):
176
    d.putValue(value["mds"], MillisecondsSinceMidnight)
177
    d.putNumChild(1)
hjk's avatar
hjk committed
178
    if d.isExpanded():
179
        qt = d.ns + "Qt::"
180
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
181
182
183
184
        with Children(d):
            d.putCallItem("toString", value, "toString", qt + "TextDate")
            d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
            d.putCallItem("(SystemLocale)", value, "toString",
hjk's avatar
hjk committed
185
                 qt + "SystemLocaleDate")
hjk's avatar
hjk committed
186
187
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
            d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
188
189


hjk's avatar
hjk committed
190
def qdump__QDateTime(d, value):
191
192
    try:
        # Fails without debug info.
193
        p = value["d"]["d"].dereference()
194
    except:
hjk's avatar
hjk committed
195
        d.putPlainChildren(value)
196
        return
197
198
    d.putValue("%s/%s" % (p["date"]["jd"], p["time"]["mds"]),
        JulianDateAndMillisecondsSinceMidnight)
199
    d.putNumChild(1)
hjk's avatar
hjk committed
200
    if d.isExpanded():
201
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
202
        with Children(d):
203
            qt = d.ns + "Qt::"
hjk's avatar
hjk committed
204
205
206
207
208
209
210
211
212
213
            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")


def qdump__QDir(d, value):
hjk's avatar
hjk committed
214
    d.putNumChild(1)
215
216
217
218
219
220
221
    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
222
223
224
225
    if d.isExpanded():
        with Children(d):
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
hjk's avatar
hjk committed
226
227


hjk's avatar
hjk committed
228
def qdump__QFile(d, value):
hjk's avatar
hjk committed
229
230
231
232
233
234
235
    try:
        ptype = lookupType(d.ns + "QFilePrivate").pointer()
        d_ptr = value["d_ptr"]["d"]
        d.putStringValue(d_ptr.cast(ptype).dereference()["fileName"])
    except:
        d.putPlainChildren(value)
        return
236
    d.putNumChild(1)
hjk's avatar
hjk committed
237
238
    if d.isExpanded():
        with Children(d):
239
240
            base = value.type.fields()[0].type
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
241
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
242
243


hjk's avatar
hjk committed
244
def qdump__QFileInfo(d, value):
245
    try:
hjk's avatar
hjk committed
246
        d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3])
247
    except:
hjk's avatar
hjk committed
248
        d.putPlainChildren(value)
249
        return
hjk's avatar
hjk committed
250
    d.putNumChild(1)
hjk's avatar
hjk committed
251
252
253
254
255
256
257
258
259
    if d.isExpanded():
        with Children(d, childType=lookupType(d.ns + "QString")):
            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")
260
261
            if False:
                #ifdef Q_OS_MACX
hjk's avatar
hjk committed
262
263
264
265
                d.putCallItem("isBundle", value, "isBundle")
                d.putCallItem("bundleName", value, "bundleName")
            d.putCallItem("fileName", value, "fileName")
            d.putCallItem("filePath", value, "filePath")
266
            # Crashes gdb (archer-tromey-python, at dad6b53fe)
hjk's avatar
hjk committed
267
268
269
            #d.putCallItem("group", value, "group")
            #d.putCallItem("owner", value, "owner")
            d.putCallItem("path", value, "path")
270

hjk's avatar
hjk committed
271
272
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
273
274

            #QFile::Permissions permissions () const
hjk's avatar
hjk committed
275
            perms = call(value, "permissions")
276
277
278
            if perms is None:
                d.putValue("<not available>")
            else:
hjk's avatar
hjk committed
279
                with SubItem(d, "permissions"):
280
281
282
                    d.putValue(" ")
                    d.putType(d.ns + "QFile::Permissions")
                    d.putNumChild(10)
hjk's avatar
hjk committed
283
                    if d.isExpanded():
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
                        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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
            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
320
321
322
323
    d.putValue("%s/64 = %s" % (v, v/64.0))
    d.putNumChild(0)


hjk's avatar
hjk committed
324
325
326
327
328
329
330
331
332
333
def qdump__QFiniteStack(d, value):
    alloc = value["_alloc"]
    size = value["_size"]
    check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
    d.putItemCount(size)
    d.putNumChild(size)
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        d.putArrayData(innerType, value["_array"], size)

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# 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
349
350
#    Traceback (most recent call last): File "<string>", line 1,
#      in <module> RuntimeError: No type named N::S::E.
351
352
353
354
355
#  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
356
357
def qdump__QFlags(d, value):
    i = value["i"]
358
    try:
hjk's avatar
hjk committed
359
        enumType = templateArgument(value.type.unqualified(), 0)
360
361
362
        d.putValue("%s (%s)" % (i.cast(enumType), i))
    except:
        d.putValue("%s" % i)
hjk's avatar
hjk committed
363
364
365
    d.putNumChild(0)


366
367
368
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
369
def qdump__QHash(d, value):
hjk's avatar
hjk committed
370
371

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
372
373
374
375
        val = value.cast(hashDataType)
        bucket = val["buckets"]
        e = val.cast(hashNodeType)
        for n in xrange(val["numBuckets"] - 1, -1, -1):
hjk's avatar
hjk committed
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
            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()
        numBuckets = d["numBuckets"]
        start = (node["h"] % numBuckets) + 1
        bucket = d["buckets"] + start
392
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
393
394
395
396
397
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

hjk's avatar
hjk committed
398
399
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
400

hjk's avatar
hjk committed
401
402
    d_ptr = value["d"]
    e_ptr = value["e"]
403
    size = d_ptr["size"]
hjk's avatar
hjk committed
404
405
406
407

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

408
    check(0 <= size and size <= 100 * 1000 * 1000)
409
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
410

411
412
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
413
    if d.isExpanded():
414
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
415
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
416
        innerType = e_ptr.dereference().type
417
        childType = innerType
418
        if isCompact:
419
            childType = valueType
hjk's avatar
hjk committed
420
        with Children(d, size, maxNumChild=1000, childType=childType):
421
422
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
423
                with SubItem(d, i):
424
425
426
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
427
428
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
429
                        d.putItem(it)
430
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
431
432


hjk's avatar
hjk committed
433
434
435
436
437
def qdump__QHashNode(d, value):
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
    key = value["key"]
    val = value["value"]
hjk's avatar
hjk committed
438

439
440
441
442
443
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
444

445
    d.putNumChild(2)
hjk's avatar
hjk committed
446
    if d.isExpanded():
447
        with Children(d):
hjk's avatar
hjk committed
448
449
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
450
451


452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
def qHashIteratorHelper(d, value):
    typeName = str(value.type)
    hashType = lookupType(typeName[0:typeName.rfind("::")])
    keyType = templateArgument(hashType, 0)
    valueType = templateArgument(hashType, 1)
    d.putNumChild(1)
    d.putValue(" ")
    if d.isExpanded():
        with Children(d):
            typeName = "%sQHash<%s,%s>::Node" % (d.ns, keyType, valueType)
            node = value["i"].cast(lookupType(typeName).pointer())
            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
473
474
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
475
476
477
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
478
479
480
481
482
483
        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
484
    d.putNumChild(1)
hjk's avatar
hjk committed
485
    if d.isExpanded():
hjk's avatar
hjk committed
486
        with Children(d):
hjk's avatar
hjk committed
487
           d.putFields(data)
hjk's avatar
hjk committed
488
489


hjk's avatar
hjk committed
490
491
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
492
493
494
495
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
496
497
    size = end - begin
    check(size >= 0)
498
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
499
500

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
501
    innerType = templateArgument(value.type, 0)
502
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
503
504
505
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
506
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
507

508
509
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
510
    if d.isExpanded():
hjk's avatar
hjk committed
511
512
513
514
515
516
517
        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:
        isInternal = innerSize <= d_ptr.type.sizeof and d.isMovableType(innerType)
518
        dummyType = lookupType("void").pointer().pointer()
519
520
        innerTypePointer = innerType.pointer()
        p = gdb.Value(array).cast(dummyType) + begin
521
522
523
524
        if innerTypeIsPointer:
            inner = innerType.target()
        else:
            inner = innerType
525
        # about 0.5s / 1000 items
hjk's avatar
hjk committed
526
        with Children(d, size, maxNumChild=2000, childType=inner):
527
528
            for i in d.childRange():
                if isInternal:
hjk's avatar
hjk committed
529
                    d.putSubItem(i, p.cast(innerTypePointer).dereference())
530
                else:
hjk's avatar
hjk committed
531
                    d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference())
532
                p += 1
hjk's avatar
hjk committed
533

hjk's avatar
hjk committed
534
535
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
536

hjk's avatar
hjk committed
537
def qdump__QImage(d, value):
538
    try:
hjk's avatar
hjk committed
539
        painters = value["painters"]
540
    except:
hjk's avatar
hjk committed
541
        d.putPlainChildren(value)
542
        return
hjk's avatar
hjk committed
543
    check(0 <= painters and painters < 1000)
hjk's avatar
hjk committed
544
    d_ptr = value["d"]
hjk's avatar
hjk committed
545
    if isNull(d_ptr):
546
        d.putValue("(null)")
hjk's avatar
hjk committed
547
    else:
548
        checkSimpleRef(d_ptr["ref"])
549
        d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
550
551
    bits = d_ptr["data"]
    nbytes = d_ptr["nbytes"]
552
    d.putNumChild(0)
hjk's avatar
hjk committed
553
    #d.putNumChild(1)
hjk's avatar
hjk committed
554
    if d.isExpanded():
555
        with Children(d):
hjk's avatar
hjk committed
556
            with SubItem(d, "data"):
557
                d.putNoType()
558
559
                d.putNumChild(0)
                d.putValue("size: %s bytes" % nbytes);
hjk's avatar
hjk committed
560
    format = d.currentItemFormat()
561
    if format == 1:
562
        d.putDisplay(StopDisplay)
563
    elif format == 2:
hjk's avatar
hjk committed
564
565
566
567
        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.
            d.putField("editformat", 1)  # Magic marker for direct "QImage" data.
568
            d.put('%s="' % name)
hjk's avatar
hjk committed
569
570
571
            d.put("%08x" % int(d_ptr["width"]))
            d.put("%08x" % int(d_ptr["height"]))
            d.put("%08x" % int(d_ptr["format"]))
572
            p = bits.cast(lookupType("unsigned int").pointer())
hjk's avatar
hjk committed
573
574
575
            for i in xrange(nbytes / 4):
                d.put("%08x" % int(p.dereference()))
                p += 1
576
            d.put('",')
hjk's avatar
hjk committed
577
578
579
        else:
            # Write to an external file. Much faster ;-(
            file = tempfile.mkstemp(prefix="gdbpy_")
580
            filename = file[1].replace("\\", "\\\\")
581
            p = bits.cast(lookupType("unsigned char").pointer())
hjk's avatar
hjk committed
582
583
            gdb.execute("dump binary memory %s %s %s" %
                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
584
585
            d.putDisplay(DisplayImage, " %d %d %d %s"
                % (d_ptr["width"], d_ptr["height"], d_ptr["format"], filename))
hjk's avatar
hjk committed
586
587


hjk's avatar
hjk committed
588
589
590
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
591
    n = d_ptr["size"]
hjk's avatar
hjk committed
592
    check(0 <= n and n <= 100*1000*1000)
593
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
594
    d.putItemCount(n)
595
    d.putNumChild(n)
hjk's avatar
hjk committed
596
597
598
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
599
600
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
601
                d.putSubItem(i, p["t"])
602
                p = p["n"]
hjk's avatar
hjk committed
603

604
qqLocalesCount = None
hjk's avatar
hjk committed
605

hjk's avatar
hjk committed
606
def qdump__QLocale(d, value):
607
608
609
610
611
612
613
614
    # Check for uninitialized 'index' variable. Retrieve size of QLocale data array
    # from variable in qlocale.cpp (default: 368/Qt 4.8), 368 being 'System'.
    global qqLocalesCount
    if qqLocalesCount is None:
        try:
            qqLocalesCount = int(value(qtNamespace() + 'locale_data_size'))
        except:
            qqLocalesCount = 368
hjk's avatar
hjk committed
615
    index = int(value["p"]["index"])
616
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
617
    d.putStringValue(call(value, "name"))
618
619
620
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
621
622
623
624
625
626
627
    if d.isExpanded():
        with Children(d, childType=lookupType(d.ns + "QChar"), childNumChild=0):
            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
628
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
629
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
630
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
631
632
633
634
635
636
            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
637
638


hjk's avatar
hjk committed
639
def qdump__QMapNode(d, value):
640
641
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
642
643
644
645
646
647
648
649
650
    if d.isExpanded():
        with Children(d):
            d.putSubItem("key", value["key"])
            d.putSubItem("value", value["value"])


def qdumpHelper__QMap(d, value, forceLong):
    d_ptr = value["d"].dereference()
    e_ptr = value["e"].dereference()
hjk's avatar
hjk committed
651
652
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
653
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
654
655

    d.putItemCount(n)
656
    d.putNumChild(n)
hjk's avatar
hjk committed
657
    if d.isExpanded():
hjk's avatar
hjk committed
658
659
660
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
661
662
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
663
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
664
665
666
667
668
669

        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 *)
670
671
672
        nodeType = lookupType(d.ns + "QMapNode<%s, %s>" % (keyType, valueType))
        payloadSize = nodeType.sizeof - 2 * lookupType("void").pointer().sizeof
        charPtr = lookupType("char").pointer()
hjk's avatar
hjk committed
673

674
        if isCompact:
675
676
677
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
678

hjk's avatar
hjk committed
679
        with Children(d, n, childType=innerType):
680
681
682
683
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
684
                with SubItem(d, i):
685
                    if isCompact:
686
                        #d.putType(valueType)
hjk's avatar
hjk committed
687
                        if forceLong:
688
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
689
                        else:
690
691
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
692
                    else:
hjk's avatar
hjk committed
693
                        d.putItem(node)
694
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
695
696


697
698
699
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
700
701
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
702

703
704
705
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
706
707
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
708
709
710
711
712
713
714
715
716
717
718
719
720


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
721
722
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
723
    try:
724
        privateTypeName = d.ns + "QObjectPrivate"
725
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
726
727
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
728
729
        #warn("D_PTR: %s " % d_ptr)
        objectName = d_ptr["objectName"]
730
    except:
hjk's avatar
hjk committed
731
        d.putPlainChildren(value)
732
        return
hjk's avatar
hjk committed
733
    #warn("SMO: %s " % staticMetaObject)
734
735
736
737
738
739
740
    #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)

741
742
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
743
        #d.putValue(cleanAddress(value.address))
744
        d.putPlainChildren(value)
hjk's avatar
hjk committed
745
        if d.isExpanded():
746
            with Children(d):
hjk's avatar
hjk committed
747
                d.putFields(value)
748
        return
hjk's avatar
hjk committed
749
    #warn("OBJECTNAME: %s " % objectName)
750
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
751
    mo = d_ptr["metaObject"]
752
753
754
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
755
756
757
758
759
760
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
761
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
762
763
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
764
765
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
766
767
    #d.putValue("")
    d.putStringValue(objectName)
hjk's avatar
hjk committed
768
    #QSignalMapper::staticMetaObject
769
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
770
    d.putNumChild(4)
hjk's avatar
hjk committed
771
    if d.isExpanded():
772
      with Children(d):
773

hjk's avatar
hjk committed
774
        # Local data.
775
776
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
777
              with SubItem(d, "data"):
778
                d.putValue(" ")
779
                d.putNoType()
780
                d.putNumChild(1)
hjk's avatar
hjk committed
781
                if d.isExpanded():
782
                    with Children(d):
hjk's avatar
hjk committed
783
                        d.putFields(d_ptr, False)
784
785


hjk's avatar
hjk committed
786
        d.putFields(value)
787
        # Parent and children.
hjk's avatar
hjk committed
788
789
790
        if stripClassTag(str(value.type)) == d.ns + "QObject":
            d.putSubItem("parent", d_ptr["parent"])
            d.putSubItem("children", d_ptr["children"])
hjk's avatar
hjk committed
791

792
        # Properties.
hjk's avatar
hjk committed
793
        with SubItem(d, "properties"):
794
            # Prolog
795
796
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
797
                dynamicPropertyCount = 0
798
            else:
799
                extraDataType = lookupType(
800
801
802
803
804
805
806
807
808
                    d.ns + "QObjectPrivate::ExtraData").pointer()
                extraData = extraData.cast(extraDataType)
                ed = extraData.dereference()
                names = ed["propertyNames"]
                values = ed["propertyValues"]
                #userData = ed["userData"]
                namesBegin = names["d"]["begin"]
                namesEnd = names["d"]["end"]
                namesArray = names["d"]["array"]
809
810
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
811
            #staticPropertyCount = call(mo, "propertyCount")
812
            staticPropertyCount = metaData[6]
813
814
815
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

816
            d.putNoType()
817
818
819
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
820
            if d.isExpanded():
821
822
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
823
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
824
825
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
826
                gdb.execute("set $d.d.is_shared = 0")
827

hjk's avatar
hjk committed
828
                with Children(d):
829
                    # Dynamic properties.
830
831
832
833
834
835
836
837
838
839
                    if dynamicPropertyCount != 0:
                        dummyType = lookupType("void").pointer().pointer()
                        namesType = lookupType(d.ns + "QByteArray")
                        valuesBegin = values["d"]["begin"]
                        valuesEnd = values["d"]["end"]
                        valuesArray = values["d"]["array"]
                        valuesType = lookupType(d.ns + "QVariant")
                        p = namesArray.cast(dummyType) + namesBegin
                        q = valuesArray.cast(dummyType) + valuesBegin
                        for i in xrange(dynamicPropertyCount):
hjk's avatar
hjk committed
840
                            with SubItem(d, i):
841
842
843
844
845
846
                                pp = p.cast(namesType.pointer()).dereference();
                                d.putField("key", encodeByteArray(pp))
                                d.putField("keyencoded", Hex2EncodedLatin1)
                                qq = q.cast(valuesType.pointer().pointer())
                                qq = qq.dereference();
                                d.putField("addr", cleanAddress(qq))
847
848
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
849
850
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
851
                                d.putBetterType(t)
852
853
                            p += 1
                            q += 1
854
855
856
857

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
858
                      with NoAddress(d):
hjk's avatar
hjk committed
859
860
861
862
863
864
                        offset = propertyData + 3 * i
                        propertyName = extractCString(metaStringData,
                                                      metaData[offset])
                        propertyType = extractCString(metaStringData,
                                                      metaData[offset + 1])
                        with SubItem(d, propertyName):
865
866
867
868
                            #flags = metaData[offset + 2]
                            #warn("FLAGS: %s " % flags)
                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
hjk's avatar
hjk committed
869
                            #     % (d.ns, value.address, propertyName)
hjk's avatar
hjk committed
870
                            #exp = '"((\'%sQObject\'*)%s)"' %
hjk's avatar
hjk committed
871
                            #(d.ns, value.address,)
872
                            #warn("EXPRESSION:  %s" % exp)
hjk's avatar
hjk committed
873
                            prop = call(value, "property",
hjk's avatar
hjk committed
874
                                str(cleanAddress(metaStringData + metaData[offset])))
hjk's avatar
hjk committed
875
                            value1 = prop["d"]
876
                            #warn("   CODE: %s" % value1["type"])
hjk's avatar
hjk committed
877
878
                            # Type 1 and 2 are bool and int.
                            # Try to save a few cycles in this case:
879
                            if int(value1["type"]) > 2:
hjk's avatar
hjk committed
880
                                # Poke back prop
hjk's avatar
hjk committed
881
882
883
884
885
886
                                gdb.execute("set $d.d.data.ull = %s"
                                        % value1["data"]["ull"])
                                gdb.execute("set $d.d.type = %s"
                                        % value1["type"])
                                gdb.execute("set $d.d.is_null = %s"
                                        % value1["is_null"])
hjk's avatar
hjk committed
887
                                prop = parseAndEvaluate("$d").dereference()
hjk's avatar
hjk committed
888
                            val, inner, innert, handled = \
hjk's avatar
hjk committed
889
                                qdumpHelper__QVariant(d, prop)
hjk's avatar
hjk committed
890
891
892
893

                            if handled:
                                pass
                            elif len(inner):
894
895
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
896
                                d.putItem(val)
897
898
                            else:
                                # User types.
899
900
                           #    func = "typeToName(('%sQVariant::Type')%d)"
                           #       % (d.ns, variantType)
hjk's avatar
hjk committed
901
                           #    type = str(call(value, func))
902
903
                           #    type = type[type.find('"') + 1 : type.rfind('"')]
                           #    type = type.replace("Q", d.ns + "Q") # HACK!
hjk's avatar
hjk committed
904
                           #    data = call(value, "constData")
905
906
                           #    tdata = data.cast(lookupType(type).pointer())
                           #      .dereference()
907
908
909
                           #    d.putValue("(%s)" % tdata.type)
                           #    d.putType(tdata.type)
                           #    d.putNumChild(1)
hjk's avatar
hjk committed
910
                           #    if d.isExpanded():
911
                           #        with Children(d):
hjk's avatar
hjk committed
912
                           #           d.putSubItem("data", tdata)
913
                                warn("FIXME: CUSTOM QOBJECT PROPERTY: %s %s"
914
915
916
917
918
                                    % (propertyType, innert))
                                d.putType(propertyType)
                                d.putValue("...")
                                d.putNumChild(0)

919
        # Connections.
hjk's avatar
hjk committed
920
        with SubItem(d, "connections"):
921
            d.putNoType()
922
923
924