From b70c0978d1ab80a8298af18ffe07f024d2eb1d37 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Thu, 8 Apr 2010 14:08:19 +0200
Subject: [PATCH] debugger: rework error handling in python dumpers

---
 share/qtcreator/gdbmacros/dumper.py    |  634 +++++------
 share/qtcreator/gdbmacros/gdbmacros.py | 1352 +++++++++++-------------
 2 files changed, 950 insertions(+), 1036 deletions(-)

diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py
index 77e40dbf83f..f7000863f30 100644
--- a/share/qtcreator/gdbmacros/dumper.py
+++ b/share/qtcreator/gdbmacros/dumper.py
@@ -137,6 +137,131 @@ def catchCliOutput(command):
     return lines
 
 
+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
+
+
+class OutputSafer:
+    def __init__(self, d, pre = "", post = ""):
+        self.d = d
+        self.pre = pre
+        self.post = post
+
+    def __enter__(self):
+        self.d.put(self.pre)
+        self.savedOutput = self.d.output
+        self.d.output = ""
+
+    def __exit__(self, exType, exValue, exTraceBack):
+        self.d.put(self.post)
+        if self.d.passExceptions and not exType is None:
+            showException("OUTPUTSAFER", exType, exValue, exTraceBack)
+            self.d.output = self.savedOutput
+        else:
+            self.d.output = self.savedOutput + self.d.output
+        return False
+
+
+class SubItem:
+    def __init__(self, d):
+        self.d = d
+
+    def __enter__(self):
+        self.d.put('{')
+        self.savedValue = self.d.currentValue
+        self.savedValuePriority = self.d.currentValuePriority
+        self.savedValueEncoding = self.d.currentValueEncoding
+        self.savedType = self.d.currentType
+        self.savedTypePriority = self.d.currentTypePriority
+        self.d.currentValue = ""
+        self.d.currentValuePriority = 0
+        self.d.currentValueEncoding = None
+        self.d.currentType = ""
+        self.d.currentTypePriority = 0
+
+    def __exit__(self, exType, exValue, exTraceBack):
+        #warn(" CURRENT VALUE: %s %s %s" % (self.d.currentValue,
+        #    self.d.currentValueEncoding, self.d.currentValuePriority))
+        if self.d.passExceptions and not exType is None:
+            showException("SUBITEM", exType, exValue, exTraceBack)
+        if not self.d.currentValueEncoding is None:
+            self.d.putField("valueencoded", self.d.currentValueEncoding)
+        if not self.d.currentValue is None:
+            self.d.putField("value", self.d.currentValue)
+        #warn("TYPE CURRENT: %s" % self.d.currentType)
+        type = stripClassTag(str(self.d.currentType))
+        #warn("TYPE: '%s'  DEFAULT: '%s'" % (type, self.d.currentChildType))
+        if len(type) > 0 and type != self.d.currentChildType:
+            self.d.put('type="%s",' % type) # str(type.unqualified()) ?
+        self.d.put('},')
+        self.d.currentValue = self.savedValue
+        self.d.currentValuePriority = self.savedValuePriority
+        self.d.currentValueEncoding = self.savedValueEncoding
+        self.d.currentType = self.savedType
+        self.d.currentTypePriority = self.savedTypePriority
+        return True
+
+
+class Children:
+    def __init__(self, d, numChild = 1, childType = None, childNumChild = None):
+        self.d = d
+        self.numChild = numChild
+        self.childType = childType
+        self.childNumChild = childNumChild
+        #warn("CHILDREN: %s %s %s" % (numChild, childType, childNumChild))
+
+    def __enter__(self):
+        childType = ""
+        childNumChild = -1
+        if type(self.numChild) is list:
+            numChild = self.numChild[0]
+            maxNumChild = self.numChild[1]
+        else:
+            numChild = self.numChild
+            maxNumChild = self.numChild
+        if numChild == 0:
+            self.childType = None
+        if not self.childType is None:
+            childType = stripClassTag(str(self.childType))
+            self.d.put('childtype="%s",' % childType)
+            if isSimpleType(self.childType) or isStringType(self.d, self.childType):
+                self.d.put('childnumchild="0",')
+                childNumChild = 0
+            elif self.childType.code == gdb.TYPE_CODE_PTR:
+                self.d.put('childnumchild="1",')
+                childNumChild = 1
+        if not self.childNumChild is None:
+            self.d.put('childnumchild="%s",' % self.childNumChild)
+            childNumChild = self.childNumChild
+        self.savedChildType = self.d.currentChildType
+        self.savedChildNumChild = self.d.currentChildNumChild
+        self.savedNumChilds = self.d.currentNumChilds
+        self.savedMaxNumChilds = self.d.currentNumChilds
+        self.d.currentChildType = childType
+        self.d.currentChildNumChild = childNumChild
+        self.d.currentNumChilds = numChild
+        self.d.currentMaxNumChilds = maxNumChild
+        self.d.put("children=[")
+
+    def __exit__(self, exType, exValue, exTraceBack):
+        if self.d.passExceptions and not exType is None:
+            showException("CHILDREN", exType, exValue, exTraceBack)
+        if self.d.currentMaxNumChilds < self.d.currentNumChilds:
+            self.d.putEllipsis();
+        self.d.currentChildType = self.savedChildType
+        self.d.currentChildNumChild = self.savedChildNumChild
+        self.d.currentNumChilds = self.savedNumChilds
+        self.d.currentMaxNumChilds = self.savedMaxNumChilds
+        self.d.put('],')
+        return True
+
+
 class Breakpoint:
     def __init__(self):
         self.number = None
@@ -345,7 +470,7 @@ def listOfLocals(varList):
                 # like 'Warning: can't find linker symbol for virtual table for
                 # `std::less<char const*>' value\n\nwarning:  found
                 # `myns::QHashData::shared_null' instead [...]
-                # that break subsequent parsing. Chicken out and take the 
+                # that break subsequent parsing. Chicken out and take the
                 # next "usable" line.
                 continue
             items.append(item)
