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


46
47
48
def qform__QByteArray():
    return "Inline,As Latin1 in Separate Window,As UTF-8 in Separate Window"

hjk's avatar
hjk committed
49
50
51
def qdump__QByteArray(d, value):
    d.putByteArrayValue(value)
    data, size, alloc = qByteArrayData(value)
52
    d.putNumChild(size)
53
54
55
56
57
58
59
60
61
    format = d.currentItemFormat()
    if format == 1:
        d.putDisplay(StopDisplay)
    elif format == 2:
        d.putField("editformat", 5)
        d.putField("editvalue", encodeByteArray(value))
    elif format == 3:
        d.putField("editformat", 6)
        d.putField("editvalue", encodeByteArray(value))
hjk's avatar
hjk committed
62
    if d.isExpanded():
63
        d.putArrayData(lookupType("char"), data, size)
hjk's avatar
hjk committed
64
65


hjk's avatar
hjk committed
66
67
def qdump__QChar(d, value):
    ucs = int(value["ucs"])
68
    d.putValue("'%c' (%d)" % (printableChar(ucs), ucs))
hjk's avatar
hjk committed
69
70
71
    d.putNumChild(0)


hjk's avatar
hjk committed
72
def qform__QAbstractItemModel():
73
    return "Normal,Enhanced"
74

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

114
115
116
def qform__QModelIndex():
    return "Normal,Enhanced"

hjk's avatar
hjk committed
117
def qdump__QModelIndex(d, value):
118
119
120
121
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
hjk's avatar
hjk committed
122
123
124
125
    r = value["r"]
    c = value["c"]
    p = value["p"]
    m = value["m"]
126
127
    mm = m.dereference()
    mm = mm.cast(mm.type.unqualified())
128
    try:
129
130
131
        mi = makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
        mm_ = makeExpression(mm)
        mi_ = makeExpression(mi)
132
133
134
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
    except:
hjk's avatar
hjk committed
135
        d.putPlainChildren(value)
136
        return
137
138
139

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

hjk's avatar
hjk committed
172

hjk's avatar
hjk committed
173
def qdump__QDate(d, value):
174
    d.putValue(value["jd"], JulianDate)
175
    d.putNumChild(1)
hjk's avatar
hjk committed
176
    if d.isExpanded():
177
        qt = d.ns + "Qt::"
178
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
179
180
181
182
        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
183
                qt + "SystemLocaleDate")
hjk's avatar
hjk committed
184
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
hjk's avatar
hjk committed
185
186


hjk's avatar
hjk committed
187
def qdump__QTime(d, value):
188
    d.putValue(value["mds"], MillisecondsSinceMidnight)
189
    d.putNumChild(1)
hjk's avatar
hjk committed
190
    if d.isExpanded():
191
        qt = d.ns + "Qt::"
192
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
193
194
195
196
        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
197
                 qt + "SystemLocaleDate")
hjk's avatar
hjk committed
198
199
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
            d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
200
201


hjk's avatar
hjk committed
202
def qdump__QDateTime(d, value):
203
204
    try:
        # Fails without debug info.
205
        p = value["d"]["d"].dereference()
206
    except:
hjk's avatar
hjk committed
207
        d.putPlainChildren(value)
208
        return
209
210
    d.putValue("%s/%s" % (p["date"]["jd"], p["time"]["mds"]),
        JulianDateAndMillisecondsSinceMidnight)
211
    d.putNumChild(1)
hjk's avatar
hjk committed
212
    if d.isExpanded():
213
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
214
        with Children(d):
215
            qt = d.ns + "Qt::"
hjk's avatar
hjk committed
216
217
218
219
220
221
222
223
224
225
            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
226
    d.putNumChild(1)
227
228
229
230
231
232
233
    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
234
235
236
237
    if d.isExpanded():
        with Children(d):
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
hjk's avatar
hjk committed
238
239


hjk's avatar
hjk committed
240
def qdump__QFile(d, value):
hjk's avatar
hjk committed
241
242
243
244
245
246
247
    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
248
    d.putNumChild(1)
hjk's avatar
hjk committed
249
250
    if d.isExpanded():
        with Children(d):
