forked from qt-creator/qt-creator
debugger: implement selected of string encoding per pointer type/individual pointer
This commit is contained in:
@@ -432,12 +432,50 @@ def qtNamespace():
|
||||
# Happens for none-Qt applications
|
||||
return ""
|
||||
|
||||
def encodeCharArray(p, size):
|
||||
def findFirstZero(p, max):
|
||||
for i in xrange(max):
|
||||
if p.dereference() == 0:
|
||||
return i
|
||||
p = p + 1
|
||||
return -1
|
||||
|
||||
def encodeCharArray(p, maxsize):
|
||||
t = gdb.lookup_type("unsigned char").pointer()
|
||||
p = p.cast(t)
|
||||
i = findFirstZero(p, maxsize)
|
||||
limit = select(i < 0, maxsize, i)
|
||||
s = ""
|
||||
p = p.cast(gdb.lookup_type("unsigned char").pointer())
|
||||
for i in xrange(size):
|
||||
for i in xrange(limit):
|
||||
s += "%02x" % int(p.dereference())
|
||||
p += 1
|
||||
if i == maxsize:
|
||||
s += "2e2e2e"
|
||||
return s
|
||||
|
||||
def encodeChar2Array(p, maxsize):
|
||||
t = gdb.lookup_type("unsigned short").pointer()
|
||||
p = p.cast(t)
|
||||
i = findFirstZero(p, maxsize)
|
||||
limit = select(i < 0, maxsize, i)
|
||||
s = ""
|
||||
for i in xrange(limit):
|
||||
s += "%04x" % int(p.dereference())
|
||||
p += 1
|
||||
if i == maxsize:
|
||||
s += "2e002e002e00"
|
||||
return s
|
||||
|
||||
def encodeChar4Array(p, maxsize):
|
||||
t = gdb.lookup_type("unsigned int").pointer()
|
||||
p = p.cast(t)
|
||||
i = findFirstZero(p, maxsize)
|
||||
limit = select(i < 0, maxsize, i)
|
||||
s = ""
|
||||
for i in xrange(limit):
|
||||
s += "%08x" % int(p.dereference())
|
||||
p += 1
|
||||
if i == maxsize:
|
||||
s += "2e0000002e0000002e000000"
|
||||
return s
|
||||
|
||||
def encodeByteArray(value):
|
||||
@@ -450,10 +488,7 @@ def encodeByteArray(value):
|
||||
if size > 0:
|
||||
checkAccess(data, 4)
|
||||
checkAccess(data + size) == 0
|
||||
|
||||
innerType = gdb.lookup_type("char")
|
||||
p = gdb.Value(data.cast(innerType.pointer()))
|
||||
return encodeCharArray(p, size)
|
||||
return encodeCharArray(data, size)
|
||||
|
||||
def encodeString(value):
|
||||
d_ptr = value['d'].dereference()
|
||||
@@ -502,22 +537,33 @@ class FrameCommand(gdb.Command):
|
||||
def __init__(self):
|
||||
super(FrameCommand, self).__init__("bb", gdb.COMMAND_OBSCURE)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
args = arg.split(' ')
|
||||
|
||||
#warn("ARG: %s" % arg)
|
||||
#warn("ARGS: %s" % args)
|
||||
options = args[0].split(",")
|
||||
varList = args[1][1:]
|
||||
if len(varList) == 0:
|
||||
def invoke(self, args, from_tty):
|
||||
options = []
|
||||
varList = []
|
||||
else:
|
||||
varList = varList.split(",")
|
||||
expandedINames = set(args[2].split(","))
|
||||
typeformats = {}
|
||||
formats = {}
|
||||
watchers = ""
|
||||
if len(args) > 3:
|
||||
watchers = base64.b16decode(args[3], True)
|
||||
#warn("WATCHERS: %s" % watchers)
|
||||
for arg in args.split(' '):
|
||||
pos = arg.find(":") + 1
|
||||
if arg.startswith("options:"):
|
||||
options = arg[pos:].split(",")
|
||||
elif arg.startswith("vars:"):
|
||||
vars = arg[pos:].split(",")
|
||||
elif arg.startswith("expanded:"):
|
||||
expandedINames = set(arg[pos:].split(","))
|
||||
elif arg.startswith("typeformats:"):
|
||||
for f in arg[pos:].split(","):
|
||||
pos = f.find("=")
|
||||
if pos != -1:
|
||||
type = base64.b16decode(f[0:pos], True)
|
||||
typeformats[type] = int(f[pos+1:])
|
||||
elif arg.startswith("formats:"):
|
||||
for f in arg[pos:].split(","):
|
||||
pos = f.find("=")
|
||||
if pos != -1:
|
||||
formats[f[0:pos]] = int(f[pos+1:])
|
||||
elif arg.startswith("watchers:"):
|
||||
watchers = base64.b16decode(arg[pos:], True)
|
||||
|
||||
useFancy = "fancy" in options
|
||||
|
||||
@@ -552,6 +598,8 @@ class FrameCommand(gdb.Command):
|
||||
|
||||
d = Dumper()
|
||||
d.dumpers = self.dumpers
|
||||
d.typeformats = typeformats
|
||||
d.formats = formats
|
||||
d.useFancy = useFancy
|
||||
d.passExceptions = "passexceptions" in options
|
||||
d.autoDerefPointers = "autoderef" in options
|
||||
@@ -837,6 +885,9 @@ class Dumper:
|
||||
if len(type) > 0 and type != self.childTypes[-1]:
|
||||
self.put('type="%s",' % type) # str(type.unqualified()) ?
|
||||
|
||||
def putAddress(self, addr):
|
||||
self.put('addr="%s",' % cleanAddress(addr))
|
||||
|
||||
def putNumChild(self, numchild):
|
||||
#warn("NUM CHILD: '%s' '%s'" % (numchild, self.childNumChilds[-1]))
|
||||
if numchild != self.childNumChilds[-1]:
|
||||
@@ -1038,13 +1089,36 @@ class Dumper:
|
||||
|
||||
|
||||
elif type.code == gdb.TYPE_CODE_PTR:
|
||||
#warn("A POINTER: %s" % value.type)
|
||||
isHandled = False
|
||||
|
||||
if str(type.strip_typedefs()).find("(") != -1:
|
||||
format = self.formats.get(item.iname)
|
||||
if format is None:
|
||||
format = self.typeformats.get(str(value.type))
|
||||
|
||||
if not format is None:
|
||||
self.putAddress(value.address)
|
||||
self.putType(item.value.type)
|
||||
self.putNumChild(0)
|
||||
isHandled = True
|
||||
|
||||
if format == 0:
|
||||
# Bald pointer.
|
||||
self.putValue(str(cleanAddress(value.address)))
|
||||
elif format == 1 or format == 2:
|
||||
# Latin1 or UTF-8
|
||||
f = select(format == 1, "6", "9")
|
||||
self.putValue(encodeCharArray(value, 100), f)
|
||||
elif format == 3:
|
||||
# UTF-16.
|
||||
self.putValue(encodeChar2Array(value, 100), "11")
|
||||
elif format == 4:
|
||||
# UCS-4:
|
||||
self.putValue(encodeChar4Array(value, 100), "10")
|
||||
|
||||
if (not isHandled) and str(type.strip_typedefs()).find("(") != -1:
|
||||
# A function pointer.
|
||||
self.putValue(str(item.value))
|
||||
self.put('addr="%s",' % cleanAddress(value.address))
|
||||
self.putAddress(value.address)
|
||||
self.putType(item.value.type)
|
||||
self.putNumChild(0)
|
||||
isHandled = True
|
||||
@@ -1069,20 +1143,7 @@ class Dumper:
|
||||
# Display values up to given length directly
|
||||
#warn("CHAR AUTODEREF: %s" % value.address)
|
||||
self.putType(item.value.type)
|
||||
firstNul = -1
|
||||
p = value
|
||||
found = False
|
||||
for i in xrange(100):
|
||||
if p.dereference() == 0:
|
||||
# Found terminating NUL
|
||||
found = True
|
||||
break
|
||||
p += 1
|
||||
if found:
|
||||
self.putValue(encodeCharArray(value, i), "6")
|
||||
self.putNumChild(0)
|
||||
else:
|
||||
self.putValue(encodeCharArray(value, 100) + "2e2e2e", "6")
|
||||
self.putValue(encodeCharArray(value, 100), "6")
|
||||
self.putNumChild(0)
|
||||
isHandled = True
|
||||
|
||||
@@ -1105,8 +1166,9 @@ class Dumper:
|
||||
if not isHandled:
|
||||
#warn("GENERIC PLAIN POINTER: %s" % value.type)
|
||||
self.putType(item.value.type)
|
||||
self.putValue(str(value))
|
||||
self.put('addr="%s",' % cleanAddress(value.address))
|
||||
#self.putValue(str(value))
|
||||
self.putValue("")
|
||||
self.putAddress(value.address)
|
||||
self.putNumChild(1)
|
||||
if self.isExpanded(item):
|
||||
self.beginChildren()
|
||||
@@ -1208,7 +1270,7 @@ class Dumper:
|
||||
value = item.value[field.name]
|
||||
child = Item(value, item.iname, field.name, field.name)
|
||||
self.beginHash()
|
||||
self.put('addr="%s",' % cleanAddress(value.address))
|
||||
self.putAddress(value.address)
|
||||
self.putItemHelper(child)
|
||||
self.endHash();
|
||||
else:
|
||||
|
||||
@@ -252,10 +252,10 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
|
||||
return;
|
||||
}
|
||||
|
||||
// we should have a type now. this is relied upon further below
|
||||
// We should have a type now. This is relied upon further below.
|
||||
QTC_ASSERT(!data.type.isEmpty(), return);
|
||||
|
||||
// a common case that can be easily solved
|
||||
// A common case that can be easily solved.
|
||||
if (data.isChildrenNeeded() && isPointerType(data.type)
|
||||
&& !hasDebuggingHelperForType(data.type)) {
|
||||
// We sometimes know what kind of children pointers have
|
||||
@@ -431,8 +431,6 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
||||
while (out.endsWith(' ') || out.endsWith('\n'))
|
||||
out.chop(1);
|
||||
QList<QByteArray> list = out.split(' ');
|
||||
//qDebug() << "RECEIVED" << response.toString() << "FOR" << data0.toString()
|
||||
// << " STREAM:" << out;
|
||||
if (list.isEmpty()) {
|
||||
//: Value for variable
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
@@ -538,7 +536,7 @@ void GdbEngine::tryLoadDebuggingHelpersClassic()
|
||||
postCommand("call (void*)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
|
||||
+ "\", " + flag + ")",
|
||||
CB(handleDebuggingHelperSetup));
|
||||
// some older systems like CentOS 4.6 prefer this:
|
||||
// Some older systems like CentOS 4.6 prefer this:
|
||||
postCommand("call (void*)__dlopen(\"" + GdbMi::escapeCString(dlopenLib)
|
||||
+ "\", " + flag + ")",
|
||||
CB(handleDebuggingHelperSetup));
|
||||
@@ -550,7 +548,7 @@ void GdbEngine::tryLoadDebuggingHelpersClassic()
|
||||
void GdbEngine::tryQueryDebuggingHelpersClassic()
|
||||
{
|
||||
PRECONDITION;
|
||||
// retrieve list of dumpable classes
|
||||
// Retrieve list of dumpable classes.
|
||||
postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
|
||||
postCommand("p (char*)&qDumpOutBuffer",
|
||||
CB(handleQueryDebuggingHelperClassic));
|
||||
@@ -560,7 +558,7 @@ void GdbEngine::recheckDebuggingHelperAvailabilityClassic()
|
||||
{
|
||||
PRECONDITION;
|
||||
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
|
||||
// retrieve list of dumpable classes
|
||||
// Retrieve list of dumpable classes.
|
||||
postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
|
||||
postCommand("p (char*)&qDumpOutBuffer",
|
||||
CB(handleQueryDebuggingHelperClassic));
|
||||
@@ -681,7 +679,6 @@ bool GdbEngine::checkDebuggingHelpersClassic()
|
||||
if (!manager()->qtDumperLibraryEnabled())
|
||||
return false;
|
||||
const QString lib = qtDumperLibraryName();
|
||||
//qDebug() << "DUMPERLIB:" << lib;
|
||||
const QFileInfo fi(lib);
|
||||
if (!fi.exists()) {
|
||||
const QStringList &locations = manager()->qtDumperLibraryLocations();
|
||||
|
||||
@@ -3321,7 +3321,7 @@ void GdbEngine::setWatchDataDisplayedType(WatchData &data, const GdbMi &item)
|
||||
void GdbEngine::handleVarCreate(const GdbResponse &response)
|
||||
{
|
||||
WatchData data = response.cookie.value<WatchData>();
|
||||
// happens e.g. when we already issued a var-evaluate command
|
||||
// Happens e.g. when we already issued a var-evaluate command.
|
||||
if (!data.isValid())
|
||||
return;
|
||||
//qDebug() << "HANDLE VARIABLE CREATION:" << data.toString();
|
||||
@@ -3351,11 +3351,9 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
|
||||
|
||||
void GdbEngine::handleDebuggingHelperSetup(const GdbResponse &response)
|
||||
{
|
||||
//qDebug() << "CUSTOM SETUP RESULT:" << response.toString();
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
} else {
|
||||
QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
|
||||
//qDebug() << "CUSTOM DUMPER SETUP ERROR MESSAGE:" << msg;
|
||||
showStatusMessage(tr("Custom dumper setup: %1").arg(msg), 10000);
|
||||
}
|
||||
}
|
||||
@@ -3381,7 +3379,6 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
|
||||
}
|
||||
setWatchDataType(data, item.findChild("type"));
|
||||
setWatchDataEditValue(data, item.findChild("editvalue"));
|
||||
setWatchDataChildCount(data, item.findChild("numchild"));
|
||||
setWatchDataValue(data, item.findChild("value"),
|
||||
item.findChild("valueencoded").data().toInt());
|
||||
setWatchDataAddress(data, item.findChild("addr"));
|
||||
@@ -3391,6 +3388,7 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
|
||||
item.findChild("valuetooltipencoded").data().toInt());
|
||||
setWatchDataValueEnabled(data, item.findChild("valueenabled"));
|
||||
setWatchDataValueEditable(data, item.findChild("valueeditable"));
|
||||
setWatchDataChildCount(data, item.findChild("numchild"));
|
||||
//qDebug() << "\nAPPEND TO LIST: " << data.toString() << "\n";
|
||||
list->append(data);
|
||||
|
||||
@@ -3451,7 +3449,7 @@ void GdbEngine::updateLocals(const QVariant &cookie)
|
||||
}
|
||||
|
||||
|
||||
// Parse a local variable from GdbMi
|
||||
// Parse a local variable from GdbMi.
|
||||
WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||
const QStringList &uninitializedVariables,
|
||||
QMap<QByteArray, int> *seen)
|
||||
@@ -3479,7 +3477,7 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||
WatchData data;
|
||||
QString nam = _(name);
|
||||
data.iname = "local." + name + QByteArray::number(n + 1);
|
||||
//: Variable %1 is the variable name, %2 is a simple count
|
||||
//: Variable %1 is the variable name, %2 is a simple count.
|
||||
data.name = WatchData::shadowedName(nam, n);
|
||||
if (uninitializedVariables.contains(data.name)) {
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
@@ -3511,8 +3509,8 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||
// somewhere in the response.
|
||||
data.setChildrenUnneeded();
|
||||
} else {
|
||||
// set value only directly if it is simple enough, otherwise
|
||||
// pass through the insertData() machinery
|
||||
// Set value only directly if it is simple enough, otherwise
|
||||
// pass through the insertData() machinery.
|
||||
if (isIntOrFloatType(data.type) || isPointerType(data.type))
|
||||
setWatchDataValue(data, item.findChild("value"));
|
||||
if (isSymbianIntType(data.type)) {
|
||||
@@ -3523,7 +3521,11 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||
|
||||
if (!m_manager->watchHandler()->isExpandedIName(data.iname))
|
||||
data.setChildrenUnneeded();
|
||||
if (isPointerType(data.type) || data.name == __("this"))
|
||||
|
||||
GdbMi t = item.findChild("numchild");
|
||||
if (t.isValid())
|
||||
data.setHasChildren(t.data().toInt() > 0);
|
||||
else if (isPointerType(data.type) || data.name == __("this"))
|
||||
data.setHasChildren(true);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -55,13 +55,7 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList)
|
||||
//m_toolTipExpression.clear();
|
||||
WatchHandler *handler = m_manager->watchHandler();
|
||||
|
||||
QByteArray expanded;
|
||||
QSet<QByteArray> expandedINames = handler->expandedINames();
|
||||
QSetIterator<QByteArray> jt(expandedINames);
|
||||
while (jt.hasNext()) {
|
||||
expanded.append(jt.next());
|
||||
expanded.append(',');
|
||||
}
|
||||
QByteArray expanded = handler->formatRequests();
|
||||
if (expanded.isEmpty())
|
||||
expanded.append("defaults,");
|
||||
expanded.chop(1);
|
||||
@@ -92,8 +86,8 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList)
|
||||
options += "defaults,";
|
||||
options.chop(1);
|
||||
|
||||
postCommand("bb " + options + " @" + varList + ' '
|
||||
+ expanded + ' ' + watchers.toHex(),
|
||||
postCommand("bb options:" + options + " vars:" + varList + ' '
|
||||
+ expanded + " watchers:" + watchers.toHex(),
|
||||
WatchUpdate, CB(handleStackFramePython));
|
||||
}
|
||||
|
||||
|
||||
@@ -639,27 +639,6 @@ static QString formattedValue(const WatchData &data, int format)
|
||||
return reformatInteger(data.value.toULongLong(), format);
|
||||
return reformatInteger(data.value.toLongLong(), format);
|
||||
}
|
||||
if (0 && !data.addr.isEmpty()) {
|
||||
if (format == BaldPointerFormat)
|
||||
return data.value;
|
||||
bool ok = false;
|
||||
const void *addr =
|
||||
reinterpret_cast<void *>(data.value.toULongLong(&ok, 0));
|
||||
if (!ok || !addr)
|
||||
return data.value;
|
||||
// FIXME: add a round trip through the debugger to prevent crashs?
|
||||
if (format == Latin1StringFormat)
|
||||
return QString::fromLatin1(static_cast<const char *>(addr));
|
||||
if (format == Local8BitStringFormat)
|
||||
return QString::fromLocal8Bit(static_cast<const char *>(addr));
|
||||
if (format == Utf8StringFormat)
|
||||
return QString::fromUtf8(static_cast<const char *>(addr));
|
||||
if (format == Utf16StringFormat)
|
||||
return QString::fromUtf16(static_cast<const ushort *>(addr));
|
||||
if (format == Ucs4StringFormat)
|
||||
return QString::fromUcs4(static_cast<const uint *>(addr));
|
||||
return data.value;
|
||||
}
|
||||
return data.value;
|
||||
}
|
||||
|
||||
@@ -802,7 +781,6 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
||||
int format = m_handler->m_individualFormats.value(data.iname, -1);
|
||||
if (format == -1)
|
||||
format = m_handler->m_typeFormats.value(data.type, -1);
|
||||
//qDebug() << "FORMATTED: " << format << formattedValue(data, format);
|
||||
return truncateValue(formattedValue(data, format));
|
||||
}
|
||||
case 2: {
|
||||
@@ -845,7 +823,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
||||
if (isIntType(data.type))
|
||||
return QStringList() << tr("decimal") << tr("hexadecimal")
|
||||
<< tr("binary") << tr("octal");
|
||||
if (!data.addr.isEmpty())
|
||||
if (data.type.endsWith(QLatin1Char('*')))
|
||||
return QStringList()
|
||||
<< tr("Bald pointer")
|
||||
<< tr("Latin1 string")
|
||||
@@ -889,6 +867,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
}
|
||||
} else if (role == TypeFormatRole) {
|
||||
m_handler->setFormat(data.type, value.toInt());
|
||||
m_handler->m_manager->updateWatchData(data);
|
||||
} else if (role == IndividualFormatRole) {
|
||||
const int format = value.toInt();
|
||||
if (format == -1) {
|
||||
@@ -896,6 +875,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
} else {
|
||||
m_handler->m_individualFormats[data.iname] = format;
|
||||
}
|
||||
m_handler->m_manager->updateWatchData(data);
|
||||
}
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
@@ -1155,8 +1135,8 @@ WatchItem *WatchModel::findItem(const QByteArray &iname, WatchItem *root) const
|
||||
static void debugRecursion(QDebug &d, const WatchItem *item, int depth)
|
||||
{
|
||||
d << QString(2 * depth, QLatin1Char(' ')) << item->toString() << '\n';
|
||||
foreach(const WatchItem *i, item->children)
|
||||
debugRecursion(d, i, depth + 1);
|
||||
foreach (const WatchItem *child, item->children)
|
||||
debugRecursion(d, child, depth + 1);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const WatchModel &m)
|
||||
@@ -1167,6 +1147,16 @@ QDebug operator<<(QDebug d, const WatchModel &m)
|
||||
return d;
|
||||
}
|
||||
|
||||
void WatchModel::formatRequests(QByteArray *out, const WatchItem *item) const
|
||||
{
|
||||
int format = m_handler->m_individualFormats.value(item->iname, -1);
|
||||
if (format == -1)
|
||||
format = m_handler->m_typeFormats.value(item->type, -1);
|
||||
if (format != -1)
|
||||
*out += item->iname + ":format=" + QByteArray::number(format) + ',';
|
||||
foreach (const WatchItem *child, item->children)
|
||||
formatRequests(out, child);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -1573,5 +1563,65 @@ void WatchHandler::setFormat(const QString &type, int format)
|
||||
m_tooltips->emitDataChanged(1);
|
||||
}
|
||||
|
||||
int WatchHandler::format(const QByteArray &iname) const
|
||||
{
|
||||
int result = -1;
|
||||
if (const WatchData *item = findItem(iname)) {
|
||||
int result = m_individualFormats.value(iname, -1);
|
||||
if (result == -1)
|
||||
result = m_typeFormats.value(item->type, -1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray WatchHandler::formatRequests() const
|
||||
{
|
||||
QByteArray ba;
|
||||
//m_locals->formatRequests(&ba, m_locals->m_root);
|
||||
//m_watchers->formatRequests(&ba, m_watchers->m_root);
|
||||
|
||||
ba.append("expanded:");
|
||||
if (!m_expandedINames.isEmpty()) {
|
||||
QSetIterator<QByteArray> jt(m_expandedINames);
|
||||
while (jt.hasNext()) {
|
||||
QByteArray iname = jt.next();
|
||||
ba.append(iname);
|
||||
ba.append(',');
|
||||
}
|
||||
ba.chop(1);
|
||||
}
|
||||
ba.append(' ');
|
||||
|
||||
ba.append("typeformats:");
|
||||
if (!m_typeFormats.isEmpty()) {
|
||||
QHashIterator<QString, int> it(m_typeFormats);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
ba.append(it.key().toLatin1().toHex());
|
||||
ba.append('=');
|
||||
ba.append(QByteArray::number(it.value()));
|
||||
ba.append(',');
|
||||
}
|
||||
ba.chop(1);
|
||||
}
|
||||
ba.append(' ');
|
||||
|
||||
ba.append("formats:");
|
||||
if (!m_individualFormats.isEmpty()) {
|
||||
QHashIterator<QString, int> it(m_individualFormats);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
ba.append(it.key().toLatin1());
|
||||
ba.append('=');
|
||||
ba.append(QByteArray::number(it.value()));
|
||||
ba.append(',');
|
||||
}
|
||||
ba.chop(1);
|
||||
}
|
||||
ba.append(' ');
|
||||
|
||||
return ba;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -139,8 +139,6 @@ public:
|
||||
bool valueEditable; // value will be editable
|
||||
bool error;
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
int source; // Used by some debuggers (CDB) to tell where it originates from (dumper or symbol evaluation)
|
||||
int state;
|
||||
@@ -239,6 +237,7 @@ signals:
|
||||
|
||||
private:
|
||||
QString niceType(const QString &typeIn) const;
|
||||
void formatRequests(QByteArray *out, const WatchItem *item) const;
|
||||
|
||||
WatchHandler *m_handler;
|
||||
WatchType m_type;
|
||||
@@ -284,8 +283,10 @@ public:
|
||||
QStringList watchedExpressions() const;
|
||||
QHash<QByteArray, int> watcherNames() const
|
||||
{ return m_watcherNames; }
|
||||
QByteArray formatRequests() const;
|
||||
|
||||
static QString watcherEditPlaceHolder();
|
||||
int format(const QByteArray &iname) const;
|
||||
|
||||
private:
|
||||
friend class WatchModel;
|
||||
|
||||
@@ -640,7 +640,7 @@ QString decodeData(const QByteArray &ba, int encoding)
|
||||
case 5: { // base64 encoded 8 bit data, without quotes (see 1)
|
||||
return quoteUnprintableLatin1(QByteArray::fromBase64(ba));
|
||||
}
|
||||
case 6: { // %02x encoded 8 bit data
|
||||
case 6: { // %02x encoded 8 bit Latin1 data
|
||||
const QChar doubleQuote(QLatin1Char('"'));
|
||||
const QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||
@@ -660,6 +660,39 @@ QString decodeData(const QByteArray &ba, int encoding)
|
||||
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
||||
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
||||
}
|
||||
case 9: { // %02x encoded 8 bit Utf-8 data
|
||||
const QChar doubleQuote(QLatin1Char('"'));
|
||||
const QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||
return doubleQuote + QString::fromUtf8(decodedBa) + doubleQuote;
|
||||
}
|
||||
case 10: { // %08x encoded 32 bit data, Big Endian
|
||||
const QChar doubleQuote(QLatin1Char('"'));
|
||||
QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||
for (int i = 0; i < decodedBa.size(); i += 4) {
|
||||
char c = decodedBa.at(i);
|
||||
decodedBa[i] = decodedBa.at(i + 3);
|
||||
decodedBa[i + 3] = c;
|
||||
c = decodedBa.at(i + 1);
|
||||
decodedBa[i + 1] = decodedBa.at(i + 2);
|
||||
decodedBa[i + 2] = c;
|
||||
}
|
||||
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
||||
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
||||
}
|
||||
case 11: { // %02x encoded 16 bit data, Big Endian
|
||||
const QChar doubleQuote(QLatin1Char('"'));
|
||||
QByteArray decodedBa = QByteArray::fromHex(ba);
|
||||
for (int i = 0; i < decodedBa.size(); i += 2) {
|
||||
char c = decodedBa.at(i);
|
||||
decodedBa[i] = decodedBa.at(i + 1);
|
||||
decodedBa[i + 1] = c;
|
||||
}
|
||||
//qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
|
||||
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
|
||||
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
|
||||
}
|
||||
}
|
||||
qDebug() << "ENCODING ERROR: " << encoding;
|
||||
return QCoreApplication::translate("Debugger", "<Encoding error>");
|
||||
|
||||
@@ -269,7 +269,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
|
||||
|
||||
if (canShowMemory && !address.isEmpty())
|
||||
actWatchKnownMemory = new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
||||
actWatchKnownMemory =
|
||||
new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
||||
menu.addSeparator();
|
||||
|
||||
QAction *actWatchOrRemove;
|
||||
@@ -293,8 +294,10 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
|
||||
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
||||
menu.addAction(theDebuggerAction(UseDebuggingHelpers));
|
||||
QAction *actClearCodeModelSnapshot = new QAction(tr("Refresh Code Model Snapshot"), &menu);
|
||||
actClearCodeModelSnapshot->setEnabled(actionsEnabled && theDebuggerAction(UseCodeModel)->isChecked());
|
||||
QAction *actClearCodeModelSnapshot
|
||||
= new QAction(tr("Refresh Code Model Snapshot"), &menu);
|
||||
actClearCodeModelSnapshot->setEnabled(actionsEnabled
|
||||
&& theDebuggerAction(UseCodeModel)->isChecked());
|
||||
menu.addAction(actClearCodeModelSnapshot);
|
||||
menu.addSeparator();
|
||||
menu.addAction(theDebuggerAction(UseToolTipsInLocalsView));
|
||||
|
||||
@@ -1486,6 +1486,8 @@ int main(int argc, char *argv[])
|
||||
testPlugin();
|
||||
testQList();
|
||||
testQLinkedList();
|
||||
char *s = "aöa";
|
||||
wchar_t *w = L"aöa";
|
||||
testNamespace();
|
||||
//return 0;
|
||||
testQHash();
|
||||
|
||||
Reference in New Issue
Block a user