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

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
    format = d.currentItemFormat()
    if format == 1:
        d.putDisplay(StopDisplay)
    elif format == 2:
57
        d.putField("editformat", DisplayLatin1String)
58
        d.putField("editvalue", encodeByteArray(value, None))
59
    elif format == 3:
60
        d.putField("editformat", DisplayUtf8String)
61
        d.putField("editvalue", encodeByteArray(value, None))
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
    r = value["r"]
    c = value["c"]
124
125
126
127
    try:
        p = value["p"]
    except:
        p = value["i"]
hjk's avatar
hjk committed
128
    m = value["m"]
129
130
131
132
133
    if isNull(m) or r < 0 or c < 0:
        d.putValue("(invalid)")
        d.putPlainChildren(value)
        return

134
135
    mm = m.dereference()
    mm = mm.cast(mm.type.unqualified())
136
    try:
137
138
139
        mi = makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
        mm_ = makeExpression(mm)
        mi_ = makeExpression(mi)
140
141
142
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
    except:
143
        d.putValue(" ")
hjk's avatar
hjk committed
144
        d.putPlainChildren(value)
145
        return
146
147
148

    try:
        # Access DisplayRole as value
hjk's avatar
hjk committed
149
150
        val = parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_))
        v = val["d"]["data"]["ptr"]
151
152
153
154
        d.putStringValue(makeValue(d.ns + 'QString', v))
    except:
        d.putValue("(invalid)")

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    d.putNumChild(rowCount * columnCount)
    if d.isExpanded():
        with Children(d):
            i = 0
            for row in xrange(rowCount):
                for column in xrange(columnCount):
                    with UnnamedSubItem(d, i):
                        d.putName("[%s, %s]" % (row, column))
                        mi2 = parseAndEvaluate("%s.index(%d,%d,%s)"
                            % (mm_, row, column, mi_))
                        d.putItem(mi2)
                        i = i + 1
            #d.putCallItem("parent", val, "parent")
            #with SubItem(d, "model"):
            #    d.putValue(m)
            #    d.putType(d.ns + "QAbstractItemModel*")
            #    d.putNumChild(1)
172
173
    #gdb.execute("call free($mi)")

hjk's avatar
hjk committed
174

hjk's avatar
hjk committed
175
def qdump__QDate(d, value):
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    jd = value["jd"]
    if int(jd):
        d.putValue(jd, JulianDate)
        d.putNumChild(1)
        if d.isExpanded():
            qt = d.ns + "Qt::"
            # FIXME: This improperly uses complex return values.
            with Children(d):
                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")
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
192
193


hjk's avatar
hjk committed
194
def qdump__QTime(d, value):
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    mds = value["mds"]
    if int(mds) >= 0:
        d.putValue(value["mds"], MillisecondsSinceMidnight)
        d.putNumChild(1)
        if d.isExpanded():
            qt = d.ns + "Qt::"
            # FIXME: This improperly uses complex return values.
            with Children(d):
                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")
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
212
213


hjk's avatar
hjk committed
214
def qdump__QDateTime(d, value):
215
216
    try:
        # Fails without debug info.
217
        p = value["d"]["d"].dereference()
218
    except:
hjk's avatar
hjk committed
219
        d.putPlainChildren(value)
220
        return
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
    mds = p["time"]["mds"]
    if int(mds) >= 0:
        d.putValue("%s/%s" % (p["date"]["jd"], mds),
            JulianDateAndMillisecondsSinceMidnight)
        d.putNumChild(1)
        if d.isExpanded():
            # FIXME: This improperly uses complex return values.
            with Children(d):
                qt = d.ns + "Qt::"
                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")
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
240
241
242


def qdump__QDir(d, value):
hjk's avatar
hjk committed
243
    d.putNumChild(1)
244
245
246
247
248
249
250
    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
251
252
    if d.isExpanded():
        with Children(d):
253
            qdir = d.ns + "QDir::"
hjk's avatar
hjk committed
254
255
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
hjk's avatar
hjk committed
256
257
            d.putSubItem("entryList", data["files"])
            d.putSubItem("entryInfoList", data["fileInfos"])
hjk's avatar
hjk committed
258
259


hjk's avatar
hjk committed
260
def qdump__QFile(d, value):
hjk's avatar
hjk committed
261
262
263
264
265
266
267
    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
268
    d.putNumChild(1)
