Blob Blame History Raw
From b852c77e068a8f3dedf550470be99d913241d7a8 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 29 Jul 2011 13:22:35 +0200
Subject: [PATCH 1/2] add gdb pretty printers

---
 solenv/gdb/libreoffice/__init__.py           |   30 ++
 solenv/gdb/libreoffice/cppu.py               |  164 ++++++++
 solenv/gdb/libreoffice/sal.py                |  121 ++++++
 solenv/gdb/libreoffice/svl.py                |  125 ++++++
 solenv/gdb/libreoffice/sw.py                 |  119 ++++++
 solenv/gdb/libreoffice/tl.py                 |  371 ++++++++++++++++++
 solenv/gdb/libreoffice/util/__init__.py      |   30 ++
 solenv/gdb/libreoffice/util/compatibility.py |   38 ++
 solenv/gdb/libreoffice/util/printing.py      |  139 +++++++
 solenv/gdb/libreoffice/util/string.py        |   93 +++++
 solenv/gdb/libreoffice/util/uno.py           |  539 ++++++++++++++++++++++++++
 11 files changed, 1769 insertions(+), 0 deletions(-)
 create mode 100644 solenv/gdb/libreoffice/__init__.py
 create mode 100644 solenv/gdb/libreoffice/cppu.py
 create mode 100644 solenv/gdb/libreoffice/sal.py
 create mode 100644 solenv/gdb/libreoffice/svl.py
 create mode 100644 solenv/gdb/libreoffice/sw.py
 create mode 100644 solenv/gdb/libreoffice/tl.py
 create mode 100644 solenv/gdb/libreoffice/util/__init__.py
 create mode 100644 solenv/gdb/libreoffice/util/compatibility.py
 create mode 100644 solenv/gdb/libreoffice/util/printing.py
 create mode 100644 solenv/gdb/libreoffice/util/string.py
 create mode 100644 solenv/gdb/libreoffice/util/uno.py

