forked from qt-creator/qt-creator
		
	Change-Id: Ie2b12a526ff7199bcadfc21a3deb5354063a3e3b Reviewed-by: hjk <hjk121@nokiamail.com>
		
			
				
	
	
		
			541 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			541 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
############################################################################
 | 
						|
#
 | 
						|
# Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
						|
# Contact: http://www.qt-project.org/legal
 | 
						|
#
 | 
						|
# This file is part of Qt Creator.
 | 
						|
#
 | 
						|
# Commercial License Usage
 | 
						|
# Licensees holding valid commercial Qt licenses may use this file in
 | 
						|
# accordance with the commercial license agreement provided with the
 | 
						|
# Software or, alternatively, in accordance with the terms contained in
 | 
						|
# a written agreement between you and Digia.  For licensing terms and
 | 
						|
# conditions see http://qt.digia.com/licensing.  For further information
 | 
						|
# use the contact form at http://qt.digia.com/contact-us.
 | 
						|
#
 | 
						|
# GNU Lesser General Public License Usage
 | 
						|
# Alternatively, this file may be used under the terms of the GNU Lesser
 | 
						|
# General Public License version 2.1 as published by the Free Software
 | 
						|
# Foundation and appearing in the file LICENSE.LGPL included in the
 | 
						|
# packaging of this file.  Please review the following information to
 | 
						|
# ensure the GNU Lesser General Public License version 2.1 requirements
 | 
						|
# will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
						|
#
 | 
						|
# In addition, as a special exception, Digia gives you certain additional
 | 
						|
# rights.  These rights are described in the Digia Qt LGPL Exception
 | 
						|
# version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | 
						|
#
 | 
						|
############################################################################
 | 
						|
 | 
						|
import os
 | 
						|
import sys
 | 
						|
import base64
 | 
						|
 | 
						|
if sys.version_info[0] >= 3:
 | 
						|
    xrange = range
 | 
						|
    toInteger = int
 | 
						|
else:
 | 
						|
    toInteger = long
 | 
						|
 | 
						|
 | 
						|
verbosity = 0
 | 
						|
verbosity = 1
 | 
						|
 | 
						|
qqStringCutOff = 10000
 | 
						|
 | 
						|
# This is a cache mapping from 'type name' to 'display alternatives'.
 | 
						|
qqFormats = {}
 | 
						|
 | 
						|
# This is a cache of all known dumpers.
 | 
						|
qqDumpers = {}
 | 
						|
 | 
						|
# This is a cache of all dumpers that support writing.
 | 
						|
qqEditable = {}
 | 
						|
 | 
						|
# This is an approximation of the Qt Version found
 | 
						|
qqVersion = None
 | 
						|
 | 
						|
# This keeps canonical forms of the typenames, without array indices etc.
 | 
						|
qqStripForFormat = {}
 | 
						|
 | 
						|
def stripForFormat(typeName):
 | 
						|
    global qqStripForFormat
 | 
						|
    if typeName in qqStripForFormat:
 | 
						|
        return qqStripForFormat[typeName]
 | 
						|
    stripped = ""
 | 
						|
    inArray = 0
 | 
						|
    for c in stripClassTag(typeName):
 | 
						|
        if c == '<':
 | 
						|
            break
 | 
						|
        if c == ' ':
 | 
						|
            continue
 | 
						|
        if c == '[':
 | 
						|
            inArray += 1
 | 
						|
        elif c == ']':
 | 
						|
            inArray -= 1
 | 
						|
        if inArray and ord(c) >= 48 and ord(c) <= 57:
 | 
						|
            continue
 | 
						|
        stripped +=  c
 | 
						|
    qqStripForFormat[typeName] = stripped
 | 
						|
    return stripped
 | 
						|
 | 
						|
def hasPlot():
 | 
						|
    fileName = "/usr/bin/gnuplot"
 | 
						|
    return os.path.isfile(fileName) and os.access(fileName, os.X_OK)
 | 
						|
 | 
						|
try:
 | 
						|
    import subprocess
 | 
						|
    def arrayForms():
 | 
						|
        if hasPlot():
 | 
						|
            return "Normal,Plot"
 | 
						|
        return "Normal"
 | 
						|
except:
 | 
						|
    def arrayForms():
 | 
						|
        return "Normal"
 | 
						|
 | 
						|
 | 
						|
def bytesToString(b):
 | 
						|
    if sys.version_info[0] == 2:
 | 
						|
        return b
 | 
						|
    return b.decode("utf8")
 | 
						|
 | 
						|