hjk's avatar
hjk committed
269
270
    if d.isExpanded():
        with Children(d):
271
272
            base = value.type.fields()[0].type
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
273
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
274
275


hjk's avatar
hjk committed
276
def qdump__QFileInfo(d, value):
277
    try:
hjk's avatar
hjk committed
278
        d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3])
279
    except:
hjk's avatar
hjk committed
280
        d.putPlainChildren(value)
281
        return
hjk's avatar
hjk committed
282
    d.putNumChild(1)
hjk's avatar
hjk committed
283
284
285
286
287
288
289
290
291
    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")
292
293
            if False:
                #ifdef Q_OS_MACX
hjk's avatar
hjk committed
294
295
296
297
                d.putCallItem("isBundle", value, "isBundle")
                d.putCallItem("bundleName", value, "bundleName")
            d.putCallItem("fileName", value, "fileName")
            d.putCallItem("filePath", value, "filePath")
298
            # Crashes gdb (archer-tromey-python, at dad6b53fe)
hjk's avatar
hjk committed
299
300
301
            #d.putCallItem("group", value, "group")
            #d.putCallItem("owner", value, "owner")
            d.putCallItem("path", value, "path")
302

hjk's avatar
hjk committed
303
304
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
305
306

            #QFile::Permissions permissions () const
hjk's avatar
hjk committed
307
            perms = call(value, "permissions")
308
309
310
            if perms is None:
                d.putValue("<not available>")
            else:
hjk's avatar
hjk committed
311
                with SubItem(d, "permissions"):
312
313
314
                    d.putValue(" ")
                    d.putType(d.ns + "QFile::Permissions")
                    d.putNumChild(10)
hjk's avatar
hjk committed
315
                    if d.isExpanded():
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
                        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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
            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
352
353
354
355
    d.putValue("%s/64 = %s" % (v, v/64.0))
    d.putNumChild(0)


hjk's avatar
hjk committed
356
357
358
359
360
361
362
363
364
365
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)

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# 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
381
382
#    Traceback (most recent call last): File "<string>", line 1,
#      in <module> RuntimeError: No type named N::S::E.
383
384
385
386
387
#  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
388
389
def qdump__QFlags(d, value):
    i = value["i"]
390
    try:
hjk's avatar
hjk committed
391
        enumType = templateArgument(value.type.unqualified(), 0)
392
393
394
        d.putValue("%s (%s)" % (i.cast(enumType), i))
    except:
        d.putValue("%s" % i)
hjk's avatar
hjk committed
395
396
397
    d.putNumChild(0)


398
399
400
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
401
def qdump__QHash(d, value):
hjk's avatar
hjk committed
402
403

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
404
405
406
407
        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
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
            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
424
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
425
426
427
428
429
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

hjk's avatar
hjk committed
430
431
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
432

hjk's avatar
hjk committed
433
434
    d_ptr = value["d"]
    e_ptr = value["e"]
435
    size = d_ptr["size"]
hjk's avatar
hjk committed
436
437
438
439

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

440
    check(0 <= size and size <= 100 * 1000 * 1000)
441
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
442

443
444
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
445
    if d.isExpanded():
446
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
447
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
448
        innerType = e_ptr.dereference().type
449
        childType = innerType
450
        if isCompact:
451
            childType = valueType
hjk's avatar
hjk committed
452
        with Children(d, size, maxNumChild=1000, childType=childType):
453
454
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
455
                with SubItem(d, i):
456
457
458
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
459
460
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
461
                        d.putItem(it)
462
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
463
464


hjk's avatar
hjk committed
465
466
467
468
469
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
470

471
472
473
474
475
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
476

477
    d.putNumChild(2)
hjk's avatar
hjk committed
478
    if d.isExpanded():
479
        with Children(d):
hjk's avatar
hjk committed
480
481
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
482
483


484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
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
505
506
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
507
508
509
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
510
511
512
513
514
515
        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
516
    d.putNumChild(1)
hjk's avatar
hjk committed
517
    if d.isExpanded():
hjk's avatar
hjk committed
518
        with Children(d):
hjk's avatar
hjk committed
519
           d.putFields(data)
hjk's avatar
hjk committed
520
521


hjk's avatar
hjk committed
522
523
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
524
525
526
527
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
528
529
    size = end - begin
    check(size >= 0)
530
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
531
532

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
533
    innerType = templateArgument(value.type, 0)
534
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
535
536
537
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
538
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
539

