1# -*- python -*- 2# Package : omniidl 3# types.py Created on: 2000/4/10 4# Author : David Scott (djs) 5# 6# Copyright (C) 2003-2009 Apasphere Ltd 7# Copyright (C) 1999 AT&T Laboratories Cambridge 8# 9# This file is part of omniidl. 10# 11# omniidl is free software; you can redistribute it and/or modify it 12# under the terms of the GNU General Public License as published by 13# the Free Software Foundation; either version 2 of the License, or 14# (at your option) any later version. 15# 16# This program is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19# General Public License for more details. 20# 21# You should have received a copy of the GNU General Public License 22# along with this program. If not, see http://www.gnu.org/licenses/ 23# 24# Description: 25# 26# Type utility functions designed for the C++ backend 27 28try: 29 # Python 3 does not have a built in reduce() 30 from functools import reduce 31except ImportError: 32 pass 33 34from omniidl import idltype, idlast, idlutil 35from omniidl_be.cxx import util, config, id 36 37# direction constants 38IN = 0 39OUT = 1 40INOUT = 2 41RET = 3 42 43# we don't support these 44unsupported_typecodes =[idltype.tk_Principal, 45 idltype.tk_native] 46 47class Type: 48 """Wrapper around an IDL type providing useful extra functionality""" 49 def __init__(self, type): 50 assert isinstance(type, idltype.Type) 51 self.__type = type 52 53 def type(self): 54 """type(types.Type): idltype.Type 55 returns the wrapped type""" 56 return self.__type 57 58 def kind(self): 59 """type(types.Type): idltype.kind 60 returns the kind of the wrapped type""" 61 return self.__type.kind() 62 63 def deref(self, keep_dims = 0): 64 """deref(types.Type, keep_dims boolean option) -> types.Type 65 Return the type with outer aliases removed. 66 (if keep_dims is true then it will not remove aliases with 67 array dimensions)""" 68 type = self 69 while (type.typedef()): 70 decl = type.__type.decl() 71 if keep_dims and decl.sizes() != []: 72 return type 73 type = Type(decl.alias().aliasType()) 74 75 return type 76 77 def variable(self): 78 """variable(types.Type): boolean 79 Returns whether the type has a variable length representation 80 under the C++ mapping""" 81 type = self.__type 82 83 if type.kind() in already_Variable: 84 return already_Variable[type.kind()] 85 86 if isinstance(type, idltype.Declared): 87 decl = type.decl() 88 return variableDecl(decl) 89 90 util.fatalError("Error while computing the variable-ness of a type") 91 92 def dims(self): 93 """dims(types.Type): int list 94 Returns the full dimensions of the type""" 95 96 type = self.__type 97 if isinstance(type, idltype.Declared): 98 decl = type.decl() 99 if type.kind() == idltype.tk_alias: 100 sizes = [] 101 if decl.sizes() != None: 102 sizes = decl.sizes() 103 if decl.alias() != None: 104 sizes = sizes + Type(decl.alias().aliasType()).dims() 105 return sizes 106 if isinstance(type.decl(), idlast.Typedef): 107 return Type(type.decl().aliasType()).dims() 108 return [] 109 return [] 110 111 def array(self): 112 """array(types.Type): boolean 113 Returns true if this type has array dimensions""" 114 return self.dims() != [] 115 116 def __apply_mapping(self, xxx_todo_changeme, thing): 117 # __apply_mapping(types.Type, (const bool, ref bool, ptr bool), string) 118 # : string 119 # Make an instance of "thing" which is optionally const, a reference 120 # and a pointer types 121 (const, ref, ptr) = xxx_todo_changeme 122 text = thing 123 if const: text = "const " + text 124 if ptr: text = text + "*" 125 if ref: text = text + "&" 126 return text 127 128 def _argmapping(self, direction): 129 # _argmapping(types.Type, int direction): const * reference * pointer 130 # Returns info on operation argument mapping for a type for 131 # a particular direction. 132 133 # CORBA2.3 P1-204 Table 1-3 Basic argument and result mapping 134 array = self.array() 135 variable = self.variable() 136 137 if array and not variable: 138 # array of fixed size elements 139 return ( (1, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 1) )[direction] 140 141 if array and variable: 142 # array of variable size elements 143 return ( (1, 0, 0), (0, 1, 1), (0, 0, 0), (0, 0, 1) )[direction] 144 145 type = self.deref().__type 146 kind = type.kind() 147 148 if kind in [ idltype.tk_short, idltype.tk_long, idltype.tk_longlong, 149 idltype.tk_ushort, idltype.tk_ulong, idltype.tk_ulonglong, 150 idltype.tk_float, idltype.tk_double, idltype.tk_enum, 151 idltype.tk_longdouble, idltype.tk_boolean, 152 idltype.tk_char, idltype.tk_wchar, idltype.tk_octet ]: 153 # from short to enum the entries are the same 154 return ( (0, 0, 0), (0, 1, 0), (0, 1, 0), (0, 0, 0) )[direction] 155 156 if kind in [ idltype.tk_objref, 157 idltype.tk_TypeCode, 158 idltype.tk_abstract_interface, 159 idltype.tk_local_interface ]: 160 161 # objref_ptr objref_ptr& objref_ptr& objref_ptr 162 return ( (0, 0, 0), (0, 1, 0), (0, 1, 0), (0, 0, 0) )[direction] 163 164 if kind in [ idltype.tk_struct, idltype.tk_union ]: 165 if variable: 166 # variable struct or union 167 return ((1, 1, 0), (0, 1, 1), (0, 1, 0), (0, 0, 1))[direction] 168 else: 169 # fixed struct or union 170 return ((1, 1, 0), (0, 1, 0), (0, 1, 0), (0, 0, 0))[direction] 171 172 if kind in [ idltype.tk_string, idltype.tk_wstring ]: 173 return ( (1, 0, 0), (0, 1, 0), (0, 1, 0), (0, 0, 0) )[direction] 174 175 if kind in [ idltype.tk_sequence, idltype.tk_any ]: 176 return ( (1, 1, 0), (0, 1, 1), (0, 1, 0), (0, 0, 1) )[direction] 177 178 if kind == idltype.tk_fixed: 179 return ( (1, 1, 0), (0, 1, 0), (0, 1, 0), (0, 0, 0) )[direction] 180 181 if kind in [ idltype.tk_value, 182 idltype.tk_value_box ]: 183 184 return ( (0, 0, 1), (0, 1, 1), (0, 1, 1), (0, 0, 1) )[direction] 185 186 if kind == idltype.tk_void: 187 return (0, 0, 0) 188 189 if kind in unsupported_typecodes: 190 util.unsupportedIDL() 191 192 util.fatalError("Unknown type encountered (kind = " + str(kind) + ")") 193 return 194 195 def op_is_pointer(self, direction): 196 if not self.array() and \ 197 (self.deref().string() or self.deref().wstring()): 198 return 0 199 return self._argmapping(direction)[2] 200 201 def __var_argmapping(self, direction): 202 # __var_argmapping(types.Type, direction): const * reference * pointer 203 # Returns info on argument mapping for a type in a _var 204 # context 205 206 # CORBA2.3 P1-204 Table 1-4 T_var argument and result mapping 207 kind = self.__type.kind() 208 209 if (kind in [ idltype.tk_objref, 210 idltype.tk_struct, 211 idltype.tk_union, 212 idltype.tk_string, 213 idltype.tk_wstring, 214 idltype.tk_sequence, 215 idltype.tk_any, 216 idltype.tk_value, 217 idltype.tk_value_box, 218 idltype.tk_abstract_interface, 219 idltype.tk_local_interface ] 220 or 221 self.array()): 222 223 return ( (1, 1, 0), (0, 1, 0), (0, 1, 0), (0, 0, 0) )[direction] 224 225 util.fatalError("T_var argmapping requested for type with no such " 226 "concept") 227 return 228 229 def base(self, environment = None, gscope = 0): 230 """base(types.Type, id.Environment option): C++ type string 231 Returns a basic C++ mapped version of the type""" 232 kind = self.kind() 233 d_type = self.deref(1) 234 d_kind = d_type.kind() 235 236 # CORBA2.3 P1-15 1.5 Mapping for Basic Data Types 237 if kind in basic_map: 238 return basic_map[kind] 239 if self.string() or d_type.string(): 240 return "char*" 241 if self.wstring() or d_type.wstring(): 242 return "::CORBA::WChar*" 243 if self.typecode(): 244 return "::CORBA::TypeCode_ptr" 245 if self.any(): 246 return "::CORBA::Any" 247 if self.void(): 248 return "void" 249 if self.fixed(): 250 return "::CORBA::Fixed" 251 if self.sequence(): 252 return self.sequenceTemplate(environment, gscope=gscope) 253 254 name = id.Name(self.type().scopedName()).unambiguous(environment) 255 if gscope: 256 assert environment is None 257 name = "::" + name 258 259 if d_type.interface() or d_type.typecode(): 260 return name + "_ptr" 261 else: 262 return name 263 264 def __base_type_OUT(self, environment = None): 265 # ___base_type_OUT(types.Type, id.Environment option): special C++ 266 # OUT type 267 type = self.__type 268 d_type = self.deref() 269 d_kind = type.kind() 270 if d_kind in basic_map_out: 271 return basic_map_out[d_kind] 272 if d_type.string(): 273 return "::CORBA::String_out" 274 if d_type.wstring(): 275 return "::CORBA::WString_out" 276 if d_type.typecode(): 277 return "::CORBA::TypeCode_OUT_arg" 278 if d_type.any(): 279 return "::CORBA::Any_OUT_arg" 280 if d_type.sequence(): 281 return Type(d_type.type().seqType()).__base_type_OUT(environment) 282 283 name = id.Name(type.scopedName()) 284 uname = name.unambiguous(environment) 285 286 return uname + "_out" 287 288 def __base_type_INOUT(self, environment = None): 289 # __base_type_INOUT(types.Type): special C++ INOUT type string 290 291 d_type = self.deref() 292 kind = d_type.kind() 293 if d_type.string(): 294 return "::CORBA::String_INOUT_arg" 295 if d_type.wstring(): 296 return "::CORBA::WString_INOUT_arg" 297 if d_type.typecode(): 298 return "::CORBA::TypeCode_INOUT_arg" 299 if d_type.any(): 300 return "::CORBA::Any_INOUT_arg" 301 302 name = id.Name(self.type().scopedName()) 303 uname = name.unambiguous(environment) 304 305 if d_type.interface(): 306 name = id.Name(d_type.type().scopedName()) 307 308 if d_type.objref(): 309 objref_name = name.prefix("_objref_") 310 else: 311 objref_name = name 312 313 if d_type.type().scopedName() == ["CORBA", "Object"]: 314 return "::CORBA::Object_INOUT_arg" 315 316 return "_CORBA_ObjRef_INOUT_arg< " + objref_name.fullyQualify() + \ 317 ", " + name.unambiguous(environment) + "_Helper >" 318 319 if d_type.value() or d_type.valuebox(): 320 name = id.Name(d_type.type().scopedName()) 321 return "_CORBA_Value_INOUT_arg< " + name.fullyQualify() + \ 322 ", " + name.unambiguous(environment) + "_Helper >" 323 324 return uname + "_INOUT_arg" 325 326 def op(self, direction, environment = None, use_out = 1): 327 """op(types.Type, int direction, id.Environment option, use_out bool) 328 : C++ type argument mapping""" 329 type = Type(self.__type) 330 d_type = type.deref() 331 332 base = self.base(environment) 333 334 old_sig = config.state['Old Signatures'] 335 336 # this is very superfluous: 337 if not self.array(): 338 if d_type.any() and self.typedef() and not old_sig: 339 if direction == OUT: 340 return d_type.__base_type_OUT(environment) 341 342 343 if d_type.typecode() and not old_sig: 344 if direction == OUT: 345 return d_type.__base_type_OUT(environment) 346 elif direction == INOUT and use_out: 347 return d_type.__base_type_INOUT(environment) 348 else: 349 base = d_type.base(environment) 350 351 352 # Use the ObjRef template for non-arrays of objrefs rather than use 353 # the (equivalent?) _out type? 354 if not d_type.objref() or type.array(): 355 356 # if its an out type and a typedef (to a variable type), 357 # use the predefined _out type 358 if type.typedef() and type.variable() and direction == OUT: 359 360 if (not d_type.string() or not d_type.wstring() or \ 361 (d_type.string() and type.array()) or \ 362 (d_type.wstring() and type.array())): 363 364 base = id.Name(type.__type.scopedName()).unambiguous(environment) 365 base = base + "_out" 366 return base 367 # superfluous deref for a typedef to an objref 368 if d_type.objref() and not type.array(): 369 base = d_type.base(environment) 370 371 # Deal with special cases ---------------------------------- 372 if not self.array(): 373 374 if direction == OUT and not use_out: 375 if d_type.string() and not old_sig: 376 return self.__base_type_OUT(environment) 377 if d_type.wstring() and not old_sig: 378 return self.__base_type_OUT(environment) 379 if d_type.interface() and not old_sig: 380 return self.__base_type_OUT(environment) 381 if d_type.typecode() and not old_sig: 382 return self.__base_type_OUT(environment) 383 if d_type.any() and not old_sig: 384 return self.__base_type_OUT(environment) 385 386 if direction == OUT: 387 if d_type.string(): 388 return self.__base_type_OUT(environment) 389 if d_type.wstring(): 390 return self.__base_type_OUT(environment) 391 if d_type.typecode(): 392 return self.__base_type_OUT(environment) 393 if d_type.interface(): 394 return self.__base_type_OUT(environment) 395 if d_type.any() and (not old_sig or use_out): 396 return self.__base_type_OUT(environment) 397 if d_type.variable() and (not old_sig or use_out): 398 return self.__base_type_OUT(environment) 399 400 if direction == INOUT: 401 if d_type.string() and use_out: 402 return self.__base_type_INOUT(environment) 403 if d_type.wstring() and use_out: 404 return self.__base_type_INOUT(environment) 405 if d_type.typecode() and use_out: 406 return self.__base_type_INOUT(environment) 407 if d_type.interface() and use_out: 408 return self.__base_type_INOUT(environment) 409 410 if d_type.string() and not type.array(): 411 base = d_type.base(environment) 412 413 if d_type.wstring() and not type.array(): 414 base = d_type.base(environment) 415 416 # P1-104 mentions two cases: returning an array and a variable 417 # array out argument. For the latter rely on the _out type 418 if (type.array() and direction == RET): 419 base = base + "_slice" 420 421 mapping = self._argmapping(direction) 422 423 return self.__apply_mapping(mapping, base) 424 425 def member(self, environment = None, decl = None, gscope = 0): 426 """member(types.Type, id.Environment option, idlast.Declarator option): 427 C++ member type""" 428 429 if gscope: 430 assert environment is None 431 432 decl_dims = [] 433 if decl != None: 434 assert isinstance(decl, idlast.Declarator) 435 decl_dims = decl.sizes() 436 437 is_array_declarator = decl_dims != [] 438 439 if not self.array(): 440 d_type = self.deref() 441 if d_type.string(): 442 return "::CORBA::String_member" 443 if d_type.wstring(): 444 return "::CORBA::WString_member" 445 if d_type.interface(): 446 return d_type.objRefTemplate("Member", environment, 447 gscope=gscope) 448 if d_type.typecode(): 449 return "::CORBA::TypeCode_member" 450 451 if self.sequence(): 452 return d_type.sequenceTemplate(environment, gscope=gscope) 453 454 if self.value() or self.valuebox(): 455 m = self.base(environment) + "_member" 456 if gscope: m = "::" + m 457 return m 458 459 if self.typedef(): 460 # for the type to have dimensions, it must be a typedef 461 m = id.Name(self.__type.scopedName()).unambiguous(environment) 462 if gscope: m = "::" + m 463 return m 464 465 return self.base(environment, gscope=gscope) 466 467 def objRefTemplate(self, suffix, environment = None, gscope = 0): 468 """objRefTemplate(types.Type, suffix string, id.Environment option): 469 Returns a template objref instance for the current type""" 470 type = self.deref().__type 471 name = type.decl().scopedName() 472 if name == ["CORBA", "Object"]: 473 return "::CORBA::Object_" + suffix 474 475 name = id.Name(name) 476 uname = name.unambiguous(environment) 477 if self.objref(): 478 objref_name = name.prefix("_objref_") 479 objref_uname = objref_name.unambiguous(environment) 480 else: 481 objref_uname = uname 482 483 if gscope: 484 uname = "::" + uname 485 objref_uname = "::" + objref_uname 486 487 return "_CORBA_ObjRef_" + suffix + \ 488 "< " + objref_uname + ", " + uname + "_Helper> " 489 490 def valueTemplate(self, suffix, environment = None, gscope = 0): 491 """valueTemplate(types.Type, suffix string, id.Environment option): 492 Returns a template value instance for the current type""" 493 type = self.deref().__type 494 name = type.decl().scopedName() 495 name = id.Name(name) 496 uname = name.unambiguous(environment) 497 if gscope: 498 uname = "::" + uname 499 500 return "_CORBA_Value_%s< %s, %s > " % (suffix, uname, 501 uname + "_Helper") 502 503 def literal(self, value, environment = None): 504 """literal(types.Type, value any, id.Environment option): string 505 Returns a C++ representation of a value""" 506 507 type = self.deref() 508 kind = type.__type.kind() 509 510 # (unsigned) short ints are themselves 511 if kind in [ idltype.tk_short, idltype.tk_ushort ]: 512 return str(value) 513 514 # careful with long ints to avoid "L" postfix 515 if kind in [ idltype.tk_long, idltype.tk_ulong ]: 516 s = str(value) 517 if s[-1] == 'L': s = s[0:-1] 518 if kind == idltype.tk_ulong: s = s + "U" 519 return s 520 521 if kind in [ idltype.tk_longlong, idltype.tk_ulonglong ]: 522 s = str(value) 523 if s[-1] == 'L': s = s[:-1] 524 if kind == idltype.tk_ulonglong: s = s + "U" 525 return "_CORBA_LONGLONG_CONST(" + s + ")" 526 527 if kind in [ idltype.tk_float ]: 528 return idlutil.reprFloat(value) + "F" 529 530 if kind in [ idltype.tk_double ]: 531 return idlutil.reprFloat(value) 532 533 if kind in [ idltype.tk_longdouble ]: 534 return idlutil.reprFloat(value) + "L" 535 536 # chars are single-quoted 537 if kind in [ idltype.tk_char ]: 538 return "'" + idlutil.escapifyString(value) + "'" 539 540 if kind in [ idltype.tk_wchar ]: 541 return "L'" + idlutil.escapifyWString([value], "x") + "'" 542 543 # booleans are straightforward 544 if kind in [ idltype.tk_boolean ]: 545 return str(value) 546 547 if kind in [ idltype.tk_enum ]: 548 # value is an enumerator 549 enum_name = id.Name(value.scopedName()) 550 #enum_name = id.Name(type.__type.decl().scopedName() + [str(value)]) 551 return enum_name.unambiguous(environment) 552 553 if kind in [ idltype.tk_string ]: 554 return '"' + idlutil.escapifyString(value) + '"' 555 556 if kind in [ idltype.tk_wstring ]: 557 return 'L"' + idlutil.escapifyWString(value, "x") + '"' 558 559 if kind in [ idltype.tk_octet ]: 560 return str(value) 561 562 if kind in [ idltype.tk_fixed ]: 563 return '"' + value + '"' 564 565 util.fatalError("Internal error when handling value (" +\ 566 repr(value) +")" ) 567 568 def sequenceTemplate(self, environment = None, gscope = 0): 569 """sequenceTemplate(types.Type, id.Environment option): C++ template 570 Returns a C++ template instance for the current type as a 571 sequence""" 572 # returns a template instantiation suitable for the 573 # sequence type 574 sequence = self.__type 575 assert isinstance(sequence, idltype.Sequence) 576 577 SeqType = Type(sequence.seqType()) 578 d_SeqType = SeqType.deref() 579 SeqTypeID = SeqType.base(environment, gscope=gscope) 580 d_SeqTypeID = d_SeqType.base(environment, gscope=gscope) 581 if d_SeqType.typecode(): 582 d_SeqTypeID = "::CORBA::TypeCode_member" 583 SeqTypeID = "::CORBA::TypeCode_member" 584 elif d_SeqType.interface(): 585 d_SeqTypeID = d_SeqTypeID.replace("_ptr","") 586 SeqTypeID = SeqTypeID.replace("_ptr","") 587 elif d_SeqType.string(): 588 d_SeqTypeID = "::CORBA::String_member" 589 elif d_SeqType.wstring(): 590 d_SeqTypeID = "::CORBA::WString_member" 591 592 if SeqType.string(): 593 SeqTypeID = "::CORBA::String_member" 594 595 if SeqType.wstring(): 596 SeqTypeID = "::CORBA::WString_member" 597 598 # silly special case (not needed?): 599 #if d_SeqType.objref() and SeqType.typedef(): 600 # SeqTypeID = id.Name(SeqType.type().scopedName()).\ 601 # unambiguous(environment) 602 603 seq_dims = SeqType.dims() 604 is_array = seq_dims != [] 605 dimension = reduce(lambda x,y: x * y, seq_dims, 1) 606 607 template = {} 608 template["bounded"] = sequence.bound() 609 template["array"] = is_array 610 template["dimension"] = dimension 611 612 template["seqTypeID"] = SeqTypeID 613 template["derefSeqTypeID"] = d_SeqTypeID 614 615 # if the seqType is a typedef to a sequence, use the typedef name 616 # else if a direct sequence<sequence<...., do recursion 617 if d_SeqType.sequence() and not SeqType.typedef(): 618 element_template = d_SeqType.sequenceTemplate(environment) 619 template["seqTypeID"] = element_template 620 template["derefSeqTypeID"] = element_template 621 622 if is_array: 623 if d_SeqType.sequence(): 624 template["derefSeqTypeID"] = d_SeqType.\ 625 sequenceTemplate(environment) 626 627 if d_SeqType.char(): 628 template["suffix"] = "_Char" 629 elif d_SeqType.wchar(): 630 template["suffix"] = "_WChar" 631 elif d_SeqType.boolean(): 632 template["suffix"] = "_Boolean" 633 elif d_SeqType.octet(): 634 template["suffix"] = "_Octet" 635 # strings are always special 636 elif d_SeqType.string() and not is_array: 637 template["suffix"] = "_String" 638 elif d_SeqType.wstring() and not is_array: 639 template["suffix"] = "_WString" 640 elif d_SeqType.structforward() or d_SeqType.unionforward(): 641 template["forward"] = 1 642 elif d_SeqType.type().kind() in typeSizeAlignMap: 643 template["fixed"] = typeSizeAlignMap[d_SeqType.type().kind()] 644 elif d_SeqType.interface(): 645 scopedName = d_SeqType.type().decl().scopedName() 646 is_CORBA_Object = scopedName == ["CORBA", "Object"] 647 scopedName = id.Name(scopedName) 648 649 if not is_CORBA_Object and d_SeqType.objref(): 650 # CORBA::Object doesn't have an _objref_xxx 651 scopedName = scopedName.prefix("_objref_") 652 653 objref_name = scopedName.unambiguous(environment) 654 655 if not is_array: 656 objref_template = d_SeqType.objRefTemplate("Element", environment) 657 else: 658 objref_template = d_SeqType.objRefTemplate("Member", environment) 659 template["objref_name"] = objref_name 660 template["objref_template"] = objref_template 661 template["objref_helper"] = SeqTypeID + "_Helper" 662 template["objref"] = 1 663 664 elif d_SeqType.value() or d_SeqType.valuebox(): 665 scopedName = d_SeqType.type().decl().scopedName() 666 scopedName = id.Name(scopedName) 667 668 value_name = scopedName.unambiguous(environment) 669 670 if not is_array: 671 value_template = d_SeqType.valueTemplate("Element", environment) 672 else: 673 value_template = d_SeqType.valueTemplate("Member", environment) 674 675 template["value_name"] = value_name 676 template["value_template"] = value_template 677 template["value_helper"] = SeqTypeID + "_Helper" 678 template["value"] = 1 679 680 return self.__templateToString(template) 681 682 # converts a hash of template properties into a template instance 683 def __templateToString(self, template): 684 # ------------------------------------ 685 # work out the template name 686 if template["bounded"]: 687 name = "_CORBA_Bounded_Sequence" 688 else: 689 name = "_CORBA_Unbounded_Sequence" 690 691 if template["array"]: 692 name = name + "_Array" 693 694 if "suffix" in template: 695 name = name + template["suffix"] 696 697 if "forward" in template: 698 name = name + "_Forward" 699 700 elif "objref" in template and not template["array"]: 701 name = name + "_ObjRef" 702 703 elif "value" in template and not template["array"]: 704 name = name + "_Value" 705 706 if "fixed" in template: 707 name = name + "_w_FixSizeElement" 708 709 # ------------------------------------ 710 # build the argument list 711 args = [] 712 713 seqTypeID = template["seqTypeID"] 714 derefSeqTypeID = template["derefSeqTypeID"] 715 dimension = template["dimension"] 716 717 # Note the difference between an ObjRef and an array of ObjRefs 718 if template["array"]: 719 args.extend([seqTypeID, seqTypeID + "_slice"]) 720 721 if "objref" in template: 722 args.append(template["objref_template"]) 723 724 elif "value" in template: 725 args.append(template["value_template"]) 726 727 elif "suffix" not in template: 728 # __Boolean __Octet __String 729 # these already contain the type info- no need for another 730 # parameter... 731 args.append(derefSeqTypeID) 732 733 args.append(str(dimension)) 734 735 elif "objref" in template: 736 args.extend([template["objref_name"], 737 template["objref_template"], 738 template["objref_helper"]]) 739 740 elif "value" in template: 741 args.extend([template["value_name"], 742 template["value_template"], 743 template["value_helper"]]) 744 745 elif "suffix" not in template: 746 # see above 747 args.append(seqTypeID) 748 749 if "bounded" in template and \ 750 template["bounded"]: 751 args.append(str(template["bounded"])) 752 753 if "fixed" in template: 754 (element_size, alignment) = template["fixed"] 755 args.extend([str(element_size), str(alignment)]) 756 757 # ----------------------------------- 758 # build the template instance 759 if args: 760 name = name + "< " + ", ".join(args) + " > " 761 return name 762 763 return name 764 765 def _var(self, environment = None): 766 """Returns a representation of the type which is responsible for its 767 own destruction. Assigning a heap allocated thing to this type 768 should allow the user to forget about deallocation.""" 769 d_T = self.deref() 770 771 if self.array() or d_T.struct() or d_T.union() or \ 772 d_T.exception() or d_T.sequence() or \ 773 d_T.interface() or d_T.value() or \ 774 d_T.valuebox(): 775 name = id.Name(self.type().decl().scopedName()).suffix("_var") 776 return name.unambiguous(environment) 777 778 if d_T.typecode(): return "::CORBA::TypeCode_var" 779 if d_T.any(): return "::CORBA::Any_var" 780 if d_T.string(): return "::CORBA::String_var" 781 if d_T.wstring(): return "::CORBA::WString_var" 782 if d_T.enum(): 783 name = id.Name(self.type().decl().scopedName()) 784 return name.unambiguous(environment) 785 786 if self.is_basic_data_types(): 787 return basic_map[d_T.kind()] 788 789 if d_T.void(): 790 raise NotImplementedError("No such thing as a void _var type") 791 792 raise AssertionError("Unknown _var type, kind = " + str(d_T.kind())) 793 794 def out(self, ident): 795 if self.is_basic_data_types(): 796 return ident 797 798 return ident + ".out()" 799 800 def free(self, thing, environment = None): 801 """Ensures that any heap allocated storage associated with this type 802 has been deallocated.""" 803 804 if self.array(): 805 name = id.Name(self.type().decl().scopedName()).suffix("_free") 806 return name.unambiguous(environment) + "(" + thing + ");" 807 808 d_T = self.deref() 809 810 if d_T.interface() or d_T.typecode(): 811 return "::CORBA::release(" + thing + ");" 812 if d_T.string(): return "::CORBA::string_free(" + thing + ");" 813 814 if d_T.wstring(): return "::CORBA::wstring_free(" + thing + ");" 815 816 if d_T.struct() or d_T.union() or d_T.exception() or \ 817 d_T.sequence() or d_T.any(): 818 if d_T.variable(): 819 return "delete " + thing + ";" 820 return "" # stored by value 821 822 if d_T.enum() or d_T.void() or (self.is_basic_data_types()): 823 return "" 824 825 raise AssertionError("Don't know how to free type, kind = " + 826 str(d_T.kind())) 827 828 def copy(self, src, dest, environment = None): 829 """Copies an entity from src to dest""" 830 831 if self.array(): 832 name = id.Name(self.type().decl().scopedName()).suffix("_dup") 833 return dest + " = " + name.unambiguous(environment) + "("+src+");" 834 835 d_T = self.deref() 836 if d_T.typecode(): 837 return dest + " = ::CORBA::TypeCode::_duplicate(" + src + ");" 838 if d_T.interface(): 839 # Use the internal omniORB duplicate function in case the 840 # normal one isn't available 841 name = id.Name(self.type().decl().scopedName()).suffix("_Helper") 842 return name.unambiguous(environment) + "::duplicate" +\ 843 "(" + src + ");\n" + dest + " = " + src + ";" 844 if d_T.string(): 845 return dest + " = ::CORBA::string_dup(" + src + ");" 846 if d_T.wstring(): 847 return dest + " = ::CORBA::wstring_dup(" + src + ");" 848 if d_T.any(): 849 return dest + " = new ::CORBA::Any(" + src + ");" 850 851 if d_T.struct() or d_T.union() or d_T.exception() or d_T.sequence(): 852 name = id.Name(self.type().decl().scopedName()).\ 853 unambiguous(environment) 854 if d_T.variable(): 855 return dest + " = new " + name + "(" + src + ");" 856 return dest + " = " + src + ";" 857 858 if d_T.enum() or self.is_basic_data_types(): 859 return dest + " = " + src + ";" 860 861 raise AssertionError("Don't know how to copy type, kind = " + 862 str(d_T.kind())) 863 864 def representable_by_int(self): 865 """representable_by_int(types.Type): boolean 866 Returns true if the type is representable by an integer""" 867 return self.integer() or self.char() or self.boolean() or self.octet() 868 869 def is_basic_data_types(self): 870 d_T = self.deref() 871 return d_T.kind() in basic_map 872 873 def integer(self): 874 type = self.__type 875 return type.kind() in [ idltype.tk_short, idltype.tk_long, 876 idltype.tk_longlong, idltype.tk_ushort, 877 idltype.tk_ulong, idltype.tk_ulonglong ] 878 def char(self): 879 type = self.__type 880 return type.kind() == idltype.tk_char 881 882 def wchar(self): 883 type = self.__type 884 return type.kind() == idltype.tk_wchar 885 886 def floating(self): 887 type = self.__type 888 return type.kind() in [ idltype.tk_float, idltype.tk_double ] 889 890 def float(self): 891 type = self.__type 892 return type.kind() == idltype.tk_float 893 894 def double(self): 895 type = self.__type 896 return type.kind() == idltype.tk_double 897 898 def boolean(self): 899 type = self.__type 900 return type.kind() == idltype.tk_boolean 901 902 def enum(self): 903 type = self.__type 904 return type.kind() == idltype.tk_enum 905 906 def octet(self): 907 type = self.__type 908 return type.kind() == idltype.tk_octet 909 910 def string(self): 911 type = self.__type 912 return type.kind() == idltype.tk_string 913 914 def wstring(self): 915 type = self.__type 916 return type.kind() == idltype.tk_wstring 917 918 def objref(self): 919 type = self.__type 920 return type.kind() == idltype.tk_objref 921 922 def sequence(self): 923 type = self.__type 924 return type.kind() == idltype.tk_sequence 925 926 def typecode(self): 927 type = self.__type 928 return type.kind() == idltype.tk_TypeCode 929 930 def typedef(self): 931 type = self.__type 932 return type.kind() == idltype.tk_alias 933 934 def struct(self): 935 type = self.__type 936 return type.kind() == idltype.tk_struct 937 938 def structforward(self): 939 type = self.__type 940 return type.kind() == idltype.ot_structforward 941 942 def union(self): 943 type = self.__type 944 return type.kind() == idltype.tk_union 945 946 def unionforward(self): 947 type = self.__type 948 return type.kind() == idltype.ot_unionforward 949 950 def exception(self): 951 type = self.__type 952 return type.kind() == idltype.tk_except 953 954 def void(self): 955 type = self.__type 956 return type.kind() == idltype.tk_void 957 958 def any(self): 959 type = self.__type 960 return type.kind() == idltype.tk_any 961 962 def fixed(self): 963 type = self.__type 964 return type.kind() == idltype.tk_fixed 965 966 def value(self): 967 type = self.__type 968 return type.kind() == idltype.tk_value 969 970 def valuebox(self): 971 type = self.__type 972 return type.kind() == idltype.tk_value_box 973 974 def abstract_interface(self): 975 type = self.__type 976 return type.kind() == idltype.tk_abstract_interface 977 978 def local_interface(self): 979 type = self.__type 980 return type.kind() == idltype.tk_local_interface 981 982 def interface(self): 983 type = self.__type 984 return type.kind() in [ idltype.tk_objref, 985 idltype.tk_abstract_interface, 986 idltype.tk_local_interface ] 987 988 989def variableDecl(decl): 990 """types.variableDecl(idlast.Decl): boolean 991 Returns true if the declaration represents a variable type""" 992 # interfaces are mapped to objects, which are always 993 # variable types. same goes for exceptions. 994 if isinstance(decl, idlast.Interface) or \ 995 isinstance(decl, idlast.Forward) or \ 996 isinstance(decl, idlast.Exception): 997 return 1 998 elif isinstance(decl, idlast.Const) or \ 999 isinstance(decl, idlast.Enum): 1000 return 0 1001 1002 # a typedef is only a type alias- as such it has no storage 1003 # at all. However it eventually points to something that would. 1004 elif isinstance(decl, idlast.Typedef): 1005 return Type(decl.aliasType()).variable() 1006 1007 # a structure is variable if any one of its constituents 1008 # is also variable 1009 elif isinstance(decl, idlast.Struct): 1010 for m in decl.members(): 1011 if Type(m.memberType()).variable(): 1012 return 1 1013 return 0 1014 1015 # a union is variable if any one if its constituents 1016 # is also variable 1017 elif isinstance(decl, idlast.Union): 1018 for c in decl.cases(): 1019 if Type(c.caseType()).variable(): 1020 return 1 1021 return 0 1022 1023 # a declarator is variable if it is an alias to a variable 1024 # type 1025 elif isinstance(decl, idlast.Declarator) and \ 1026 decl.alias() != None: 1027 return Type(decl.alias().aliasType()).variable() 1028 1029 util.fatalError("Unknown AST node, scopedName = " +repr(decl.scopedName())) 1030 1031 1032 1033 1034def direction(param): 1035 if param.is_in() and param.is_out(): 1036 return INOUT 1037 elif param.is_in(): 1038 return IN 1039 elif param.is_out(): 1040 return OUT 1041 1042 # Top 12 things likely to be overheard from a Klingon Programmer: 1043 # ... 1044 # 1045 # 7) "Klingon function calls do not have 'parameters' - they 1046 # have 'arguments' - and they ALWAYS WIN THEM." 1047 # ... 1048 1049 util.fatalError("Illegal parameter direction") 1050 1051 1052################################################################# 1053# Tables of useful data ripped from the CORBA spec 1054 1055# already_Variable maps typecode kinds onto true/ false 1056# 1057# An entry in this table indicates we already know is a type is 1058# variable or not, without having to look at its declaration. 1059# (note that eg structs and unions are only variable if one of 1060# their members are) 1061 1062# CORBA2.3 P1-21 1.9 Mapping for Structured Types 1063already_Variable = { 1064 idltype.tk_null: 0, 1065 idltype.tk_void: 0, 1066 idltype.tk_short: 0, 1067 idltype.tk_long: 0, 1068 idltype.tk_ushort: 0, 1069 idltype.tk_ulong: 0, 1070 idltype.tk_float: 0, 1071 idltype.tk_double: 0, 1072 idltype.tk_boolean: 0, 1073 idltype.tk_char: 0, 1074 idltype.tk_octet: 0, 1075 idltype.tk_any: 1, 1076 idltype.tk_objref: 1, 1077 idltype.tk_string: 1, 1078 idltype.tk_sequence: 1, 1079 idltype.tk_except: 1, 1080 idltype.tk_longlong: 0, 1081 idltype.tk_ulonglong: 0, 1082 idltype.tk_longdouble: 0, 1083 idltype.tk_wchar: 0, 1084 idltype.tk_wstring: 1, 1085 idltype.tk_fixed: 0, 1086 idltype.tk_value: 1, 1087 idltype.tk_value_box: 1, 1088 idltype.tk_abstract_interface: 1, 1089 idltype.tk_TypeCode: 1, 1090 idltype.tk_local_interface: 1, 1091 } 1092 1093# CORBA2.3 P1-15 1.5 Mapping for Basic Data Types 1094basic_map = { 1095 idltype.tk_short: "::CORBA::Short", 1096 idltype.tk_long: "::CORBA::Long", 1097 idltype.tk_longlong: "::CORBA::LongLong", 1098 idltype.tk_ushort: "::CORBA::UShort", 1099 idltype.tk_ulong: "::CORBA::ULong", 1100 idltype.tk_ulonglong: "::CORBA::ULongLong", 1101 idltype.tk_float: "::CORBA::Float", 1102 idltype.tk_double: "::CORBA::Double", 1103 idltype.tk_longdouble: "::CORBA::LongDouble", 1104 idltype.tk_char: "::CORBA::Char", 1105 idltype.tk_wchar: "::CORBA::WChar", 1106 idltype.tk_boolean: "::CORBA::Boolean", 1107 idltype.tk_octet: "::CORBA::Octet" 1108 } 1109basic_map_out = { } 1110for key,value in list(basic_map.items()): 1111 basic_map_out[key] = value + "_out" 1112 1113 1114# Info on size and alignment of basic types 1115typeSizeAlignMap = { 1116 idltype.tk_char: (1, 1), 1117 idltype.tk_boolean: (1, 1), 1118 idltype.tk_wchar: (2, 2), 1119 idltype.tk_short: (2, 2), 1120 idltype.tk_ushort: (2, 2), 1121 idltype.tk_long: (4, 4), 1122 idltype.tk_ulong: (4, 4), 1123 idltype.tk_float: (4, 4), 1124 idltype.tk_enum: (4, 4), 1125 idltype.tk_double: (8, 8), 1126 idltype.tk_octet: (1, 1), 1127 idltype.tk_longlong: (8, 8), 1128 idltype.tk_ulonglong: (8, 8) 1129 } 1130