# -*- python -*-
# Package : omniidl
# call.py Created on: 2000/08/03
# Author : David Scott (djs)
#
# Copyright (C) 2002-2008 Apasphere Ltd
# Copyright (C) 2000 AT&T Laboratories Cambridge
#
# This file is part of omniidl.
#
# omniidl is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# Description:
# Produce local callback functions
#
# $Id: call.py,v 1.1.6.12 2009/05/06 16:15:53 dgrisby Exp $
# $Log: call.py,v $
# Revision 1.1.6.12 2009/05/06 16:15:53 dgrisby
# Update lots of copyright notices.
#
# Revision 1.1.6.11 2008/10/28 15:33:42 dgrisby
# Undeclared user exceptions not caught in local calls.
#
# Revision 1.1.6.10 2007/09/19 14:16:08 dgrisby
# Avoid namespace clashes if IDL defines modules named CORBA.
#
# Revision 1.1.6.9 2007/02/26 15:51:15 dgrisby
# Suppress cd parameter when it is definitely unused, to avoid compiler
# warnings.
#
# Revision 1.1.6.8 2005/11/09 12:22:18 dgrisby
# Local interfaces support.
#
# Revision 1.1.6.7 2005/08/16 13:51:21 dgrisby
# Problems with valuetype / abstract interface C++ mapping.
#
# Revision 1.1.6.6 2005/03/30 23:36:11 dgrisby
# Another merge from omni4_0_develop.
#
# Revision 1.1.6.5 2005/01/06 23:09:49 dgrisby
# Big merge from omni4_0_develop.
#
# Revision 1.1.6.4 2004/10/13 17:58:21 dgrisby
# Abstract interfaces support; values support interfaces; value bug fixes.
#
# Revision 1.1.6.3 2003/11/06 11:56:56 dgrisby
# Yet more valuetype. Plain valuetype and abstract valuetype are now working.
#
# Revision 1.1.6.2 2003/10/23 11:25:54 dgrisby
# More valuetype support.
#
# Revision 1.1.6.1 2003/03/23 21:02:42 dgrisby
# Start of omniORB 4.1.x development branch.
#
# Revision 1.1.4.13 2003/01/14 11:48:16 dgrisby
# Remove warnings from gcc -Wshadow. Thanks Pablo Mejia.
#
# Revision 1.1.4.12 2002/11/21 16:12:34 dgrisby
# Oneway call descriptor bug.
#
# Revision 1.1.4.11 2001/11/27 14:35:08 dpg1
# Context, DII fixes.
#
# Revision 1.1.4.10 2001/11/06 15:41:37 dpg1
# Reimplement Context. Remove CORBA::Status. Tidying up.
#
# Revision 1.1.4.9 2001/10/18 12:45:27 dpg1
# IDL compiler tweaks.
#
# Revision 1.1.4.8 2001/10/17 16:50:25 dpg1
# Incorrect code with multiple out arguments
#
# Revision 1.1.4.7 2001/08/15 10:26:10 dpg1
# New object table behaviour, correct POA semantics.
#
# Revision 1.1.4.6 2001/05/31 16:18:11 dpg1
# inline string matching functions, re-ordered string matching in
# _ptrToInterface/_ptrToObjRef
#
# Revision 1.1.4.5 2001/05/02 14:20:15 sll
# Make sure that getStream() is used instead of casting to get a cdrStream
# from a IOP_C and IOP_S.
#
# Revision 1.1.4.4 2001/04/19 09:30:12 sll
# Big checkin with the brand new internal APIs.
# Scoped where appropriate with the omni namespace.
#
# Revision 1.1.4.3 2000/11/07 18:27:31 sll
# out_objrefcall now generates the correct unambiguous type name in its castings.
#
# Revision 1.1.4.2 2000/11/03 19:25:23 sll
# A new class CallDescriptor. The class contains all the code to generate
# the call descriptor for each operation. It also has functions to be called
# by different parts of the stub that use the call descriptor.
#
# Revision 1.1.4.1 2000/10/12 15:37:46 sll
# Updated from omni3_1_develop.
#
# Revision 1.1.2.2 2000/09/14 16:03:01 djs
# Remodularised C++ descriptor name generator
# Bug in listing all inherited interfaces if one is a forward
# repoID munging function now handles #pragma ID in bootstrap.idl
# Naming environments generating code now copes with new IDL AST types
# Modified type utility functions
# Minor tidying
#
# Revision 1.1.2.1 2000/08/21 11:34:32 djs
# Lots of omniidl/C++ backend changes
#
"""Produce call descriptors and local callback functions"""
from omniidl import idlast,idltype
from omniidl_be.cxx import types,id,util,skutil,output,cxx,ast,descriptor
from omniidl_be.cxx.skel import mangler,template
import string
# Callable- represents the notion of a callable entity (eg operation or
# attribute accessor method). Note that a read/write attribute is really
# two such entities paired together.
#
# .interface(): get the associated Interface object
# .operation_name(): get the IIOP operation name (eg get_colour)
# .method_name(): get the C++ mapped method name (eg colour)
# .returnType(): idltype
# .parameters(): idlast.Parameter
# .oneway(): boolean
# .contexts():
# .signature(): string representing the IDL signature
# .method(use_out): C++ mapping
#
class Callable:
def __init__(self, interface, operation_name, method_name, returnType,
parameters, oneway = 0, raises = [], contexts = []):
self.__interface = interface
self.__operation_name = operation_name
self.__method_name = method_name
self.__returnType = returnType
self.__parameters = parameters
self.__oneway = oneway
self.__raises = raises
self.__contexts = contexts
self.__signature = mangler.produce_signature(returnType, parameters,
raises, oneway)
def interface(self): return self.__interface
def operation_name(self): return self.__operation_name
def method_name(self): return self.__method_name
def returnType(self): return self.__returnType
def parameters(self): return self.__parameters
def oneway(self): return self.__oneway
def raises(self): return self.__raises
def contexts(self): return self.__contexts
def signature(self): return self.__signature
# Utility functions to build Callables #################################
#
def operation(interface, operation):
assert isinstance(operation, idlast.Operation)
return Callable(interface,
operation.identifier(),
id.mapID(operation.identifier()),
operation.returnType(),
operation.parameters(),
operation.oneway(),
operation.raises(),
operation.contexts())
def read_attributes(interface, attribute):
assert isinstance(attribute, idlast.Attribute)
callables = []
for identifier in attribute.identifiers():
callables.append(Callable(interface,
"_get_" + identifier,
id.mapID(identifier),
attribute.attrType(),
[], 0, [], []))
return callables
def write_attributes(interface, attribute):
assert isinstance(attribute, idlast.Attribute)
voidType = idltype.Base(idltype.tk_void)
callables = []
param = idlast.Parameter(attribute.file(), attribute.line(),
attribute.mainFile(), [], [],
0, attribute.attrType(), "_v")
for identifier in attribute.identifiers():
callables.append(Callable(interface,
"_set_" + identifier,
id.mapID(identifier),
voidType, [param], 0, [], []))
return callables
#####################################################################
class CallDescriptor:
# How this works:
#
# A call descriptor can be used on both sides:
# 1. on the client side to drive a remote call
# 2. on the server side to drive an upcall
#
# Therefore, it has to have a way to hold the arguments that is suitable
# for both the client and the server side.
#
# On the server side there is an additional requirement that it must
# provide the storage for the in and inout arguments.
#
# For this requirement, the call descriptor must contain 2 member per
# argument:
# 1. an argument holder, as the name suggests, is to hold the argument
# passed by the proxy call on the client side.
# 2. an argument storage which is used to store the argument and to
# remove it from the heap when finished.
#
# The naming convention is that a holder is named "arg_n" and
# a storage is named "arg_n_".
#
# In many cases, the holder member is the same as the storage member. Under
# these circumstances, only a single member is provided in the call descriptor
# and is named "arg_n".
#
# Some examples:
#
# For a string IN argument, the call descriptor members are:
# const char* arg_0;
# CORBA::String_var arg_0_;
#
# For a string OUT argument, the member is just
# CORBA::String_var arg_0;
#
# For a variable length struct IN argument:
# const varStruct* arg_0;
# varStruct_var arg_0_;
# Notice that the argument holder is a pointer to the struct whereas
# the mapping signature is const varStruct&.
#
# To determine what is most appropriate given a type and direction combination,
# the helper function _arg_info() is defined. The function is called with
# the type and direction as input and it returns a tuple of this form:
# ((is_const, is_ptr), (same_as_holder, is_var))
#
# The 1st element of the tuple describes the argument holder. The element
# itself is also a tuple:
# is_const == 1 if the holder is a const (e.g. IN string)
# is_ptr == 1 if the holder is a pointer (e.g. IN varStruct and ! IN string)
#
# The 2nd decribes the argument storage:
# same_as_holder == 1 if both holder & storage are the same (e.g. OUT string)
# is_var == 1 if the storage is a _var type (e.g. OUT string, OUT varStruct).
# If it is a _var type, of course the actual storage for
# the argument must be allocated on the heap.
#
# All the member functions of this class generates code based on this tuple
#
def __init__(self,signature,callable):
self.__signature = signature
self.__name = descriptor.call_descriptor(signature)
self.__oneway = callable.oneway()
self.__arguments = callable.parameters()
self.__returntype = callable.returnType()
self.__exceptions = callable.raises()
self.__contexts = callable.contexts()
self.__has_in_args = 0
self.__has_out_args = 0
self.__has_return_value = 0
for argument in self.__arguments:
if argument.is_in():
self.__has_in_args = 1
if argument.is_out():
self.__has_out_args = 1
if self.__returntype.kind() != idltype.tk_void:
self.__has_return_value = 1
if self.__contexts:
self.__context_name = descriptor.\
context_descriptor(self.__signature)
def out_desc(self, stream):
self.__out_declaration(stream)
self.__out_contextDescriptor(stream)
self.__out_marshalArgument(stream)
self.__out_unmarshalArgument(stream)
self.__out_marshalReturnedValues(stream)
self.__out_unmarshalReturnedValues(stream)
self.__out_userException(stream)
def out_localcall(self, stream, interface_name, operation, function_name):
assert isinstance(stream, output.Stream)
assert isinstance(interface_name, id.Name)
impl_args = []
n = -1
for argument in self.__arguments:
n = n + 1
arg_n = "tcd->arg_" + str(n)
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,argument.direction())
if h_is_ptr:
arg_n = "*" + arg_n
if s_is_holder and s_is_var:
if argument.is_in():
if argument.is_out():
arg_n = arg_n + ".inout()"
else:
arg_n = arg_n + ".in()"
else:
arg_n = arg_n + ".out()"
impl_args.append(arg_n)
if self.__has_return_value:
result_string = "tcd->result = "
else:
result_string = ""
if self.__contexts:
impl_args.append("ctxt")
# If we have no return value, no arguments, no exceptions, and
# no contexts, we don't use the call descriptor argument at
# all, so we do not give it a name, so as to avoid warnings on
# some compilers.
if result_string or impl_args or self.__exceptions or self.__contexts:
cd_arg = " cd"
else:
cd_arg = ""
# If we have no return value and no arguments at all then we don't
# need to fetch the call descriptor. This suppresses a warning in gcc
# about an unused variable.
if result_string or impl_args:
get_cd = self.__name + "* tcd = (" + self.__name + "*)cd;"
else:
get_cd = ""
impl_call = output.StringStream()
catch = output.StringStream()
# Deal with context
if self.__contexts:
impl_call.out(template.interface_callback_context,
cname = self.__context_name,
count = str(len(self.__contexts)))
# Deal with user exceptions
raises = self.__exceptions
if raises:
for exception in raises:
ex_scopedName = id.Name(exception.scopedName())
catch.out(template.interface_operation_catch_exn,
exname = ex_scopedName.fullyQualify())
impl_call.out(template.interface_callback_tryblock,
result = result_string,
cxx_operation_name = operation,
operation_arguments = string.join(impl_args, ", "),
catch = str(catch))
else:
impl_call.out(template.interface_callback_invoke,
result = result_string,
cxx_operation_name = operation,
operation_arguments = string.join(impl_args, ", "))
stream.out(template.interface_callback,
local_call_descriptor = function_name,
cd_arg = cd_arg,
get_call_descriptor = get_cd,
impl_fqname =interface_name.prefix("_impl_").fullyQualify(),
name = interface_name.fullyQualify(),
impl_call = str(impl_call))
def out_objrefcall(self,stream,operation,args,localcall_fn,environment):
assert isinstance(stream, output.Stream)
ctor_args = [ localcall_fn, "\"" + operation + "\"",
str(len(operation) + 1) ]
assign_args = []
assign_res = []
n = -1
for argument in self.__arguments:
n = n + 1
arg_n = "_call_desc.arg_" + str(n)
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,argument.direction())
if s_is_holder:
if argument.is_in():
rvalue = args[n]
if argtype.array():
rvalue = "&" + rvalue + "[0]"
if h_is_ptr:
rvalue = "&(" + argtype.base(environment) + "&) " \
+ rvalue
assign_args.append(arg_n + " = " + rvalue + ";")
else:
if s_is_var:
arg_n = arg_n + "._retn()"
assign_res.append(args[n] + " = " \
+ arg_n + ";")
else:
rvalue = args[n]
if argtype.array():
rvalue = "&" + rvalue + "[0]"
if argtype.value() or argtype.valuebox():
star = "*"
else:
star = ""
if h_is_ptr:
rvalue = "&(" + argtype.base(environment) + star + "&) " \
+ rvalue
assign_args.append(arg_n + " = " + rvalue + ";")
if self.__has_return_value:
argtype = types.Type(self.__returntype)
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,3)
if s_is_var:
assign_res.append("return _call_desc.result._retn();")
else:
assign_res.append("return _call_desc.result;")
if self.__contexts:
assign_context = "_call_desc.ctxt = "\
"::CORBA::Context::_duplicate(_ctxt);"
else:
assign_context = ""
stream.out(template.interface_operation,
call_descriptor = self.__name,
call_desc_args = string.join(ctor_args, ", "),
assign_args = string.join(assign_args,"\n"),
assign_res = string.join(assign_res,"\n"),
assign_context = assign_context)
def out_implcall(self,stream,operation,localcall_fn):
assert isinstance(stream, output.Stream)
ctor_args = [localcall_fn, "\"" + operation + "\"",
str(len(operation)+1),str(1) ]
prepare_out_args = []
if self.__has_out_args:
n = -1
for argument in self.__arguments:
n = n + 1
if argument.is_out() and not argument.is_in():
arg_n = "_call_desc.arg_" + str(n)
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,argument.direction())
if not s_is_holder:
rvalue = arg_n + "_"
if s_is_var:
rvalue = rvalue + ".out()"
if h_is_ptr:
rvalue = "&" + rvalue
prepare_out_args.append(arg_n + " = " + rvalue + ";")
# main block of code goes here
stream.out(template.interface_operation_dispatch,
idl_operation_name = operation,
call_descriptor = self.__name,
call_desc_args = string.join(ctor_args, ", "),
prepare_out_args = string.join(prepare_out_args,"\n"))
def __out_declaration(self,stream):
# build up the constructor argument list, the initialisation
# list and the data members list
ctor_args = ["LocalCallFn lcfn", "const char* op_", "size_t oplen",
"_CORBA_Boolean upcall=0" ]
base_ctor = ("omniCallDescriptor(lcfn, op_, oplen, %s, _user_exns, "
"%d, upcall)" % (self.__oneway, len(self.__exceptions)))
if self.__exceptions:
user_exceptions_decl = \
"void userException(cdrStream&,_OMNI_NS(IOP_C)*,const char*);"
else:
user_exceptions_decl = ""
in_arguments_decl = ""
out_arguments_decl = ""
if self.__has_in_args or self.__contexts:
in_arguments_decl = "void marshalArguments(cdrStream&);\n" + \
"void unmarshalArguments(cdrStream&);\n"
if self.__has_out_args or self.__has_return_value:
out_arguments_decl = \
"void unmarshalReturnedValues(cdrStream&);\n" + \
"void marshalReturnedValues(cdrStream&);\n"
data_members = []
n = -1
containsValues = 0
for argument in self.__arguments:
containsValues = (containsValues or
idltype.containsValueType(argument.paramType()))
n = n + 1
holder_n = "arg_" + str(n)
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),\
(s_is_holder,s_is_var)) = _arg_info(argtype,argument.direction())
if s_is_var:
storage = argtype._var()
else:
storage = argtype.base()
storage_n = holder_n
if not s_is_holder:
storage_n = storage_n + "_"
data_members.append(storage + " " + storage_n + ";")
if not s_is_holder:
holder = argtype.base()
if h_is_const:
holder = "const " + holder
if argtype.array():
holder = holder + "_slice*"
if h_is_ptr:
holder = holder + "*"
if argtype.value() or argtype.valuebox():
holder = holder + "*"
data_members.append(holder + " " + holder_n + ";")
if self.__has_return_value:
containsValues = (containsValues or
idltype.containsValueType(self.__returntype))
returntype = types.Type(self.__returntype)
((h_is_const,h_is_ptr),\
(s_is_holder,s_is_var)) = _arg_info(returntype,3)
holder_n = "result"
if s_is_var:
storage = returntype._var()
else:
storage = returntype.base()
storage_n = holder_n
if not s_is_holder:
storage_n = storage_n + "_"
data_members.append(storage + " " + storage_n + ";")
if self.__contexts:
data_members.append("::CORBA::Context_var ctxt;");
if containsValues:
contains_values = "containsValues(1);"
else:
contains_values = ""
# Write the proxy class definition
stream.out(template.interface_proxy_class,
signature = self.__signature,
call_descriptor = self.__name,
ctor_args = string.join(ctor_args,","),
base_ctor = base_ctor,
contains_values = contains_values,
in_arguments_decl = in_arguments_decl,
out_arguments_decl = out_arguments_decl,
user_exceptions_decl = user_exceptions_decl,
member_data = string.join(data_members,"\n"))
def __out_contextDescriptor(self,stream):
if self.__contexts:
contexts = output.StringStream()
for context in self.__contexts:
contexts.out('"' + context + '",')
stream.out(template.interface_context_array,
context_descriptor = self.__context_name,
contexts = str(contexts))
def __out_marshalArgument(self,stream):
if not (self.__has_in_args or self.__contexts): return
marshal_block = output.StringStream()
self.__out_marshalArgument_shared(marshal_block,1)
if self.__contexts:
marshal_block.out(template.interface_proxy_marshal_context,
name = self.__context_name,
count = str(len(self.__contexts)))
stream.out(template.interface_proxy_marshal_arguments,
call_descriptor = self.__name,
marshal_block = marshal_block)
def __out_marshalReturnedValues(self,stream):
if not (self.__has_out_args or self.__has_return_value): return
marshal_block = output.StringStream()
if self.__has_return_value:
argtype = types.Type(self.__returntype)
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,3)
argname = "result"
if (h_is_ptr):
argname = "*" + argname
skutil.marshall(marshal_block, None, argtype, None, argname, "_n")
self.__out_marshalArgument_shared(marshal_block,0)
stream.out(template.interface_proxy_marshal_returnedvalues,
call_descriptor = self.__name,
marshal_block = marshal_block)
def __out_marshalArgument_shared(self,stream,is_in):
n = -1
for argument in self.__arguments:
n = n + 1
if (is_in and not argument.is_in()) or \
(not is_in and not argument.is_out()): continue
arg_n = "arg_" + str(n)
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,argument.direction())
if h_is_ptr:
arg_n = "*" + arg_n
skutil.marshall(stream, None, argtype, None, arg_n, "_n")
def __out_unmarshalArgument(self,stream):
if not self.__has_in_args: return
marshal_block = output.StringStream()
n = -1
for argument in self.__arguments:
n = n + 1
if not argument.is_in(): continue
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,argument.direction())
arg_n = "arg_" + str(n)
if s_is_holder:
storage_n = arg_n
else:
storage_n = arg_n + "_"
if s_is_var:
alloc = ""
d_type = argtype.deref(1)
if argtype.array():
alloc = argtype.base() + "_alloc()"
elif not (d_type.typecode() or
d_type.string() or
d_type.wstring() or
d_type.interface() or
d_type.value() or
d_type.valuebox()):
alloc = "new " + argtype.base()
if alloc != "":
marshal_block.out(storage_n + " = " + alloc + ";")
skutil.unmarshall(marshal_block, None,
argtype, None, storage_n, "_n")
if not s_is_holder:
if s_is_var:
if argument.direction() == 0:
lvalue = storage_n + ".in()"
else:
lvalue = storage_n + ".inout()"
else:
lvalue = storage_n
if argtype.array():
lvalue = "&" + lvalue + "[0]"
if h_is_ptr:
marshal_block.out(arg_n + " = &" + lvalue + ";")
else:
marshal_block.out(arg_n + " = " + lvalue + ";")
if self.__contexts:
marshal_block.out(template.interface_proxy_unmarshal_context)
stream.out(template.interface_proxy_unmarshal_arguments,
call_descriptor = self.__name,
marshal_block = marshal_block)
def __out_unmarshalReturnedValues(self,stream):
if not (self.__has_out_args or self.__has_return_value): return
marshal_block = output.StringStream()
if self.__has_return_value:
argtype = types.Type(self.__returntype)
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,3)
argname = "result"
if s_is_var:
alloc = ""
d_type = argtype.deref(1)
if argtype.array():
alloc = argtype.base() + "_alloc()"
elif not (d_type.typecode() or
d_type.string() or
d_type.wstring() or
d_type.interface() or
d_type.value() or
d_type.valuebox()):
alloc = "new " + argtype.base()
if alloc != "":
marshal_block.out(argname + " = " + alloc + ";")
skutil.unmarshall(marshal_block, None,
argtype, None, argname, "_n")
n = -1
for argument in self.__arguments:
n = n + 1
if not argument.is_out(): continue
argtype = types.Type(argument.paramType())
((h_is_const,h_is_ptr),(s_is_holder,s_is_var)) = \
_arg_info(argtype,argument.direction())
arg_n = "arg_" + str(n)
d_type = argtype.deref(1)
if s_is_holder:
if s_is_var:
alloc = ""
if argtype.array():
alloc = argtype.base() + "_alloc()"
elif not (d_type.typecode() or
d_type.string() or
d_type.wstring() or
d_type.interface() or
d_type.value() or
d_type.valuebox()):
alloc = "new " + argtype.base()
if alloc != "":
marshal_block.out(arg_n + " = " + alloc + ";")
elif h_is_ptr:
if d_type.typecode():
marshal_block.out(arg_n + "_ = *" + arg_n + ";\n"+ \
"*" + arg_n + " = " + \
"::CORBA::TypeCode::_nil();")
elif d_type.interface():
nilobjref = string.replace(d_type.base(),"_ptr","::_nil()")
if isinstance(d_type.type().decl(),idlast.Forward):
nilobjref = string.replace(nilobjref,\
"::_nil()",\
"_Helper::_nil()")
marshal_block.out(arg_n + "_ = *" + arg_n + ";\n" + \
"*" + arg_n + " = " + \
nilobjref + ";")
elif d_type.string():
marshal_block.out(arg_n + "_ = *" + arg_n + ";\n"+ \
"*" + arg_n + " = " + \
"(char*) _CORBA_String_helper::empty_string;")
elif d_type.wstring():
marshal_block.out(arg_n + "_ = *" + arg_n + ";\n" + \
"*" + arg_n + " = " + \
"(::CORBA::WChar*) _CORBA_WString_helper::empty_wstring;")
arg_n = "*" + arg_n
skutil.unmarshall(marshal_block, None,
argtype, None, arg_n, "_n")
stream.out(template.interface_proxy_unmarshal_returnedvalues,
call_descriptor = self.__name,
marshal_block = marshal_block)
def __out_userException(self, stream):
if self.__exceptions:
block = output.StringStream()
exceptions = skutil.sort_exceptions(self.__exceptions)
repoIDs = []
for exception in exceptions:
scopedName = exception.scopedName()
repoID = scopedName + ["_PD_repoId"]
repoID_str = id.Name(repoID).fullyQualify()
repoIDs.append(repoID_str)
exname = id.Name(scopedName).fullyQualify()
block.out(template.interface_proxy_exn_handle,
repoID_str = repoID_str, exname = exname)
# write the user exception template
stream.out(template.interface_proxy_exn,
call_descriptor = self.__name,
exception_block = str(block),
exception_namelist = string.join(repoIDs,",\n"))
else:
stream.out(template.interface_proxy_empty_exn,
call_descriptor = self.__name)
def _arg_info(type,direction):
# Return a tuple containing the information about the mapping of
# this argument type.
# The tuple is of this form:
# (is_const, is_ptr), (same_as_holder, is_var)
# The 1st element is about the argument holder and
# is_const == 1 if the holder is a const
# is_ptr == 1 if the holder is a pointer
# The 2nd element is about the argument storage and
# same_as_holder == 1 if the storage is the same variable as the holder
# is_var == 1 if the storage is a CORBA _var type, otherwise the
# storage is the base type.
assert isinstance(type, types.Type)
if type.array():
if type.variable():
return _arg_array_mapping[_variable][direction]
else:
return _arg_array_mapping[_fixed][direction]
else:
d_type = type.deref(1)
d_kind = d_type.kind()
if _arg_mapping.has_key(d_kind):
return _arg_mapping[d_kind][direction]
else:
assert d_kind == idltype.tk_struct or \
d_kind == idltype.tk_union
if d_type.variable():
return _arg_struct_mapping[_variable][direction]
else:
return _arg_struct_mapping[_fixed][direction]
# (holder_is_const, holder_is_ptr), (storage_same_as_holder, storage_is_var)
# See _arg_info for the meaning of these 0s and 1s.
_arg_mapping = {
idltype.tk_boolean:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_char:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_octet:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_short:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_ushort:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_long:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_ulong:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_longlong:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_ulonglong:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_float:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_double:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_longdouble:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_enum:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_wchar:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_fixed:
( ((0,0),(1,0)), ((0,0),(1,0)), ((0,1),(0,0)), ((0,0),(1,0)) ),
idltype.tk_string:
( ((1,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_wstring:
( ((1,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_sequence:
( ((1,1),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_objref:
( ((0,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_TypeCode:
( ((0,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_any:
( ((1,1),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_value:
( ((0,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_value_box:
( ((0,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_abstract_interface:
( ((0,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
idltype.tk_local_interface:
( ((0,0),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
}
_fixed = 0
_variable = 1
# See _arg_info for the meaning of these 0s and 1s.
_arg_struct_mapping = {
_variable:
( ((1,1),(0,1)), ((0,0),(1,1)), ((0,1),(0,1)), ((0,0),(1,1)) ),
_fixed:
( ((1,1),(0,0)), ((0,1),(0,0)), ((0,1),(0,0)), ((0,0),(1,0)) )
}
# See _arg_info for the meaning of these 0s and 1s.
_arg_array_mapping = {
_variable:
( ((1,0),(0,1)), ((0,0),(1,1)), ((0,0),(0,1)), ((0,0),(1,1)) ),
_fixed:
( ((1,0),(0,0)), ((0,0),(0,0)), ((0,0),(0,0)), ((0,0),(1,1)) )
}
|