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

def mapForms():
    return "Normal,Compact"

def mapCompact(format, keyType, valueType):
    if format == 2:
        return True # Compact.
    return isSimpleType(keyType) and isSimpleType(valueType)


hjk's avatar
hjk committed
20
21
def qdump__QAtomicInt(d, value):
    d.putValue(value["_q_value"])
hjk's avatar
hjk committed
22
23
24
    d.putNumChild(0)


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


hjk's avatar
hjk committed
30
31
32
def qdump__QBasicAtomicPointer(d, value):
    d.putType(value.type)
    p = cleanAddress(value["_q_value"])
33
    d.putValue(p)
hjk's avatar
hjk committed
34
    d.putPointerValue(value.address)
35
    d.putNumChild(p)
hjk's avatar
hjk committed
36
    if d.isExpanded():
37
        with Children(d):
hjk's avatar
hjk committed
38
           d.putItem(value["_q_value"])
39
40


hjk's avatar
hjk committed
41
42
43
def qdump__QByteArray(d, value):
    d.putByteArrayValue(value)
    data, size, alloc = qByteArrayData(value)
44
    d.putNumChild(size)
hjk's avatar
hjk committed
45

hjk's avatar
hjk committed
46
    if d.isExpanded():
47
        innerType = lookupType("char")
hjk's avatar
hjk committed
48
49
        with Children(d, numChild=size, maxNumChild=1000, childType=innerType,
                addrBase=cleanAddress(data), addrStep=1):
50
51
            p = gdb.Value(data.cast(innerType.pointer()))
            for i in d.childRange():
hjk's avatar
hjk committed
52
                d.put('{value="%d"},' % p.dereference())
53
                p += 1
hjk's avatar
hjk committed
54
55


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


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

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

104
105
106
def qform__QModelIndex():
    return "Normal,Enhanced"

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

    try:
        # Access DisplayRole as value
hjk's avatar
hjk committed
130
131
        val = parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_))
        v = val["d"]["data"]["ptr"]
132
133
134
135
136
137
        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
138
        if d.isExpanded():
139
140
141
142
            with Children(d):
                i = 0
                for row in xrange(rowCount):
                    for column in xrange(columnCount):
hjk's avatar
hjk committed
143
                        with UnnamedSubItem(d, i):
144
145
146
                            d.putName("[%s, %s]" % (row, column))
                            mi2 = parseAndEvaluate("%s.index(%d,%d,%s)"
                                % (mm_, row, column, mi_))
hjk's avatar
hjk committed
147
                            d.putItem(mi2)
148
                            i = i + 1
hjk's avatar
hjk committed
149
150
                #d.putCallItem("parent", val, "parent")
                #with SubItem(d, "model"):
151
152
153
154
155
156
                #    d.putValue(m)
                #    d.putType(d.ns + "QAbstractItemModel*")
                #    d.putNumChild(1)
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
157
        if d.isExpanded():
158
159
160
161
            with Children(d):
                pass
    #gdb.execute("call free($mi)")

hjk's avatar
hjk committed
162

hjk's avatar
hjk committed
163
def qdump__QDate(d, value):
164
    d.putValue(value["jd"], JulianDate)
165
    d.putNumChild(1)
hjk's avatar
hjk committed
166
    if d.isExpanded():
167
        qt = d.ns + "Qt::"
168
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
169
170
171
172
        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
173
                qt + "SystemLocaleDate")
hjk's avatar
hjk committed
174
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
hjk's avatar
hjk committed
175
176


hjk's avatar
hjk committed
177
def qdump__QTime(d, value):
178
    d.putValue(value["mds"], MillisecondsSinceMidnight)
179
    d.putNumChild(1)
hjk's avatar
hjk committed
180
    if d.isExpanded():
181
        qt = d.ns + "Qt::"
182
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
183
184
185
186
        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
187
                 qt + "SystemLocaleDate")
hjk's avatar
hjk committed
188
189
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
            d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
190
191


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


hjk's avatar
hjk committed
224
def qdump__QFile(d, value):
hjk's avatar
hjk committed
225
226
227
228
229
230
231
    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
232
    d.putNumChild(1)