diff --git a/solenv/gdb/libreoffice/__init__.py b/solenv/gdb/libreoffice/__init__.py
new file mode 100644
index 0000000..90d8012
--- /dev/null
+++ b/solenv/gdb/libreoffice/__init__.py
@@ -0,0 +1,30 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/cppu.py b/solenv/gdb/libreoffice/cppu.py
new file mode 100644
index 0000000..8707ea5
--- /dev/null
+++ b/solenv/gdb/libreoffice/cppu.py
@@ -0,0 +1,164 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+from libreoffice.util import printing
+from libreoffice.util.uno import TypeClass, make_uno_type, uno_cast
+
+class UnoAnyPrinter(object):
+    '''Prints UNO any'''
+
+    def __init__(self, typename, value):
+        self.value = value
+        self.typename = typename.replace('com::sun::star::', '')
+
+    def to_string(self):
+        if self._is_set():
+            return ('%s %s' % (self.typename, self._make_string()))
+        else:
+            return "empty %s" % self.typename
+
+    def _is_set(self):
+        return self.value['pType'].dereference()['eTypeClass'] != TypeClass.VOID
+
+    def _make_string(self):
+        ptr = self.value['pData']
+        assert ptr
+        type_desc = self.value['pType']
+        assert type_desc
+        type = make_uno_type(type_desc.dereference())
+        assert type
+        return str(uno_cast(type, ptr).dereference())
+
+class UnoReferencePrinter(object):
+    '''Prints reference to a UNO interface'''
+
+    def __init__(self, typename, value):
+        self.value = value
+        self.typename = typename.replace('com::sun::star::', '')
+
+    def to_string(self):
+        iface = self.value['_pInterface']
+        if iface:
+            impl = iface.cast(self._itype()).dereference()
+            return '%s to %s' % (self.typename, str(impl))
+        else:
+            return "empty %s" % self.typename
+
+    def _itype(self):
+        return self.value.type.template_argument(0).pointer()
+
+class UnoSequencePrinter(object):
+    '''Prints UNO Sequence'''
+
+    class iterator(object):
+        '''Sequence iterator'''
+
+        def __init__(self, first, size):
+            self.item = first
+            self.size = size
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.count == self.size:
+                raise StopIteration
+            count = self.count
+            self.count = self.count + 1
+            elem = self.item.dereference()
+            self.item = self.item + 1
+            return ('[%d]' % count, elem)
+
+
+    def __init__(self, typename, value):
+        self.value = value
+        self.typename = typename.replace('com::sun::star::', '')
+
+    def to_string(self):
+        pimpl = self.value['_pSequence']
+        if pimpl:
+            impl = pimpl.dereference()
+            elems = impl['nElements']
+            if elems == 0:
+                return "empty %s" % self.typename
+            else:
+                return "%s of length %d" % (self.typename, elems)
+        else:
+            return "uninitialized %s" % self.typename
+
+    def children(self):
+        pimpl = self.value['_pSequence']
+        if pimpl:
+            impl = pimpl.dereference()
+            elemtype = self.value.type.template_argument(0)
+            elements = impl['elements'].cast(elemtype.pointer())
+            return self.iterator(elements, int(impl['nElements']))
+        else:
+            # TODO is that the best thing to do here?
+            return None
+
+    def display_hint(self):
+        if self.value['_pSequence']:
+            return 'array'
+        else:
+            return None
+
+class UnoTypePrinter(object):
+    '''Prints UNO Type'''
+
+    def __init__(self, typename, value):
+        self.value = value
+        self.typename = typename.replace('com::sun::star::', '')
+
+    def to_string(self):
+        uno = make_uno_type(self.value)
+        if uno:
+            return "%s %s" % (self.typename, uno.tag)
+            # return "%s %s" % (self.typename, uno.typename)
+        else:
+            return "invalid %s" % self.typename
+
+printer = None
+
+def build_pretty_printers():
+    global printer
+
+    printer = printing.Printer("libreoffice/cppu")
+
+    # basic UNO stuff
+    printer.add('_uno_Any', UnoAnyPrinter)
+    printer.add('com::sun::star::uno::Any', UnoAnyPrinter)
+    printer.add('com::sun::star::uno::Sequence', UnoSequencePrinter)
+    printer.add('com::sun::star::uno::Type', UnoTypePrinter)
+
+def register_pretty_printers(obj):
+    printing.register_pretty_printer(printer, obj)
+
+build_pretty_printers()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/sal.py b/solenv/gdb/libreoffice/sal.py
new file mode 100644
index 0000000..e5a5d32
--- /dev/null
+++ b/solenv/gdb/libreoffice/sal.py
@@ -0,0 +1,121 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import gdb
+
+from libreoffice.util import printing
+from libreoffice.util.string import StringPrinterHelper
+
+class RtlStringPrinter(StringPrinterHelper):
+    '''Prints rtl_String or rtl_uString'''
+
+    def __init__(self, typename, val, encoding = None):
+        super(RtlStringPrinter, self).__init__(typename, val, encoding)
+
+    def data(self):
+        return self.val['buffer']
+
+    def length(self):
+        return self.val['length']
+
+class StringPrinter(StringPrinterHelper):
+    '''Prints rtl:: strings and string buffers'''
+
+    def __init__(self, typename, val, encoding = None):
+        super(StringPrinter, self).__init__(typename, val, encoding)
+
+    def valid(self):
+        return self.val['pData']
+
+    def data(self):
+        assert self.val['pData']
+        return self.val['pData'].dereference()['buffer']
+
+    def length(self):
+        assert self.val['pData']
+        return self.val['pData'].dereference()['length']
+
+class SalUnicodePrinter(StringPrinterHelper):
+    '''Prints a sal_Unicode*'''
+
+    def __init__(self, typename, val):
+        super(SalUnicodePrinter, self).__init__(typename, val, 'utf-16')
+
+    def data(self):
+        return self.val
+
+    @staticmethod
+    def query(type):
+        type = type.unqualified()
+        if type.code != gdb.TYPE_CODE_PTR:
+            return False
+        return str(type.target()) == 'sal_Unicode'
+
+class RtlReferencePrinter(object):
+    '''Prints rtl::Reference'''
+
+    def __init__(self, typename, val):
+        self.typename = typename
+        self.val = val
+
+    def to_string(self):
+        print("RtlReferencePrinter:to_string")
+        pointee = self.val['m_pBody']
+        if pointee:
+            val = pointee.dereference()
+            return '%s to %s' % (self.typename, str(val))
+        else:
+            return "empty %s" % self.typename
+
+printer = None
+
+def build_pretty_printers():
+    global printer
+
+    printer = printing.Printer("libreoffice/sal")
+
+    # strings and string buffers
+    printer.add('_rtl_String', RtlStringPrinter)
+    printer.add('_rtl_uString', lambda name, val: RtlStringPrinter(name,
+        val, 'utf-16le'))
+    printer.add('rtl::OString', StringPrinter)
+    printer.add('rtl::OUString', lambda name, val: StringPrinter(name, val, 'utf-16'))
+    printer.add('rtl::OStringBuffer', StringPrinter)
+    printer.add('rtl::OUStringBuffer', lambda name, val: StringPrinter(name, val, 'utf-16'))
+    printer.add('sal_Unicode', SalUnicodePrinter, SalUnicodePrinter.query)
+
+    # other stuff
+    printer.add('rtl::Reference', RtlReferencePrinter)
+
+    return printer
+
+def register_pretty_printers(obj):
+    printing.register_pretty_printer(printer, obj)
+
+build_pretty_printers()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/svl.py b/solenv/gdb/libreoffice/svl.py
new file mode 100644
index 0000000..639f7c5
--- /dev/null
+++ b/solenv/gdb/libreoffice/svl.py
@@ -0,0 +1,125 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import gdb
+
+from libreoffice.util import printing
+
+class SvArrayPrinter(object):
+    '''Prints macro-declared arrays from svl module'''
+
+    def __init__(self, typename, value):
+        self.typename = typename
+        self.value = value
+
+    def to_string(self):
+        if int(self.value['nA']):
+            return "%s of length %d" % (self.typename, self.value['nA'])
+        else:
+            return "empty " + self.typename
+
+    def children(self):
+        return self._iterator(self.value['pData'], self.value['nA'])
+
+    def display_hint(self):
+        return 'array'
+
+    class _iterator(object):
+
+        def __init__(self, data, count):
+            self.data = data
+            self.count = count
+            self.pos = 0
+            self._check_invariant()
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.pos == self.count:
+                raise StopIteration()
+
+            pos = self.pos
+            elem = self.data[pos]
+            self.pos = self.pos + 1
+
+            self._check_invariant()
+            return (str(pos), elem)
+
+        def _check_invariant(self):
+            assert self.count >= 0
+            if self.count > 0:
+                assert self.data
+            assert self.pos >= 0
+            assert self.pos <= self.count
+
+    @staticmethod
+    def query(type):
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target()
+        type = type.unqualified().strip_typedefs()
+
+        if not type.tag:
+            return False
+
+        ushort = gdb.lookup_type('sal_uInt16')
+        conforming = True
+        for field in type.fields():
+            if field.name == 'pData':
+                conforming = field.type.code == gdb.TYPE_CODE_PTR
+            elif field.name == 'nFree':
+                conforming = field.type == ushort
+            elif field.name == 'nA':
+                conforming = field.type == ushort
+            else:
+                conforming = False
+            if not conforming:
+                return False
+
+        try:
+            gdb.lookup_type('FnForEach_' + type.tag)
+        except RuntimeError:
+            return False
+
+        return True
+
+printer = None
+
+def build_pretty_printers():
+    global printer
+
+    printer = printing.Printer("libreoffice/svl")
+
+    # macro-based arrays from svl module
+    printer.add('SvArray', SvArrayPrinter, SvArrayPrinter.query)
+
+def register_pretty_printers(obj):
+    printing.register_pretty_printer(printer, obj)
+
+build_pretty_printers()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/sw.py b/solenv/gdb/libreoffice/sw.py
new file mode 100644
index 0000000..761c153
--- /dev/null
+++ b/solenv/gdb/libreoffice/sw.py
@@ -0,0 +1,119 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+from libreoffice.util import printing
+
+
+class BigPtrArrayPrinter(object):
+    '''Prints BigPtrArray.'''
+
+    def __init__(self, typename, value):
+        self.typename = typename
+        self.value = value
+
+    def to_string(self):
+        length = self.value['nSize']
+        if length > 0:
+            return "%s of length %d" % (self.typename, length)
+        else:
+            return "empty %s" % self.typename
+
+    def children(self):
+        return self._iterator(self.value)
+
+    def display_hint(self):
+        return 'array'
+
+
+    class _iterator(object):
+
+        def __init__(self, array):
+            self.blocks = array['ppInf']
+            self.count = array['nSize']
+            self.pos = 0
+            self.block_count = array['nBlock']
+            self.block_pos = 0
+            self.block = None
+            self._next_block(False)
+            self._check_invariant()
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.pos == self.count:
+                raise StopIteration()
+
+            name = str(self.pos)
+            value = self.block['pData'][self.pos - self.block['nStart']]
+            if self.pos == self.block['nEnd']:
+                self._next_block()
+            self.pos += 1
+
+            self._check_invariant()
+            return (name, value)
+
+        def _next_block(self, advance = True):
+            if advance:
+                self.block_pos += 1
+
+            if self.block_pos == self.block_count:
+                return
+
+            pblock = self.blocks[self.block_pos]
+            assert pblock
+            block = pblock.dereference()
+            start = block['nStart']
+            end = block['nEnd']
+            assert end - start + 1 == block['nElem']
+            if self.block:
+                assert start == self.block['nEnd'] + 1
+                assert end <= self.count
+            else:
+                assert start == 0
+            self.block = block
+
+        def _check_invariant(self):
+            assert self.pos <= self.count
+            assert self.block_pos <= self.block_count
+            if self.pos == 0 and self.pos < self.count:
+                assert self.block != None
+
+printer = None
+
+def build_pretty_printers():
+    global printer
+
+    printer = printing.Printer("libreoffice/sw")
+    printer.add('BigPtrArray', BigPtrArrayPrinter)
+
+def register_pretty_printers(obj):
+    printing.register_pretty_printer(printer, obj)
+
+build_pretty_printers()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/tl.py b/solenv/gdb/libreoffice/tl.py
new file mode 100644
index 0000000..62c5ff5
--- /dev/null
+++ b/solenv/gdb/libreoffice/tl.py
@@ -0,0 +1,371 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import gdb
+
+from libreoffice.util import printing
+from libreoffice.util.string import StringPrinterHelper
+
+class StringPrinter(StringPrinterHelper):
+    '''Prints ByteString or UniString'''
+
+    def __init__(self, typename, val, encoding = None):
+        super(StringPrinter, self).__init__(typename, val, encoding)
+
+    def valid(self):
+        data = self.val['mpData']
+        # mnRefCount is not a good indicator: it seems there could be
+        # cases where it is negative (-7FFFFFED)
+        return data #and data.dereference()['mnRefCount'] > 0
+
+    def data(self):
+        assert self.val['mpData']
+        return self.val['mpData'].dereference()['maStr']
+
+    def length(self):
+        assert self.val['mpData']
+        return self.val['mpData'].dereference()['mnLen']
+
+class BigIntPrinter(object):
+    '''Prints big integer'''
+
+    def __init__(self, typename, val):
+        self.val = val
+
+    def to_string(self):
+        if self.val['bIsSet']:
+            if self.val['bIsBig']:
+                return self._value()
+            else:
+                return self.val['nVal']
+        else:
+            return "unset %s" % self.typename
+
+    def _value(self):
+        len = self.val['nLen']
+        digits = self.val['nNum']
+        dsize = digits.dereference().type.sizeof * 8
+        num = 0
+        # The least significant byte is on index 0
+        for i in reversed(range(0, len)):
+            num <<= dsize
+            num += digits[i]
+        return num
+
+class ColorPrinter(object):
+    '''Prints color as rgb(r, g, b) or rgba(r, g, b, a)'''
+
+    def __init__(self, typename, val):
+        self.val = val
+
+    def to_string(self):
+        color = self.val['mnColor']
+        b = color & 0xff
+        g = (color >> 8) & 0xff
+        r = (color >> 16) & 0xff
+        a = (color >> 24) & 0xff
+        if a:
+            return "rgba(%d, %d, %d, %d)" % (r, g, b, a)
+        else:
+            return "rgb(%d, %d, %d)" % (r, g, b)
+
+class FractionPrinter(object):
+    '''Prints fraction'''
+
+    def __init__(self, typename, val):
+        self.typename = typename
+        self.val = val
+
+    def to_string(self):
+        numerator = self.val['nNumerator']
+        denominator = self.val['nDenominator']
+        if denominator > 0:
+            return "%d/%d" % (numerator, denominator)
+        else:
+            return "invalid %s" % self.typename
+
+class DateTimeImpl(object):
+
+    def __init__(self, date, time):
+        self.date = date
+        self.time = time
+
+    def __str__(self):
+        result = ''
+        if self.date:
+            result += str(self.date)
+            if self.time:
+                result += ' '
+        if self.time:
+            result += str(self.time)
+        return result
+
+    @staticmethod
+    def parse(val):
+        return DateTimeImpl(DateImpl.parse(val), TimeImpl.parse(val))
+
+class DateTimePrinter(object):
+    '''Prints date and time'''
+
+    def __init__(self, typename, val):
+        self.val = val
+
+    def to_string(self):
+        return str(DateTimeImpl.parse(self.val))
+
+class DateImpl(DateTimeImpl):
+
+    def __init__(self, year, month, day):
+        super(DateImpl, self).__init__(self, None)
+        self.year = year
+        self.month = month
+        self.day = day
+
+    def __str__(self):
+        return "%d-%d-%d" % (self.year, self.month, self.day)
+
+    @staticmethod
+    def parse(val):
+        date = val['nDate']
+        d = date % 100
+        m = (date / 100) % 100
+        y = date / 10000
+        return DateImpl(y, m, d)
+
+class DatePrinter(object):
+    '''Prints date'''
+
+    def __init__(self, typename, val):
+        self.val = val
+
+    def to_string(self):
+        return str(DateImpl.parse(self.val))
+
+class TimeImpl(DateTimeImpl):
+
+    def __init__(self, hour, minute, second, hundreth_of_second = 0):
+        super(TimeImpl, self).__init__(None, self)
+        self.hour = hour
+        self.minute = minute
+        self.second = second
+        self.hundreth_of_second = hundreth_of_second
+
+    def __str__(self):
+        decimal = ''
+        if self.hundreth_of_second != 0:
+            decimal = '.%d' % self.hundreth_of_second
+        return "%d:%d:%d%s" % (self.hour, self.minute, self.second, decimal)
+
+    @staticmethod
+    def parse(val):
+        time = val['nTime']
+        h = time / 1000000
+        m = (time / 10000) % 100
+        s = (time / 100) % 100
+        s_100 = time % 100
+        return TimeImpl(h, m, s, s_100)
+
+class TimePrinter(object):
+    '''Prints time'''
+
+    def __init__(self, typename, val):
+        self.val = val
+
+    def to_string(self):
+        return str(TimeImpl.parse(self.val))
+
+class IteratorHelper(object):
+    '''Implements a container iterator useable for both 'linear'
+        containers (like DynArray or List) and Tables
+    '''
+
+    def __init__(self, block, count, type = None):
+        self.count = count
+        self.type = type
+        self.pos = 0
+        self.block = None
+        self.block_count = 0
+        self.block_pos = 0
+        if block:
+            self._next_block(block)
+
+        self._check_invariant()
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if self.pos == self.count:
+            raise StopIteration()
+
+        if self.block_pos == self.block_count:
+            self._next_block(self.block['pNext'])
+
+        name = self.name()
+        val = self.value()
+        self.advance()
+
+        self._check_invariant()
+        return (name, val)
+
+    def _next_block(self, block):
+        assert block
+
+        self.block = block.dereference()
+        self.block_pos = 0
+        self.block_count = block['nCount']
+
+        assert self.block_count <= block['nSize']
+        assert self.block_count + self.pos <= self.count
+
+    def _check_invariant(self):
+        assert self.count >= 0
+        assert self.pos >= 0
+        assert self.pos <= self.count
+        assert self.block_count >= 0
+        if self.pos < self.count:
+            assert self.block_count > 0
+            assert self.block != None
+        assert self.block_count <= self.count
+        assert self.block_pos >= 0
+        assert self.block_pos <= self.block_count
+
+class NoItemType(Exception):
+    pass
+
+class ContainerHelper(object):
+    '''Provides support for specialized container printers'''
+
+    def __init__(self, typename, val, iterator):
+        self.typename = typename
+        self.val = val
+        self.iterator = iterator
+
+    def to_string(self):
+        size = self.val['nCount']
+        if size > 0:
+            return "%s of length %d" % (self.typename, size)
+        elif size == 0:
+            return "empty %s" % self.typename
+        else:
+            return "invalid %s" % self.typename
+
+    def children(self):
+        count = self.val.cast(gdb.lookup_type('Container'))['nCount']
+        return self.iterator(self.val['pFirstBlock'], count)
+
+class LinearIterator(IteratorHelper):
+    '''Is iterator for 'linear' container'''
+
+    def __init__(self, block, count, type = None):
+        super(LinearIterator, self).__init__(block, count, type)
+
+    def name(self):
+        return str(self.pos)
+
+    def value(self):
+        nodes = self.block['pNodes']#.cast(self.type.pointer())
+        return nodes[self.block_pos]
+
+    def advance(self):
+        self.pos += 1
+        self.block_pos += 1
+
+class LinearContainerPrinter(ContainerHelper):
+    '''Prints 'linear' container, like DynArray or List'''
+
+    def __init__(self, typename, val):
+        super(LinearContainerPrinter, self).__init__(typename, val, LinearIterator)
+
+    def display_hint(self):
+        return 'array'
+
+class TableIterator(IteratorHelper):
+    '''Is iterator for Table'''
+
+    def __init__(self, block, count, type = None):
+        super(TableIterator, self).__init__(block, count, type)
+        # ULONG doesn't work on 64-bit for some reason (gdb says it has
+        # size 4 and it's not a typedef to sal_uIntPtr)
+        self._key_type = gdb.lookup_type('sal_uIntPtr')
+        self.is_key = True
+
+    def name(self):
+        return ''
+
+    def value(self):
+        nodes = self.block['pNodes']#.cast(self.type.pointer())
+        val = nodes[self.block_pos]
+        if self.is_key:
+            val = str(val.cast(self._key_type))
+        return val
+
+    def advance(self):
+        self.pos += 1
+        self.block_pos += 1
+        self.is_key = not self.is_key
+
+class TablePrinter(ContainerHelper):
+    '''Prints table'''
+
+    def __init__(self, typename, val):
+        super(TablePrinter, self).__init__(typename, val, TableIterator)
+
+    def display_hint(self):
+        return 'map'
+
+printer = None
+
+def build_pretty_printers():
+    global printer
+
+    printer = printing.Printer('libreoffice/tl')
+
+    # old-style strings
+    printer.add('ByteString', StringPrinter)
+    printer.add('String', lambda name, val: StringPrinter(name, val, 'utf-16'))
+
+    # old-style containers
+    printer.add('DynArray', LinearContainerPrinter)
+    printer.add('List', LinearContainerPrinter)
+    printer.add('Stack', LinearContainerPrinter)
+    printer.add('Table', TablePrinter)
+
+    # various types
+    printer.add('BigInt', BigIntPrinter)
+    printer.add('Color', ColorPrinter)
+    printer.add('Fraction', FractionPrinter)
+    printer.add('DateTime', DateTimePrinter)
+    printer.add('Date', DatePrinter)
+    printer.add('Time', TimePrinter)
+
+def register_pretty_printers(obj):
+    printing.register_pretty_printer(printer, obj)
+
+build_pretty_printers()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/util/__init__.py b/solenv/gdb/libreoffice/util/__init__.py
new file mode 100644
index 0000000..90d8012
--- /dev/null
+++ b/solenv/gdb/libreoffice/util/__init__.py
@@ -0,0 +1,30 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/util/compatibility.py b/solenv/gdb/libreoffice/util/compatibility.py
new file mode 100644
index 0000000..3011f93
--- /dev/null
+++ b/solenv/gdb/libreoffice/util/compatibility.py
@@ -0,0 +1,38 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import gdb
+
+use_gdb_printing = True
+try:
+    import gdb.printing
+except ImportError:
+    use_gdb_printing = False
+
+use_lazy_string = hasattr(gdb.Value, 'lazy_string')
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/util/printing.py b/solenv/gdb/libreoffice/util/printing.py
new file mode 100644
index 0000000..e1f55b3
--- /dev/null
+++ b/solenv/gdb/libreoffice/util/printing.py
@@ -0,0 +1,139 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+from collections import Mapping
+import gdb
+import re
+
+from libreoffice.util.compatibility import use_gdb_printing
+
+class SimplePrinter(object):
+
+    def __init__(self, name, function):
+        self.name = name
+        self.function = function
+        self.enabled = True
+
+    def invoke(self, val):
+        if not self.enabled:
+            return None
+        return self.function(self.name, val)
+
+class NameLookup(Mapping):
+
+    def __init__(self):
+        self.map = {}
+        self.name_regex = re.compile('^([\w:]+)(<.*>)?')
+
+    def add(self, name, printer):
+        self.map[name] = printer
+
+    def __len__(self):
+        return len(self.map)
+
+    def __getitem__(self, type):
+        typename = self._basic_type(type)
+        if typename and typename in self.map:
+            return self.map[typename]
+        return None
+
+    def __iter__(self):
+        return self.map
+
+    def _basic_type(self, type):
+        basic_type = self.basic_type(type)
+        if basic_type:
+            match = self.name_regex.match(basic_type)
+            if match:
+                return match.group(1)
+        return None
+
+    @staticmethod
+    def basic_type(type):
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target()
+        type = type.unqualified().strip_typedefs()
+        return type.tag
+
+class FunctionLookup(Mapping):
+
+    def __init__(self):
+        self.map = {}
+
+    def add(self, test, printer):
+        self.map[test] = printer
+
+    def __len__(self):
+        return len(self.map)
+
+    def __getitem__(self, type):
+        for (test, printer) in self.map.iteritems():
+            if test(type):
+                return printer
+        return None
+
+    def __iter__(self):
+        return self.map
+
+class Printer(object):
+
+    def __init__(self, name):
+        self.name = name
+        self.subprinters = []
+        self.name_lookup = NameLookup()
+        self.func_lookup = FunctionLookup()
+        self.enabled = True
+
+    def add(self, name, function, lookup = None):
+        printer = SimplePrinter(name, function)
+        self.subprinters.append(printer)
+        if not lookup:
+            self.name_lookup.add(name, printer)
+        else:
+            self.func_lookup.add(lookup, printer)
+
+
+    def __call__(self, val):
+        printer = self.name_lookup[val.type]
+        if not printer:
+            printer = self.func_lookup[val.type]
+
+        if printer:
+            return printer.invoke(val)
+        return None
+
+def register_pretty_printer(printer, obj):
+    '''Registers printer with objfile'''
+
+    if use_gdb_printing:
+        gdb.printing.register_pretty_printer(obj, printer)
+    else:
+        if obj is None:
+            obj = gdb
+        obj.pretty_printers.append(printer)
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/util/string.py b/solenv/gdb/libreoffice/util/string.py
new file mode 100644
index 0000000..e2db622
--- /dev/null
+++ b/solenv/gdb/libreoffice/util/string.py
@@ -0,0 +1,93 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import gdb
+
+from libreoffice.util.compatibility import use_lazy_string
+
+class StringPrinterHelper(object):
+    '''Base for all string pretty printers'''
+
+    class MustBeImplemented(Exception):
+        pass
+
+    def __init__(self, typename, val, encoding = None):
+        self.typename = typename
+        self.val = val
+        self.encoding = encoding
+
+    def to_string(self):
+        data = self.data()
+        len = self.length()
+        if self.valid():
+            return self.make_string(data, self.encoding, len)
+        else:
+            return "unintialized %s" % self.typename
+
+    def display_hint(self):
+        if self.valid():
+            return 'string'
+        else:
+            return None
+
+    def valid(self):
+        return True
+
+    def data(self):
+        raise self.MustBeImplemented()
+
+    def length(self):
+        return -1
+
+    @staticmethod
+    def make_string(data, encoding = None, length = -1):
+        '''Creates a new string from memory'''
+
+        if not encoding:
+            encoding = ''
+
+        if use_lazy_string:
+            return data.lazy_string(encoding, length)
+
+        # we need to determine length, if not given (for sal_Unicode*)
+        if length < 0:
+            length = 0
+            while data[length] != 0 and length <= 512: # arbitrary limit
+                length += 1
+
+        # The gdb.Value.string() conversion works on array of bytes, but
+        # the length we have is the length of the string. So we must
+        # multiply it by width of character if the string is Unicode.
+        width = data[0].type.sizeof
+        if width > 1:
+            length = length * width
+
+        char = gdb.lookup_type('char')
+        bytes = data.cast(char.pointer())
+        return bytes.string(encoding, length = length)
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/libreoffice/util/uno.py b/solenv/gdb/libreoffice/util/uno.py
new file mode 100644
index 0000000..23cf06a
--- /dev/null
+++ b/solenv/gdb/libreoffice/util/uno.py
@@ -0,0 +1,539 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import gdb
+import re
+
+class UnsupportedType(Exception):
+    '''Represents exception thrown when an unsupported UNO type(like
+        array or union) is used.'''
+
+    def __init__(self, type):
+        self.type = type
+
+class UnknownType(Exception):
+    '''Represents exception thrown when an unknown UNO type is used.'''
+
+    def __init__(self, type):
+        self.type = type
+
+class TypeClass(object):
+    '''Represents type class of UNO type.'''
+
+    # type class of void
+    VOID = 0
+    # type class of char
+    CHAR = 1
+    # type class of boolean
+    BOOLEAN = 2
+    # type class of byte
+    BYTE = 3
+    # type class of short
+    SHORT = 4
+    # type class of unsigned short
+    UNSIGNED_SHORT = 5
+    # type class of long
+    LONG = 6
+    # type class of unsigned long
+    UNSIGNED_LONG = 7
+    # type class of hyper
+    HYPER = 8
+    # type class of unsigned hyper
+    UNSIGNED_HYPER = 9
+    # type class of float
+    FLOAT = 10
+    # type class of double
+    DOUBLE = 11
+    # type class of string
+    STRING = 12
+    # type class of type
+    TYPE = 13
+    # type class of any
+    ANY = 14
+    # type class of enum
+    ENUM = 15
+    # type class of typedef
+    TYPEDEF = 16
+    # type class of struct
+    STRUCT = 17
+    # type class of union (not implemented)
+    UNION = 18
+    # type class of exception
+    EXCEPTION = 19
+    # type class of sequence
+    SEQUENCE = 20
+    # type class of array (not implemented)
+    ARRAY = 21
+    # type class of interface
+    INTERFACE = 22
+    # type class of service (not implemented)
+    SERVICE = 23
+    # type class of module (not implemented)
+    MODULE = 24
+    # type class of interface method
+    INTERFACE_METHOD = 25
+    # type class of interface attribute
+    INTERFACE_ATTRIBUTE = 26
+    # type class of unknown type
+    UNKNOWN = 27
+    # type class of properties
+    PROPERTY = 28
+    # type class of constants
+    CONSTANT = 29
+    # type class of constants groups
+    CONSTANTS = 30
+    # type class of singletons
+    SINGLETON = 31
+
+class TemplateType(object):
+
+    def __init__(self, template, *args):
+        self.template = template
+        self.args = args
+
+    def __str__(self):
+        argtypes = [str(gdb.lookup_type(arg).strip_typedefs()) for arg in self.args]
+        return self.template + '<' + ', '.join(argtypes) + '>'
+
+class Type(object):
+    '''Describes a UNO type.'''
+
+    def __init__(self, typeclass, tag):
+        '''Constructs a new Type.
+            @param[in] typeclass value of com::sun::star::uno::TypeClass
+            @param[in] tag UNO name of the type
+        '''
+        self.typeclass = typeclass
+        self.tag = tag
+        # C++ name of the type
+        self.typename = None
+
+    def type(self):
+        '''Gets gdb.Type for the type'''
+        if self.typename:
+            return gdb.lookup_type(str(self.typename))
+        return None
+
+    @staticmethod
+    def uno2cpp(typename):
+        return str(typename).replace('.', '::')[1:-1]
+
+    def strip_typedefs(self):
+        copy = self.copy()
+        copy.typename = self._strip_typedefs(self.typename)
+        return copy
+
+    def _strip_typedefs(self, typename):
+        template_args = re.compile('([^<]+)(<.*>)')
+        match = template_args.match(typename)
+        type = self._lookup_type(match.group(1))
+        types = []
+        if match.group(2):
+            list_delim = re.compile(', *')
+            # FIXME: this does not work with nested templates
+            for arg in match.group(2).split(list_delim):
+                types.append(self._lookup_type(arg))
+
+        typename = str(type)
+        if not types.empty():
+            typename += '<' + types.join(', ') + '>'
+
+        return typename
+
+    def _lookup_type(self, typename):
+        if typename != '':
+            type = gdb.lookup_type(typename)
+            if type:
+                type = type.strip_typedefs()
+        return type
+
+def make_uno_type(val):
+    '''Creates a UNO type from gdb.Value of type
+        com::sun::star::uno::Type, typelib_TypeDescription, or
+        typelib_TypeDescriptionReference
+    '''
+
+    cssu_type = 'com::sun::star::uno::Type'
+    type_desc = '_typelib_TypeDescription'
+    type_descs =(
+            type_desc,
+            '_typelib_CompoundTypeDescription',
+            '_typelib_StructTypeDescription',
+            '_typelib_IndirectTypeDescription',
+            '_typelib_EnumTypeDescription',
+            '_typelib_InterfaceMemberTypeDescription',
+            '_typelib_InterfaceMethodTypeDescription',
+            '_typelib_InterfaceAttributeTypeDescription',
+            '_typelib_InterfaceTypeDescription'
+    )
+    type_desc_ref = '_typelib_TypeDescriptionReference'
+
+    type = val.type.strip_typedefs()
+
+    if type.tag == cssu_type:
+        pvalue = val['_pType']
+        assert pvalue
+        val = pvalue.dereference()
+        type = val.type.strip_typedefs()
+
+    while type.tag == type_desc_ref:
+        pvalue = val['pType']
+        assert pvalue
+        val = pvalue.dereference()
+        type = val.type.strip_typedefs()
+
+    if type.tag not in type_descs:
+        return None
+
+    # determination of the UNO type
+    full_val = val
+    if type.tag != type_desc:
+        while 'aBase' in val:
+            val = val['aBase']
+    type_class = int(val['eTypeClass'])
+    name = val['pTypeName'].dereference()
+    uno_type = None
+    if type_class == TypeClass.VOID:
+        uno_type = VoidType()
+    elif type_class == TypeClass.CHAR:
+        uno_type = PrimitiveType(type_class, name, 'sal_Char')
+    elif type_class == TypeClass.BOOLEAN:
+        uno_type = PrimitiveType(type_class, name, 'sal_Bool')
+    elif type_class == TypeClass.BYTE:
+        uno_type = PrimitiveType(type_class, name, 'sal_Int8')
+    elif type_class == TypeClass.SHORT:
+        uno_type = PrimitiveType(type_class, name, 'sal_Int16')
+    elif type_class == TypeClass.UNSIGNED_SHORT:
+        uno_type = PrimitiveType(type_class, name, 'sal_uInt16')
+    elif type_class == TypeClass.LONG:
+        uno_type = PrimitiveType(type_class, name, 'sal_Int32')
+    elif type_class == TypeClass.UNSIGNED_LONG:
+        uno_type = PrimitiveType(type_class, name, 'sal_uInt32')
+    elif type_class == TypeClass.HYPER:
+        uno_type = PrimitiveType(type_class, name, 'sal_Int64')
+    elif type_class == TypeClass.UNSIGNED_HYPER:
+        uno_type = PrimitiveType(type_class, name, 'sal_uInt64')
+    elif type_class == TypeClass.FLOAT:
+        uno_type = PrimitiveType(type_class, name, 'float')
+    elif type_class == TypeClass.DOUBLE:
+        uno_type = PrimitiveType(type_class, name, 'double')
+    elif type_class == TypeClass.STRING:
+        uno_type = PrimitiveType(type_class, name, 'rtl::OUString')
+    elif type_class == TypeClass.TYPE:
+        uno_type = PrimitiveType(type_class, name, 'com::sun::star::uno::Type')
+    elif type_class == TypeClass.ANY:
+        uno_type = PrimitiveType(type_class, name, 'com::sun::star::uno::Any')
+    elif type_class == TypeClass.ENUM:
+        uno_type = EnumType(val, full_val)
+    elif type_class == TypeClass.TYPEDEF:
+        pass
+    elif type_class == TypeClass.STRUCT:
+        uno_type = StructType(val, full_val)
+    elif type_class == TypeClass.UNION:
+        raise UnsupportedType('union')
+    elif type_class == TypeClass.EXCEPTION:
+        uno_type = CompoundType(val, full_val)
+    elif type_class == TypeClass.SEQUENCE:
+        uno_type = IndirectType(val, full_val)
+    elif type_class == TypeClass.ARRAY:
+        raise UnsupportedType('array')
+    elif type_class == TypeClass.INTERFACE:
+        uno_type = InterfaceType(val, full_val)
+    elif type_class == TypeClass.SERVICE:
+        raise UnsupportedType('service')
+    elif type_class == TypeClass.MODULE:
+        raise UnsupportedType('module')
+    elif type_class == TypeClass.INTERFACE_METHOD:
+        uno_type = InterfaceMethodType(val, full_val)
+    elif type_class == TypeClass.INTERFACE_ATTRIBUTE:
+        uno_type = InterfaceAttributeType(val, full_val)
+    elif type_class == TypeClass.UNKNOWN:
+        raise UnknownType(type)
+    elif type_class == TypeClass.PROPERTY:
+        pass
+    elif type_class == TypeClass.CONSTANT:
+        pass
+    elif type_class == TypeClass.CONSTANTS:
+        pass
+    elif type_class == TypeClass.SINGLETON:
+        pass
+    else:
+        raise UnknownType(type)
+
+    assert uno_type
+    return uno_type
+
+def uno_cast(type, val):
+    '''Casts val or pointer to UNO type represented by type'''
+    if val.type.code == gdb.TYPE_CODE_PTR:
+        return val.cast(type.type().pointer())
+    else:
+        return val.cast(type.type())
+
+class VoidType(Type):
+
+    def __init__(self):
+        super(VoidType, self).__init__(TypeClass.VOID, "void")
+        self.typename = "void"
+
+class PrimitiveType(Type):
+
+    def __init__(self, typeclass, typename_uno, typename_cpp):
+        super(PrimitiveType, self).__init__(typeclass, typename_uno)
+        self.typename = str(typename_cpp)
+
+class CompoundType(Type):
+
+    def __init__(self, type, full_type):
+        super(CompoundType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference())
+        self.typename = self.uno2cpp(self.tag)
+        self._type = full_type
+
+    class _iterator(object):
+
+        def __init__(self, count, types, names):
+            self.count = count
+            self.members = members
+            self.names = names
+            self.pos = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            assert self.pos >= 0 and self.pos <= self.count
+            if self.pos == self.count:
+                raise StopIteration
+
+            pmember = self.members[self.pos]
+            assert pmember
+            pname = self.names[self.i]
+            assert pname
+            self.pos = self.pos + 1
+            member = make_uno_type(pmember.dereference())
+            assert member
+            name = str(pname.dereference())
+            return (name, member)
+
+    def attributes(self):
+        return _iterator(self._type['nMembers'], self._type['ppTypeRefs'],
+                self._type['ppMemberNames'])
+
+class StructType(CompoundType):
+
+    def __init__(self, type, full_type):
+        full_type = full_type.cast(gdb.lookup_type('_typelib_StructTypeDescription'))
+        super(StructType, self).__init__(type, full_type['aBase'])
+
+class IndirectType(Type):
+
+    def __init__(self, type, full_type):
+        super(IndirectType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference())
+        full_type = full_type.cast(gdb.lookup_type('_typelib_IndirectTypeDescription'))
+        pelem = full_type['pType']
+        assert pelem
+        self.element = make_uno_type(pelem.dereference())
+        assert self.element
+        self.typename = TemplateType('com::sun::star::uno::Sequence', self.element.typename)
+
+class EnumType(Type):
+
+    def __init__(self, type, full_type):
+        super(EnumType, self).__init__(TypeClass.ENUM, type['pTypeName'].dereference())
+        self.typename = self.uno2cpp(self.tag)
+        self._type = full_type.cast(gdb.lookup_type('_typelib_EnumTypeDescription'))
+
+    class _iterator(object):
+
+        def __init__(self, count, values, names):
+            self.count = count
+            self.values = values
+            self.names = names
+            self.pos = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            assert self.pos >= 0 and self.pos <= self.count
+            if self.pos == self.count:
+                raise StopIteration
+
+            pvalue = self.values[self.pos]
+            assert pvalue
+            pname = self.names[self.pos]
+            assert pname
+            self.pos = self.pos + 1
+            val = int(pvalue.dereference())
+            name = str(pname.dereference())
+            return (name, val)
+
+    def values(self):
+        return _iterator(self._type['nEnumValues'],
+                self._type['ppEnumNames'], self._type['pEnumValues'])
+
+    def default_value(self):
+        return self._type['nDefaultEnumValue']
+
+class InterfaceMemberType(Type):
+
+    def __init__(self, type, full_type):
+        super(InterfaceMemberType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference())
+        (interface, delim, member) = self.tag.partition('::')
+        self.typename = self.uno2cpp(interface) + '::*' + member
+        full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceMemberTypeDescription'))
+        self.position = full_type['nPosition']
+        pname = full_type['pMemberName']
+        assert pname
+        self.name = pname.dereference()
+
+class InterfaceMethodType(InterfaceMemberType):
+
+    def __init__(self, type, full_type):
+        full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceMethodTypeDescription'))
+        super(InterfaceMethodType, self).__init__(type, full_type['aBase'])
+        pret = full_type['pReturnTypeRef']
+        assert pret
+        self.return_type = make_uno_type(pret.dereference())
+        assert self.return_type
+        self.oneway = full_type['bOneWay']
+        self._type = full_type
+
+    class _iterator(object):
+
+        def __init__(self, count, values):
+            self.count = count
+            self.values = values
+            self.pos = 0
+            assert values
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            assert self.pos >= 0 and self.pos <= self.count
+            if self.pos == self.count:
+                raise StopIteration
+
+            val = self.values[self.pos]
+            self.pos = self.pos + 1
+            return val
+
+    class parameter(tuple):
+
+        def __init__(self, type):
+            self.__init_tuple(type)
+            self.input = type['bIn']
+            self.output = type['bOut']
+
+        def _init_tuple(self, type):
+            pname = self['pName']
+            assert pname
+            ptype = self['pTypeRef']
+            assert ptype
+            name = str(pname.dereference())
+            type = make_uno_type(ptype.dereference())
+            assert type
+            super(parameter, self).__init__(name, type)
+
+    def parameters(self):
+        for param in _iterator(self._type['nParams'], self._type['pParams']):
+            yield parameter(param)
+
+    def exceptions(self):
+        def make_exception(self, pex):
+            assert pex
+            ex = make_uno_type(pex.dereference())
+            assert ex
+            return ex
+
+        for ex in _iterator(
+                self._type['nExceptions'], self._type['ppExceptions']):
+            yield make_exception(ex)
+
+class InterfaceAttributeType(InterfaceMemberType):
+
+    def __init__(self, type, full_type):
+        full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceAttributeTypeDescription'))
+        super(InterfaceAttributeType, self).__init__(type, full_type['aBase'])
+        self.readonly = full_type['bReadOnly']
+        ptype = full_type['pAttributeTypeRef']
+        assert ptype
+        self.type = make_uno_type(ptype.dereference())
+        assert self.type
+
+class MembersNotInitialized(Exception):
+    '''Represents exception raised when interface type' members haven't
+        been initialized(i.e. just level 1 initialization has been
+        performed)'''
+    pass
+
+class InterfaceType(Type):
+
+    def __init__(self, type, full_type):
+        super(InterfaceType, self).__init__(TypeClass.INTERFACE, type['pTypeName'].dereference())
+        assert int(type['eTypeClass']) == TypeClass.INTERFACE
+        self.typename = self.uno2cpp(self.tag)
+        full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceTypeDescription'))
+        self.uik = full_type['aUik']
+        self._type = full_type
+
+    class _iterator(object):
+
+        def __init__(self, count, values):
+            assert values
+            self.count = count
+            self.values = values
+            self.pos = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            assert self.pos >= 0 and self.pos <= self.count
+            pvalue = self.values[self.pos]
+            assert pvalue
+            self.pos = self.pos + 1
+            uno = make_uno_type(pvalue.dereference())
+            assert uno
+            return uno
+
+    def members(self):
+        return __members(self._type['nMembers'], self._type['ppMembers'])
+
+    def all_members(self):
+        return __members(self._type['nAllMembers'], self._type['ppAllMembers'])
+
+    def __members(count, values):
+        if values == 0:
+            raise MembersNotInitialized
+        return _iterator(count, values)
+
+    def bases(self):
+        return _iterator(self._type['nBaseTypes'], self._type['ppBaseTypes'])
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
-- 
1.7.6