251
252
            base = value.type.fields()[0].type
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
253
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
254
255


hjk's avatar
hjk committed
256
def qdump__QFileInfo(d, value):
257
    try:
hjk's avatar
hjk committed
258
        d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3])
259
    except:
hjk's avatar
hjk committed
260
        d.putPlainChildren(value)
261
        return
hjk's avatar
hjk committed
262
    d.putNumChild(1)
hjk's avatar
hjk committed
263
264
265
266
267
268
269
270
271
    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")
272
273
            if False:
                #ifdef Q_OS_MACX
hjk's avatar
hjk committed
274
275
276
277
                d.putCallItem("isBundle", value, "isBundle")
                d.putCallItem("bundleName", value, "bundleName")
            d.putCallItem("fileName", value, "fileName")
            d.putCallItem("filePath", value, "filePath")
278
            # Crashes gdb (archer-tromey-python, at dad6b53fe)
hjk's avatar
hjk committed
279
280
281
            #d.putCallItem("group", value, "group")
            #d.putCallItem("owner", value, "owner")
            d.putCallItem("path", value, "path")
282

hjk's avatar
hjk committed
283
284
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
285
286

            #QFile::Permissions permissions () const
hjk's avatar
hjk committed
287
            perms = call(value, "permissions")
288
289
290
            if perms is None:
                d.putValue("<not available>")
            else:
hjk's avatar
hjk committed
291
                with SubItem(d, "permissions"):
292
293
294
                    d.putValue(" ")
                    d.putType(d.ns + "QFile::Permissions")
                    d.putNumChild(10)
hjk's avatar
hjk committed
295
                    if d.isExpanded():
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
                        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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
            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
332
333
334
335
    d.putValue("%s/64 = %s" % (v, v/64.0))
    d.putNumChild(0)


hjk's avatar
hjk committed
336
337
338
339
340
341
342
343
344
345
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)

346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# 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
361
362
#    Traceback (most recent call last): File "<string>", line 1,
#      in <module> RuntimeError: No type named N::S::E.
363
364
365
366
367
#  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
368
369
def qdump__QFlags(d, value):
    i = value["i"]
370
    try:
hjk's avatar
hjk committed
371
        enumType = templateArgument(value.type.unqualified(), 0)
372
373
374
        d.putValue("%s (%s)" % (i.cast(enumType), i))
    except:
        d.putValue("%s" % i)
hjk's avatar
hjk committed
375
376
377
    d.putNumChild(0)


378
379
380
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
381
def qdump__QHash(d, value):
hjk's avatar
hjk committed
382
383

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
384
385
386
387
        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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
            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
404
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
405
406
407
408
409
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

hjk's avatar
hjk committed
410
411
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
412

hjk's avatar
hjk committed
413
414
    d_ptr = value["d"]
    e_ptr = value["e"]
415
    size = d_ptr["size"]
hjk's avatar
hjk committed
416
417
418
419

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

420
    check(0 <= size and size <= 100 * 1000 * 1000)
421
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
422

423
424
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
425
    if d.isExpanded():
426
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
427
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
428
        innerType = e_ptr.dereference().type
429
        childType = innerType
430
        if isCompact:
431
            childType = valueType
hjk's avatar
hjk committed
432
        with Children(d, size, maxNumChild=1000, childType=childType):
433
434
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
435
                with SubItem(d, i):
436
437
438
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
439
440
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
441
                        d.putItem(it)
442
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
443
444


hjk's avatar
hjk committed
445
446
447
448
449
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
450

451
452
453
454
455
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
456

457
    d.putNumChild(2)
hjk's avatar
hjk committed
458
    if d.isExpanded():
459
        with Children(d):
hjk's avatar
hjk committed
460
461
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
462
463


464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
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
485
486
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
487
488
489
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
490
491
492
493
494
495
        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
496
    d.putNumChild(1)
hjk's avatar
hjk committed
497
    if d.isExpanded():
hjk's avatar
hjk committed
498
        with Children(d):
hjk's avatar
hjk committed
499
           d.putFields(data)
hjk's avatar
hjk committed
500
501


