qttypes.py 94.7 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")
256
257
258
259
260
261
            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
262
263


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


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

hjk's avatar
hjk committed
307
308
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
309
310

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


hjk's avatar
hjk committed
360
361
362
363
364
365
366
367
368
369
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)

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


402
403
404
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
405
def qdump__QHash(d, value):
hjk's avatar
hjk committed
406
407

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

hjk's avatar
hjk committed
434
435
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
436

hjk's avatar
hjk committed
437
438
    d_ptr = value["d"]
    e_ptr = value["e"]
439
    size = d_ptr["size"]
hjk's avatar
hjk committed
440
441
442
443

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

444
    check(0 <= size and size <= 100 * 1000 * 1000)
445
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
446

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


hjk's avatar
hjk committed
469
470
471
472
473
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
474

475
476
477
478
479
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
480

481
    d.putNumChild(2)
hjk's avatar
hjk committed
482
    if d.isExpanded():
483
        with Children(d):
hjk's avatar
hjk committed
484
485
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
486
487


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


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

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

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

hjk's avatar
hjk committed
570
571
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
572

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


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

640
qqLocalesCount = None
hjk's avatar
hjk committed
641

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


hjk's avatar
hjk committed
675
def qdump__QMapNode(d, value):
676
677
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
678
679
680
681
682
683
    if d.isExpanded():
        with Children(d):
            d.putSubItem("key", value["key"])
            d.putSubItem("value", value["value"])


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

    d.putItemCount(n)
692
    d.putNumChild(n)
hjk's avatar
hjk committed
693
    if d.isExpanded():
694
695
        if n > 10000:
            n = 10000
hjk's avatar
hjk committed
696

hjk's avatar
hjk committed
697
698
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
699
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
700
701
702
703
704
705

        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 *)
706
707
708
        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
709

710
        if isCompact:
711
712
713
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
714

hjk's avatar
hjk committed
715
        with Children(d, n, childType=innerType):
716
717
718
719
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
720
                with SubItem(d, i):
721
                    if isCompact:
722
                        #d.putType(valueType)
hjk's avatar
hjk committed
723
                        if forceLong:
724
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
725
                        else:
726
727
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
728
                    else:
hjk's avatar
hjk committed
729
                        d.putItem(node)
730
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
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
789
790
791
792
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)

793
794
795
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
796
797
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
798

799
800
801
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
802
803
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
804
805
806
807
808
809
810
811
812
813
814
815
816


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

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

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

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


hjk's avatar
hjk committed
897
        d.putFields(value)
898
        # Parent and children.
hjk's avatar
hjk committed
899
900
901
        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
902

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

hjk's avatar
hjk committed
922
            #staticPropertyCount = call(mo, "propertyCount")
923
            staticPropertyCount = metaData[6]
924
925
926
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

927
            d.putNoType()
928
929
930
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

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

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

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

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