/*
* 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 <assert.h>
#include <string.h>
#include <stdlib.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"
#define FLICK_CLIENT_SKEL_TYPE_NAME "flick_dispatch_t"
#define FLICK_SERVER_SKEL_TYPE_NAME "flick_dispatch_t"
/* Generate server skeleton stub presentation for an AOI interface. */
int pg_state::p_skel(aoi_interface * /*ai*/)
{
pres_c_skel *skel;
char *skel_name;
int skel_index;
aoi_ref saved_parent_ref, saved_derived_ref;
/* Save the original name context for when we return. */
char *old_name = name;
/*
* Set the `pg_state' interface reference data members to point at the
* interfaces under consideration so that `pg_state::calc_name' can
* compute names.
*/
saved_parent_ref = parent_interface_ref;
saved_derived_ref = derived_interface_ref;
parent_interface_ref = cur_aoi_idx;
derived_interface_ref = cur_aoi_idx;
/* Allocate a PRES_C_STUB for this interface. */
skel_index = p_add_stub(out_pres);
/*
* Initialize the skeleton.
* Prepare the skeleton name.
* Set `skel->c_def' to the C declaration for this skeleton.
*/
if (gen_server) {
s(skel_index).kind = PRES_C_SERVER_SKEL;
skel = &s(skel_index).pres_c_stub_u.sskel;
skel_name = calc_server_skel_name("");
skel->c_def = p_skel_cdef(skel_name,
FLICK_SERVER_SKEL_TYPE_NAME);
} else {
s(skel_index).kind = PRES_C_CLIENT_SKEL;
skel = &s(skel_index).pres_c_stub_u.cskel;
skel_name = calc_client_skel_name("");
skel->c_def = p_skel_cdef(skel_name,
FLICK_CLIENT_SKEL_TYPE_NAME);
}
out_pres->stubs_cast.cast_scope_val[skel->c_def].
channel = ch(cur_aoi_idx, PG_CHANNEL_SERVER_IMPL);
name = skel_name;
/*
* Set `skel->request_itype' and `skel->reply_itype' to the top-level
* MINT message union.
*/
skel->request_itype = top_union;
skel->reply_itype = top_union;
/* Generate presentations for the work functions. */
skel->funcs.funcs_len = 0;
skel->funcs.funcs_val = 0;
p_skel_internal(cur_aoi_idx, cur_aoi_idx, skel_index);
/* Restore the name context */
name = old_name;
/*
* Finally, restore the `pg_state' AOI interface references that we
* changed previously.
*/
parent_interface_ref = saved_parent_ref;
derived_interface_ref = saved_derived_ref;
return( skel_index );
}
void pg_state::p_skel_internal(aoi_ref this_ref,
aoi_ref derived_ref,
int skel_index)
{
aoi_interface *this_interface, *derived_interface;
pres_c_skel *skel;
aoi_ref saved_parent_ref, saved_derived_ref;
aoi_ref saved_cur_idx;
if (gen_server)
skel = &s(skel_index).pres_c_stub_u.sskel;
else
skel = &s(skel_index).pres_c_stub_u.cskel;
u_int ops_len;
#ifdef ATTRIBUTE_STUBS
u_int attribs_len;
#endif /* ATTRIBUTE_STUBS */
u_int parents_len;
u_int i;
int flags;
pres_c_func *funcs;
u_int funcs_size;
u_int funcs_count;
/*
* Set `this_interface' and `derived_interface' to point at the AOI
* interfaces under consideration. We also save the cur_aoi_idx
* so that we can generate the proper names when
* server_funcs_for_inherited_operations == 0.
*/
assert((this_ref >= 0)
&& (this_ref < ((aoi_ref) in_aoi->defs.defs_len)));
assert(a(this_ref).binding
&& (a(this_ref).binding->kind == AOI_INTERFACE));
this_interface = &(a(this_ref).binding->aoi_type_u_u.interface_def);
assert((derived_ref >= 0)
&& (derived_ref < ((aoi_ref) in_aoi->defs.defs_len)));
assert(a(derived_ref).binding
&& (a(derived_ref).binding->kind == AOI_INTERFACE));
derived_interface = &(a(derived_ref).binding->aoi_type_u_u.
interface_def);
saved_cur_idx = cur_aoi_idx;
if( !server_funcs_for_inherited_operations )
cur_aoi_idx = this_ref;
/*
* Set the `pg_state' interface reference data members to point at the
* interfaces under consideration so that `pg_state::calc_name' can
* compute names.
*/
saved_parent_ref = parent_interface_ref;
saved_derived_ref = derived_interface_ref;
parent_interface_ref = this_ref;
/*
* If we aren't supposed to generate separate server funcs then
* we set it to the current interface to fake out calc_name
*/
if( server_funcs_for_inherited_operations )
derived_interface_ref = derived_ref;
else
derived_interface_ref = this_ref;
/* Get the lengths of arrays that are part of `this_interface'. */
ops_len = this_interface->ops.ops_len;
#ifdef ATTRIBUTE_STUBS
attribs_len = this_interface->attribs.attribs_len;
#endif
parents_len = this_interface->parents.parents_len;
/*
* Count the number of server functions that we might generate as part
* of `this_interface' and allocate a vector to hold the PRES_C stubs.
*/
funcs_size = ops_len;
#ifdef ATTRIBUTE_STUBS
for (i = 0; i < attribs_len; i++)
funcs_size +=
((this_interface->attribs.attribs_val[i].readonly) ?
1 : /* Read-only attributes result in one stub. */
2); /* Read/write attributes result in two. */
#endif /* ATTRIBUTE_STUBS */
funcs = (pres_c_func *)
mustmalloc(sizeof(pres_c_func) * funcs_size);
funcs_count = 0;
/* Generate the send message function for asynchronous messages. */
if (async_stubs && derived_interface == this_interface) {
p_send_stub(derived_interface, 1 /* request */);
p_send_stub(derived_interface, 0 /* reply */);
p_continue_func_types(derived_interface);
}
/*
* Generate the stubs for the operations defined by `this_interface',
* which are inherited by `derived_interface'.
*/
for (i = 0; i < ops_len; ++i) {
aoi_operation *ao = &(this_interface->ops.ops_val[i]);
/*
* We must check if we have already generated a stub for this
* (interface, operation) pair. This may occur, for example,
* when `this_interface' is inherited through multiple paths
* to `derived_interface'.
*/
flags = p_interface_table_get_value(derived_interface, ao);
if (!(flags & P_SERVER_SKEL_OP_MARK)) {
p_interface_table_set_value(derived_interface, ao,
(flags
| P_SERVER_SKEL_OP_MARK));
/*
* Generate message m/u and continuation stubs
* for the server side.
* (Client side is done in p_client_stub.)
*/
if (async_stubs) {
if (gen_server) {
p_message_marshal_stub(
derived_interface, ao,
0 /* server */,
1 /* request */);
p_message_marshal_stub(
derived_interface, ao,
0 /* server */,
0 /* reply */);
p_continue_stub(derived_interface, ao,
1 /* request */);
/*
* p_message_marshal_stub() and
* p_continue_stub() make new stubs,
* and can thus realloc the stubs
* list. Here we reset sskel to point
* to the reallocated list.
*/
skel = &s(skel_index).pres_c_stub_u.
sskel;
}
funcs[funcs_count] =
p_receive_func(derived_interface, ao,
((gen_server) ?
1 /* request */ :
0 /* reply */));
/*
* Make sure a func was made.
* (``oneway'' ops will not generate a func.)
*/
if (funcs[funcs_count].kind != -1)
funcs_count++;
} else {
funcs[funcs_count++] =
p_server_func(derived_interface, ao);
}
}
}
#ifdef ATTRIBUTE_STUBS
/*
* Generate the stubs for the attributes defined by `this_interface',
* which are inherited by `derived_interface'.
*/
for (i = 0; i < attribs_len; ++i) {
aoi_attribute *aa = &(this_interface->attribs.attribs_val[i]);
/*
* As above, we must screen out attributes that we have already
* processed.
*/
flags = p_interface_table_get_value(derived_interface, aa);
if (!(flags & P_SERVER_SKEL_OP_MARK)) {
p_interface_table_set_value(derived_interface, aa,
(flags
| P_SERVER_SKEL_OP_MARK));
funcs[funcs_count++] =
p_server_attrib_func(derived_interface,
aa,
/* XXX: READ */);
if (!(aa->readonly))
funcs[funcs_count++] =
p_server_attrib_func(derived_interface,
aa,
/* XXX: WRITE */);
}
}
#endif /* ATTRIBUTE_STUBS */
/* Incorporate the work functions that we just made into `skel'. */
if (funcs_count > 0) {
skel->funcs.funcs_val =
(pres_c_func *)
mustrealloc(skel->funcs.funcs_val,
(sizeof(pres_c_func)
* (skel->funcs.funcs_len
+ funcs_count)));
for (i = 0; i < funcs_count; ++i)
skel->funcs.funcs_val[i + skel->funcs.funcs_len] =
funcs[i];
skel->funcs.funcs_len += funcs_count;
}
free(funcs);
/*
* Generate the stubs for the operations and attributes that are
* inherited from parents of `this_interface'.
*/
for (i = 0; i < parents_len; ++i) {
aoi_type parent_val = this_interface->parents.parents_val[i];
aoi_ref parent_ref;
aoi_interface *parent_interface;
/*
* All parent references must be through indirects so that
* we can find the name to go with the parent interface!
*/
assert(parent_val->kind == AOI_INDIRECT);
parent_ref = aoi_deref_fwd(in_aoi, parent_val->
aoi_type_u_u.indirect_ref);
assert(parent_ref != -1);
parent_interface = &(a(parent_ref).binding->aoi_type_u_u.
interface_def);
/*
* As above, we check to see if we've already processed this
* parent. (If we didn't do this check we would still generate
* correct code because all of the parent's operations and
* attributes are marked separately. But doing this check can
* save us time.)
*/
flags = p_interface_table_get_value(derived_interface,
parent_interface);
if (!(flags & P_SERVER_SKEL_PARENT_MARK)) {
p_interface_table_set_value(
derived_interface,
parent_interface,
(flags | P_SERVER_SKEL_PARENT_MARK));
p_skel_internal(parent_ref,
derived_ref,
skel_index);
}
}
/* NOTE: The recursive call to p_skel_internal() may invalidate the
variable ``skel''. */
/* Let the presentation generator add its own server functions */
if (gen_server)
p_add_builtin_server_func(this_interface,
a(cur_aoi_idx).name,
&s(skel_index).pres_c_stub_u.sskel);
/*
* Finally, restore the `pg_state' AOI interface references that we
* changed previously.
*/
cur_aoi_idx = saved_cur_idx;
parent_interface_ref = saved_parent_ref;
derived_interface_ref = saved_derived_ref;
}
/***** Auxiliary functions. *****/
/*
* `p_skel_cdef' allocates and returns an index to the CAST declaration
* of a skeleton (a.k.a. a client or server dispatch function).
*/
cast_ref pg_state::p_skel_cdef(const char *skel_name,
const char *skel_type_name)
{
cast_ref cdef;
cast_ref skel_cref = cast_add_def((cast_scope *)top_ptr(scope_stack),
cast_new_scoped_name(skel_name,
NULL),
CAST_SC_EXTERN,
CAST_VAR_DECL,
ch(cur_aoi_idx,
PG_CHANNEL_SERVER_DECL),
current_protection);
cast_def *skel_cdef = &(((cast_scope *)top_ptr(scope_stack))->
cast_scope_val[skel_cref]);
skel_cdef->u.cast_def_u_u.var_type =
cast_new_type_name(skel_type_name);
cdef = cast_add_def(
&out_pres->stubs_cast,
gen_server ? calc_server_skel_scoped_name(cur_aoi_idx,
skel_name) :
calc_client_skel_scoped_name(cur_aoi_idx,
skel_name),
CAST_SC_EXTERN,
CAST_VAR_DECL,
ch(cur_aoi_idx, PG_CHANNEL_SERVER_IMPL),
CAST_PROT_NONE);
out_pres->stubs_cast.cast_scope_val[cdef].u = skel_cdef->u;
return cdef;
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1