ifr_adding_visitor_structure.cpp

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

Generated on Thu Nov 9 14:11:50 2006 for TAO_IFR by doxygen 1.3.6