@@ -447,6 +572,8 @@ movableTypes = set([
 def stripClassTag(type):
     if type.startswith("class "):
         return type[6:]
+    elif type.startswith("struct "):
+        return type[7:]
     return type
 
 def checkPointerRange(p, n):
@@ -461,7 +588,11 @@ def call(value, func):
         type = "'" + type + "'"
     exp = "((%s*)%s)->%s" % (type, value.address, func)
     #warn("CALL: %s" % exp)
-    result = parseAndEvaluate(exp)
+    result = None
+    try:
+        result = parseAndEvaluate(exp)
+    except:
+        pass
     #warn("  -> %s" % result)
     return result
 
@@ -684,6 +815,7 @@ class FrameCommand(gdb.Command):
         # Locals
         #
         for item in listOfLocals(varList):
+          with OutputSafer(d, "", ""):
             d.anonNumber = -1
             #warn("ITEM NAME %s: " % item.name)
             try:
@@ -695,14 +827,13 @@ class FrameCommand(gdb.Command):
                 pass
             except:
                 # Locals with failing memory access.
-                d.beginHash()
-                d.put('iname="%s",' % item.iname)
-                d.put('name="%s",' % item.name)
-                d.put('addr="<not accessible>",')
-                d.put('value="<not accessible>",')
-                d.put('type="%s",' % item.value.type)
-                d.put('numchild="0"');
-                d.endHash()
+                with SubItem(d):
+                    d.put('iname="%s",' % item.iname)
+                    d.put('name="%s",' % item.name)
+                    d.put('addr="<not accessible>",')
+                    d.put('value="<not accessible>",')
+                    d.put('type="%s",' % item.value.type)
+                    d.put('numchild="0"');
                 continue
 
             type = item.value.type
@@ -717,74 +848,56 @@ class FrameCommand(gdb.Command):
                         p += 1
                         n += 1
 
-                d.beginHash()
-                d.put('iname="%s",' % item.iname)
-                d.putName(item.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(n):
-                        value = p.dereference()
-                        d.putItem(Item(value, item.iname, i, None))
-                        p += 1
-                    if n > 100:
-                        d.putEllipsis()
-                    d.endChildren()
-                d.endHash()
+                with SubItem(d):
+                    d.put('iname="%s",' % item.iname)
+                    d.putName(item.name)
+                    d.putItemCount(select(n <= 100, n, "> 100"))
+                    d.putType(type)
+                    d.putNumChild(n)
+                    if d.isExpanded(item):
+                        p = item.value
+                        with Children(d, n):
+                            for i in xrange(n):
+                                value = p.dereference()
+                                d.putItem(Item(value, item.iname, i, None))
+                                p += 1
+                            if n > 100:
+                                d.putEllipsis()
 
             else:
                 # A "normal" local variable or parameter.
                 try:
                    addr = cleanAddress(item.value.address)
-                   d.beginHash()
-                   d.put('iname="%s",' % item.iname)
-                   d.put('addr="%s",' % addr)
-                   d.safePutItemHelper(item)
-                   d.endHash()
+                   with SubItem(d):
+                       d.put('iname="%s",' % item.iname)
+                       d.put('addr="%s",' % addr)
+                       d.putItemHelper(item)
                 except AttributeError:
                     # Thrown by cleanAddress with message "'NoneType' object
                     # has no attribute 'cast'" for optimized-out values.
-                    d.beginHash()
-                    d.put('iname="%s",' % item.iname)
-                    d.put('name="%s",' % item.name)
-                    d.put('addr="<optimized out>",')
-                    d.put('value="<optimized out>",')
-                    d.put('type="%s"' % item.value.type)
-                    d.endHash()
-
-        d.pushOutput()
-        locals = d.safeoutput
-
+                    with SubItem(d):
+                        d.put('iname="%s",' % item.iname)
+                        d.put('name="%s",' % item.name)
+                        d.put('addr="<optimized out>",')
+                        d.put('value="<optimized out>",')
+                        d.put('type="%s"' % item.value.type)
 
         #
         # Watchers
         #
-        d.safeoutput = ""
-        if len(watchers) > 0:
-            for watcher in watchers.split("##"):
-                (exp, iname) = watcher.split("#")
-                self.handleWatch(d, exp, iname)
-        d.pushOutput()
-        watchers = d.safeoutput
-
-        sep = ""
-        if len(locals) and len(watchers):
-            sep = ","
+        with OutputSafer(d, ",", ""):
+            if len(watchers) > 0:
+                for watcher in watchers.split("##"):
+                    (exp, iname) = watcher.split("#")
+                    self.handleWatch(d, exp, iname)
 
         #
         # Breakpoints
         #
-        #breakpoints = ""
-        #d.safeoutput = ""
         #listOfBreakpoints(d)
-        #d.pushOutput()
-        #breakpoints = d.safeoutput
 
         #print('data=[' + locals + sep + watchers + '],bkpts=[' + breakpoints + ']\n')
-        print('data=[' + locals + sep + watchers + ']\n')
+        print('data=[' + d.output + ']')
 
 
     def handleWatch(self, d, exp, iname):
@@ -793,49 +906,46 @@ class FrameCommand(gdb.Command):
         #warn("HANDLING WATCH %s, INAME: '%s'" % (exp, iname))
         if exp.startswith("[") and exp.endswith("]"):
             #warn("EVAL: EXP: %s" % exp)
-            d.beginHash()
+            with SubItem(d):
+                d.putField("iname", iname)
+                d.putField("name", escapedExp)
+                d.putField("exp", escapedExp)
+                try:
+                    list = eval(exp)
+                    d.putValue("")
+                    d.putType(" ")
+                    d.putNumChild(len(list))
+                    # This is a list of expressions to evaluate
+                    with Children(d, len(list)):
+                        itemNumber = 0
+                        for item in list:
+                            self.handleWatch(d, item, "%s.%d" % (iname, itemNumber))
+                            itemNumber += 1
+                except RuntimeError, error:
+                    warn("EVAL: ERROR CAUGHT %s" % error)
+                    d.putValue("<syntax error>")
+                    d.putType(" ")
+                    d.putNumChild(0)
+                    with Children(d, 0):
+                        pass
+            return
+
+        with SubItem(d):
             d.putField("iname", iname)
             d.putField("name", escapedExp)
             d.putField("exp", escapedExp)
-            try:
-                list = eval(exp)
-                d.putValue("")
-                d.putType(" ")
-                d.putNumChild(len(list))
-                # This is a list of expressions to evaluate
-                d.beginChildren(len(list))
-                itemNumber = 0
-                for item in list:
-                    self.handleWatch(d, item, "%s.%d" % (iname, itemNumber))
-                    itemNumber += 1
-                d.endChildren()
-            except RuntimeError, error:
-                warn("EVAL: ERROR CAUGHT %s" % error)
-                d.putValue("<syntax error>")
-                d.putType(" ")
-                d.putNumChild(0)
-                d.beginChildren(0)
-                d.endChildren()
-            d.endHash()
-            return
-
-        d.beginHash()
-        d.putField("iname", iname)
-        d.putField("name", escapedExp)
-        d.putField("exp", escapedExp)
-        handled = False
-        if exp == "<Edit>" or len(exp) == 0:
-            d.put('value=" ",type=" ",numchild="0",')
-        else:
-            try:
-                value = parseAndEvaluate(exp)
-                item = Item(value, iname, None, None)
-                if not value is None:
-                    d.putAddress(value.address)
-                d.putItemHelper(item)
-            except RuntimeError:
-                d.put('value="<invalid>",type="<unknown>",numchild="0",')
-        d.endHash()
+            handled = False
+            if exp == "<Edit>" or len(exp) == 0:
+                d.put('value=" ",type=" ",numchild="0",')
+            else:
+                try:
+                    value = parseAndEvaluate(exp)
+                    item = Item(value, iname, None, None)
+                    if not value is None:
+                        d.putAddress(value.address)
+                    d.putItemHelper(item)
+                except RuntimeError:
+                    d.put('value="<invalid>",type="<unknown>",numchild="0",')
 
 
 FrameCommand()
@@ -882,11 +992,15 @@ SalCommand()
 class Dumper:
     def __init__(self):
         self.output = ""
-        self.safeoutput = ""
-        self.childTypes = [""]
-        self.childNumChilds = [-1]
-        self.maxNumChilds = [-1]
-        self.numChilds = [-1]
+        self.currentChildType = ""
+        self.currentChildNumChild = -1
+        self.currentMaxNumChilds = -1
+        self.currentNumChilds = -1
+        self.currentValue = None
+        self.currentValuePriority = -100
+        self.currentValueEncoding = None
+        self.currentType = None
+        self.currentTypePriority = -100
 
     def put(self, value):
         self.output += value
@@ -894,60 +1008,14 @@ class Dumper:
     def putField(self, name, value):
         self.put('%s="%s",' % (name, value))
 
-    def beginHash(self):
-        self.put('{')
-
-    def endHash(self):
-        self.put('},')
-
     def beginItem(self, name):
         self.put('%s="' % name)
 
     def endItem(self):
         self.put('",')
 
-    def beginChildren(self, numChild_ = 1, childType_ = None, childNumChild_ = None):
-        childType = ""
-        childNumChild = -1
-        if type(numChild_) is list:
-            numChild = numChild_[0]
-            maxNumChild = numChild_[1]
-        else:
-            numChild = numChild_
-            maxNumChild = numChild_
-        if numChild == 0:
-            childType_ = None
-        if not childType_ is None:
-            childType = stripClassTag(str(childType_))
-            self.put('childtype="%s",' % childType)
-            if isSimpleType(childType_) or isStringType(self, childType_):
-                self.put('childnumchild="0",')
-                childNumChild = 0
-            elif childType_.code == gdb.TYPE_CODE_PTR:
-                self.put('childnumchild="1",')
-                childNumChild = 1
-        if not childNumChild_ is None:
-            self.put('childnumchild="%s",' % childNumChild_)
-            childNumChild = childNumChild_
-        self.childTypes.append(childType)
-        self.childNumChilds.append(childNumChild)
-        self.numChilds.append(numChild)
-        self.maxNumChilds.append(maxNumChild)
-        #warn("BEGIN: %s" % self.childTypes)
-        self.put("children=[")
-
-    def endChildren(self):
-        #warn("END: %s" % self.childTypes)
-        numChild = self.numChilds.pop()
-        maxNumChild = self.maxNumChilds.pop()
-        if maxNumChild < numChild:
-            self.putEllipsis();
-        self.childTypes.pop()
-        self.childNumChilds.pop()
-        self.put('],')
-
     def childRange(self):
-        return xrange(qmin(self.maxNumChilds[-1], self.numChilds[-1]))
+        return xrange(qmin(self.currentMaxNumChilds, self.currentNumChilds))
 
     # convenience
     def putItemCount(self, count):
@@ -956,28 +1024,30 @@ class Dumper:
     def putEllipsis(self):
         self.put('{name="<incomplete>",value="",type="",numchild="0"},')
 
-    def putType(self, type):
-        #warn("TYPES: '%s' '%s'" % (type, self.childTypes))
-        #warn("  EQUAL 2: %s " % (str(type) == self.childTypes[-1]))
-        type = stripClassTag(str(type))
-        if len(type) > 0 and type != self.childTypes[-1]:
-            self.put('type="%s",' % type) # str(type.unqualified()) ?
+    def putType(self, type, priority = 0):
+        # higher priority values override lower ones 
+        if priority >= self.currentTypePriority:
+            self.currentType = type
+            self.currentTypePriority = priority
 
     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]:
+        #warn("NUM CHILD: '%s' '%s'" % (numchild, self.currentChildNumChild))
+        if numchild != self.currentChildNumChild:
             self.put('numchild="%s",' % numchild)
 
-    def putValue(self, value, encoding = None):
-        if not encoding is None:
-            self.putField("valueencoded", encoding)
-        self.putField("value", value)
+    def putValue(self, value, encoding = None, priority = 0):
+        # higher priority values override lower ones 
+        if priority >= self.currentValuePriority:
+            self.currentValue = value
+            self.currentValuePriority = priority
+            self.currentValueEncoding = encoding
 
     def putPointerValue(self, value):
-        self.putValue("0x%x" % value.dereference().cast(
+        # Use a lower priority
+        self.putField("value2", "0x%x" % value.dereference().cast(
             gdb.lookup_type("unsigned long")))
 
     def putStringValue(self, value):
@@ -1014,11 +1084,6 @@ class Dumper:
     def isExpandedIName(self, iname):
         return iname in self.expandedINames
 
-    def unputField(self, name):
-        pos = self.output.rfind(",")
-        if self.output[pos + 1:].startswith(name):
-            self.output = self.output[0:pos]
-
     def stripNamespaceFromType(self, typeobj):
         # This breaks for dumpers type names containing '__star'.
         # But this should not happen as identifiers containing two
@@ -1044,29 +1109,18 @@ class Dumper:
         return self.stripNamespaceFromType(type) in movableTypes
 
     def putIntItem(self, name, value):
-        self.beginHash()
-        self.putName(name)
-        self.putValue(value)
-        self.putType("int")
-        self.putNumChild(0)
-        self.endHash()
+        with SubItem(self):
+            self.putName(name)
+            self.putValue(value)
+            self.putType("int")
+            self.putNumChild(0)
 
     def putBoolItem(self, name, value):
-        self.beginHash()
-        self.putName(name)
-        self.putValue(value)
-        self.putType("bool")
-        self.putNumChild(0)
-        self.endHash()
-
-    def pushOutput(self):
-        #warn("PUSH OUTPUT: %s " % self.output)
-        self.safeoutput += self.output
-        self.output = ""
-
-    def dumpInnerValueHelper(self, item):
-        if isSimpleType(item.value.type):
-            self.safePutItemHelper(item)
+        with SubItem(self):
+            self.putName(name)
+            self.putValue(value)
+            self.putType("bool")
+            self.putNumChild(0)
 
     def itemFormat(self, item):
         format = self.formats.get(str(cleanAddress(item.value.address)))
@@ -1074,58 +1128,13 @@ class Dumper:
             format = self.typeformats.get(stripClassTag(str(item.value.type)))
         return format
 
-    def safePutItem(self, item):
-        self.beginHash()
-        self.safePutItemHelper(item)
-        self.endHash()
-
-    def safePutItemHelper(self, item):
-        self.pushOutput()
-        # This is only used at the top level to ensure continuation
-        # after failures due to uninitialized or corrupted data.
-        if self.passExceptions:
-            # for debugging reasons propagate errors.
-            self.putItemHelper(item)
-
-        else:
-            try:
-                self.putItemHelper(item)
-
-            except RuntimeError:
-                self.output = ""
-                # FIXME: Only catch debugger related exceptions
-                #exType, exValue, exTraceback = sys.exc_info()
-                #tb = traceback.format_exception(exType, exValue, exTraceback)
-                #warn("Exception: %s" % ex.message)
-                # DeprecationWarning: BaseException.message
-                # has been deprecated
-                #warn("Exception.")
-                #for line in tb:
-                #    warn("%s" % line)
-                self.putName(item.name)
-                try:
-                    d.putAddress(item.value.address)
-                except:
-                    pass
-                self.putValue("<invalid>")
-                self.putType(str(item.value.type))
-                self.putNumChild(0)
-                #if self.isExpanded(item):
-                self.beginChildren()
-                self.endChildren()
-        self.pushOutput()
-
     def putItem(self, item):
-        self.beginHash()
-        self.safePutItemHelper(item)
-        self.endHash()
+        with SubItem(self):
+            self.putItemHelper(item)
 
     def putCallItem(self, name, item, func):
-        try:
-            result = call(item.value, func)
-            self.safePutItem(Item(result, item.iname, name, name))
-        except:
-            self.safePutItem(Item(None, item.iname))
+        result = call(item.value, func)
+        self.putItem(Item(result, item.iname, name, name))
 
     def putItemHelper(self, item):
         name = getattr(item, "name", None)
@@ -1194,7 +1203,6 @@ class Dumper:
             format = self.itemFormat(item)
 
             if not format is None:
-                #warn("FORMAT %s" % format)
                 self.putAddress(value.address)
                 self.putType(item.value.type)
                 self.putNumChild(0)
@@ -1256,11 +1264,11 @@ class Dumper:
                 #warn("GENERIC AUTODEREF POINTER: %s" % value.address)
                 innerType = item.value.type.target()
                 self.putType(innerType)
-                self.childTypes.append(
-                    stripClassTag(str(innerType)))
+                savedCurrentChildType = self.currentChildType
+                self.currentChildType = stripClassTag(str(innerType))
                 self.putItemHelper(
                     Item(item.value.dereference(), item.iname, None, None))
-                self.childTypes.pop()
+                self.currentChildType = savedCurrentChildType
                 self.putPointerValue(value.address)
                 isHandled = True
 
@@ -1271,10 +1279,9 @@ class Dumper:
                 self.putAddress(value.address)
                 self.putNumChild(1)
                 if self.isExpanded(item):
-                    self.beginChildren()
-                    self.putItem(
-                          Item(item.value.dereference(), item.iname, "*", "*"))
-                    self.endChildren()
+                    with Children(self):
+                        self.putItem(
+                              Item(item.value.dereference(), item.iname, "*", "*"))
                 self.putPointerValue(value.address)
 
         elif str(type).startswith("<anon"):
@@ -1283,9 +1290,8 @@ class Dumper:
             self.putType(item.value.type)
             self.putValue("{...}")
             self.anonNumber += 1
-            self.beginChildren(1)
-            self.listAnonymous(item, "#%d" % self.anonNumber, type)
-            self.endChildren()
+            with Children(self, 1):
+                self.listAnonymous(item, "#%d" % self.anonNumber, type)
 
         else:
             #warn("GENERIC STRUCT: %s" % item.value.type)
@@ -1326,56 +1332,53 @@ class Dumper:
                 innerType = None
                 if len(fields) == 1 and fields[0].name is None:
                     innerType = value.type.target()
-                self.beginChildren(1, innerType)
-
-                baseNumber = 0
-                for field in fields:
-                    #warn("FIELD: %s" % field)
-                    #warn("  BITSIZE: %s" % field.bitsize)
-                    #warn("  ARTIFICIAL: %s" % field.artificial)
-                    bitpos = getattr(field, "bitpos", None)
-                    if bitpos is None: # FIXME: Is check correct?
-                        continue  # A static class member(?).
-
-                    if field.name is None:
-                        innerType = value.type.target()
-                        p = value.cast(innerType.pointer())
-                        for i in xrange(value.type.sizeof / innerType.sizeof):
-                            self.putItem(Item(p.dereference(), item.iname, i, None))
-                            p = p + 1
-                        continue
-
-                    # Ignore vtable pointers for virtual inheritance.
-                    if field.name.startswith("_vptr."):
-                        continue
-
-                    #warn("FIELD NAME: %s" % field.name)
-                    #warn("FIELD TYPE: %s" % field.type)
-                    if field.name == stripClassTag(str(field.type)):
-                        # Field is base type. We cannot use field.name as part
-                        # of the iname as it might contain spaces and other
-                        # strange characters.
-                        child = Item(value.cast(field.type),
-                            item.iname, "@%d" % baseNumber, field.name)
-                        baseNumber += 1
-                        self.beginHash()
-                        self.putField("iname", child.iname)
-                        self.safePutItemHelper(child)
-                        self.endHash()
-                    elif len(field.name) == 0:
-                        # Anonymous union. We need a dummy name to distinguish
-                        # multiple anonymous unions in the struct.
-                        self.anonNumber += 1
-                        self.listAnonymous(item, "#%d" % self.anonNumber, field.type)
-                    else:
-                        # Named field.
-                        self.beginHash()
-                        child = Item(value[field.name],
-                            item.iname, field.name, field.name)
-                        self.safePutItemHelper(child)
-                        self.endHash()
-
-                self.endChildren()
+                with Children(self, 1, innerType):
+
+                    baseNumber = 0
+                    for field in fields:
+                        #warn("FIELD: %s" % field)
+                        #warn("  BITSIZE: %s" % field.bitsize)
+                        #warn("  ARTIFICIAL: %s" % field.artificial)
+                        bitpos = getattr(field, "bitpos", None)
+                        if bitpos is None: # FIXME: Is check correct?
+                            continue  # A static class member(?).
+
+                        if field.name is None:
+                            innerType = value.type.target()
+                            p = value.cast(innerType.pointer())
+                            for i in xrange(value.type.sizeof / innerType.sizeof):
+                                self.putItem(Item(p.dereference(), item.iname, i, None))
+                                p = p + 1
+                            continue
+
+                        # Ignore vtable pointers for virtual inheritance.
+                        if field.name.startswith("_vptr."):
+                            continue
+
+                        #warn("FIELD NAME: %s" % field.name)
+                        #warn("FIELD TYPE: %s" % field.type)
+                        if field.name == stripClassTag(str(field.type)):
+                            # Field is base type. We cannot use field.name as part
+                            # of the iname as it might contain spaces and other
+                            # strange characters.
+                            child = Item(value.cast(field.type),
+                                item.iname, "@%d" % baseNumber, field.name)
+                            baseNumber += 1
+                            with SubItem(self):
+                                self.putField("iname", child.iname)
+                                self.putItemHelper(child)
+                        elif len(field.name) == 0:
+                            # Anonymous union. We need a dummy name to distinguish
+                            # multiple anonymous unions in the struct.
+                            self.anonNumber += 1
+                            self.listAnonymous(item, "#%d" % self.anonNumber,
+                                field.type)
+                        else:
+                            # Named field.
+                            with SubItem(self):
+                                child = Item(value[field.name],
+                                    item.iname, field.name, field.name)
+                                self.putItemHelper(child)
 
     def listAnonymous(self, item, name, type):
         for field in type.fields():
@@ -1383,28 +1386,25 @@ class Dumper:
             if len(field.name) > 0:
                 value = item.value[field.name]
                 child = Item(value, item.iname, field.name, field.name)
-                self.beginHash()
-                self.putAddress(value.address)
-                self.putItemHelper(child)
-                self.endHash();
+                with SubItem(self):
+                    self.putAddress(value.address)
+                    self.putItemHelper(child)
             else:
                 # Further nested.
                 self.anonNumber += 1
                 name = "#%d" % self.anonNumber
                 iname = "%s.%s" % (item.iname, name)
                 child = Item(item.value, iname, None, name)
-                self.beginHash()
-                self.putField("name", name)
-                self.putField("value", " ")
-                if str(field.type).endswith("<anonymous union>"):
-                    self.putField("type", "<anonymous union>")
-                elif str(field.type).endswith("<anonymous struct>"):
-                    self.putField("type", "<anonymous struct>")
-                else:
-                    self.putField("type", field.type)
-                self.beginChildren(1)
-                self.listAnonymous(child, name, field.type)
-                self.endChildren()
-                self.endHash()
+                with SubItem(self):
+                    self.putField("name", name)
+                    self.putField("value", " ")
+                    if str(field.type).endswith("<anonymous union>"):
+                        self.putField("type", "<anonymous union>")
+                    elif str(field.type).endswith("<anonymous struct>"):
+                        self.putField("type", "<anonymous struct>")
+                    else:
+                        self.putField("type", field.type)
+                    with Children(self, 1):
+                        self.listAnonymous(child, name, field.type)
 
 
diff --git a/share/qtcreator/gdbmacros/gdbmacros.py b/share/qtcreator/gdbmacros/gdbmacros.py
index 9762bbaf4ae..f18a2292c7b 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.py
+++ b/share/qtcreator/gdbmacros/gdbmacros.py
@@ -26,13 +26,12 @@ def qdump__QByteArray(d, item):
 
     if d.isExpanded(item):
         innerType = gdb.lookup_type("char")
-        data = d_ptr['data']
-        d.beginChildren([size, 1000], innerType)
-        p = gdb.Value(data.cast(innerType.pointer()))
-        for i in d.childRange():
-            d.putItem(Item(p.dereference(), item.iname, i))
-            p += 1
-        d.endChildren()
+        with Children(d, [size, 1000], innerType):
+            data = d_ptr['data']
+            p = gdb.Value(data.cast(innerType.pointer()))
+            for i in d.childRange():
+                d.putItem(Item(p.dereference(), item.iname, i))
+                p += 1
 
 
 def qdump__QChar(d, item):
@@ -55,25 +54,23 @@ def qdump__QAbstractItem(d, item):
     d.putStringValue(call(m, "data(mi, Qt::DisplayRole).toString()"))
     d.putNumChild(rowCount * columnCount)
     if d.isExpanded(item):
-        innerType = gdb.lookup_type(d.ns + "QAbstractItem")
-        d.beginChildren()
-        for row in xrange(rowCount):
-            for column in xrange(columnCount):
-                child = call(m, "index(row, column, mi)")
-                d.putName("[%s,%s]" % (row, column))
-                rr = call(m, "rowCount(child)")
-                cc = call(m, "columnCount(child)")
-                d.putNumChild(rr * cc)
-                d.putField("value",
-                    call(m, "data(child, Qt::DisplayRole).toString())"), 6)
-                d.endHash()
-        #d.beginHash()
-        #d.putName("DisplayRole")
-        #d.putNumChild(0)
-        #d.putValue(m->data(mi, Qt::DisplayRole).toString(), 2)
-        #d.putField("type", ns + "QString")
-        #d.endHash()
-        d.endChildren()
+        with Children(d):
+            innerType = gdb.lookup_type(d.ns + "QAbstractItem")
+            for row in xrange(rowCount):
+                for column in xrange(columnCount):
+                    with SubItem(d):
+                        child = call(m, "index(row, column, mi)")
+                        d.putName("[%s,%s]" % (row, column))
+                        rr = call(m, "rowCount(child)")
+                        cc = call(m, "columnCount(child)")
+                        d.putNumChild(rr * cc)
+                        d.putField("value",
+                            call(m, "data(child, Qt::DisplayRole).toString())"), 6)
+            #with SubItem(d):
+            #    d.putName("DisplayRole")
+            #    d.putNumChild(0)
+            #    d.putValue(m->data(mi, Qt::DisplayRole).toString(), 2)
+            #    d.putField("type", ns + "QString")
 
 
 #def qdump__QAbstractItemModel(d, item):
@@ -89,144 +86,136 @@ def qdump__QAbstractItem(d, item):
 #    d.putValue("(%s,%s)" % (rowCount, columnCount))
 #    d.putNumChild(1)
 #    if d.isExpanded(item):
-#        d.beginChildren(1 + rowCount * columnCount)
-#        d.beginHash()
-#        d.putNumChild(1)
-#        d.putName(d.ns + "QObject")
-#        d.putStringValue(call(item.value, "objectName()"))
-#        d.putType(d.ns + "QObject")
-#        d.put('addr="%s",' % cleanAddress(item.value.address))
-#        #d.putField("displayedtype", call(item, "m.metaObject()->className()"))
-#        d.endHash()
-#        gdb.execute("set variable %s->m=('%sQAbstractItemModel'*)%s" \
-#            % (dummy, d.ns, item.value.address))
-#        for row in xrange(rowCount):
-#            for column in xrange(columnCount):
-#                gdb.execute("set variable %s->r=-1" % dummy)
-#                gdb.execute("set variable %s->c=-1" % dummy)
-#                d.beginHash()
-#                d.putName("[%s,%s]" % (row, column))
-#                value = call(item.value, "data(*%s, 0)" % dummy)
-#                d.putValue(str(value))
-#                d.putNumChild(0)
-#                d.putType(" ")
-#                d.endHash()
-#        d.endChildren()
+#        with Children(d, 1 + rowCount * columnCount):
+#            with SubItem(d):
+    #            d.putNumChild(1)
+    #            d.putName(d.ns + "QObject")
+    #            d.putStringValue(call(item.value, "objectName()"))
+    #            d.putType(d.ns + "QObject")
+    #            d.put('addr="%s",' % cleanAddress(item.value.address))
+#            #d.putField("displayedtype", call(item, "m.metaObject()->className()"))
+#            gdb.execute("set variable %s->m=('%sQAbstractItemModel'*)%s" \
+#                % (dummy, d.ns, item.value.address))
+#            for row in xrange(rowCount):
+#                for column in xrange(columnCount):
+#                    gdb.execute("set variable %s->r=-1" % dummy)
+#                    gdb.execute("set variable %s->c=-1" % dummy)
+#                    with SubItem(d):
+    #                    d.putName("[%s,%s]" % (row, column))
+    #                    value = call(item.value, "data(*%s, 0)" % dummy)
+    #                    d.putValue(str(value))
+    #                    d.putNumChild(0)
+    #                    d.putType(" ")
 
 
 def qdump__QDateTime(d, item):
-    d.putStringValue(call(item.value, "toString(%sQt::TextDate)" % d.ns))
+    d.putStringValue(call(item.value, "toString('%sQt::TextDate')" % d.ns))
     d.putNumChild(3)
     if d.isExpanded(item):
-        d.beginChildren(8)
-        d.putCallItem("isNull", item, "isNull()")
-        d.putCallItem("toTime_t", item, "toTime_t()")
-        d.putCallItem("toString",
-            item, "toString(%sQt::TextDate)" % d.ns)
-        d.putCallItem("(ISO)",
-            item, "toString(%sQt::ISODate)" % d.ns)
-        d.putCallItem("(SystemLocale)",
-            item, "toString(%sQt::SystemLocaleDate)" % d.ns)
-        d.putCallItem("(Locale)",
-            item, "toString(%sQt::LocaleDate)" % d.ns)
-        d.putCallItem("toUTC",
-            item, "toTimeSpec(%sQt::UTC)" % d.ns)
-        d.putCallItem("toLocalTime",
-            item, "toTimeSpec(%sQt::LocalTime)" % d.ns)
-        d.endChildren()
+        with Children(d, 8):
+            d.putCallItem("isNull", item, "isNull()")
+            d.putCallItem("toTime_t", item, "toTime_t()")
+            d.putCallItem("toString",
+                item, "toString('%sQt::TextDate')" % d.ns)
+            d.putCallItem("(ISO)",
+                item, "toString('%sQt::ISODate')" % d.ns)
+            d.putCallItem("(SystemLocale)",
+                item, "toString('%sQt::SystemLocaleDate')" % d.ns)
+            d.putCallItem("(Locale)",
+                item, "toString('%sQt::LocaleDate')" % d.ns)
+            d.putCallItem("toUTC",
+                item, "toTimeSpec('%sQt::UTC')" % d.ns)
+            d.putCallItem("toLocalTime",
+                item, "toTimeSpec('%sQt::LocalTime')" % d.ns)
 
 
 def qdump__QDir(d, item):
     d.putStringValue(call(item.value, "path()"))
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren(2)
-        d.putCallItem("absolutePath", item, "absolutePath()")
-        d.putCallItem("canonicalPath", item, "canonicalPath()")
-        d.endChildren()
+        with Children(d, 2):
+            d.putCallItem("absolutePath", item, "absolutePath()")
+            d.putCallItem("canonicalPath", item, "canonicalPath()")
 
 
 def qdump__QFile(d, item):
     d.putStringValue(call(item.value, "fileName()"))
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren(2)
-        d.putCallItem("fileName", item, "fileName()")
-        d.putCallItem("exists", item, "exists()")
-        d.endChildren()
+        with Children(d, 2):
+            d.putCallItem("fileName", item, "fileName()")
+            d.putCallItem("exists", item, "exists()")
 
 
 def qdump__QFileInfo(d, item):
     d.putStringValue(call(item.value, "filePath()"))
     d.putNumChild(3)
     if d.isExpanded(item):
-        d.beginChildren(10, gdb.lookup_type(d.ns + "QString"))
-        d.putCallItem("absolutePath", item, "absolutePath()")
-        d.putCallItem("absoluteFilePath", item, "absoluteFilePath()")
-        d.putCallItem("canonicalPath", item, "canonicalPath()")
-        d.putCallItem("canonicalFilePath", item, "canonicalFilePath()")
-        d.putCallItem("completeBaseName", item, "completeBaseName()")
-        d.putCallItem("completeSuffix", item, "completeSuffix()")
-        d.putCallItem("baseName", item, "baseName()")
-        if False:
-            #ifdef Q_OS_MACX
-            d.putCallItem("isBundle", item, "isBundle()")
-            d.putCallItem("bundleName", item, "bundleName()")
-        d.putCallItem("fileName", item, "fileName()")
-        d.putCallItem("filePath", item, "filePath()")
-        # Crashes gdb (archer-tromey-python, at dad6b53fe)
-        #d.putCallItem("group", item, "group()")
-        #d.putCallItem("owner", item, "owner()")
-        d.putCallItem("path", item, "path()")
-
-        d.putCallItem("groupid", item, "groupId()")
-        d.putCallItem("ownerid", item, "ownerId()")
-
-        #QFile::Permissions permissions () const
-        perms = call(item.value, "permissions()")
-        if perms is None:
-            d.putValue("<not available>")
-        else:
-            d.beginHash()
-            d.putName("permissions")
-            d.putValue(" ")
-            d.putType(d.ns + "QFile::Permissions")
-            d.putNumChild(10)
-            if d.isExpandedIName(item.iname + ".permissions"):
-                d.beginChildren(10)
-                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)
-                d.endChildren()
-            d.endHash()
-
-        #QDir absoluteDir () const
-        #QDir dir () const
-        d.putCallItem("caching", item, "caching()")
-        d.putCallItem("exists", item, "exists()")
-        d.putCallItem("isAbsolute", item, "isAbsolute()")
-        d.putCallItem("isDir", item, "isDir()")
-        d.putCallItem("isExecutable", item, "isExecutable()")
-        d.putCallItem("isFile", item, "isFile()")
-        d.putCallItem("isHidden", item, "isHidden()")
-        d.putCallItem("isReadable", item, "isReadable()")
-        d.putCallItem("isRelative", item, "isRelative()")
-        d.putCallItem("isRoot", item, "isRoot()")
-        d.putCallItem("isSymLink", item, "isSymLink()")
-        d.putCallItem("isWritable", item, "isWritable()")
-        d.putCallItem("created", item, "created()")
-        d.putCallItem("lastModified", item, "lastModified()")
-        d.putCallItem("lastRead", item, "lastRead()")
-        d.endChildren()
+        with Children(d, 10, gdb.lookup_type(d.ns + "QString")):
+            d.putCallItem("absolutePath", item, "absolutePath()")
+            d.putCallItem("absoluteFilePath", item, "absoluteFilePath()")
+            d.putCallItem("canonicalPath", item, "canonicalPath()")
+            d.putCallItem("canonicalFilePath", item, "canonicalFilePath()")
+            d.putCallItem("completeBaseName", item, "completeBaseName()")
+            d.putCallItem("completeSuffix", item, "completeSuffix()")
+            d.putCallItem("baseName", item, "baseName()")
+            if False:
+                #ifdef Q_OS_MACX
+                d.putCallItem("isBundle", item, "isBundle()")
+                d.putCallItem("bundleName", item, "bundleName()")
+            d.putCallItem("fileName", item, "fileName()")
+            d.putCallItem("filePath", item, "filePath()")
+            # Crashes gdb (archer-tromey-python, at dad6b53fe)
+            #d.putCallItem("group", item, "group()")
+            #d.putCallItem("owner", item, "owner()")
+            d.putCallItem("path", item, "path()")
+
+            d.putCallItem("groupid", item, "groupId()")
+            d.putCallItem("ownerid", item, "ownerId()")
+
+            #QFile::Permissions permissions () const
+            perms = call(item.value, "permissions()")
+            if perms is None:
+                d.putValue("<not available>")
+            else:
+                with SubItem(d):
+                    d.putName("permissions")
+                    d.putValue(" ")
+                    d.putType(d.ns + "QFile::Permissions")
+                    d.putNumChild(10)
+                    if d.isExpandedIName(item.iname + ".permissions"):
+                        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
+            d.putCallItem("caching", item, "caching()")
+            d.putCallItem("exists", item, "exists()")
+            d.putCallItem("isAbsolute", item, "isAbsolute()")
+            d.putCallItem("isDir", item, "isDir()")
+            d.putCallItem("isExecutable", item, "isExecutable()")
+            d.putCallItem("isFile", item, "isFile()")
+            d.putCallItem("isHidden", item, "isHidden()")
+            d.putCallItem("isReadable", item, "isReadable()")
+            d.putCallItem("isRelative", item, "isRelative()")
+            d.putCallItem("isRoot", item, "isRoot()")
+            d.putCallItem("isSymLink", item, "isSymLink()")
+            d.putCallItem("isWritable", item, "isWritable()")
+            d.putCallItem("created", item, "created()")
+            d.putCallItem("lastModified", item, "lastModified()")
+            d.putCallItem("lastRead", item, "lastRead()")
 
 
 def qdump__QFlags(d, item):
@@ -289,21 +278,19 @@ def qdump__QHash(d, item):
 
         innerType = e_ptr.dereference().type
         inner = select(isSimpleKey and isSimpleValue, valueType, innerType)
-        d.beginChildren([size, 1000], inner)
-        for i in d.childRange():
-            it = node.dereference().cast(innerType)
-            d.beginHash()
-            key = it["key"]
-            value = it["value"]
-            if isSimpleKey and isSimpleValue:
-                d.putName(key)
-                d.putItemHelper(Item(value, item.iname, i))
-                d.putType(valueType)
-            else:
-                d.putItemHelper(Item(it, item.iname, i))
-            d.endHash()
-            node = hashDataNextNode(node)
-        d.endChildren()
+        with Children(d, [size, 1000], inner):
+            for i in d.childRange():
+                it = node.dereference().cast(innerType)
+                with SubItem(d):
+                    key = it["key"]
+                    value = it["value"]
+                    if isSimpleKey and isSimpleValue:
+                        d.putName(key)
+                        d.putItemHelper(Item(value, item.iname, i))
+                        d.putType(valueType)
+                    else:
+                        d.putItemHelper(Item(it, item.iname, i))
+                node = hashDataNextNode(node)
 
 
 def qdump__QHashNode(d, item):
@@ -313,22 +300,19 @@ def qdump__QHashNode(d, item):
     value = item.value["value"]
 
     if isSimpleType(keyType) and isSimpleType(valueType):
-        d.safePutItemHelper(Item(value, "data", item.iname))
+        d.putItemHelper(Item(value, "data", item.iname))
     else:
         d.putValue(" ")
 
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren()
-        d.beginHash()
-        d.putName("key")
-        d.putItemHelper(Item(key, item.iname, "key"))
-        d.endHash()
-        d.beginHash()
-        d.putName("value")
-        d.putItemHelper(Item(value, item.iname, "value"))
-        d.endHash()
-        d.endChildren()
+        with Children(d):
+            with SubItem(d):
+                d.putName("key")
+                d.putItemHelper(Item(key, item.iname, "key"))
+            with SubItem(d):
+                d.putName("value")
+                d.putItemHelper(Item(value, item.iname, "value"))
 
 
 def qdump__QList(d, item):
@@ -370,15 +354,14 @@ def qdump__QList(d, item):
         else:
             inner = innerType
         # about 0.5s / 1000 items
-        d.beginChildren([size, 2000], inner)
-        for i in d.childRange():
-            if isInternal:
-                d.putItem(Item(p.dereference(), item.iname, i))
-            else:
-                pp = p.cast(innerType.pointer().pointer()).dereference()
-                d.putItem(Item(pp.dereference(), item.iname, i))
-            p += 1
-        d.endChildren()
+        with Children(d, [size, 2000], inner):
+            for i in d.childRange():
+                if isInternal:
+                    d.putItem(Item(p.dereference(), item.iname, i))
+                else:
+                    pp = p.cast(innerType.pointer().pointer()).dereference()
+                    d.putItem(Item(pp.dereference(), item.iname, i))
+                p += 1
 
 
 def qdump__QImage(d, item):
@@ -396,14 +379,12 @@ def qdump__QImage(d, item):
     d.putNumChild(0)
     #d.putNumChild(1)
     if d.isExpanded(item):
-        d.beginChildren()
-        d.beginHash()
-        d.putName("data")
-        d.putType(" ");
-        d.putNumChild(0)
-        d.putValue("size: %s bytes" % nbytes);
-        d.endHash()
-        d.endChildren()
+        with Children(d):
+            with SubItem(d):
+                d.putName("data")
+                d.putType(" ");
+                d.putNumChild(0)
+                d.putValue("size: %s bytes" % nbytes);
     format = d.itemFormat(item)
     if format == 0:
         d.putDisplay(StopDisplay)
@@ -441,50 +422,45 @@ def qdump__QLinkedList(d, item):
     d.putItemCount(n)
     d.putNumChild(n)
     if d.isExpanded(item):
-        d.beginChildren([n, 1000], item.value.type.template_argument(0))
-        p = e_ptr["n"]
-        for i in d.childRange():
-            d.safePutItem(Item(p["t"], item.iname, i))
-            p = p["n"]
-        d.endChildren()
+        with Children(d, [n, 1000], item.value.type.template_argument(0)):
+            p = e_ptr["n"]
+            for i in d.childRange():
+                d.putItem(Item(p["t"], item.iname, i))
+                p = p["n"]
 
 
 def qdump__QLocale(d, item):
     d.putStringValue(call(item.value, "name()"))
     d.putNumChild(8)
     if d.isExpanded(item):
-        d.beginChildren(1, gdb.lookup_type(d.ns + "QChar"), 0)
-        d.putCallItem("country", item, "country()")
-        d.putCallItem("language", item, "language()")
-        d.putCallItem("measurementSystem", item, "measurementSystem()")
-        d.putCallItem("numberOptions", item, "numberOptions()")
-        d.putCallItem("timeFormat_(short)", item,
-            "timeFormat(" + d.ns + "QLocale::ShortFormat)")
-        d.putCallItem("timeFormat_(long)", item,
-            "timeFormat(" + d.ns + "QLocale::LongFormat)")
-        d.putCallItem("decimalPoint", item, "decimalPoint()")
-        d.putCallItem("exponential", item, "exponential()")
-        d.putCallItem("percent", item, "percent()")
-        d.putCallItem("zeroDigit", item, "zeroDigit()")
-        d.putCallItem("groupSeparator", item, "groupSeparator()")
-        d.putCallItem("negativeSign", item, "negativeSign()")
-        d.endChildren()
+        with Children(d, 1, gdb.lookup_type(d.ns + "QChar"), 0):
+            d.putCallItem("country", item, "country()")
+            d.putCallItem("language", item, "language()")
+            d.putCallItem("measurementSystem", item, "measurementSystem()")
+            d.putCallItem("numberOptions", item, "numberOptions()")
+            d.putCallItem("timeFormat_(short)", item,
+                "timeFormat(" + d.ns + "QLocale::ShortFormat)")
+            d.putCallItem("timeFormat_(long)", item,
+                "timeFormat(" + d.ns + "QLocale::LongFormat)")
+            d.putCallItem("decimalPoint", item, "decimalPoint()")
+            d.putCallItem("exponential", item, "exponential()")
+            d.putCallItem("percent", item, "percent()")
+            d.putCallItem("zeroDigit", item, "zeroDigit()")
+            d.putCallItem("groupSeparator", item, "groupSeparator()")
+            d.putCallItem("negativeSign", item, "negativeSign()")
 
 
 def qdump__QMapNode(d, item):
     d.putValue(" ")
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren(2)
-        d.beginHash()
-        d.putName("key")
-        d.putItemHelper(Item(item.value["key"], item.iname, "name"))
-        d.endHash()
-        d.beginHash()
-        d.putName("value")
-        d.putItemHelper(Item(item.value["value"], item.iname, "value"))
-        d.endHash()
-        d.endChildren()
+        with Children(d, 2):
+            with SubItem(d):
+                d.putName("key")
+                d.putItemHelper(Item(item.value["key"], item.iname, "name"))
+            with SubItem(d):
+                d.putName("value")
+                d.putItemHelper(Item(item.value["value"], item.iname, "value"))
 
 
 def qdump__QMap(d, item):
@@ -517,25 +493,22 @@ def qdump__QMap(d, item):
 
         innerType = select(isSimpleKey and isSimpleValue, valueType, nodeType)
 
-        d.beginChildren(n, innerType)
-        for i in xrange(n):
-            itd = it.dereference()
-            base = it.cast(charPtr) - payloadSize
-            node = base.cast(nodeType.pointer()).dereference()
-            d.beginHash()
-
-            key = node["key"]
-            value = node["value"]
-            #if isSimpleType(item.value.type): # or isStringType(d, item.value.type):
-            if isSimpleKey and isSimpleValue:
-                #d.putType(valueType)
-                d.putName(key)
-                d.putItemHelper(Item(value, item.iname, i))
-            else:
-                d.putItemHelper(Item(node, item.iname, i))
-            d.endHash()
-            it = it.dereference()["forward"].dereference()
-        d.endChildren()
+        with Children(d, n, innerType):
+            for i in xrange(n):
+                itd = it.dereference()
+                base = it.cast(charPtr) - payloadSize
+                node = base.cast(nodeType.pointer()).dereference()
+                with SubItem(d):
+                    key = node["key"]
+                    value = node["value"]
+                    #if isSimpleType(item.value.type): # or isStringType(d, item.value.type):
+                    if isSimpleKey and isSimpleValue:
+                        #d.putType(valueType)
+                        d.putName(key)
+                        d.putItemHelper(Item(value, item.iname, i))
+                    else:
+                        d.putItemHelper(Item(node, item.iname, i))
+                it = it.dereference()["forward"].dereference()
 
 
 def qdump__MultiMap(d, item):
@@ -551,18 +524,21 @@ def qdump__QModelIndex(d, item):
         d.putValue("(%s, %s)" % (r, c))
         d.putNumChild(5)
         if d.isExpanded(item):
-            d.beginChildren()
-            d.putIntItem("row", r)
-            d.putIntItem("column", c)
-            d.putCallItem("parent", item, "parent()")
-            d.beginHash()
-            d.putName("model")
-            d.putValue(m)
-            d.putType(d.ns + "QAbstractItemModel*")
-            d.putNumChild(1)
-            d.endHash()
-
-            d.endChildren()
+            with Children(d):
+                d.putIntItem("row", r)
+                d.putIntItem("column", c)
+                d.putCallItem("parent", item, "parent()")
+
+                with SubItem(d):
+                    d.putValue(m)
+                    d.putType(d.ns + "QAbstractItemModel*")
+                    d.putNumChild(1)
+
+                with SubItem(d):
+                    d.putName("model")
+                    d.putValue(m)
+                    d.putType(d.ns + "QAbstractItemModel*")
+                    d.putNumChild(1)
     else:
         d.putValue("(invalid)")
         d.putNumChild(0)
@@ -610,152 +586,136 @@ def qdump__QObject(d, item):
     #warn("METADATA: %s " % metaData)
     #warn("STRINGDATA: %s " % metaStringData)
     #warn("TYPE: %s " % item.value.type)
+    #warn("INAME: %s " % item.iname)
     #d.putValue("")
     d.putStringValue(objectName)
     #QSignalMapper::staticMetaObject
     #checkRef(d_ptr["ref"])
     d.putNumChild(4)
     if d.isExpanded(item):
-        d.beginChildren()
-
+      with Children(d):
         # Parent and children.
         d.putItem(Item(d_ptr["parent"], item.iname, "parent", "parent"))
         d.putItem(Item(d_ptr["children"], item.iname, "children", "children"))
 
         # Properties.
-        d.beginHash()
-        #propertyCount = metaData[6]
-        # FIXME: Replace with plain memory accesses.
-        propertyCount = int(call(mo, "propertyCount()"))
-        warn("PROPERTY COUNT: %s" % propertyCount)
-        propertyData = metaData[7]
-        d.putName("properties")
-        d.putItemCount(propertyCount)
-        d.putType(" ")
-        d.putNumChild(propertyCount)
-        if d.isExpandedIName(item.iname + ".properties"):
-            d.beginChildren()
-            for property in xrange(propertyCount):
-                d.beginHash()
-                offset = propertyData + 3 * property
-                propertyName = extractCString(metaStringData, metaData[offset])
-                propertyType = extractCString(metaStringData, metaData[offset + 1])
-                d.putName(propertyName)
-                #flags = metaData[offset + 2]
-                #warn("FLAGS: %s " % flags)
-                #warn("PROPERTY: %s %s " % (propertyType, propertyName))
-                # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
-                #     % (d.ns, item.value.address, propertyName)
-                #exp = '"((\'%sQObject\'*)%s)"' % (d.ns, item.value.address,)
-                #warn("EXPRESSION:  %s" % exp)
-                value = call(item.value, 'property("%s")' % propertyName)
-                val, inner, innert = qdumpHelper__QVariant(d, value)
-                if len(inner):
-                    # Build-in types.
-                    d.putType(inner)
-                    d.putItemHelper(Item(val, item.iname + ".properties",
-                                        propertyName, propertyName))
-
-                else:
-                    # User types.
-               #    func = "typeToName(('%sQVariant::Type')%d)" % (d.ns, variantType)
-               #    type = str(call(item.value, func))
-               #    type = type[type.find('"') + 1 : type.rfind('"')]
-               #    type = type.replace("Q", d.ns + "Q") # HACK!
-               #    data = call(item.value, "constData()")
-               #    tdata = data.cast(gdb.lookup_type(type).pointer()).dereference()
-               #    d.putValue("(%s)" % tdata.type)
-               #    d.putType(tdata.type)
-               #    d.putNumChild(1)
-               #    if d.isExpanded(item):
-               #        d.beginChildren()
-               #        d.putItem(Item(tdata, item.iname, "data", "data"))
-               #        d.endChildren()
-                    warn("FIXME: CUSTOM QOBJECT PROPERTIES NOT IMPLEMENTED: %s %s"
-                        % (propertyType, innert))
-                    d.putType(propertyType)
-                    d.putValue("...")
-                    d.putNumChild(0)
-
-                d.endHash()
-            d.endChildren()
-
-
-        # connections
-        d.beginHash()
-        connectionCount = 0
-        d.putName("connections")
-        d.putItemCount(connectionCount)
-        d.putType(" ")
-        d.putNumChild(connectionCount)
-        if connectionCount:
-            d.putField("childtype", "")
-            d.putField("childnumchild", "0")
-
-        if d.isExpandedIName(item.iname + ".connections"):
-            d.beginChildren()
-
-            connectionLists = d_ptr["connectionLists"]
-            warn("CONNECTIONLISTS: %s " % connectionLists)
-
-            for connection in xrange(connectionCount):
-                d.beginHash()
-                d.putField("iname", "%s.connections.%d" % (item.iname, connection))
-                d.putName("connection %d" % connection)
-                d.putValue("")
-                d.endHash()
-            d.endChildren()
-        d.endHash()
+        with SubItem(d):
+            #propertyCount = metaData[6]
+            # FIXME: Replace with plain memory accesses.
+            propertyCount = call(mo, "propertyCount()")
+            #warn("PROPERTY COUNT: %s" % propertyCount)
+            propertyData = metaData[7]
+            d.putName("properties")
+            d.putItemCount(propertyCount)
+            d.putType(" ")
+            d.putNumChild(propertyCount)
+            if d.isExpandedIName(item.iname + ".properties"):
+                with Children(d):
+                    for property in xrange(propertyCount):
+                        with SubItem(d):
+                            offset = propertyData + 3 * property
+                            propertyName = extractCString(metaStringData, metaData[offset])
+                            propertyType = extractCString(metaStringData, metaData[offset + 1])
+                            d.putName(propertyName)
+                            #flags = metaData[offset + 2]
+                            #warn("FLAGS: %s " % flags)
+                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
+                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
+                            #     % (d.ns, item.value.address, propertyName)
+                            #exp = '"((\'%sQObject\'*)%s)"' % (d.ns, item.value.address,)
+                            #warn("EXPRESSION:  %s" % exp)
+                            value = call(item.value, 'property("%s")' % propertyName)
+                            val, inner, innert = qdumpHelper__QVariant(d, value)
+                            if len(inner):
+                                # Build-in types.
+                                d.putType(inner)
+                                d.putItemHelper(Item(val, item.iname + ".properties",
+                                                    propertyName, propertyName))
+
+                            else:
+                                # User types.
+                           #    func = "typeToName(('%sQVariant::Type')%d)" % (d.ns, variantType)
+                           #    type = str(call(item.value, func))
+                           #    type = type[type.find('"') + 1 : type.rfind('"')]
+                           #    type = type.replace("Q", d.ns + "Q") # HACK!
+                           #    data = call(item.value, "constData()")
+                           #    tdata = data.cast(gdb.lookup_type(type).pointer()).dereference()
+                           #    d.putValue("(%s)" % tdata.type)
+                           #    d.putType(tdata.type)
+                           #    d.putNumChild(1)
+                           #    if d.isExpanded(item):
+                           #        with Children(d):
+                           #           d.putItem(Item(tdata, item.iname, "data", "data"))
+                                warn("FIXME: CUSTOM QOBJECT PROPERTIES NOT IMPLEMENTED: %s %s"
+                                    % (propertyType, innert))
+                                d.putType(propertyType)
+                                d.putValue("...")
+                                d.putNumChild(0)
+
+
+            # connections
+            with SubItem(d):
+                connectionCount = 0
+                d.putName("connections")
+                d.putItemCount(connectionCount)
+                d.putType(" ")
+                d.putNumChild(connectionCount)
+                if connectionCount:
+                    d.putField("childtype", "")
+                    d.putField("childnumchild", "0")
+
+                if d.isExpandedIName(item.iname + ".connections"):
+                    with Children(d):
+                        connectionLists = d_ptr["connectionLists"]
+                        warn("CONNECTIONLISTS: %s " % connectionLists)
+
+                        for connection in xrange(connectionCount):
+                            with SubItem(d):
+                                d.putField("iname", "%s.connections.%d"
+                                    % (item.iname, connection))
+                                d.putName("connection %d" % connection)
+                                d.putValue("")
 
         # Signals
         signalCount = metaData[13]
-        d.beginHash()
-        d.putName("signals")
-        d.putItemCount(signalCount)
-        d.putType(" ")
-        d.putNumChild(signalCount)
-        if signalCount:
-            # FIXME: empty type does not work for childtype
-            #d.putField("childtype", ".")
-            d.putField("childnumchild", "0")
-        if d.isExpandedIName(item.iname + ".signals"):
-            d.beginChildren()
-            for signal in xrange(signalCount):
-                d.beginHash()
-                offset = metaData[14 + 5 * signal]
-                d.putField("iname", "%s.signals.%d" % (item.iname, signal))
-                d.putName("signal %d" % signal)
-                d.putType(" ")
-                d.putValue(extractCString(metaStringData, offset))
-                d.endHash()
-            d.endChildren()
-        d.endHash()
+        with SubItem(d):
+            d.putName("signals")
+            d.putItemCount(signalCount)
+            d.putType(" ")
+            d.putNumChild(signalCount)
+            if signalCount:
+                # FIXME: empty type does not work for childtype
+                #d.putField("childtype", ".")
+                d.putField("childnumchild", "0")
+            if d.isExpandedIName(item.iname + ".signals"):
+                with Children(d):
+                    for signal in xrange(signalCount):
+                        with SubItem(d):
+                            offset = metaData[14 + 5 * signal]
+                            d.putField("iname", "%s.signals.%d" % (item.iname, signal))
+                            d.putName("signal %d" % signal)
+                            d.putType(" ")
+                            d.putValue(extractCString(metaStringData, offset))
 
         # Slots
-        d.beginHash()
-        slotCount = metaData[4] - signalCount
-        d.putName("slots")
-        d.putItemCount(slotCount)
-        d.putType(" ")
-        d.putNumChild(slotCount)
-        if slotCount:
-            #d.putField("childtype", ".")
-            d.putField("childnumchild", "0")
-        if d.isExpandedIName(item.iname + ".slots"):
-            d.beginChildren()
-            for slot in xrange(slotCount):
-                d.beginHash()
-                offset = metaData[14 + 5 * (signalCount + slot)]
-                d.putField("iname", "%s.slots.%d" % (item.iname, slot))
-                d.putName("slot %d" % slot)
-                d.putType(" ")
-                d.putValue(extractCString(metaStringData, offset))
-                d.endHash()
-            d.endChildren()
-        d.endHash()
-
-        d.endChildren()
-
+        with SubItem(d):
+            slotCount = metaData[4] - signalCount
+            d.putName("slots")
+            d.putItemCount(slotCount)
+            d.putType(" ")
+            d.putNumChild(slotCount)
+            if slotCount:
+                #d.putField("childtype", ".")
+                d.putField("childnumchild", "0")
+            if d.isExpandedIName(item.iname + ".slots"):
+                with Children(d):
+                    for slot in xrange(slotCount):
+                        with SubItem(d):
+                            offset = metaData[14 + 5 * (signalCount + slot)]
+                            d.putField("iname", "%s.slots.%d" % (item.iname, slot))
+                            d.putName("slot %d" % slot)
+                            d.putType(" ")
+                            d.putValue(extractCString(metaStringData, offset))
 
 # QObject
 
@@ -871,57 +831,49 @@ def qdump__QObject(d, item):
 #             signalCount += (mt == QMetaMethod::Signal)
 #             slotCount += (mt == QMetaMethod::Slot)
 #         }
-#         d.beginChildren()
-#         d.beginHash()
-#             d.putName("properties")
-#             // using 'addr' does not work in gdb as 'exp' is recreated as
-#             // (type *)addr, and here we have different 'types':
-#             // QObject vs QObjectPropertyList!
-#             d.putField("addr", d.data)
-#             d.putField("type", d.ns + "QObjectPropertyList")
-#             d.putItemCount(mo->propertyCount())
-#             d.putField("numchild", mo->propertyCount())
-#         d.endHash()
-#         d.beginHash()
-#             d.putName("signals")
-#             d.putField("addr", d.data)
-#             d.putField("type", d.ns + "QObjectSignalList")
-#             d.putItemCount(signalCount)
-#             d.putField("numchild", signalCount)
-#         d.endHash()
-#         d.beginHash()
-#             d.putName("slots")
-#             d.putField("addr", d.data)
-#             d.putField("type", d.ns + "QObjectSlotList")
-#             d.putItemCount(slotCount)
-#             d.putField("numchild", slotCount)
-#         d.endHash()
-#         const QObjectList objectChildren = ob->children()
-#         if !objectChildren.empty()) {
-#             d.beginHash()
-#             d.putName("children")
-#             d.putField("addr", d.data)
-#             d.putField("type", ns + "QObjectChildList")
-#             d.putItemCount(objectChildren.size())
-#             d.putField("numchild", objectChildren.size())
-#             d.endHash()
-#         }
-#         d.beginHash()
-#             d.putName("parent")
-#             dumpInnerValueHelper(d, ns + "QObject *", ob->parent())
-#         d.endHash()
-# #if 1
-#         d.beginHash()
-#             d.putName("className")
-#             d.putValue(ob->metaObject()->className())
-#             d.putField("type", "")
-#             d.putField("numchild", "0")
-#         d.endHash()
-# #endif
-#         d.endChildren()
+#         with Children(d):
+#             with SubItem(d):
+#                 d.putName("properties")
+#                 // using 'addr' does not work in gdb as 'exp' is recreated as
+#                 // (type *)addr, and here we have different 'types':
+#                 // QObject vs QObjectPropertyList!
+#                 d.putField("addr", d.data)
+#                 d.putField("type", d.ns + "QObjectPropertyList")
+#                 d.putItemCount(mo->propertyCount())
+#                 d.putField("numchild", mo->propertyCount())
+#             with SubItem(d):
+#                 d.putName("signals")
+#                 d.putField("addr", d.data)
+#                 d.putField("type", d.ns + "QObjectSignalList")
+#                 d.putItemCount(signalCount)
+#                 d.putField("numchild", signalCount)
+#             with SubItem(d):
+#                 d.putName("slots")
+#                 d.putField("addr", d.data)
+#                 d.putField("type", d.ns + "QObjectSlotList")
+#                 d.putItemCount(slotCount)
+#                 d.putField("numchild", slotCount)
+#             const QObjectList objectChildren = ob->children()
+#             if !objectChildren.empty()) {
+#                 with SubItem(d):
+#                    d.putName("children")
+#                    d.putField("addr", d.data)
+#                    d.putField("type", ns + "QObjectChildList")
+#                    d.putItemCount(objectChildren.size())
+#                    d.putField("numchild", objectChildren.size())
+#             with SubItem(d):
+#                 d.putName("parent")
+#                 if isSimpleType(item.value.type):
+#                     d.putItemHelper(d, ns + "QObject *", ob->parent())
+#     #if 1
+#             with SubItem(d):
+#                 d.putName("className")
+#                 d.putValue(ob->metaObject()->className())
+#                 d.putField("type", "")
+#                 d.putField("numchild", "0")
+#     #endif
 
 
-# #if USE_QT_GUI
 # static const char *sizePolicyEnumValue(QSizePolicy::Policy p)
 # {
 #     switch (p) {
@@ -1029,25 +981,19 @@ def qdump__QObject(d, item):
 #     if d.isExpanded(item):
 #         d.putField("childtype", ns + "QMetaMethod::Method")
 #         d.putField("childnumchild", "0")
-#         d.beginChildren()
-#         for (int i = 0; i != mo->methodCount(); ++i) {
-#             const QMetaMethod & method = mo->method(i)
-#             int mt = method.methodType()
-#             d.beginHash()
-#             d.beginItem("name")
-#                 d.put(i).put(" ").put(mo->indexOfMethod(method.signature()))
-#                 d.put(" ").put(method.signature())
-#             d.endItem()
-#             d.beginItem("value")
-#                 d.put((mt == QMetaMethod::Signal ? "<Signal>" : "<Slot>"))
-#                 d.put(" (").put(mt).put(")")
-#             d.endItem()
-#             d.endHash()
-#         }
-#         d.endChildren()
-#     }
-#     d.disarm()
-# }
+#         with Children(d):
+#            for (int i = 0; i != mo->methodCount(); ++i) {
+#                const QMetaMethod & method = mo->method(i)
+#                int mt = method.methodType()
+#                with SubItem(d):
+#                    d.beginItem("name")
+#                        d.put(i).put(" ").put(mo->indexOfMethod(method.signature()))
+#                        d.put(" ").put(method.signature())
+#                    d.endItem()
+#                    d.beginItem("value")
+#                        d.put((mt == QMetaMethod::Signal ? "<Signal>" : "<Slot>"))
+#                        d.put(" (").put(mt).put(")")
+#                    d.endItem()
 #
 # def qConnectionType(type):
 #     Qt::ConnectionType connType = static_cast<Qt::ConnectionType>(type)
@@ -1087,19 +1033,18 @@ def qdump__QObject(d, item):
 #                                               const QObject *partner,
 #                                               int number, const char *namePostfix)
 # {
-#     d.beginHash()
-#     d.beginItem("name")
-#     d.put(number).put(namePostfix)
-#     d.endItem()
-#     if partner == owner) {
-#         d.putValue("<this>")
-#         d.putField("type", owner->metaObject()->className())
-#         d.putField("numchild", 0)
-#         d.putField("addr", owner)
-#     } else {
-#         dumpInnerValueHelper(d, ns + "QObject *", partner)
-#     }
-#     d.endHash()
+#     with SubItem(d):
+#         d.beginItem("name")
+#         d.put(number).put(namePostfix)
+#         d.endItem()
+#         if partner == owner) {
+#             d.putValue("<this>")
+#             d.putField("type", owner->metaObject()->className())
+#             d.putField("numchild", 0)
+#             d.putField("addr", owner)
+#         } else {
+#       if isSimpleType(item.value.type):
+#           d.putItemHelper(ns + "QObject *", partner)
 #
 # static void dumpQObjectSignal(QDumper &d)
 # {
@@ -1112,34 +1057,30 @@ def qdump__QObject(d, item):
 # #if QT_VERSION >= 0x040400
 #     if d.isExpanded(item):
 #         const QObject *ob = reinterpret_cast<const QObject *>(d.data)
-#         d.beginChildren()
-#         const ConnectionList &connList = qConnectionList(ob, signalNumber)
-#         for (int i = 0; i != connList.size(); ++i) {
-#             const Connection &conn = connectionAt(connList, i)
-#             dumpQObjectConnectionPart(d, ob, conn.receiver, i, " receiver")
-#             d.beginHash()
-#                 d.beginItem("name")
-#                     d.put(i).put(" slot")
-#                 d.endItem()
-#                 d.putField("type", "")
-#                 if conn.receiver)
-#                     d.putValue(conn.receiver->metaObject()->method(conn.method).signature())
-#                 else
-#                     d.putValue("<invalid receiver>")
-#                 d.putField("numchild", "0")
-#             d.endHash()
-#             d.beginHash()
-#                 d.beginItem("name")
-#                     d.put(i).put(" type")
-#                 d.endItem()
-#                 d.putField("type", "")
-#                 d.beginItem("value")
-#                     d.put("<").put(qConnectionType(conn.connectionType)).put(" connection>")
-#                 d.endItem()
-#                 d.putField("numchild", "0")
-#             d.endHash()
-#         }
-#         d.endChildren()
+#         with Children(d):
+#              const ConnectionList &connList = qConnectionList(ob, signalNumber)
+#              for (int i = 0; i != connList.size(); ++i) {
+#                  const Connection &conn = connectionAt(connList, i)
+#                  dumpQObjectConnectionPart(d, ob, conn.receiver, i, " receiver")
+#                  with SubItem(d):
+#                      d.beginItem("name")
+#                          d.put(i).put(" slot")
+#                      d.endItem()
+#                      d.putField("type", "")
+#                      if conn.receiver)
+#                          d.putValue(conn.receiver->metaObject()->method(conn.method).signature())
+#                      else
+#                          d.putValue("<invalid receiver>")
+#                      d.putField("numchild", "0")
+#                  with SubItem(d):
+#                      d.beginItem("name")
+#                          d.put(i).put(" type")
+#                      d.endItem()
+#                      d.putField("type", "")
+#                      d.beginItem("value")
+#                          d.put("<").put(qConnectionType(conn.connectionType)).put(" connection>")
+#                      d.endItem()
+#                      d.putField("numchild", "0")
 #         d.putField("numchild", connList.size())
 # #endif
 #
@@ -1157,19 +1098,18 @@ def qdump__QObject(d, item):
 #     d.putField("numchild", count)
 # #if QT_VERSION >= 0x040400
 #     if d.isExpanded(item):
-#         d.beginChildren()
+#         with Children(d):
 #         for (int i = 0; i != methodCount; ++i) {
 #             const QMetaMethod & method = mo->method(i)
 #             if method.methodType() == QMetaMethod::Signal) {
 #                 int k = mo->indexOfSignal(method.signature())
 #                 const ConnectionList &connList = qConnectionList(ob, k)
-#                 d.beginHash()
-#                 d.putName(k)
-#                 d.putValue(method.signature())
-#                 d.putField("numchild", connList.size())
-#                 d.putField("addr", d.data)
-#                 d.putField("type", ns + "QObjectSignal")
-#                 d.endHash()
+#                 with SubItem(d):
+#                     d.putName(k)
+#                     d.putValue(method.signature())
+#                     d.putField("numchild", connList.size())
+#                     d.putField("addr", d.data)
+#                     d.putField("type", ns + "QObjectSignal")
 # #endif
 #
 # static void dumpQObjectSlot(QDumper &d)
@@ -1182,51 +1122,48 @@ def qdump__QObject(d, item):
 #
 # #if QT_VERSION >= 0x040400
 #     if d.isExpanded(item):
-#         d.beginChildren()
-#         int numchild = 0
-#         const QObject *ob = reinterpret_cast<const QObject *>(d.data)
-#         const ObjectPrivate *p = reinterpret_cast<const ObjectPrivate *>(dfunc(ob))
-# #if QT_VERSION >= 0x040600
-#         int s = 0
-#         for (SenderList senderList = p->senders; senderList != 0
-#              senderList = senderList->next, ++s) {
-#             const QObject *sender = senderList->sender
-#             int signal = senderList->method; // FIXME: 'method' is wrong.
-# #else
-#         for (int s = 0; s != p->senders.size(); ++s) {
-#             const QObject *sender = senderAt(p->senders, s)
-#             int signal = signalAt(p->senders, s)
-# #endif
-#             const ConnectionList &connList = qConnectionList(sender, signal)
-#             for (int i = 0; i != connList.size(); ++i) {
-#                 const Connection &conn = connectionAt(connList, i)
-#                 if conn.receiver == ob and conn.method == slotNumber) {
-#                     ++numchild
-#                     const QMetaMethod &method = sender->metaObject()->method(signal)
-#                     dumpQObjectConnectionPart(d, ob, sender, s, " sender")
-#                     d.beginHash()
-#                         d.beginItem("name")
-#                             d.put(s).put(" signal")
-#                         d.endItem()
-#                         d.putField("type", "")
-#                         d.putValue(method.signature())
-#                         d.putField("numchild", "0")
-#                     d.endHash()
-#                     d.beginHash()
-#                         d.beginItem("name")
-#                             d.put(s).put(" type")
-#                         d.endItem()
-#                         d.putField("type", "")
-#                         d.beginItem("value")
-#                             d.put("<").put(qConnectionType(conn.method))
-#                             d.put(" connection>")
-#                         d.endItem()
-#                         d.putField("numchild", "0")
-#                     d.endHash()
+#         with Children(d):
+#             int numchild = 0
+#             const QObject *ob = reinterpret_cast<const QObject *>(d.data)
+#             const ObjectPrivate *p = reinterpret_cast<const ObjectPrivate *>(dfunc(ob))
+# #####if QT_VERSION >= 0x040600
+#             int s = 0
+#             for (SenderList senderList = p->senders; senderList != 0
+#                  senderList = senderList->next, ++s) {
+#                 const QObject *sender = senderList->sender
+#                 int signal = senderList->method; // FIXME: 'method' is wrong.
+# #####else
+#             for (int s = 0; s != p->senders.size(); ++s) {
+#                 const QObject *sender = senderAt(p->senders, s)
+#                 int signal = signalAt(p->senders, s)
+# #####endif
+#                 const ConnectionList &connList = qConnectionList(sender, signal)
+#                 for (int i = 0; i != connList.size(); ++i) {
+#                     const Connection &conn = connectionAt(connList, i)
+#                     if conn.receiver == ob and conn.method == slotNumber) {
+#                         ++numchild
+#                         const QMetaMethod &method = sender->metaObject()->method(signal)
+#                         dumpQObjectConnectionPart(d, ob, sender, s, " sender")
+#                         with SubItem(d):
+#                             d.beginItem("name")
+#                                 d.put(s).put(" signal")
+#                             d.endItem()
+#                             d.putField("type", "")
+#                             d.putValue(method.signature())
+#                             d.putField("numchild", "0")
+#                         with SubItem(d):
+#                             d.beginItem("name")
+#                                 d.put(s).put(" type")
+#                             d.endItem()
+#                             d.putField("type", "")
+#                             d.beginItem("value")
+#                                 d.put("<").put(qConnectionType(conn.method))
+#                                 d.put(" connection>")
+#                             d.endItem()
+#                             d.putField("numchild", "0")
+#                     }
 #                 }
 #             }
-#         }
-#         d.endChildren()
 #         d.putField("numchild", numchild)
 #     }
 # #endif
@@ -1250,44 +1187,42 @@ def qdump__QObject(d, item):
 #     d.putItemCount(count)
 #     d.putField("type", ns + "QObjectSlotList")
 #     if d.isExpanded(item):
-#         d.beginChildren()
-# #if QT_VERSION >= 0x040400
-#         for (int i = 0; i != methodCount; ++i) {
-#             const QMetaMethod & method = mo->method(i)
-#             if method.methodType() == QMetaMethod::Slot) {
-#                 d.beginHash()
-#                 int k = mo->indexOfSlot(method.signature())
-#                 d.putName(k)
-#                 d.putValue(method.signature())
+#         with Children(d):
+#      #if QT_VERSION >= 0x040400
+#              for (int i = 0; i != methodCount; ++i) {
+#                  const QMetaMethod & method = mo->method(i)
+#                  if method.methodType() == QMetaMethod::Slot) {
+#                      with SubItem(d):
+#                           int k = mo->indexOfSlot(method.signature())
+#                           d.putName(k)
+#                           d.putValue(method.signature())
 #
-#                 // count senders. expensive...
-#                 int numchild = 0
-# #if QT_VERSION >= 0x040600
-#                 int s = 0
-#                 for (SenderList senderList = p->senders; senderList != 0
-#                      senderList = senderList->next, ++s) {
-#                     const QObject *sender = senderList->sender
-#                     int signal = senderList->method; // FIXME: 'method' is wrong.
-# #else
-#                 for (int s = 0; s != p->senders.size(); ++s) {
-#                     const QObject *sender = senderAt(p->senders, s)
-#                     int signal = signalAt(p->senders, s)
-# #endif
-#                     const ConnectionList &connList = qConnectionList(sender, signal)
-#                     for (int c = 0; c != connList.size(); ++c) {
-#                         const Connection &conn = connectionAt(connList, c)
-#                         if conn.receiver == ob and conn.method == k)
-#                             ++numchild
-#                     }
-#                 }
-#                 d.putField("numchild", numchild)
-#                 d.putField("addr", d.data)
-#                 d.putField("type", ns + "QObjectSlot")
-#                 d.endHash()
-#             }
-#         }
-# #endif
-#         d.endChildren()
+#                           // count senders. expensive...
+#                           int numchild = 0
+#      #if QT_VERSION      >= 0x040600
+#                           int s = 0
+#                           for (SenderList senderList = p->senders; senderList != 0
+#                                senderList = senderList->next, ++s) {
+#                               const QObject *sender = senderList->sender
+#                               int signal = senderList->method; // FIXME: 'method' is wrong.
+#      #else
+#                           for (int s = 0; s != p->senders.size(); ++s) {
+#                               const QObject *sender = senderAt(p->senders, s)
+#                               int signal = signalAt(p->senders, s)
+#      #endif
+#                               const ConnectionList &connList = qConnectionList(sender, signal)
+#                               for (int c = 0; c != connList.size(); ++c) {
+#                                   const Connection &conn = connectionAt(connList, c)
+#                                   if conn.receiver == ob and conn.method == k)
+#                                       ++numchild
+#                               }
+#                           }
+#                           d.putField("numchild", numchild)
+#                           d.putField("addr", d.data)
+#                           d.putField("type", ns + "QObjectSlot")
+#                  }
+#              }
+#      #endif
 #
 # #endif // QT_BOOTSTRAPPED
 
@@ -1313,10 +1248,9 @@ def qdump__QPoint(d, item):
     d.putValue("(%s, %s)" % (x, y))
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren(2, x.type.strip_typedefs())
-        d.putItem(Item(x, None, None, "x"))
-        d.putItem(Item(y, None, None, "y"))
-        d.endChildren()
+        with Children(d, 2, x.type.strip_typedefs()):
+            d.putItem(Item(x, None, None, "x"))
+            d.putItem(Item(y, None, None, "y"))
 
 
 def qdump__QPointF(d, item):
@@ -1334,12 +1268,11 @@ def qdump__QRect(d, item):
     d.putValue("%sx%s%s%s" % (w, h, pp(x1), pp(y1)))
     d.putNumChild(4)
     if d.isExpanded(item):
-        d.beginChildren(4, x1.type.strip_typedefs())
-        d.putItem(Item(x1, None, None, "x1"))
-        d.putItem(Item(y1, None, None, "y1"))
-        d.putItem(Item(x2, None, None, "x2"))
-        d.putItem(Item(y2, None, None, "y2"))
-        d.endChildren()
+        with Children(d, 4, x1.type.strip_typedefs()):
+            d.putItem(Item(x1, None, None, "x1"))
+            d.putItem(Item(y1, None, None, "y1"))
+            d.putItem(Item(x2, None, None, "x2"))
+            d.putItem(Item(y2, None, None, "y2"))
 
 
 def qdump__QRectF(d, item):
@@ -1356,12 +1289,11 @@ def qdump__QRectF(d, item):
     d.putValue("%sx%s%s%s" % (w, h, pp(x), pp(y)))
     d.putNumChild(4)
     if d.isExpanded(item):
-        d.beginChildren(4, x.type.strip_typedefs())
-        d.putItem(Item(x, None, None, "x"))
-        d.putItem(Item(y, None, None, "y"))
-        d.putItem(Item(w, None, None, "w"))
-        d.putItem(Item(h, None, None, "h"))
-        d.endChildren()
+        with Children(d, 4, x.type.strip_typedefs()):
+            d.putItem(Item(x, None, None, "x"))
+            d.putItem(Item(y, None, None, "y"))
+            d.putItem(Item(w, None, None, "w"))
+            d.putItem(Item(h, None, None, "h"))
 
 
 def qdump__QSet(d, item):
@@ -1411,19 +1343,17 @@ def qdump__QSet(d, item):
         isSimpleKey = isSimpleType(keyType)
         node = hashDataFirstNode(item.value)
         innerType = e_ptr.dereference().type
-        d.beginChildren([size, 1000], keyType)
-        for i in xrange(size):
-            it = node.dereference().cast(innerType)
-            d.beginHash()
-            key = it["key"]
-            if isSimpleKey:
-                d.putType(keyType)
-                d.putItemHelper(Item(key, None, None))
-            else:
-                d.putItemHelper(Item(key, item.iname, i))
-            d.endHash()
-            node = hashDataNextNode(node)
-        d.endChildren()
+        with Children(d, [size, 1000], keyType):
+            for i in xrange(size):
+                it = node.dereference().cast(innerType)
+                with SubItem(d):
+                    key = it["key"]
+                    if isSimpleKey:
+                        d.putType(keyType)
+                        d.putItemHelper(Item(key, None, None))
+                    else:
+                        d.putItemHelper(Item(key, item.iname, i))
+                node = hashDataNextNode(node)
 
 
 def qdump__QSharedPointer(d, item):
@@ -1436,10 +1366,9 @@ def qdump__QSize(d, item):
     d.putValue("(%s, %s)" % (w, h))
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren(2, w.type)
-        d.putItem(Item(w, item.iname, "w", "w"))
-        d.putItem(Item(h, item.iname, "h", "h"))
-        d.endChildren()
+        with Children(d, 2, w.type):
+            d.putItem(Item(w, item.iname, "w", "w"))
+            d.putItem(Item(h, item.iname, "h", "h"))
 
 
 def qdump__QSizeF(d, item):
@@ -1470,11 +1399,10 @@ def qdump__QStringList(d, item):
     if d.isExpanded(item):
         innerType = gdb.lookup_type(d.ns + "QString")
         ptr = gdb.Value(d_ptr["array"]).cast(innerType.pointer())
-        d.beginChildren([size, 1000], innerType)
-        for i in d.childRange():
-            d.putItem(Item(ptr.dereference(), item.iname, i))
-            ptr += 1
-        d.endChildren()
+        with Children(d, [size, 1000], innerType):
+            for i in d.childRange():
+                d.putItem(Item(ptr.dereference(), item.iname, i))
+                ptr += 1
 
 
 def qdump__QTemporaryFile(d, item):
@@ -1486,10 +1414,9 @@ def qdump__QTextCodec(d, item):
     d.putValue(encodeByteArray(value), 6)
     d.putNumChild(2)
     if d.isExpanded(item):
-        d.beginChildren()
-        d.putCallItem("name", item, "name()")
-        d.putCallItem("mibEnum", item, "mibEnum()")
-        d.endChildren()
+        with Children(d):
+            d.putCallItem("name", item, "name()")
+            d.putCallItem("mibEnum", item, "mibEnum()")
 
 def qdumpHelper__QVariant(d, value):
     #warn("VARIANT TYPE: %s : " % variantType)
@@ -1639,12 +1566,12 @@ def qdump__QVariant(d, item):
 
     if len(inner):
         # Build-in types.
-        d.putValue("(%s)" % innert)
+        #d.putValue("(%s)" % innert)
+        d.putType("%sQVariant (%s)" % (d.ns, innert))
         d.putNumChild(1)
         if d.isExpanded(item):
-            d.beginChildren()
-            d.putItem(Item(val, item.iname, "data", "data"))
-            d.endChildren()
+            with Children(d):
+                d.putItem(Item(val, item.iname, "data", "data"))
     else:
         # User types.
         d_member = item.value["d"]
@@ -1654,13 +1581,11 @@ def qdump__QVariant(d, item):
         type = type.replace("Q", d.ns + "Q") # HACK!
         data = call(item.value, "constData()")
         tdata = data.cast(gdb.lookup_type(type).pointer()).dereference()
-        d.putValue("(%s)" % tdata.type)
-        d.putType(tdata.type)
+        d.putType("%sQVariant (%s)" % (d.ns, tdata.type))
         d.putNumChild(1)
         if d.isExpanded(item):
-            d.beginChildren()
-            d.putItem(Item(tdata, item.iname, "data", "data"))
-            d.endChildren()
+            with Children(d):
+                d.putItem(Item(tdata, item.iname, "data", "data"))
 
 
 def qdump__QVector(d, item):
@@ -1677,11 +1602,10 @@ def qdump__QVector(d, item):
     d.putNumChild(size)
     if d.isExpanded(item):
         p = gdb.Value(p_ptr["array"]).cast(innerType.pointer())
-        d.beginChildren([size, 2000], innerType)
-        for i in d.childRange():
-            d.safePutItem(Item(p.dereference(), item.iname, i))
-            p += 1
-        d.endChildren()
+        with Children(d, [size, 2000], innerType):
+            for i in d.childRange():
+                d.putItem(Item(p.dereference(), item.iname, i))
+                p += 1
 
 
 def qdump__QWeakPointer(d, item):
@@ -1709,11 +1633,10 @@ def qdump__QWeakPointer(d, item):
 
     d.putNumChild(3)
     if d.isExpanded(item):
-        d.beginChildren(3)
-        d.putItem(Item(value.dereference(), item.iname, "data", "data"))
-        d.putIntItem("weakref", weakref)
-        d.putIntItem("strongref", strongref)
-        d.endChildren()
+        with Children(d, 3):
+            d.putItem(Item(value.dereference(), item.iname, "data", "data"))
+            d.putIntItem("weakref", weakref)
+            d.putIntItem("strongref", strongref)
 
 
 
@@ -1733,21 +1656,20 @@ def qdump__std__deque(d, item):
         innerType = item.value.type.template_argument(0)
         innerSize = innerType.sizeof
         bufsize = select(innerSize < 512, 512 / innerSize, 1)
-        d.beginChildren([size, 2000], innerType)
-        pcur = start["_M_cur"]
-        pfirst = start["_M_first"]
-        plast = start["_M_last"]
-        pnode = start["_M_node"]
-        for i in d.childRange():
-            d.safePutItem(Item(pcur.dereference(), item.iname, i))
-            pcur += 1
-            if pcur == plast:
-                newnode = pnode + 1
-                pnode = newnode
-                pfirst = newnode.dereference()
-                plast = pfirst + bufsize
-                pcur = pfirst
-        d.endChildren()
+        with Children(d, [size, 2000], innerType):
+            pcur = start["_M_cur"]
+            pfirst = start["_M_first"]
+            plast = start["_M_last"]
+            pnode = start["_M_node"]
+            for i in d.childRange():
+                d.putItem(Item(pcur.dereference(), item.iname, i))
+                pcur += 1
+                if pcur == plast:
+                    newnode = pnode + 1
+                    pnode = newnode
+                    pfirst = newnode.dereference()
+                    plast = pfirst + bufsize
+                    pcur = pfirst
 
 
 def qdump__std__list(d, item):
@@ -1766,13 +1688,12 @@ def qdump__std__list(d, item):
     if d.isExpanded(item):
         p = node["_M_next"]
         innerType = item.value.type.template_argument(0)
-        d.beginChildren([size, 1000], innerType)
-        for i in d.childRange():
-            innerPointer = innerType.pointer()
-            value = (p + 1).cast(innerPointer).dereference()
-            d.safePutItem(Item(value, item.iname, i))
-            p = p["_M_next"]
-        d.endChildren()
+        with Children(d, [size, 1000], innerType):
+            for i in d.childRange():
+                innerPointer = innerType.pointer()
+                value = (p + 1).cast(innerPointer).dereference()
+                d.putItem(Item(value, item.iname, i))
+                p = p["_M_next"]
 
 
 def qdump__std__map(d, item):
@@ -1791,39 +1712,36 @@ def qdump__std__map(d, item):
         innerType = select(isSimpleKey and isSimpleValue, valueType, pairType)
         pairPointer = pairType.pointer()
         node = impl["_M_header"]["_M_left"]
-        d.beginChildren([size, 1000], select(size > 0, innerType, pairType),
-            select(isSimpleKey and isSimpleValue, None, 2))
-        for i in d.childRange():
-            pair = (node + 1).cast(pairPointer).dereference()
-
-            d.beginHash()
-            if isSimpleKey and isSimpleValue:
-                d.putName(str(pair["first"]))
-                d.putItemHelper(Item(pair["second"], item.iname, i))
-            else:
-                d.putValue(" ")
-                if d.isExpandedIName("%s.%d" % (item.iname, i)):
-                    d.beginChildren(2, None)
-                    iname = "%s.%d" % (item.iname, i)
-                    keyItem = Item(pair["first"], iname, "first", "first")
-                    valueItem = Item(pair["second"], iname, "second", "second")
-                    d.putItem(keyItem)
-                    d.putItem(valueItem)
-                    d.endChildren()
-            d.endHash()
-
-            if isNull(node["_M_right"]):
-                parent = node["_M_parent"]
-                while node == parent["_M_right"]:
-                    node = parent
-                    parent = parent["_M_parent"]
-                if node["_M_right"] != parent:
-                    node = parent
-            else:
-                node = node["_M_right"]
-                while not isNull(node["_M_left"]):
-                    node = node["_M_left"]
-        d.endChildren()
+        with Children(d, [size, 1000], select(size > 0, innerType, pairType),
+            select(isSimpleKey and isSimpleValue, None, 2)):
+            for i in d.childRange():
+                pair = (node + 1).cast(pairPointer).dereference()
+
+                with SubItem(d):
+                    if isSimpleKey and isSimpleValue:
+                        d.putName(str(pair["first"]))
+                        d.putItemHelper(Item(pair["second"], item.iname, i))
+                    else:
+                        d.putValue(" ")
+                        if d.isExpandedIName("%s.%d" % (item.iname, i)):
+                            with Children(d, 2, None):
+                                iname = "%s.%d" % (item.iname, i)
+                                keyItem = Item(pair["first"], iname, "first", "first")
+                                valueItem = Item(pair["second"], iname, "second", "second")
+                                d.putItem(keyItem)
+                                d.putItem(valueItem)
+
+                if isNull(node["_M_right"]):
+                    parent = node["_M_parent"]
+                    while node == parent["_M_right"]:
+                        node = parent
+                        parent = parent["_M_parent"]
+                    if node["_M_right"] != parent:
+                        node = parent
+                else:
+                    node = node["_M_right"]
+                    while not isNull(node["_M_left"]):
+                        node = node["_M_left"]
 
 
 def qdump__std__set(d, item):
@@ -1835,23 +1753,22 @@ def qdump__std__set(d, item):
     if d.isExpanded(item):
         valueType = item.value.type.template_argument(0)
         node = impl["_M_header"]["_M_left"]
-        d.beginChildren([size, 1000], valueType)
-        for i in d.childRange():
-            element = (node + 1).cast(valueType.pointer()).dereference()
-            d.putItem(Item(element, item.iname, i))
-
-            if isNull(node["_M_right"]):
-                parent = node["_M_parent"]
-                while node == parent["_M_right"]:
-                    node = parent
-                    parent = parent["_M_parent"]
-                if node["_M_right"] != parent:
-                    node = parent
-            else:
-                node = node["_M_right"]
-                while not isNull(node["_M_left"]):
-                    node = node["_M_left"]
-        d.endChildren()
+        with Children(d, [size, 1000], valueType):
+            for i in d.childRange():
+                element = (node + 1).cast(valueType.pointer()).dereference()
+                d.putItem(Item(element, item.iname, i))
+
+                if isNull(node["_M_right"]):
+                    parent = node["_M_parent"]
+                    while node == parent["_M_right"]:
+                        node = parent
+                        parent = parent["_M_parent"]
+                    if node["_M_right"] != parent:
+                        node = parent
+                else:
+                    node = node["_M_right"]
+                    while not isNull(node["_M_left"]):
+                        node = node["_M_left"]
 
 
 def qdump__std__string(d, item):
@@ -1864,15 +1781,13 @@ def qdump__std__string(d, item):
     alloc = rep['_M_capacity']
     check(rep['_M_refcount'] >= 0)
     check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
-    d.unputField("type")
     p = gdb.Value(data.cast(charType.pointer()))
     s = ""
+    # Override "std::basic_string<...>
     if str(charType) == "char":
-        d.putType("std::string")
+        d.putType("std::string", 1)
     elif str(charType) == "wchar_t":
-        d.putType("std::wstring")
-    else:
-        d.putType(baseType)
+        d.putType("std::wstring", 1)
 
     n = qmin(size, 1000)
     if charType.sizeof == 1:
@@ -1880,7 +1795,7 @@ def qdump__std__string(d, item):
         for i in xrange(size):
             s += format % int(p.dereference())
             p += 1
-        d.putValue(s, Hex4EncodedLittleEndian)
+        d.putValue(s, Hex2EncodedLatin1)
         d.putNumChild(0)
     elif charType.sizeof == 2:
         format = "%02x%02x"
@@ -1919,12 +1834,11 @@ def qdump__std__vector(d, item):
     d.putItemCount(size)
     d.putNumChild(size)
     if d.isExpanded(item):
-        p = start
-        d.beginChildren([size, 10000], item.value.type.template_argument(0))
-        for i in d.childRange():
-            d.safePutItem(Item(p.dereference(), item.iname, i))
-            p += 1
-        d.endChildren()
+        with Children(d, [size, 10000], item.value.type.template_argument(0)):
+            p = start
+            for i in d.childRange():
+                d.putItem(Item(p.dereference(), item.iname, i))
+                p += 1
 
 
 def qdump__string(d, item):
-- 
GitLab