hjk's avatar
hjk committed
233
234
    if d.isExpanded():
        with Children(d):
hjk's avatar
hjk committed
235
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
236
237


hjk's avatar
hjk committed
238
def qdump__QFileInfo(d, value):
239
    try:
hjk's avatar
hjk committed
240
        d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3])
241
    except:
hjk's avatar
hjk committed
242
        d.putPlainChildren(value)
243
        return
hjk's avatar
hjk committed
244
    d.putNumChild(1)
hjk's avatar
hjk committed
245
246
247
248
249
250
251
252
253
    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")
254
255
            if False:
                #ifdef Q_OS_MACX
hjk's avatar
hjk committed
256
257
258
259
                d.putCallItem("isBundle", value, "isBundle")
                d.putCallItem("bundleName", value, "bundleName")
            d.putCallItem("fileName", value, "fileName")
            d.putCallItem("filePath", value, "filePath")
260
            # Crashes gdb (archer-tromey-python, at dad6b53fe)
hjk's avatar
hjk committed
261
262
263
            #d.putCallItem("group", value, "group")
            #d.putCallItem("owner", value, "owner")
            d.putCallItem("path", value, "path")
264

hjk's avatar
hjk committed
265
266
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
267
268

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


318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# 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
333
334
#    Traceback (most recent call last): File "<string>", line 1,
#      in <module> RuntimeError: No type named N::S::E.
335
336
337
338
339
#  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
340
341
def qdump__QFlags(d, value):
    i = value["i"]
342
    try:
hjk's avatar
hjk committed
343
        enumType = templateArgument(value.type.unqualified(), 0)
344
345
346
        d.putValue("%s (%s)" % (i.cast(enumType), i))
    except:
        d.putValue("%s" % i)
hjk's avatar
hjk committed
347
348
349
    d.putNumChild(0)


350
351
352
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
353
def qdump__QHash(d, value):
hjk's avatar
hjk committed
354
355

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
356
357
358
359
        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
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
            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
376
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
377
378
379
380
381
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

hjk's avatar
hjk committed
382
383
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
384

hjk's avatar
hjk committed
385
386
    d_ptr = value["d"]
    e_ptr = value["e"]
387
    size = d_ptr["size"]
hjk's avatar
hjk committed
388
389
390
391

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

392
    check(0 <= size and size <= 100 * 1000 * 1000)
393
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
394

395
396
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
397
    if d.isExpanded():
398
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
399
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
400
        innerType = e_ptr.dereference().type
401
        childType = innerType
402
        if isCompact:
403
            childType = valueType
hjk's avatar
hjk committed
404
        with Children(d, size, maxNumChild=1000, childType=childType):
405
406
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
407
                with SubItem(d, i):
408
409
410
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
411
412
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
413
                        d.putItem(it)
414
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
415
416


hjk's avatar
hjk committed
417
418
419
420
421
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
422

423
424
425
426
427
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
428

429
    d.putNumChild(2)
hjk's avatar
hjk committed
430
    if d.isExpanded():
431
        with Children(d):
hjk's avatar
hjk committed
432
433
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
434
435


hjk's avatar
hjk committed
436
437
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
438
439
440
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
441
442
443
444
445
446
        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
447
    d.putNumChild(1)
hjk's avatar
hjk committed
448
    if d.isExpanded():
hjk's avatar
hjk committed
449
        with Children(d):
hjk's avatar
hjk committed
450
           d.putFields(data)
hjk's avatar
hjk committed
451
452


hjk's avatar
hjk committed
453
454
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
455
456
457
458
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
459
460
    size = end - begin
    check(size >= 0)
hjk's avatar
hjk committed
461
462
463
    #if n > 0:
    #    checkAccess(&list.front())
    #    checkAccess(&list.back())
464
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
465
466

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
467
    innerType = templateArgument(value.type, 0)
468
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
469
470
471
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
472
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
473

474
475
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
476
    if d.isExpanded():
hjk's avatar
hjk committed
477
478
479
480
481
482
483
        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)
484
        dummyType = lookupType("void").pointer().pointer()
485
486
        innerTypePointer = innerType.pointer()
        p = gdb.Value(array).cast(dummyType) + begin