hjk's avatar
hjk committed
502
503
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
504
505
506
507
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
508
509
    size = end - begin
    check(size >= 0)
510
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
511
512

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
513
    innerType = templateArgument(value.type, 0)
514
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
515
516
517
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
518
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
519

520
521
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
522
    if d.isExpanded():
hjk's avatar
hjk committed
523
524
525
526
527
528
529
        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)
530
        dummyType = lookupType("void").pointer().pointer()
531
532
        innerTypePointer = innerType.pointer()
        p = gdb.Value(array).cast(dummyType) + begin
533
534
535
536
        if innerTypeIsPointer:
            inner = innerType.target()
        else:
            inner = innerType
537
        # about 0.5s / 1000 items
hjk's avatar
hjk committed
538
        with Children(d, size, maxNumChild=2000, childType=inner):
539
540
            for i in d.childRange():
                if isInternal:
hjk's avatar
hjk committed
541
                    d.putSubItem(i, p.cast(innerTypePointer).dereference())
542
                else:
hjk's avatar
hjk committed
543
                    d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference())
544
                p += 1
hjk's avatar
hjk committed
545

hjk's avatar
hjk committed
546
547
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
548

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


hjk's avatar
hjk committed
600
601
602
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
603
    n = d_ptr["size"]
hjk's avatar
hjk committed
604
    check(0 <= n and n <= 100*1000*1000)
605
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
606
    d.putItemCount(n)
607
    d.putNumChild(n)
hjk's avatar
hjk committed
608
609
610
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
611
612
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
613
                d.putSubItem(i, p["t"])
614
                p = p["n"]
hjk's avatar
hjk committed
615

616
qqLocalesCount = None
hjk's avatar
hjk committed
617

hjk's avatar
hjk committed
618
def qdump__QLocale(d, value):
619
620
621
622
623
624
625
626
    # 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
627
    index = int(value["p"]["index"])
628
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
629
    d.putStringValue(call(value, "name"))
630
631
632
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
633
634
635
636
637
638
639
    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
640
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
641
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
642
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
643
644
645
646
647
648
            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
649
650


hjk's avatar
hjk committed
651
def qdump__QMapNode(d, value):
652
653
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
654
655
656
657
658
659
660
661
662
    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
663
664
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
665
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
666
667

    d.putItemCount(n)
668
    d.putNumChild(n)
hjk's avatar
hjk committed
669
    if d.isExpanded():
hjk's avatar
hjk committed
670
671
672
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
673
674
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
675
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
676
677
678
679
680
681

        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 *)
682
683
684
        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
685

686
        if isCompact:
687
688
689
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
690

hjk's avatar
hjk committed
691
        with Children(d, n, childType=innerType):
692
693
694
695
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
696
                with SubItem(d, i):
697
                    if isCompact:
698
                        #d.putType(valueType)
hjk's avatar
hjk committed
699
                        if forceLong:
700
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
701
                        else:
702
703
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
704
                    else:
hjk's avatar
hjk committed
705
                        d.putItem(node)
706
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
707
708


709
710
711
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
712
713
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
714

715
716
717
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
718
719
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
720
721
722
723
724
725
726
727
728
729
730
731
732


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
733
734
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
735
    try:
736
        privateTypeName = d.ns + "QObjectPrivate"
737
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
738
739
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
740
741
        #warn("D_PTR: %s " % d_ptr)
        objectName = d_ptr["objectName"]
742
    except:
hjk's avatar
hjk committed
743
        d.putPlainChildren(value)
744
        return
hjk's avatar
hjk committed
745
    #warn("SMO: %s " % staticMetaObject)
746
747
748
749
750
751
752
    #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)

753
754
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
755
        #d.putValue(cleanAddress(value.address))
756
        d.putPlainChildren(value)
hjk's avatar
hjk committed
757
        if d.isExpanded():
758
            with Children(d):
hjk's avatar
hjk committed
759
                d.putFields(value)
760
        return
hjk's avatar
hjk committed
761
    #warn("OBJECTNAME: %s " % objectName)
762
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
763
    mo = d_ptr["metaObject"]
764
765
766
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
767
768
769
770
771
772
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
773
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
774
775
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
776
777
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
778
779
    #d.putValue("")
    d.putStringValue(objectName)