540
541
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
542
    if d.isExpanded():
hjk's avatar
hjk committed
543
544
545
546
547
548
549
        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)
550
        dummyType = lookupType("void").pointer().pointer()
551
552
        innerTypePointer = innerType.pointer()
        p = gdb.Value(array).cast(dummyType) + begin
553
554
555
556
        if innerTypeIsPointer:
            inner = innerType.target()
        else:
            inner = innerType
557
        # about 0.5s / 1000 items
hjk's avatar
hjk committed
558
        with Children(d, size, maxNumChild=2000, childType=inner):
559
560
            for i in d.childRange():
                if isInternal:
hjk's avatar
hjk committed
561
                    d.putSubItem(i, p.cast(innerTypePointer).dereference())
562
                else:
hjk's avatar
hjk committed
563
                    d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference())
564
                p += 1
hjk's avatar
hjk committed
565

hjk's avatar
hjk committed
566
567
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
568

hjk's avatar
hjk committed
569
def qdump__QImage(d, value):
570
    try:
hjk's avatar
hjk committed
571
        painters = value["painters"]
572
    except:
hjk's avatar
hjk committed
573
        d.putPlainChildren(value)
574
        return
hjk's avatar
hjk committed
575
    check(0 <= painters and painters < 1000)
hjk's avatar
hjk committed
576
    d_ptr = value["d"]
hjk's avatar
hjk committed
577
    if isNull(d_ptr):
578
        d.putValue("(null)")
hjk's avatar
hjk committed
579
    else:
580
        checkSimpleRef(d_ptr["ref"])
581
        d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
582
583
    bits = d_ptr["data"]
    nbytes = d_ptr["nbytes"]
584
    d.putNumChild(0)
hjk's avatar
hjk committed
585
    #d.putNumChild(1)
hjk's avatar
hjk committed
586
    if d.isExpanded():
587
        with Children(d):
hjk's avatar
hjk committed
588
            with SubItem(d, "data"):
589
                d.putNoType()
590
591
                d.putNumChild(0)
                d.putValue("size: %s bytes" % nbytes);
hjk's avatar
hjk committed
592
    format = d.currentItemFormat()
593
    if format == 1:
594
        d.putDisplay(StopDisplay)
595
    elif format == 2:
hjk's avatar
hjk committed
596
597
598
        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.
599
            d.putField("editformat", DisplayImageData)
600
            d.put('%s="' % name)
hjk's avatar
hjk committed
601
602
603
            d.put("%08x" % int(d_ptr["width"]))
            d.put("%08x" % int(d_ptr["height"]))
            d.put("%08x" % int(d_ptr["format"]))
604
            p = bits.cast(lookupType("unsigned int").pointer())
hjk's avatar
hjk committed
605
606
607
            for i in xrange(nbytes / 4):
                d.put("%08x" % int(p.dereference()))
                p += 1
608
            d.put('",')
hjk's avatar
hjk committed
609
610
611
        else:
            # Write to an external file. Much faster ;-(
            file = tempfile.mkstemp(prefix="gdbpy_")
612
            filename = file[1].replace("\\", "\\\\")
613
            p = bits.cast(lookupType("unsigned char").pointer())
hjk's avatar
hjk committed
614
615
            gdb.execute("dump binary memory %s %s %s" %
                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
616
            d.putDisplay(DisplayImageFile, " %d %d %d %s"
617
                % (d_ptr["width"], d_ptr["height"], d_ptr["format"], filename))
hjk's avatar
hjk committed
618
619


hjk's avatar
hjk committed
620
621
622
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
623
    n = d_ptr["size"]
hjk's avatar
hjk committed
624
    check(0 <= n and n <= 100*1000*1000)
625
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
626
    d.putItemCount(n)
627
    d.putNumChild(n)
hjk's avatar
hjk committed
628
629
630
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
631
632
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
633
                d.putSubItem(i, p["t"])
634
                p = p["n"]
hjk's avatar
hjk committed
635

636
qqLocalesCount = None
hjk's avatar
hjk committed
637

hjk's avatar
hjk committed
638
def qdump__QLocale(d, value):
639
640
641
642
643
644
645
646
    # 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
647
    index = int(value["p"]["index"])
648
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
649
    d.putStringValue(call(value, "name"))
650
651
652
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
653
654
655
656
657
658
659
    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
660
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
661
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
662
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
663
664
665
666
667
668
            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
669
670


hjk's avatar
hjk committed
671
def qdump__QMapNode(d, value):
672
673
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
674
675
676
677
678
679
    if d.isExpanded():
        with Children(d):
            d.putSubItem("key", value["key"])
            d.putSubItem("value", value["value"])


680
def qdumpHelper__Qt4_QMap(d, value, forceLong):
hjk's avatar
hjk committed
681
682
    d_ptr = value["d"].dereference()
    e_ptr = value["e"].dereference()
hjk's avatar
hjk committed
683
684
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
685
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
686
687

    d.putItemCount(n)
688
    d.putNumChild(n)
hjk's avatar
hjk committed
689
    if d.isExpanded():
690
691
        if n > 10000:
            n = 10000
hjk's avatar
hjk committed
692

hjk's avatar
hjk committed
693
694
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
695
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
696
697
698
699
700
701

        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 *)
