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


hjk's avatar
hjk committed
230
def qdump__QFile(d, value):
hjk's avatar
hjk committed
231
232
233
234
235
236
237
    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
238
    d.putNumChild(1)
hjk's avatar
hjk committed
239
240
    if d.isExpanded():
        with Children(d):
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)


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


356
357
358
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
359
def qdump__QHash(d, value):
hjk's avatar
hjk committed
360
361

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

hjk's avatar
hjk committed
388
389
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
390

hjk's avatar
hjk committed
391
392
    d_ptr = value["d"]
    e_ptr = value["e"]
393
    size = d_ptr["size"]
hjk's avatar
hjk committed
394
395
396
397

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

398
    check(0 <= size and size <= 100 * 1000 * 1000)
399
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
400

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


hjk's avatar
hjk committed
423
424
425
426
427
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
428

429
430
431
432
433
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
434

435
    d.putNumChild(2)
hjk's avatar
hjk committed
436
    if d.isExpanded():
437
        with Children(d):
hjk's avatar
hjk committed
438
439
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
440
441


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


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

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
473
    innerType = templateArgument(value.type, 0)
474
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
475
476
477
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
478
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
479

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

hjk's avatar
hjk committed
506
507
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
508

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


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

576
qqLocalesCount = None
hjk's avatar
hjk committed
577

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


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

    d.putItemCount(n)
628
    d.putNumChild(n)
hjk's avatar
hjk committed
629
    if d.isExpanded():
hjk's avatar
hjk committed
630
631
632
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
633
634
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
635
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
636
637
638
639
640
641

        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 *)
642
643
644
        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
645

646
        if isCompact:
647
648
649
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
650

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


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

hjk's avatar
hjk committed
672
673
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
674

675
676
677
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
678
679
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
680
681
682
683
684
685
686
687
688
689
690
691
692


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

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

hjk's avatar
hjk committed
746
        # Local data.
747
748
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
749
              with SubItem(d, "data"):
750
                d.putValue(" ")
751
                d.putNoType()
752
                d.putNumChild(1)
hjk's avatar
hjk committed
753
                if d.isExpanded():
754
                    with Children(d):
hjk's avatar
hjk committed
755
                        d.putFields(d_ptr, False)
756
757


hjk's avatar
hjk committed
758
        d.putFields(value)
759
        # Parent and children.
hjk's avatar
hjk committed
760
761
762
        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
763

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

hjk's avatar
hjk committed
783
            #staticPropertyCount = call(mo, "propertyCount")
784
            staticPropertyCount = metaData[6]
785
786
787
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

788
            d.putNoType()
789
790
791
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
792
            if d.isExpanded():
793
794
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
795
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
796
797
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
798
                gdb.execute("set $d.d.is_shared = 0")
799

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

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

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

891
        # Connections.
hjk's avatar
hjk committed
892
        with SubItem(d, "connections"):
893
            d.putNoType()
894
895
896
897
            connections = d_ptr["connectionLists"]
            connectionListCount = 0
            if not isNull(connections):
                connectionListCount = connections["d"]["size"]
898
            d.putItemCount(connectionListCount, 0)
899
            d.putNumChild(connectionListCount)
hjk's avatar
hjk committed
900
            if d.isExpanded():
901
                pp = 0
902
903
                with Children(d):