From e307e6d6083fcc8815a6899c87a2ac564b2a5e45 Mon Sep 17 00:00:00 2001 From: Stefan Taferner Date: Mon, 9 Oct 2006 13:04:31 +0200 Subject: [PATCH] Display the value of wchar_t strings. A small testprogram widechar.cpp is included in the directory testprogs. The patch does the following: The values of variables of type "wchar_t*" (as well as "const wchar_t*") ar displayed analogous to "char*". I have used your implementations of handlePrint methods as guidelines and implemented it the same way. When a variable of type "wchar_t*" is found, then its contents is requested from GDB and the resulting array is displayed as string. Limitations: Unfortunately, this does not work for arrays of wchar_t. A tip how this could be done is appreciated. If there are invalid pointers, then the function wcslen, which is used internally, crashes. But GDB handles this correctly and there are no problems (at least for me). It is assumed that wchart_t and QChar contain the same characters. At least this is the case for me, and as far as I understand this topic, this should be ok generally. [J6t: Actually, no. There is no guarantee that wchar_t contains Unicode characters. But for all practical purposes, the assumption should be valid.] --- kdbg/dbgdriver.h | 1 + kdbg/debugger.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++--- kdbg/debugger.h | 1 + kdbg/gdbdriver.cpp | 11 +++++++++++ kdbg/testprogs/Makefile.am | 5 ++++- kdbg/testprogs/widechar.cpp | 22 ++++++++++++++++++++++ 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 kdbg/testprogs/widechar.cpp diff --git a/kdbg/dbgdriver.h b/kdbg/dbgdriver.h index 4ff75be..66ff8d7 100644 --- a/kdbg/dbgdriver.h +++ b/kdbg/dbgdriver.h @@ -91,6 +91,7 @@ enum DbgCommand { DCcondition, DCsetpc, DCignore, + DCprintWChar, DCsetvariable }; diff --git a/kdbg/debugger.cpp b/kdbg/debugger.cpp index 98c840a..151e492 100644 --- a/kdbg/debugger.cpp +++ b/kdbg/debugger.cpp @@ -1045,6 +1045,9 @@ void KDebugger::parse(CmdQueueItem* cmd, const char* output) case DCprintDeref: handlePrintDeref(cmd, output); break; + case DCprintWChar: + handlePrintWChar(cmd, output); + break; case DCattach: m_haveExecutable = true; // fall through @@ -1397,6 +1400,34 @@ bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output) return true; } +bool KDebugger::handlePrintWChar(CmdQueueItem* cmd, const char* output) +{ + ASSERT(cmd->m_expr != 0); + + VarTree* variable = m_d->parseQCharArray(output, false, true); + if (variable == 0) return false; + + variable->setText(cmd->m_expr->getText()); + variable->m_nameKind = VarTree::NKplain; + variable->m_varKind = VarTree::VKsimple; +// variable->m_value = partValue; + + QString val = cmd->m_expr->m_partialValue; + int pos = val.find(") "); + if (pos>0) val = val.mid(pos+2); + variable->m_value = val+" L"+variable->m_value; + + m_localVariables.updateExpr(variable); + delete variable; + + delete cmd->m_expr; + cmd->m_expr = 0; + + evalExpressions(); /* enqueue dereferenced pointers */ + + return true; +} + bool KDebugger::handlePrintDeref(CmdQueueItem* cmd, const char* output) { ASSERT(cmd->m_expr != 0); @@ -1578,14 +1609,23 @@ void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem, bool immediate) { ASSERT(exprItem->m_varKind == VarTree::VKpointer); + DbgCommand dbgCmd = DCprintDeref; QString expr = exprItem->computeExpr(); + + if (strncmp(exprItem->m_value, "(const wchar_t *)", 17)==0 || + strncmp(exprItem->m_value, "(wchar_t *)", 11)==0) + { + expr = "*"+expr+"@wcslen("+expr+")"; + dbgCmd = DCprintWChar; + } + TRACE("dereferencing pointer: " + expr); CmdQueueItem* cmd; if (immediate) { - cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverrideMoreEqual); + cmd = m_d->queueCmd(dbgCmd, expr, DebuggerDriver::QMoverrideMoreEqual); } else { - cmd = m_d->queueCmd(DCprintDeref, expr, DebuggerDriver::QMoverride); + cmd = m_d->queueCmd(dbgCmd, expr, DebuggerDriver::QMoverride); } // remember which expr this was cmd->m_expr = exprItem; @@ -1632,7 +1672,7 @@ void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output) } } if (info == 0) { - TRACE("unknown type"); + TRACE("unknown type "+type); cmd->m_expr->m_type = TypeInfo::unknownType(); } else { cmd->m_expr->m_type = info; diff --git a/kdbg/debugger.h b/kdbg/debugger.h index 8712462..ebeabe0 100644 --- a/kdbg/debugger.h +++ b/kdbg/debugger.h @@ -355,6 +355,7 @@ protected: void handleLocals(const char* output); bool handlePrint(CmdQueueItem* cmd, const char* output); bool handlePrintDeref(CmdQueueItem* cmd, const char* output); + bool handlePrintWChar(CmdQueueItem* cmd, const char* output); void handleBacktrace(const char* output); void handleFrameChange(const char* output); void handleFindType(CmdQueueItem* cmd, const char* output); diff --git a/kdbg/gdbdriver.cpp b/kdbg/gdbdriver.cpp index 2a5c5d2..4e2e6ae 100644 --- a/kdbg/gdbdriver.cpp +++ b/kdbg/gdbdriver.cpp @@ -115,6 +115,7 @@ static GdbCmdInfo cmds[] = { { DCcondition, "condition %d %s\n", GdbCmdInfo::argNumString}, { DCsetpc, "set variable $pc=%s\n", GdbCmdInfo::argString }, { DCignore, "ignore %d %d\n", GdbCmdInfo::argNum2}, + { DCprintWChar, "print ($s=%s)?*$s@wcslen($s):0x0\n", GdbCmdInfo::argString }, { DCsetvariable, "set variable %s=%s\n", GdbCmdInfo::argString2 }, }; @@ -2025,6 +2026,16 @@ void GdbDriver::parseLocals(const char* output, QList& newVars) goto skipDuplicate; } } + if ((variable->m_value.startsWith("(const wchar_t *)") || + variable->m_value.startsWith("(wchar_t *)")) && + !variable->m_value.endsWith(" 0x0")) + { + variable->m_varKind = VarTree::VKsimple; + variable->m_partialValue = variable->m_value; + variable->m_value = QString::null; + CmdQueueItem *c = executeCmd(DCprintWChar, variable->getText()); + c->m_expr = new VarTree(*variable); + } newVars.append(variable); skipDuplicate:; } diff --git a/kdbg/testprogs/Makefile.am b/kdbg/testprogs/Makefile.am index 1dfc080..ed45263 100644 --- a/kdbg/testprogs/Makefile.am +++ b/kdbg/testprogs/Makefile.am @@ -13,7 +13,7 @@ AM_CXXFLAGS = -g CXXFLAGS:=$(patsubst -O%,,$(CXXFLAGS)) if BUILDTESTPROGS -PROGS = testfile locals maths repeats std templates +PROGS = testfile locals maths repeats std templates widechar else PROGS = endif @@ -39,3 +39,6 @@ std_LDFLAGS = -g templates_SOURCES = templates.cpp templates_LDFLAGS = -g + +widechar_SOURCES = widechar.cpp +widechar_LDFLAGS = -g diff --git a/kdbg/testprogs/widechar.cpp b/kdbg/testprogs/widechar.cpp new file mode 100644 index 0000000..20ce78e --- /dev/null +++ b/kdbg/testprogs/widechar.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +int main() +{ + int j=3; + const wchar_t* nullPtr = 0; + const wchar_t* uninitializedPtr = (const wchar_t*)0xdeadbeef; + const wchar_t* str = L"abc"; + wchar_t* str2 = L"def"; + const char* shortStr = "12345"; + wchar_t wstr[64], *wstrPtr = wstr; + + wprintf(L"wide string: %S\n", str); + + for (int i=0; i