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

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

8
9
from __future__ import with_statement

10
11
12
13
14
15
16
17
18
19

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
    if d.isExpanded():
46
        d.putArrayData(lookupType("char"), data, size)
hjk's avatar
hjk committed
47
48


hjk's avatar
hjk committed
49
50
def qdump__QChar(d, value):
    ucs = int(value["ucs"])
51
    d.putValue("'%c' (%d)" % (printableChar(ucs), ucs))
hjk's avatar
hjk committed
52
53
54
    d.putNumChild(0)


hjk's avatar
hjk committed
55
def qform__QAbstractItemModel():
56
    return "Normal,Enhanced"
57

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

97
98
99
def qform__QModelIndex():
    return "Normal,Enhanced"

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

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

hjk's avatar
hjk committed
155

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


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


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


hjk's avatar
hjk committed
223
def qdump__QFile(d, value):
hjk's avatar
hjk committed
224
225
226
227
228
229
230
    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
231
    d.putNumChild(1)
hjk's avatar
hjk committed
232
233
    if d.isExpanded():
        with Children(d):
234
235
            base = value.type.fields()[0].type
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
236
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
237
238


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

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

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


hjk's avatar
hjk committed
319
320
321
322
323
324
325
326
327
328
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)

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


361
362
363
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
364
def qdump__QHash(d, value):
hjk's avatar
hjk committed
365
366

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

hjk's avatar
hjk committed
393
394
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
395

hjk's avatar
hjk committed
396
397
    d_ptr = value["d"]
    e_ptr = value["e"]
398
    size = d_ptr["size"]
hjk's avatar
hjk committed
399
400
401
402

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

403
    check(0 <= size and size <= 100 * 1000 * 1000)
404
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
405

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


hjk's avatar
hjk committed
428
429
430
431
432
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
433

434
435
436
437
438
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
439

440
    d.putNumChild(2)
hjk's avatar
hjk committed
441
    if d.isExpanded():
442
        with Children(d):
hjk's avatar
hjk committed
443
444
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
445
446


447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
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
468
469
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
470
471
472
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
473
474
475
476
477
478
        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
479
    d.putNumChild(1)
hjk's avatar
hjk committed
480
    if d.isExpanded():
hjk's avatar
hjk committed
481
        with Children(d):
hjk's avatar
hjk committed
482
           d.putFields(data)
hjk's avatar
hjk committed
483
484


hjk's avatar
hjk committed
485
486
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
487
488
489
490
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
491
492
    size = end - begin
    check(size >= 0)
493
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
494
495

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

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

hjk's avatar
hjk committed
529
530
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
531

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


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

599
qqLocalesCount = None
hjk's avatar
hjk committed
600

hjk's avatar
hjk committed
601
def qdump__QLocale(d, value):
602
603
604
605
606
607
608
609
    # 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
610
    index = int(value["p"]["index"])
611
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
612
    d.putStringValue(call(value, "name"))
613
614
615
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
616
617
618
619
620
621
622
    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
623
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
624
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
625
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
626
627
628
629
630
631
            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
632
633


hjk's avatar
hjk committed
634
def qdump__QMapNode(d, value):
635
636
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
637
638
639
640
641
642
643
644
645
    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
646
647
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
648
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
649
650

    d.putItemCount(n)
651
    d.putNumChild(n)
hjk's avatar
hjk committed
652
    if d.isExpanded():
hjk's avatar
hjk committed
653
654
655
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
656
657
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
658
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
659
660
661
662
663
664

        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 *)
665
666
667
        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
668

669
        if isCompact:
670
671
672
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
673

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


692
693
694
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
695
696
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
697

698
699
700
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
701
702
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
703
704
705
706
707
708
709
710
711
712
713
714
715


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

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

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


hjk's avatar
hjk committed
781
        d.putFields(value)
782
        # Parent and children.
hjk's avatar
hjk committed
783
784
785
        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
786

787
        # Properties.
hjk's avatar
hjk committed
788
        with SubItem(d, "properties"):
789
            # Prolog
790
791
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
792
                dynamicPropertyCount = 0
793
            else:
794
                extraDataType = lookupType(
795
796
797
798
799
800
801
802
803
                    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"]
804
805
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
806
            #staticPropertyCount = call(mo, "propertyCount")
807
            staticPropertyCount = metaData[6]
808
809
810
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

811
            d.putNoType()
812
813
814
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

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

hjk's avatar
hjk committed
823
                with Children(d):
824
                    # Dynamic properties.
825
826
827
828
829
830
831
832
833
834
                    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
835
                            with SubItem(d, i):
836
837
838
839
840
841
                                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))
842
843
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
844
845
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
846
                                d.putBetterType(t)
847
848
                            p += 1
                            q += 1
849
850
851
852

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

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

914
        # Connections.
hjk's avatar
hjk committed
915
        with SubItem(d, "connections"):
916
            d.putNoType()
917
918
919
920
            connections = d_ptr["connectionLists"]
            connectionListCount = 0
            if not isNull(connections):
                connectionListCount = connections["d"]["size"]
921
            d.putItemCount(connectionListCount, 0)
922
            d.putNumChild(connectionListCount)
hjk's avatar
hjk committed
923
            if d.isExpanded():
924
                pp = 0