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
    d.putValue("%s/%s" % (p["date"]["jd"], p["time"]["mds"]),
        JulianDateAndMillisecondsSinceMidnight)
223
    d.putNumChild(1)
hjk's avatar
hjk committed
224
    if d.isExpanded():
225
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
226
        with Children(d):
227
            qt = d.ns + "Qt::"
hjk's avatar
hjk committed
228
229
230
231
232
233
234
235
236
237
            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
238
    d.putNumChild(1)
239
240
241
242
243
244
245
    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
246
247
    if d.isExpanded():
        with Children(d):
248
            qdir = d.ns + "QDir::"
hjk's avatar
hjk committed
249
250
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
251
252
253
254
255
256
            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
257
258


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


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

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

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


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

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


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

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

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

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

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

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

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

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


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

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

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


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


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

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

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

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

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


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

635
qqLocalesCount = None
hjk's avatar
hjk committed
636

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


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


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

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

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

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

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

hjk's avatar
hjk committed
710
        with Children(d, n, childType=innerType):
711
712
713
714
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
715
                with SubItem(d, i):
716
                    if isCompact:
717
                        #d.putType(valueType)
hjk's avatar
hjk committed
718
                        if forceLong:
719
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
720
                        else:
721
722
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
723
                    else:
hjk's avatar
hjk committed
724
                        d.putItem(node)
725
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
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
778
779
780
781
782
783
784
785
786
787
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)

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

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

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

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


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

840
841
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
842
        #d.putValue(cleanAddress(value.address))
843
        d.putPlainChildren(value)
hjk's avatar
hjk committed
844
        if d.isExpanded():
845
            with Children(d):
hjk's avatar
hjk committed
846
                d.putFields(value)
847
        return
hjk's avatar
hjk committed
848
    #warn("OBJECTNAME: %s " % objectName)
849
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
850
    mo = d_ptr["metaObject"]
851
852
853
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
854
855
856
857
858
859
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
860
861
862
863
864
865
866
867
    # 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

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

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


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

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

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

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

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

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

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

                            if handled:
                                pass
                            elif len(inner):
1000
1001
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
1002
                                d.putItem(val)
1003
1004
                            else:
                                # User types.