/*
* 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 <mom/libmint.h>
#include <mom/c/libcast.h>
#include <mom/c/libpres_c.h>
#include "trapeze.h"
struct be_state *get_be_state()
{
return( new trapeze_be_state );
}
trapeze_be_state::trapeze_be_state()
{
this->name = "trapeze";
cast_language = CAST_C;
}
trapeze_protocol_t what_protocol(pres_c_1 *pres)
{
if (strcmp(pres->pres_context, "sun") == 0)
return TRAPEZE_ONC;
return TRAPEZE;
}
trapeze_mu_state::trapeze_mu_state(be_state *_state,
mu_state_op mu_op,
int mu_assumptions,
const char *mu_which,
int swap)
: mem_mu_state(_state, mu_op, mu_assumptions, 2, 0, 120, mu_which)
{
should_swap = swap;
has_payload = 0;
protocol = what_protocol(pres);
}
trapeze_mu_state::trapeze_mu_state(const trapeze_mu_state &must)
: mem_mu_state(must)
{
should_swap = must.should_swap;
has_payload = must.has_payload;
protocol = must.protocol;
}
mu_state *trapeze_mu_state::another(mu_state_op mu_op)
{
return new trapeze_mu_state(state, mu_op, assumptions,
get_which_stub(),
should_swap);
}
mu_state *trapeze_mu_state::clone()
{
return new trapeze_mu_state(*this);
}
trapeze_target_mu_state::trapeze_target_mu_state(be_state *_state,
mu_state_op mu_op,
int mu_assumptions,
const char *mu_which)
: target_mu_state(_state, mu_op, mu_assumptions, mu_which)
{
protocol = what_protocol(pres);
}
trapeze_target_mu_state::trapeze_target_mu_state(
const trapeze_target_mu_state &must)
: target_mu_state(must)
{
protocol = must.protocol;
}
mu_state *trapeze_target_mu_state::clone()
{
return new trapeze_target_mu_state(*this);
}
const char *trapeze_target_mu_state::get_encode_name()
{
const char *name;
switch (protocol) {
case TRAPEZE:
name = "cdr";
break;
case TRAPEZE_ONC:
name = "xdr";
break;
default:
name = "";
panic(("In `trapeze_target_mu_state::get_encode_name', "
"unrecognized protocol specifier."));
break;
}
return name;
}
const char *trapeze_target_mu_state::get_be_name()
{
return "trapeze";
}
trapeze_client_mu_state::trapeze_client_mu_state(be_state *_state,
mu_state_op mu_op,
int mu_assumptions,
const char *mu_which)
: client_mu_state(_state, mu_op, mu_assumptions, mu_which)
{
protocol = what_protocol(pres);
}
trapeze_client_mu_state::trapeze_client_mu_state(
const trapeze_client_mu_state &must)
: client_mu_state(must)
{
protocol = must.protocol;
}
mu_state *trapeze_client_mu_state::clone()
{
return new trapeze_client_mu_state(*this);
}
const char *trapeze_client_mu_state::get_encode_name()
{
const char *name;
switch (protocol) {
case TRAPEZE:
name = "cdr";
break;
case TRAPEZE_ONC:
name = "xdr";
break;
default:
name = "";
panic(("In `trapeze_client_mu_state::get_encode_name', "
"unrecognized protocol specifier."));
break;
}
return name;
}
const char *trapeze_client_mu_state::get_be_name()
{
return "trapeze";
}
const char *trapeze_mu_state::get_encode_name()
{
const char *name;
switch (protocol) {
case TRAPEZE:
if ((should_swap == TRAPEZE_NO_SWAP) || !(op & MUST_DECODE))
name = "cdr";
else
name = "cdr_swap";
break;
case TRAPEZE_ONC:
if ((should_swap == TRAPEZE_NO_SWAP) || !(op & MUST_DECODE))
name = "xdr";
else
name = "xdr_swap";
break;
default:
name = "";
panic(("In `trapeze_mu_state::get_encode_name', "
"unrecognized protocol specifier."));
break;
}
return name;
}
/*
* Return the index of the message word that contains the Trapeze reply token.
* The index is relative to the start of the Trapeze control message data
* buffer (as returned by `tpz_mtod') and is a word index, *not* a byte index.
*
* The position of the reply token depends on the protocol being used, because
* we produce different message headers for each protocol. See the header file
* <flick/link/trapeze.h> for details.
*/
unsigned int trapeze_mu_state::get_replytoken_index()
{
unsigned int index;
switch (protocol) {
case TRAPEZE:
index = 3;
break;
case TRAPEZE_ONC:
index = 7;
break;
default:
index = 0;
panic(("In `trapeze_mu_state::get_replytoken_index', "
"unrecognized protocol specifier."));
break;
}
return index;
}
/*
* Return the number of bytes in the control message buffer that are available
* for message data marshaled by Flick --- i.e., the number of bytes in a
* Trapeze control message data buffer, minus of whatever space is consumed by
* ``magic'' header fields that are not m/u'ed through the back end's normal
* mechanisms for m/u'ing message data. In practice, the ``magic'' header data
* is everything before the operation discriminator.
*
* The amount of data space depends on the protocol being used, because we
* produce different message headers for each protocol. See the header file
* <flick/link/trapeze.h> for details.
*/
unsigned int trapeze_mu_state::get_control_msg_data_size()
{
unsigned int header_words;
switch (protocol) {
case TRAPEZE:
header_words = 2; // Two 4-byte words before Flick does m/u.
break;
case TRAPEZE_ONC:
header_words = 6; // Six 4-byte word before Flick does m/u.
break;
default:
header_words = 0;
panic(("In `trapeze_mu_state::get_control_msg_data_size', "
"unrecognized protocol specifier."));
break;
}
return (TRAPEZE_MAX_CONTROL_SIZE - (header_words * 4));
}
const char *trapeze_mu_state::get_be_name()
{
return "trapeze";
}
const char *trapeze_mu_state::get_mu_stream_name()
{
/*
* XXX - This is completely bogus! The m/u stubs actually don't work
* at all, because we have taken away the stream model, and use local
* vars (which can be optimized into CPU registers). However, m/u
* stubs need the stream abstraction if they are to get anything right.
*/
return "_buf_current";
};
void trapeze_mu_state::mu_server_func(pres_c_inline inl, mint_ref tn_r,
pres_c_server_func *sfunc,
pres_c_skel *sskel)
{
has_payload = 0; /* reset the payload ptr */
mem_mu_state::mu_server_func(inl, tn_r, sfunc, sskel);
}
/* This handles PRES_C_MAPPING_SYSTEM_EXCEPTION nodes,
which are used to opaquely represent system exceptions.
They're opaque, because their presentation varies greatly.
*/
void trapeze_mu_state::mu_mapping_system_exception(cast_expr cexpr,
cast_type /* ctype */,
mint_ref itype)
{
mint_def *idef = &pres->mint.defs.defs_val[itype];
assert(idef->kind == MINT_SYSTEM_EXCEPTION);
/*
* The `mu_state' version of this method breaks the current glob
* because it doesn't know what the presentation-specific macro will
* do. Well, neither do we! But we don't call the presentation macro;
* we call a Trapeze-specific macro that implements our on-the-wire
* encoding of system exceptions, and which translates to/from the
* presented representation.
*
* XXX --- This is along the lines of the solution to PR flick/262.
*/
cast_expr macro
= cast_new_expr_name(
flick_asprintf("flick_%s_%s_system_exception",
get_be_name(),
get_buf_name()
));
cast_expr ofs_cexpr
= cast_new_expr_lit_int(
chunk_prim(TRAPEZE_SYSTEM_EXCEPTION_ALIGN_BITS,
TRAPEZE_SYSTEM_EXCEPTION_BYTES),
0);
cast_expr call_cexpr
= cast_new_expr_call_3(macro,
ofs_cexpr,
cexpr,
cast_new_expr_name(pres->pres_context)
);
add_stmt(cast_new_stmt_expr(call_cexpr));
}
void
w_header_includes(pres_c_1 *pres)
{
trapeze_protocol_t protocol;
protocol = what_protocol(pres);
w_printf("#define FLICK_PROTOCOL_TRAPEZE");
switch (protocol) {
case TRAPEZE:
/* w_printf(""); */
break;
case TRAPEZE_ONC:
w_printf("_ONC");
break;
default:
panic(("In `w_header_includes', "
"unrecognized protocol specifier."));
break;
}
w_printf("\n");
w_printf("#include <flick/link/trapeze.h>\n");
w_printf("#include <flick/encode/");
switch (protocol) {
case TRAPEZE:
w_printf("cdr.h");
break;
case TRAPEZE_ONC:
w_printf("xdr.h");
break;
default:
panic(("In `w_header_includes', "
"unrecognized protocol specifier."));
break;
}
w_printf(">\n");
}
/*
* Replace the operation identifier with a sequentially numbered
* constant value. This reduces the overhead of [un]marshaling an
* unbounded array for the operation name.
*/
void replace_operation_ids(pres_c_1 *pres,
mint_ref itype,
pres_c_inline inl)
{
static int counter = 0;
assert(pres->mint.defs.defs_val[itype].kind == MINT_UNION);
mint_union_def *udef = &(pres->mint.defs.defs_val[itype].mint_def_u.
union_def);
assert(inl->kind == PRES_C_INLINE_COLLAPSED_UNION);
pres_c_inline_collapsed_union *cuinl
= &(inl->pres_c_inline_u_u.collapsed_union);
/* Find the appropriate case. */
mint_ref case_var_r;
for (int case_num = 0; ; case_num++) {
if (case_num >= (signed int) udef->cases.cases_len) {
if (udef->dfault == mint_ref_null)
panic("union collapsed on nonexistent case");
case_var_r = udef->dfault;
break;
}
/* replace the mint_const here with a manufactured
constant integer, so we don't have to [un]marshal
an unbounded array -- just a 4-byte int! */
if (mint_const_cmp(udef->cases.cases_val[case_num].val,
cuinl->discrim_val) == 0) {
if (cuinl->discrim_val->kind != MINT_CONST_INT) {
mint_const myconst =
mint_new_const_int(counter++);
cuinl->discrim_val = myconst;
udef->cases.cases_val[case_num].val = myconst;
udef->discrim =
pres->mint.standard_refs.signed32_ref;
}
break;
}
}
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1