summaryrefslogtreecommitdiff
path: root/trunk/TAO/TAO_IDL/be/be_visitor_ami_pre_proc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/TAO/TAO_IDL/be/be_visitor_ami_pre_proc.cpp')
-rw-r--r--trunk/TAO/TAO_IDL/be/be_visitor_ami_pre_proc.cpp1273
1 files changed, 1273 insertions, 0 deletions
diff --git a/trunk/TAO/TAO_IDL/be/be_visitor_ami_pre_proc.cpp b/trunk/TAO/TAO_IDL/be/be_visitor_ami_pre_proc.cpp
new file mode 100644
index 00000000000..7cb78d6bd37
--- /dev/null
+++ b/trunk/TAO/TAO_IDL/be/be_visitor_ami_pre_proc.cpp
@@ -0,0 +1,1273 @@
+//
+// $Id$
+//
+
+/* -*- c++ -*- */
+// ============================================================================
+//
+// = LIBRARY
+// TAO IDL
+//
+// = FILENAME
+// be_visitor_ami_pre_proc.cpp
+//
+// = DESCRIPTION
+// This visitor creates for AMI implied IDL constructs
+// the appropriate AST (Abstract Syntax Tree) node,
+// sets the corresponding interface or operation strategy
+// on it and enteres the nodes into the AST.
+//
+// = AUTHOR
+// Michael Kircher <Michael.Kircher@mchp.siemens.de>
+//
+// ============================================================================
+
+#include "be_visitor_ami_pre_proc.h"
+#include "be_visitor_context.h"
+#include "be_root.h"
+#include "be_module.h"
+#include "be_interface.h"
+#include "be_interface_strategy.h"
+#include "be_valuetype.h"
+#include "be_operation.h"
+#include "be_operation_strategy.h"
+#include "be_attribute.h"
+#include "be_predefined_type.h"
+#include "be_argument.h"
+#include "be_global.h"
+#include "be_extern.h"
+#include "utl_identifier.h"
+#include "utl_exceptlist.h"
+#include "nr_extern.h"
+#include "global_extern.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID (be,
+ be_visitor_ami_pre_proc,
+ "$Id$")
+
+
+be_visitor_ami_pre_proc::be_visitor_ami_pre_proc (be_visitor_context *ctx)
+ : be_visitor_scope (ctx)
+{
+
+}
+
+be_visitor_ami_pre_proc::~be_visitor_ami_pre_proc (void)
+{
+
+}
+
+int
+be_visitor_ami_pre_proc::visit_root (be_root *node)
+{
+ if (this->visit_scope (node) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "visit_root - "
+ "visit scope failed\n"),
+ -1);
+ }
+
+ return 0;
+}
+
+int
+be_visitor_ami_pre_proc::visit_module (be_module *node)
+{
+ // Skip this for now until we get AMI integrated with
+ // CIAO.
+ if (0 == ACE_OS::strcmp (node->local_name ()->get_string (), "Components"))
+ {
+ return 0;
+ }
+
+ if (this->visit_scope (node) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "visit_module - "
+ "visit scope failed\n"),
+ -1);
+ }
+
+ return 0;
+}
+
+int
+be_visitor_ami_pre_proc::visit_interface (be_interface *node)
+{
+ // We check for an imported node after generating the reply handler.
+ if (node->is_local () || node->is_abstract ())
+ {
+ return 0;
+ }
+
+ // The following 3 IF blocks are checks for CCM-related nodes, which
+ // we want to skip until we get AMI integrated with CIAO.
+
+ // Skip the *EventConsumer added for each eventtype.
+ if (node->is_event_consumer ())
+ {
+ return 0;
+ }
+
+ // Check for home equivalent interface. The lookup will find the
+ // home itself, which was declared first.
+ Identifier *node_lname = node->AST_Decl::local_name ();
+ AST_Decl *first_stored =
+ node->defined_in ()->lookup_by_name_local (node_lname, 0);
+
+ if (0 != first_stored && first_stored->node_type () == AST_Decl::NT_home)
+ {
+ return 0;
+ }
+
+ ACE_CString lname (node_lname->get_string ());
+
+ // Skip the *Explict and *Implicit interfaces added for a home.
+ if (lname.substr (lname.length () - 6) == "plicit")
+ {
+ UTL_Scope *s = node->defined_in ();
+ Identifier local_id (lname.substr (0, lname.length () - 8).c_str ());
+ AST_Decl *d = s->lookup_by_name_local (&local_id, 0);
+ local_id.destroy ();
+
+ if (0 != d)
+ {
+ return 0;
+ }
+ }
+
+ AST_Module *module =
+ AST_Module::narrow_from_scope (node->defined_in ());
+
+ if (!module)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "visit_interface - "
+ "module is null\n"),
+ -1);
+ }
+
+ be_valuetype *excep_holder = this->create_exception_holder (node);
+ be_interface *reply_handler = this->create_reply_handler (node,
+ excep_holder);
+ if (reply_handler)
+ {
+ reply_handler->set_defined_in (node->defined_in ());
+
+ // Insert the ami handler after the node, the
+ // exception holder will be placed between these two later.
+ module->be_add_interface (reply_handler, node);
+
+ // Remember from whom we were cloned
+ reply_handler->original_interface (node);
+
+ // If this was created for an imported node, it will be wrong
+ // unless we set it.
+ reply_handler->set_imported (node->imported ());
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "visit_interface - "
+ "creating the reply handler failed\n"),
+ -1);
+ }
+
+ // Set the proper strategy.
+ be_interface_ami_strategy *bias = 0;
+ ACE_NEW_RETURN (bias,
+ be_interface_ami_strategy (node,
+ reply_handler),
+ -1);
+ be_interface_strategy *old_strategy = node->set_strategy (bias);
+
+ if (old_strategy)
+ {
+ old_strategy->destroy ();
+ delete old_strategy;
+ old_strategy = 0;
+ }
+
+ if (this->visit_scope (node) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "visit_interface - "
+ "visit scope failed\n"),
+ -1);
+ }
+
+ return 0;
+}
+
+int
+be_visitor_ami_pre_proc::visit_operation (be_operation *node)
+{
+ if (node->flags () == AST_Operation::OP_oneway)
+ {
+ // We do nothing for oneways!
+ return 0;
+ }
+
+ // If we're here, we're sure that the arg traits specialization
+ // for this will be needed.
+ be_global->messaging_exceptionholder ()->seen_in_operation (true);
+
+ be_operation *sendc_marshaling =
+ this->create_sendc_operation (node,
+ 0); // for arguments = FALSE
+
+ be_operation *sendc_arguments =
+ this->create_sendc_operation (node,
+ 1); // for arguments = TRUE
+
+ if (0 != sendc_marshaling && 0 != sendc_arguments)
+ {
+ sendc_marshaling->set_defined_in (node->defined_in ());
+
+ sendc_arguments->set_defined_in (node->defined_in ());
+
+ // We do not copy the exceptions because the exceptions
+ // are delivered by the excep methods.
+
+ // Set the proper strategy, and store the specialized
+ // marshaling and arguments operations in it.
+ be_operation_ami_sendc_strategy * boass = 0;
+ ACE_NEW_RETURN (boass,
+ be_operation_ami_sendc_strategy (node,
+ sendc_marshaling,
+ sendc_arguments),
+ -1);
+
+ be_operation_strategy *old_strategy = node->set_strategy (boass);
+
+ if (old_strategy)
+ {
+ old_strategy->destroy ();
+ delete old_strategy;
+ old_strategy = 0;
+ }
+ }
+
+ return 0;
+}
+
+int
+be_visitor_ami_pre_proc::visit_attribute (be_attribute *node)
+{
+ // Temporerily generate the set operation.
+ be_operation *set_operation =
+ this->generate_set_operation (node);
+
+ this->visit_operation (set_operation);
+
+ // Retrieve the strategy set by the visit operation.
+ be_operation_default_strategy *bods = 0;
+ ACE_NEW_RETURN (bods,
+ be_operation_default_strategy (set_operation),
+ -1);
+
+ be_operation_strategy *set_operation_strategy =
+ set_operation->set_strategy (bods);
+
+ set_operation->destroy ();
+ delete set_operation;
+ set_operation = 0;
+
+ // Assign it to the attribute as set_operation strategy.
+ if (0 != set_operation_strategy)
+ {
+ be_operation_strategy *bos =
+ node->set_set_strategy (set_operation_strategy);
+
+ if (0 != bos)
+ {
+ bos->destroy ();
+ delete bos;
+ bos = 0;
+ }
+ }
+
+ // Temporerily generate the get operation.
+ be_operation *get_operation =
+ this->generate_get_operation (node);
+
+ this->visit_operation (get_operation);
+
+ // Retrieve the strategy set by the visit operation.
+ ACE_NEW_RETURN (bods,
+ be_operation_default_strategy (get_operation),
+ -1);
+
+ be_operation_strategy *get_operation_strategy =
+ get_operation->set_strategy (bods);
+
+ get_operation->destroy ();
+ delete get_operation;
+ get_operation = 0;
+
+ // Assign it to the attribute as get_operation strategy.
+ if (0 != get_operation_strategy)
+ {
+ be_operation_strategy *bos =
+ node->set_get_strategy (get_operation_strategy);
+
+ if (0 != bos)
+ {
+ bos->destroy ();
+ delete bos;
+ bos = 0;
+ }
+ }
+
+ return 0;
+}
+
+be_valuetype *
+be_visitor_ami_pre_proc::create_exception_holder (be_interface *)
+{
+ return be_global->messaging_exceptionholder ();
+}
+
+be_interface *
+be_visitor_ami_pre_proc::create_reply_handler (be_interface *node,
+ be_valuetype *excep_holder)
+{
+ // We're at global scope here so we need to fool the scope stack
+ // for a minute so the correct repo id can be calculated at
+ // interface construction time.
+ UTL_Scope *s = node->defined_in ();
+ idl_global->scopes ().push (s);
+
+ // Create the reply handler name.
+ ACE_CString reply_handler_local_name;
+ this->generate_name (reply_handler_local_name,
+ "AMI_",
+ node->name ()->last_component ()->get_string(),
+ "Handler");
+
+ UTL_ScopedName *reply_handler_name =
+ static_cast<UTL_ScopedName *> (node->name ()->copy ());
+ reply_handler_name->last_component ()->replace_string (
+ reply_handler_local_name.c_str ()
+ );
+
+ long n_parents = 0;
+ AST_Interface **p_intf = this->create_inheritance_list (node, n_parents);
+
+ be_interface *reply_handler = 0;
+ ACE_NEW_RETURN (reply_handler,
+ be_interface (reply_handler_name, // name
+ p_intf, // list of inherited
+ n_parents, // number of inherited
+ 0, // list of all ancestors
+ 0, // number of ancestors
+ 0, // non-local
+ 0), // non-abstract
+ 0);
+
+ // Back to reality.
+ idl_global->scopes ().pop ();
+
+ reply_handler->set_name (reply_handler_name);
+ reply_handler->set_defined_in (s);
+
+ // Set repo id to 0, so it will be recomputed on the next access,
+ // and set the prefix to the node's prefix. All this is
+ // necessary in case the node's prefix was modified after
+ // its declaration.
+ reply_handler->AST_Decl::repoID (0);
+ reply_handler->prefix (const_cast<char*> (node->prefix ()));
+
+ reply_handler->gen_fwd_helper_name ();
+
+ // Now our customized reply handler is created, we have to
+ // add the operations and attributes to the scope.
+ // Imported nodes get admitted here, so they can get
+ // the reply handler operations added, in case they are
+ // needed in the inheritance graph traversal for a
+ // child reply handler. However, no exception holder
+ // stuff is executed for an imported node.
+ if (node->nmembers () > 0)
+ {
+ this->elem_number_ = 0;
+ // Initialize an iterator to iterate thru our scope.
+
+ for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ AST_Decl *d = si.item ();
+
+ if (!d)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::visit_interface - "
+ "bad node in this scope\n"),
+ 0);
+
+ }
+
+ if (d->node_type () == AST_Decl::NT_attr)
+ {
+ be_attribute *attribute = be_attribute::narrow_from_decl (d);
+
+ if (attribute == 0)
+ {
+ return 0;
+ }
+
+ be_operation *get_operation =
+ this->generate_get_operation (attribute);
+
+ this->create_reply_handler_operation (get_operation,
+ reply_handler);
+
+ this->create_excep_operation (get_operation,
+ reply_handler,
+ excep_holder);
+
+ get_operation->destroy ();
+ delete get_operation;
+ get_operation = 0;
+
+ if (!attribute->readonly ())
+ {
+ be_operation *set_operation =
+ this->generate_set_operation (attribute);
+
+ this->create_reply_handler_operation (set_operation,
+ reply_handler);
+
+ this->create_excep_operation (set_operation,
+ reply_handler,
+ excep_holder);
+
+ set_operation->destroy ();
+ delete set_operation;
+ set_operation = 0;
+ }
+ }
+ else
+ {
+ be_operation* operation = be_operation::narrow_from_decl (d);
+
+ if (operation)
+ {
+ this->create_reply_handler_operation (operation,
+ reply_handler);
+
+ this->create_excep_operation (operation,
+ reply_handler,
+ excep_holder);
+ }
+ }
+ } // end of while loop
+ } // end of if
+
+ return reply_handler;
+}
+
+int
+be_visitor_ami_pre_proc::create_raise_operation (
+ be_decl *node,
+ be_valuetype *excep_holder,
+ Operation_Kind operation_kind
+ )
+{
+ be_operation *orig_op = 0;
+
+ if (operation_kind == NORMAL)
+ {
+ orig_op = be_operation::narrow_from_decl (node);
+
+ if (orig_op)
+ {
+ if (orig_op->flags () == AST_Operation::OP_oneway)
+ {
+ // We do nothing for oneways!
+ return 0;
+ }
+ }
+ }
+
+ Identifier *id = 0;
+ UTL_ScopedName *sn = 0;
+
+ ACE_NEW_RETURN (id,
+ Identifier ("void"),
+ -1);
+
+ ACE_NEW_RETURN (sn,
+ UTL_ScopedName (id,
+ 0),
+ -1);
+
+ // Create the return type, which is "void"
+ be_predefined_type *rt = 0;
+ ACE_NEW_RETURN (rt,
+ be_predefined_type (AST_PredefinedType::PT_void,
+ sn),
+ -1);
+
+ // Name the operation properly
+ UTL_ScopedName *op_name =
+ static_cast<UTL_ScopedName *> (excep_holder->name ()->copy ());
+
+ ACE_CString new_local_name ("raise_");
+
+ if (operation_kind == SET_OPERATION)
+ {
+ new_local_name += "set_";
+ }
+ else if (operation_kind == GET_OPERATION)
+ {
+ new_local_name += "get_";
+ }
+
+ new_local_name += node->name ()->last_component ()->get_string ();
+
+ ACE_NEW_RETURN (id,
+ Identifier (new_local_name.c_str ()),
+ -1);
+
+ ACE_NEW_RETURN (sn,
+ UTL_ScopedName (id,
+ 0),
+ -1);
+
+ op_name->nconc (sn);
+
+ be_operation *operation = 0;
+ ACE_NEW_RETURN (operation,
+ be_operation (rt,
+ AST_Operation::OP_noflags,
+ op_name,
+ 0,
+ 0),
+ -1);
+
+ operation->set_name (op_name);
+ operation->set_defined_in (excep_holder);
+
+#if defined (TAO_HAS_DEPRECATED_EXCEPTION_HOLDER)
+ if (operation_kind == NORMAL)
+ {
+ if (orig_op)
+ {
+ // Copy the exceptions.
+ UTL_ExceptList *exceptions = orig_op->exceptions ();
+
+ if (0 != exceptions)
+ {
+ operation->be_add_exceptions (exceptions->copy ());
+ }
+ }
+ }
+#endif
+
+ // Set the proper strategy.
+ be_operation_ami_exception_holder_raise_strategy *boaehrs = 0;
+ ACE_NEW_RETURN (boaehrs,
+ be_operation_ami_exception_holder_raise_strategy (operation),
+ -1);
+
+ be_operation_strategy *old_strategy = operation->set_strategy (boaehrs);
+
+ if (old_strategy)
+ {
+ old_strategy->destroy ();
+ delete old_strategy;
+ old_strategy = 0;
+ }
+
+ // After having generated the operation we insert it into the
+ // exceptionholder valuetype.
+ if (0 == excep_holder->be_add_operation (operation))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+be_operation *
+be_visitor_ami_pre_proc::create_sendc_operation (be_operation *node,
+ int for_arguments)
+{
+ if (node->flags () == AST_Operation::OP_oneway)
+ {
+ // We do nothing for oneways!
+ return 0;
+ }
+
+ Identifier *id = 0;
+ UTL_ScopedName *sn = 0;
+
+ // Create the new name
+ // Prepend "sendc_" to the name of the operation
+ ACE_CString original_op_name (
+ node->name ()->last_component ()->get_string ()
+ );
+ ACE_CString new_op_name = ACE_CString ("sendc_") + original_op_name;
+
+ UTL_ScopedName *op_name =
+ static_cast<UTL_ScopedName *> (node->name ()->copy ());
+ op_name->last_component ()->replace_string (new_op_name.c_str ());
+
+ // Create the operation
+ be_operation *op = 0;
+ ACE_NEW_RETURN (op,
+ be_operation (be_global->void_type (),
+ AST_Operation::OP_noflags,
+ op_name,
+ 0,
+ 0),
+ 0);
+
+ op->set_name (op_name);
+
+ // Create the first argument, which is a Reply Handler
+
+ if (for_arguments)
+ {
+ // Look up the field type.
+ UTL_Scope *s = node->defined_in ();
+ be_decl *parent = be_scope::narrow_from_scope (s)->decl ();
+
+ // Add the pre- and suffix
+ ACE_CString handler_local_name;
+ this->generate_name (handler_local_name,
+ "AMI_",
+ parent->name ()->last_component ()->get_string (),
+ "Handler");
+
+ UTL_ScopedName *field_name =
+ static_cast<UTL_ScopedName *> (parent->name ()->copy ());
+ field_name->last_component ()->replace_string (
+ handler_local_name.c_str ()
+ );
+
+ AST_Decl *d = s->lookup_by_name (field_name, true);
+ field_name->destroy ();
+ delete field_name;
+ field_name = 0;
+
+ if (0 == d)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "create_sendc_operation - "
+ "lookup of reply handler failed\n"),
+ 0);
+ }
+
+ be_interface *field_type = be_interface::narrow_from_decl (d);
+
+ // Create the argument.
+ ACE_NEW_RETURN (id,
+ Identifier ("ami_handler"),
+ 0);
+
+ UTL_ScopedName *tmp = 0;
+
+ ACE_NEW_RETURN (tmp,
+ UTL_ScopedName (id,
+ 0),
+ 0);
+
+ sn = (UTL_ScopedName *)op->name ()->copy ();
+ sn->nconc (tmp);
+
+ be_argument *arg = 0;
+ ACE_NEW_RETURN (arg,
+ be_argument (AST_Argument::dir_IN,
+ field_type, // is also a valuetype
+ sn),
+ 0);
+
+ arg->set_defined_in (op);
+ arg->set_name (sn);
+ op->be_add_argument (arg);
+
+ if (field_type->imported ())
+ {
+ field_type->seen_in_operation (false);
+ }
+ }
+
+ // Iterate over the arguments and put all the in and inout
+ // into the new method.
+ if (node->nmembers () > 0)
+ {
+ // initialize an iterator to iterate thru our scope
+ for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ AST_Decl *d = si.item ();
+
+ if (!d)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::create_sendc_method - "
+ "bad node in this scope\n"
+ ),
+ 0
+ );
+
+ }
+
+ AST_Argument *original_arg = AST_Argument::narrow_from_decl (d);
+
+ if (original_arg->direction () == AST_Argument::dir_IN ||
+ original_arg->direction () == AST_Argument::dir_INOUT)
+ {
+ // Create the argument.
+ be_argument *arg = 0;
+ UTL_ScopedName *new_name =
+ (UTL_ScopedName *)original_arg->name ()->copy ();
+ ACE_NEW_RETURN (arg,
+ be_argument (AST_Argument::dir_IN,
+ original_arg->field_type (),
+ new_name),
+ 0);
+
+ arg->set_defined_in (op);
+ arg->set_name (new_name);
+ op->be_add_argument (arg);
+ }
+ } // end of while loop
+ } // end of if
+
+ return op;
+}
+
+int
+be_visitor_ami_pre_proc::create_reply_handler_operation (
+ be_operation *node,
+ be_interface *reply_handler
+ )
+{
+ if (!node)
+ {
+ return -1;
+ }
+
+ if (node->flags () == AST_Operation::OP_oneway)
+ {
+ // We do nothing for oneways!
+ return 0;
+ }
+
+ Identifier *id = 0;
+ UTL_ScopedName *sn = 0;
+
+ ACE_CString original_op_name (
+ node->name ()->last_component ()->get_string ()
+ );
+
+ UTL_ScopedName *op_name =
+ static_cast<UTL_ScopedName *> (reply_handler->name ()-> copy ());
+
+ ACE_NEW_RETURN (id,
+ Identifier (original_op_name.c_str ()),
+ -1);
+
+ ACE_NEW_RETURN (sn,
+ UTL_ScopedName (id,
+ 0),
+ -1);
+
+ op_name->nconc (sn);
+
+ // Create the operation.
+ be_operation *operation = 0;
+ ACE_NEW_RETURN (operation,
+ be_operation (be_global->void_type (),
+ AST_Operation::OP_noflags,
+ op_name,
+ 0,
+ 0),
+ -1);
+
+ operation->set_name (op_name);
+
+ // If return type is non-void add it as first argument.
+
+ if (!node->void_return_type ())
+ {
+ ACE_NEW_RETURN (id,
+ Identifier ("ami_return_val"),
+ -1);
+
+ UTL_ScopedName *tmp = 0;
+
+ ACE_NEW_RETURN (tmp,
+ UTL_ScopedName (id,
+ 0),
+ -1);
+
+ sn = (UTL_ScopedName *)operation->name ()->copy ();
+ sn->nconc (tmp);
+
+ // Create the argument.
+ be_argument *arg = 0;
+ ACE_NEW_RETURN (arg,
+ be_argument (AST_Argument::dir_IN,
+ node->return_type (),
+ sn),
+ -1);
+
+ arg->set_defined_in (operation);
+ arg->set_name (sn);
+
+ // Add the reply handler to the argument list.
+ operation->be_add_argument (arg);
+ }
+
+ // Iterate over the arguments and put all the in and inout
+ // into the new method.
+ if (node->nmembers () > 0)
+ {
+ // Initialize an iterator to iterate thru our scope.
+ for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ AST_Decl *d = si.item ();
+
+ if (d == 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_ami_pre_proc::"
+ "create_reply_handler_operation - "
+ "bad node in this scope\n"),
+ -1);
+
+ }
+
+ AST_Argument *original_arg = AST_Argument::narrow_from_decl (d);
+
+ if (original_arg->direction () == AST_Argument::dir_INOUT ||
+ original_arg->direction () == AST_Argument::dir_OUT)
+ {
+ // Create the argument.
+ be_argument *arg = 0;
+ UTL_ScopedName *new_name =
+ (UTL_ScopedName *)original_arg->name ()->copy ();
+ ACE_NEW_RETURN (arg,
+ be_argument (AST_Argument::dir_IN,
+ original_arg->field_type (),
+ new_name),
+ -1);
+
+ arg->set_defined_in (operation);
+ arg->set_name (new_name);
+ operation->be_add_argument (arg);
+ }
+ } // end of while loop
+ } // end of if
+
+ // Set the proper strategy.
+ be_operation_ami_handler_reply_stub_strategy *boahrss = 0;
+ ACE_NEW_RETURN (boahrss,
+ be_operation_ami_handler_reply_stub_strategy (operation),
+ -1);
+
+ be_operation_strategy *old_strategy = operation->set_strategy (boahrss);
+
+ if (old_strategy)
+ {
+ old_strategy->destroy ();
+ delete old_strategy;
+ old_strategy = 0;
+ }
+
+ operation->set_defined_in (reply_handler);
+
+ // Copy the exceptions.
+ if (node->exceptions ())
+ {
+ UTL_ExceptList *exceptions = node->exceptions ();
+
+ if (0 != exceptions)
+ {
+ operation->be_add_exceptions (exceptions->copy ());
+ }
+ }
+
+ // After having generated the operation we insert it into the
+ // reply handler interface.
+ if (0 == reply_handler->be_add_operation (operation))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+be_visitor_ami_pre_proc::create_excep_operation (be_operation *node,
+ be_interface *reply_handler,
+ be_valuetype *excep_holder)
+{
+ if (!node)
+ {
+ return -1;
+ }
+
+ if (node->flags () == AST_Operation::OP_oneway)
+ {
+ // We do nothing for oneways!
+ return 0;
+ }
+
+ // Create the return type, which is "void".
+ Identifier *id = 0;
+ UTL_ScopedName *sn = 0;
+
+ // Create the argument.
+ ACE_NEW_RETURN (id,
+ Identifier ("excep_holder"),
+ -1);
+
+ ACE_NEW_RETURN (sn,
+ UTL_ScopedName (id,
+ 0),
+ -1);
+
+ be_argument *arg = 0;
+ ACE_NEW_RETURN (arg,
+ be_argument (AST_Argument::dir_IN,
+ excep_holder, // is also a valuetype
+ sn),
+ -1);
+
+ arg->set_name (sn);
+
+ UTL_ScopedName *tmp = (UTL_ScopedName *)sn->copy ();
+
+ // Create the new name
+ // Append _execp to the name of the operation
+ ACE_CString original_op_name (
+ node->name ()->last_component ()->get_string ()
+ );
+ ACE_CString new_op_name = original_op_name + ACE_CString ("_excep");
+
+ UTL_ScopedName *op_name =
+ static_cast<UTL_ScopedName *> (reply_handler->name ()->copy ());
+
+ ACE_NEW_RETURN (id,
+ Identifier (new_op_name.c_str ()),
+ -1);
+
+ ACE_NEW_RETURN (sn,
+ UTL_ScopedName (id,
+ 0),
+ -1);
+
+ op_name->nconc (sn);
+
+ AST_PredefinedType *rt = be_global->void_type ();
+
+ // Create the operation.
+ be_operation *operation = 0;
+ ACE_NEW_RETURN (operation,
+ be_operation (rt,
+ AST_Operation::OP_noflags,
+ op_name,
+ 0,
+ 0),
+ -1);
+
+ operation->set_name (op_name);
+ operation->be_add_argument (arg);
+ operation->set_defined_in (reply_handler);
+
+ UTL_ScopedName *arg_name = (UTL_ScopedName *)op_name->copy ();
+ arg_name->nconc (tmp);
+ arg->set_name (arg_name);
+ arg->set_defined_in (operation);
+
+ // Copy the exceptions since the user exception information may
+ // be needed when collocation is disabled.
+ UTL_ExceptList *exceptions = node->exceptions ();
+
+ if (0 != exceptions)
+ {
+ operation->be_add_exceptions (exceptions->copy ());
+ }
+
+ // After having generated the operation we insert it into the
+ // reply handler interface.
+ if (0 == reply_handler->be_add_operation (operation))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+// Visit the scope and its elements.
+int
+be_visitor_ami_pre_proc::visit_scope (be_scope *node)
+{
+ // proceed if the number of members in our scope is greater than 0
+ if (node->nmembers () > 0)
+ {
+ int number_of_elements = 0;
+
+ {
+ // initialize an iterator to iterate thru our scope
+ for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ ++number_of_elements;
+ }
+ }
+
+ AST_Decl **elements;
+ ACE_NEW_RETURN (elements,
+ AST_Decl *[number_of_elements],
+ -1);
+
+ {
+ int position = 0;
+
+ // Initialize an iterator to iterate thru our scope.
+ for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ elements[position++] = si.item ();
+ }
+ }
+
+ int elem_number = 0;
+
+ // Continue until each element is visited.
+ while (elem_number < number_of_elements)
+ {
+ AST_Decl *d = elements[elem_number];
+
+ if (!d)
+ {
+ delete [] elements;
+ elements = 0;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_scope::visit_scope - "
+ "bad node in this scope\n"),
+ -1);
+
+ }
+
+ be_decl *bd = be_decl::narrow_from_decl (d);
+
+ // Set the scope node as "node" in which the code is being
+ // generated so that elements in the node's scope can use it
+ // for code generation.
+ this->ctx_->scope (node->decl ());
+
+ // Set the node to be visited.
+ this->ctx_->node (bd);
+ ++elem_number;
+
+
+ // Send the visitor.
+ if (bd == 0 || bd->accept (this) == -1)
+ {
+ delete [] elements;
+ elements = 0;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_visitor_scope::visit_scope - "
+ "codegen for scope failed\n"),
+ -1);
+ }
+ } // end of while loop
+
+ delete [] elements;
+ elements = 0;
+ } // end of if
+
+ return 0;
+}
+
+// Helper methods
+
+int
+be_visitor_ami_pre_proc::generate_name (ACE_CString &destination,
+ const char *prefix,
+ const char *middle_name,
+ const char *suffix)
+{
+ destination = prefix;
+ destination += middle_name;
+ destination += suffix;
+ return 0;
+}
+
+be_operation *
+be_visitor_ami_pre_proc::generate_get_operation (be_attribute *node)
+{
+ ACE_CString original_op_name (
+ node->name ()->last_component ()->get_string ()
+ );
+ ACE_CString new_op_name = ACE_CString ("get_") + original_op_name;
+
+ UTL_ScopedName *get_name =
+ static_cast<UTL_ScopedName *> (node->name ()->copy ());
+ get_name->last_component ()->replace_string (new_op_name.c_str ());
+
+ be_operation *operation = 0;
+ ACE_NEW_RETURN (operation,
+ be_operation (node->field_type (),
+ AST_Operation::OP_noflags,
+ get_name,
+ 0,
+ 0),
+ 0);
+
+ operation->set_name (get_name);
+ operation->set_defined_in (node->defined_in ());
+
+ return operation;
+}
+
+be_operation *
+be_visitor_ami_pre_proc::generate_set_operation (be_attribute *node)
+{
+ ACE_CString original_op_name (
+ node->name ()->last_component ()->get_string ()
+ );
+ ACE_CString new_op_name = ACE_CString ("set_") + original_op_name;
+
+ UTL_ScopedName *set_name =
+ static_cast<UTL_ScopedName *> (node->name ()-> copy ());
+ set_name->last_component ()->replace_string (new_op_name.c_str ());
+
+ // Argument type is the same as the attribute type.
+ be_argument *arg = 0;
+ ACE_NEW_RETURN (arg,
+ be_argument (AST_Argument::dir_IN,
+ node->field_type (),
+ set_name),
+ 0);
+
+ arg->set_name ((UTL_ScopedName *) node->name ()->copy ());
+
+ // Create the operation.
+ be_operation *operation = 0;
+ ACE_NEW_RETURN (operation,
+ be_operation (be_global->void_type (),
+ AST_Operation::OP_noflags,
+ set_name,
+ 0,
+ 0),
+ 0);
+
+ operation->set_name (set_name);
+ operation->set_defined_in (node->defined_in ());
+ operation->be_add_argument (arg);
+
+ return operation;
+}
+
+AST_Interface **
+be_visitor_ami_pre_proc::create_inheritance_list (be_interface *node,
+ long &n_rh_parents)
+{
+ AST_Interface **retval = 0;
+
+ long n_parents = node->n_inherits ();
+ AST_Interface **parents = node->inherits ();
+ AST_Interface *parent = 0;
+
+ for (long i = 0; i < n_parents; ++i)
+ {
+ parent = parents[i];
+
+ if (parent->is_abstract ())
+ {
+ continue;
+ }
+
+ ++n_rh_parents;
+ }
+
+ if (n_rh_parents == 0)
+ {
+ be_interface *inherit_intf = be_global->messaging_replyhandler ();
+
+ ACE_NEW_RETURN (retval,
+ AST_Interface *[1],
+ 0);
+
+ retval[0] = inherit_intf;
+ n_rh_parents = 1;
+ }
+ else
+ {
+ ACE_NEW_RETURN (retval,
+ AST_Interface *[n_rh_parents],
+ 0);
+
+ ACE_CString prefix ("AMI_");
+ ACE_CString suffix ("Handler");
+ long index = 0;
+
+ for (long j = 0; j < n_parents; ++j)
+ {
+ parent = parents[j];
+
+ if (parent->is_abstract ())
+ {
+ continue;
+ }
+
+ ACE_CString rh_local_name =
+ prefix + parent->local_name ()->get_string () + suffix;
+
+ UTL_ScopedName *rh_parent_name =
+ static_cast<UTL_ScopedName *> (parent->name ()->copy ());
+
+ rh_parent_name->last_component ()->replace_string (
+ rh_local_name.c_str ()
+ );
+
+ AST_Decl *d =
+ node->defined_in ()->lookup_by_name (rh_parent_name,
+ true);
+
+ if (d != 0)
+ {
+ retval[index] = AST_Interface::narrow_from_decl (d);
+ retval[index++]->set_prefix_with_typeprefix (parent->prefix () ?
+ const_cast<char*> (parent->prefix()) :
+ const_cast<char*> (""));
+ }
+
+ rh_parent_name->destroy ();
+ delete rh_parent_name;
+ rh_parent_name = 0;
+ }
+
+ // Just a sanity check until we're sure this works in all use cases.
+ if (n_rh_parents != index)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "reply handler parent iteration mismatch\n"),
+ 0);
+ }
+ }
+
+ return retval;
+}