/*
* Copyright (c) 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
*
* This file is part of Flick, the Flexible IDL Compiler Kit.
*
* Flick 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.
*
* Flick 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 Flick; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
*/
#include <assert.h>
#include <string.h>
#include <mom/compiler.h>
#include <mom/libaoi.h>
#include <mom/libmint.h>
#include <mom/c/pfe.hh>
#include <mom/c/libcast.h>
#include <mom/c/libpres_c.h>
#include "private.hh"
/*****************************************************************************/
/*
* Generate a message send stub presentation for an AOI interface.
*/
void pg_state::p_continue_stub(aoi_interface *ai,
aoi_operation *orig_ao,
int request)
{
pres_c_continue_stub *cstub;
int newstub;
int cr, cdef;
char *old_name;
int cast_params_len;
cast_func_type cfunc;
stub_special_params specials;
int i, j;
mint_ref m_ref;
mint_ref request_ref;
mint_ref reply_ref;
mint_const oper_request;
mint_const oper_reply;
cast_scope *scope = (cast_scope *)top_ptr(scope_stack);
/*****/
if (orig_ao->flags & AOI_OP_FLAG_ONEWAY && !request) {
/* Oneway operations do not have reply stubs */
return;
}
/*
* Some presentation styles dictate that client stubs are created only
* for operations that are *defined* within an interface, not for
* operations that are *inherited* from parent interfaces. In such a
* presentation, one would invoke the parent's client stub to invoke an
* inherited operation on an instance of a derived object type.
*/
if ((parent_interface_ref != derived_interface_ref)
&& !client_stubs_for_inherited_operations)
return;
if(!lookup_interface_mint_discrims(ai, orig_ao,
&oper_request, &oper_reply)) {
panic("In `pg_state::p_ccontinue_stub', "
"cannot find MINT request and reply discriminators.");
}
/*
* Find the MINT references to the request and reply types.
*/
p_client_stub_find_refs(ai, orig_ao, oper_request, oper_reply,
&request_ref,
&reply_ref);
if (request)
m_ref = request_ref;
else
m_ref = reply_ref;
/*
* Determine the special parameters for this stub: the target object
* reference, the environment reference, etc.
*
* NOTE: We can (re)use the send_stub function for this because many
* of the parameters are the same for the continuation stub.
*/
p_msg_cont_stub_special_params(ai, &specials, request);
/*
* Determine the total number of stub parameters.
*/
cast_params_len = 0;//2;
for (i = 0;
i < stub_special_params::number_of_stub_special_param_kinds;
++i)
if (specials.params[i].index != -1)
++cast_params_len;
/*
* Verify our set of special parameters.
*/
for (i = 0;
i < stub_special_params::number_of_stub_special_param_kinds;
++i) {
if (specials.params[i].index != -1) {
/*
* Assert that this special parameter has a valid
* CAST type and a valid, unique index.
*/
assert(specials.params[i].ctype != 0);
assert((specials.params[i].index >= 0)
&& (specials.params[i].index
< cast_params_len));
for (j = i + 1;
j < stub_special_params::
number_of_stub_special_param_kinds;
++j)
assert(specials.params[i].index
!= specials.params[j].index);
}
}
/* Save the original name context for when we return. */
old_name = name;
if (request)
name = calc_continue_request_stub_name(orig_ao->name);
else
name = calc_continue_reply_stub_name(orig_ao->name);
/*
* Now we are ready to start building the presentation PRES_C and CAST
* goo.
*/
cast_init_function_type(&cfunc, cast_params_len);
if (cast_params_len) {
cfunc.params.params_len = cast_params_len;
cfunc.params.params_val
= (cast_func_param *)
mustcalloc(cast_params_len *
sizeof(cast_func_param));
}
/*
* Build MINT for this stub.
* Since the asynchronous send stub is solely a presentation entity,
* MINT for it does not come from AOI, so we have to ``manufacture''
* it here.
*/
m_ref = mint_add_def(&out_pres->mint);
m(m_ref).kind = MINT_STRUCT;
m(m_ref).mint_def_u.struct_def.slots.slots_len = 0;
m(m_ref).mint_def_u.struct_def.slots.slots_val = 0;
/*
* Build an aoi operation for the send stub.
* This enables us to reuse a lot of code to build the PRES_C.
*/
aoi_operation ao;
ao.name = name;
ao.request_code = 0; /* XXX */
ao.reply_code = 0; /* XXX */
ao.flags = 0;
ao.params.params_len = 0;
ao.params.params_val = 0;
ao.return_type = (aoi_type) mustcalloc(sizeof(aoi_type_u));
ao.return_type->kind = AOI_VOID;
ao.exceps.exceps_len = 0;
ao.exceps.exceps_val = 0;
/*
* Build the group of pres_c_inline structures containing the
* parameters, starting with level 4 (params struct) then levels
* 3, 2, 1 (unions).
*/
pres_c_inline l4_inl = pres_c_new_inline_func_params_struct(0);
process_async_params(&cfunc,
&specials,
m_ref,
&ao, l4_inl,
0 /* no target */, 0 /* no client */,
1 /* send => encode */, request);
/*
* The continuation stub return type is always void.
*/
cfunc.return_type = cast_new_type(CAST_TYPE_VOID);
/*
* Allocate a pres_c_stub for this operation --- UNLESS we have already
* created an appropriate client stub.
*
* Perhaps we are inheriting the current AOI operation from a parent
* interface and the user has changed the rule for creating stub names
* so that we now have a name conflict. (In this case, however, the
* user should instead tweak the flag that controls the creation of
* client stubs for inherited operations.)
*
* XXX --- We should be more careful about this check. Checking just
* the name is bad news. We must check for MINT and PRES_C equality as
* well!
*/
cast_scope *deep_scope = scope;
if (cast_find_def(&deep_scope,
cast_new_scoped_name(name, NULL),
CAST_FUNC_DECL) >= 0) {
/*
* XXX --- Check that our MINT and PRES_C is equal to that of
* the existing client stub. (Hell, check that `name' refers
* to a client stub and not some typedef or something else!)
*
* In lieu of being smart, warn the user.
*/
warn("Suppressing extra definition for message send stub `%s'.",
name);
/* Restore the name context. */
name = old_name;
return;
}
newstub = p_add_stub(out_pres);
s(newstub).kind = PRES_C_CONTINUE_STUB;
cstub = &s(newstub).pres_c_stub_u.continue_stub;
/* Set the message itype to the top-level "mom_msg" MINT union. */
cstub->itype = m_ref;
deep_scope = scope;
cast_scoped_name scn = cast_new_scoped_name(name, NULL);
if( (cr = cast_find_def(&deep_scope,
scn,
CAST_FUNC_DECL)) == -1 ) {
cr = cast_add_def(scope,
scn,
CAST_SC_NONE,
CAST_FUNC_DECL,
ch(cur_aoi_idx, PG_CHANNEL_SERVER_DECL),
current_protection);
scope->cast_scope_val[cr].u.cast_def_u_u.func_type = cfunc;
}
cdef = cast_add_def(&out_pres->stubs_cast,
request ? calc_continue_request_stub_scoped_name(
cur_aoi_idx, name) :
calc_continue_reply_stub_scoped_name(cur_aoi_idx,
name),
CAST_SC_NONE,
CAST_FUNC_DECL,
ch(cur_aoi_idx, PG_CHANNEL_SERVER_IMPL),
current_protection);
out_pres->stubs_cast.cast_scope_val[cdef].u.cast_def_u_u.func_type =
cfunc;
cstub->c_func = cdef;
/*
* Initialize the `return_slot' to null.
*/
l4_inl->pres_c_inline_u_u.func_params_i.return_slot = 0;
/*
* We need to turn the reply into the union of good, bad, & ugly values
*/
// if (!request)
// p_do_return_union(&ao, &l4_inl, m_ref, cr);
/*
* level 3
*
* XXX - might need to modify the operation request code here,
* e.g. add a prefix in the CORBA case (perhaps in overriding
* function)
*/
pres_c_inline l3_inl =
pres_c_new_inline(PRES_C_INLINE_COLLAPSED_UNION);
l3_inl->pres_c_inline_u_u.collapsed_union.discrim_val =
request? oper_request : oper_reply;
l3_inl->pres_c_inline_u_u.collapsed_union.selected_case =
l4_inl;
/* level 2 */
pres_c_inline l2_inl =
pres_c_new_inline(PRES_C_INLINE_COLLAPSED_UNION);
l2_inl->pres_c_inline_u_u.collapsed_union.discrim_val =
mint_new_const_from_aoi_const(ai->code);
l2_inl->pres_c_inline_u_u.collapsed_union.selected_case =
l3_inl;
/* level 1 */
pres_c_inline l1_inl =
pres_c_new_inline(PRES_C_INLINE_COLLAPSED_UNION);
l1_inl->pres_c_inline_u_u.collapsed_union.discrim_val =
mint_new_const_int((int)ai->idl);
l1_inl->pres_c_inline_u_u.collapsed_union.selected_case =
l2_inl;
/* Assign the unions and param struct to cstub fields. */
cstub->i = l4_inl;
cstub->request = request;
/* Restore the name context. */
name = old_name;
}
/*****************************************************************************/
void pg_state::p_continue_func_types(aoi_interface */*ai*/)
{
/* Produce a typedef for the request continuer function. */
cast_type req_type
= cast_new_function_type(cast_new_type(CAST_TYPE_VOID), 5);
req_type->cast_type_u_u.func_type.params.params_val[0].name
= calc_client_stub_object_param_name(name);
req_type->cast_type_u_u.func_type.params.params_val[0].type
= cast_new_type_name(
calc_client_stub_object_type_name(name));
req_type->cast_type_u_u.func_type.params.params_val[1].name
= ir_strlit("msg");
req_type->cast_type_u_u.func_type.params.params_val[1].type
= cast_new_type_name(
calc_message_request_type_name(name));
req_type->cast_type_u_u.func_type.params.params_val[2].name
= ir_strlit("inv_id");
req_type->cast_type_u_u.func_type.params.params_val[2].type
= cast_new_type_name(calc_stub_invocation_id_type_name(name));
req_type->cast_type_u_u.func_type.params.params_val[3].name
= ir_strlit("client");
req_type->cast_type_u_u.func_type.params.params_val[3].type
= cast_new_type_name(
calc_stub_client_ref_type_name(name));
req_type->cast_type_u_u.func_type.params.params_val[4].name
= ir_strlit("data");
req_type->cast_type_u_u.func_type.params.params_val[4].type
= cast_new_pointer_type(cast_new_type(CAST_TYPE_VOID));
cast_type preq_type = cast_new_pointer_type(req_type);
int cdef = cast_add_def(&out_pres->cast,
cast_new_scoped_name(
calc_request_continuer_func_type_name(
name),
NULL),
CAST_SC_NONE,
CAST_TYPEDEF,
ch(cur_aoi_idx, PG_CHANNEL_SERVER_DECL),
CAST_PROT_NONE);
c(cdef).u.cast_def_u_u.typedef_type = preq_type;
/* Now make one for the reply. */
cast_type rep_type
= cast_new_function_type(cast_new_type(CAST_TYPE_VOID), 5);
rep_type->cast_type_u_u.func_type.params.params_val[0].name
= ir_strlit("client");
rep_type->cast_type_u_u.func_type.params.params_val[0].type
= cast_new_type_name(
calc_stub_client_ref_type_name(name));
rep_type->cast_type_u_u.func_type.params.params_val[1].name
= ir_strlit("msg");
rep_type->cast_type_u_u.func_type.params.params_val[1].type
= cast_new_type_name(
calc_message_reply_type_name(name));
rep_type->cast_type_u_u.func_type.params.params_val[2].name
= ir_strlit("inv_id");
rep_type->cast_type_u_u.func_type.params.params_val[2].type
= cast_new_type_name(calc_stub_invocation_id_type_name(name));
rep_type->cast_type_u_u.func_type.params.params_val[3].name
= calc_client_stub_object_param_name(name);
rep_type->cast_type_u_u.func_type.params.params_val[3].type
= cast_new_type_name(
calc_client_stub_object_type_name(name));
rep_type->cast_type_u_u.func_type.params.params_val[4].name
= ir_strlit("data");
rep_type->cast_type_u_u.func_type.params.params_val[4].type
= cast_new_pointer_type(cast_new_type(CAST_TYPE_VOID));
cast_type prep_type = cast_new_pointer_type(rep_type);
cdef = cast_add_def(&out_pres->cast,
cast_new_scoped_name(
calc_reply_continuer_func_type_name(
name),
NULL),
CAST_SC_NONE,
CAST_TYPEDEF,
ch(cur_aoi_idx, PG_CHANNEL_SERVER_DECL),
CAST_PROT_NONE);
c(cdef).u.cast_def_u_u.typedef_type = prep_type;
}
/*****************************************************************************/
/***** Auxiliary functions. *****/
int pg_state::p_msg_cont_stub_special_params(aoi_interface */*ai*/,
stub_special_params *specials,
int request)
{
int newparms = 0;
stub_special_params::stub_param_info *this_param;
// char *name = getscopedname(cur_aoi_idx);
int i;
/*
* Initialize all of our special parameter data, just in case we fail
* to initialize any individual parameter below.
*/
for (i = 0;
i < stub_special_params::number_of_stub_special_param_kinds;
++i) {
specials->params[i].spec = 0;
specials->params[i].name = 0;
specials->params[i].ctype = 0;
specials->params[i].index = -1;
}
if (request) {
/* Request Continuer Stub has target object as first param */
/*
* Initialize the object reference type and index.
*/
this_param = &(specials->params[stub_special_params
::object_ref]);
this_param->name =
calc_client_stub_object_param_name(name);
this_param->ctype = cast_new_type_name(
calc_client_stub_object_type_name(name));
this_param->index = newparms;
newparms++;
} else {
/* Reply Continuer Stub has client object as first param */
/*
* Initialize the client type and index.
*/
this_param = &(specials->params[stub_special_params::
client_ref]);
this_param->name = "client";
this_param->ctype
= cast_new_type_name(
calc_stub_client_ref_type_name(name));
this_param->index = newparms;
newparms++;
}
/*
* Initialize the message reference type and index.
* This is only for message unmarshal, send, receive, and continuation
* stubs, since the normal presentation never passes around messages.
*/
this_param = &(specials->params[stub_special_params::message_ref]);
this_param->name = "_msg";
if (request) {
this_param->ctype
= cast_new_type_name(
calc_message_request_type_name(name));
} else {
this_param->ctype
= cast_new_type_name(
calc_message_reply_type_name(name));
}
this_param->index = newparms;
newparms++;
/*
* Initialize the invocation identifier type and index.
* This is only for message send, receive, and continuation stubs.
*/
this_param = &(specials->params[stub_special_params::invocation_ref]);
this_param->name = "inv_id";
this_param->ctype
= cast_new_type_name(calc_stub_invocation_id_type_name(name));
this_param->index = newparms;
newparms++;
if (request) {
/* Request Continuer Stub has client object as fourth param */
/*
* Initialize the client type and index.
*/
this_param = &(specials->params[stub_special_params::
client_ref]);
this_param->name = "client";
this_param->ctype
= cast_new_type_name(
calc_stub_client_ref_type_name(name));
this_param->index = newparms;
newparms++;
} else {
/* Reply Send Stub has target object as fourth param */
/*
* Initialize the object reference type and index.
*/
this_param = &(specials->params[stub_special_params
::object_ref]);
this_param->name =
calc_client_stub_object_param_name(name);
this_param->ctype = cast_new_type_name(
calc_client_stub_object_type_name(name));
this_param->index = newparms;
newparms++;
}
/*
* Initialize the continuation function type and index.
* This is only for message continuation stubs.
*/
this_param = &(specials->params[stub_special_params::
continue_func_ref]);
this_param->name = "func";
this_param->ctype
= (request)?
cast_new_type_name(
calc_request_continuer_func_type_name(name)) :
cast_new_type_name(
calc_reply_continuer_func_type_name(name));
this_param->index = newparms;
newparms++;
/*
* Initialize the continuation function type and index.
* This is only for message continuation stubs.
*/
this_param = &(specials->params[stub_special_params::
continue_data_ref]);
this_param->name = "data";
this_param->ctype = cast_new_pointer_type(
cast_new_type(CAST_TYPE_VOID));
this_param->index = newparms;
newparms++;
/*
* Initialize the environment reference type and index. The default is
* for the environment reference not to appear. We set the CAST type
* anyway for the possible benefit of derived presentation generators.
*/
this_param = &(specials->params[stub_special_params::environment_ref]);
this_param->name =
/*
* XXX --- Don't use `name' until `pg_corba::p_get_
* exception_discrim_name' et al. have access to the operation
* name, too.
*/
calc_client_stub_environment_param_name("");
this_param->ctype = cast_new_type_name(
/*
* XXX --- Don't use `name' until `pg_corba::p_get_env_
* struct_type' has access to the operation name, too.
*/
calc_client_stub_environment_type_name(""));
this_param->index = -1;
/* Finally, we're done! */
return newparms;
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1