hjk's avatar
hjk committed
780
    #QSignalMapper::staticMetaObject
781
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
782
    d.putNumChild(4)
hjk's avatar
hjk committed
783
    if d.isExpanded():
784
      with Children(d):
785

hjk's avatar
hjk committed
786
        # Local data.
787
788
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
789
              with SubItem(d, "data"):
790
                d.putValue(" ")
791
                d.putNoType()
792
                d.putNumChild(1)
hjk's avatar
hjk committed
793
                if d.isExpanded():
794
                    with Children(d):
hjk's avatar
hjk committed
795
                        d.putFields(d_ptr, False)
796
797


hjk's avatar
hjk committed
798
        d.putFields(value)
799
        # Parent and children.
hjk's avatar
hjk committed
800
801
802
        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
803

804
        # Properties.
hjk's avatar
hjk committed
805
        with SubItem(d, "properties"):
806
            # Prolog
807
808
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
809
                dynamicPropertyCount = 0
810
            else:
811
                extraDataType = lookupType(
812
813
814
815
816
817
818
819
820
                    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"]
821
822
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
823
            #staticPropertyCount = call(mo, "propertyCount")
824
            staticPropertyCount = metaData[6]
825
826
827
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

828
            d.putNoType()
829
830
831
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
832
            if d.isExpanded():
833
834
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
835
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
836
837
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
838
                gdb.execute("set $d.d.is_shared = 0")
839

hjk's avatar
hjk committed
840
                with Children(d):
841
                    # Dynamic properties.
842
843
844
845
846
847
848
849
850
851
                    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
852
                            with SubItem(d, i):
853
854
855
856
857
858
                                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))
859
860
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
861
862
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
863
                                d.putBetterType(t)
864
865
                            p += 1
                            q += 1
866
867
868
869

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
870
                      with NoAddress(d):
hjk's avatar
hjk committed
871
872
873
874
875
876
                        offset = propertyData + 3 * i
                        propertyName = extractCString(metaStringData,
                                                      metaData[offset])
                        propertyType = extractCString(metaStringData,
                                                      metaData[offset + 1])
                        with SubItem(d, propertyName):
877
878
879
880
                            #flags = metaData[offset + 2]
                            #warn("FLAGS: %s " % flags)
                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
hjk's avatar
hjk committed
881
                            #     % (d.ns, value.address, propertyName)
hjk's avatar
hjk committed
882
                            #exp = '"((\'%sQObject\'*)%s)"' %
hjk's avatar
hjk committed
883
                            #(d.ns, value.address,)
884
                            #warn("EXPRESSION:  %s" % exp)
hjk's avatar
hjk committed
885
                            prop = call(value, "property",
hjk's avatar
hjk committed
886
                                str(cleanAddress(metaStringData + metaData[offset])))
hjk's avatar
hjk committed
887
                            value1 = prop["d"]
888
                            #warn("   CODE: %s" % value1["type"])
hjk's avatar
hjk committed
889
890
                            # Type 1 and 2 are bool and int.
                            # Try to save a few cycles in this case:
891
                            if int(value1["type"]) > 2:
hjk's avatar
hjk committed
892
                                # Poke back prop
hjk's avatar
hjk committed
893
894
895
896
897
898
                                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
899
                                prop = parseAndEvaluate("$d").dereference()
hjk's avatar
hjk committed
900
                            val, inner, innert, handled = \
hjk's avatar
hjk committed
901
                                qdumpHelper__QVariant(d, prop)
hjk's avatar
hjk committed
902
903
904
905

                            if handled:
                                pass
                            elif len(inner):
906
907
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
908
                                d.putItem(val)
909
910
                            else:
                                # User types.
911
912
                           #    func = "typeToName(('%sQVariant::Type')%d)"
                           #       % (d.ns, variantType)
hjk's avatar
hjk committed
913
                           #    type = str(call(value, func))
914
915
                           #    type = type[type.find('"') + 1 : type.rfind('"')]
                           #    type = type.replace("Q", d.ns + "Q") # HACK!
hjk's avatar
hjk committed
916
                           #    data = call(value, "constData")