public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-tromey-python:  * python/lib/gdb/libstdcxx/v6/printers.py: New file.
@ 2008-11-22  1:39 tromey
  0 siblings, 0 replies; only message in thread
From: tromey @ 2008-11-22  1:39 UTC (permalink / raw)
  To: archer-commits

The branch, archer-tromey-python has been updated
       via  e991a85b6bc0ec175e1d0357f10d74c5dd60780a (commit)
      from  6c35e923d5ba223e01f943798d9d093f58acf3da (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit e991a85b6bc0ec175e1d0357f10d74c5dd60780a
Author: Tom Tromey <tromey@redhat.com>
Date:   Fri Nov 21 18:38:39 2008 -0700

    	* python/lib/gdb/libstdcxx/v6/printers.py: New file.
    	* python/python.c (_initialize_python): Conditionally define
    	gdb.datadir.  Correctly update sys.path.  Set gdb.__path__.
    	* configure: Rebuild.
    	* configure.ac: Update CONFIG_INSTALL and CONFIG_UNINSTALL for
    	Python.
    	* Makefile.in (PY_FILES): New variable.
    	(install-python): New target.
    	(uninstall-python): Likewise.
    	(PY_DIRS): New variable.

-----------------------------------------------------------------------

Summary of changes:
 gdb/ChangeLog                               |   13 +
 gdb/Makefile.in                             |   29 ++
 gdb/configure                               |    2 +
 gdb/configure.ac                            |    2 +
 gdb/python/lib/gdb/libstdcxx/v6/printers.py |  522 +++++++++++++++++++++++++++
 gdb/python/python.c                         |    7 +-
 6 files changed, 573 insertions(+), 2 deletions(-)
 create mode 100644 gdb/python/lib/gdb/libstdcxx/v6/printers.py

First 500 lines of diff:
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cf899c5..8b15a01 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,18 @@
 2008-11-21  Tom Tromey  <tromey@redhat.com>
 
+	* python/lib/gdb/libstdcxx/v6/printers.py: New file.
+	* python/python.c (_initialize_python): Conditionally define
+	gdb.datadir.  Correctly update sys.path.  Set gdb.__path__.
+	* configure: Rebuild.
+	* configure.ac: Update CONFIG_INSTALL and CONFIG_UNINSTALL for
+	Python.
+	* Makefile.in (PY_FILES): New variable.
+	(install-python): New target.
+	(uninstall-python): Likewise.
+	(PY_DIRS): New variable.
+
+2008-11-21  Tom Tromey  <tromey@redhat.com>
+
 	* python/python.c (get_parameter): Use var_type, not type.
 
 2008-11-21  Tom Tromey  <tromey@redhat.com>
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index e60a504..79a9d1c 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1913,6 +1913,35 @@ python-value.o: $(srcdir)/python/python-value.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-value.c
 	$(POSTCOMPILE)
 
+# All Python install directories.  These must be sorted, shallowest
+# first.  These are maintained by hand because that is simpler than
+# writing portable sh to make the __init__.py files, and the result is
+# faster.
+PY_DIRS = gdb gdb/libstdcxx gdb/libstdcxx/v6
+
+# All python library files, with the "python/lib" stripped off.
+# Note that we should only install files in the "gdb" module.
+PY_FILES = gdb/libstdcxx/v6/printers.py
+
+# Install the Python library.  Python library files go under
+# $(GDB_DATADIR_PATH)/python.  We create a dummy __init__.py for
+# each directory, to make importing work properly.  If there is a real
+# __init__.py in PY_FILES, it will overwrite the dummy file.
+install-python:
+	dirs='$(PY_DIRS)'; for dir in $$dirs; do \
+	  $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR_PATH)/python/$$dir; \
+	  if ! test -f $(DESTDIR)$(GDB_DATADIR_PATH)/python/$$dir/__init__.py; then \
+	    echo > $(DESTDIR)$(GDB_DATADIR_PATH)/python/$$dir/__init__.py; \
+	  fi; \
+	done; \
+	files='$(PY_FILES)'; for file in $$files; do \
+	  $(INSTALL_DATA) $(srcdir)/python/lib/$$file $(DESTDIR)$(GDB_DATADIR_PATH)/python/$$file; \
+	done
+
+# Brute force.
+uninstall-python:
+	rm -rf $(DESTDIR)/$(GDB_DATADIR_PATH)/python
+
 #
 # Dependency tracking.  Most of this is conditional on GNU Make being
 # found by configure; if GNU Make is not found, we fall back to a
diff --git a/gdb/configure b/gdb/configure
index a3cc179..13ebfae 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -11739,6 +11739,8 @@ _ACEOF
   CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
   CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
   CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+  CONFIG_INSTALL="$CONFIG_INSTALL install-python"
+  CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python"
   ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
 
   # Flags needed to compile Python code (taken from python-config --cflags).
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 77e2f6c..08e0af8 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -681,6 +681,8 @@ if test "${have_libpython}" = yes; then
   CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
   CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
   CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+  CONFIG_INSTALL="$CONFIG_INSTALL install-python"