def stringToBytes(s):
 | 
						|
    if sys.version_info[0] == 2:
 | 
						|
        return s
 | 
						|
    return s.encode("utf8")
 | 
						|
 | 
						|
# Base 16 decoding operating on string->string
 | 
						|
def b16decode(s):
 | 
						|
    return bytesToString(base64.b16decode(stringToBytes(s), True))
 | 
						|
 | 
						|
# Base 16 decoding operating on string->string
 | 
						|
def b16encode(s):
 | 
						|
    return bytesToString(base64.b16encode(stringToBytes(s)))
 | 
						|
 | 
						|
# Base 64 decoding operating on string->string
 | 
						|
def b64decode(s):
 | 
						|
    return bytesToString(base64.b64decode(stringToBytes(s)))
 | 
						|
 | 
						|
# Base 64 decoding operating on string->string
 | 
						|
def b64encode(s):
 | 
						|
    return bytesToString(base64.b64encode(stringToBytes(s)))
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# Gnuplot based display for array-like structures.
 | 
						|
#
 | 
						|
gnuplotPipe = {}
 | 
						|
gnuplotPid = {}
 | 
						|
 | 
						|
def warn(message):
 | 
						|
    print("XXX: %s\n" % message.encode("latin1"))
 | 
						|
 | 
						|
 | 
						|
def showException(msg, exType, exValue, exTraceback):
 | 
						|
    warn("**** CAUGHT EXCEPTION: %s ****" % msg)
 | 
						|
    try:
 | 
						|
        import traceback
 | 
						|
        for line in traceback.format_exception(exType, exValue, exTraceback):
 | 
						|
            warn("%s" % line)
 | 
						|
    except:
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
def stripClassTag(typeName):
 | 
						|
    if typeName.startswith("class "):
 | 
						|
        return typeName[6:]
 | 
						|
    if typeName.startswith("struct "):
 | 
						|
        return typeName[7:]
 | 
						|
    if typeName.startswith("const "):
 | 
						|
        return typeName[6:]
 | 
						|
    if typeName.startswith("volatile "):
 | 
						|
        return typeName[9:]
 | 
						|
    return typeName
 | 
						|
 | 
						|
 | 
						|
class Children:
 | 
						|
    def __init__(self, d, numChild = 1, childType = None, childNumChild = None,
 | 
						|
            maxNumChild = None, addrBase = None, addrStep = None):
 | 
						|
        self.d = d
 | 
						|
        self.numChild = numChild
 | 
						|
        self.childNumChild = childNumChild
 | 
						|
        self.maxNumChild = maxNumChild
 | 
						|
        self.addrBase = addrBase
 | 
						|
        self.addrStep = addrStep
 | 
						|
        self.printsAddress = True
 | 
						|
        if childType is None:
 | 
						|
            self.childType = None
 | 
						|
        else:
 | 
						|
            self.childType = stripClassTag(str(childType))
 | 
						|
            self.d.put('childtype="%s",' % self.childType)
 | 
						|
            if childNumChild is None:
 | 
						|
                pass
 | 
						|
                #if self.d.isSimpleType(childType):
 | 
						|
                #    self.d.put('childnumchild="0",')
 | 
						|
                #    self.childNumChild = 0
 | 
						|
                #elif childType.code == PointerCode:
 | 
						|
                #    self.d.put('childnumchild="1",')
 | 
						|
                #    self.childNumChild = 1
 | 
						|
            else:
 | 
						|
                self.d.put('childnumchild="%s",' % childNumChild)
 | 
						|
                self.childNumChild = childNumChild
 | 
						|
        try:
 | 
						|
            if not addrBase is None and not addrStep is None:
 | 
						|
                self.d.put('addrbase="0x%x",' % toInteger(addrBase))
 | 
						|
                self.d.put('addrstep="0x%x",' % toInteger(addrStep))
 | 
						|
                self.printsAddress = False
 | 
						|
        except:
 | 
						|
            warn("ADDRBASE: %s" % addrBase)
 | 
						|
            warn("ADDRSTEP: %s" % addrStep)
 | 
						|
        #warn("CHILDREN: %s %s %s" % (numChild, childType, childNumChild))
 | 
						|
 | 
						|
    def __enter__(self):
 | 
						|
        self.savedChildType = self.d.currentChildType
 | 
						|
        self.savedChildNumChild = self.d.currentChildNumChild
 | 
						|
        self.savedNumChild = self.d.currentNumChild
 | 
						|
        self.savedMaxNumChild = self.d.currentMaxNumChild
 | 
						|
        self.savedPrintsAddress = self.d.currentPrintsAddress
 | 
						|
        self.d.currentChildType = self.childType
 | 
						|
        self.d.currentChildNumChild = self.childNumChild
 | 
						|
        self.d.currentNumChild = self.numChild
 | 
						|
        self.d.currentMaxNumChild = self.maxNumChild
 | 
						|
        self.d.currentPrintsAddress = self.printsAddress
 | 
						|
        self.d.put("children=[")
 | 
						|
 | 
						|
    def __exit__(self, exType, exValue, exTraceBack):
 | 
						|
        if not exType is None:
 | 
						|
            if self.d.passExceptions:
 | 
						|
                showException("CHILDREN", exType, exValue, exTraceBack)
 | 
						|
            self.d.putNumChild(0)
 | 
						|
            self.d.putValue("<not accessible>")
 | 
						|
        if not self.d.currentMaxNumChild is None:
 | 
						|
            if self.d.currentMaxNumChild < self.d.currentNumChild:
 | 
						|
                self.d.put('{name="<incomplete>",value="",type="",numchild="0"},')
 | 
						|
        self.d.currentChildType = self.savedChildType
 | 
						|
        self.d.currentChildNumChild = self.savedChildNumChild
 | 
						|
        self.d.currentNumChild = self.savedNumChild
 | 
						|
        self.d.currentMaxNumChild = self.savedMaxNumChild
 | 
						|
        self.d.currentPrintsAddress = self.savedPrintsAddress
 | 
						|
        self.d.put('],')
 | 
						|
        return True
 | 
						|
 | 
						|
 | 
						|
