1# -*- python -*- 2# Package : omniidl 3# tie.py Created on: 1999/12/13 4# Author : David Scott (djs) 5# 6# Copyright (C) 2007-2011 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"""Produce the 'tie' templates""" 27 28from omniidl import idlast, idlvisitor 29from omniidl_be.cxx import id, config, types, output, ast 30from omniidl_be.cxx.header import template 31 32import sys 33self = sys.modules[__name__] 34 35 36# Write a single tie template class called <name>, inheriting from <inherits> 37# and grab the operations from <node> 38def write_template(name, inherits, node, stream, 39 Template = template.tie_template): 40 # build methods which bind the interface operations and attributes 41 # note that this includes inherited callables since tie 42 # templates are outside the normal inheritance structure 43 where = output.StringStream() 44 45 # defined_so_far contains keys corresponding to method names which 46 # have been defined already (and which should not be included twice) 47 def buildCallables(interface, where, continuation, defined_so_far = {}): 48 interface = ast.remove_ast_typedefs(interface) 49 50 callables = interface.callables() 51 operations = [x for x in callables if isinstance(x, idlast.Operation)] 52 for operation in operations: 53 returnType = types.Type(operation.returnType()) 54 identifier = operation.identifier() 55 if (identifier in defined_so_far): 56 # don't repeat it 57 continue 58 defined_so_far[identifier] = 1 59 60 parameters = operation.parameters() 61 has_return_value = not returnType.void() 62 # FIXME: return types are fully scoped but argument types 63 # arent? 64 returnType_name = returnType.op(types.RET) 65 66 operation_name = id.mapID(identifier) 67 68 signature = [] 69 call = [] 70 71 for parameter in parameters: 72 paramType = types.Type(parameter.paramType()) 73 # Need to call the _impl operation not the _objref operation 74 param_type_name = paramType.op(types.direction(parameter), 75 use_out = 0) 76 param_id = id.mapID(parameter.identifier()) 77 signature.append(param_type_name + " " + param_id) 78 call.append(param_id) 79 80 # deal with call contextx 81 if operation.contexts() != []: 82 signature.append("::CORBA::Context_ptr _ctxt") 83 call.append("_ctxt") 84 85 if has_return_value: 86 return_str = "return " 87 else: 88 return_str = "" 89 90 where.out("""\ 91@return_type_name@ @operation_name@(@signature@) { @return_str@pd_obj->@operation_name@(@call@); }""", return_type_name = returnType_name, 92 operation_name = operation_name, 93 return_str = return_str, 94 signature = ", ".join(signature), 95 call = ", ".join(call)) 96 97 attributes = [x for x in callables if isinstance(x, idlast.Attribute)] 98 for attribute in attributes: 99 identifiers = attribute.identifiers() 100 attrType = types.Type(attribute.attrType()) 101 102 attrType_name_RET = attrType.op(types.RET) 103 attrType_name_IN = attrType.op(types.IN) 104 105 for identifier in identifiers: 106 if identifier in defined_so_far: 107 # don't repeat it 108 continue 109 defined_so_far[identifier] = 1 110 111 ident = id.mapID(identifier) 112 where.out("""\ 113@attr_type_ret_name@ @attribute_name@() { return pd_obj->@attribute_name@(); }""", attr_type_ret_name = attrType_name_RET, 114 attribute_name = ident) 115 116 if not attribute.readonly(): 117 where.out("""\ 118void @attribute_name@(@attr_type_in_name@ _value) { pd_obj->@attribute_name@(_value); }""", attribute_name = ident, 119 attr_type_in_name = attrType_name_IN) 120 # do the recursive bit 121 for i in interface.inherits(): 122 i = i.fullDecl() 123 continuation(i, where, continuation, defined_so_far) 124 125 # done 126 return 127 128 buildCallables(node, where, buildCallables) 129 130 stream.out(Template, 131 tie_name = name, 132 inherits = inherits, 133 callables = str(where)) 134 return 135 136 137# Unflattened BOA tie templates are built in a block out of line. 138# IDL name template name 139# ::A ::_tie_A 140# ::B ::_tie_B 141# ::M::C ::_tie_M::C 142 143class BOATieTemplates(idlvisitor.AstVisitor): 144 def __init__(self, stream): 145 self.stream = stream 146 147 def visitAST(self, node): 148 for d in node.declarations(): 149 if ast.shouldGenerateCodeForDecl(d): 150 d.accept(self) 151 152 def visitModule(self, node): 153 name = id.Name(node.scopedName()) 154 155 self.stream.out(template.module_begin, 156 name = "_tie_" + name.simple()) 157 self.stream.inc_indent() 158 159 for d in node.definitions(): d.accept(self) 160 161 self.stream.dec_indent() 162 self.stream.out(template.module_end) 163 164 165 def visitInterface(self, node): 166 name = id.Name(node.scopedName()) 167 168 tie_name = name.simple() 169 if len(node.scopedName()) == 1: tie_name = "_tie_" + tie_name 170 171 sk_name = name.prefix("_sk_") 172 173 write_template(tie_name, sk_name.fullyQualify(), node, self.stream, 174 Template = template.tie_template_old) 175 176 177# Flat Tie Templates are all (by definition) in the global scope, 178# so can combine POA and BOA code into one 179class FlatTieTemplates(idlvisitor.AstVisitor): 180 def __init__(self, stream): 181 self.stream = stream 182 183 def visitAST(self, node): 184 for d in node.declarations(): 185 if ast.shouldGenerateCodeForDecl(d): 186 d.accept(self) 187 188 def visitModule(self, node): 189 for d in node.definitions(): 190 d.accept(self) 191 192 def visitInterface(self, node): 193 self.generate_POA_tie(node) 194 if config.state['BOA Skeletons']: 195 self.generate_BOA_tie(node) 196 197 def generate_BOA_tie(self, node): 198 name = id.Name(node.scopedName()) 199 tie_name = "_tie_" + "_".join(name.fullName()) 200 sk_name = name.prefix("_sk_") 201 202 write_template(tie_name, sk_name.fullyQualify(), node, self.stream, 203 Template = template.tie_template_old) 204 205 def generate_POA_tie(self, node): 206 name = id.Name(node.scopedName()) 207 tie_name = "POA_" + "_".join(name.fullName()) + "_tie" 208 poa_name = "POA_" + name.fullyQualify() 209 210 write_template(tie_name, poa_name, node, self.stream) 211