+  CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python"
   ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
 
   # Flags needed to compile Python code (taken from python-config --cflags).
diff --git a/gdb/python/lib/gdb/libstdcxx/v6/printers.py b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
new file mode 100644
index 0000000..d25b4db
--- /dev/null
+++ b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
@@ -0,0 +1,522 @@
+# Pretty-printers for libstc++.
+
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import gdb
+import itertools
+
+class StdPointerPrinter:
+    "Print a smart pointer of some kind"
+
+    def __init__ (self, typename, val):
+        self.typename = typename
+        self.val = val
+
+    def to_string (self):
+        return '%s (count %d) %s' % (self.typename, self.val['_M_refcount'],
+                                     self.val['_M_ptr'])
+
+class UniquePointerPrinter:
+    "Print a unique_ptr"
+
+    def __init__ (self, val):
+        self.val = val
+
+    def to_string (self):
+        return self.val['_M_t']
+
+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 __init__(self, val):
+        self.val = val
+
+    def children(self):
+        itype = self.val.type().template_argument(0)
+        nodetype = gdb.Type('std::_List_node<%s>' % itype).pointer()
+        return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
+
+    def to_string(self):
+        if self.val['_M_impl']['_M_node'].address() == self.val['_M_impl']['_M_node']['_M_next']:
+            return 'empty std::list'
+        return 'std::list'
+
+class StdSlistPrinter:
+    "Print a __gnu_cxx::slist"
+
+    class _iterator:
+        def __init__(self, nodetype, head):
+            self.nodetype = nodetype
+            self.base = head['_M_head']['_M_next']
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.base == 0:
+                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 __init__(self, val):
+        self.val = val
+
+    def children(self):
+        itype = self.val.type().template_argument(0)
+        nodetype = gdb.Type('__gnu_cxx::_Slist_node<%s>' % itype).pointer()
+        return self._iterator(nodetype, self.val)
+
+    def to_string(self):
+        if self.val['_M_head']['_M_next'] == 0:
+            return 'empty __gnu_cxx::slist'
+        return '__gnu_cxx::slist'
+
+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 __init__(self, val):
+        self.val = val
+
+    def children(self):
+        return self._iterator(self.val['_M_impl']['_M_start'],
+                              self.val['_M_impl']['_M_finish'])
+
+    def to_string(self):
+        start = self.val['_M_impl']['_M_start']
+        finish = self.val['_M_impl']['_M_finish']
+        end = self.val['_M_impl']['_M_end_of_storage']
+        return ('std::vector of length %d, capacity %d'
+                % (int (finish - start), int (end - start)))
+
+    def display_hint(self):
+        return 'whatever'
+
+class StdStackOrQueuePrinter:
+    "Print a std::stack or std::queue"
+
+    def __init__ (self, typename, val):
+        self.typename = typename
+        self.visualizer = gdb.get_default_visualizer(val['c'])
+
+    def children (self):
+        return self.visualizer.children()
+
+    def to_string (self):
+        return '%s wrapping: %s' % (self.typename,
+                                    self.visualizer.to_string())
+
+class RbtreeIterator:
+    def __init__(self, rbtree):
+        self.size = rbtree['_M_t']['_M_impl']['_M_node_count']
+        self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left']
+        self.count = 0
+
+    def __iter__(self):
+        return self
+
+    def __len__(self):
+        return int (self.size)
+
+    def next(self):
+        if self.count == self.size:
+            raise StopIteration
+        result = self.node
+        self.count = self.count + 1
+        if self.count < self.size:
+            # Compute the next node.
+            node = self.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
+            self.node = node
+        return result
+
+class StdMapPrinter:
+    "Print a std::map or std::multimap"
+
+    # Turn an RbtreeIterator into a pretty-print iterator.
+    class _iter:
+        def __init__(self, rbiter, type):
+            self.rbiter = rbiter
+            self.count = 0
+            self.type = type
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.count % 2 == 0:
+                n = self.rbiter.next()
+                n = n.cast(self.type).dereference()['_M_value_field']
+                self.pair = n
+                item = n['first']
+            else:
+                item = self.pair['second']
+            result = ('[%d]' % self.count, item)
+            self.count = self.count + 1
+            return result
+
+    def __init__ (self, typename, val):
+        self.typename = typename
+        self.val = val
+        self.iter = RbtreeIterator (val)
+
+    def to_string (self):
+        return '%s with %d elements' % (self.typename, len (self.iter))
+
+    def children (self):
+        keytype = self.val.type().template_argument(0)
+        valuetype = self.val.type().template_argument(1)
+        nodetype = gdb.Type('std::_Rb_tree_node< std::pair< const %s, %s > >' % (keytype, valuetype))
+        nodetype = nodetype.pointer()
+        return self._iter (self.iter, nodetype)
+
+    def display_hint (self):
+        return 'map'
+
+class StdSetPrinter:
+    "Print a std::set or std::multiset"
+
+    # Turn an RbtreeIterator into a pretty-print iterator.
+    class _iter:
+        def __init__(self, rbiter, type):
+            self.rbiter = rbiter
+            self.count = 0
+            self.type = type
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            item = self.rbiter.next()
+            item = item.cast(self.type).dereference()['_M_value_field']
+            # FIXME: this is weird ... what to do?
+            # Maybe a 'set' display hint?
+            result = ('[%d]' % self.count, item)
+            self.count = self.count + 1
+            return result
+
+    def __init__ (self, typename, val):
+        self.typename = typename
+        self.val = val
+        self.iter = RbtreeIterator (val)
+
+    def to_string (self):
+        return '%s with %d elements' % (self.typename, len (self.iter))
+
+    def children (self):
+        keytype = self.val.type().template_argument(0)
+        nodetype = gdb.Type('std::_Rb_tree_node< %s >' % keytype).pointer()
+        return self._iter (self.iter, nodetype)
+
+class StdBitsetPrinter:
+    "Print a std::bitset"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string (self):
+        # If template_argument handled values, we could print the
+        # size.  Or we could use a regexp on the type.
+        return 'std::bitset'
+
+    def children (self):
+        words = self.val['_M_w']
+        wtype = words.type()
+        tsize = wtype.target().sizeof()
+        nwords = wtype.sizeof() / tsize
+        result = []
+        byte = 0
+        while byte < nwords:
+            w = words[byte]
+            bit = 0
+            while w != 0:
+                if (w & 1) != 0:
+                    # Another spot where we could use 'set'?
+                    result.append(('[%d]' % (byte * tsize * 8 + bit), 1))
+                bit = bit + 1
+                w = w >> 1
+            byte = byte + 1
+        return result
+
+class StdDequePrinter:
+    "Print a std::deque"
+
+    class _iter:
+        def __init__(self, node, start, end, last, buffer_size):
+            self.node = node
+            self.p = start
+            self.end = end
+            self.last = last
+            self.buffer_size = buffer_size
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.p == self.last:
+                raise StopIteration
+
+            result = ('[%d]' % self.count, self.p.dereference())
+            self.count = self.count + 1
+
+            # Advance the 'cur' pointer.
+            self.p = self.p + 1
+            if self.p == self.end:
+                # If we got to the end of this bucket, move to the
+                # next bucket.
+                self.node = self.node + 1
+                self.p = self.node[0]
+                self.end = self.p + self.buffer_size
+
+            return result
+
+    def __init__(self, val):
+        self.val = val
+        self.elttype = val.type().template_argument(0)
+        size = self.elttype.sizeof ()
+        if size < 512:
+            self.buffer_size = int (512 / size)
+        else:
+            self.buffer_size = 1
+
+    def to_string(self):
+        start = self.val['_M_impl']['_M_start']
+        end = self.val['_M_impl']['_M_finish']
+
+        delta_n = end['_M_node'] - start['_M_node'] - 1
+        delta_s = start['_M_last'] - start['_M_cur']
+        delta_e = end['_M_cur'] - end['_M_first']
+
+        size = self.buffer_size * delta_n + delta_s + delta_e
+
+        return 'std::deque with %d elements' % long (size)
+
+    def children(self):
+        start = self.val['_M_impl']['_M_start']
+        end = self.val['_M_impl']['_M_finish']
+        return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'],
+                          end['_M_cur'], self.buffer_size)
+
+class WideEncoding (gdb.Parameter):
+    """The target wide character set is the encoding used for wchar_t."""
+
+    set_doc = "Set the target wide character set."
+    show_doc = "Show the target wide character set."
+
+    # FIXME: needs a complete method -- but does Parameter support it?
+    def __init__ (self):
+        super (WideEncoding, self).__init__ ("target-wide-charset",
+                                             gdb.COMMAND_SUPPORT,
+                                             gdb.PARAM_STRING)
+        # I think this is ok for most glibc locales.
+        self.value = 'UTF-32'
+
+target_wide_charset = WideEncoding()
+
+class StdStringPrinter:
+    "Print a std::basic_string of some kind"
+
+    def __init__(self, encoding, val):
+        self.encoding = encoding
+        self.val = val
+
+    def to_string(self):
+        # Look up the target encoding as late as possible.
+        encoding = self.encoding
+        if encoding is None:
+            encoding = gdb.get_parameter('target-charset')
+        elif isinstance(encoding, WideEncoding):
+            encoding = encoding.value
+        return self.val['_M_dataplus']['_M_p'].string(encoding)
+
+class Tr1HashtableIterator:
+    def __init__ (self, hash):
+        self.count = 0
+        self.n_buckets = hash['_M_bucket_count']
+        if self.n_buckets == 0:
+            self.node = False
+        else:
+            self.bucket = hash['_M_buckets']
+            self.node = self.bucket[0]
+            self.update ()


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-11-22  1:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-22  1:39 [SCM] archer-tromey-python: * python/lib/gdb/libstdcxx/v6/printers.py: New file tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).