class SubItem:
 | 
						|
    def __init__(self, d, component):
 | 
						|
        self.d = d
 | 
						|
        self.name = component
 | 
						|
        self.iname = None
 | 
						|
 | 
						|
    def __enter__(self):
 | 
						|
        self.d.enterSubItem(self)
 | 
						|
 | 
						|
    def __exit__(self, exType, exValue, exTraceBack):
 | 
						|
        return self.d.exitSubItem(self, exType, exValue, exTraceBack)
 | 
						|
 | 
						|
class NoAddress:
 | 
						|
    def __init__(self, d):
 | 
						|
        self.d = d
 | 
						|
 | 
						|
    def __enter__(self):
 | 
						|
        self.savedPrintsAddress = self.d.currentPrintsAddress
 | 
						|
        self.d.currentPrintsAddress = False
 | 
						|
 | 
						|
    def __exit__(self, exType, exValue, exTraceBack):
 | 
						|
        self.d.currentPrintsAddress = self.savedPrintsAddress
 | 
						|
 | 
						|
class TopLevelItem(SubItem):
 | 
						|
    def __init__(self, d, iname):
 | 
						|
        self.d = d
 | 
						|
        self.iname = iname
 | 
						|
        self.name = None
 | 
						|
 | 
						|
class UnnamedSubItem(SubItem):
 | 
						|
    def __init__(self, d, component):
 | 
						|
        self.d = d
 | 
						|
        self.iname = "%s.%s" % (self.d.currentIName, component)
 | 
						|
        self.name = None
 | 
						|
 | 
						|
movableTypes = set([
 | 
						|
    "QBrush", "QBitArray", "QByteArray", "QCustomTypeInfo", "QChar", "QDate",
 | 
						|
    "QDateTime", "QFileInfo", "QFixed", "QFixedPoint", "QFixedSize",
 | 
						|
    "QHashDummyValue", "QIcon", "QImage", "QLine", "QLineF", "QLatin1Char",
 | 
						|
    "QLocale", "QMatrix", "QModelIndex", "QPoint", "QPointF", "QPen",
 | 
						|
    "QPersistentModelIndex", "QResourceRoot", "QRect", "QRectF", "QRegExp",
 | 
						|
    "QSize", "QSizeF", "QString", "QTime", "QTextBlock", "QUrl", "QVariant",
 | 
						|
    "QXmlStreamAttribute", "QXmlStreamNamespaceDeclaration",
 | 
						|
    "QXmlStreamNotationDeclaration", "QXmlStreamEntityDeclaration"
 | 
						|
])
 | 
						|
 | 
						|
