ifr_adding_visitor_structure.cpp

Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 // $Id: ifr_adding_visitor_structure.cpp 80487 2008-01-23 20:55:08Z parsons $
00003 
00004 #include "ast_enum.h"
00005 #include "ast_expression.h"
00006 #include "ast_field.h"
00007 #include "ast_union.h"
00008 #include "utl_identifier.h"
00009 
00010 #include "ifr_adding_visitor_structure.h"
00011 #include "ifr_adding_visitor_union.h"
00012 
00013 ACE_RCSID (IFR_Service,
00014            ifr_adding_visitor_structure,
00015            "$Id: ifr_adding_visitor_structure.cpp 80487 2008-01-23 20:55:08Z parsons $")
00016 
00017 ifr_adding_visitor_structure::ifr_adding_visitor_structure (
00018     AST_Decl *scope,
00019     bool is_nested
00020   )
00021   : ifr_adding_visitor (scope),
00022     is_nested_ (is_nested)
00023 {
00024 }
00025 
00026 ifr_adding_visitor_structure::~ifr_adding_visitor_structure (void)
00027 {
00028 }
00029 
00030 // Specialized visit_scope method for stucts only.
00031 int
00032 ifr_adding_visitor_structure::visit_scope (UTL_Scope *node)
00033 {
00034   // If the struct has members that are scopes but not structs,
00035   // the regular visit_scope method should be called instead.
00036   if (node->scope_node_type () != AST_Decl::NT_struct)
00037     {
00038       return ifr_adding_visitor::visit_scope (node);
00039     }
00040 
00041   AST_Structure *s = AST_Structure::narrow_from_scope (node);
00042   CORBA::ULong nfields = static_cast<CORBA::ULong> (s->nfields ());
00043   this->members_.length (nfields);
00044   AST_Field **f = 0;
00045 
00046   try
00047     {
00048       // Visit each field.
00049       for (CORBA::ULong i = 0; i < nfields; ++i)
00050         {
00051           if (s->field (f, i) != 0)
00052             {
00053               ACE_ERROR_RETURN ((
00054                   LM_ERROR,
00055                   ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00056                   ACE_TEXT ("visit_scope -")
00057                   ACE_TEXT (" field node access failed\n")
00058                 ),
00059                 -1
00060               );
00061             }
00062 
00063           AST_Type *ft = (*f)->field_type ();
00064           bool defined_here = ft->is_child (this->scope_);
00065 
00066           // If the struct member is defined in the struct, we have to
00067           // do some visiting - otherwise we can just look up the entry.
00068           if (defined_here)
00069             {
00070               if (ft->node_type () == AST_Decl::NT_struct)
00071                 {
00072                   // Since the enclosing scope hasn't been created yet,
00073                   // we make a special visitor to create this member
00074                   // at global scope and move it into the struct later.
00075                   ifr_adding_visitor_structure visitor (ft, true);
00076 
00077                   if (ft->ast_accept (&visitor) == -1)
00078                     {
00079                       ACE_ERROR_RETURN ((
00080                           LM_ERROR,
00081                           ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00082                           ACE_TEXT ("visit_scope -")
00083                           ACE_TEXT (" failed to accept visitor\n")
00084                         ),
00085                         -1
00086                       );
00087                     }
00088 
00089                   this->ir_current_ =
00090                     CORBA::IDLType::_duplicate (visitor.ir_current ());
00091 
00092                   CORBA::Contained_ptr tmp =
00093                     CORBA::Contained::_narrow (visitor.ir_current ());
00094 
00095                   this->move_queue_.enqueue_tail (tmp);
00096                 }
00097               else
00098                 {
00099                   if (ft->ast_accept (this) == -1)
00100                     {
00101                       ACE_ERROR_RETURN ((
00102                           LM_ERROR,
00103                           ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00104                           ACE_TEXT ("visit_scope -")
00105                           ACE_TEXT (" failed to accept visitor\n")
00106                         ),
00107                         -1
00108                       );
00109                     }
00110                 }
00111             }
00112           else
00113             {
00114               // Updates ir_current_.
00115               this->get_referenced_type (ft);
00116             }
00117 
00118           this->members_[i].name =
00119             CORBA::string_dup ((*f)->local_name ()->get_string ());
00120 
00121           // IfR method create_struct does not use this - it just needs
00122           // to be non-zero for marshaling.
00123           this->members_[i].type =
00124             CORBA::TypeCode::_duplicate (CORBA::_tc_void);
00125 
00126           this->members_[i].type_def =
00127             CORBA::IDLType::_duplicate (this->ir_current_.in ());
00128         }
00129     }
00130   catch (const CORBA::Exception& ex)
00131     {
00132       ex._tao_print_exception (
00133         ACE_TEXT (
00134           "ifr_adding_visitor_structure::visit_scope"));
00135 
00136       return -1;
00137     }
00138 
00139   return 0;
00140 }
00141 
00142 int
00143 ifr_adding_visitor_structure::visit_structure (AST_Structure *node)
00144 {
00145   try
00146     {
00147       CORBA::StructDef_var struct_def;
00148       CORBA::Contained_var prev_def =
00149         be_global->repository ()->lookup_id (node->repoID ());
00150 
00151       if (CORBA::is_nil (prev_def.in ()))
00152         {
00153           CORBA::StructDef_var struct_def;
00154           CORBA::StructMemberSeq dummyMembers;
00155           dummyMembers.length (0);
00156 
00157           CORBA::Container_ptr current_scope = CORBA::Container::_nil ();
00158           
00159           if (this->is_nested_)
00160             {
00161               current_scope = be_global->holding_scope ();
00162             }
00163           else if (be_global->ifr_scopes ().top (current_scope) != 0)
00164             {
00165               ACE_ERROR_RETURN ((
00166                   LM_ERROR,
00167                   ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00168                   ACE_TEXT ("visit_structure -")
00169                   ACE_TEXT (" scope stack is empty\n")
00170                 ),
00171                 -1
00172               );
00173             }
00174 
00175           // First create the named structure without any members.
00176           struct_def =
00177             current_scope->create_struct (
00178                 node->repoID (),
00179                 node->local_name ()->get_string (),
00180                 node->version (),
00181                 dummyMembers
00182               );
00183 
00184           // Then add the real structure members (which corrupts ir_current_).
00185           if (this->add_members (node, struct_def.in ()) == -1)
00186             {
00187               ACE_ERROR_RETURN ((
00188                   LM_ERROR,
00189                   ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00190                   ACE_TEXT ("visit_structure -")
00191                   ACE_TEXT (" visit_scope failed\n")
00192                 ),
00193                 -1
00194               );
00195             }
00196         }
00197       else
00198         {
00199           // Are we seeing the full definition of a previous forward
00200           // declaration. If so, just add the members so the repo
00201           // entry referencing the StructDef will still be valid.
00202           if (node->ifr_fwd_added ())
00203             {
00204               struct_def = CORBA::StructDef::_narrow (prev_def.in ());
00205           
00206               if (this->add_members (node, struct_def.in ()) == -1)
00207                 {
00208                   ACE_ERROR_RETURN ((
00209                       LM_ERROR,
00210                       ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00211                       ACE_TEXT ("visit_structure -")
00212                       ACE_TEXT (" visit_scope failed\n")
00213                     ),
00214                     -1
00215                   );
00216                 }
00217                 
00218               // We shouldn't see this node again, but just in case.
00219               node->ifr_fwd_added (false);
00220            }
00221            
00222           // Are we clobbering a previous
00223           // entry (from another IDL file) of another type? In that
00224           // case we do what other ORB vendors do, and destroy the
00225           // original entry, create the new one, and let the user beware.
00226           if (!node->ifr_added ())
00227             {
00228               prev_def->destroy ();
00229 
00230               // This call will take the other branch.
00231               return this->visit_structure (node);
00232             }
00233 
00234           this->ir_current_ = CORBA::IDLType::_narrow (prev_def.in ());
00235         }
00236     }
00237   catch (const CORBA::Exception& ex)
00238     {
00239       ex._tao_print_exception (
00240         ACE_TEXT (
00241           "ifr_adding_visitor_structure::visit_structure"));
00242 
00243       return -1;
00244     }
00245 
00246   return 0;
00247 }
00248 
00249 int
00250 ifr_adding_visitor_structure::visit_enum (AST_Enum *node)
00251 {
00252   try
00253     {
00254       // Is this enum already in the respository?
00255       CORBA::Contained_var prev_def =
00256         be_global->repository ()->lookup_id (node->repoID ());
00257 
00258       // If not, create a new entry.
00259       if (CORBA::is_nil (prev_def.in ()))
00260         {
00261           CORBA::ULong member_count = static_cast<CORBA::ULong> (node->member_count ());
00262 
00263           CORBA::EnumMemberSeq members (member_count);
00264           members.length (member_count);
00265 
00266           UTL_ScopedName *member_name = 0;
00267 
00268           // Get a list of the member names.
00269           for (CORBA::ULong i = 0; i < member_count; ++i)
00270             {
00271               member_name = node->value_to_name (i);
00272 
00273               members[i] =
00274                 CORBA::string_dup (
00275                     member_name->last_component ()->get_string ()
00276                   );
00277             }
00278 
00279           this->ir_current_ =
00280             be_global->repository ()->create_enum (
00281                                           node->repoID (),
00282                                           node->local_name ()->get_string (),
00283                                           node->version (),
00284                                           members
00285                                         );
00286 
00287           CORBA::Contained_ptr tmp =
00288             CORBA::Contained::_narrow (this->ir_current_.in ());
00289 
00290           // Since the enclosing StructDef hasn't been created
00291           // yet, we don't have a scope, so this nested EnumDef
00292           // (which was created at global scope) goes on the
00293           // queue to be moved later.
00294           this->move_queue_.enqueue_tail (tmp);
00295 
00296           node->ifr_added (true);
00297         }
00298       else
00299         {
00300           // If the line below is true, we are clobbering a previous
00301           // entry (from another IDL file) of another type. In that
00302           // case we do what other ORB vendors do, and destroy the
00303           // original entry, create the new one, and let the user beware.
00304           if (!node->ifr_added ())
00305             {
00306               prev_def->destroy ();
00307 
00308               // This call will take the other branch.
00309               return this->visit_enum (node);
00310             }
00311 
00312           this->ir_current_ =
00313             CORBA::IDLType::_narrow (prev_def.in ());
00314         }
00315     }
00316   catch (const CORBA::Exception& ex)
00317     {
00318       ex._tao_print_exception (
00319         ACE_TEXT (
00320           "ifr_adding_visitor_structure::visit_enum"));
00321 
00322       return -1;
00323     }
00324 
00325   return 0;
00326 }
00327 
00328 int
00329 ifr_adding_visitor_structure::visit_union (AST_Union *node)
00330 {
00331   try
00332     {
00333       // Is this union already in the respository?
00334       CORBA::Contained_var prev_def =
00335         be_global->repository ()->lookup_id (node->repoID ());
00336 
00337       // If not, create a new entry.
00338       if (CORBA::is_nil (prev_def.in ()))
00339         {
00340           ifr_adding_visitor_union visitor (node,
00341                                             1);
00342 
00343           int retval = visitor.visit_union (node);
00344 
00345           if (retval == 0)
00346             {
00347               // Get the result of the visit.
00348               this->ir_current_ =
00349                 CORBA::IDLType::_duplicate (visitor.ir_current ());
00350 
00351               CORBA::Contained_ptr tmp =
00352                 CORBA::Contained::_narrow (visitor.ir_current ());
00353 
00354               // Since the enclosing StructDef hasn't been created
00355               // yet, we don't have a scope, so this nested UnionDef
00356               // (which was created at global scope) goes on the
00357               // queue to be moved later.
00358               this->move_queue_.enqueue_tail (tmp);
00359             }
00360 
00361           return retval;
00362         }
00363       else
00364         {
00365           // If the line below is true, we are clobbering a previous
00366           // entry (from another IDL file) of another type. In that
00367           // case we do what other ORB vendors do, and destroy the
00368           // original entry, create the new one, and let the user beware.
00369           if (!node->ifr_added ())
00370             {
00371               prev_def->destroy ();
00372 
00373               // This call will take the other branch.
00374               return this->visit_union (node);
00375             }
00376 
00377           this->ir_current_ =
00378             CORBA::IDLType::_narrow (prev_def.in ());
00379         }
00380     }
00381   catch (const CORBA::Exception& ex)
00382     {
00383       ex._tao_print_exception (
00384         ACE_TEXT (
00385           "ifr_adding_visitor_structure::visit_union"));
00386 
00387       return -1;
00388     }
00389 
00390   return 0;
00391 }
00392 
00393 CORBA::IDLType_ptr
00394 ifr_adding_visitor_structure::ir_current (void) const
00395 {
00396   return this->ir_current_.in ();
00397 }
00398 
00399 int
00400 ifr_adding_visitor_structure::add_members (AST_Structure *node,
00401                                            CORBA::StructDef_ptr struct_def)
00402 {
00403   if (this->visit_scope (node) == -1)
00404     {
00405       ACE_ERROR_RETURN ((
00406           LM_ERROR,
00407           ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::")
00408           ACE_TEXT ("visit_structure -")
00409           ACE_TEXT (" visit_scope failed\n")
00410         ),
00411         -1
00412       );
00413     }
00414 
00415   // Correct ir_current_ and move the real members into the struct.
00416   this->ir_current_= CORBA::StructDef::_duplicate (struct_def);
00417   struct_def->members (this->members_);
00418   size_t size = this->move_queue_.size ();
00419 
00420   if (size > 0)
00421     {
00422       CORBA::Contained_var traveller;
00423 
00424       CORBA::Container_var new_container =
00425         CORBA::Container::_narrow (this->ir_current_.in ());
00426 
00427       for (size_t i = 0; i < size; ++i)
00428         {
00429           this->move_queue_.dequeue_head (traveller);
00430 
00431           CORBA::String_var name = traveller->name ();
00432           CORBA::String_var version = traveller->version ();
00433 
00434           traveller->move (new_container.in (),
00435                            name.in (),
00436                            version.in ());
00437         }
00438     }
00439    
00440   node->ifr_added (true);
00441   return 0;
00442 }

Generated on Tue Feb 2 17:50:49 2010 for TAO_IFR by  doxygen 1.4.7