From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20550 invoked by alias); 5 Oct 2008 00:00:43 -0000 Received: (qmail 20539 invoked by uid 22791); 5 Oct 2008 00:00:41 -0000 X-Spam-Check-By: sourceware.org Received: from mx2.redhat.com (HELO mx2.redhat.com) (66.187.237.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 05 Oct 2008 00:00:05 +0000 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id m94Nxw4p013424; Sat, 4 Oct 2008 19:59:59 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m94Nxv5U018340; Sat, 4 Oct 2008 19:59:57 -0400 Received: from opsy.redhat.com (vpn-10-12.bos.redhat.com [10.16.10.12]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id m94NxtZp008903; Sat, 4 Oct 2008 19:59:55 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id B867137831F; Sat, 4 Oct 2008 17:58:16 -0600 (MDT) To: Joel Brobecker Cc: Thiago Jung Bauermann , gdb-patches ml Subject: Re: [rfc] expose gdb values to python References: <1221199426.24580.26.camel@localhost.localdomain> <20081001054741.GE3665@adacore.com> <20081004222055.GA7541@caradoc.them.org> From: Tom Tromey Reply-To: Tom Tromey X-Attribution: Tom Date: Sun, 05 Oct 2008 00:00:00 -0000 In-Reply-To: <20081004222055.GA7541@caradoc.them.org> (Daniel Jacobowitz's message of "Sat\, 4 Oct 2008 18\:20\:55 -0400") Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-10/txt/msg00123.txt.bz2 >>>>> "Daniel" == Daniel Jacobowitz writes: Daniel> WDYT about making this work anyway - and using a documented namespace Daniel> for any methods we add? Then the common case will be able to use the Daniel> attributes safely. In practice, I don't mind how it works now. I wrote a few pretty-printers (appended for your viewing pleasure) and I found that the array syntax is not a real impediment. If anything, the dereference method is more of a pain. FYI -- on the current python branch, Value already has a few more methods: address, cast, and type. I guess I wouldn't mind a mangling scheme if it were unobtrusive enough. Tom # Pretty-printers for libstc++. def printstdlist(val): "Print a std::list" itype = val.type().template_argument(0) nodetype = gdb.Type('std::_List_node<%s>' % itype).pointer() head = val['_M_impl']['_M_node'] base = head['_M_next'] head = head.address() max = gdb.get_parameter('print elements') n = 0 result = [] while base != head and (max == 0 or n < max): elt = base.cast(nodetype).dereference() datum = elt['_M_data'] result.append ('[%d] = %s' % (n, str (datum))) n = n + 1 base = elt['_M_next'] if len (result) == 0: result.append('<>') return "\n".join(result) def printstdvector(val): "Print a std::vector" start = val['_M_impl']['_M_start'] finish = val['_M_impl']['_M_finish'] end = val['_M_impl']['_M_end_of_storage'] 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) def printstdstring(val): "Print a std::string" return val['_M_dataplus']['_M_p'] gdb.pretty_printers['^std::list<.*>$'] = printstdlist gdb.pretty_printers['^std::vector<.*>$'] = printstdvector gdb.pretty_printers['^std::map<.*>$'] = printstdmap gdb.pretty_printers['^std::set<.*>$'] = printstdset gdb.pretty_printers['^std::basic_string$'] = printstdstring gdb.pretty_printers['^std::stack<.*>$'] = printstdstack gdb.pretty_printers['^std::queue<.*>$'] = printstdstack