movableTypes5 = set([
 | 
						|
    "QStringList"
 | 
						|
])
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class DumperBase:
 | 
						|
    def __init__(self):
 | 
						|
        self.isCdb = False
 | 
						|
        self.isGdb = False
 | 
						|
        self.isLldb = False
 | 
						|
 | 
						|
    def computeLimit(self, size, limit):
 | 
						|
        if limit is None:
 | 
						|
            return size
 | 
						|
        if limit == 0:
 | 
						|
            return min(size, qqStringCutOff)
 | 
						|
        return min(size, limit)
 | 
						|
 | 
						|
    def byteArrayDataHelper(self, addr):
 | 
						|
        if self.qtVersion() >= 0x050000:
 | 
						|
            # QTypedArray:
 | 
						|
            # - QtPrivate::RefCount ref
 | 
						|
            # - int size
 | 
						|
            # - uint alloc : 31, capacityReserved : 1
 | 
						|
            # - qptrdiff offset
 | 
						|
            size = self.extractInt(addr + 4)
 | 
						|
            alloc = self.extractInt(addr + 8) & 0x7ffffff
 | 
						|
            data = addr + self.dereference(addr + 8 + self.ptrSize())
 | 
						|
            if self.ptrSize() == 4:
 | 
						|
                data = data & 0xffffffff
 | 
						|
            else:
 | 
						|
                data = data & 0xffffffffffffffff
 | 
						|
        else:
 | 
						|
            # Data:
 | 
						|
            # - QBasicAtomicInt ref;
 | 
						|
            # - int alloc, size;
 | 
						|
            # - [padding]
 | 
						|
            # - char *data;
 | 
						|
            alloc = self.extractInt(addr + 4)
 | 
						|
            size = self.extractInt(addr + 8)
 | 
						|
            data = self.dereference(addr + 8 + self.ptrSize())
 | 
						|
        return data, size, alloc
 | 
						|
 | 
						|
    # addr is the begin of a QByteArrayData structure
 | 
						|
    def encodeStringHelper(self, addr, limit = 0):
 | 
						|
        # Should not happen, but we get it with LLDB as result
 | 
						|
        # of inferior calls
 | 
						|
        if addr == 0:
 | 
						|
            return ""
 | 
						|
        data, size, alloc = self.byteArrayDataHelper(addr)
 | 
						|
        if alloc != 0:
 | 
						|
            self.check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
 | 
						|
        limit = self.computeLimit(size, limit)
 | 
						|
        s = self.readMemory(data, 2 * limit)
 | 
						|
        if limit < size:
 | 
						|
            s += "2e002e002e00"
 | 
						|
        return s
 | 
						|
 | 
						|
    def encodeByteArrayHelper(self, addr, limit = None):
 | 
						|
        data, size, alloc = self.byteArrayDataHelper(addr)
 | 
						|
        if alloc != 0:
 | 
						|
            self.check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
 | 
						|
        limit = self.computeLimit(size, limit)
 | 
						|
        s = self.readMemory(data, limit)
 | 
						|
        if limit < size:
 | 
						|
            s += "2e2e2e"
 | 
						|
        return s
 | 
						|
 | 
						|
    def encodeByteArray(self, value):
 | 
						|
        return self.encodeByteArrayHelper(self.dereferenceValue(value))
 | 
						|
 | 
						|
    def byteArrayData(self, value):
 | 
						|
        return self.byteArrayDataHelper(self.dereferenceValue(value))
 | 
						|
 | 
						|
    def putByteArrayValue(self, value):
 | 
						|
        return self.putValue(self.encodeByteArray(value), Hex2EncodedLatin1)
 | 
						|
 | 
						|
    def putStringValueByAddress(self, addr):
 | 
						|
        self.putValue(self.encodeStringHelper(self.dereference(addr)),
 | 
						|
            Hex4EncodedLittleEndian)
 | 
						|
 | 
						|
    def encodeString(self, value):
 | 
						|
        return self.encodeStringHelper(self.dereferenceValue(value))
 | 
						|
 | 
						|
    def stringData(self, value):
 | 
						|
        return self.byteArrayDataHelper(self.dereferenceValue(value))
 | 
						|
 | 
						|
    def putStringValue(self, value):
 | 
						|
        return self.putValue(self.encodeString(value), Hex4EncodedLittleEndian)
 | 
						|
 | 
						|
    def putMapName(self, value):
 | 
						|
        if str(value.type) == self.ns + "QString":
 | 
						|
            self.put('key="%s",' % self.encodeString(value))
 | 
						|
            self.put('keyencoded="%s",' % Hex4EncodedLittleEndian)
 | 
						|
        elif str(value.type) == self.ns + "QByteArray":
 | 
						|
            self.put('key="%s",' % self.encodeByteArray(value))
 | 
						|
            self.put('keyencoded="%s",' % Hex2EncodedLatin1)
 | 
						|
        else:
 | 
						|
            if self.isLldb:
 | 
						|
                self.put('name="%s",' % value.GetValue())
 | 
						|
            else:
 | 
						|
                self.put('name="%s",' % value)
 | 
						|
 | 
						|
    def isMapCompact(self, keyType, valueType):
 | 
						|
        format = self.currentItemFormat()
 | 
						|
        if format == 2:
 | 
						|
            return True # Compact.
 | 
						|
        return self.isSimpleType(keyType) and self.isSimpleType(valueType)
 | 
						|
 | 
						|
 | 
						|
    def check(self, exp):
 | 
						|
        if not exp:
 | 
						|
            raise RuntimeError("Check failed")
 | 
						|
 | 
						|
    def checkRef(self, ref):
 | 
						|
        try:
 | 
						|
            count = int(ref["atomic"]["_q_value"]) # Qt 5.
 | 
						|
            minimum = -1
 | 
						|
        except:
 | 
						|
            count = int(ref["_q_value"]) # Qt 4.
 | 
						|
            minimum = 0
 | 
						|
        # Assume there aren't a million references to any object.
 | 
						|
        self.check(count >= minimum)
 | 
						|
        self.check(count < 1000000)
 | 
						|
 | 
						|
    def findFirstZero(self, p, maximum):
 | 
						|
        for i in xrange(maximum):
 | 
						|
            if int(p.dereference()) == 0:
 | 
						|
                return i
 | 
						|
            p = p + 1
 | 
						|
        return maximum + 1
 | 
						|
 | 
						|
    def encodeCArray(self, p, innerType, suffix):
 | 
						|
        t = self.lookupType(innerType)
 | 
						|
        p = p.cast(t.pointer())
 | 
						|
        limit = self.findFirstZero(p, qqStringCutOff)
 | 
						|
        s = self.readMemory(p, limit * t.sizeof)
 | 
						|
        if limit > qqStringCutOff:
 | 
						|
            s += suffix
 | 
						|
        return s
 | 
						|
 | 
						|
    def encodeCharArray(self, p):
 | 
						|
        return self.encodeCArray(p, "unsigned char", "2e2e2e")
 | 
						|
 | 
						|
    def encodeChar2Array(self, p):
 | 
						|
        return self.encodeCArray(p, "unsigned short", "2e002e002e00")
 | 
						|
 | 
						|
    def encodeChar4Array(self, p):
 | 
						|
        return self.encodeCArray(p, "unsigned int", "2e0000002e0000002e000000")
 | 
						|
 | 
						|
    def putQObjectNameValue(self, value):
 | 
						|
        try:
 | 
						|
            intSize = self.intSize()
 | 
						|
            ptrSize = self.ptrSize()
 | 
						|
            # dd = value["d_ptr"]["d"] is just behind the vtable.
 | 
						|
            dd = self.dereference(self.addressOf(value) + ptrSize)
 | 
						|
 | 
						|
            if self.qtVersion() < 0x050000:
 | 
						|
                # Size of QObjectData: 5 pointer + 2 int
 | 
						|
                #  - vtable
 | 
						|
                #   - QObject *q_ptr;
 | 
						|
                #   - QObject *parent;
 | 
						|
                #   - QObjectList children;
 | 
						|
                #   - uint isWidget : 1; etc..
 | 
						|
                #   - int postedEvents;
 | 
						|
                #   - QMetaObject *metaObject;
 | 
						|
 | 
						|
                # Offset of objectName in QObjectPrivate: 5 pointer + 2 int
 | 
						|
                #   - [QObjectData base]
 | 
						|
                #   - QString objectName
 | 
						|
                objectName = self.dereference(dd + 5 * ptrSize + 2 * intSize)
 | 
						|
 | 
						|
            else:
 | 
						|
                # Size of QObjectData: 5 pointer + 2 int
 | 
						|
                #   - vtable
 | 
						|
                #   - QObject *q_ptr;
 | 
						|
                #   - QObject *parent;
 | 
						|
                #   - QObjectList children;
 | 
						|
                #   - uint isWidget : 1; etc...
 | 
						|
                #   - int postedEvents;
 | 
						|
                #   - QDynamicMetaObjectData *metaObject;
 | 
						|
                extra = self.dereference(dd + 5 * ptrSize + 2 * intSize)
 | 
						|
                if extra == 0:
 | 
						|
                    return False
 | 
						|
 | 
						|
                # Offset of objectName in ExtraData: 6 pointer
 | 
						|
                #   - QVector<QObjectUserData *> userData; only #ifndef QT_NO_USERDATA
 | 
						|
                #   - QList<QByteArray> propertyNames;
 | 
						|
                #   - QList<QVariant> propertyValues;
 | 
						|
                #   - QVector<int> runningTimers;
 | 
						|
                #   - QList<QPointer<QObject> > eventFilters;
 | 
						|
                #   - QString objectName
 | 
						|
                objectName = self.dereference(extra + 5 * ptrSize)
 | 
						|
 | 
						|
            data, size, alloc = self.byteArrayDataHelper(objectName)
 | 
						|
 | 
						|
            if size == 0:
 | 
						|
                return False
 | 
						|
 | 
						|
            str = self.readMemory(data, 2 * size)
 | 
						|
            self.putValue(str, Hex4EncodedLittleEndian, 1)
 | 
						|
            return True
 | 
						|
 | 
						|
        except:
 | 
						|
            pass
 | 
						|
 | 
						|