702
703
704
        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
705

706
        if isCompact:
707
708
709
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
710

hjk's avatar
hjk committed
711
        with Children(d, n, childType=innerType):
712
713
714
715
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
716
                with SubItem(d, i):
717
                    if isCompact:
718
                        #d.putType(valueType)
hjk's avatar
hjk committed
719
                        if forceLong:
720
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
721
                        else:
722
723
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
724
                    else:
hjk's avatar
hjk committed
725
                        d.putItem(node)
726
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
727
728


729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
def qdumpHelper__Qt5_QMap(d, value, forceLong):
    d_ptr = value["d"].dereference()
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
    checkRef(d_ptr["ref"])

    d.putItemCount(n)
    d.putNumChild(n)
    if d.isExpanded():
        if n > 10000:
            n = 10000

        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
        nodeType = lookupType(d.ns + "QMapNode<%s, %s>" % (keyType, valueType))
        if isCompact:
            innerType = valueType
        else:
            innerType = nodeType

        with Children(d, n, childType=innerType):
            toDo = []
            i = -1
            node = d_ptr["header"]
            left = node["left"]
            if not isNull(left):
                toDo.append(left.dereference())
            right = node["right"]
            if not isNull(right):
                toDo.append(right.dereference())

            while len(toDo):
                node = toDo[0].cast(nodeType)
                toDo = toDo[1:]
                left = node["left"]
                if not isNull(left):
                    toDo.append(left.dereference())
                right = node["right"]
                if not isNull(right):
                    toDo.append(right.dereference())
                i += 1

                with SubItem(d, i):
                    if isCompact:
                        if forceLong:
                            d.putName("[%s] %s" % (i, node["key"]))
                        else:
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
                    else:
                        qdump__QMapNode(d, node)


def qdumpHelper__QMap(d, value, forceLong):
    if value["d"].dereference().type.fields()[0].name == "backward":
        qdumpHelper__Qt4_QMap(d, value, forceLong)
    else:
        qdumpHelper__Qt5_QMap(d, value, forceLong)

789
790
791
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
792
793
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
794

795
796
797
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
798
799
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
800
801
802
803
804
805
806
807
808
809
810
811
812


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
813
814
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
815
    try:
816
        privateTypeName = d.ns + "QObjectPrivate"
817
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
818
819
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
820
        #warn("D_PTR: %s " % d_ptr)
821
        objectName = None
822
823
824
        try:
            objectName = d_ptr["objectName"]
        except: # Qt 5
825
826
827
828
829
            p = d_ptr["extraData"]
            if not isNull(p):
                objectName = p.dereference()["objectName"]
        if not objectName is None:
            d.putStringValue(objectName)
830
    except:
hjk's avatar
hjk committed
831
        d.putPlainChildren(value)
832
        return
hjk's avatar
hjk committed
833
    #warn("SMO: %s " % staticMetaObject)
834
835
836
837
838
839
840
    #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)

841
842
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
843
        #d.putValue(cleanAddress(value.address))
844
        d.putPlainChildren(value)
hjk's avatar
hjk committed
845
        if d.isExpanded():
846
            with Children(d):
hjk's avatar
hjk committed
847
                d.putFields(value)
848
        return
hjk's avatar
hjk committed
849
    #warn("OBJECTNAME: %s " % objectName)
850
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
851
    mo = d_ptr["metaObject"]
