From d2ab8762e930fcb4422184d8858c64e56279dd3d Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Mon, 7 Dec 2009 09:14:35 +0100
Subject: [PATCH] debugger: special handling of char *argv[] in l&w

It's nicer this way.
---
 share/qtcreator/gdbmacros/dumper.py | 85 +++++++++++++++++++++--------
 tests/auto/debugger/tst_gdb.cpp     | 21 ++++---
 2 files changed, 71 insertions(+), 35 deletions(-)

diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py
index 3f4ff20a8a1..258784746a4 100644
--- a/share/qtcreator/gdbmacros/dumper.py
+++ b/share/qtcreator/gdbmacros/dumper.py
@@ -22,6 +22,13 @@ def qmin(n, m):
         return n
     return m
 
+def value(expr):
+    value = gdb.parse_and_eval(expr)
+    try:
+        return int(value)
+    except:
+        return str(value)
+
 def isSimpleType(typeobj):
     type = str(typeobj)
     return type == "bool" \
@@ -122,6 +129,13 @@ def qtNamespace():
     except RuntimeError:
         return ""
 
+def encodeCharArray(p, size):
+    s = ""
+    for i in xrange(0, size):
+        s += "%02x" % int(p.dereference())
+        p += 1
+    return s
+
 def encodeByteArray(value):
     d_ptr = value['d'].dereference()
     data = d_ptr['data']
@@ -135,11 +149,7 @@ def encodeByteArray(value):
 
     innerType = gdb.lookup_type("char")
     p = gdb.Value(data.cast(innerType.pointer()))
-    s = ""
-    for i in xrange(0, size):
-        s += "%02x" % int(p.dereference())
-        p += 1
-    return s
+    return encodeCharArray(p, size)
 
 def encodeString(value):
     d_ptr = value['d'].dereference()
@@ -267,11 +277,41 @@ class FrameCommand(gdb.Command):
                     continue
                 #warn("ITEM %s: " % item.value)
 
-                d.beginHash()
-                d.put('iname="%s",' % item.iname)
-                d.put('addr="%s",' % item.value.address)
-                d.safePutItemHelper(item)
-                d.endHash()
+                type = item.value.type
+                if type.code == gdb.TYPE_CODE_PTR \
+                        and name == "argv" and str(type) == "char **":
+                    # Special handling for char** argv:
+                    n = 0
+                    p = item.value
+                    while not isNull(p.dereference()) and n <= 100:
+                        p += 1
+                        n += 1
+
+                    d.beginHash()
+                    d.put('iname="%s",' % item.iname)
+                    d.putName(name)
+                    d.putItemCount(select(n <= 100, n, "> 100"))
+                    d.putType(type)
+                    d.putNumChild(n)
+                    if d.isExpanded(item):
+                        p = item.value
+                        d.beginChildren(n)
+                        for i in xrange(0, n):
+                            value = p.dereference()
+                            d.putItemOrPointer(Item(value, item.iname, i, None))
+                            p += 1
+                        if n > 100:
+                            d.putEllipsis()
+                        d.endChildren()
+                    d.endHash()
+
+                else:
+                    # A "normal" local variable or parameter
+                    d.beginHash()
+                    d.put('iname="%s",' % item.iname)
+                    d.put('addr="%s",' % item.value.address)
+                    d.safePutItemHelper(item)
+                    d.endHash()
 
             # The outermost block in a function has the function member
             # FIXME: check whether this is guaranteed.
@@ -292,9 +332,10 @@ class FrameCommand(gdb.Command):
         watchers = ""
         if len(args) > 3:
             watchers = base64.b16decode(args[3], True)
-        for watcher in watchers.split("$$"):
-            (exp, name) = watcher.split("$")
-            self.handleWatch(d, exp, name)
+        if len(watchers) > 0:
+            for watcher in watchers.split("$$"):
+                (exp, name) = watcher.split("$")
+                self.handleWatch(d, exp, name)
         d.pushOutput()
         watchers = d.safeoutput
 