def cleanAddress(addr):
 | 
						|
    if addr is None:
 | 
						|
        return "<no address>"
 | 
						|
    # We cannot use str(addr) as it yields rubbish for char pointers
 | 
						|
    # that might trigger Unicode encoding errors.
 | 
						|
    #return addr.cast(lookupType("void").pointer())
 | 
						|
    # We do not use "hex(...)" as it (sometimes?) adds a "L" suffix.
 | 
						|
    return "0x%x" % toInteger(addr)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
# Some "Enums"
 | 
						|
 | 
						|
# Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h
 | 
						|
Unencoded8Bit, \
 | 
						|
Base64Encoded8BitWithQuotes, \
 | 
						|
Base64Encoded16BitWithQuotes, \
 | 
						|
Base64Encoded32BitWithQuotes, \
 | 
						|
Base64Encoded16Bit, \
 | 
						|
Base64Encoded8Bit, \
 | 
						|
Hex2EncodedLatin1, \
 | 
						|
Hex4EncodedLittleEndian, \
 | 
						|
Hex8EncodedLittleEndian, \
 | 
						|
Hex2EncodedUtf8, \
 | 
						|
Hex8EncodedBigEndian, \
 | 
						|
Hex4EncodedBigEndian, \
 | 
						|
Hex4EncodedLittleEndianWithoutQuotes, \
 | 
						|
