/*
* Copyright (c) 1995, 1996, 1997, 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 <mom/compiler.h>
#include <mom/c/pfe.hh>
#include <mom/c/libcast.h>
#include <mom/c/libpres_c.h>
#include <assert.h>
#include "private.hh"
/*
* Generate pres_c_inline (pres_c_inline_atom) for an operation parameter.
*/
cast_func_param pg_state::p_param(
aoi_parameter *ap,
int cast_param_index, // NOT a CAST ref!
mint_ref mr,
pres_c_inline request_i,
pres_c_inline reply_i,
int request_mint_struct_slot_index, // NOT a MINT ref!
int reply_mint_struct_slot_index // NOT a MINT ref!
)
{
cast_type param_ctype;
pres_c_mapping param_map;
char *old_name;
cast_func_param res;
/* Some initial assertions and local variable assignments. */
assert(request_i->kind == PRES_C_INLINE_FUNC_PARAMS_STRUCT);
assert(reply_i->kind == PRES_C_INLINE_FUNC_PARAMS_STRUCT);
/* Save the original name context. */
old_name = name;
name = calc_stub_param_name(ap->name);
/* Set the parameter name. */
res.name = name;
/* Set the parameter type. */
p_param_type(ap->type, mr, ap->direction, ¶m_ctype, ¶m_map);
res.type = param_ctype;
res.spec = 0;
res.default_value = 0;
/* Add the parameter to the request inline struct if appropriate. */
if ((ap->direction == AOI_DIR_IN) ||
(ap->direction == AOI_DIR_INOUT)) {
int inline_slot_index
= pres_c_add_inline_struct_slot(request_i);
request_i->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
mint_struct_slot_index
= request_mint_struct_slot_index;
request_i->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
inl
= pres_c_new_inline_atom(cast_param_index, param_map);
}
if ((ap->direction == AOI_DIR_OUT)
&& gen_server) {
/*
*
*/
pres_c_mapping alloc_map;
p_param_server_alloc_out(param_ctype, mr, param_map,
&alloc_map);
if (alloc_map != 0) {
int inline_slot_index
= pres_c_add_inline_struct_slot(request_i);
request_i->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
mint_struct_slot_index
= mint_slot_index_null;
request_i->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
inl
= pres_c_new_inline_atom(cast_param_index,
alloc_map);
}
}
/* Add the parameter to the reply inline struct if appropriate. */
if ((ap->direction == AOI_DIR_INOUT) ||
(ap->direction == AOI_DIR_OUT)) {
int inline_slot_index
= pres_c_add_inline_struct_slot(reply_i);
reply_i->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
mint_struct_slot_index
= reply_mint_struct_slot_index;
reply_i->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
inl
= pres_c_new_inline_atom(cast_param_index, param_map);
}
/* Restore the name context. */
name = old_name;
return res;
}
/*
* Generate pres_c_inline (pres_c_inline_atom) for an operation parameter.
* (asynchronous message marshal/unmarshal stub version)
*/
cast_func_param pg_state::p_async_param(
aoi_parameter *ap,
int cast_param_index, // NOT a CAST ref!
mint_ref mr,
pres_c_inline inl,
int mint_struct_slot_index, // NOT a MINT ref!
int encode, // 1=encode, 0=decode
int request // 1=request, 0=reply
)
{
cast_type param_ctype;
pres_c_mapping param_map;
char *old_name;
cast_func_param res;
/* Some initial assertions and local variable assignments. */
assert(inl->kind == PRES_C_INLINE_FUNC_PARAMS_STRUCT);
/* Save the original name context. */
old_name = name;
name = calc_stub_param_name(ap->name);
/* Set the parameter name. */
res.name = name;
res.type = 0;
res.spec = 0;
res.default_value = 0;
/* Add the parameter to the inline struct if appropriate. */
if ((request
&& ((ap->direction == AOI_DIR_IN)
|| (ap->direction == AOI_DIR_INOUT)))
|| (!request
&& ((ap->direction == AOI_DIR_INOUT) ||
(ap->direction == AOI_DIR_OUT)))) {
/* Set the parameter type. */
p_async_param_type(ap->type, mr, ap->direction,
¶m_ctype, ¶m_map, encode);
int inline_slot_index
= pres_c_add_inline_struct_slot(inl);
inl->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
mint_struct_slot_index
= mint_struct_slot_index;
inl->pres_c_inline_u_u.func_params_i.slots.
slots_val[inline_slot_index].
inl
= pres_c_new_inline_atom(cast_param_index, param_map);
res.type = param_ctype;
}
/* Restore the name context. */
name = old_name;
return res;
}
/*
* Generate pres_c_inline (pres_c_inline_atom) that presents an operation
* return value as a parameter of an asynchronous message marshal/unmarshal
* stub.
*/
cast_func_param pg_state::p_async_param_return(
const char *param_name,
aoi_type param_aoi_type,
int cast_param_index, // NOT a CAST ref!
mint_ref mr,
pres_c_inline inl,
int mint_struct_slot_index, // NOT a MINT ref!
int encode, // 1=encode, 0=decode
int request // 1=request, 0=reply
)
{
cast_type param_ctype;
pres_c_mapping param_map;
char *old_name;
pres_c_inline_struct_slot *return_struct_slot;
cast_func_param res;
/* Some initial assertions and local variable assignments. */
assert(inl->kind == PRES_C_INLINE_FUNC_PARAMS_STRUCT);
/* Save the original name context. */
old_name = name;
name = pg_state_name_strlit(param_name);
if (request) {
/*
* The return value does not appear in the request message.
*/
res.name = 0;
res.type = 0;
res.default_value = 0;
res.spec = 0;
/*
* Since the return value is not part of the message, we must
* clear the `return_slot' of the `inline_func_params_struct'
* that we were given.
*/
inl->pres_c_inline_u_u.func_params_i.return_slot = 0;
} else {
/*
* The return value is a component of the reply message.
*/
/* Determine the return parameter type and mapping. */
p_async_param_return_type(param_aoi_type, mr,
¶m_ctype, ¶m_map, encode);
/*
* The return parameter mapping goes into an `inline_atom',
* which in turn goes into the `return_slot' of the `inl' we
* were given.
*/
return_struct_slot = (pres_c_inline_struct_slot *)
mustmalloc(
sizeof(pres_c_inline_struct_slot)
);
return_struct_slot->mint_struct_slot_index
= mint_struct_slot_index;
/* XXX --- Should `cast_find_typedef_type' here. */
if (param_ctype->kind == CAST_TYPE_VOID) {
/*
* Special case: the return type is void. In this
* case, we don't make a function parameter to hold the
* return value. Additionally, we make a special
* inline atom that refers the (void) function return
* value in the inline state constructed by the BE.
*/
return_struct_slot->inl
= pres_c_new_inline_atom(
pres_c_func_return_index,
param_map);
res.name = 0;
res.type = 0;
res.default_value = 0;
res.spec = 0;
} else {
/*
* Normal case: we present our return value as a
* function parameter.
*/
return_struct_slot->inl
= pres_c_new_inline_atom(cast_param_index,
param_map);
res.name = ir_strlit(param_name);
res.type = param_ctype;
res.default_value = 0;
res.spec = 0;
}
/*
* Insert the PRES_C for handling the return value into the
* `return_slot' of the overall `inline_func_params_struct'.
*/
inl->pres_c_inline_u_u.func_params_i.return_slot
= return_struct_slot;
}
/* Restore the name context. */
name = old_name;
return res;
}
/*
* Generate pres_c_inline for a client SID parameter.
*/
void pg_state::p_param_client_sid(int param_index,
pres_c_inline request_inline)
{
pres_c_mapping param_map;
int slot_index;
/* Make the PRES_C mapping for the client SID. */
param_map = pres_c_new_mapping(PRES_C_MAPPING_SID);
param_map->pres_c_mapping_u_u.sid.kind = PRES_C_SID_CLIENT;
/* Tell the back end that this is the ``root'' of the parameter. */
pres_c_interpose_param_root(¶m_map, 0, 0);
/*
* Now make an inline atom containing our SID's mapping, and add that
* atom to the request inline structure.
*
* By setting our `mint_struct_slot_index' to `mint_slot_index_null',
* we indicate that this SID parameter has no representation in the
* MINT structure that describes the request message. That is, the SID
* is outside of the IDL-specified interface.
*/
slot_index = pres_c_add_inline_struct_slot(request_inline);
request_inline->pres_c_inline_u_u.struct_i.slots.slots_val[slot_index].
mint_struct_slot_index
= mint_slot_index_null;
request_inline->pres_c_inline_u_u.struct_i.slots.slots_val[slot_index].
inl
= pres_c_new_inline_atom(param_index, param_map);
}
/*
* Generate pres_c_inline for a required server SID parameter.
*/
void pg_state::p_param_required_server_sid(int param_index,
pres_c_inline request_inline)
{
pres_c_mapping param_map;
int slot_index;
/* Make the PRES_C mapping for the server SID. */
param_map = pres_c_new_mapping(PRES_C_MAPPING_SID);
param_map->pres_c_mapping_u_u.sid.kind = PRES_C_SID_SERVER;
/* Tell the back end that this is the ``root'' of the parameter. */
pres_c_interpose_param_root(¶m_map, 0, 0);
/*
* Now make an inline atom containing our SID's mapping, and add that
* atom to the request inline structure.
*
* By setting our `mint_struct_slot_index' to `mint_slot_index_null',
* we indicate that this SID parameter has no representation in the
* MINT structure that describes the request message. That is, the SID
* is outside of the IDL-specified interface.
*/
slot_index = pres_c_add_inline_struct_slot(request_inline);
request_inline->pres_c_inline_u_u.struct_i.slots.slots_val[slot_index].
mint_struct_slot_index
= mint_slot_index_null;
request_inline->pres_c_inline_u_u.struct_i.slots.slots_val[slot_index].
inl
= pres_c_new_inline_atom(param_index, param_map);
}
/*
* Generate pres_c_inline for an actual server SID parameter.
*/
void pg_state::p_param_actual_server_sid(int param_index,
pres_c_inline reply_inline)
{
pres_c_mapping param_map;
int slot_index;
/* Make the PRES_C mapping for the server SID. */
param_map = pres_c_new_mapping(PRES_C_MAPPING_SID);
param_map->pres_c_mapping_u_u.sid.kind = PRES_C_SID_SERVER;
/* Tell the back end that this is the ``root'' of the parameter. */
pres_c_interpose_param_root(¶m_map, 0, 0);
/*
* Now make an inline atom containing our SID's mapping, and add that
* atom to the reply inline structure.
*
* By setting our `mint_struct_slot_index' to `mint_slot_index_null',
* we indicate that this SID parameter has no representation in the
* MINT structure that describes the request message. That is, the SID
* is outside of the IDL-specified interface.
*/
slot_index = pres_c_add_inline_struct_slot(reply_inline);
reply_inline->pres_c_inline_u_u.struct_i.slots.slots_val[slot_index].
mint_struct_slot_index
= mint_slot_index_null;
reply_inline->pres_c_inline_u_u.struct_i.slots.slots_val[slot_index].
inl
= pres_c_new_inline_atom(param_index, param_map);
}
/*****************************************************************************/
/***** Auxiliary functions. *****/
/* This method determines how `p_param' processes a parameter type.
Some presentation generators override this method. */
void pg_state::p_param_type(aoi_type at, mint_ref /*mr*/, aoi_direction dir,
cast_type *out_ctype, pres_c_mapping *out_mapping)
{
p_type_collection *ptc = 0;
p_type_node *ptn;
/*
* The default behavior is to:
* (1) call `p_type' to compute the basic C type and PRES_C mapping;
* (2) interpose a pointer for `inout' and `out' parameters; and
* (3) encapsulate the mapping with information about the parameter
* direction.
*/
p_type(at, &ptc);
ptn = ptc->find_type("definition");
*out_ctype = ptn->get_type();
*out_mapping = ptn->get_mapping();
if ((dir == AOI_DIR_INOUT) || (dir == AOI_DIR_OUT)) {
// Set up the allocation semantics of the indirection pointer.
pres_c_allocation alloc;
/* Direction is InOut or Out, so other cases are invalid. */
alloc.cases[PRES_C_DIRECTION_UNKNOWN].allow
= PRES_C_ALLOCATION_INVALID;
alloc.cases[PRES_C_DIRECTION_IN].allow
= PRES_C_ALLOCATION_INVALID;
alloc.cases[PRES_C_DIRECTION_RETURN].allow
= PRES_C_ALLOCATION_INVALID;
/*
* This is an indirection pointer:
* Client side never allocs nor deallocs.
* Server side always allocs and deallocs.
*/
alloc.cases[PRES_C_DIRECTION_INOUT].allow
= PRES_C_ALLOCATION_ALLOW;
if (gen_client)
alloc.cases[PRES_C_DIRECTION_INOUT].
pres_c_allocation_u_u.val.flags
= PRES_C_ALLOC_NEVER | PRES_C_DEALLOC_NEVER;
else if (gen_server)
alloc.cases[PRES_C_DIRECTION_INOUT].
pres_c_allocation_u_u.val.flags
= PRES_C_ALLOC_ALWAYS | PRES_C_DEALLOC_ALWAYS;
else
panic("In pg_state::p_param_type: "
"Generating neither client nor server!");
alloc.cases[PRES_C_DIRECTION_INOUT].pres_c_allocation_u_u.
val.allocator.kind = PRES_C_ALLOCATOR_DONTCARE;
alloc.cases[PRES_C_DIRECTION_INOUT].pres_c_allocation_u_u.
val.alloc_init = 0;
/* Out is the same as the InOut case */
alloc.cases[PRES_C_DIRECTION_OUT]
= alloc.cases[PRES_C_DIRECTION_INOUT];
pres_c_interpose_indirection_pointer(out_ctype, out_mapping,
alloc);
}
/* Tell the back end that this is the ``root'' of the parameter. */
pres_c_interpose_param_root(out_mapping, 0, 0);
/* Tell the back end about this parameter's direction. */
pres_c_interpose_direction(out_mapping, dir);
}
/* This method determines how `p_async_param' processes a parameter type.
Some presentation generators override this method. */
void pg_state::p_async_param_type(aoi_type at, mint_ref mr,
aoi_direction dir,
cast_type *out_ctype,
pres_c_mapping *out_mapping,
int encode)
{
p_type_collection *ptc = 0;
p_type_node *ptn;
/*
* The default behavior is to call `p_type' to compute the basic C type
* and PRES_C mapping. If we are decoding the parameter, we also make
* it a pointer (pass-by-reference).
*/
p_type(at, &ptc);
ptn = ptc->find_type("definition");
*out_ctype = ptn->get_type();
*out_mapping = ptn->get_mapping();
if (!encode) {
/*
* The semantics of `in' data is that it lives as long as the
* message in which it is contained. Since the message can
* live on indefinitely, it may be relocated to free up
* precious resources for the network layer (e.g., buffer
* space, Trapeze receive rings, etc.). Further, storage may
* be allocated to hold `in' data, but the user should not be
* forced to free it --- it should automatically be freed when
* the message dies.
*
* To allow for these semantics, we add an extra level of
* indirection, saving the pointer (into the message or to
* allocated space) within the message, and giving the user a
* ``handle'' to the data.
*
* NOTE: This only affects NON-primitive data types.
*/
cast_type ct = cast_find_typedef_type(
(cast_scope *)top_ptr(scope_stack),
*out_ctype);
if (dir == AOI_DIR_IN
&& ct
&& (ct->kind == CAST_TYPE_POINTER
|| ct->kind == CAST_TYPE_ARRAY)) {
/*
* Fix the current CAST_TYPE so it will be allocated
* properly.
*/
if (ct && ct->kind == CAST_TYPE_ARRAY) {
*out_ctype = cast_new_type(CAST_TYPE_POINTER);
(*out_ctype)->cast_type_u_u.pointer_type.target
= ct->cast_type_u_u.array_type.
element_type;
}
if ((*out_mapping)->kind == PRES_C_MAPPING_STUB) {
int stub_idx
= pres_c_find_mu_stub(
out_pres, mr, *out_ctype,
*out_mapping,
PRES_C_UNMARSHAL_STUB);
assert(stub_idx >= 0);
pres_c_mapping map
= (pres_c_mapping)
mustcalloc(sizeof *map);
*map = *(out_pres->
stubs.stubs_val[stub_idx].
pres_c_stub_u.ustub.seethru_map);
*out_mapping = map;
}
#if 0
/*
* XXX - #if 0'ed out because we don't have to dig to
* find the allocation. It's now at a higher level and
* gets set correctly.
*/
pres_c_allocation *alloc = 0;
switch ((*out_mapping)->kind) {
case PRES_C_MAPPING_POINTER:
alloc = &(*out_mapping)->pres_c_mapping_u_u.
pointer.alloc;
break;
case PRES_C_MAPPING_OPTIONAL_POINTER:
alloc = &(*out_mapping)->pres_c_mapping_u_u.
optional_pointer.alloc;
break;
case PRES_C_MAPPING_FIXED_ARRAY:
alloc = &(*out_mapping)->pres_c_mapping_u_u.
fixed_array.alloc;
break;
case PRES_C_MAPPING_TERMINATED_ARRAY:
alloc = &(*out_mapping)->pres_c_mapping_u_u.
terminated_array.alloc;
break;
default:
assert(!"Invalid mapping for pointer/array.");
}
assert(alloc);
/* Force allocation/deallocation of every parameter. */
pres_c_allocation ptr_alloc;
pres_c_allocation_u dfault;
dfault.allow = PRES_C_ALLOCATION_ALLOW;
dfault.pres_c_allocation_u_u.val.flags
= PRES_C_ALLOC_ALWAYS | PRES_C_DEALLOC_ALWAYS;
dfault.pres_c_allocation_u_u.val.allocator.kind
= PRES_C_ALLOCATOR_DONTCARE;
dfault.pres_c_allocation_u_u.val.alloc_init = 0;
ptr_alloc.cases[PRES_C_DIRECTION_UNKNOWN].allow
= PRES_C_ALLOCATION_INVALID;
ptr_alloc.cases[PRES_C_DIRECTION_IN] = dfault;
ptr_alloc.cases[PRES_C_DIRECTION_INOUT] = dfault;
ptr_alloc.cases[PRES_C_DIRECTION_OUT] = dfault;
ptr_alloc.cases[PRES_C_DIRECTION_RETURN] = dfault;
*alloc = ptr_alloc;
#endif
/* Make handle_alloc for message handles. */
pres_c_allocation handle_alloc;
pres_c_allocation_u dfault;
dfault.allow = PRES_C_ALLOCATION_ALLOW;
dfault.pres_c_allocation_u_u.val.flags
= PRES_C_ALLOC_ALWAYS | PRES_C_DEALLOC_ALWAYS;
dfault.pres_c_allocation_u_u.val.allocator.kind
= PRES_C_ALLOCATOR_NAME;
dfault.pres_c_allocation_u_u.val.allocator.
pres_c_allocator_u.name
= ir_strlit("msg_handle");
dfault.pres_c_allocation_u_u.val.alloc_init = 0;
handle_alloc.cases[PRES_C_DIRECTION_UNKNOWN].allow
= PRES_C_ALLOCATION_INVALID;
handle_alloc.cases[PRES_C_DIRECTION_IN] = dfault;
handle_alloc.cases[PRES_C_DIRECTION_INOUT] = dfault;
handle_alloc.cases[PRES_C_DIRECTION_OUT] = dfault;
handle_alloc.cases[PRES_C_DIRECTION_RETURN] = dfault;
/* The ``handle'' to the data. */
pres_c_interpose_indirection_pointer(out_ctype,
out_mapping,
handle_alloc);
}
/*
* One level of pointer indirection for all types. This allows
* unmarshaled data to be returned like an `out' parameter.
*/
pres_c_allocation alloc;
/*
* Direction is `in', `inout', or `out', so other cases are
* invalid.
*/
alloc.cases[PRES_C_DIRECTION_UNKNOWN].allow
= PRES_C_ALLOCATION_INVALID;
alloc.cases[PRES_C_DIRECTION_RETURN].allow
= PRES_C_ALLOCATION_INVALID;
/*
* This is an indirection pointer: never allocated nor
* deallocated.
*/
alloc.cases[PRES_C_DIRECTION_IN].allow
= PRES_C_ALLOCATION_ALLOW;
alloc.cases[PRES_C_DIRECTION_IN].pres_c_allocation_u_u.val.
flags
= (PRES_C_ALLOC_NEVER | PRES_C_DEALLOC_NEVER);
alloc.cases[PRES_C_DIRECTION_IN].pres_c_allocation_u_u.val.
allocator.kind
= PRES_C_ALLOCATOR_DONTCARE;
alloc.cases[PRES_C_DIRECTION_IN].pres_c_allocation_u_u.val.
alloc_init = 0;
/* `inout' and `out' are the same as the `in' case. */
alloc.cases[PRES_C_DIRECTION_INOUT]
= alloc.cases[PRES_C_DIRECTION_IN];
alloc.cases[PRES_C_DIRECTION_OUT]
= alloc.cases[PRES_C_DIRECTION_IN];
pres_c_interpose_indirection_pointer(out_ctype, out_mapping,
alloc);
}
/* Tell the back end that this is the ``root'' of the parameter. */
pres_c_interpose_param_root(out_mapping, 0, 0);
/* Tell the back end about this parameter's direction. */
pres_c_interpose_direction(out_mapping, dir);
}
void pg_state::p_async_param_return_type(aoi_type at, mint_ref /* mr */,
cast_type *out_ctype,
pres_c_mapping *out_mapping,
int encode)
{
p_type_collection *ptc = 0;
p_type_node *ptn;
/*
* The default behavior is to call `p_type' to compute the
* basic C type and PRES_C mapping. If we are decoding the
* parameter, we also make it a pointer (pass-by-reference).
*/
p_type(at, &ptc);
ptn = ptc->find_type("definition");
*out_ctype = ptn->get_type();
*out_mapping = ptn->get_mapping();
/* XXX --- Should `cast_find_typedef_type' here. */
if ((*out_ctype)->kind == CAST_TYPE_VOID) {
/*
* Special case: the return type is void. Set up an `ignore'
* mapping rather than the usual `direct' mapping (although
* either should work).
*/
*out_mapping = pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
} else if (!encode) {
/*
* A return value is presented as an `out' parameter, so we
* don't need all the code from `p_async_param_type' that
* handles `in' data.
*/
pres_c_allocation alloc;
/*
* Direction is `out', so other cases are invalid.
*/
alloc.cases[PRES_C_DIRECTION_UNKNOWN].allow
= PRES_C_ALLOCATION_INVALID;
alloc.cases[PRES_C_DIRECTION_RETURN].allow
= PRES_C_ALLOCATION_INVALID;
alloc.cases[PRES_C_DIRECTION_IN].allow
= PRES_C_ALLOCATION_INVALID;
alloc.cases[PRES_C_DIRECTION_INOUT].allow
= PRES_C_ALLOCATION_INVALID;
/*
* This is an indirection pointer: never allocated nor
* deallocated.
*/
alloc.cases[PRES_C_DIRECTION_OUT].allow
= PRES_C_ALLOCATION_ALLOW;
alloc.cases[PRES_C_DIRECTION_OUT].pres_c_allocation_u_u.val.
flags
= (PRES_C_ALLOC_NEVER | PRES_C_DEALLOC_NEVER);
alloc.cases[PRES_C_DIRECTION_OUT].pres_c_allocation_u_u.val.
allocator.kind
= PRES_C_ALLOCATOR_DONTCARE;
alloc.cases[PRES_C_DIRECTION_OUT].pres_c_allocation_u_u.val.
alloc_init = 0;
pres_c_interpose_indirection_pointer(out_ctype, out_mapping,
alloc);
}
/* Indicate that this is the return value. Some back ends use this. */
pres_c_interpose_argument(out_mapping, "params", "return");
if ((*out_ctype)->kind != CAST_TYPE_VOID) {
/* Tell the BE that this is the ``root'' of the parameter. */
pres_c_interpose_param_root(out_mapping, 0, 0);
}
/* Tell the back end about this parameter's direction. */
pres_c_interpose_direction(out_mapping, AOI_DIR_OUT);
}
/*
* THIS CODE HAS BEEN COPIED INTO `fe/mig/xlate_pres.c' AS
* make_arg_server_alloc_out(). ANY CHANGES SHOULD BE REFLECTED THERE ALSO!
*
* Decide if this is an `out' parameter for which the server must allocate
* storage beyond the root. If so, create an `alloc_mapping' for doing this.
*/
#define DEEP 0
void pg_state::p_param_server_alloc_out(cast_type param_ctype,
mint_ref param_itype,
pres_c_mapping param_mapping,
pres_c_mapping *alloc_mapping)
{
#if DEEP
mint_ref new_itype = mint_ref_null;
#endif
cast_type new_ctype = 0;
pres_c_mapping new_map = 0;
mint_def *idef;
/*****/
*alloc_mapping = 0;
assert(param_itype >= 0);
assert(param_itype < (mint_ref)out_pres->mint.defs.defs_len);
idef = &out_pres->mint.defs.defs_val[param_itype];
switch (param_mapping->kind) {
default:
/*
* By default, we assume that the server dispatch function is
* not required to do anything special beyond allocating the
* ``root'' of the out parameter.
*/
warn("In `p_param_server_alloc_out', "
"unexpected mapping type %d.",
param_mapping->kind);
break;
#if DEEP /* XXX --- These cases are never encountered, at least not now. */
case PRES_C_MAPPING_IGNORE:
case PRES_C_MAPPING_DIRECT:
case PRES_C_MAPPING_REFERENCE:
case PRES_C_MAPPING_MESSAGE_ATTRIBUTE:
case PRES_C_MAPPING_STRUCT:
case PRES_C_MAPPING_SID:
/*
* Handle mappings for values presumably passed by reference.
*
* In these cases, there is nothing for the server dispatch
* function to do but allocate the parameter root.
* Thus, we change the mapping into a MAPPING_IGNORE.
*/
*alloc_mapping = pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
break;
#endif
case PRES_C_MAPPING_POINTER:
/*
* Descend the target mapping.
*/
#if DEEP
if (param_ctype->kind == CAST_TYPE_NAME) {
param_ctype = cast_find_typedef_type(&(out_pres->cast),
param_ctype);
if (!param_ctype)
panic(("In `p_param_server_alloc_out(), can't "
"locate `typedef' for a named type."));
}
assert(param_ctype->kind == CAST_TYPE_POINTER);
new_ctype = param_ctype->cast_type_u_u.pointer_type.target;
p_param_server_alloc_out(new_ctype, param_itype,
(param_mapping->pres_c_mapping_u_u.
pointer.target),
&new_map);
/* Reinsert the pointer. */
assert(new_map);
#else
new_map = pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
*alloc_mapping = pres_c_new_mapping(PRES_C_MAPPING_POINTER);
(*alloc_mapping)->pres_c_mapping_u_u.pointer
= param_mapping->pres_c_mapping_u_u.pointer;
(*alloc_mapping)->pres_c_mapping_u_u.pointer.target
= new_map;
break;
case PRES_C_MAPPING_INTERNAL_ARRAY:
/*
* Descend the element mapping.
*/
#if DEEP
if (param_ctype->kind == CAST_TYPE_NAME) {
param_ctype = cast_find_typedef_type(&(out_pres->cast),
param_ctype);
if (!param_ctype)
panic(("In `p_param_server_alloc_out(), can't "
"locate `typedef' for a named type."));
}
if (param_ctype->kind == CAST_TYPE_POINTER) {
new_ctype = (param_ctype->cast_type_u_u.pointer_type.
target);
} else if (param_ctype->kind == CAST_TYPE_ARRAY) {
new_ctype = (param_ctype->cast_type_u_u.array_type.
element_type);
} else
panic(("In p_param_server_alloc_out(), "
"internal array mapping is not associated with "
"a CAST array or CAST pointer."));
assert(idef->kind == MINT_ARRAY);
new_itype = idef->mint_def_u.array_def.element_type;
p_param_server_alloc_out(new_ctype, param_itype,
(param_mapping->pres_c_mapping_u_u.
internal_array.element_mapping),
&new_map);
/* Reinsert the internal array. */
assert(new_map);
#else
new_map = pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_INTERNAL_ARRAY);
(*alloc_mapping)->pres_c_mapping_u_u.internal_array
= param_mapping->pres_c_mapping_u_u.internal_array;
(*alloc_mapping)->pres_c_mapping_u_u.internal_array.
element_mapping
= new_map;
break;
case PRES_C_MAPPING_VAR_REFERENCE:
/*
* Descend the referent mapping.
*/
#if DEEP
if (param_ctype->kind == CAST_TYPE_NAME) {
param_ctype = cast_find_typedef_type(&(out_pres->cast),
param_ctype);
if (!param_ctype)
panic(("In `p_param_server_alloc_out(), can't "
"locate `typedef' for a named type."));
}
assert(param_ctype->kind == CAST_TYPE_REFERENCE);
new_ctype = param_ctype->cast_type_u_u.reference_type.target;
p_param_server_alloc_out(new_ctype, param_itype,
(param_mapping->pres_c_mapping_u_u.
var_ref.target),
&new_map);
/* Reinsert the reference. */
assert(new_map);
#else
new_map = pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_VAR_REFERENCE);
(*alloc_mapping)->pres_c_mapping_u_u.var_ref
= param_mapping->pres_c_mapping_u_u.var_ref;
(*alloc_mapping)->pres_c_mapping_u_u.var_ref.target
= new_map;
break;
case PRES_C_MAPPING_STUB:
/*
* Descend into the stub's mapping.
*/
new_ctype = param_ctype;
new_map = param_mapping;
pres_descend_mapping_stub(out_pres, param_itype,
&new_ctype, &new_map);
p_param_server_alloc_out(new_ctype, param_itype, new_map,
alloc_mapping);
break;
case PRES_C_MAPPING_XLATE:
/*
* Descend into the translation.
*/
new_ctype = param_mapping->pres_c_mapping_u_u.xlate.
internal_ctype;
new_map = param_mapping->pres_c_mapping_u_u.xlate.
internal_mapping;
p_param_server_alloc_out(new_ctype, param_itype, new_map,
alloc_mapping);
/* Reinsert the translation node. */
#if DEEP
assert(*alloc_mapping);
#else
if (!*alloc_mapping)
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
new_map = pres_c_new_mapping(PRES_C_MAPPING_XLATE);
*new_map = *param_mapping;
new_map->pres_c_mapping_u_u.xlate.internal_mapping
= *alloc_mapping;
*alloc_mapping = new_map;
break;
case PRES_C_MAPPING_DIRECTION:
/*
* Skip past the direction mapping.
*/
p_param_server_alloc_out(param_ctype, param_itype,
(param_mapping->pres_c_mapping_u_u.
direction.mapping),
alloc_mapping);
/* Reinsert the direction node. */
#if DEEP
assert(*alloc_mapping);
#else
if (!*alloc_mapping)
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
new_map = pres_c_new_mapping(PRES_C_MAPPING_DIRECTION);
new_map->pres_c_mapping_u_u.direction
= param_mapping->pres_c_mapping_u_u.direction;
new_map->pres_c_mapping_u_u.direction.mapping
= *alloc_mapping;
*alloc_mapping = new_map;
break;
case PRES_C_MAPPING_ARGUMENT:
/*
* Skip past the argument mapping.
*/
p_param_server_alloc_out(param_ctype, param_itype,
(param_mapping->pres_c_mapping_u_u.
argument.map),
alloc_mapping);
/* Reinsert the argument node. */
#if DEEP
assert(*alloc_mapping);
#else
if (!*alloc_mapping)
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
pres_c_interpose_argument(alloc_mapping,
(param_mapping->
pres_c_mapping_u_u.argument.
arglist_name),
(param_mapping->
pres_c_mapping_u_u.argument.
arg_name));
break;
case PRES_C_MAPPING_PARAM_ROOT:
/*
* Skip past the ``parameter root'' mapping.
*/
new_ctype = param_mapping->pres_c_mapping_u_u.param_root.ctype;
p_param_server_alloc_out(new_ctype ? new_ctype : param_ctype,
param_itype,
(param_mapping->pres_c_mapping_u_u.
param_root.map),
alloc_mapping);
/*
* Reinsert the ``parameter root'' node. This node must always
* be inserted, or else the back end won't notice the parameter
* root at all!
*/
#if DEEP
assert(*alloc_mapping);
#else
if (!(*alloc_mapping))
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
pres_c_interpose_param_root(alloc_mapping, new_ctype,
(param_mapping->pres_c_mapping_u_u.
param_root.init));
break;
case PRES_C_MAPPING_SINGLETON: {
/*
* Skip past the singleton mapping. Unfortunately, this
* returns us to inline mode, and we really aren't prepared to
* handle inlines at this point. The only case that we should
* encounter is a PRES_C_INLINE_ALLOCATION_CONTEXT node, which
* we need to pluck off also, then a PRES_C_INLINE_ATOM in the
* ptr slot that should refer to slot 0 of the singleton, and
* then we can continue looking for the mapping. Phew!
*/
pres_c_inline_allocation_context *ac;
pres_c_inline inl;
assert(param_mapping->pres_c_mapping_u_u.singleton.inl->kind
== PRES_C_INLINE_ALLOCATION_CONTEXT);
ac = ¶m_mapping->pres_c_mapping_u_u.singleton.inl->
pres_c_inline_u_u.acontext;
assert(ac->ptr->kind == PRES_C_INLINE_ATOM);
assert(ac->ptr->pres_c_inline_u_u.atom.index == 0);
/* Go for the *real* mapping. */
p_param_server_alloc_out(param_ctype, param_itype,
(ac->ptr->pres_c_inline_u_u.atom.
mapping),
alloc_mapping);
/* Reinsert a copy of all the junk we just stripped off. */
assert(*alloc_mapping);
inl = pres_c_new_inline(PRES_C_INLINE_ALLOCATION_CONTEXT);
inl->pres_c_inline_u_u.acontext = *ac;
inl->pres_c_inline_u_u.acontext.ptr
= pres_c_new_inline_atom(0, *alloc_mapping);
/* We may also have to do the length mapping. */
if (ac->length->kind == PRES_C_INLINE_ATOM) {
assert(ac->length->pres_c_inline_u_u.atom.index == 0);
p_param_server_alloc_out(param_ctype, param_itype,
(ac->length->
pres_c_inline_u_u.atom.
mapping),
alloc_mapping);
assert(*alloc_mapping);
inl->pres_c_inline_u_u.acontext.length
= pres_c_new_inline_atom(0, *alloc_mapping);
}
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_SINGLETON);
(*alloc_mapping)->pres_c_mapping_u_u.singleton.inl = inl;
break;
}
case PRES_C_MAPPING_TEMPORARY:
/*
* Descend the temporary mapping.
*/
new_ctype = param_mapping->pres_c_mapping_u_u.temp.ctype;
p_param_server_alloc_out(new_ctype, param_itype,
(param_mapping->pres_c_mapping_u_u.
temp.map),
&new_map);
/* Reinsert the temporary. */
#if DEEP
assert(new_map);
#else
if (!new_map)
new_map = pres_c_new_mapping(PRES_C_MAPPING_IGNORE);
#endif
*alloc_mapping
= pres_c_new_mapping(PRES_C_MAPPING_TEMPORARY);
(*alloc_mapping)->pres_c_mapping_u_u.temp
= param_mapping->pres_c_mapping_u_u.temp;
(*alloc_mapping)->pres_c_mapping_u_u.temp.map
= new_map;
break;
}
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1