487
488
489
490
        if innerTypeIsPointer:
            inner = innerType.target()
        else:
            inner = innerType
491
        # about 0.5s / 1000 items
hjk's avatar
hjk committed
492
        with Children(d, size, maxNumChild=2000, childType=inner):
493
494
            for i in d.childRange():
                if isInternal:
hjk's avatar
hjk committed
495
                    d.putSubItem(i, p.cast(innerTypePointer).dereference())
496
                else:
hjk's avatar
hjk committed
497
                    d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference())
498
                p += 1
hjk's avatar
hjk committed
499

hjk's avatar
hjk committed
500
501
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
502

hjk's avatar
hjk committed
503
def qdump__QImage(d, value):
504
    try:
hjk's avatar
hjk committed
505
        painters = value["painters"]
506
    except:
hjk's avatar
hjk committed
507
        d.putPlainChildren(value)
508
        return
hjk's avatar
hjk committed
509
    check(0 <= painters and painters < 1000)
hjk's avatar
hjk committed
510
    d_ptr = value["d"]
hjk's avatar
hjk committed
511
    if isNull(d_ptr):
512
        d.putValue("(null)")
hjk's avatar
hjk committed
513
    else:
514
        checkRef(d_ptr["ref"])
515
        d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
516
517
    bits = d_ptr["data"]
    nbytes = d_ptr["nbytes"]
518
    d.putNumChild(0)
hjk's avatar
hjk committed
519
    #d.putNumChild(1)
hjk's avatar
hjk committed
520
    if d.isExpanded():
521
        with Children(d):
hjk's avatar
hjk committed
522
            with SubItem(d, "data"):
523
                d.putNoType()
524
525
                d.putNumChild(0)
                d.putValue("size: %s bytes" % nbytes);
hjk's avatar
hjk committed
526
    format = d.currentItemFormat()
527
    if format == 1:
528
        d.putDisplay(StopDisplay)
529
    elif format == 2:
hjk's avatar
hjk committed
530
531
532
533
        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.
534
            d.put('%s="' % name)
hjk's avatar
hjk committed
535
536
537
            d.put("%08x" % int(d_ptr["width"]))
            d.put("%08x" % int(d_ptr["height"]))
            d.put("%08x" % int(d_ptr["format"]))
538
            p = bits.cast(lookupType("unsigned int").pointer())
hjk's avatar
hjk committed
539
540
541
            for i in xrange(nbytes / 4):
                d.put("%08x" % int(p.dereference()))
                p += 1
542
            d.put('",')
hjk's avatar
hjk committed
543
544
545
        else:
            # Write to an external file. Much faster ;-(
            file = tempfile.mkstemp(prefix="gdbpy_")
546
            filename = file[1].replace("\\", "\\\\")
547
            p = bits.cast(lookupType("unsigned char").pointer())
hjk's avatar
hjk committed
548
549
            gdb.execute("dump binary memory %s %s %s" %
                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
550
551
            d.putDisplay(DisplayImage, " %d %d %d %s"
                % (d_ptr["width"], d_ptr["height"], d_ptr["format"], filename))
hjk's avatar
hjk committed
552
553


hjk's avatar
hjk committed
554
555
556
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
557
    n = d_ptr["size"]
hjk's avatar
hjk committed
558
    check(0 <= n and n <= 100*1000*1000)
559
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
560
    d.putItemCount(n)
561
    d.putNumChild(n)
hjk's avatar
hjk committed
562
563
564
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
565
566
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
567
                d.putSubItem(i, p["t"])
568
                p = p["n"]
hjk's avatar
hjk committed
569

570
qqLocalesCount = None
hjk's avatar
hjk committed
571

hjk's avatar
hjk committed
572
def qdump__QLocale(d, value):
573
574
575
576
577
578
579
580
    # 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
581
    index = int(value["p"]["index"])
582
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
583
    d.putStringValue(call(value, "name"))
584
585
586
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
587
588
589
590
591
592
593
    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
594
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
595
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
596
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
597
598
599
600
601
602
            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
603
604


hjk's avatar
hjk committed
605
def qdump__QMapNode(d, value):
606
607
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
608
609
610
611
612
613
614
615
616
    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
617
618
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
619
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
620
621

    d.putItemCount(n)
622
    d.putNumChild(n)
hjk's avatar
hjk committed
623
    if d.isExpanded():
hjk's avatar
hjk committed
624
625
626
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
627
628
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
629
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
630
631
632
633
634
635

        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 *)
