This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] Fix glitches with libstdc++ pretty printers


>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:

Paul> Using Tom's pretty printers from:
Paul>  http://sourceware.org/ml/gdb-patches/2008-10/msg00123.html

FYI -- I randomly change these as I work on the pretty-printing code.
I've appended my current file.  You can see how some of the MI-style
printers are written here.

I guess I could check this in temporarily so we could share.
I don't want to ship this with gdb, since I think it belongs in
libstdc++.  But, in the interim it is nice if we can all be
up-to-date.  What do you think?

Paul> I am not making a test case for this, because there are some more
Paul> glitches to fix, and I'd rather have a single test for everything.

I haven't written any pretty-printing tests yet anyhow.  That is on my
to-do list, as is finishing the documentation on writing a
pretty-printer.

This patch is ok, thanks.

Tom


# Pretty-printers for libstc++.

class StdListPrinter:
    "Print a std::list"

    class _iterator:
        def __init__(self, nodetype, head):
            self.nodetype = nodetype
            self.base = head['_M_next']
            self.head = head.address()
            self.count = 0

        def __iter__(self):
            return self

        def next(self):
            if self.base == self.head:
                raise StopIteration
            elt = self.base.cast(self.nodetype).dereference()
            self.base = elt['_M_next']
            count = self.count
            self.count = self.count + 1
            return ('[%d]' % count, elt['_M_data'])

    def children(self, val):
        itype = val.type().template_argument(0)
        nodetype = gdb.Type('std::_List_node<%s>' % itype).pointer()
        return self._iterator(nodetype, val['_M_impl']['_M_node'])

    def header(self, val):
        if val['_M_impl']['_M_node'].address() == val['_M_impl']['_M_node']['_M_next']:
            return 'empty std::list'
        return 'std::list'

class StdVectorPrinter:
    "Print a std::vector"

    class _iterator:
        def __init__ (self, start, finish):
            self.item = start
            self.finish = finish
            self.count = 0

        def __iter__(self):
            return self

        def next(self):
            if self.item == self.finish:
                raise StopIteration
            count = self.count
            self.count = self.count + 1
            elt = self.item.dereference()
            self.item = self.item + 1
            return ('[%d]' % count, elt)

    def children(self, val):
        return self._iterator(val['_M_impl']['_M_start'],
                              val['_M_impl']['_M_finish'])

    def header(self, val):
        start = val['_M_impl']['_M_start'],
        finish = val['_M_impl']['_M_finish']
        end = val['_M_impl']['_M_end_of_storage']
        return ('std::vector of length %d, capacity %d'
                % (int (finish - start), int (end - start)))

# def printstdvector(val):
#     max = gdb.get_parameter('print elements')
#     result = []
#     result.append('std::vector of length %d, capacity %d'
#                   % (int (finish - start), int (end - start)))
#     i = 0
#     while start < finish and (max == 0 or i < max):
#         result.append('[%d] = %s' % (i, str(start.dereference())))
#         start = start + 1
#         i = i + 1
#     return "\n".join(result)

def printstdstack(val):
    "Print a std::stack or std::queue"
    # Maybe we should print stack and queue in opposite orders?
    cur = val['c']['_M_impl']['_M_start']['_M_cur']
    finish = val['c']['_M_impl']['_M_finish']['_M_cur']
    i = 0
    max = gdb.get_parameter('print elements')
    result = ['std::stack or std::queue of size %d' % int (finish -cur)]
    while cur != finish and (max == 0 or i < max):
        result.append('[%d] = %s' % (i, str (cur.dereference())))
        cur = cur + 1
        i = i + 1
    return "\n".join(result)

def rbtree_to_list(val):
    "Turn an rbtree into a size and a list of elements."
    maxprint = gdb.get_parameter('print elements')
    size = val['_M_t']['_M_impl']['_M_node_count']
    if maxprint == 0 or maxprint > size:
        maxprint = size
    node = val['_M_t']['_M_impl']['_M_header']['_M_left']
    i = 0
    result = []
    while i < maxprint:
        result.append(node)
        if node.dereference()['_M_right']:
            node = node.dereference()['_M_right']
            while node.dereference()['_M_left']:
                node = node.dereference()['_M_left']
        else:
            parent = node.dereference()['_M_parent']
            while node == parent.dereference()['_M_right']:
                node = parent
                parent = parent.dereference()['_M_parent']
            if node.dereference()['_M_right'] != parent:
                node = parent
        i = i + 1
    return (size, result)

def printstdmap(val):
    "Print a std::map"
    keytype = val.type().template_argument(0)
    valuetype = val.type().template_argument(1)
    nodetype = gdb.Type('std::_Rb_tree_node< std::pair< const %s, %s > >' % (keytype, valuetype))
    nodetype = nodetype.pointer()
    (size, nodes) = rbtree_to_list (val)
    result = ['std::map with %d elements' % int (size)]
    for node in nodes:
        pair = node.cast(nodetype).dereference()['_M_value_field']
        result.append('[%s] = %s' % (str (pair['first']), str (pair['second'])))
    return "\n".join(result)

def printstdset(val):
    "Print a std::set"
    keytype = val.type().template_argument(0)
    nodetype = gdb.Type("std::_Rb_tree_node< %s >" % keytype).pointer()
    (size, nodes) = rbtree_to_list (val)
    result = ['std::set with %d elements' % int (size)]
    for node in nodes:
        elt = node.cast(nodetype).dereference()['_M_value_field']
        result.append('  %s' % str (elt))
    return "\n".join(result)

class StdStringPrinter:
    def to_string(self, val):
        "Print a std::string"
        return val['_M_dataplus']['_M_p']

    def children(self, val):
        return ()

gdb.cli_pretty_printers['^std::basic_string<char.*>$'] = StdStringPrinter()
gdb.mi_pretty_printers['^std::basic_string<char.*>$'] = StdStringPrinter

gdb.cli_pretty_printers['^std::list<.*>$'] = StdListPrinter()
gdb.mi_pretty_printers['^std::list<.*>$'] = StdListPrinter

gdb.cli_pretty_printers['^std::vector<.*>$'] = StdVectorPrinter()
gdb.mi_pretty_printers['^std::vector<.*>$'] = StdVectorPrinter

gdb.cli_pretty_printers['^std::map<.*>$'] = printstdmap
gdb.cli_pretty_printers['^std::set<.*>$'] = printstdset
gdb.cli_pretty_printers['^std::stack<.*>$'] = printstdstack
gdb.cli_pretty_printers['^std::queue<.*>$'] = printstdstack


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]