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

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

8
9
from __future__ import with_statement

10
11
12
13

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


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


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


hjk's avatar
hjk committed
249
def qdump__QFile(d, value):
hjk's avatar
hjk committed
250
251
252
253
254
255
256
    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
257
    d.putNumChild(1)
hjk's avatar
hjk committed
258
259
    if d.isExpanded():
        with Children(d):
260
261
            base = value.type.fields()[0].type
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
262
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
263
264


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

hjk's avatar
hjk committed
292
293
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
294
295

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


hjk's avatar
hjk committed
345
346
347
348
349
350
351
352
353
354
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)

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


387
388
389
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
390
def qdump__QHash(d, value):
hjk's avatar
hjk committed
391
392

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
393
394
395
396
        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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
            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
413
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
414
415
416
417
418
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

hjk's avatar
hjk committed
419
420
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
421

hjk's avatar
hjk committed
422
423
    d_ptr = value["d"]
    e_ptr = value["e"]
424
    size = d_ptr["size"]
hjk's avatar
hjk committed
425
426
427
428

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

429
    check(0 <= size and size <= 100 * 1000 * 1000)
430
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
431

432
433
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
434
    if d.isExpanded():
435
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
436
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
437
        innerType = e_ptr.dereference().type
438
        childType = innerType
439
        if isCompact:
440
            childType = valueType
hjk's avatar
hjk committed
441
        with Children(d, size, maxNumChild=1000, childType=childType):
442
443
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
444
                with SubItem(d, i):
445
446
447
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
448
449
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
450
                        d.putItem(it)
451
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
452
453


hjk's avatar
hjk committed
454
455
456
457
458
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
459

460
461
462
463
464
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
465

466
    d.putNumChild(2)
hjk's avatar
hjk committed
467
    if d.isExpanded():
468
        with Children(d):
hjk's avatar
hjk committed
469
470
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
471
472


473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
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
494
495
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
496
497
498
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
499
500
501
502
503
504
        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
505
    d.putNumChild(1)
hjk's avatar
hjk committed
506
    if d.isExpanded():
hjk's avatar
hjk committed
507
        with Children(d):
hjk's avatar
hjk committed
508
           d.putFields(data)
hjk's avatar
hjk committed
509
510


hjk's avatar
hjk committed
511
512
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
513
514
515
516
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
517
518
    size = end - begin
    check(size >= 0)
519
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
520
521

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
522
    innerType = templateArgument(value.type, 0)
523
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
524
525
526
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
527
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
528

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

hjk's avatar
hjk committed
555
556
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
557

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


hjk's avatar
hjk committed
609
610
611
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
612
    n = d_ptr["size"]
hjk's avatar
hjk committed
613
    check(0 <= n and n <= 100*1000*1000)
614
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
615
    d.putItemCount(n)
616
    d.putNumChild(n)
hjk's avatar
hjk committed
617
618
619
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
620
621
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
622
                d.putSubItem(i, p["t"])
623
                p = p["n"]
hjk's avatar
hjk committed
624

625
qqLocalesCount = None
hjk's avatar
hjk committed
626

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


hjk's avatar
hjk committed
660
def qdump__QMapNode(d, value):
661
662
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
663
664
665
666
667
668
    if d.isExpanded():
        with Children(d):
            d.putSubItem("key", value["key"])
            d.putSubItem("value", value["value"])


669
def qdumpHelper__Qt4_QMap(d, value, forceLong):
hjk's avatar
hjk committed
670
671
    d_ptr = value["d"].dereference()
    e_ptr = value["e"].dereference()
hjk's avatar
hjk committed
672
673
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
674
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
675
676

    d.putItemCount(n)
677
    d.putNumChild(n)
hjk's avatar
hjk committed
678
    if d.isExpanded():
679
680
        if n > 10000:
            n = 10000
hjk's avatar
hjk committed
681

hjk's avatar
hjk committed
682
683
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
684
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
685
686
687
688
689
690

        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 *)