636
637
638
        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
639

640
        if isCompact:
641
642
643
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
644

hjk's avatar
hjk committed
645
        with Children(d, n, childType=innerType):
646
647
648
649
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
650
                with SubItem(d, i):
651
                    if isCompact:
652
                        #d.putType(valueType)
hjk's avatar
hjk committed
653
                        if forceLong:
654
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
655
                        else:
656
657
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
658
                    else:
hjk's avatar
hjk committed
659
                        d.putItem(node)
660
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
661
662


663
664
665
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
666
667
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
668

669
670
671
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
672
673
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
674
675
676
677
678
679
680
681
682
683
684
685
686


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
687
688
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
689
    try:
690
        privateTypeName = d.ns + "QObjectPrivate"
691
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
692
693
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
694
695
        #warn("D_PTR: %s " % d_ptr)
        objectName = d_ptr["objectName"]
696
    except:
hjk's avatar
hjk committed
697
        d.putPlainChildren(value)
698
        return
hjk's avatar
hjk committed
699
    #warn("SMO: %s " % staticMetaObject)
700
701
702
703
704
705
706
    #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)

707
708
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
709
        #d.putValue(cleanAddress(value.address))
710
        d.putPlainChildren(value)
hjk's avatar
hjk committed
711
        if d.isExpanded():
712
            with Children(d):
hjk's avatar
hjk committed
713
                d.putFields(value)
714
        return
hjk's avatar
hjk committed
715
    #warn("OBJECTNAME: %s " % objectName)
716
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
717
    mo = d_ptr["metaObject"]
718
719
720
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
721
722
723
724
725
726
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
727
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
728
729
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
730
731
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
732
733
    #d.putValue("")
    d.putStringValue(objectName)
hjk's avatar
hjk committed
734
    #QSignalMapper::staticMetaObject
735
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
736
    d.putNumChild(4)
hjk's avatar
hjk committed
737
    if d.isExpanded():
738
      with Children(d):
739

hjk's avatar
hjk committed
740
        # Local data.
741
742
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
743
              with SubItem(d, "data"):
744
                d.putValue(" ")
745
                d.putNoType()
746
                d.putNumChild(1)
hjk's avatar
hjk committed
747
                if d.isExpanded():
748
                    with Children(d):
hjk's avatar
hjk committed
749
                        d.putFields(d_ptr, False)
750
751


hjk's avatar
hjk committed
752
        d.putFields(value)
753
        # Parent and children.
hjk's avatar
hjk committed
754
755
756
        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
757

758
        # Properties.
hjk's avatar
hjk committed
759
        with SubItem(d, "properties"):
760
            # Prolog
761
762
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
763
                dynamicPropertyCount = 0
764
            else:
765
                extraDataType = lookupType(
766
767
768
769
770
771
772
773
774
                    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"]
775
776
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
777
            #staticPropertyCount = call(mo, "propertyCount")
778
            staticPropertyCount = metaData[6]
779
780
781
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

782
            d.putNoType()
783
784
785
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
786
            if d.isExpanded():
787
788
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
789
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
790
791
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
792
                gdb.execute("set $d.d.is_shared = 0")
793

hjk's avatar
hjk committed
794
                with Children(d):
795
                    # Dynamic properties.
796
797
798
799
800
801
802
803
804
805
                    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
806
                            with SubItem(d, i):
807
808
809
810
811
812
                                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))
813
814
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
815
816
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
817
                                d.putBetterType(t)
818
819
                            p += 1
                            q += 1
820
821
822
823

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
824
                      with NoAddress(d):
hjk's avatar
hjk committed
825
826
827
828
829
830
                        offset = propertyData + 3 * i
                        propertyName = extractCString(metaStringData,
                                                      metaData[offset])
                        propertyType = extractCString(metaStringData,
                                                      metaData[offset + 1])
                        with SubItem(d, propertyName):