Hex2EncodedLocal8Bit, \
 | 
						|
JulianDate, \
 | 
						|
MillisecondsSinceMidnight, \
 | 
						|
JulianDateAndMillisecondsSinceMidnight, \
 | 
						|
Hex2EncodedInt1, \
 | 
						|
Hex2EncodedInt2, \
 | 
						|
Hex2EncodedInt4, \
 | 
						|
Hex2EncodedInt8, \
 | 
						|
Hex2EncodedUInt1, \
 | 
						|
Hex2EncodedUInt2, \
 | 
						|
Hex2EncodedUInt4, \
 | 
						|
Hex2EncodedUInt8, \
 | 
						|
Hex2EncodedFloat4, \
 | 
						|
Hex2EncodedFloat8, \
 | 
						|
IPv6AddressAndHexScopeId, \
 | 
						|
Hex2EncodedUtf8WithoutQuotes, \
 | 
						|
MillisecondsSinceEpoch \
 | 
						|
    = range(30)
 | 
						|
 | 
						|
# Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h
 | 
						|
StopDisplay, \
 | 
						|
DisplayImageData, \
 | 
						|
DisplayUtf16String, \
 | 
						|
DisplayImageFile, \
 | 
						|
DisplayProcess, \
 | 
						|
DisplayLatin1String, \
 | 
						|
DisplayUtf8String \
 | 
						|
    = range(7)
 | 
						|
 | 
						|
 | 
						|
def mapForms():
 | 
						|
    return "Normal,Compact"
 | 
						|
 | 
						|
def arrayForms():
 | 
						|
    if hasPlot():
 | 
						|
        return "Normal,Plot"
 | 
						|
    return "Normal"
 | 
						|
 |