691
692
693
        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
694

695
        if isCompact:
696
697
698
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
699

hjk's avatar
hjk committed
700
        with Children(d, n, childType=innerType):
701
702
703
704
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
705
                with SubItem(d, i):
706
                    if isCompact:
707
                        #d.putType(valueType)
hjk's avatar
hjk committed
708
                        if forceLong:
709
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
710
                        else:
711
712
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
713
                    else:
hjk's avatar
hjk committed
714
                        d.putItem(node)
715
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
716
717


718
719
720
721
722
723
724
725
726
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
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)

778
779
780
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
781
782
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
783

784
785
786
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
787
788
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
789
790
791
792
793
794
795
796
797
798
799
800
801


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
802
803
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
804
    try:
805
        privateTypeName = d.ns + "QObjectPrivate"
806
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
807
808
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
809
        #warn("D_PTR: %s " % d_ptr)
810
        objectName = None
811
812
813
        try:
            objectName = d_ptr["objectName"]
        except: # Qt 5
814
815
816
817
818
            p = d_ptr["extraData"]
            if not isNull(p):
                objectName = p.dereference()["objectName"]
        if not objectName is None:
            d.putStringValue(objectName)
819
    except:
hjk's avatar
hjk committed
820
        d.putPlainChildren(value)
821
        return
hjk's avatar
hjk committed
822
    #warn("SMO: %s " % staticMetaObject)
823
824
825
826
827
828
829
    #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)

830
831
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
832
        #d.putValue(cleanAddress(value.address))
833
        d.putPlainChildren(value)
hjk's avatar
hjk committed
834
        if d.isExpanded():
835
            with Children(d):
hjk's avatar
hjk committed
836
                d.putFields(value)
837
        return
hjk's avatar
hjk committed
838
    #warn("OBJECTNAME: %s " % objectName)
839
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
840
    mo = d_ptr["metaObject"]
841
842
843
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
844
845
846
847
848
849
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
850
851
852
853
854
855
856
857
    # 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

858
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
859
860
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
861
862
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
863
    #d.putValue("")
hjk's avatar
hjk committed
864
    #QSignalMapper::staticMetaObject
865
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
866
    d.putNumChild(4)
hjk's avatar
hjk committed
867
    if d.isExpanded():
868
      with Children(d):
869

hjk's avatar
hjk committed
870
        # Local data.
871
872
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
873
              with SubItem(d, "data"):
874
                d.putValue(" ")
875
                d.putNoType()
876
                d.putNumChild(1)
hjk's avatar
hjk committed
877
                if d.isExpanded():
878
                    with Children(d):
hjk's avatar
hjk committed
879
                        d.putFields(d_ptr, False)
880
881


hjk's avatar
hjk committed
882
        d.putFields(value)
883
        # Parent and children.
hjk's avatar
hjk committed
884
885
886
        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
887

888
        # Properties.
hjk's avatar
hjk committed
889
        with SubItem(d, "properties"):
890
            # Prolog
891
892
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
893
                dynamicPropertyCount = 0
894
            else:
895
                extraDataType = lookupType(
896
897
898
899
900
901
902
903
904
                    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"]
905
906
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
907
            #staticPropertyCount = call(mo, "propertyCount")
908
            staticPropertyCount = metaData[6]
909
910
911
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

912
            d.putNoType()
913
914
915
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
916
            if d.isExpanded():
917
918
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
919
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
920
921
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
922
                gdb.execute("set $d.d.is_shared = 0")
923

hjk's avatar
hjk committed
924
                with Children(d):
925
                    # Dynamic properties.
926
927
928
929
930
931
932
933
934
935
                    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
936
                            with SubItem(d, i):
937
938
939
940
941
942
                                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))
943
944
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
945
946
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
947
                                d.putBetterType(t)
948
949
                            p += 1
                            q += 1
950
951
952
953

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
954
                      with NoAddress(d):
hjk's avatar
hjk committed
955