831
832
833
834
                            #flags = metaData[offset + 2]
                            #warn("FLAGS: %s " % flags)
                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
hjk's avatar
hjk committed
835
                            #     % (d.ns, value.address, propertyName)
hjk's avatar
hjk committed
836
                            #exp = '"((\'%sQObject\'*)%s)"' %
hjk's avatar
hjk committed
837
                            #(d.ns, value.address,)
838
                            #warn("EXPRESSION:  %s" % exp)
hjk's avatar
hjk committed
839
                            prop = call(value, "property",
hjk's avatar
hjk committed
840
                                str(cleanAddress(metaStringData + metaData[offset])))
hjk's avatar
hjk committed
841
                            value1 = prop["d"]
842
                            #warn("   CODE: %s" % value1["type"])
hjk's avatar
hjk committed
843
844
                            # Type 1 and 2 are bool and int.
                            # Try to save a few cycles in this case:
845
                            if int(value1["type"]) > 2:
hjk's avatar
hjk committed
846
                                # Poke back prop
hjk's avatar
hjk committed
847
848
849
850
851
852
                                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
853
                                prop = parseAndEvaluate("$d").dereference()
hjk's avatar
hjk committed
854
                            val, inner, innert, handled = \
hjk's avatar
hjk committed
855
                                qdumpHelper__QVariant(d, prop)
hjk's avatar
hjk committed
856
857
858
859

                            if handled:
                                pass
                            elif len(inner):
860
861
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
862
                                d.putItem(val)
863
864
                            else:
                                # User types.
865
866
                           #    func = "typeToName(('%sQVariant::Type')%d)"
                           #       % (d.ns, variantType)
hjk's avatar
hjk committed
867
                           #    type = str(call(value, func))
868
869
                           #    type = type[type.find('"') + 1 : type.rfind('"')]
                           #    type = type.replace("Q", d.ns + "Q") # HACK!
hjk's avatar
hjk committed
870
                           #    data = call(value, "constData")
871
872
                           #    tdata = data.cast(lookupType(type).pointer())
                           #      .dereference()
873
874
875
                           #    d.putValue("(%s)" % tdata.type)
                           #    d.putType(tdata.type)
                           #    d.putNumChild(1)
hjk's avatar
hjk committed
876
                           #    if d.isExpanded():
877
                           #        with Children(d):
hjk's avatar
hjk committed
878
                           #           d.putSubItem("data", tdata)
879
                                warn("FIXME: CUSTOM QOBJECT PROPERTY: %s %s"
880
881
882
883
884
                                    % (propertyType, innert))
                                d.putType(propertyType)
                                d.putValue("...")
                                d.putNumChild(0)

885
        # Connections.
hjk's avatar
hjk committed
886
        with SubItem(d, "connections"):
887
            d.putNoType()
888
889
890
891
            connections = d_ptr["connectionLists"]
            connectionListCount = 0
            if not isNull(connections):
                connectionListCount = connections["d"]["size"]
892
            d.putItemCount(connectionListCount, 0)
893
            d.putNumChild(connectionListCount)
hjk's avatar
hjk committed
894
            if d.isExpanded():
895
                pp = 0
896
897
                with Children(d):
                    vectorType = connections.type.target().fields()[0].type
898
                    innerType = templateArgument(vectorType, 0)
899
900
901
902
903
                    # Should check:  innerType == ns::QObjectPrivate::ConnectionList
                    p = gdb.Value(connections["p"]["array"]).cast(innerType.pointer())
                    for i in xrange(connectionListCount):
                        first = p.dereference()["first"]
                        while not isNull(first):
904
905
906
907
908
                            with SubItem(d, pp):
                                connection = first.dereference()
                                d.putItem(connection)
                                d.putValue(connection["callFunction"])
                            first = first["nextConnectionList"]
909
910
911
912
913
                            # We need to enforce some upper limit.
                            pp += 1
                            if pp > 1000:
                                break
                        p += 1
914
915
                if pp < 1000:
                    d.putItemCount(pp)
916

hjk's avatar
hjk committed