From 9c1e67838844b4826c5a47f03aa4b363c127a705 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Tue, 9 Aug 2011 10:35:19 +0200
Subject: [PATCH 2/2] install gdb pretty printers

---
 Makefile.in                     |    4 ++-
 solenv/bin/install-gdb-printers |   68 +++++++++++++++++++++++++++++++++++++++
 solenv/gdb/autoload.template    |   42 ++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 1 deletions(-)
 create mode 100755 solenv/bin/install-gdb-printers
 create mode 100644 solenv/gdb/autoload.template

diff --git a/Makefile.in b/Makefile.in
index 72ef758..6ea879e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -30,7 +30,8 @@ install:
 	ooinstall "@INSTALLDIR@" && \
 	echo "" && \
 	echo "Installation finished, you can now execute:" && \
-	echo "@INSTALLDIR@/program/soffice"
+	echo "@INSTALLDIR@/program/soffice" && \
+	install-gdb-printers -a "@INSTALLDIR@"
 
 distro-pack-install: install
 	./bin/distro-install-clean-up
@@ -46,6 +47,7 @@ dev-install:
 dev-install:
 	@. ./*[Ee]nv.[Ss]et.sh && \
         ooinstall -l @abs_builddir@/install && \
+	install-gdb-printers -a "$$SOLARVER/$$INPATH/installation/opt" -L && \
         echo "" && \
         echo "Developer installation finished, you can now execute:" && \
         echo "@abs_builddir@/install/program/soffice"
diff --git a/solenv/bin/install-gdb-printers b/solenv/bin/install-gdb-printers
new file mode 100755
index 0000000..719c280
--- /dev/null
+++ b/solenv/bin/install-gdb-printers
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+GDBDIR="${SOLARENV}/gdb"
+
+die() {
+    echo "$1" >&2
+    exit 1
+}
+
+make_autoload() {
+    local dir="${DESTDIR}${autoloaddir}/$2"
+    local gdbfile="${dir}/$3-gdb.py"
+
+    if ${create}; then
+        mkdir -p "${dir}" || die "cannot create dir '${dir}'"
+    elif ${follow}; then
+        gdbfile="$(readlink -f "${dir}/$3")-gdb.py"
+    fi
+    sed -e "s!%PYTHONDIR%!${pythondir}!" -e "s!%MODULE%!libreoffice.$1!" \
+        "${GDBDIR}/autoload.template" > "${gdbfile}"
+}
+
+# dir where the autoloaders will be placed
+autoloaddir=
+# dir where the pretty printers will be placed
+pythondir="${GDBDIR}"
+# Create autoload dir if it does not exist. This only makes sense when
+# installing into system gdb dir, so $autoloaddir must be absolute path.
+create=false
+# Follow links when looking up the path for the autoload file. This only
+# makes sense for dev-install.
+follow=false
+
+#  b defghijklmno qrstuvwxyzABCDEFGHIJK MNOPQRSTUVWXYZ0123456789
+while getopts :a:cp:L opt; do
+    case ${opt} in
+        a) autoloaddir="${OPTARG}" ;;
+        c) create=true ;;
+        p) pythondir="${OPTARG}" ;;
+        L) follow=true ;;
+        *) die "unknown option ${OPTARG}" ;;
+    esac
+done
+
+${create} && ${follow} && die "-c and -L cannot be used together"
+if [[ -n ${DESTDIR} ]]; then
+    [[ ${autoloaddir:0:1} = / ]] || die 'the arg to -a must be an absolute path'
+    [[ ${pythondir:0:1} = / ]] || die 'the arg to -p must be an absolute path'
+fi
+if ${create}; then
+    [[ ${autoloaddir:0:1} = / ]] || die 'the arg to -a must be an absolute path'
+else
+    [[ ! -d ${DESTDIR}${autoloaddir} ]] && die "directory '${DESTDIR}${autoloaddir}' does not exist"
+fi
+[[ ! -d ${GDBDIR} ]] && die "directory '${GDBDIR}' does not exist"
+
+if [[ ${DESTDIR}${pythondir} != ${GDBDIR} ]]; then
+    mkdir -p "${DESTDIR}${pythondir}" || die "cannot create dir '${DESTDIR}${pythondir}'"
+    cp -r "${GDBDIR}/libreoffice" "${DESTDIR}${pythondir}"
+fi
+
+make_autoload cppu ure/lib libuno_cppu.so.3
+make_autoload sal ure/lib libuno_sal.so.3
+make_autoload svl basis3.4/program libsvllo.so
+make_autoload sw basis3.4/program libswlo.so
+make_autoload tl basis3.4/program libtllo.so
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/solenv/gdb/autoload.template b/solenv/gdb/autoload.template
new file mode 100644
index 0000000..3351606
--- /dev/null
+++ b/solenv/gdb/autoload.template
@@ -0,0 +1,42 @@
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Initial Developer of the Original Code is
+#       David Tardon, Red Hat Inc. <dtardon@redhat.com>
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Major Contributor(s):
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+import os.path
+import sys
+
+import gdb
+
+pythondir = os.path.normpath('%PYTHONDIR%')
+
+if gdb.current_objfile():
+    if pythondir not in sys.path:
+        sys.path.insert(0, pythondir)
+
+from %MODULE% import register_pretty_printers
+register_pretty_printers(gdb.current_objfile())
+
+# vim:set filetype=python shiftwidth=4 softtabstop=4 expandtab:
-- 
1.7.6