office-gobmx/solenv/gdb/libreoffice/tl.py
2011-08-22 17:30:18 +02:00

371 lines
10 KiB
Python

# 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: