[libreoffice] add gdb pretty printers

David Tardon dtardon at fedoraproject.org
Tue Aug 23 06:37:51 UTC 2011


commit e400f2609274b3e9aae58e6ea67f132f5f0b8cbb
Author: David Tardon <dtardon at redhat.com>
Date:   Tue Aug 23 08:37:16 2011 +0200

    add gdb pretty printers

 gdb-pretty-printers.patch | 2028 +++++++++++++++++++++++++++++++++++++++++++++
 libreoffice.spec          |   50 +-
 2 files changed, 2075 insertions(+), 3 deletions(-)
---
diff --git a/gdb-pretty-printers.patch b/gdb-pretty-printers.patch
new file mode 100644
index 0000000..77ec5bf
--- /dev/null
+++ b/gdb-pretty-printers.patch
@@ -0,0 +1,2028 @@
+From b852c77e068a8f3dedf550470be99d913241d7a8 Mon Sep 17 00:00:00 2001
+From: David Tardon <dtardon at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 basis-link/ure-link/lib libuno_cppu.so.3
++make_autoload sal basis-link/ure-link/lib libuno_sal.so.3
++make_autoload svl basis-link/program libsvllo.so
++make_autoload sw basis-link/program libswlo.so
++make_autoload tl basis-link/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 at 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
+
diff --git a/libreoffice.spec b/libreoffice.spec
index 6d708b7..2607d28 100644
--- a/libreoffice.spec
+++ b/libreoffice.spec
@@ -119,6 +119,7 @@ Patch24: 0001-Resolves-rhbz-715549-use-fontconfig-s-detected-forma.patch
 Patch25: 0001-this-is-definitely-not-present-in-qt-4.8.0-beta1.patch
 Patch26: 0001-Resolves-rhbz-693265-fix-crash-from-unhandled-except.patch
 Patch27: 0001-Related-rhbz-730225-avoid-segv-in-ld-this-was-set-to.patch
+Patch28: gdb-pretty-printers.patch
 
 %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
 %define instdir %{_libdir}
@@ -498,6 +499,41 @@ Requires: %{name}-core = %{epoch}:%{version}-%{release}
 %description kde
 A plug-in for LibreOffice that enables integration into the KDE desktop environment.
 
+%if 0%{?_enable_debug_packages}
+
+%define debug_package %{nil}
+%global __debug_package 1
+
+%package debuginfo
+Summary: Debug information for package %{name}
+Group: Development/Debug
+AutoReqProv: 0
+Requires: libreoffice-core = %{epoch}:%{version}-%{release}
+Requires: libreoffice-gdb-debug-support = %{epoch}:%{version}-%{release}
+
+%description debuginfo
+This package provides debug information for package %{name}.
+Debug information is useful when developing applications that use this
+package or when debugging this package.
+
+%files debuginfo -f debugfiles.list
+%defattr(-,root,root)
+
+%package gdb-debug-support
+Summary: Additional support for debugging with gdb
+Group: Development/Debug
+Requires: gdb
+AutoReqProv: 0
+
+%description gdb-debug-support
+This package provides gdb pretty printers for package %{name}.
+
+%files gdb-debug-support
+%defattr(-,root,root)
+%{_datadir}/gdb/auto-load%{baseinstdir}
+%{_datadir}/libreoffice/gdb
+
+%endif
 
 # Defines a language pack subpackage.
 #
@@ -748,10 +784,12 @@ mv -f redhat.soc extras/source/palettes/standard.soc
 %patch25 -p1 -b .this-is-definitely-not-present-in-qt-4.8.0-beta1.patch
 %patch26 -p1 -b .rhbz693265-fix-crash-from-unhandled-except.patch
 %patch27 -p1 -b .rhbz730225-avoid-segv-in-ld-this-was-set-to.patch
+%patch28 -p1 -b .gdb-pretty-printers.patch
 
 # these are horribly incomplete--empty translations and copied english
 # strings with spattering of translated strings
 rm -rf translations/source/{gu,he,hr}/helpcontent2
+chmod +x solenv/bin/install-gdb-printers
 
 %build
 echo build start time is `date`, diskspace: `df -h . | tail -n 1`
@@ -1222,9 +1260,9 @@ pushd sysui/output/usr/share/
 rm -rf icons/gnome applications application-registry
 
 #relocate the rest of them
-for icon in `find icons -type f`; do
-    mv $icon `echo $icon | sed -e s at office$ICONVERSION at office@`
-done
+# for icon in `find icons -type f`; do
+    # mv $icon `echo $icon | sed -e s at office$ICONVERSION at office@`
+# done
 cp -r icons $RPM_BUILD_ROOT/%{_datadir}
 mkdir -p $RPM_BUILD_ROOT/%{_datadir}/mime-info
 cp -p mime-info/libreoffice$PRODUCTVERSION.keys $RPM_BUILD_ROOT/%{_datadir}/mime-info/libreoffice.keys
@@ -1244,6 +1282,9 @@ cp -r psprint_config/configuration/ppds/SGENPRT.PS $RPM_BUILD_ROOT/%{basisinstdi
 # rhbz#465664 to get lucene working for functional help
 sed -i -e "s#URE_MORE_JAVA_CLASSPATH_URLS.*#& file:///usr/share/java/lucene.jar file:///usr/share/java/lucene-contrib/lucene-analyzers.jar file:///usr/share/java/postgresql-jdbc.jar#" $RPM_BUILD_ROOT/%{basisinstdir}/program/fundamentalbasisrc
 
+export DESTDIR=$RPM_BUILD_ROOT
+install-gdb-printers -a %{_datadir}/gdb/auto-load%{baseinstdir} -c -p %{_datadir}/libreoffice/gdb
+
 %check
 source ./Linux*Env.Set.sh
 cd test
@@ -2032,6 +2073,9 @@ update-desktop-database %{_datadir}/applications &> /dev/null || :
 %{basisinstdir}/program/kde-open-url
 
 %changelog
+* Mon Aug 22 2011 David Tardon <dtardon at redhat.com> - 3.4.3.1-2
+- add gdb pretty printers
+
 * Tue Aug 16 2011 David Tardon <dtardon at redhat.com> - 3.4.3.1-1
 - 3.4.3 rc1
 - drop integrated 0001-Resolves-rhbz-725144-wrong-csh-syntax.patch


More information about the scm-commits mailing list