@@ -305,16 +346,16 @@ class FrameCommand(gdb.Command):
 
 
     def handleWatch(self, d, exp, name):
-        warn("HANDLING WATCH %s, NAME: %s" % (exp, name))
+        #warn("HANDLING WATCH %s, NAME: %s" % (exp, name))
         if exp.startswith("["):
-            warn("EVAL: EXP: %s" % exp)
+            #warn("EVAL: EXP: %s" % exp)
             d.beginHash()
             d.put('iname="watch.%s",' % name)
             d.put('name="%s",' % exp)
             d.put('exp="%s"' % exp)
             try:
                 list = eval(exp)
-                warn("EVAL: LIST: %s" % list)
+                #warn("EVAL: LIST: %s" % list)
                 d.put('value=" "')
                 d.put('type=" "')
                 d.put('numchild="%d"' % len(list))
@@ -578,7 +619,7 @@ class Dumper:
 
     def putItemOrPointerHelper(self, item):
         if item.value.type.code == gdb.TYPE_CODE_PTR \
-                and str(item.value.type.unqualified) != "char":
+                and str(item.value.type.target()) != "char":
             if not isNull(item.value):
                 self.putItemOrPointerHelper(
                     Item(item.value.dereference(), item.iname, None, None))
@@ -639,24 +680,20 @@ class Dumper:
                 isHandled = True
 
             target = str(type.target().unqualified())
-            #warn("TARGET: %s" % target)
             if target == "char" and not isHandled:
                 # Display values up to given length directly
                 firstNul = -1
                 p = value
-                for i in xrange(0, 10):
+                for i in xrange(0, 100):
                     if p.dereference() == 0:
                         # Found terminating NUL
                         self.putField("valueencoded", "6")
                         self.put(',value="')
-                        p = value
-                        for j in xrange(0, i):
-                            self.put('%02x' % int(p.dereference()))
-                            p += 1
+                        self.put(encodeCharArray(value, i))
                         self.put('"')
                         self.putNumChild(0)
                         isHandled = True
-                        break
+                        return
                     p += 1
 
             if not isHandled:
diff --git a/tests/auto/debugger/tst_gdb.cpp b/tests/auto/debugger/tst_gdb.cpp
index 3f8b9b9fffc..f13bde84af4 100644
--- a/tests/auto/debugger/tst_gdb.cpp
+++ b/tests/auto/debugger/tst_gdb.cpp
@@ -278,9 +278,6 @@ private:
     Thread m_thread;
 };
 
-//QMutex m_mutex;
-//QWaitCondition m_waitCondition;
-
 QByteArray buffer;
 QSemaphore freeBytes(1);
 QSemaphore usedBytes(0);
@@ -569,13 +566,6 @@ void tst_Gdb::check(const QByteArray &label, const QByteArray &expected0,
     qWarning() << label << "...";
     writeToGdb("bb " + N(int(fancy)) + " 1 " + expanded);
 
-    //m_mutex.lock();
-    //m_waitCondition.wait(&m_mutex);
-    //QByteArray ba = m_thread.m_output;
-    //m_thread.m_output.clear();
-    //m_mutex.unlock();
-    //GdbMi locals;
-
     //qDebug() << "\n1 ABOUT TO AQUIRE USED ";
     usedBytes.acquire();
     //qDebug() << "\n1 AQUIRED USED ";
@@ -602,7 +592,16 @@ void tst_Gdb::check(const QByteArray &label, const QByteArray &expected0,
         "children=[" + expected0 + "]}";
     int line = m_thread.m_line;
 
-    QByteArrayList l1 = actual.split(',');
+    QByteArrayList l1_0 = actual.split(',');
+    QByteArrayList l1;
+    for (int i = 0; i != l1_0.size(); ++i) {
+        const QByteArray &ba = l1_0.at(i);
+        if (ba.startsWith("watchers={iname"))
+            break;
+        if (!ba.startsWith("addr"))
+            l1.append(ba);
+    }
+
     QByteArrayList l2 = expected.split(',');
 
     bool ok = l1.size() == l2.size();
-- 
GitLab