2 //=============================================================================
4 * @file be_interface.cpp
6 * Extension of class AST_Interface that provides additional means for C++
7 * mapping of an interface.
9 * @author Copyright 1994-1995 by Sun Microsystems
10 * @author Inc. and Aniruddha Gokhale
11 * @author Michael Kircher
13 //=============================================================================
15 #include "be_interface.h"
16 #include "be_component.h"
17 #include "be_connector.h"
18 #include "be_attribute.h"
19 #include "be_operation.h"
20 #include "be_exception.h"
21 #include "be_visitor.h"
22 #include "be_helper.h"
24 #include "be_identifier_helper.h"
25 #include "be_extern.h"
27 #include "be_visitor_interface.h"
28 #include "be_visitor_operation.h"
29 #include "be_visitor_attribute.h"
30 #include "be_visitor_context.h"
32 #include "utl_identifier.h"
33 #include "utl_exceptlist.h"
35 #include "ast_generator.h"
38 #include "global_extern.h"
39 #include "idl_defines.h"
40 #include "nr_extern.h"
42 #include "ace/Process.h"
43 #include "ace/Lib_Find.h"
44 #include "ace/OS_NS_time.h"
45 #include "ace/OS_NS_unistd.h"
46 #include "ace/OS_NS_fcntl.h"
48 const char *be_interface::suffix_table_
[] =
53 const char *be_interface::tag_table_
[] =
59 be_interface::be_interface (UTL_ScopedName
*n
,
62 AST_Interface
**ih_flat
,
68 AST_Decl (AST_Decl::NT_interface
,
70 AST_Type (AST_Decl::NT_interface
,
72 UTL_Scope (AST_Decl::NT_interface
),
80 be_scope (AST_Decl::NT_interface
),
81 be_decl (AST_Decl::NT_interface
,
83 be_type (AST_Decl::NT_interface
,
85 direct_proxy_impl_name_ (nullptr),
86 full_direct_proxy_impl_name_ (nullptr),
87 client_scope_ (nullptr),
88 flat_client_scope_ (nullptr),
89 server_scope_ (nullptr),
90 flat_server_scope_ (nullptr),
91 var_out_seq_decls_gen_ (false),
93 in_mult_inheritance_ (-1),
94 original_interface_ (nullptr),
97 is_ami4ccm_rh_ (false),
98 full_skel_name_ (nullptr),
99 full_coll_name_ (nullptr),
100 local_coll_name_ (nullptr),
101 relative_skel_name_ (nullptr),
103 has_rw_attributes_ (false),
104 dds_connector_traits_done_ (false)
106 AST_Decl::NodeType nt
= this->node_type ();
108 if (this->imported ()
109 || nt
== AST_Decl::NT_valuetype
110 || nt
== AST_Decl::NT_eventtype
)
115 if (this->is_defined ())
117 // Set the flag that says we have a interface in this IDL file.
118 idl_global
->interface_seen_
= true;
120 if (abstract
|| this->has_mixed_parentage ())
122 // Set the flag for abstract interface seen in this IDL file.
123 idl_global
->abstract_iface_seen_
= true;
128 // Set the flag for local interface seen in this IDL file.
129 idl_global
->local_iface_seen_
= true;
133 // Set the flag for non-local interface seen in this IDL file.
134 idl_global
->non_local_iface_seen_
= true;
139 // Forward declared non-defined interface. Still gets a _var decl.
140 idl_global
->fwd_iface_seen_
= true;
144 be_interface::~be_interface ()
149 be_interface::local_name ()
151 // Return the local name.
152 // return this->strategy_->local_name ();
153 return this->AST_Decl::local_name ()->get_string ();
157 be_interface::full_skel_name ()
159 if (this->full_skel_name_
== nullptr)
161 this->compute_full_skel_name ("POA_",
162 this->full_skel_name_
);
165 return this->full_skel_name_
;
169 be_interface::full_coll_name (int type
)
171 this->compute_coll_names (type
,
175 return this->full_coll_name_
;
179 be_interface::local_coll_name (int type
)
181 this->compute_coll_names (type
,
185 return this->local_coll_name_
;
189 be_interface::relative_skel_name (const char *skel_name
)
191 return be_interface::relative_name (this->full_skel_name (),
196 be_interface::compute_full_skel_name (const char *prefix
,
199 if (skel_name
!= nullptr)
204 size_t namelen
= ACE_OS::strlen (prefix
);
207 char *item_name
= nullptr;
209 // In the first loop compute the total length.
210 for (UTL_IdListActiveIterator
i (this->name ());
216 namelen
+= 2; // for "::"
220 first
= second
= false;
223 // Print the identifier.
224 item_name
= i
.item ()->get_string ();
225 namelen
+= ACE_OS::strlen (item_name
);
227 // Additional 4 for the POA_ characters.
230 if (ACE_OS::strcmp (item_name
, "") != 0)
232 // Does not start with a "".
247 ACE_OS::strcat (skel_name
, prefix
);
249 for (UTL_IdListActiveIterator
j (this->name ());
255 ACE_OS::strcat (skel_name
, "::");
259 first
= second
= false;
262 // Print the identifier.
263 item_name
= j
.item ()->get_string ();
264 ACE_OS::strcat (skel_name
, item_name
);
268 if (ACE_OS::strcmp (item_name
, "") != 0)
270 // Does not start with a "".
281 // Compute stringified fully qualified collocated class name.
283 be_interface::compute_coll_names (int type
,
287 if (type
== this->cached_type_
&& this->full_coll_name_
!= nullptr)
293 this->cached_type_
= type
;
294 delete [] this->full_coll_name_
;
295 delete [] this->local_coll_name_
;
297 // Reset to zero in case allocations below fail, and cause
298 // premature return to caller.
299 this->full_coll_name_
= nullptr;
300 this->local_coll_name_
= nullptr;
303 static const char *collocated_names
[] = {"_tao_thru_poa_collocated_",
304 "_tao_direct_collocated_"};
305 static const char *poa
= "POA_";
307 // Reserve enough room for the "POA_" prefix, the "_tao_collocated_"
308 // prefix and the local name and the (optional) "::"
309 const char *collocated
= collocated_names
[type
];
311 size_t name_len
= ACE_OS::strlen (collocated
)
312 + ACE_OS::strlen (poa
)
317 name_len
+= ACE_OS::strlen (prefix
);
322 name_len
+= ACE_OS::strlen (suffix
);
325 for (UTL_IdListActiveIterator
i (this->name ());
329 // Reserve 2 characters for "::".
330 name_len
+= ACE_OS::strlen (i
.item ()->get_string ()) + 2;
333 ACE_NEW (this->full_coll_name_
,
336 // Null terminate the string.
337 this->full_coll_name_
[0] = 0;
339 // Only the first component get the "POA_" preffix.
343 // Must advance the iterator explicitly inside the loop.
344 for (UTL_IdListActiveIterator
j (this->name ());
347 const char *item
= j
.item ()->get_string ();
349 // Increase right away, so we can test for the final component
353 // We add the POA_ prefix only if the first component is not
354 // the global scope...
355 if (ACE_OS::strcmp (item
, "") != 0)
359 // We only add the POA_ prefix if there are more than
360 // two components in the name, in other words, if the
361 // class is inside some scope.
364 ACE_OS::strcat (this->full_coll_name_
, poa
);
367 ACE_OS::strcat (this->full_coll_name_
, item
);
368 ACE_OS::strcat (this->full_coll_name_
, "::");
372 ACE_OS::strcat (this->full_coll_name_
, collocated
);
376 ACE_OS::strcat (this->full_coll_name_
, prefix
);
379 ACE_OS::strcat (this->full_coll_name_
, item
);
383 ACE_OS::strcat (this->full_coll_name_
, suffix
);
389 // Compute the local name for the collocated class.
391 this->AST_Interface::local_name ()->get_string ();
392 size_t local_len
= ACE_OS::strlen (collocated
)
393 + ACE_OS::strlen (local_name
)
397 local_len
+= ACE_OS::strlen (prefix
);
402 local_len
+= ACE_OS::strlen (suffix
);
405 ACE_NEW (this->local_coll_name_
,
408 ACE_OS::strcpy (this->local_coll_name_
,
413 ACE_OS::strcat (this->local_coll_name_
,
417 ACE_OS::strcat (this->local_coll_name_
,
418 this->AST_Interface::local_name ()->get_string ());
422 ACE_OS::strcat (this->local_coll_name_
, suffix
);
427 be_interface::relative_name (const char *localname
,
428 const char *othername
)
430 // Some compilers do not like generating a fully scoped name for a
431 // type that was defined in the same enclosing scope in which it was
432 // defined. We have to emit just the partial name, relative to our
435 // The tricky part here is that it is not enough to check if the
436 // typename we are using was defined in the current scope. But we
437 // need to ensure that it was not defined in any of our ancestor
440 // Thus we need some sort of relative name to be generated.
442 static char macro
[NAMEBUFSIZE
];
444 // Hold the fully scoped name.
445 char def_name
[NAMEBUFSIZE
];
446 char use_name
[NAMEBUFSIZE
];
448 // These point to the curr and next component in the scope.
449 char *def_curr
= def_name
;
451 char *use_curr
= use_name
;
454 ACE_OS::memset (macro
,
457 ACE_OS::memset (def_name
,
460 ACE_OS::memset (use_name
,
464 // Traverse every component of the def_scope and use_scope beginning at the
465 // root and proceeding towards the leaf trying to see if the components
466 // match. Continue until there is a match and keep accumulating the path
468 ACE_OS::strcpy (def_name
,
470 ACE_OS::strcpy (use_name
,
473 while (def_curr
&& use_curr
)
475 // Find the first occurrence of a ::
476 // and advance the next pointers accordingly.
477 def_next
= ACE_OS::strstr (def_curr
, "::");
478 use_next
= ACE_OS::strstr (use_curr
, "::");
490 if (!ACE_OS::strcmp (def_curr
, use_curr
))
492 // They have same prefix, append to arg1.
493 def_curr
= (def_next
? (def_next
+2) : nullptr); // Skip the ::
494 use_curr
= (use_next
? (use_next
+2) : nullptr); // Skip the ::
498 // We had overwritten a ':' by a '\0' for string comparison. We
499 // revert back because we want the rest of the relative name to be
511 // No match. This is the end of the first argument. Get out
512 // of the loop as no more comparisons are necessary.
517 // Start the 2nd argument of the macro.
519 // Copy the remaining def_name (if any left)
522 ACE_OS::strcat (macro
,
530 // Am I in some kind of a multiple inheritance?
532 be_interface::in_mult_inheritance ()
534 if (this->in_mult_inheritance_
== -1)
536 // Compute once for all.
537 // Determine if we are in some form of a multiple inheritance.
538 if (this->traverse_inheritance_graph (
539 be_interface::in_mult_inheritance_helper
,
543 ACE_ERROR_RETURN ((LM_ERROR
,
544 "be_interface::in_mult_inheritance "
545 "error determining mult inheritance\n"),
550 return this->in_mult_inheritance_
;
554 be_interface::in_mult_inheritance (int mi
)
556 if (this->in_mult_inheritance_
== -1)
558 this->in_mult_inheritance_
= mi
;
563 be_interface::has_rw_attributes () const
565 return this->has_rw_attributes_
;
569 be_interface::redefine (AST_Interface
*from
)
571 be_interface
*bi
= dynamic_cast<be_interface
*> (from
);
572 this->var_out_seq_decls_gen_
= bi
->var_out_seq_decls_gen_
;
573 this->has_mixed_parentage_
= bi
->has_mixed_parentage_
;
575 if (bi
->has_mixed_parentage_
)
577 ACE_Unbounded_Queue
<AST_Interface
*> &q
=
578 idl_global
->mixed_parentage_interfaces ();
580 AST_Interface
**t
= nullptr;
582 // The queue of interfaces with mixed parentage must
583 // replace each interface that has been forward
584 // declared, since the pointer existing in the queue
585 // will be deleted after redefine() returns.
586 for (slot
= 0; slot
< q
.size (); ++slot
)
588 (void) q
.get (t
, slot
);
592 (void) q
.set (this, slot
);
598 AST_Interface::redefine (from
);
601 // Generate default constructors.
603 be_interface::gen_def_ctors (TAO_OutStream
*os
)
605 if (this->traverse_inheritance_graph (be_interface::gen_def_ctors_helper
,
607 ACE_ERROR ((LM_ERROR
,
608 "(%N:%l) be_interface::gen_def_ctors "
609 "error inheritance graph\n"));
614 be_interface::gen_def_ctors_helper (be_interface
* node
,
618 static int first
= 0;
624 *os
<< be_global
->impl_class_prefix () << base
->flat_name ()
625 << be_global
->impl_class_suffix () << " ()";
631 *os
<< ", " << be_global
->impl_class_prefix ()
632 << base
->flat_name ()
633 << be_global
->impl_class_suffix () << " ()";
647 be_interface::gen_stub_ctor (TAO_OutStream
*os
)
649 // Generate the constructor from stub and servant.
650 if (!this->is_local ())
652 bool const abstract
= this->is_abstract ();
654 << "ACE_INLINE" << be_nl
;
655 *os
<< this->name () << "::"
656 << this->local_name () << " ("
657 << be_idt
<< be_idt_nl
658 << "TAO_Stub *objref," << be_nl
659 << "::CORBA::Boolean _tao_collocated," << be_nl
660 << "TAO_Abstract_ServantBase *servant," << be_nl
661 << "TAO_ORB_Core *" << (abstract
? "" : "oc") << ")"
666 (this->has_mixed_parentage_
667 && !this->is_abstract_
668 && this->pd_n_inherits
> 0
669 && this->pd_inherits
[0]->is_abstract ())
670 || this->is_abstract_
;
672 if (this->has_mixed_parentage_
|| this->is_abstract_
)
675 << (the_check
? "AbstractBase" : "Object")
677 << be_idt
<< be_idt
<< be_idt_nl
678 << "objref," << be_nl
679 << "_tao_collocated," << be_nl
681 << (the_check
? "" : ", oc") << be_uidt_nl
687 << "::CORBA::AbstractBase ("
688 << be_idt
<< be_idt_nl
689 << "objref," << be_nl
690 << "_tao_collocated," << be_nl
691 << "servant" << be_uidt_nl
696 this->traverse_inheritance_graph (
697 be_interface::gen_abstract_init_helper
,
703 ACE_ERROR ((LM_ERROR
,
704 "be_interface::gen_stub_ctor - "
705 "inheritance graph traversal failed\n"));
713 if (the_check
&& !this->is_abstract_
)
715 *os
<< "," << be_uidt_nl
;
718 if (!this->is_abstract_
719 && (!this->has_mixed_parentage_
|| the_check
))
721 *os
<< "::CORBA::Object (objref, _tao_collocated, servant, oc)";
724 *os
<< be_uidt
<< be_uidt_nl
<< "{" << be_nl
<< "}";
728 // Generate the forward declarations and static methods used by the
729 // interface _var and _out template classes, as well as by the
730 // template sequence classes for object references.
732 be_interface::gen_var_out_seq_decls ()
734 if (this->var_out_seq_decls_gen_
)
739 const char *lname
= this->local_name ();
740 TAO_OutStream
*os
= tao_cg
->client_header ();
742 TAO_INSERT_COMMENT (os
);
744 // Generate the ifdefined macro for this interface.
745 os
->gen_ifdef_macro (this->flat_name (),
748 // Need this clunky string compare for when we are processing
749 // the *A.idl file. The *_sendc operations are generated in
750 // a separate interface distinguished only by the AMI4CCM_
751 // prefix. Since it does not come from implied IDL (in this
752 // execution of the IDL compiler) there is nothing
753 // to tell the IDL compiler that this interface is in any
754 // way special. All we can do is search for the prefix.
755 ACE_CString
test (lname
, nullptr, false);
756 bool has_ami4ccm_prefix
= (test
.find ("AMI4CCM_") == 0);
760 || this->is_ami4ccm_rh ()
761 || has_ami4ccm_prefix
);
763 /// Forward declare the handler interface before declaring
764 /// the original interface.
765 if (be_global
->ami_call_back ()
769 << "class AMI_" << lname
<< "Handler;" << be_nl
770 << "typedef AMI_" << lname
<< "Handler *AMI_"
771 << lname
<< "Handler_ptr;";
774 if (be_global
->ami4ccm_call_back ()
778 << "class AMI4CCM_" << lname
<< "Handler;" << be_nl
779 << "typedef AMI4CCM_" << lname
<< "Handler *AMI4CCM_"
780 << lname
<< "Handler_ptr;";
784 << "class " << lname
<< ";" << be_nl
785 << "using " << lname
<< "_ptr = " << lname
<< "*;";
788 << "using " << lname
<< "_var = TAO_Objref_Var_T<"
791 << "using " << lname
<< "_out = TAO_Objref_Out_T<"
797 this->var_out_seq_decls_gen_
= true;
800 // ****************************************************************
802 TAO_IDL_Inheritance_Hierarchy_Worker::~TAO_IDL_Inheritance_Hierarchy_Worker ()
806 // =================================================================
808 class TAO_IDL_Gen_OpTable_Worker
809 : public TAO_IDL_Inheritance_Hierarchy_Worker
812 TAO_IDL_Gen_OpTable_Worker (const char *skeleton_name
);
814 virtual int emit (be_interface
*derived_interface
,
816 be_interface
*base_interface
);
819 const char *skeleton_name_
;
822 TAO_IDL_Gen_OpTable_Worker::TAO_IDL_Gen_OpTable_Worker (
823 const char *skeleton_name
)
824 : skeleton_name_ (skeleton_name
)
829 TAO_IDL_Gen_OpTable_Worker::emit (be_interface
*derived_interface
,
831 be_interface
*base_interface
)
833 // Generate entries for the derived class using the properties of its
835 be_interface
*bi
= dynamic_cast<be_interface
*> (base_interface
);
836 return bi
->gen_optable_entries (derived_interface
,
837 this->skeleton_name_
,
841 // =================================================================
843 class Pure_Virtual_Regenerator
844 : public TAO_IDL_Inheritance_Hierarchy_Worker
847 Pure_Virtual_Regenerator (be_visitor
*visitor
);
849 virtual int emit (be_interface
*derived_interface
,
851 be_interface
*base_interface
);
854 be_visitor
*visitor_
;
857 Pure_Virtual_Regenerator::Pure_Virtual_Regenerator (be_visitor
*visitor
)
862 // We don't use the output stream in the signature but instead
863 // pass the visitor member (which is always be_visitor_operation_ch)
864 // to each iterator item, and (almost, see below) everything else
867 Pure_Virtual_Regenerator::emit (be_interface
*derived_interface
,
869 be_interface
*base_interface
)
871 if (derived_interface
== base_interface
)
876 // If the parent is local, it will already have its operations declared
877 // as pure virtual, and if it's abstract, its operations will already
878 // be generated as pure virtual for the derived local interface.
879 if (base_interface
->is_local () || base_interface
->is_abstract ())
884 be_decl
*d
= nullptr;
886 for (UTL_ScopeActiveIterator
si (base_interface
, UTL_Scope::IK_decls
);
890 d
= dynamic_cast<be_decl
*> (si
.item ());
892 if (d
->node_type () == AST_Decl::NT_op
)
894 // Hack to force the generation of the pure virtual ' = 0'
895 // at the end of the operation declaration.
898 if (d
->accept (this->visitor_
) == -1)
900 ACE_ERROR_RETURN ((LM_ERROR
,
901 "(%N:%l) Pure_Virtual_Regenerator::emit - "
902 "visit base interface operation failed\n"),
906 d
->set_local (false);
913 // =================================================================
916 be_interface::gen_operation_table (const char *flat_name
,
917 const char *skeleton_class_name
)
920 // find another way to determine whether this is an AMH class
921 // Create 'is_amh' methods, just like AMI. Problem is finding where
922 // to invoke these methods since an AMH class is generated twice:
923 // once for AMH and once the 'normal' way.
926 ACE_CString
tmp (skeleton_class_name
);
927 if (tmp
.strstr ("AMH_") != ACE_String_Base_Const::npos
)
932 // Check out the op_lookup_strategy.
933 switch (be_global
->lookup_strategy ())
935 case BE_GlobalData::TAO_DYNAMIC_HASH
:
937 this->skel_count_
= 0;
938 // Init the outstream appropriately.
939 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
941 // Start from current indentation level.
944 // Start the table generation.
946 << "static const TAO_operation_db_entry " << flat_name
947 << "_operations [] = {" << be_idt_nl
;
949 // Make sure the queues are empty.
950 this->insert_queue
.reset ();
951 this->del_queue
.reset ();
953 // Insert ourselves in the queue.
954 if (insert_queue
.enqueue_tail (this) == -1)
956 ACE_ERROR_RETURN ((LM_ERROR
,
957 "(%N:%l) be_interface::gen_operation_table - "
958 "error generating entries\n"),
962 // Traverse the graph.
963 TAO_IDL_Gen_OpTable_Worker
worker (skeleton_class_name
);
965 if (this->traverse_inheritance_graph (worker
, os
) == -1)
967 ACE_ERROR_RETURN ((LM_ERROR
,
968 "(%N:%l) be_interface::gen_operation_table - "
969 "inheritance graph traversal failed\n"), -1);
972 // Generate the skeleton for the is_a method.
975 *os
<< "{\"_is_a\", std::addressof(TAO_AMH_Skeletons::_is_a_amh_skel), nullptr}," << be_nl
;
977 else if (be_global
->gen_thru_poa_collocation ())
979 *os
<< "{\"_is_a\", std::addressof(TAO_ServantBase::_is_a_thru_poa_skel), nullptr}," << be_nl
;
983 *os
<< "{\"_is_a\", std::addressof(TAO_ServantBase::_is_a_skel), nullptr}," << be_nl
;
988 if (!be_global
->gen_minimum_corba ())
992 *os
<< "{\"_non_existent\", std::addressof(TAO_AMH_Skeletons"
993 << "::_non_existent_amh_skel), nullptr}," << be_nl
;
995 else if (be_global
->gen_thru_poa_collocation ())
997 *os
<< "{\"_non_existent\", std::addressof(TAO_ServantBase"
998 << "::_non_existent_thru_poa_skel), nullptr}," << be_nl
;
1002 *os
<< "{\"_non_existent\", std::addressof(TAO_ServantBase"
1003 << "::_non_existent_skel), nullptr}," << be_nl
;
1006 ++this->skel_count_
;
1009 if (!be_global
->gen_corba_e () && !be_global
->gen_minimum_corba ())
1013 *os
<< "{\"_component\", std::addressof(TAO_AMH_Skeletons"
1014 << "::_component_amh_skel), nullptr}," << be_nl
;
1016 else if (be_global
->gen_thru_poa_collocation ())
1018 *os
<< "{\"_component\", std::addressof(TAO_ServantBase"
1019 << "::_component_thru_poa_skel), nullptr}," << be_nl
;
1023 *os
<< "{\"_component\", std::addressof(TAO_ServantBase"
1024 << "::_component_skel), nullptr}," << be_nl
;
1027 ++this->skel_count_
;
1030 if (!be_global
->gen_corba_e () && !be_global
->gen_minimum_corba ())
1034 *os
<< "{\"_interface\", std::addressof(TAO_AMH_Skeletons"
1035 << "::_interface_amh_skel), nullptr}," << be_nl
;
1039 *os
<< "{\"_interface\", std::addressof(TAO_ServantBase"
1040 << "::_interface_skel), nullptr}," << be_nl
;
1043 ++this->skel_count_
;
1046 if (!be_global
->gen_minimum_corba ())
1050 *os
<< "{\"_repository_id\", std::addressof(TAO_AMH_Skeletons"
1051 << "::_repository_id_amh_skel), nullptr}" << be_uidt_nl
;
1053 else if (be_global
->gen_thru_poa_collocation ())
1055 *os
<< "{\"_repository_id\", std::addressof(TAO_ServantBase"
1056 << "::_repository_id_thru_poa_skel), nullptr}" << be_uidt_nl
;
1060 *os
<< "{\"_repository_id\", std::addressof(TAO_ServantBase"
1061 << "::_repository_id_skel), nullptr}" << be_uidt_nl
;
1064 ++this->skel_count_
;
1067 *os
<< "};" << be_nl_2
;
1068 *os
<< "static const ::CORBA::Long _tao_" << flat_name
1069 << "_optable_size = sizeof (ACE_Hash_Map_Entry<const char *,"
1070 << " TAO::Operation_Skeletons>) * (" << (3 * this->skel_count_
)
1072 *os
<< "static char _tao_" << flat_name
<< "_optable_pool "
1073 << "[_tao_" << flat_name
<< "_optable_size];" << be_nl
;
1074 *os
<< "static ACE_Static_Allocator_Base _tao_" << flat_name
1075 << "_allocator (_tao_" << flat_name
<< "_optable_pool, "
1076 << "_tao_" << flat_name
<< "_optable_size);" << be_nl
;
1077 *os
<< "static TAO_Dynamic_Hash_OpTable tao_"
1078 << flat_name
<< "_optable " << "(" << be_idt
<< be_idt_nl
1079 << flat_name
<< "_operations," << be_nl
1080 << this->skel_count_
<< "," << be_nl
1081 << 2 * this->skel_count_
<< "," << be_nl
1082 << "&_tao_" << flat_name
<< "_allocator" << be_uidt_nl
1083 << ");" << be_uidt_nl
;
1087 case BE_GlobalData::TAO_LINEAR_SEARCH
:
1088 // For generating linear search also, we are calling GPERF
1090 case BE_GlobalData::TAO_BINARY_SEARCH
:
1091 // For generating binary search also, we are calling GPERF
1093 case BE_GlobalData::TAO_PERFECT_HASH
:
1094 // For each interface in the IDL, have a new temp file to
1095 // collect the input for the gperf program.
1098 // We must randomize this a bit in order to avoid problems with
1099 // processing more than one idl file (in separate processes) with
1100 // the same name (in different directories).
1101 char *temp_file
= nullptr;
1102 ACE_NEW_RETURN (temp_file
,
1103 char [ACE_OS::strlen (idl_global
->temp_dir ())
1104 + 11 // The number of possible digits in
1105 // a 32-bit number plus a dot
1106 + 11 // for process id
1107 + ACE_OS::strlen (flat_name
)
1108 + ACE_OS::strlen (".gperf")
1112 // This degree of randomness is necessary because there was an
1113 // obscure chance of even this arriving at colliding filenames
1114 // on multiprocessor machines when the IDL compiler was run at
1115 // exactly the same time.
1117 (static_cast<unsigned int> (ACE_OS::time())
1118 + static_cast<unsigned int> (ACE_OS::getpid ()));
1119 ACE_OS::sprintf (temp_file
,
1121 idl_global
->temp_dir (),
1122 ACE_OS::rand_r (&seed
),
1123 static_cast<int> (ACE_OS::getpid ()),
1126 // QNX can't handle individual file names (path components)
1127 // longer than 48 characters.
1128 #if defined(__QNX__)
1129 size_t const temp_dir_len
= ACE_OS::strlen (idl_global
->temp_dir ());
1131 if (ACE_OS::strlen (temp_file
) > temp_dir_len
+ 47)
1133 temp_file
[temp_dir_len
+ 47] = 0;
1135 #endif /* defined(__QNX__) */
1137 // Save this file name with the codegen singleton.
1138 tao_cg
->gperf_input_filename (temp_file
);
1140 // Make a new outstream to hold the gperf_temp_file for this
1142 TAO_OutStream
*os
= nullptr;
1143 ACE_NEW_NORETURN (os
, TAO_OutStream
);
1147 ACE_ERROR_RETURN ((LM_ERROR
,
1148 "be_visitor_interface_ss"
1151 "make_outstream failed\n"),
1155 // Store the outstream with the codegen singleton.
1156 tao_cg
->gperf_input_stream (os
);
1158 // Open the temp file.
1159 if (os
->open (temp_file
,
1160 TAO_OutStream::TAO_GPERF_INPUT
) == -1)
1162 ACE_ERROR_RETURN ((LM_ERROR
,
1163 "be_visitor_interface_ss"
1166 "gperf_input.tmp file open failed\n"),
1170 // Add the gperf input header.
1171 this->gen_gperf_input_header (os
);
1173 // Make sure the queues are empty.
1174 this->insert_queue
.reset ();
1175 this->del_queue
.reset ();
1177 // Insert ourselves in the queue.
1178 if (insert_queue
.enqueue_tail (this) == -1)
1180 ACE_ERROR_RETURN ((LM_ERROR
,
1181 "(%N:%l) be_interface::gen_operation_table - "
1182 "error generating entries\n"),
1186 // Traverse the graph.
1187 TAO_IDL_Gen_OpTable_Worker
worker (skeleton_class_name
);
1189 if (this->traverse_inheritance_graph (worker
, os
) == -1)
1191 ACE_ERROR_RETURN ((LM_ERROR
,
1192 "(%N:%l) be_interface::gen_operation_table - "
1193 "inheritance graph traversal failed\n"),
1199 *os
<< "_is_a,std::addressof(TAO_AMH_Skeletons"
1200 << "::_is_a_amh_skel), nullptr" << be_nl
;
1202 else if (be_global
->gen_thru_poa_collocation ())
1204 *os
<< "_is_a,std::addressof(TAO_ServantBase"
1205 << "::_is_a_thru_poa_skel), nullptr" << be_nl
;
1209 *os
<< "_is_a,std::addressof(TAO_ServantBase"
1210 << "::_is_a_skel), nullptr" << be_nl
;
1213 ++this->skel_count_
;
1215 if (!be_global
->gen_minimum_corba ())
1219 *os
<< "_non_existent,std::addressof(TAO_AMH_Skeletons"
1220 << "::_non_existent_amh_skel), nullptr" << be_nl
;
1222 else if (be_global
->gen_thru_poa_collocation ())
1224 *os
<< "_non_existent,std::addressof(TAO_ServantBase"
1225 << "::_non_existent_thru_poa_skel), nullptr" << be_nl
;
1229 *os
<< "_non_existent,std::addressof(TAO_ServantBase"
1230 << "::_non_existent_skel), nullptr" << be_nl
;
1233 ++this->skel_count_
;
1236 if (!be_global
->gen_corba_e () && !be_global
->gen_minimum_corba ())
1240 *os
<< "_component,std::addressof(TAO_AMH_Skeletons"
1241 << "::_component_amh_skel), nullptr" << be_nl
;
1243 else if (be_global
->gen_thru_poa_collocation ())
1245 *os
<< "_component,std::addressof(TAO_ServantBase"
1246 << "::_component_thru_poa_skel), nullptr" << be_nl
;
1250 *os
<< "_component,std::addressof(TAO_ServantBase"
1251 << "::_component_skel), nullptr" << be_nl
;
1253 ++this->skel_count_
;
1256 if (!be_global
->gen_corba_e () && !be_global
->gen_minimum_corba ())
1260 *os
<< "_interface,std::addressof(TAO_AMH_Skeletons"
1261 << "::_interface_amh_skel), nullptr" << be_nl
;
1265 *os
<< "_interface,std::addressof(TAO_ServantBase"
1266 << "::_interface_skel), nullptr" << be_nl
;
1269 ++this->skel_count_
;
1272 if (!be_global
->gen_minimum_corba ())
1276 *os
<< "_repository_id,std::addressof(TAO_AMH_Skeletons"
1277 << "::_repository_id_amh_skel), nullptr" << be_nl
;
1279 else if (be_global
->gen_thru_poa_collocation ())
1281 *os
<< "_repository_id,std::addressof(TAO_ServantBase"
1282 << "::_repository_id_thru_poa_skel), nullptr" << be_nl
;
1286 *os
<< "_repository_id,std::addressof(TAO_ServantBase"
1287 << "::_repository_id_skel), nullptr" << be_nl
;
1290 ++this->skel_count_
;
1293 // Input to the gperf is ready. Run gperf and get things
1294 // done. This method also unlinks the temp file that we used
1296 this->gen_gperf_things (flat_name
);
1301 ACE_ERROR_RETURN ((LM_ERROR
,
1304 "gen_operation_table"
1305 "unknown op_lookup_strategy\n"),
1313 be_interface::convert_parent_ops (be_visitor
*visitor
)
1315 // Make sure the queues are empty.
1316 this->insert_queue
.reset ();
1317 this->del_queue
.reset ();
1319 // Insert ourselves in the queue.
1320 if (insert_queue
.enqueue_tail (this) == -1)
1322 ACE_ERROR_RETURN ((LM_ERROR
,
1323 "(%N:%l) be_interface::convert_parent_ops - "
1324 "error generating entries\n"),
1328 // Traverse the graph.
1329 Pure_Virtual_Regenerator
worker (visitor
);
1331 if (this->traverse_inheritance_graph (worker
, nullptr) == -1)
1333 ACE_ERROR_RETURN ((LM_ERROR
,
1334 "(%N:%l) be_interface::"
1335 "convert_parent_ops - "
1336 "codegen for base class operations failed\n"),
1343 // Output the header (type declaration and %%) to the gperf's input
1346 be_interface::gen_gperf_input_header (TAO_OutStream
*os
)
1348 *os
<< "TAO_operation_db_entry {\n"
1349 << "\tchar * opname;" << "\n"
1350 << "\tTAO_Skeleton skel_ptr;" << "\n"
1356 // We separate the generation of operation table entries from the
1357 // "gen_operation_table" method. This enables us to invoke generation of
1358 // entries for interfaces from which we inherit without any additional
1359 // code. The parameter "derived" is the one for which the entire operation
1360 // table is being built.
1362 be_interface::gen_optable_entries (be_interface
*derived_interface
,
1363 const char *full_skeleton_name
,
1366 int const lookup_strategy
=
1367 be_global
->lookup_strategy ();
1369 if (lookup_strategy
== BE_GlobalData::TAO_DYNAMIC_HASH
)
1371 for (UTL_ScopeActiveIterator
si (this, UTL_Scope::IK_decls
);
1375 // Get the next AST decl node
1376 AST_Decl
*d
= si
.item ();
1378 if (d
->node_type () == AST_Decl::NT_op
)
1381 dynamic_cast<be_operation
*> (d
);
1383 if (op
->is_sendc_ami ())
1388 // We are an operation node.
1389 *os
<< "{\"" << d
->original_local_name () << "\", std::addressof("
1390 << full_skeleton_name
<< "::"
1391 << d
->local_name () << "_skel),";
1393 if (be_global
->gen_direct_collocation ())
1395 *os
<< " std::addressof("
1396 << this->full_direct_proxy_impl_name ()
1397 << "::" << d
->local_name () << ")";
1404 *os
<< "}," << be_nl
;
1406 ++derived_interface
->skel_count_
;
1408 else if (d
->node_type () == AST_Decl::NT_attr
)
1410 AST_Attribute
*attr
=
1411 dynamic_cast<AST_Attribute
*> (d
);
1413 if (attr
== nullptr)
1416 // Generate only the "get" entry if we are
1418 *os
<< "{\"_get_" << d
->original_local_name ()
1419 << "\", std::addressof(" << full_skeleton_name
1420 << "::_get_" << d
->local_name () << "_skel),";
1422 if (be_global
->gen_direct_collocation ())
1424 *os
<< " std::addressof("
1425 << this->full_direct_proxy_impl_name ()
1426 << "::_get_" << d
->local_name () << ")";
1433 *os
<< "}," << be_nl
;
1435 ++derived_interface
->skel_count_
;
1437 if (!attr
->readonly ())
1440 *os
<< "{\"_set_" << d
->original_local_name ()
1441 << "\", std::addressof(" << full_skeleton_name
1442 << "::_set_" << d
->local_name () << "_skel),";
1444 if (be_global
->gen_direct_collocation ())
1446 *os
<< " std::addressof("
1447 << this->full_direct_proxy_impl_name ()
1448 << "::_set_" << d
->local_name () << ")";
1455 *os
<< "}," << be_nl
;
1457 ++derived_interface
->skel_count_
;
1462 else if (lookup_strategy
== BE_GlobalData::TAO_LINEAR_SEARCH
1463 || lookup_strategy
== BE_GlobalData::TAO_BINARY_SEARCH
1464 || lookup_strategy
== BE_GlobalData::TAO_PERFECT_HASH
)
1466 // We call GPERF for all these three strategies.
1467 // Init the outstream.
1468 // @@ We probably do no need to do this, the "right" <os>
1469 // argument is passed down!!
1470 os
= tao_cg
->gperf_input_stream ();
1472 for (UTL_ScopeActiveIterator
si (this, UTL_Scope::IK_decls
);
1476 // get the next AST decl node
1477 AST_Decl
*d
= si
.item ();
1479 if (d
->node_type () == AST_Decl::NT_op
)
1482 dynamic_cast<be_operation
*> (d
);
1484 if (op
->is_sendc_ami ())
1489 // Generate operation name.
1491 // We are an operation node. We use the original
1492 // operation name, not the one with _cxx_ in it.
1493 // We need to the name of the base class!! But since
1494 // we don't know whether this is an AMH class, we
1495 // need to check this, using the full_skeleton_name
1496 // TODO: find a more elegant solution for this
1497 ACE_CString
tmp (full_skeleton_name
);
1498 if (tmp
.strstr ("AMH_") != ACE_String_Base_Const::npos
)
1500 ACE_CString
name (d
->full_name ());
1501 ACE_String_Base_Const::size_type
const last
= name
.rfind(':') - 1;
1502 name
= name
.substring (0, last
);
1503 if (name
.rfind (':') != ACE_String_Base_Const::npos
)
1505 ACE_CString nspace
= name
.substring (0, name
.rfind (':') - 1);
1506 name
= name
.substring (name
.rfind (':') + 1);
1507 *os
<< d
->original_local_name () << ",std::addressof(POA_"
1508 << nspace
.c_str () << "::AMH_"
1509 << name
.c_str () << "::"
1510 << d
->original_local_name ()
1515 *os
<< d
->original_local_name () << ",std::addressof(POA_AMH_"
1516 << name
.c_str () << "::"
1517 << d
->original_local_name ()
1523 if (!d
->is_abstract ())
1525 *os
<< d
->original_local_name () << ",std::addressof(POA_"
1526 << d
->full_name () << "_skel),";
1530 *os
<< d
->original_local_name () << ",std::addressof("
1531 << full_skeleton_name
<< "::"
1532 << d
->original_local_name ()
1536 if (be_global
->gen_direct_collocation ())
1538 if (!d
->is_abstract ())
1540 *os
<< " std::addressof("
1541 << this->full_direct_proxy_impl_name ()
1542 << "::" << d
->local_name () << ")";
1546 *os
<< " std::addressof("
1547 << derived_interface
->full_direct_proxy_impl_name ()
1548 << "::" << d
->local_name () << ")";
1559 ++this->skel_count_
;
1561 else if (d
->node_type () == AST_Decl::NT_attr
)
1563 AST_Attribute
*attr
=
1564 dynamic_cast<AST_Attribute
*> (d
);
1566 if (attr
== nullptr)
1571 // Generate only the "get" entry if we are readonly.
1572 // we need to split the full name in order to push _set_
1573 // or _get_ in between the namespace and attribute name.
1575 //determine the correct namespace
1576 ACE_CString
nspace (d
->full_name ());
1577 ACE_String_Base_Const::size_type
const pos
= nspace
.rfind(':');
1578 nspace
= nspace
.substring(0, pos
+ 1);
1580 if (!d
->is_abstract ())
1582 *os
<< "_get_" << d
->original_local_name () << ",std::addressof(POA_"
1583 << nspace
.c_str () << "_get_"
1584 << d
->original_local_name () << "_skel),";
1586 if (be_global
->gen_direct_collocation ())
1588 *os
<< " std::addressof("
1589 << this->full_direct_proxy_impl_name ()
1590 << "::_get_" << d
->local_name () << ")";
1599 *os
<< "_get_" << d
->original_local_name () << ",std::addressof("
1600 << full_skeleton_name
<< "::_get_"
1601 << d
->original_local_name () << "_skel),";
1603 if (be_global
->gen_direct_collocation ())
1605 *os
<< " std::addressof("
1606 << derived_interface
->full_direct_proxy_impl_name ()
1607 << "::_get_" << d
->local_name () << ")";
1617 ++this->skel_count_
;
1619 if (!attr
->readonly ())
1621 if (!d
->is_abstract ())
1624 *os
<< "_set_" << d
->original_local_name () << ",std::addressof(POA_"
1625 << nspace
.c_str () << "_set_"
1626 << d
->original_local_name () << "_skel),";
1628 if (be_global
->gen_direct_collocation ())
1630 *os
<< " std::addressof("
1631 << this->full_direct_proxy_impl_name ()
1632 << "::_set_" << d
->local_name () << ")";
1641 // The set method in case abstract
1642 *os
<< "_set_" << d
->original_local_name () << ",std::addressof("
1643 << full_skeleton_name
<< "::_set_"
1644 << d
->original_local_name () << "_skel),";
1646 if (be_global
->gen_direct_collocation ())
1648 *os
<< " std::addressof("
1649 << derived_interface
->full_direct_proxy_impl_name ()
1650 << "::_set_" << d
->local_name () << ")";
1660 ++this->skel_count_
;
1667 ACE_ERROR_RETURN ((LM_ERROR
,
1668 "be_interface::gen_optable_entries - "
1669 "unknown op_lookup_strategy\n"),
1677 be_interface::gen_ostream_operator (TAO_OutStream
*os
,
1678 bool /* use_underscore */)
1681 << "std::ostream& operator<< (" << be_idt
<< be_idt_nl
1682 << "std::ostream &strm," << be_nl
1683 << "const " << this->name () << "_ptr _tao_objref" << be_uidt_nl
1684 << ")" << be_uidt_nl
1686 << "return ::CORBA::"
1687 << (this->is_abstract () ? "AbstractBase" : "Object")
1688 << "::_tao_stream (strm, _tao_objref);"
1694 be_interface::gen_member_ostream_operator (TAO_OutStream
*os
,
1695 const char *instance_name
,
1696 bool /* use_underscore */,
1699 *os
<< instance_name
<< (accessor
? " ()" : ".in ()");
1702 // ****************************************************************
1704 be_code_emitter_wrapper::be_code_emitter_wrapper (
1705 be_interface::tao_code_emitter emitter
)
1706 : emitter_ (emitter
)
1711 be_code_emitter_wrapper::emit (be_interface
*derived_interface
,
1712 TAO_OutStream
*output_stream
,
1713 be_interface
*base_interface
)
1715 return this->emitter_ (derived_interface
,
1720 // ****************************************************************
1722 // Template method that traverses the inheritance graph in a breadth-first
1723 // style. The actual work on each element in the inheritance graph is carried
1724 // out by the function passed as argument.
1726 be_interface::traverse_inheritance_graph (
1727 be_interface::tao_code_emitter gen
,
1729 bool abstract_paths_only
,
1730 bool add_ccm_object
)
1732 // Make sure the queues are empty.
1733 this->insert_queue
.reset ();
1734 this->del_queue
.reset ();
1736 // Insert ourselves in the queue.
1737 if (insert_queue
.enqueue_tail (this) == -1)
1739 ACE_ERROR_RETURN ((LM_ERROR
,
1740 "(%N:%l) be_interface::traverse_inheritance_graph"
1741 " - error generating entries\n"),
1745 be_code_emitter_wrapper
wrapper (gen
);
1748 this->traverse_inheritance_graph (wrapper
,
1750 abstract_paths_only
,
1755 be_interface::traverse_inheritance_graph (
1756 TAO_IDL_Inheritance_Hierarchy_Worker
&worker
,
1758 bool abstract_paths_only
,
1759 bool add_ccm_object
)
1761 AST_Type
*intf
= nullptr; // element inside the queue
1763 if (!this->insert_queue
.is_empty ())
1765 // Dequeue the element at the head of the queue.
1766 if (this->insert_queue
.dequeue_head (intf
) != 0)
1768 ACE_ERROR_RETURN ((LM_ERROR
,
1769 "(%N:%l) be_interface::traverse_graph - "
1770 "dequeue_head failed\n"),
1774 AST_Decl::NodeType nt
= intf
->node_type ();
1776 // If we are doing a home, we check for a parent.
1777 if (nt
== AST_Decl::NT_home
)
1779 this->enqueue_base_home_r (
1780 dynamic_cast<AST_Home
*> (intf
));
1783 // If we are doing a component, we check for a parent.
1784 if (nt
== AST_Decl::NT_component
|| nt
== AST_Decl::NT_connector
)
1788 (void) this->insert_non_dup (be_global
->ccmobject ());
1791 this->enqueue_base_component_r (
1792 dynamic_cast<AST_Component
*> (intf
));
1795 (void) this->insert_non_dup (intf
, abstract_paths_only
);
1798 // Do until queue is empty.
1799 while (!this->insert_queue
.is_empty ())
1801 // Use breadth-first strategy i.e., first generate entries for ourselves,
1802 // followed by nodes that we immediately inherit from, and so on. In the
1803 // process make sure that we do not generate code for the same node more
1804 // than once. Such a case may arise due to multiple inheritance forming
1805 // a diamond-like inheritance graph.
1807 // Dequeue the element at the head of the queue.
1808 if (this->insert_queue
.dequeue_head (intf
))
1810 ACE_ERROR_RETURN ((LM_ERROR
,
1811 "(%N:%l) be_interface::traverse_graph - "
1812 "dequeue_head failed\n"),
1816 // Insert the dequeued element in the del_queue.
1817 if (this->del_queue
.enqueue_tail (intf
) == -1)
1819 ACE_ERROR_RETURN ((LM_ERROR
,
1820 "(%N:%l) be_interface::traverse_graph - "
1821 "enqueue_head failed\n"),
1825 be_interface
*bi
= dynamic_cast<be_interface
*> (intf
);
1827 // Use the helper method to generate code for ourself using the
1828 // properties of the element dequeued. For the first iteration, the
1829 // element dequeued and "this" will be the same i.e., ourselves.
1830 if (worker
.emit (this, os
, bi
) == -1)
1832 ACE_ERROR_RETURN ((LM_ERROR
,
1833 "(%N:%l) be_interface::traverse_graph - "
1834 "helper code gen failed\n"),
1837 } // end of while queue not empty
1842 // Run GPERF and get the correct lookup and other operations
1843 // depending on which strategy we are using. Returns 0 on sucess, -1
1846 be_interface::gen_gperf_things (const char *flat_name
)
1848 // GPERF can give Binary search, Linear search and Perfect Hash
1849 // methods. Generate the class definition according to that.
1851 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
1853 TAO_INSERT_COMMENT (os
);
1855 // Generate the correct class definition for the operation lookup
1856 // strategy. Then, get the lookup method from GPERF. And then,
1857 // instantiate the correct class for the operation lookup strategy
1858 // we are following.
1859 switch (be_global
->lookup_strategy ())
1861 case BE_GlobalData::TAO_PERFECT_HASH
:
1862 // Output a class definition deriving from
1863 // TAO_Perfect_Hash_OpTable.
1864 this->gen_perfect_hash_class_definition (flat_name
);
1866 // Call GPERF and get the methods defined.
1867 if (this->gen_gperf_lookup_methods (flat_name
) == -1)
1872 // Create an instance of the correct class corresponding the
1873 // operation lookup strategy we are following.
1874 this->gen_perfect_hash_instance (flat_name
);
1878 case BE_GlobalData::TAO_BINARY_SEARCH
:
1879 // Output a class definition deriving from
1880 // TAO_Binary_Search_OpTable.
1881 this->gen_binary_search_class_definition (flat_name
);
1883 // Call GPERF and get the methods defined.
1884 if (gen_gperf_lookup_methods (flat_name
) == -1)
1889 // Create an instance of the correct class corresponding the
1890 // operation lookup strategy we are following.
1891 this->gen_binary_search_instance (flat_name
);
1895 case BE_GlobalData::TAO_LINEAR_SEARCH
:
1896 // Output a class definition deriving from
1897 // TAO_Linear_Search_OpTable.
1898 this->gen_linear_search_class_definition (flat_name
);
1900 // Call GPERF and get the methods defined.
1901 if (this->gen_gperf_lookup_methods (flat_name
) == -1)
1906 // Create an instance of the correct class corresponding the
1907 // operation lookup strategy we are following.
1908 this->gen_linear_search_instance (flat_name
);
1915 "tao_idl:ERROR:%N:%l:Unknown Operation Lookup Strategy\n"),
1922 // Outputs the class definition for the perfect hashing. This class
1923 // will inherit from the TAO_Perfect_Hash_OpTable.
1925 be_interface::gen_perfect_hash_class_definition (const char *flat_name
)
1928 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
1930 *os
<< "class " << "TAO_" << flat_name
<< "_Perfect_Hash_OpTable"
1932 << ": public TAO_Perfect_Hash_OpTable" << be_uidt_nl
1934 << "private:" << be_idt_nl
1935 << "unsigned int hash (const char *str, unsigned int len) override;"
1936 << be_uidt_nl
<< be_nl
1937 << "public:" << be_idt_nl
1938 << "const TAO_operation_db_entry * lookup "
1939 << "(const char *str, unsigned int len) override;"
1944 // Outputs the class definition for the binary searching. This class
1945 // will inherit from the TAO_Binary_Seach_OpTable.
1947 be_interface::gen_binary_search_class_definition (const char *flat_name
)
1950 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
1952 *os
<< "class " << "TAO_" << flat_name
<< "_Binary_Search_OpTable"
1954 << ": public TAO_Binary_Search_OpTable" << be_uidt_nl
1956 << "public:" << be_idt_nl
1957 << "const TAO_operation_db_entry * lookup (const char *str) override;"
1962 // Outputs the class definition for the linear search. This class
1963 // will inherit from the TAO_Linear_Search_OpTable.
1965 be_interface::gen_linear_search_class_definition (const char *flat_name
)
1968 TAO_OutStream
*ss
= tao_cg
->server_skeletons ();
1970 *ss
<< "class " << "TAO_" << flat_name
<< "_Linear_Search_OpTable"
1972 << ": public TAO_Linear_Search_OpTable" << be_nl
1974 << "public:" << be_idt_nl
1975 << "const TAO_operation_db_entry * lookup (const char *str) override;"
1980 // We have collected the input (Operations and the corresponding
1981 // skeleton pointers) for the gperf program. Now let us execute gperf
1982 // and get things done.
1983 // GPERF reads from our temp file and write to the Server Skeleton
1986 be_interface::gen_gperf_lookup_methods (const char *flat_name
)
1988 // Using ACE_Process.
1989 ACE_Process process
;
1990 ACE_Process_Options process_options
;
1992 // Adjust the offset of the underlying file pointer.
1993 ACE_OS::rewind (tao_cg
->gperf_input_stream ()->file ());
1995 // Set the stdin and stdout appropriately for the gperf program.
1997 // Stdin is our temp file. Close the temp file and open. We will use
1998 // <open_temp_file> to open the file now, so that the file will get
1999 // deleted once when we close the file.
2002 if (ACE_OS::fclose (tao_cg
->gperf_input_stream ()->file ()) == -1)
2004 ACE_ERROR_RETURN ((LM_ERROR
,
2005 ACE_TEXT ("Error:%p:File close failed ")
2006 ACE_TEXT ("on temp gperf's input file\n"),
2011 // And reset file to 0 because otherwise there is a problem during destruction of stream.
2012 tao_cg
->gperf_input_stream ()->file () = nullptr;
2014 // Open the temp file.
2016 ACE::open_temp_file (
2017 ACE_TEXT_CHAR_TO_TCHAR (tao_cg
->gperf_input_filename ()),
2020 if (input
== ACE_INVALID_HANDLE
)
2024 ACE_TEXT ("Error:%p:File open failed on ")
2025 ACE_TEXT ("gperf's temp input file %s\n"),
2027 tao_cg
->gperf_input_filename ()),
2031 // Flush the output stream. Gperf also uses it as output. Ensure
2032 // current contents are written before gperf writes.
2033 ACE_OS::fflush (tao_cg
->server_skeletons ()->file ());
2035 // Stdout is server skeleton. Do *not* close the file, just open
2036 // again with <ACE_OS::open> with WRITE + APPEND option.. After
2037 // this, remember to update the file offset to the correct location.
2039 ACE_OS::open (be_global
->be_get_server_skeleton_fname (),
2040 O_WRONLY
| O_APPEND
);
2042 if (output
== ACE_INVALID_HANDLE
)
2044 ACE_OS::close (input
);
2045 ACE_ERROR_RETURN ((LM_ERROR
,
2046 ACE_TEXT ("Error:%p:File open failed ")
2047 ACE_TEXT ("on server skeleton file\n"),
2052 // Seek to the end of the output file.
2053 ACE_OS::lseek (output
, 0, SEEK_END
);
2055 // Set the handles now in the process options.
2056 process_options
.set_handles (input
, output
);
2060 // Set the command line for the gperf program. Give the right
2061 // arguments for the operation lookup strategy that we are using.
2062 switch (be_global
->lookup_strategy ())
2065 case BE_GlobalData::TAO_PERFECT_HASH
:
2066 process_options
.command_line (ACE_TEXT ("%s")
2068 ACE_TEXT ("-m -M -J -c -C")
2070 ACE_TEXT ("-D -E -T -f 0")
2074 ACE_TEXT ("-a -o -t -p -K")
2076 ACE_TEXT ("opname -L C++")
2078 ACE_TEXT ("-Z TAO_%s_Perfect_Hash_OpTable")
2080 ACE_TEXT ("-N lookup"),
2081 idl_global
->gperf_path (),
2085 // Binary search methods from GPERF. Everythis and the -B flag.
2086 case BE_GlobalData::TAO_BINARY_SEARCH
:
2087 process_options
.command_line (ACE_TEXT ("%s")
2091 ACE_TEXT ("-m -M -J -c -C")
2093 ACE_TEXT ("-D -E -T -f 0")
2095 ACE_TEXT ("-F 0,0,0")
2097 ACE_TEXT ("-a -o -t -p -K")
2099 ACE_TEXT ("opname -L C++")
2101 ACE_TEXT ("-Z TAO_%s_Binary_Search_OpTable")
2103 ACE_TEXT ("-N lookup"),
2104 idl_global
->gperf_path (),
2108 // Linear search methods from GPERF. Everything and the -Z flag.
2109 case BE_GlobalData::TAO_LINEAR_SEARCH
:
2110 process_options
.command_line (ACE_TEXT ("%s")
2114 ACE_TEXT ("-m -M -J -c -C")
2116 ACE_TEXT ("-D -E -T -f 0")
2120 ACE_TEXT ("-a -o -t -p -K")
2122 ACE_TEXT ("opname -L C++")
2124 ACE_TEXT ("-Z TAO_%s_Linear_Search_OpTable")
2126 ACE_TEXT ("-N lookup"),
2127 idl_global
->gperf_path (),
2132 ACE_ERROR ((LM_ERROR
,
2133 ACE_TEXT ("tao_idl:ERROR:%N:%l:Unknown ")
2134 ACE_TEXT ("Operation Lookup Strategy\n")));
2141 result
= process
.spawn (process_options
);
2143 // Spawn a process for gperf.
2146 ACE_ERROR ((LM_ERROR
,
2147 ACE_TEXT ("Error:%p:Couldn't spawn a ")
2148 ACE_TEXT ("process for gperf program\n")));
2151 // Wait for gperf to complete.
2154 ACE_exitcode exitcode
;
2155 result
= process
.wait (&exitcode
);
2159 ACE_ERROR ((LM_ERROR
,
2160 ACE_TEXT ("Error:%p:gperf program ")
2161 ACE_TEXT ("returned exit code %d.\n"),
2166 // Adjust the file offset to the EOF for the server skeleton
2168 ACE_OS::fseek (tao_cg
->server_skeletons ()->file (),
2173 ACE_OS::close (output
);
2174 ACE_OS::close (input
);
2179 // Create an instance of this perfect hash table.
2181 be_interface::gen_perfect_hash_instance (const char *flat_name
)
2184 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
2187 << "static TAO_" << flat_name
<< "_Perfect_Hash_OpTable"
2189 << "tao_" << flat_name
<< "_optable;";
2192 // Create an instance of the binary search optable.
2194 be_interface::gen_binary_search_instance (const char *flat_name
)
2197 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
2200 << "static TAO_" << flat_name
<< "_Binary_Search_OpTable"
2202 << "tao_" << flat_name
<< "_optable;";
2206 // Create an instance of this perfect hash table.
2208 be_interface::gen_linear_search_instance (const char *flat_name
)
2211 TAO_OutStream
*os
= tao_cg
->server_skeletons ();
2214 << "static TAO_" << flat_name
<< "_Linear_Search_OpTable"
2216 << "tao_" << flat_name
<< "_optable;";
2220 be_interface::is_a_helper (be_interface
* /*derived*/,
2224 // Emit the comparison code.
2225 *os
<< "std::strcmp (value, \"" << bi
->repoID () << "\") == 0 ||" << be_nl
;
2231 be_interface::copy_ctor_helper (be_interface
*derived
,
2235 // We can't call ourselves in a copy constructor, and
2236 // abstract interfaces don't exist on the skeleton side.
2237 if (derived
== base
|| base
->is_abstract () || derived
->nmembers () > 0)
2242 *os
<< "," << be_idt_nl
;
2245 (ACE_OS::strcmp (base
->flat_name (), "Messaging_ReplyHandler") == 0);
2249 *os
<< "::POA_Messaging::ReplyHandler (rhs)";
2251 else if (base
->is_nested ())
2253 be_decl
*scope
= nullptr;
2254 scope
= dynamic_cast<be_scope
*> (base
->defined_in ())->decl ();
2256 *os
<< "POA_" << scope
->name () << "::"
2257 << base
->local_name () << " (rhs)";
2261 *os
<< base
->full_skel_name () << " (rhs)";
2270 be_interface::in_mult_inheritance_helper (be_interface
*derived
,
2274 switch (derived
->n_inherits ())
2278 derived
->in_mult_inheritance (0);
2281 if (derived
== base
)
2283 // Prevent indefinite recursion.
2284 derived
->in_mult_inheritance (-1);
2288 // One parent. We have the same characteristics as our base.
2289 derived
->in_mult_inheritance (base
->in_mult_inheritance ());
2294 // Direct multiple inheritance.
2295 derived
->in_mult_inheritance (1);
2302 be_interface::gen_abstract_init_helper (be_interface
*node
,
2311 *os
<< "," << be_nl
;
2313 if (base
->is_nested ())
2315 UTL_Scope
*parent_scope
= base
->defined_in ();
2316 AST_Decl
*parent_decl
= ScopeAsDecl (parent_scope
);
2319 << parent_decl
->name () << "::"
2320 << base
->local_name ()<< " (" << be_idt
<< be_idt_nl
;
2324 *os
<< base
->name () << " (" << be_idt
<< be_idt_nl
;
2327 *os
<< "objref," << be_nl
2328 << "_tao_collocated," << be_nl
2329 << "servant" << be_uidt_nl
2337 be_interface::op_attr_decl_helper (be_interface
* /*derived */,
2338 be_interface
*ancestor
,
2341 if (dynamic_cast<be_component
*> (ancestor
) != nullptr)
2346 be_visitor_context ctx
;
2348 ctx
.state (TAO_CodeGen::TAO_ROOT_SVH
);
2350 for (UTL_ScopeActiveIterator
si (ancestor
, UTL_Scope::IK_decls
);
2354 // Get the next AST decl node
2355 AST_Decl
*d
= si
.item ();
2356 AST_Decl::NodeType nt
= d
->node_type ();
2358 if (nt
== AST_Decl::NT_op
)
2360 be_operation
*op
= dynamic_cast<be_operation
*> (d
);
2362 /// No sendc_* operations in facet servants. If the
2363 /// original interface had these generated as AMI
2364 /// implied IDL, we want to skip them.
2365 if (be_global
->in_facet_servant () && op
->is_sendc_ami ())
2370 be_visitor_operation_ch
v (&ctx
);
2372 if (v
.visit_operation (op
) == -1)
2374 ACE_ERROR_RETURN ((LM_ERROR
,
2375 ACE_TEXT ("be_interface::")
2376 ACE_TEXT ("op_attr_decl_helper - ")
2377 ACE_TEXT ("visit_operation()")
2378 ACE_TEXT (" failed\n")),
2382 else if (nt
== AST_Decl::NT_attr
)
2384 be_attribute
*attr
= dynamic_cast<be_attribute
*> (d
);
2385 be_visitor_attribute
v (&ctx
);
2387 if (v
.visit_attribute (attr
) == -1)
2389 ACE_ERROR_RETURN ((LM_ERROR
,
2390 ACE_TEXT ("be_interface::")
2391 ACE_TEXT ("op_attr_decl_helper - ")
2392 ACE_TEXT ("visit_attribute()")
2393 ACE_TEXT (" failed\n")),
2403 be_interface::destroy ()
2405 delete [] this->full_skel_name_
;
2406 this->full_skel_name_
= nullptr;
2408 delete [] this->full_coll_name_
;
2409 this->full_coll_name_
= nullptr;
2411 delete [] this->local_coll_name_
;
2412 this->local_coll_name_
= nullptr;
2414 delete [] this->relative_skel_name_
;
2415 this->relative_skel_name_
= nullptr;
2417 delete [] this->direct_proxy_impl_name_
;
2418 this->direct_proxy_impl_name_
= nullptr;
2420 delete [] this->full_direct_proxy_impl_name_
;
2421 this->full_direct_proxy_impl_name_
= nullptr;
2423 delete [] this->client_scope_
;
2424 this->client_scope_
= nullptr;
2426 delete [] this->flat_client_scope_
;
2427 this->flat_client_scope_
= nullptr;
2429 delete [] this->server_scope_
;
2430 this->server_scope_
= nullptr;
2432 delete [] this->flat_server_scope_
;
2433 this->flat_server_scope_
= nullptr;
2435 // Call the destroy methods of our base classes.
2436 this->AST_Interface::destroy ();
2437 this->be_scope::destroy ();
2438 this->be_type::destroy ();
2442 be_interface::accept (be_visitor
*visitor
)
2444 return visitor
->visit_interface (this);
2448 be_interface::original_interface (be_interface
*original_interface
)
2450 this->original_interface_
= original_interface
;
2454 be_interface::original_interface ()
2456 return this->original_interface_
;
2460 be_interface::is_event_consumer ()
2463 this->pd_n_inherits
== 1
2464 && ACE_OS::strcmp (this->pd_inherits
[0]->full_name (),
2465 "Components::EventConsumerBase") == 0;
2469 be_interface::gen_facet_idl (TAO_OutStream
&os
)
2471 if (this->ex_idl_facet_gen ())
2476 be_util::gen_nesting_open (os
, this);
2479 << "local interface CCM_"
2480 << this->original_local_name ()->get_string ()
2482 << IdentifierHelper::orig_sn (this->name ()).c_str ()
2489 be_util::gen_nesting_close (os
, this);
2491 this->ex_idl_facet_gen (true);
2495 be_interface::enqueue_base_component_r (AST_Component
*node
)
2497 AST_Component
*base
= node
->base_component ();
2499 if (base
== nullptr)
2504 this->enqueue_base_component_r (base
);
2506 (void) this->insert_non_dup (base
);
2508 long const n_supports
= base
->n_supports ();
2509 AST_Type
**supports
= base
->supports ();
2511 for (long j
= 0; j
< n_supports
; ++j
)
2513 (void) this->insert_non_dup (supports
[j
]);
2518 be_interface::enqueue_base_home_r (AST_Home
*node
)
2520 AST_Home
*base
= node
->base_home ();
2522 if (base
== nullptr)
2527 this->enqueue_base_home_r (base
);
2529 (void) this->insert_non_dup (base
);
2531 long const n_supports
= base
->n_supports ();
2532 AST_Type
**supports
= base
->supports ();
2534 for (long j
= 0; j
< n_supports
; ++j
)
2536 (void) this->insert_non_dup (supports
[j
]);
2541 be_interface::dds_connector_traits_done () const
2543 return this->dds_connector_traits_done_
;
2547 be_interface::dds_connector_traits_done (bool val
)
2549 this->dds_connector_traits_done_
= val
;
2553 be_interface::gen_stub_inheritance (TAO_OutStream
*os
)
2556 long nparents
= this->n_inherits ();
2557 bool has_concrete_parent
= false;
2558 bool i_am_abs
= this->is_abstract ();
2560 // If node interface inherits from other interfaces.
2565 AST_Type
**parents
= this->inherits ();
2567 for (i
= 0; i
< nparents
; ++i
)
2569 AST_Type
*parent
= parents
[i
];
2571 if (! parent
->is_abstract ())
2573 has_concrete_parent
= true;
2576 *os
<< "public virtual ::"
2579 if (i
< nparents
- 1)
2581 // Node has multiple inheritance, so put a comma.
2582 *os
<< "," << be_nl
;
2586 if (has_concrete_parent
|| i_am_abs
)
2588 *os
<< be_uidt
<< be_uidt_nl
;
2590 else if (! i_am_abs
)
2592 *os
<< "," << be_nl
;
2596 if (i_am_abs
&& nparents
== 0)
2598 *os
<< "public virtual ::CORBA::AbstractBase"
2602 if (! has_concrete_parent
&& ! i_am_abs
)
2604 *os
<< "public virtual ::CORBA::Object";
2616 be_interface::gen_skel_inheritance (TAO_OutStream
*os
)
2618 long n_parents
= this->n_inherits ();
2619 AST_Type
*parent
= nullptr;
2620 AST_Type
**parents
= this->inherits ();
2621 bool has_concrete_parent
= false;
2623 for (int i
= 0; i
< n_parents
; ++i
)
2625 parent
= parents
[i
];
2627 if (parent
->is_abstract ())
2632 if (has_concrete_parent
)
2634 *os
<< "," << be_nl
;
2637 *os
<< "public virtual " << "POA_"
2640 has_concrete_parent
= true;
2643 if (! has_concrete_parent
)
2645 // We don't inherit from another user defined object, hence our
2646 // base class is the ServantBase class.
2647 *os
<< "public virtual PortableServer::ServantBase";
2652 be_interface::gen_is_a_ancestors (TAO_OutStream
*os
)
2655 this->traverse_inheritance_graph (be_interface::is_a_helper
,
2660 ACE_ERROR_RETURN ((LM_ERROR
,
2661 ACE_TEXT ("be_interface::")
2662 ACE_TEXT ("gen_is_a_ancestors - ")
2663 ACE_TEXT ("traverse_inheritance_graph failed\n")),
2667 if (this->is_abstract () || this->has_mixed_parentage ())
2669 *os
<< "std::strcmp (value, \"IDL:omg.org/CORBA/AbstractBase:1.0\") == 0";
2671 else if (this->is_local ())
2673 *os
<< "std::strcmp (value, \"IDL:omg.org/CORBA/LocalObject:1.0\") == 0";
2676 if (this->has_mixed_parentage () || this->is_local ())
2678 *os
<< " ||" << be_nl
;
2680 else if (this->is_abstract ())
2685 if (! this->is_abstract ())
2687 *os
<< "std::strcmp (value, \"IDL:omg.org/CORBA/Object:1.0\") == 0" << be_nl
;
2693 // =================================================================
2695 class Facet_Op_Attr_Helper
2696 : public TAO_IDL_Inheritance_Hierarchy_Worker
2699 Facet_Op_Attr_Helper (be_visitor
*visitor
);
2701 virtual int emit (be_interface
*derived_interface
,
2703 be_interface
*base_interface
);
2706 be_visitor
*visitor_
;
2709 Facet_Op_Attr_Helper::Facet_Op_Attr_Helper (
2710 be_visitor
*visitor
)
2711 : visitor_ (visitor
)
2716 Facet_Op_Attr_Helper::emit (be_interface
* /*derived_interface */,
2718 be_interface
*base_interface
)
2720 AST_Decl::NodeType nt
= base_interface
->node_type ();
2722 if (nt
== AST_Decl::NT_component
|| nt
== AST_Decl::NT_connector
)
2727 return visitor_
->visit_scope (base_interface
);
2730 // ================================================================
2733 be_interface::gen_ami4ccm_idl (TAO_OutStream
*os
)
2735 if (this->ami4ccm_ex_idl_gen ())
2740 be_util::gen_nesting_open (*os
, this);
2742 be_visitor_context ctx
;
2745 be_visitor_ami4ccm_rh_ex_idl
rh_visitor (&ctx
);
2747 if (rh_visitor
.visit_interface (this) == -1)
2749 ACE_ERROR_RETURN ((LM_ERROR
,
2750 ACE_TEXT ("be_interface::gen_ami4ccm_idl - ")
2751 ACE_TEXT ("rh visitor failed\n")),
2755 be_visitor_ami4ccm_sendc_ex_idl
sendc_visitor (&ctx
);
2757 if (sendc_visitor
.visit_interface (this) == -1)
2759 ACE_ERROR_RETURN ((LM_ERROR
,
2760 ACE_TEXT ("be_interface::gen_ami4ccm_idl - ")
2761 ACE_TEXT ("sendc visitor failed\n")),
2765 be_visitor_ami4ccm_conn_ex_idl
conn_visitor (&ctx
);
2767 if (conn_visitor
.visit_interface (this) == -1)
2769 ACE_ERROR_RETURN ((LM_ERROR
,
2770 ACE_TEXT ("be_interface::gen_ami4ccm_idl - ")
2771 ACE_TEXT ("connector visitor failed\n")),
2775 be_util::gen_nesting_close (*os
, this);
2777 this->ami4ccm_ex_idl_gen (true);
2783 be_interface::is_ami_rh () const
2785 return this->is_ami_rh_
;
2789 be_interface::is_ami_rh (bool val
)
2791 this->is_ami_rh_
= val
;
2795 be_interface::is_ami4ccm_rh () const
2797 return this->is_ami4ccm_rh_
;
2801 be_interface::is_ami4ccm_rh (bool val
)
2803 this->is_ami4ccm_rh_
= val
;
2807 be_interface::direct_proxy_impl_name ()
2809 if (this->direct_proxy_impl_name_
== nullptr)
2811 this->direct_proxy_impl_name_
=
2812 this->create_with_prefix_suffix (
2813 this->tag_table_
[GC_PREFIX
],
2814 this->local_name (),
2815 this->suffix_table_
[PROXY_IMPL
],
2816 this->tag_table_
[DIRECT
]);
2819 return this->direct_proxy_impl_name_
;
2823 be_interface::full_direct_proxy_impl_name ()
2825 if (this->full_direct_proxy_impl_name_
== nullptr)
2827 const char *scope
= this->server_enclosing_scope ();
2828 const char *base_name
= this->direct_proxy_impl_name ();
2831 ACE_OS::strlen (scope
) + ACE_OS::strlen (base_name
);
2833 ACE_NEW_RETURN (this->full_direct_proxy_impl_name_
,
2837 ACE_OS::strcpy (this->full_direct_proxy_impl_name_
,
2839 ACE_OS::strcat (this->full_direct_proxy_impl_name_
,
2843 return this->full_direct_proxy_impl_name_
;
2848 be_interface::client_enclosing_scope ()
2850 if (this->client_scope_
== nullptr)
2852 const char *full_name
= this->full_name ();
2853 const char *name
= this->local_name ();
2855 size_t offset
= ACE_OS::strlen (name
);
2856 size_t length
= ACE_OS::strlen (full_name
) - offset
;
2857 ACE_NEW_RETURN (this->client_scope_
,
2861 ACE_OS::strncpy (this->client_scope_
, full_name
, length
);
2862 this->client_scope_
[length
] = '\0';
2865 return this->client_scope_
;
2869 be_interface::flat_client_enclosing_scope ()
2871 if (this->flat_client_scope_
== nullptr)
2873 const char *full_name
= this->flat_name ();
2875 this->original_local_name ()->get_string ();
2877 size_t offset
= ACE_OS::strlen (name
);
2878 size_t length
= ACE_OS::strlen (full_name
) - offset
;
2880 ACE_NEW_RETURN (this->flat_client_scope_
,
2884 ACE_OS::strncpy (this->flat_client_scope_
,
2887 this->flat_client_scope_
[length
] = '\0';
2890 return this->flat_client_scope_
;
2894 be_interface::server_enclosing_scope ()
2896 if (this->server_scope_
== nullptr)
2898 const char *full_name
=
2899 this->full_coll_name (be_interface::DIRECT
);
2902 this->local_coll_name (be_interface::DIRECT
);
2904 size_t offset
= ACE_OS::strlen (name
);
2905 size_t length
= ACE_OS::strlen (full_name
) - offset
;
2906 ACE_NEW_RETURN (this->server_scope_
,
2910 ACE_OS::strncpy (this->server_scope_
, full_name
, length
);
2911 this->server_scope_
[length
] = '\0';
2914 return this->server_scope_
;
2918 be_interface::create_with_prefix_suffix (const char *prefix
,
2921 const char *separator
)
2923 char *cat_string
= nullptr;
2925 ACE_OS::strlen (str
) +
2926 ACE_OS::strlen (prefix
) +
2927 ACE_OS::strlen (suffix
) +
2928 ACE_OS::strlen (separator
) +
2931 ACE_NEW_RETURN (cat_string
,
2935 ACE_OS::strcpy (cat_string
, prefix
);
2936 ACE_OS::strcat (cat_string
, str
);
2937 ACE_OS::strcat (cat_string
, separator
);
2938 ACE_OS::strcat (cat_string
, suffix
);