/*
* 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 <mom/compiler.h>
#include <mom/c/libcast.h>
#include "iiop.h"
void w_msg_marshal_stub(pres_c_1 *pres, int stub_idx)
{
pres_c_msg_marshal_stub *stub;
cast_stmt stub_body;
struct mu_abort_block *mab;
cast_stmt reaper_label;
/* Find the `pres_c_msg_marshal_stub' that describes this stub. */
assert(pres);
assert(pres->stubs.stubs_val[stub_idx].kind
== PRES_C_MESSAGE_MARSHAL_STUB);
stub = &(pres->stubs.stubs_val[stub_idx].pres_c_stub_u.mmstub);
/* Find the CAST declaration of this stub. */
assert(stub->c_func >= 0);
assert(stub->c_func < (signed int)pres->stubs_cast.cast_scope_len);
cast_def *cfunc = &(pres->stubs_cast.cast_scope_val[stub->c_func]);
assert(cfunc->u.kind == CAST_FUNC_DECL);
cast_func_type *cfunct = &cfunc->u.cast_def_u_u.func_type;
assert(cfunct->return_type->kind != CAST_TYPE_VOID);
emergency_return_value = cast_new_expr_name("return _return");
mint_ref operation_itype;
pres_c_inline operation_inline;
/* Build the parameter marshal/unmarshal code. */
iiop_mu_state must(the_state,
(MUST_ENCODE | MUST_DEALLOCATE
| ((stub->request)? MUST_REQUEST
: MUST_REPLY)),
RPCM_TRUSTED,
"msg");
reaper_label = cast_new_label(
"_flick_reaper",
cast_new_stmt_expr(emergency_return_value));
mab = new mu_abort_block();
mab->set_kind(MABK_THREAD);
mab->begin();
/* Start the abort code */
mab->add_stmt(
cast_new_stmt_expr(
cast_new_expr_call_3(
cast_new_expr_name(
flick_asprintf(
"flick_%s_%s_error",
pres->pres_context,
must.which_stub)),
cast_new_expr_name(must.get_encode_name()),
cast_new_expr_name(must.get_be_name()),
cast_new_expr_name(mab->
use_current_label()))));
/*
* Set up the argument list to catch the parameter names we need.
* We actually don't need them here, but we must create places
* for them so the code generator can set them correctly.
*/
must.arglist = new mu_state_arglist("params");
must.arglist->add("params", "object");
must.arglist->add("params", "environment");
must.arglist->add("params", "return");
must.arglist->add("params", "invocation_id");
must.arglist->add("params", "client");
must.arglist->add("params", "message");
must.abort_block = mab;
/*
* Strip away the ``collapsed_union'' that represents the IDL
* and interface. IIOP doesn't require this information.
*/
remove_idl_and_interface_ids(pres,
stub->itype, stub->i,
&operation_itype, &operation_inline);
/* The reply doesn't need the operation ID either. */
if (!stub->request || !stub->client) {
remove_operation_id(pres,
operation_itype, operation_inline,
&operation_itype, &operation_inline);
}
must.mu_func_params(stub->c_func,
operation_itype, operation_inline);
must.mu_end();
/* Create the CAST body of the stub. */
if (must.c_block
&& (must.c_block->kind == CAST_STMT_BLOCK))
stub_body = must.c_block;
else {
stub_body = cast_new_block(0, 0);
if (must.c_block)
cast_block_add_stmt(&(stub_body->
cast_stmt_u_u.block),
must.c_block);
}
/* Start writing the stub. */
cast_w_func_type(cfunc->name, cfunct, 0);
w_printf("\n{\n");
w_i_printf(1, "FLICK_BUFFER __stream;\n");
w_i_printf(1, "FLICK_BUFFER *_stream = &__stream;\n");
/*
* Initialize `_return' to be zero. This eliminates compiler
* warnings about returning uninitialized data.
*/
cast_expr init_expr
= cast_new_expr_assign(
cast_new_expr_name("_return"),
cast_new_expr_lit_int(0, 0));
w_indent(1);
cast_w_type(cast_new_scoped_name("_return", NULL),
cfunct->return_type, 1);
w_printf(";\n");
w_printf("\n");
cast_w_stmt(cast_new_stmt_expr(init_expr), 1);
w_i_printf(1,
"flick_%s_msg_start_encode(%d);\n",
must.get_be_name(),
!stub->request);
/* Output the general marshaling code. */
cast_w_stmt(stub_body, 1);
w_i_printf(1,
"flick_%s_msg_end_encode();\n",
must.get_be_name());
w_i_printf(1, "flick_%s_%s_stream_to_msg(_return);\n",
must.get_be_name(),
must.get_buf_name());
/* For the request, set the ``response_expected'' field. */
if (stub->request) {
if (stub->op_flags & PRES_C_STUB_OP_FLAG_ONEWAY) {
w_i_printf(1,
"flick_%s_msg_set_response_expected"
"(0, _return);\n",
must.get_be_name());
} else {
w_i_printf(1,
"flick_%s_msg_set_response_expected"
"(1, _return);\n",
must.get_be_name());
w_i_printf(1,
"flick_%s_msg_set_reply_handler"
"(%s, _return);\n",
must.get_be_name(),
stub->reply_handler_name);
}
w_i_printf(1,
"flick_%s_msg_set_principal_mark(%d, _return);\n",
must.get_be_name(),
must.principal_mark);
}
cast_w_stmt(cast_new_stmt_expr(emergency_return_value), 1);
mab->end();
mab->set_reaper_label(reaper_label);
/* Remove any unneeded abort code */
mab->rollback();
/* write out the abort stuff */
cast_w_stmt(mab->get_block_label(), 1);
cast_w_stmt(reaper_label, 1);
w_printf("}\n\n");
}
void w_msg_unmarshal_stub(pres_c_1 *pres, int stub_idx)
{
pres_c_msg_marshal_stub *stub;
struct mu_abort_block *mab;
cast_stmt reaper_label;
/* Find the `pres_c_msg_marshal_stub' that describes this stub. */
assert(pres);
assert(pres->stubs.stubs_val[stub_idx].kind
== PRES_C_MESSAGE_UNMARSHAL_STUB);
stub = &(pres->stubs.stubs_val[stub_idx].pres_c_stub_u.mustub);
/* Find the CAST declaration of this stub. */
assert(stub->c_func >= 0);
assert(stub->c_func < (signed int)pres->stubs_cast.cast_scope_len);
cast_def *cfunc = &(pres->stubs_cast.cast_scope_val[stub->c_func]);
assert(cfunc->u.kind == CAST_FUNC_DECL);
cast_func_type *cfunct = &cfunc->u.cast_def_u_u.func_type;
assert(cfunct->return_type->kind == CAST_TYPE_VOID);
emergency_return_value = cast_new_expr_name("return");
reaper_label = cast_new_label(
"_flick_reaper",
cast_new_stmt_expr(emergency_return_value));
mab = new mu_abort_block();
mab->set_kind(MABK_THREAD);
mab->begin();
/* Start the abort code */
mab->add_stmt(
cast_new_stmt_expr(
cast_new_expr_call_3(
cast_new_expr_name(
flick_asprintf(
"flick_%s_msg_error",
pres->pres_context)),
cast_new_expr_name("cdr"),
cast_new_expr_name("iiop"),
cast_new_expr_name(mab->
use_current_label()))));
mint_ref operation_itype;
pres_c_inline operation_inline;
/* Build the parameter marshal/unmarshal code. */
iiop_mu_state must(the_state,
(MUST_DECODE | MUST_ALLOCATE
| ((stub->request)? MUST_REQUEST : MUST_REPLY)),
RPCM_TRUSTED, "msg", IIOP_NO_SWAP);
iiop_mu_state swap_must(the_state,
(MUST_DECODE | MUST_ALLOCATE
| ((stub->request)?
MUST_REQUEST : MUST_REPLY)),
RPCM_TRUSTED, "msg", IIOP_SWAP);
/*
* Set up the argument list to catch the parameter names we need.
* We actually don't need them here, but we must create places
* for them so the code generator can set them correctly.
*/
must.arglist = new mu_state_arglist("params");
must.arglist->add("params", "object");
must.arglist->add("params", "environment");
must.arglist->add("params", "return");
must.arglist->add("params", "invocation_id");
must.arglist->add("params", "client");
must.arglist->add("params", "message");
must.abort_block = mab;
must.current_span = new mu_msg_span;
must.current_span->set_kind(MSK_SEQUENTIAL);
must.current_span->begin();
swap_must.arglist = new mu_state_arglist("params");
swap_must.arglist->add("params", "object");
swap_must.arglist->add("params", "environment");
swap_must.arglist->add("params", "return");
swap_must.arglist->add("params", "invocation_id");
swap_must.arglist->add("params", "client");
swap_must.arglist->add("params", "message");
swap_must.abort_block = mab;
swap_must.current_span = new mu_msg_span;
swap_must.current_span->set_kind(MSK_SEQUENTIAL);
swap_must.current_span->begin();
/*
* Set the alignment to 0
* XXX -- We actually can determine the alignment here, if we
* dig through enough information to find the operation length
* added to the known alignment before the operation name, but
* to be simple, just force a runtime alignment.
*/
must.align_bits = 0;
must.align_ofs = 0;
swap_must.align_bits = 0;
swap_must.align_ofs = 0;
/*
* Strip away the ``collapsed_union'' that represents the IDL
* and interface. IIOP doesn't require this information.
*/
remove_idl_and_interface_ids(pres,
stub->itype, stub->i,
&operation_itype, &operation_inline);
/* The reply doesn't need the operation ID either. */
if (!stub->request || !stub->client) {
remove_operation_id(pres,
operation_itype, operation_inline,
&operation_itype, &operation_inline);
}
must.mu_func_params(stub->c_func,
operation_itype, operation_inline);
must.mu_end();
swap_must.mu_func_params(stub->c_func,
operation_itype, operation_inline);
swap_must.mu_end();
/* Collapse the span trees and commit their values */
must.current_span->end();
swap_must.current_span->end();
must.current_span->collapse();
must.current_span->commit();
swap_must.current_span->collapse();
swap_must.current_span->commit();
mab->end();
mab->set_reaper_label(reaper_label);
/* Remove any unneeded abort code */
mab->rollback();
/* Start writing the stub. */
int gotarg = 0;
cast_w_func_type(cfunc->name, cfunct, 0);
w_printf("\n{\n");
w_i_printf(1, "FLICK_BUFFER __stream;\n");
w_i_printf(1, "FLICK_BUFFER *_stream = &__stream;\n");
w_printf("\n");
cast_expr msg_expr;
cast_type msg_type;
gotarg = must.arglist->getargs("params", "message",
&msg_expr, &msg_type);
assert(gotarg);assert(msg_expr);assert(msg_type);
cast_w_stmt(
cast_new_stmt_expr(
cast_new_expr_call_1(
cast_new_expr_name(
flick_asprintf(
"flick_%s_%s_msg_to_stream",
must.get_be_name(),
must.get_buf_name())),
msg_expr)),
1);
cast_w_stmt(
cast_new_stmt_expr(
cast_new_expr_call_1(
cast_new_expr_name(
flick_asprintf(
"flick_%s_msg_start_decode",
must.get_be_name())),
cast_new_expr_lit_int(!stub->request, 0))),
1);
// We need to emit an if (swap) to determine which code is run...
cast_w_stmt(
cast_new_if(
cast_new_expr_call_0(
cast_new_expr_name("flick_cdr_swap")),
swap_must.c_block,
must.c_block),
1);
cast_w_stmt(
cast_new_stmt_expr(
cast_new_expr_call_0(
cast_new_expr_name(
flick_asprintf(
"flick_%s_msg_end_decode",
must.get_be_name())))),
1);
cast_w_stmt(cast_new_stmt_expr(emergency_return_value), 1);
/* write out the abort stuff */
cast_w_stmt(mab->get_block_label(), 1);
cast_w_stmt(reaper_label, 1);
w_printf("}\n\n");
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1