1# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- 2# 3# This file is part of the LibreOffice project. 4# 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8# 9 10import gdb 11import re 12import six 13 14class UnsupportedType(Exception): 15 '''Represents exception thrown when an unsupported UNO type(like 16 array or union) is used.''' 17 18 def __init__(self, type): 19 self.type = type 20 21class UnknownType(Exception): 22 '''Represents exception thrown when an unknown UNO type is used.''' 23 24 def __init__(self, type): 25 self.type = type 26 27class TypeClass(object): 28 '''Represents type class of UNO type.''' 29 30 # type class of void 31 VOID = 0 32 # type class of char 33 CHAR = 1 34 # type class of boolean 35 BOOLEAN = 2 36 # type class of byte 37 BYTE = 3 38 # type class of short 39 SHORT = 4 40 # type class of unsigned short 41 UNSIGNED_SHORT = 5 42 # type class of long 43 LONG = 6 44 # type class of unsigned long 45 UNSIGNED_LONG = 7 46 # type class of hyper 47 HYPER = 8 48 # type class of unsigned hyper 49 UNSIGNED_HYPER = 9 50 # type class of float 51 FLOAT = 10 52 # type class of double 53 DOUBLE = 11 54 # type class of string 55 STRING = 12 56 # type class of type 57 TYPE = 13 58 # type class of any 59 ANY = 14 60 # type class of enum 61 ENUM = 15 62 # type class of typedef 63 TYPEDEF = 16 64 # type class of struct 65 STRUCT = 17 66 67 # type class of exception 68 EXCEPTION = 19 69 # type class of sequence 70 SEQUENCE = 20 71 72 # type class of interface 73 INTERFACE = 22 74 # type class of service (not implemented) 75 SERVICE = 23 76 # type class of module (not implemented) 77 MODULE = 24 78 # type class of interface method 79 INTERFACE_METHOD = 25 80 # type class of interface attribute 81 INTERFACE_ATTRIBUTE = 26 82 # type class of unknown type 83 UNKNOWN = 27 84 # type class of properties 85 PROPERTY = 28 86 # type class of constants 87 CONSTANT = 29 88 # type class of constants groups 89 CONSTANTS = 30 90 # type class of singletons 91 SINGLETON = 31 92 93class TemplateType(object): 94 95 def __init__(self, template, *args): 96 self.template = template 97 self.args = args 98 99 def __str__(self): 100 argtypes = [str(gdb.lookup_type(str(arg)).strip_typedefs()) for arg in self.args] 101 return self.template + '<' + ', '.join(argtypes) + '>' 102 103class Type(object): 104 '''Describes a UNO type.''' 105 106 def __init__(self, typeclass, tag): 107 '''Constructs a new Type. 108 @param[in] typeclass value of com::sun::star::uno::TypeClass 109 @param[in] tag UNO name of the type 110 ''' 111 self.typeclass = typeclass 112 self.tag = tag 113 # C++ name of the type 114 self.typename = None 115 116 def type(self): 117 '''Gets gdb.Type for the type''' 118 if self.typename: 119 return gdb.lookup_type(str(self.typename)) 120 return None 121 122 @staticmethod 123 def uno2cpp(typename): 124 return str(typename).replace('.', '::')[1:-1] 125 126 def strip_typedefs(self): 127 copy = self.copy() 128 copy.typename = self._strip_typedefs(self.typename) 129 return copy 130 131 def _strip_typedefs(self, typename): 132 template_args = re.compile('([^<]+)(<.*>)') 133 match = template_args.match(typename) 134 type = self._lookup_type(match.group(1)) 135 types = [] 136 if match.group(2): 137 list_delim = re.compile(', *') 138 # FIXME: this does not work with nested templates 139 for arg in match.group(2).split(list_delim): 140 types.append(self._lookup_type(arg)) 141 142 typename = str(type) 143 if not types.empty(): 144 typename += '<' + types.join(', ') + '>' 145 146 return typename 147 148 def _lookup_type(self, typename): 149 if typename != '': 150 type = gdb.lookup_type(typename) 151 if type: 152 type = type.strip_typedefs() 153 return type 154 155def make_uno_type(val): 156 '''Creates a UNO type from gdb.Value of type 157 com::sun::star::uno::Type, typelib_TypeDescription, or 158 typelib_TypeDescriptionReference 159 ''' 160 161 cssu_type = 'com::sun::star::uno::Type' 162 type_desc = '_typelib_TypeDescription' 163 type_descs =( 164 type_desc, 165 '_typelib_CompoundTypeDescription', 166 '_typelib_StructTypeDescription', 167 '_typelib_IndirectTypeDescription', 168 '_typelib_EnumTypeDescription', 169 '_typelib_InterfaceMemberTypeDescription', 170 '_typelib_InterfaceMethodTypeDescription', 171 '_typelib_InterfaceAttributeTypeDescription', 172 '_typelib_InterfaceTypeDescription' 173 ) 174 type_desc_ref = '_typelib_TypeDescriptionReference' 175 176 type = val.type.strip_typedefs() 177 178 if type.tag == cssu_type: 179 pvalue = val['_pType'] 180 assert pvalue 181 val = pvalue.dereference() 182 type = val.type.strip_typedefs() 183 184 while type.tag == type_desc_ref: 185 pvalue = val['pType'] 186 assert pvalue 187 val = pvalue.dereference() 188 type = val.type.strip_typedefs() 189 190 if type.tag not in type_descs: 191 return None 192 193 # determination of the UNO type 194 full_val = val 195 if type.tag != type_desc: 196 while 'aBase' in val: 197 val = val['aBase'] 198 type_class = int(val['eTypeClass']) 199 name = val['pTypeName'].dereference() 200 uno_type = None 201 if type_class == TypeClass.VOID: 202 uno_type = VoidType() 203 elif type_class == TypeClass.CHAR: 204 uno_type = PrimitiveType(type_class, name, 'sal_Char') 205 elif type_class == TypeClass.BOOLEAN: 206 uno_type = PrimitiveType(type_class, name, 'sal_Bool') 207 elif type_class == TypeClass.BYTE: 208 uno_type = PrimitiveType(type_class, name, 'sal_Int8') 209 elif type_class == TypeClass.SHORT: 210 uno_type = PrimitiveType(type_class, name, 'sal_Int16') 211 elif type_class == TypeClass.UNSIGNED_SHORT: 212 uno_type = PrimitiveType(type_class, name, 'sal_uInt16') 213 elif type_class == TypeClass.LONG: 214 uno_type = PrimitiveType(type_class, name, 'sal_Int32') 215 elif type_class == TypeClass.UNSIGNED_LONG: 216 uno_type = PrimitiveType(type_class, name, 'sal_uInt32') 217 elif type_class == TypeClass.HYPER: 218 uno_type = PrimitiveType(type_class, name, 'sal_Int64') 219 elif type_class == TypeClass.UNSIGNED_HYPER: 220 uno_type = PrimitiveType(type_class, name, 'sal_uInt64') 221 elif type_class == TypeClass.FLOAT: 222 uno_type = PrimitiveType(type_class, name, 'float') 223 elif type_class == TypeClass.DOUBLE: 224 uno_type = PrimitiveType(type_class, name, 'double') 225 elif type_class == TypeClass.STRING: 226 uno_type = PrimitiveType(type_class, name, 'rtl::OUString') 227 elif type_class == TypeClass.TYPE: 228 uno_type = PrimitiveType(type_class, name, 'com::sun::star::uno::Type') 229 elif type_class == TypeClass.ANY: 230 uno_type = PrimitiveType(type_class, name, 'com::sun::star::uno::Any') 231 elif type_class == TypeClass.ENUM: 232 uno_type = EnumType(val, full_val) 233 elif type_class == TypeClass.TYPEDEF: 234 pass 235 elif type_class == TypeClass.STRUCT: 236 uno_type = StructType(val, full_val) 237 elif type_class == TypeClass.EXCEPTION: 238 uno_type = CompoundType(val, full_val) 239 elif type_class == TypeClass.SEQUENCE: 240 uno_type = IndirectType(val, full_val) 241 elif type_class == TypeClass.INTERFACE: 242 uno_type = InterfaceType(val, full_val) 243 elif type_class == TypeClass.SERVICE: 244 raise UnsupportedType('service') 245 elif type_class == TypeClass.MODULE: 246 raise UnsupportedType('module') 247 elif type_class == TypeClass.INTERFACE_METHOD: 248 uno_type = InterfaceMethodType(val, full_val) 249 elif type_class == TypeClass.INTERFACE_ATTRIBUTE: 250 uno_type = InterfaceAttributeType(val, full_val) 251 elif type_class == TypeClass.UNKNOWN: 252 raise UnknownType(type) 253 elif type_class == TypeClass.PROPERTY: 254 pass 255 elif type_class == TypeClass.CONSTANT: 256 pass 257 elif type_class == TypeClass.CONSTANTS: 258 pass 259 elif type_class == TypeClass.SINGLETON: 260 pass 261 else: 262 raise UnknownType(type) 263 264 assert uno_type 265 return uno_type 266 267def uno_cast(type, val): 268 '''Casts val or pointer to UNO type represented by type''' 269 if val.type.code == gdb.TYPE_CODE_PTR: 270 return val.cast(type.type().pointer()) 271 else: 272 return val.cast(type.type()) 273 274class VoidType(Type): 275 276 def __init__(self): 277 super(VoidType, self).__init__(TypeClass.VOID, "void") 278 self.typename = "void" 279 280class PrimitiveType(Type): 281 282 def __init__(self, typeclass, typename_uno, typename_cpp): 283 super(PrimitiveType, self).__init__(typeclass, typename_uno) 284 self.typename = str(typename_cpp) 285 286class CompoundType(Type): 287 288 def __init__(self, type, full_type): 289 super(CompoundType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference()) 290 self.typename = self.uno2cpp(self.tag) 291 self._type = full_type 292 293 class _iterator(six.Iterator): 294 295 def __init__(self, count, types, names): 296 self.count = count 297 self.members = members 298 self.names = names 299 self.pos = 0 300 301 def __iter__(self): 302 return self 303 304 def __next__(self): 305 assert self.pos >= 0 and self.pos <= self.count 306 if self.pos == self.count: 307 raise StopIteration 308 309 pmember = self.members[self.pos] 310 assert pmember 311 pname = self.names[self.i] 312 assert pname 313 self.pos = self.pos + 1 314 member = make_uno_type(pmember.dereference()) 315 assert member 316 name = str(pname.dereference()) 317 return (name, member) 318 319 def attributes(self): 320 return _iterator(self._type['nMembers'], self._type['ppTypeRefs'], 321 self._type['ppMemberNames']) 322 323class StructType(CompoundType): 324 325 def __init__(self, type, full_type): 326 full_type = full_type.cast(gdb.lookup_type('_typelib_StructTypeDescription')) 327 super(StructType, self).__init__(type, full_type['aBase']) 328 329class IndirectType(Type): 330 331 def __init__(self, type, full_type): 332 super(IndirectType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference()) 333 full_type = full_type.cast(gdb.lookup_type('_typelib_IndirectTypeDescription')) 334 pelem = full_type['pType'] 335 assert pelem 336 self.element = make_uno_type(pelem.dereference()) 337 assert self.element 338 self.typename = TemplateType('com::sun::star::uno::Sequence', self.element.typename) 339 340class EnumType(Type): 341 342 def __init__(self, type, full_type): 343 super(EnumType, self).__init__(TypeClass.ENUM, type['pTypeName'].dereference()) 344 self.typename = self.uno2cpp(self.tag) 345 self._type = full_type.cast(gdb.lookup_type('_typelib_EnumTypeDescription')) 346 347 class _iterator(six.Iterator): 348 349 def __init__(self, count, values, names): 350 self.count = count 351 self.values = values 352 self.names = names 353 self.pos = 0 354 355 def __iter__(self): 356 return self 357 358 def __next__(self): 359 assert self.pos >= 0 and self.pos <= self.count 360 if self.pos == self.count: 361 raise StopIteration 362 363 pvalue = self.values[self.pos] 364 assert pvalue 365 pname = self.names[self.pos] 366 assert pname 367 self.pos = self.pos + 1 368 val = int(pvalue.dereference()) 369 name = str(pname.dereference()) 370 return (name, val) 371 372 def values(self): 373 return _iterator(self._type['nEnumValues'], 374 self._type['ppEnumNames'], self._type['pEnumValues']) 375 376 def default_value(self): 377 return self._type['nDefaultEnumValue'] 378 379class InterfaceMemberType(Type): 380 381 def __init__(self, type, full_type): 382 super(InterfaceMemberType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference()) 383 (interface, delim, member) = self.tag.partition('::') 384 self.typename = self.uno2cpp(interface) + '::*' + member 385 full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceMemberTypeDescription')) 386 self.position = full_type['nPosition'] 387 pname = full_type['pMemberName'] 388 assert pname 389 self.name = pname.dereference() 390 391class InterfaceMethodType(InterfaceMemberType): 392 393 def __init__(self, type, full_type): 394 full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceMethodTypeDescription')) 395 super(InterfaceMethodType, self).__init__(type, full_type['aBase']) 396 pret = full_type['pReturnTypeRef'] 397 assert pret 398 self.return_type = make_uno_type(pret.dereference()) 399 assert self.return_type 400 self.oneway = full_type['bOneWay'] 401 self._type = full_type 402 403 class _iterator(six.Iterator): 404 405 def __init__(self, count, values): 406 self.count = count 407 self.values = values 408 self.pos = 0 409 assert values 410 411 def __iter__(self): 412 return self 413 414 def __next__(self): 415 assert self.pos >= 0 and self.pos <= self.count 416 if self.pos == self.count: 417 raise StopIteration 418 419 val = self.values[self.pos] 420 self.pos = self.pos + 1 421 return val 422 423 class parameter(tuple): 424 425 def __init__(self, type): 426 self.__init_tuple(type) 427 self.input = type['bIn'] 428 self.output = type['bOut'] 429 430 def _init_tuple(self, type): 431 pname = self['pName'] 432 assert pname 433 ptype = self['pTypeRef'] 434 assert ptype 435 name = str(pname.dereference()) 436 type = make_uno_type(ptype.dereference()) 437 assert type 438 super(parameter, self).__init__(name, type) 439 440 def parameters(self): 441 for param in _iterator(self._type['nParams'], self._type['pParams']): 442 yield parameter(param) 443 444 def exceptions(self): 445 def make_exception(self, pex): 446 assert pex 447 ex = make_uno_type(pex.dereference()) 448 assert ex 449 return ex 450 451 for ex in _iterator( 452 self._type['nExceptions'], self._type['ppExceptions']): 453 yield make_exception(ex) 454 455class InterfaceAttributeType(InterfaceMemberType): 456 457 def __init__(self, type, full_type): 458 full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceAttributeTypeDescription')) 459 super(InterfaceAttributeType, self).__init__(type, full_type['aBase']) 460 self.readonly = full_type['bReadOnly'] 461 ptype = full_type['pAttributeTypeRef'] 462 assert ptype 463 self.type = make_uno_type(ptype.dereference()) 464 assert self.type 465 466class MembersNotInitialized(Exception): 467 '''Represents exception raised when interface type' members haven't 468 been initialized(i.e. just level 1 initialization has been 469 performed)''' 470 pass 471 472class InterfaceType(Type): 473 474 def __init__(self, type, full_type): 475 super(InterfaceType, self).__init__(TypeClass.INTERFACE, type['pTypeName'].dereference()) 476 assert int(type['eTypeClass']) == TypeClass.INTERFACE 477 self.typename = self.uno2cpp(self.tag) 478 full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceTypeDescription')) 479 self.uik = full_type['aUik'] 480 self._type = full_type 481 482 class _iterator(six.Iterator): 483 484 def __init__(self, count, values): 485 assert values 486 self.count = count 487 self.values = values 488 self.pos = 0 489 490 def __iter__(self): 491 return self 492 493 def __next__(self): 494 assert self.pos >= 0 and self.pos <= self.count 495 pvalue = self.values[self.pos] 496 assert pvalue 497 self.pos = self.pos + 1 498 uno = make_uno_type(pvalue.dereference()) 499 assert uno 500 return uno 501 502 def members(self): 503 return __members(self._type['nMembers'], self._type['ppMembers']) 504 505 def all_members(self): 506 return __members(self._type['nAllMembers'], self._type['ppAllMembers']) 507 508 def __members(count, values): 509 if values == 0: 510 raise MembersNotInitialized 511 return _iterator(count, values) 512 513 def bases(self): 514 return _iterator(self._type['nBaseTypes'], self._type['ppBaseTypes']) 515 516# vim:set shiftwidth=4 softtabstop=4 expandtab: 517