852
853
854
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
855
856
857
858
859
860
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
861
862
863
864
865
866
867
868
    # This is char * in Qt 4 and ByteArrayData * in Qt 5.
    # Force it to the char * data in the Qt 5 case.
    try:
        offset = metaStringData["offset"]
        metaStringData = metaStringData.cast(lookupType('char*')) + int(offset)
    except:
        pass

869
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
870
871
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
872
873
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
874
    #d.putValue("")
hjk's avatar
hjk committed
875
    #QSignalMapper::staticMetaObject
876
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
877
    d.putNumChild(4)
hjk's avatar
hjk committed
878
    if d.isExpanded():
879
      with Children(d):
880

hjk's avatar
hjk committed
881
        # Local data.
882
883
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
884
              with SubItem(d, "data"):
885
                d.putValue(" ")
886
                d.putNoType()
887
                d.putNumChild(1)
hjk's avatar
hjk committed
888
                if d.isExpanded():
889
                    with Children(d):
hjk's avatar
hjk committed
890
                        d.putFields(d_ptr, False)
891
892


hjk's avatar
hjk committed
893
        d.putFields(value)
894
        # Parent and children.
hjk's avatar
hjk committed
895
896
897
        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
898

899
        # Properties.
hjk's avatar
hjk committed
900
        with SubItem(d, "properties"):
901
            # Prolog
902
903
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
904
                dynamicPropertyCount = 0
905
            else:
906
                extraDataType = lookupType(
907
908
909
910
911
912
913
914
915
                    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"]
916
917
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
918
            #staticPropertyCount = call(mo, "propertyCount")
919
            staticPropertyCount = metaData[6]
920
921
922
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

923
            d.putNoType()
924
925
926
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
927
            if d.isExpanded():
928
929
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
930
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
931
932
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
933
                gdb.execute("set $d.d.is_shared = 0")
934

hjk's avatar
hjk committed
935
                with Children(d):
936
                    # Dynamic properties.
937
938
939
940
941
942
943
944
945
946
                    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
947
                            with SubItem(d, i):
948
949
950
951
952
953
                                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))
954
955
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
956
957
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
958
                                d.putBetterType(t)
959
960
                            p += 1
                            q += 1
961
962
963
964

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
965
                      with NoAddress(d):
hjk's avatar
hjk committed
966
967
968
969
970
971
                        offset = propertyData + 3 * i
                        propertyName = extractCString(metaStringData,
                                                      metaData[offset])
                        propertyType = extractCString(metaStringData,
                                                      metaData[offset + 1])
                        with SubItem(d, propertyName):
972
973
974
975
                            #flags = metaData[offset + 2]
                            #warn("FLAGS: %s " % flags)
                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
hjk's avatar
hjk committed
976
                            #     % (d.ns, value.address, propertyName)
hjk's avatar
hjk committed
977
                            #exp = '"((\'%sQObject\'*)%s)"' %
hjk's avatar
hjk committed
978
                            #(d.ns, value.address,)
979
                            #warn("EXPRESSION:  %s" % exp)
hjk's avatar
hjk committed
980
                            prop = call(value, "property",
hjk's avatar
hjk committed
981
                                str(cleanAddress(metaStringData + metaData[offset])))
hjk's avatar
hjk committed
982
                            value1 = prop["d"]
983
                            #warn("   CODE: %s" % value1["type"])
hjk's avatar
hjk committed
984
985
                            # Type 1 and 2 are bool and int.
                            # Try to save a few cycles in this case:
986
                            if int(value1["type"]) > 2:
hjk's avatar
hjk committed
987
                                # Poke back prop
hjk's avatar
hjk committed
988
989
990
991
992
993
                                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
994
                                prop = parseAndEvaluate("$d").dereference()
hjk's avatar
hjk committed
995
                            val, inner, innert, handled = \
hjk's avatar
hjk committed
996
                                qdumpHelper__QVariant(d, prop)
hjk's avatar
hjk committed
997
998
999
1000

                            if handled:
                                pass
                            elif len(inner):
1001
1002
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
1003
                                d.putItem(val)
1004
1005
                            else:
                                # User types.
1006
1007
                           #    func = "typeToName(('%sQVariant::Type')%d)"
                           #       % (d.ns, variantType)
hjk's avatar
hjk committed
1008
                           #    type = str(call(value, func))
1009
1010
                           #    type = type[type.find('"') + 1 : type.rfind('"')]
                           #    type = type.replace("Q", d.ns + "Q") # HACK!
hjk's avatar
hjk committed
1011
                           #    data = call(value, "constData")