summaryrefslogtreecommitdiff
path: root/ACE/TAO/orbsvcs/IFR_Service/ifr_adding_visitor_union.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/TAO/orbsvcs/IFR_Service/ifr_adding_visitor_union.cpp')
-rw-r--r--ACE/TAO/orbsvcs/IFR_Service/ifr_adding_visitor_union.cpp491
1 files changed, 491 insertions, 0 deletions
diff --git a/ACE/TAO/orbsvcs/IFR_Service/ifr_adding_visitor_union.cpp b/ACE/TAO/orbsvcs/IFR_Service/ifr_adding_visitor_union.cpp
new file mode 100644
index 00000000000..dc0e8abe288
--- /dev/null
+++ b/ACE/TAO/orbsvcs/IFR_Service/ifr_adding_visitor_union.cpp
@@ -0,0 +1,491 @@
+/* -*- c++ -*- */
+// $Id$
+
+#include "ast_enum.h"
+#include "ast_expression.h"
+#include "ast_union.h"
+#include "ast_union_branch.h"
+#include "ast_union_label.h"
+#include "utl_identifier.h"
+
+#include "ifr_adding_visitor_union.h"
+#include "ifr_adding_visitor_structure.h"
+
+#include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h"
+#include "tao/CDR.h"
+
+ACE_RCSID (IFR_Service,
+ ifr_adding_visitor_union,
+ "$Id$")
+
+ifr_adding_visitor_union::ifr_adding_visitor_union (AST_Decl *scope)
+ : ifr_adding_visitor (scope)
+{
+}
+
+ifr_adding_visitor_union::~ifr_adding_visitor_union (void)
+{
+}
+
+// Specialized visit_scope method for unions only.
+int
+ifr_adding_visitor_union::visit_scope (UTL_Scope *node)
+{
+ // If the union has members that are scopes but not unions,
+ // the regular visit_scope method should be called instead.
+ if (node->scope_node_type () != AST_Decl::NT_union)
+ {
+ return ifr_adding_visitor::visit_scope (node);
+ }
+
+ AST_Union *u = AST_Union::narrow_from_scope (node);
+
+ CORBA::ULong nfields = static_cast<CORBA::ULong> (u->nfields ());
+
+ this->members_.length (nfields);
+
+ AST_Field **f = 0;
+
+ // Index into members_.
+ CORBA::ULong index = 0;
+
+ try
+ {
+ // Visit each field.
+ for (CORBA::ULong i = 0; i < nfields; ++i)
+ {
+ if (u->field (f, i) != 0)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_scope -")
+ ACE_TEXT (" field node access failed\n")
+ ),
+ -1
+ );
+ }
+
+ AST_Type *ft = (*f)->field_type ();
+
+ bool defined_here = ft->is_child (this->scope_);
+
+ // If the union member is defined in the union, we have to
+ // do some visiting - otherwise we can just look up the entry.
+ if (defined_here)
+ {
+ if (ft->node_type () == AST_Decl::NT_union)
+ {
+ // Since the enclosing scope hasn't been created yet,
+ // we make a special visitor to create this member
+ // at global scope and move it into the union later.
+ ifr_adding_visitor_union visitor (ft);
+
+ if (ft->ast_accept (&visitor) == -1)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_scope -")
+ ACE_TEXT (" failed to accept visitor\n")),
+ -1);
+ }
+
+ this->ir_current_ =
+ CORBA::IDLType::_duplicate (visitor.ir_current ());
+ }
+ else
+ {
+ if (ft->ast_accept (this) == -1)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_scope -")
+ ACE_TEXT (" failed to accept visitor\n")),
+ -1);
+ }
+ }
+ }
+ else
+ {
+ // Updates ir_current_.
+ this->get_referenced_type (ft);
+ }
+
+ // Get the case label(s).
+
+ AST_UnionLabel *case_label = 0;
+ AST_UnionBranch *ub = AST_UnionBranch::narrow_from_decl (*f);
+ unsigned long len = ub->label_list_length ();
+
+ // If there are multiple case labels, we will have an element
+ // in the UnionMemberSeq for each label, not just for each member,
+ // so the list length and the loop terminator must both be
+ // increased accordingly.
+ if (len > 1)
+ {
+ this->members_.length (this->members_.length () + len - 1);
+ }
+
+ for (unsigned long j = 0; j < len; ++j)
+ {
+ case_label = ub->label (j);
+
+ // Is this a regular label or default label?
+ if (case_label->label_kind () == AST_UnionLabel::UL_label)
+ {
+ AST_Expression::AST_ExprValue *ev =
+ case_label->label_val ()->ev ();
+
+ // If the discriminator is an enum, we can't just insert
+ // a ulong into the Any member of struct UnionMember.
+ if (u->disc_type ()->node_type () == AST_Decl::NT_enum)
+ {
+ TAO_OutputCDR cdr;
+ cdr.write_ulong (ev->u.ulval);
+ TAO_InputCDR in_cdr (cdr);
+ TAO::Unknown_IDL_Type *unk = 0;
+ ACE_NEW_RETURN (unk,
+ TAO::Unknown_IDL_Type (
+ this->disc_tc_.in (),
+ in_cdr),
+ -1);
+ this->members_[index].label.replace (unk);
+ }
+ else
+ {
+ this->load_any (ev,
+ this->members_[index].label);
+ }
+ }
+ else // Default case label.
+ {
+ this->members_[index].label <<= CORBA::Any::from_octet (0);
+ }
+
+ this->members_[index].name =
+ CORBA::string_dup ((*f)->local_name ()->get_string ());
+
+ // IfR method create_union does not use this - it just needs
+ // to be non-zero for marshaling.
+ this->members_[index].type =
+ CORBA::TypeCode::_duplicate (CORBA::_tc_void);
+
+ this->members_[index++].type_def =
+ CORBA::IDLType::_duplicate (this->ir_current_.in ());
+ }
+ }
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception (
+ ACE_TEXT (
+ "ifr_adding_visitor_union::visit_scope"));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ifr_adding_visitor_union::visit_structure (AST_Structure *node)
+{
+ try
+ {
+ // Is this struct already in the respository?
+ CORBA::Contained_var prev_def =
+ be_global->repository ()->lookup_id (node->repoID ());
+
+ // If not, create a new entry.
+ if (CORBA::is_nil (prev_def.in ()))
+ {
+ ifr_adding_visitor_structure visitor (node);
+ int retval = visitor.visit_structure (node);
+
+ if (retval == 0)
+ {
+ // Get the result of the visit.
+ this->ir_current_ =
+ CORBA::IDLType::_duplicate (visitor.ir_current ());
+ }
+
+ return retval;
+ }
+ else
+ {
+ // If the line below is true, we are clobbering a previous
+ // entry (from another IDL file) of another type. In that
+ // case we do what other ORB vendors do, and destroy the
+ // original entry, create the new one, and let the user beware.
+ if (!node->ifr_added ())
+ {
+ prev_def->destroy ();
+
+ // This call will take the other branch.
+ return this->visit_structure (node);
+ }
+
+ this->ir_current_ =
+ CORBA::IDLType::_narrow (prev_def.in ());
+ }
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception (
+ ACE_TEXT (
+ "ifr_adding_visitor_union::visit_structure"));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ifr_adding_visitor_union::visit_enum (AST_Enum *node)
+{
+ try
+ {
+ // Is this enum already in the respository?
+ CORBA::Contained_var prev_def =
+ be_global->repository ()->lookup_id (node->repoID ());
+
+ // If not, create a new entry.
+ if (CORBA::is_nil (prev_def.in ()))
+ {
+ CORBA::ULong member_count =
+ static_cast<CORBA::ULong> (node->member_count ());
+
+ CORBA::EnumMemberSeq members (member_count);
+ members.length (member_count);
+
+ UTL_ScopedName *member_name = 0;
+
+ // Get a list of the member names.
+ for (CORBA::ULong i = 0; i < member_count; ++i)
+ {
+ member_name = node->value_to_name (i);
+
+ members[i] =
+ CORBA::string_dup (
+ member_name->last_component ()->get_string ());
+ }
+
+ this->ir_current_ =
+ be_global->repository ()->create_enum (
+ node->repoID (),
+ node->local_name ()->get_string (),
+ node->version (),
+ members
+ );
+
+ node->ifr_added (true);
+ }
+ else
+ {
+ // If the line below is true, we are clobbering a previous
+ // entry (from another IDL file) of another type. In that
+ // case we do what other ORB vendors do, and destroy the
+ // original entry, create the new one, and let the user beware.
+ if (!node->ifr_added ())
+ {
+ prev_def->destroy ();
+
+ // This call will take the other branch.
+ return this->visit_enum (node);
+ }
+
+ this->ir_current_ =
+ CORBA::IDLType::_narrow (prev_def.in ());
+ }
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception (
+ ACE_TEXT (
+ "ifr_adding_visitor_union::visit_enum"));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ifr_adding_visitor_union::visit_union (AST_Union *node)
+{
+ try
+ {
+ // This will put the discriminator in ir_current_.
+ if (node->disc_type ()->ast_accept (this) == -1)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" visit of discriminator failed\n")),
+ -1);
+ }
+
+ this->disc_tc_ = this->ir_current_->type ();
+
+ CORBA::UnionDef_var union_def;
+ CORBA::Contained_var prev_def =
+ be_global->repository ()->lookup_id (node->repoID ());
+
+ if (CORBA::is_nil (prev_def.in ()))
+ {
+ CORBA::UnionMemberSeq dummyMembers;
+ dummyMembers.length (0);
+ CORBA::Container_ptr current_scope = CORBA::Container::_nil ();
+
+ if (be_global->ifr_scopes ().top (current_scope) != 0)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" scope stack is empty\n")),
+ -1);
+ }
+
+ // First create the named union without any members.
+ union_def =
+ current_scope->create_union (
+ node->repoID (),
+ node->local_name ()->get_string (),
+ node->version (),
+ this->ir_current_.in (),
+ dummyMembers
+ );
+
+ if (be_global->ifr_scopes ().push (union_def.in ()) != 0)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" scope push failed\n")
+ ),
+ -1
+ );
+ }
+
+ // Then add the real union members (which corrupts ir_current_).
+ if (this->add_members (node, union_def.in ()) == -1)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::visit_union -")
+ ACE_TEXT (" visit_scope failed\n")),
+ -1);
+ }
+
+ this->ir_current_ = CORBA::IDLType::_narrow (union_def.in ());
+
+ CORBA::Container_ptr used_scope =
+ CORBA::Container::_nil ();
+
+ // Pop the new IR object back off the scope stack.
+ if (be_global->ifr_scopes ().pop (used_scope) != 0)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" scope pop failed\n")
+ ),
+ -1
+ );
+ }
+ } // if (CORBA::is_nil (...))
+ else
+ {
+ // We are seeing the full definition of a forward
+ // declaration - just add the members so repo
+ // entries referencing the UnionDef will stay valid.
+ // Also we know node->ifr_fwd_added_ is true.
+ union_def = CORBA::UnionDef::_narrow (prev_def.in ());
+ union_def->discriminator_type_def (this->ir_current_.in ());
+
+ if (be_global->ifr_scopes ().push (union_def.in ()) != 0)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" scope push failed\n")
+ ),
+ -1
+ );
+ }
+
+ if (this->add_members (node, union_def.in ()) == -1)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" visit_scope failed\n")),
+ -1);
+ }
+
+ this->ir_current_ = CORBA::IDLType::_narrow (prev_def.in ());
+
+ CORBA::Container_ptr used_scope =
+ CORBA::Container::_nil ();
+
+ // Pop the new IR object back off the scope stack.
+ if (be_global->ifr_scopes ().pop (used_scope) != 0)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::")
+ ACE_TEXT ("visit_union -")
+ ACE_TEXT (" scope pop failed\n")
+ ),
+ -1
+ );
+ }
+ }
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception (
+ ACE_TEXT (
+ "ifr_adding_visitor_union::visit_union"));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+CORBA::IDLType_ptr
+ifr_adding_visitor_union::ir_current (void) const
+{
+ return this->ir_current_.in ();
+}
+
+int
+ifr_adding_visitor_union::add_members (AST_Union *node,
+ CORBA::UnionDef_ptr union_def)
+{
+ if (this->visit_scope (node) == -1)
+ {
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::visit_union -")
+ ACE_TEXT (" visit_scope failed\n")),
+ -1);
+ }
+
+ // Correct ir_current_ and move the real union members into the union.
+ this->ir_current_= CORBA::UnionDef::_duplicate (union_def);
+ union_def->members (this->members_);
+
+ node->ifr_added (true);
+ return 0;
+}