Use =default for skeleton copy constructor
[ACE_TAO.git] / TAO / TAO_IDL / be / be_interface.cpp
blob6f16d7657726186aca44a5c1a52d8adc9cea91c3
2 //=============================================================================
3 /**
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"
23 #include "be_util.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"
36 #include "ast_home.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_[] =
50 "_Proxy_Impl",
53 const char *be_interface::tag_table_[] =
55 "_Direct",
56 "_TAO_"
59 be_interface::be_interface (UTL_ScopedName *n,
60 AST_Type **ih,
61 long nih,
62 AST_Interface **ih_flat,
63 long nih_flat,
64 bool local,
65 bool abstract)
66 : COMMON_Base (local,
67 abstract),
68 AST_Decl (AST_Decl::NT_interface,
69 n),
70 AST_Type (AST_Decl::NT_interface,
71 n),
72 UTL_Scope (AST_Decl::NT_interface),
73 AST_Interface (n,
74 ih,
75 nih,
76 ih_flat,
77 nih_flat,
78 local,
79 abstract),
80 be_scope (AST_Decl::NT_interface),
81 be_decl (AST_Decl::NT_interface,
82 n),
83 be_type (AST_Decl::NT_interface,
84 n),
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),
92 skel_count_ (0),
93 in_mult_inheritance_ (-1),
94 original_interface_ (nullptr),
95 is_amh_rh_ (false),
96 is_ami_rh_ (false),
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),
102 cached_type_ (-1),
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)
112 return;
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;
126 if (local)
128 // Set the flag for local interface seen in this IDL file.
129 idl_global->local_iface_seen_ = true;
131 else
133 // Set the flag for non-local interface seen in this IDL file.
134 idl_global->non_local_iface_seen_ = true;
137 else
139 // Forward declared non-defined interface. Still gets a _var decl.
140 idl_global->fwd_iface_seen_ = true;
144 be_interface::~be_interface ()
148 const char *
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 ();
156 const char *
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_;
168 const char *
169 be_interface::full_coll_name (int type)
171 this->compute_coll_names (type,
172 nullptr, // prefix
173 nullptr); // suffix
175 return this->full_coll_name_;
178 const char *
179 be_interface::local_coll_name (int type)
181 this->compute_coll_names (type,
182 nullptr, // prefix
183 nullptr); // suffix
185 return this->local_coll_name_;
188 const char *
189 be_interface::relative_skel_name (const char *skel_name)
191 return be_interface::relative_name (this->full_skel_name (),
192 skel_name);
195 void
196 be_interface::compute_full_skel_name (const char *prefix,
197 char *&skel_name)
199 if (skel_name != nullptr)
201 return;
204 size_t namelen = ACE_OS::strlen (prefix);
205 long first = true;
206 long second = false;
207 char *item_name = nullptr;
209 // In the first loop compute the total length.
210 for (UTL_IdListActiveIterator i (this->name ());
211 !i.is_done ();
212 i.next ())
214 if (!first)
216 namelen += 2; // for "::"
218 else if (second)
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.
228 if (first)
230 if (ACE_OS::strcmp (item_name, "") != 0)
232 // Does not start with a "".
233 first = false;
235 else
237 second = true;
242 ACE_NEW (skel_name,
243 char [namelen + 1]);
244 skel_name[0] = '\0';
245 first = true;
246 second = false;
247 ACE_OS::strcat (skel_name, prefix);
249 for (UTL_IdListActiveIterator j (this->name ());
250 !j.is_done ();
251 j.next ())
253 if (!first)
255 ACE_OS::strcat (skel_name, "::");
257 else if (second)
259 first = second = false;
262 // Print the identifier.
263 item_name = j.item ()->get_string ();
264 ACE_OS::strcat (skel_name, item_name);
266 if (first)
268 if (ACE_OS::strcmp (item_name, "") != 0)
270 // Does not start with a "".
271 first = false;
273 else
275 second = true;
281 // Compute stringified fully qualified collocated class name.
282 void
283 be_interface::compute_coll_names (int type,
284 const char *prefix,
285 const char *suffix)
287 if (type == this->cached_type_ && this->full_coll_name_ != nullptr)
289 return;
291 else
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)
313 + 1;
315 if (prefix)
317 name_len += ACE_OS::strlen (prefix);
320 if (suffix)
322 name_len += ACE_OS::strlen (suffix);
325 for (UTL_IdListActiveIterator i (this->name ());
326 !i.is_done ();
327 i.next ())
329 // Reserve 2 characters for "::".
330 name_len += ACE_OS::strlen (i.item ()->get_string ()) + 2;
333 ACE_NEW (this->full_coll_name_,
334 char[name_len + 1]);
336 // Null terminate the string.
337 this->full_coll_name_[0] = 0;
339 // Only the first component get the "POA_" preffix.
340 int poa_added = 0;
342 // Iterate again.
343 // Must advance the iterator explicitly inside the loop.
344 for (UTL_IdListActiveIterator j (this->name ());
345 !j.is_done ();)
347 const char *item = j.item ()->get_string ();
349 // Increase right away, so we can test for the final component
350 // in the loop.
351 j.next ();
353 // We add the POA_ prefix only if the first component is not
354 // the global scope...
355 if (ACE_OS::strcmp (item, "") != 0)
357 if (!j.is_done ())
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.
362 if (!poa_added)
364 ACE_OS::strcat (this->full_coll_name_, poa);
365 poa_added = 1;
367 ACE_OS::strcat (this->full_coll_name_, item);
368 ACE_OS::strcat (this->full_coll_name_, "::");
370 else
372 ACE_OS::strcat (this->full_coll_name_, collocated);
374 if (prefix)
376 ACE_OS::strcat (this->full_coll_name_, prefix);
379 ACE_OS::strcat (this->full_coll_name_, item);
381 if (suffix)
383 ACE_OS::strcat (this->full_coll_name_, suffix);
389 // Compute the local name for the collocated class.
390 char *local_name =
391 this->AST_Interface::local_name ()->get_string ();
392 size_t local_len = ACE_OS::strlen (collocated)
393 + ACE_OS::strlen (local_name)
394 + 1;
395 if (prefix)
397 local_len += ACE_OS::strlen (prefix);
400 if (suffix)
402 local_len += ACE_OS::strlen (suffix);
405 ACE_NEW (this->local_coll_name_,
406 char[local_len]);
408 ACE_OS::strcpy (this->local_coll_name_,
409 collocated);
411 if (prefix)
413 ACE_OS::strcat (this->local_coll_name_,
414 prefix);
417 ACE_OS::strcat (this->local_coll_name_,
418 this->AST_Interface::local_name ()->get_string ());
420 if (suffix)
422 ACE_OS::strcat (this->local_coll_name_, suffix);
426 const char*
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
433 // "localname".
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
438 // scopes as well.
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;
450 char *def_next;
451 char *use_curr = use_name;
452 char *use_next;
454 ACE_OS::memset (macro,
455 '\0',
456 NAMEBUFSIZE);
457 ACE_OS::memset (def_name,
458 '\0',
459 NAMEBUFSIZE);
460 ACE_OS::memset (use_name,
461 '\0',
462 NAMEBUFSIZE);
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
467 // traversed.
468 ACE_OS::strcpy (def_name,
469 localname);
470 ACE_OS::strcpy (use_name,
471 othername);
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, "::");
480 if (def_next)
482 *def_next = 0;
485 if (use_next)
487 *use_next = 0;
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 ::
496 else
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
500 // used.
501 if (def_next)
503 *def_next = ':';
506 if (use_next)
508 *use_next = ':';
511 // No match. This is the end of the first argument. Get out
512 // of the loop as no more comparisons are necessary.
513 break;
517 // Start the 2nd argument of the macro.
519 // Copy the remaining def_name (if any left)
520 if (def_curr)
522 ACE_OS::strcat (macro,
523 def_curr);
526 return 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,
540 nullptr
541 ) == -1)
543 ACE_ERROR_RETURN ((LM_ERROR,
544 "be_interface::in_mult_inheritance "
545 "error determining mult inheritance\n"),
546 -1);
550 return this->in_mult_inheritance_;
553 void
554 be_interface::in_mult_inheritance (int mi)
556 if (this->in_mult_inheritance_ == -1)
558 this->in_mult_inheritance_ = mi;
562 bool
563 be_interface::has_rw_attributes () const
565 return this->has_rw_attributes_;
568 void
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 ();
579 size_t slot = 0;
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);
590 if (*t == bi)
592 (void) q.set (this, slot);
593 break;
598 AST_Interface::redefine (from);
601 // Generate default constructors.
602 void
603 be_interface::gen_def_ctors (TAO_OutStream *os)
605 if (this->traverse_inheritance_graph (be_interface::gen_def_ctors_helper,
606 os) == -1)
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,
615 be_interface* base,
616 TAO_OutStream *os)
618 static int first = 0;
620 if (node != base)
622 if (first)
624 *os << be_global->impl_class_prefix () << base->flat_name ()
625 << be_global->impl_class_suffix () << " ()";
627 first = 0;
629 else
631 *os << ", " << be_global->impl_class_prefix ()
632 << base->flat_name ()
633 << be_global->impl_class_suffix () << " ()";
636 else
638 *os << ":";
639 first = 1;
642 return 1;
646 void
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 ();
653 *os << be_nl_2
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") << ")"
662 << be_uidt_nl
663 << ": ";
665 bool the_check =
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_)
674 *os << "::CORBA::"
675 << (the_check ? "AbstractBase" : "Object")
676 << " ("
677 << be_idt << be_idt << be_idt_nl
678 << "objref," << be_nl
679 << "_tao_collocated," << be_nl
680 << "servant"
681 << (the_check ? "" : ", oc") << be_uidt_nl
682 << ")" << be_uidt;
684 if (!the_check)
686 *os << "," << be_nl
687 << "::CORBA::AbstractBase ("
688 << be_idt << be_idt_nl
689 << "objref," << be_nl
690 << "_tao_collocated," << be_nl
691 << "servant" << be_uidt_nl
692 << ")" << be_uidt;
695 int const status =
696 this->traverse_inheritance_graph (
697 be_interface::gen_abstract_init_helper,
699 true);
701 if (status == -1)
703 ACE_ERROR ((LM_ERROR,
704 "be_interface::gen_stub_ctor - "
705 "inheritance graph traversal failed\n"));
708 else
710 *os << be_idt;
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.
731 void
732 be_interface::gen_var_out_seq_decls ()
734 if (this->var_out_seq_decls_gen_)
736 return;
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 (),
746 "var_out");
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);
758 bool already_ami =
759 (this->is_ami_rh ()
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 ()
766 && !already_ami)
768 *os << be_nl_2
769 << "class AMI_" << lname << "Handler;" << be_nl
770 << "typedef AMI_" << lname << "Handler *AMI_"
771 << lname << "Handler_ptr;";
774 if (be_global->ami4ccm_call_back ()
775 && !already_ami)
777 *os << be_nl_2
778 << "class AMI4CCM_" << lname << "Handler;" << be_nl
779 << "typedef AMI4CCM_" << lname << "Handler *AMI4CCM_"
780 << lname << "Handler_ptr;";
783 *os << be_nl_2
784 << "class " << lname << ";" << be_nl
785 << "using " << lname << "_ptr = " << lname << "*;";
787 *os << be_nl
788 << "using " << lname << "_var = TAO_Objref_Var_T<"
789 << lname
790 << ">;" << be_nl
791 << "using " << lname << "_out = TAO_Objref_Out_T<"
792 << lname
793 << ">;";
795 os->gen_endif ();
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
811 public:
812 TAO_IDL_Gen_OpTable_Worker (const char *skeleton_name);
814 virtual int emit (be_interface *derived_interface,
815 TAO_OutStream *os,
816 be_interface *base_interface);
818 private:
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,
830 TAO_OutStream *os,
831 be_interface *base_interface)
833 // Generate entries for the derived class using the properties of its
834 // ancestors.
835 be_interface *bi = dynamic_cast<be_interface*> (base_interface);
836 return bi->gen_optable_entries (derived_interface,
837 this->skeleton_name_,
838 os);
841 // =================================================================
843 class Pure_Virtual_Regenerator
844 : public TAO_IDL_Inheritance_Hierarchy_Worker
846 public:
847 Pure_Virtual_Regenerator (be_visitor *visitor);
849 virtual int emit (be_interface *derived_interface,
850 TAO_OutStream *os,
851 be_interface *base_interface);
853 private:
854 be_visitor *visitor_;
857 Pure_Virtual_Regenerator::Pure_Virtual_Regenerator (be_visitor *visitor)
858 : 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
865 // is automatic.
867 Pure_Virtual_Regenerator::emit (be_interface *derived_interface,
868 TAO_OutStream *,
869 be_interface *base_interface)
871 if (derived_interface == base_interface)
873 return 0;
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 ())
881 return 0;
884 be_decl *d = nullptr;
886 for (UTL_ScopeActiveIterator si (base_interface, UTL_Scope::IK_decls);
887 !si.is_done ();
888 si.next ())
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.
896 d->set_local (true);
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"),
903 -1);
906 d->set_local (false);
910 return 0;
913 // =================================================================
916 be_interface::gen_operation_table (const char *flat_name,
917 const char *skeleton_class_name)
919 // TODO:
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.
925 bool amh = false;
926 ACE_CString tmp (skeleton_class_name);
927 if (tmp.strstr ("AMH_") != ACE_String_Base_Const::npos)
929 amh = true;
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.
942 os->indent ();
944 // Start the table generation.
945 *os << be_nl_2
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"),
959 -1);
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.
973 if (amh)
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;
981 else
983 *os << "{\"_is_a\", std::addressof(TAO_ServantBase::_is_a_skel), nullptr}," << be_nl;
986 ++this->skel_count_;
988 if (!be_global->gen_minimum_corba ())
990 if (amh)
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;
1000 else
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 ())
1011 if (amh)
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;
1021 else
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 ())
1032 if (amh)
1034 *os << "{\"_interface\", std::addressof(TAO_AMH_Skeletons"
1035 << "::_interface_amh_skel), nullptr}," << be_nl;
1037 else
1039 *os << "{\"_interface\", std::addressof(TAO_ServantBase"
1040 << "::_interface_skel), nullptr}," << be_nl;
1043 ++this->skel_count_;
1046 if (!be_global->gen_minimum_corba ())
1048 if (amh)
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;
1058 else
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_)
1071 << ");" << be_nl;
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;
1085 break;
1087 case BE_GlobalData::TAO_LINEAR_SEARCH:
1088 // For generating linear search also, we are calling GPERF
1089 // only.
1090 case BE_GlobalData::TAO_BINARY_SEARCH:
1091 // For generating binary search also, we are calling GPERF
1092 // only.
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.
1097 // Temp file name.
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")
1109 + 1],
1110 -1);
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.
1116 unsigned int seed =
1117 (static_cast<unsigned int> (ACE_OS::time())
1118 + static_cast<unsigned int> (ACE_OS::getpid ()));
1119 ACE_OS::sprintf (temp_file,
1120 "%s%d.%d.%s.gperf",
1121 idl_global->temp_dir (),
1122 ACE_OS::rand_r (&seed),
1123 static_cast<int> (ACE_OS::getpid ()),
1124 flat_name);
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
1141 // interface.
1142 TAO_OutStream *os = nullptr;
1143 ACE_NEW_NORETURN (os, TAO_OutStream);
1145 if (os == nullptr)
1147 ACE_ERROR_RETURN ((LM_ERROR,
1148 "be_visitor_interface_ss"
1149 "::"
1150 "visit_interface-"
1151 "make_outstream failed\n"),
1152 -1);
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"
1164 "::"
1165 "visit_interface-"
1166 "gperf_input.tmp file open failed\n"),
1167 -1);
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"),
1183 -1);
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"),
1194 -1);
1197 if (amh)
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;
1207 else
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 ())
1217 if (amh)
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;
1227 else
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 ())
1238 if (amh)
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;
1248 else
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 ())
1258 if (amh)
1260 *os << "_interface,std::addressof(TAO_AMH_Skeletons"
1261 << "::_interface_amh_skel), nullptr" << be_nl;
1263 else
1265 *os << "_interface,std::addressof(TAO_ServantBase"
1266 << "::_interface_skel), nullptr" << be_nl;
1269 ++this->skel_count_;
1272 if (!be_global->gen_minimum_corba ())
1274 if (amh)
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;
1284 else
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
1295 // for the gperf.
1296 this->gen_gperf_things (flat_name);
1298 break;
1300 default:
1301 ACE_ERROR_RETURN ((LM_ERROR,
1302 "be_interface"
1303 "::"
1304 "gen_operation_table"
1305 "unknown op_lookup_strategy\n"),
1306 -1);
1309 return 0;
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"),
1325 -1);
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"),
1337 -1);
1340 return 0;
1343 // Output the header (type declaration and %%) to the gperf's input
1344 // file.
1345 void
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"
1351 << "};" << "\n"
1352 << "%%"
1353 << "\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,
1364 TAO_OutStream *os)
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);
1372 !si.is_done ();
1373 si.next ())
1375 // Get the next AST decl node
1376 AST_Decl *d = si.item ();
1378 if (d->node_type () == AST_Decl::NT_op)
1380 be_operation *op =
1381 dynamic_cast<be_operation*> (d);
1383 if (op->is_sendc_ami ())
1385 continue;
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 () << ")";
1399 else
1401 *os << " nullptr";
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)
1414 return -1;
1416 // Generate only the "get" entry if we are
1417 // readonly.
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 () << ")";
1428 else
1430 *os << " nullptr";
1433 *os << "}," << be_nl;
1435 ++derived_interface->skel_count_;
1437 if (!attr->readonly ())
1439 // The set method
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 () << ")";
1450 else
1452 *os << " nullptr";
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);
1473 !si.is_done ();
1474 si.next ())
1476 // get the next AST decl node
1477 AST_Decl *d = si.item ();
1479 if (d->node_type () == AST_Decl::NT_op)
1481 be_operation *op =
1482 dynamic_cast<be_operation*> (d);
1484 if (op->is_sendc_ami ())
1486 continue;
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 ()
1511 << "_skel),";
1513 else
1515 *os << d->original_local_name () << ",std::addressof(POA_AMH_"
1516 << name.c_str () << "::"
1517 << d->original_local_name ()
1518 << "_skel),";
1521 else
1523 if (!d->is_abstract ())
1525 *os << d->original_local_name () << ",std::addressof(POA_"
1526 << d->full_name () << "_skel),";
1528 else
1530 *os << d->original_local_name () << ",std::addressof("
1531 << full_skeleton_name << "::"
1532 << d->original_local_name ()
1533 << "_skel),";
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 () << ")";
1544 else
1546 *os << " std::addressof("
1547 << derived_interface->full_direct_proxy_impl_name ()
1548 << "::" << d->local_name () << ")";
1552 else
1554 *os << " nullptr";
1557 *os << "\n";
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)
1568 return -1;
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 () << ")";
1592 else
1594 *os << " 0";
1597 else
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 () << ")";
1609 else
1611 *os << " nullptr";
1615 *os << "\n";
1617 ++this->skel_count_;
1619 if (!attr->readonly ())
1621 if (!d->is_abstract ())
1623 // The set method
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 () << ")";
1634 else
1636 *os << " nullptr";
1639 else
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 () << ")";
1652 else
1654 *os << " nullptr";
1658 *os << "\n";
1660 ++this->skel_count_;
1665 else
1667 ACE_ERROR_RETURN ((LM_ERROR,
1668 "be_interface::gen_optable_entries - "
1669 "unknown op_lookup_strategy\n"),
1670 -1);
1673 return 0;
1676 void
1677 be_interface::gen_ostream_operator (TAO_OutStream *os,
1678 bool /* use_underscore */)
1680 *os << be_nl
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
1685 << "{" << be_idt_nl
1686 << "return ::CORBA::"
1687 << (this->is_abstract () ? "AbstractBase" : "Object")
1688 << "::_tao_stream (strm, _tao_objref);"
1689 << be_uidt_nl
1690 << "}" << be_nl;
1693 void
1694 be_interface::gen_member_ostream_operator (TAO_OutStream *os,
1695 const char *instance_name,
1696 bool /* use_underscore */,
1697 bool accessor)
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,
1716 base_interface,
1717 output_stream);
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,
1728 TAO_OutStream *os,
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"),
1742 -1);
1745 be_code_emitter_wrapper wrapper (gen);
1747 return
1748 this->traverse_inheritance_graph (wrapper,
1750 abstract_paths_only,
1751 add_ccm_object);
1755 be_interface::traverse_inheritance_graph (
1756 TAO_IDL_Inheritance_Hierarchy_Worker &worker,
1757 TAO_OutStream *os,
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"),
1771 -1);
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)
1786 if (add_ccm_object)
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"),
1813 -1);
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"),
1822 -1);
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"),
1835 -1);
1837 } // end of while queue not empty
1839 return 0;
1842 // Run GPERF and get the correct lookup and other operations
1843 // depending on which strategy we are using. Returns 0 on sucess, -1
1844 // on error.
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)
1869 return -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);
1876 break;
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)
1886 return -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);
1893 break;
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)
1903 return -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);
1910 break;
1912 default:
1913 ACE_ERROR_RETURN ((
1914 LM_ERROR,
1915 "tao_idl:ERROR:%N:%l:Unknown Operation Lookup Strategy\n"),
1916 -1);
1919 return 0;
1922 // Outputs the class definition for the perfect hashing. This class
1923 // will inherit from the TAO_Perfect_Hash_OpTable.
1924 void
1925 be_interface::gen_perfect_hash_class_definition (const char *flat_name)
1927 // Outstream.
1928 TAO_OutStream *os = tao_cg->server_skeletons ();
1930 *os << "class " << "TAO_" << flat_name << "_Perfect_Hash_OpTable"
1931 << be_idt_nl
1932 << ": public TAO_Perfect_Hash_OpTable" << be_uidt_nl
1933 << "{" << be_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;"
1940 << be_uidt_nl
1941 << "};\n\n";
1944 // Outputs the class definition for the binary searching. This class
1945 // will inherit from the TAO_Binary_Seach_OpTable.
1946 void
1947 be_interface::gen_binary_search_class_definition (const char *flat_name)
1949 // Outstream.
1950 TAO_OutStream *os = tao_cg->server_skeletons ();
1952 *os << "class " << "TAO_" << flat_name << "_Binary_Search_OpTable"
1953 << be_idt_nl
1954 << ": public TAO_Binary_Search_OpTable" << be_uidt_nl
1955 << "{" << be_nl
1956 << "public:" << be_idt_nl
1957 << "const TAO_operation_db_entry * lookup (const char *str) override;"
1958 << be_uidt_nl
1959 << "};\n\n";
1962 // Outputs the class definition for the linear search. This class
1963 // will inherit from the TAO_Linear_Search_OpTable.
1964 void
1965 be_interface::gen_linear_search_class_definition (const char *flat_name)
1967 // Outstream.
1968 TAO_OutStream *ss = tao_cg->server_skeletons ();
1970 *ss << "class " << "TAO_" << flat_name << "_Linear_Search_OpTable"
1971 << be_idt_nl
1972 << ": public TAO_Linear_Search_OpTable" << be_nl
1973 << "{" << be_nl
1974 << "public:" << be_idt_nl
1975 << "const TAO_operation_db_entry * lookup (const char *str) override;"
1976 << be_uidt_nl
1977 << "};\n\n";
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
1984 // file.
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.
2001 // 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"),
2007 "fclose"),
2008 -1);
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.
2015 ACE_HANDLE input =
2016 ACE::open_temp_file (
2017 ACE_TEXT_CHAR_TO_TCHAR (tao_cg->gperf_input_filename ()),
2018 O_RDONLY);
2020 if (input == ACE_INVALID_HANDLE)
2022 ACE_ERROR_RETURN ((
2023 LM_ERROR,
2024 ACE_TEXT ("Error:%p:File open failed on ")
2025 ACE_TEXT ("gperf's temp input file %s\n"),
2026 "open_temp_file",
2027 tao_cg->gperf_input_filename ()),
2028 -1);
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.
2038 ACE_HANDLE output =
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"),
2048 "open"),
2049 -1);
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);
2058 int result = 0;
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 ())
2064 // Perfect Hashing.
2065 case BE_GlobalData::TAO_PERFECT_HASH:
2066 process_options.command_line (ACE_TEXT ("%s")
2067 ACE_TEXT (" ")
2068 ACE_TEXT ("-m -M -J -c -C")
2069 ACE_TEXT (" ")
2070 ACE_TEXT ("-D -E -T -f 0")
2071 ACE_TEXT (" ")
2072 ACE_TEXT ("-F 0,0")
2073 ACE_TEXT (" ")
2074 ACE_TEXT ("-a -o -t -p -K")
2075 ACE_TEXT (" ")
2076 ACE_TEXT ("opname -L C++")
2077 ACE_TEXT (" ")
2078 ACE_TEXT ("-Z TAO_%s_Perfect_Hash_OpTable")
2079 ACE_TEXT (" ")
2080 ACE_TEXT ("-N lookup"),
2081 idl_global->gperf_path (),
2082 flat_name);
2083 break;
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")
2088 ACE_TEXT (" ")
2089 ACE_TEXT ("-B")
2090 ACE_TEXT (" ")
2091 ACE_TEXT ("-m -M -J -c -C")
2092 ACE_TEXT (" ")
2093 ACE_TEXT ("-D -E -T -f 0")
2094 ACE_TEXT (" ")
2095 ACE_TEXT ("-F 0,0,0")
2096 ACE_TEXT (" ")
2097 ACE_TEXT ("-a -o -t -p -K")
2098 ACE_TEXT (" ")
2099 ACE_TEXT ("opname -L C++")
2100 ACE_TEXT (" ")
2101 ACE_TEXT ("-Z TAO_%s_Binary_Search_OpTable")
2102 ACE_TEXT (" ")
2103 ACE_TEXT ("-N lookup"),
2104 idl_global->gperf_path (),
2105 flat_name);
2106 break;
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")
2111 ACE_TEXT (" ")
2112 ACE_TEXT ("-b")
2113 ACE_TEXT (" ")
2114 ACE_TEXT ("-m -M -J -c -C")
2115 ACE_TEXT (" ")
2116 ACE_TEXT ("-D -E -T -f 0")
2117 ACE_TEXT (" ")
2118 ACE_TEXT ("-F 0,0")
2119 ACE_TEXT (" ")
2120 ACE_TEXT ("-a -o -t -p -K")
2121 ACE_TEXT (" ")
2122 ACE_TEXT ("opname -L C++")
2123 ACE_TEXT (" ")
2124 ACE_TEXT ("-Z TAO_%s_Linear_Search_OpTable")
2125 ACE_TEXT (" ")
2126 ACE_TEXT ("-N lookup"),
2127 idl_global->gperf_path (),
2128 flat_name);
2129 break;
2131 default:
2132 ACE_ERROR ((LM_ERROR,
2133 ACE_TEXT ("tao_idl:ERROR:%N:%l:Unknown ")
2134 ACE_TEXT ("Operation Lookup Strategy\n")));
2136 result = -1;
2139 if (result != -1)
2141 result = process.spawn (process_options);
2143 // Spawn a process for gperf.
2144 if (result == -1)
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.
2152 else
2154 ACE_exitcode exitcode;
2155 result = process.wait (&exitcode);
2157 if (result == -1)
2159 ACE_ERROR ((LM_ERROR,
2160 ACE_TEXT ("Error:%p:gperf program ")
2161 ACE_TEXT ("returned exit code %d.\n"),
2162 exitcode));
2166 // Adjust the file offset to the EOF for the server skeleton
2167 // file.
2168 ACE_OS::fseek (tao_cg->server_skeletons ()->file (),
2170 SEEK_END);
2173 ACE_OS::close (output);
2174 ACE_OS::close (input);
2176 return result;
2179 // Create an instance of this perfect hash table.
2180 void
2181 be_interface::gen_perfect_hash_instance (const char *flat_name)
2183 // Outstream.
2184 TAO_OutStream *os = tao_cg->server_skeletons ();
2186 *os << be_nl
2187 << "static TAO_" << flat_name << "_Perfect_Hash_OpTable"
2188 << " "
2189 << "tao_" << flat_name << "_optable;";
2192 // Create an instance of the binary search optable.
2193 void
2194 be_interface::gen_binary_search_instance (const char *flat_name)
2196 // Outstream.
2197 TAO_OutStream *os = tao_cg->server_skeletons ();
2199 *os << be_nl
2200 << "static TAO_" << flat_name << "_Binary_Search_OpTable"
2201 << " "
2202 << "tao_" << flat_name << "_optable;";
2206 // Create an instance of this perfect hash table.
2207 void
2208 be_interface::gen_linear_search_instance (const char *flat_name)
2210 // Outstream.
2211 TAO_OutStream *os = tao_cg->server_skeletons ();
2213 *os << be_nl
2214 << "static TAO_" << flat_name << "_Linear_Search_OpTable"
2215 << " "
2216 << "tao_" << flat_name << "_optable;";
2220 be_interface::is_a_helper (be_interface * /*derived*/,
2221 be_interface *bi,
2222 TAO_OutStream *os)
2224 // Emit the comparison code.
2225 *os << "std::strcmp (value, \"" << bi->repoID () << "\") == 0 ||" << be_nl;
2227 return 0;
2231 be_interface::copy_ctor_helper (be_interface *derived,
2232 be_interface *base,
2233 TAO_OutStream *os)
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)
2239 return 0;
2242 *os << "," << be_idt_nl;
2244 bool is_rh_base =
2245 (ACE_OS::strcmp (base->flat_name (), "Messaging_ReplyHandler") == 0);
2247 if (is_rh_base)
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)";
2259 else
2261 *os << base->full_skel_name () << " (rhs)";
2264 *os << be_uidt;
2266 return 0;
2270 be_interface::in_mult_inheritance_helper (be_interface *derived,
2271 be_interface *base,
2272 TAO_OutStream *)
2274 switch (derived->n_inherits ())
2276 case 0:
2277 // No parent.
2278 derived->in_mult_inheritance (0);
2279 break;
2280 case 1:
2281 if (derived == base)
2283 // Prevent indefinite recursion.
2284 derived->in_mult_inheritance (-1);
2286 else
2288 // One parent. We have the same characteristics as our base.
2289 derived->in_mult_inheritance (base->in_mult_inheritance ());
2292 break;
2293 default:
2294 // Direct multiple inheritance.
2295 derived->in_mult_inheritance (1);
2298 return 0;
2302 be_interface::gen_abstract_init_helper (be_interface *node,
2303 be_interface *base,
2304 TAO_OutStream *os)
2306 if (node == base)
2308 return 0;
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);
2318 *os << ""
2319 << parent_decl->name () << "::"
2320 << base->local_name ()<< " (" << be_idt << be_idt_nl;
2322 else
2324 *os << base->name () << " (" << be_idt << be_idt_nl;
2327 *os << "objref," << be_nl
2328 << "_tao_collocated," << be_nl
2329 << "servant" << be_uidt_nl
2330 << ")" << be_uidt;
2333 return 0;
2337 be_interface::op_attr_decl_helper (be_interface * /*derived */,
2338 be_interface *ancestor,
2339 TAO_OutStream *os)
2341 if (dynamic_cast<be_component*> (ancestor) != nullptr)
2343 return 0;
2346 be_visitor_context ctx;
2347 ctx.stream (os);
2348 ctx.state (TAO_CodeGen::TAO_ROOT_SVH);
2350 for (UTL_ScopeActiveIterator si (ancestor, UTL_Scope::IK_decls);
2351 !si.is_done ();
2352 si.next ())
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 ())
2367 continue;
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")),
2379 -1);
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")),
2394 -1);
2399 return 0;
2402 void
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);
2447 void
2448 be_interface::original_interface (be_interface *original_interface)
2450 this->original_interface_ = original_interface;
2453 be_interface *
2454 be_interface::original_interface ()
2456 return this->original_interface_;
2459 bool
2460 be_interface::is_event_consumer ()
2462 return
2463 this->pd_n_inherits == 1
2464 && ACE_OS::strcmp (this->pd_inherits[0]->full_name (),
2465 "Components::EventConsumerBase") == 0;
2468 void
2469 be_interface::gen_facet_idl (TAO_OutStream &os)
2471 if (this->ex_idl_facet_gen ())
2473 return;
2476 be_util::gen_nesting_open (os, this);
2478 os << be_nl
2479 << "local interface CCM_"
2480 << this->original_local_name ()->get_string ()
2481 << " : ::"
2482 << IdentifierHelper::orig_sn (this->name ()).c_str ()
2483 << be_nl
2484 << "{" << be_idt;
2486 os << be_uidt_nl
2487 << "};";
2489 be_util::gen_nesting_close (os, this);
2491 this->ex_idl_facet_gen (true);
2494 void
2495 be_interface::enqueue_base_component_r (AST_Component *node)
2497 AST_Component *base = node->base_component ();
2499 if (base == nullptr)
2501 return;
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]);
2517 void
2518 be_interface::enqueue_base_home_r (AST_Home *node)
2520 AST_Home *base = node->base_home ();
2522 if (base == nullptr)
2524 return;
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]);
2540 bool
2541 be_interface::dds_connector_traits_done () const
2543 return this->dds_connector_traits_done_;
2546 void
2547 be_interface::dds_connector_traits_done (bool val)
2549 this->dds_connector_traits_done_ = val;
2552 void
2553 be_interface::gen_stub_inheritance (TAO_OutStream *os)
2555 long i;
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.
2561 if (nparents > 0)
2563 *os << be_idt;
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 ::"
2577 << parent->name ();
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"
2599 << be_uidt_nl;
2602 if (! has_concrete_parent && ! i_am_abs)
2604 *os << "public virtual ::CORBA::Object";
2606 if (nparents > 0)
2608 *os << be_uidt;
2611 *os << be_uidt;
2615 void
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 ())
2629 continue;
2632 if (has_concrete_parent)
2634 *os << "," << be_nl;
2637 *os << "public virtual " << "POA_"
2638 << parent->name ();
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)
2654 int const status =
2655 this->traverse_inheritance_graph (be_interface::is_a_helper,
2656 os);
2658 if (status == -1)
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")),
2664 -1);
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 ())
2682 *os << be_nl;
2685 if (! this->is_abstract ())
2687 *os << "std::strcmp (value, \"IDL:omg.org/CORBA/Object:1.0\") == 0" << be_nl;
2690 return 0;
2693 // =================================================================
2695 class Facet_Op_Attr_Helper
2696 : public TAO_IDL_Inheritance_Hierarchy_Worker
2698 public:
2699 Facet_Op_Attr_Helper (be_visitor *visitor);
2701 virtual int emit (be_interface *derived_interface,
2702 TAO_OutStream *os,
2703 be_interface *base_interface);
2705 private:
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 */,
2717 TAO_OutStream *,
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)
2724 return 0;
2727 return visitor_->visit_scope (base_interface);
2730 // ================================================================
2733 be_interface::gen_ami4ccm_idl (TAO_OutStream *os)
2735 if (this->ami4ccm_ex_idl_gen ())
2737 return 0;
2740 be_util::gen_nesting_open (*os, this);
2742 be_visitor_context ctx;
2743 ctx.stream (os);
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")),
2752 -1);
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")),
2762 -1);
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")),
2772 -1);
2775 be_util::gen_nesting_close (*os, this);
2777 this->ami4ccm_ex_idl_gen (true);
2779 return 0;
2782 bool
2783 be_interface::is_ami_rh () const
2785 return this->is_ami_rh_;
2788 void
2789 be_interface::is_ami_rh (bool val)
2791 this->is_ami_rh_ = val;
2794 bool
2795 be_interface::is_ami4ccm_rh () const
2797 return this->is_ami4ccm_rh_;
2800 void
2801 be_interface::is_ami4ccm_rh (bool val)
2803 this->is_ami4ccm_rh_ = val;
2806 const char *
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_;
2822 const char *
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 ();
2830 size_t length =
2831 ACE_OS::strlen (scope) + ACE_OS::strlen (base_name);
2833 ACE_NEW_RETURN (this->full_direct_proxy_impl_name_,
2834 char[length + 1],
2835 nullptr);
2837 ACE_OS::strcpy (this->full_direct_proxy_impl_name_,
2838 scope);
2839 ACE_OS::strcat (this->full_direct_proxy_impl_name_,
2840 base_name);
2843 return this->full_direct_proxy_impl_name_;
2847 const char *
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_,
2858 char[length + 1],
2859 nullptr);
2861 ACE_OS::strncpy (this->client_scope_, full_name, length);
2862 this->client_scope_[length] = '\0';
2865 return this->client_scope_;
2868 const char *
2869 be_interface::flat_client_enclosing_scope ()
2871 if (this->flat_client_scope_ == nullptr)
2873 const char *full_name = this->flat_name ();
2874 const char *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_,
2881 char[length + 1],
2882 nullptr);
2884 ACE_OS::strncpy (this->flat_client_scope_,
2885 full_name,
2886 length);
2887 this->flat_client_scope_[length] = '\0';
2890 return this->flat_client_scope_;
2893 const char *
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);
2901 const char *name =
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_,
2907 char[length + 1],
2908 nullptr);
2910 ACE_OS::strncpy (this->server_scope_, full_name, length);
2911 this->server_scope_[length] = '\0';
2914 return this->server_scope_;
2917 char *
2918 be_interface::create_with_prefix_suffix (const char *prefix,
2919 const char *str,
2920 const char *suffix,
2921 const char *separator)
2923 char *cat_string = nullptr;
2924 size_t length =
2925 ACE_OS::strlen (str) +
2926 ACE_OS::strlen (prefix) +
2927 ACE_OS::strlen (suffix) +
2928 ACE_OS::strlen (separator) +
2929 1; // The '/0'
2931 ACE_NEW_RETURN (cat_string,
2932 char[length],
2933 nullptr);
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);
2940 return cat_string;