2 //=============================================================================
4 * @file be_sequence.cpp
6 * Extension of class AST_Sequence that provides additional means for C++
9 * @author Copyright 1994-1995 by Sun Microsystems
10 * @author Inc. and Aniruddha Gokhale
12 //=============================================================================
14 #include "be_sequence.h"
15 #include "be_typedef.h"
16 #include "be_interface.h"
17 #include "be_interface_fwd.h"
18 #include "be_predefined_type.h"
20 #include "be_string.h"
21 #include "be_visitor.h"
22 #include "be_helper.h"
23 #include "be_extern.h"
25 #include "utl_identifier.h"
26 #include "idl_defines.h"
27 #include "nr_extern.h"
28 #include "global_extern.h"
30 #include "ace/Log_Msg.h"
32 be_sequence::be_sequence (AST_Expression
*v
,
37 : COMMON_Base (t
->is_local () || local
,
39 AST_Decl (AST_Decl::NT_sequence
,
42 AST_Type (AST_Decl::NT_sequence
,
44 AST_ConcreteType (AST_Decl::NT_sequence
,
49 t
->is_local () || local
,
51 UTL_Scope (AST_Decl::NT_sequence
),
52 be_scope (AST_Decl::NT_sequence
),
53 be_decl (AST_Decl::NT_sequence
,
55 be_type (AST_Decl::NT_sequence
,
57 mt_ (be_sequence::MNG_UNKNOWN
),
61 this->has_constructor (true);
63 // Don't want to set any bits below for imported nodes.
64 if (this->imported ())
69 // This one gets set for all sequences, in addition to any specialized
70 // one that may get set below.
71 idl_global
->seq_seen_
= true;
72 idl_global
->var_size_decl_seen_
= true;
74 // Don't need the return value - just set the member.
75 (void) this->managed_type ();
80 idl_global
->iface_seq_seen_
= true;
83 idl_global
->pseudo_seq_seen_
= true;
86 idl_global
->vt_seq_seen_
= true;
89 idl_global
->string_seq_seen_
= true;
92 idl_global
->wstring_seq_seen_
= true;
98 AST_Type
*const base_type
= primitive_base_type ();
99 if (base_type
&& base_type
->node_type () == AST_Decl::NT_pre_defined
)
101 AST_PredefinedType
*pdt
= dynamic_cast<AST_PredefinedType
*> (base_type
);
104 case AST_PredefinedType::PT_octet
:
105 idl_global
->octet_seq_seen_
= true;
114 be_sequence::base_type () const
117 dynamic_cast<be_type
*> (
118 this->AST_Sequence::base_type ());
122 be_sequence::primitive_base_type () const
124 be_type
*type_node
= base_type ();
125 if (type_node
&& type_node
->node_type () == AST_Decl::NT_typedef
)
127 be_typedef
*const typedef_node
= dynamic_cast<be_typedef
*> (type_node
);
128 if (!typedef_node
) return nullptr;
129 type_node
= typedef_node
->primitive_base_type ();
134 // Helper to create_name.
136 be_sequence::gen_name ()
138 char namebuf
[NAMEBUFSIZE
];
139 be_type
*bt
= nullptr;
142 ACE_OS::memset (namebuf
,
146 // Retrieve the base type.
147 bt
= dynamic_cast<be_type
*> (this->base_type ());
151 ACE_ERROR_RETURN ((LM_ERROR
,
152 "(%N:%l) be_sequence::"
158 // If this is non-zero, add its local name to the generated name,
160 be_field
*fn
= this->field_node_
;
162 if (bt
->node_type () == AST_Decl::NT_sequence
)
164 // Our base type is an anonymous sequence.
165 be_sequence
*seq
= dynamic_cast<be_sequence
*> (bt
);
169 ACE_ERROR_RETURN ((LM_ERROR
,
170 "(%N:%l) be_sequence::"
172 "error converting base type to sequence\n"),
176 // If the nested sequence were defined in
177 // the scope of the enclosing sequence, we would have to
178 // not only define the nested class in two places, but also
179 // deal with the fact that, for the template classes, the
180 // enclosing sequence's template type is a class defined
181 // inside it. So we define the nested sequence in the next
182 // scope up, and the existing code generation works for both
183 // template and non-template implementations of IDL sequences.
184 UTL_Scope
*parent
= this->defined_in ();
185 seq
->set_defined_in (parent
);
186 char *seq_name
= seq
->gen_name ();
188 ACE_OS::sprintf (namebuf
,
191 fn
? fn
->local_name ()->get_string () : "");
192 ACE::strdelete (seq_name
);
196 ACE_OS::sprintf (namebuf
,
201 // Append the size (if any).
202 if (this->unbounded () == false)
204 char ulval_str
[NAMEBUFSIZE
];
205 ACE_OS::sprintf (ulval_str
,
206 "_" ACE_UINT32_FORMAT_SPECIFIER_ASCII
,
207 this->max_size ()->ev ()->u
.ulval
);
208 ACE_OS::strcat (namebuf
,
212 return ACE::strnew (namebuf
);
215 // Create a name for ourselves.
217 be_sequence::create_name (be_typedef
*node
)
219 static char *namebuf
= nullptr;
220 UTL_ScopedName
*n
= nullptr;
222 // Scope in which we are defined.
223 be_decl
*scope
= nullptr;
225 // If there is a typedef node, we use its name as our name.
229 dynamic_cast<UTL_ScopedName
*> (node
->name ()->copy ())
234 // Generate a local name.
235 namebuf
= this->gen_name ();
237 // Now see if we have a fully scoped name and if so, generate one.
238 UTL_Scope
*us
= this->defined_in ();
240 scope
= dynamic_cast<be_scope
*> (us
)->decl ();
242 if (scope
!= nullptr)
244 // Make a copy of the enclosing scope's name.
245 n
= (UTL_ScopedName
*) scope
->name ()->copy ();
247 Identifier
*id
= nullptr;
249 Identifier (namebuf
),
252 UTL_ScopedName
*conc_name
= nullptr;
253 ACE_NEW_RETURN (conc_name
,
258 // Add our local name as the last component.
259 n
->nconc (conc_name
);
261 // Set the fully scoped name.
266 // We better be not here because we must be inside some scope,
267 // at least the ROOT scope.
271 ACE::strdelete (namebuf
);
277 // Does this sequence have a managed type sequence element?
278 be_sequence::MANAGED_TYPE
279 be_sequence::managed_type ()
281 if (this->mt_
== be_sequence::MNG_UNKNOWN
) // Not calculated yet.
284 be_type
*const base_type
= primitive_base_type ();
286 ACE_ERROR_RETURN ((LM_ERROR
,
288 "dynamic_cast<be_type*> "
290 be_sequence::MNG_UNKNOWN
);
292 // Determine if we need a managed type and which one.
293 switch (base_type
->node_type ())
295 case AST_Decl::NT_interface
:
296 case AST_Decl::NT_interface_fwd
:
297 case AST_Decl::NT_component
:
298 case AST_Decl::NT_component_fwd
:
299 case AST_Decl::NT_connector
:
300 this->mt_
= be_sequence::MNG_OBJREF
;
302 case AST_Decl::NT_valuebox
:
303 case AST_Decl::NT_valuetype
:
304 case AST_Decl::NT_valuetype_fwd
:
305 case AST_Decl::NT_eventtype
:
306 case AST_Decl::NT_eventtype_fwd
:
307 this->mt_
= be_sequence::MNG_VALUE
;
309 case AST_Decl::NT_string
:
310 this->mt_
= be_sequence::MNG_STRING
;
312 case AST_Decl::NT_wstring
:
313 this->mt_
= be_sequence::MNG_WSTRING
;
315 case AST_Decl::NT_pre_defined
:
317 be_predefined_type
* const bpd
=
318 dynamic_cast<be_predefined_type
*> (base_type
);
320 AST_PredefinedType::PredefinedType pt
= bpd
->pt ();
324 case AST_PredefinedType::PT_pseudo
:
325 case AST_PredefinedType::PT_object
:
326 case AST_PredefinedType::PT_abstract
:
327 this->mt_
= be_sequence::MNG_PSEUDO
;
329 case AST_PredefinedType::PT_value
:
330 this->mt_
= be_sequence::MNG_VALUE
;
333 this->mt_
= be_sequence::MNG_NONE
;
339 this->mt_
= be_sequence::MNG_NONE
;
346 // Add this be_sequence to the locally defined types in this scope
348 be_sequence::fe_add_sequence (AST_Sequence
*t
)
355 this->add_to_local_types (t
);
368 be_sequence::gen_ostream_operator (TAO_OutStream
*os
,
369 bool /* use_underscore */)
372 << "std::ostream& operator<< (" << be_idt
<< be_idt_nl
373 << "std::ostream &strm," << be_nl
374 << "const " << this->name () << " &_tao_sequence" << be_uidt_nl
377 << "strm << \"" << this->name () << "[\";" << be_nl_2
;
379 if (be_global
->alt_mapping ())
381 *os
<< "for (CORBA::ULong i = 0; i < _tao_sequence.size (); ++i)";
385 *os
<< "for (CORBA::ULong i = 0; i < _tao_sequence.length (); ++i)";
390 << "if (i != 0)" << be_idt_nl
392 << "strm << \", \";" << be_uidt_nl
393 << "}" << be_uidt_nl
<< be_nl
394 << "strm << _tao_sequence[i];" << be_uidt_nl
395 << "}" << be_uidt_nl
<< be_nl
396 << "return strm << \"]\";" << be_uidt_nl
401 be_sequence::accept (be_visitor
*visitor
)
403 return visitor
->visit_sequence (this);
408 be_sequence::instance_name ()
410 static char namebuf
[NAMEBUFSIZE
];
411 ACE_OS::memset (namebuf
,
415 be_type
*const prim_type
= primitive_base_type ();
418 ACE_ERROR ((LM_ERROR
,
419 "(%N:%l) be_visitor_sequence_ch::"
420 "gen_instantiate_name - "
421 "Bad element type\n"));
426 // Generate the appropriate sequence type.
427 switch (this->managed_type ())
429 case be_sequence::MNG_PSEUDO
:
430 case be_sequence::MNG_OBJREF
:
431 if (this->unbounded ())
433 ACE_OS::sprintf (namebuf
,
434 "_TAO_unbounded_object_reference_sequence_%s",
435 prim_type
->local_name ()->get_string ());
439 ACE_OS::sprintf (namebuf
,
440 "_TAO_bounded_object_reference_sequence_%s_"
441 ACE_UINT32_FORMAT_SPECIFIER_ASCII
,
442 prim_type
->local_name ()->get_string (),
443 this->max_size ()->ev ()->u
.ulval
);
447 case be_sequence::MNG_VALUE
:
448 if (this->unbounded ())
450 ACE_OS::sprintf (namebuf
,
451 "_TAO_unbounded_valuetype_sequence_%s",
452 prim_type
->local_name ()->get_string ());
456 ACE_OS::sprintf (namebuf
,
457 "_TAO_bounded_valuetype_sequence_%s_"
458 ACE_UINT32_FORMAT_SPECIFIER_ASCII
,
459 prim_type
->local_name ()->get_string (),
460 this->max_size ()->ev ()->u
.ulval
);
464 case be_sequence::MNG_STRING
:
465 if (this->unbounded ())
467 ACE_OS::sprintf (namebuf
,
468 "::TAO::unbounded_basic_string_sequence<char>");
472 ACE_OS::sprintf (namebuf
,
473 "_TAO_unbounded_string_sequence_%s",
474 prim_type
->local_name ()->get_string ());
478 case be_sequence::MNG_WSTRING
:
479 if (this->unbounded ())
481 ACE_OS::sprintf (namebuf
,
482 "::TAO::unbounded_basic_string_sequence<CORBA::WChar>");
486 ACE_OS::sprintf (namebuf
,
487 "_TAO_bounded_wstring_sequence_%s",
488 prim_type
->local_name ()->get_string ());
492 default: // Not a managed type.
493 if (this->unbounded ())
495 // TAO provides extensions for octet sequences, first find out
496 // if the base type is an octet (or an alias for octet)
497 be_predefined_type
*predef
=
498 dynamic_cast<be_predefined_type
*> (prim_type
);
500 if (predef
!= nullptr
501 && predef
->pt() == AST_PredefinedType::PT_octet
)
503 ACE_OS::sprintf (namebuf
,
504 "::TAO::unbounded_value_sequence<CORBA::Octet>");
508 ACE_OS::sprintf (namebuf
,
509 "_TAO_unbounded_value_sequence_%s",
510 prim_type
->local_name ()->get_string ());
515 ACE_OS::sprintf (namebuf
,
516 "_TAO_bounded_value_sequence_%s_"
517 ACE_UINT32_FORMAT_SPECIFIER_ASCII
,
518 prim_type
->local_name ()->get_string (),
519 this->max_size ()->ev ()->u
.ulval
);
529 be_sequence::gen_base_class_name (TAO_OutStream
*os
,
530 const char * linebreak
,
533 be_type
*elem
= dynamic_cast<be_type
*> (this->base_type ());
535 if (be_global->alt_mapping () && this->unbounded ())
537 *os << "std::vector<" << elem->nested_type_name (ctx_scope)
543 // Generate the appropriate base class type.
544 switch (this->managed_type ())
546 case be_sequence::MNG_OBJREF
:
547 case be_sequence::MNG_PSEUDO
:
548 if (this->unbounded ())
550 *os
<< "::TAO::unbounded_object_reference_sequence<" << linebreak
551 << be_idt
<< be_idt_nl
552 << elem
->nested_type_name (ctx_scope
) << "," << linebreak
554 *os
<< elem
->nested_type_name (ctx_scope
, "_var") << linebreak
560 *os
<< "::TAO::bounded_object_reference_sequence<" << linebreak
561 << be_idt
<< be_idt_nl
562 << elem
->nested_type_name (ctx_scope
) << "," << linebreak
<< be_nl
;
563 *os
<< elem
->nested_type_name (ctx_scope
, "_var") << ","
564 << linebreak
<< be_nl
;
565 *os
<< this->max_size ()->ev ()->u
.ulval
<< linebreak
<< be_uidt_nl
570 case be_sequence::MNG_VALUE
:
571 if (this->unbounded ())
573 *os
<< "::TAO::unbounded_valuetype_sequence<" << linebreak
574 << be_idt
<< be_idt_nl
575 << elem
->nested_type_name (ctx_scope
) << "," << linebreak
577 *os
<< elem
->nested_type_name (ctx_scope
, "_var") << linebreak
583 *os
<< "::TAO::bounded_valuetype_sequence<" << linebreak
584 << be_idt
<< be_idt_nl
585 << elem
->nested_type_name (ctx_scope
) << "," << linebreak
587 *os
<< elem
->nested_type_name (ctx_scope
, "_var") << ","
588 << linebreak
<< be_nl
589 << this->max_size ()->ev ()->u
.ulval
<< linebreak
<< be_uidt_nl
594 case be_sequence::MNG_STRING
:
596 be_type
*const prim_type
= primitive_base_type ();
599 ACE_ERROR_RETURN ((LM_ERROR
,
600 "(%N:%l) be_sequence::"
601 "gen_base_class_name - "
602 "Bad element type\n"),
605 if (prim_type
->node_type () == AST_Decl::NT_string
)
608 dynamic_cast<be_string
*> (prim_type
);
611 ACE_ERROR_RETURN ((LM_ERROR
,
612 "(%N:%l) be_sequence::"
613 "gen_base_class_name - "
614 "bad string node\n"),
618 // We need to make a distinction between bounded and
619 // unbounded strings.
620 if (str
->max_size ()->ev ()->u
.ulval
!= 0)
622 if (this->unbounded ())
624 *os
<< "::TAO::unbounded_bd_string_sequence<char, "
625 << str
->max_size ()->ev ()->u
.ulval
<< ">";
629 *os
<< "::TAO::bounded_bd_string_sequence<char, "
630 << this->max_size ()->ev ()->u
.ulval
<< ", "
631 << str
->max_size ()->ev ()->u
.ulval
<< ">";
636 if (this->unbounded ())
638 *os
<< "::TAO::unbounded_basic_string_sequence<char>";
642 *os
<< "::TAO::bounded_basic_string_sequence<char, "
643 << this->max_size ()->ev ()->u
.ulval
<< ">";
650 case be_sequence::MNG_WSTRING
:
652 be_type
*const prim_type
= primitive_base_type ();
655 ACE_ERROR_RETURN ((LM_ERROR
,
656 "(%N:%l) be_sequence::"
657 "gen_base_class_name - "
658 "Bad element type\n"),
661 if (prim_type
->node_type () == AST_Decl::NT_wstring
)
664 dynamic_cast<be_string
*> (prim_type
);
667 ACE_ERROR_RETURN ((LM_ERROR
,
668 "(%N:%l) be_sequence::"
669 "gen_base_class_name - "
670 "bad string node\n"),
674 // We need to make a distinction between bounded and
675 // unbounded strings.
676 if (str
->max_size ()->ev ()->u
.ulval
!= 0)
678 if (this->unbounded ())
680 *os
<< "::TAO::unbounded_bd_string_sequence<CORBA::WChar, "
681 << str
->max_size ()->ev ()->u
.ulval
<< ">";
685 *os
<< "::TAO::bounded_bd_string_sequence<CORBA::WChar, "
686 << this->max_size ()->ev ()->u
.ulval
<< ", "
687 << str
->max_size ()->ev ()->u
.ulval
<< ">";
692 if (this->unbounded ())
694 *os
<< "::TAO::unbounded_basic_string_sequence<CORBA::WChar>";
698 *os
<< "::TAO::bounded_basic_string_sequence<CORBA::WChar, "
699 << this->max_size ()->ev ()->u
.ulval
<< ">";
706 default: // Not a managed type.
707 switch (elem
->base_node_type ())
709 case AST_Decl::NT_array
:
710 if (this->unbounded ())
712 *os
<< "::TAO::unbounded_array_sequence<" << linebreak
713 << be_idt
<< be_idt_nl
714 << elem
->nested_type_name (ctx_scope
) << "," << linebreak
716 *os
<< elem
->nested_type_name (ctx_scope
) << "_slice,"
717 << linebreak
<< be_nl
718 << elem
->nested_type_name (ctx_scope
) << "_tag"
719 << linebreak
<< be_uidt_nl
724 *os
<< "::TAO::bounded_array_sequence<" << linebreak
725 << be_idt
<< be_idt_nl
726 << elem
->nested_type_name (ctx_scope
) << "," << linebreak
728 *os
<< elem
->nested_type_name (ctx_scope
) << "_slice,"
729 << linebreak
<< be_nl
730 << elem
->nested_type_name (ctx_scope
) << "_tag,"
731 << linebreak
<< be_nl
732 << this->max_size ()->ev ()->u
.ulval
<< linebreak
740 be_type
*const base_type
= primitive_base_type ();
743 ACE_ERROR_RETURN ((LM_ERROR
,
744 "(%N:%l) be_sequence::"
745 "gen_base_class_name - "
746 "Bad element type\n"),
750 const char *tag
= "";
751 if (base_type
->node_type () == AST_Decl::NT_pre_defined
)
753 be_predefined_type
*const predefined_type
=
754 dynamic_cast<be_predefined_type
*> (base_type
);
755 if (!predefined_type
)
756 ACE_ERROR_RETURN ((LM_ERROR
,
757 "(%N:%l) be_sequence::"
758 "gen_base_class_name - "
759 "Bad element type\n"),
761 switch (predefined_type
->pt ())
763 case AST_PredefinedType::PT_uint8
:
764 tag
= ", CORBA::IDLv4::UInt8_tag";
766 case AST_PredefinedType::PT_int8
:
767 tag
= ", CORBA::IDLv4::Int8_tag";
775 << "::TAO::" << (unbounded () ? "un" : "") << "bounded_value_sequence< "
776 << elem
->nested_type_name (ctx_scope
);
778 *os
<< "," << this->max_size ()->ev ()->u
.ulval
;
791 be_sequence::field_node () const
793 return this->field_node_
;
797 be_sequence::field_node (be_field
*node
)
799 this->field_node_
= node
;
804 be_sequence::compute_tc_name ()
806 // Sequence TypeCodes can only be accessed through an alias
807 // TypeCode. Generate a TypeCode name that is meant for internal
810 Identifier
* tao_id
= nullptr;
814 ACE_NEW (this->tc_name_
,
815 UTL_ScopedName (tao_id
,
818 char bound
[30] = { 0 };
820 ACE_OS::sprintf (bound
,
821 "_" ACE_UINT32_FORMAT_SPECIFIER_ASCII
,
822 this->max_size ()->ev ()->u
.ulval
);
824 ACE_CString local_tc_name
=
826 + ACE_CString (this->flat_name ())
827 + ACE_CString (bound
);
829 Identifier
* typecode_scope
= nullptr;
830 ACE_NEW (typecode_scope
,
831 Identifier ("TypeCode"));
833 UTL_ScopedName
* tc_scope_conc_name
= nullptr;
834 ACE_NEW (tc_scope_conc_name
,
835 UTL_ScopedName (typecode_scope
,
838 this->tc_name_
->nconc (tc_scope_conc_name
);
840 Identifier
* id
= nullptr;
842 Identifier (local_tc_name
.c_str ()));
844 UTL_ScopedName
* conc_name
= nullptr;
849 this->tc_name_
->nconc (conc_name
);
853 be_sequence::smart_fwd_helper_name (AST_Decl
*ctx_scope
,
856 if (ScopeAsDecl (elem
->defined_in ()) == ctx_scope
)
858 ACE_CString retval
= "tao_";
859 retval
+= elem
->local_name ()->get_string ();
860 return retval
.rep ();
863 return elem
->fwd_helper_name ();
867 be_sequence::destroy ()
869 // Call the destroy methods of our base classes.
870 this->be_scope::destroy ();
871 this->be_type::destroy ();
872 this->AST_Sequence::destroy ();