// Compute total number of members. int AST_Operation::compute_argument_attr (void) { if (this->argument_count_ != -1) { return 0; } AST_Decl *d = 0; AST_Type *type = 0; AST_Argument *arg = 0; this->argument_count_ = 0; // If there are elements in this scope. if (this->nmembers () > 0) { // Instantiate a scope iterator. for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls); !si.is_done (); si.next ()) { // Get the next AST decl node. d = si.item (); if (d->node_type () == AST_Decl::NT_argument) { this->argument_count_++; arg = AST_Argument::narrow_from_decl (d); if (arg->direction() == AST_Argument::dir_IN || arg->direction() == AST_Argument::dir_INOUT) { this->has_in_arguments_ = true; } type = AST_Type::narrow_from_decl (arg->field_type ()); if (type->node_type () == AST_Decl::NT_native) { this->has_native_ = 1; } } } } type = AST_Type::narrow_from_decl (this->return_type ()); if (type->node_type () == AST_Decl::NT_native) { this->has_native_ = 1; } return 0; }
bool AST_Operation::void_return_type (void) { AST_Type* type = this->return_type (); return (type->node_type () == AST_Decl::NT_pre_defined && (AST_PredefinedType::narrow_from_decl (type)->pt () == AST_PredefinedType::PT_void)); }
int be_visitor_array::visit_typedef (be_typedef *node) { TAO_OutStream *os = this->ctx_->stream (); AST_Type *pbt = node->primitive_base_type (); AST_Decl::NodeType nt = pbt->node_type (); AST_PredefinedType::PredefinedType pt = AST_PredefinedType:: PT_void; int result = 0; // We check for these first, because in these cases, we replace the // entire slice type with one of the strings below, instead of using // the node's type name, possibly suffixed with '_var'. if (nt == AST_Decl::NT_string) { *os << "::TAO::String_Manager"; return 0; } else if (nt == AST_Decl::NT_wstring) { *os << "::TAO::WString_Manager"; return 0; } result = this->visit_node (node); if (nt == AST_Decl::NT_pre_defined) { AST_PredefinedType *pdt = AST_PredefinedType::narrow_from_decl (pbt); pt = pdt->pt (); } // We must append a "_var" for typedefs of interfaces, CORBA::Objects or // typecodes. if (nt == AST_Decl::NT_interface || nt == AST_Decl::NT_interface_fwd || pt == AST_PredefinedType::PT_pseudo || pt == AST_PredefinedType::PT_object) { *os << "_var"; } return result; }
// Compute total number of members. int AST_Factory::compute_argument_attr (void) { if (this->argument_count_ != -1) { return 0; } AST_Decl *d = 0; AST_Type *type = 0; AST_Argument *arg = 0; this->argument_count_ = 0; // If there are elements in this scope. if (this->nmembers () > 0) { for (UTL_ScopeActiveIterator i (this, IK_decls); !i.is_done (); i.next ()) { // Get the next AST decl node. d = i.item (); if (d->node_type () == AST_Decl::NT_argument) { this->argument_count_++; arg = AST_Argument::narrow_from_decl (d); type = AST_Type::narrow_from_decl (arg->field_type ()); if (type->node_type () == AST_Decl::NT_native) { this->has_native_ = 1; } } } } return 0; }
bool AST_illegal_recursive_type (AST_Decl *t) { if (t == 0) { return false; } AST_Decl::NodeType nt; AST_Type *ut = AST_Type::narrow_from_decl (t); if (ut != 0) { ut = ut->unaliased_type (); nt = ut->node_type (); } else { nt = t->node_type (); } if (nt == AST_Decl::NT_interface) { // Check for interface->struct/union->....->interface nesting. // return AST_illegal_interface_recursion (t); } else if (nt != AST_Decl::NT_struct && nt != AST_Decl::NT_union) { // Structs and unions fall through to the check below. return false; // NOT ILLEGAL. } bool check_for_struct = false; bool check_for_union = false; AST_Structure *st1 = 0; AST_Union *un1 = 0; // Narrow the type appropriately so comparison will work. if (t->node_type () == AST_Decl::NT_struct) { check_for_struct = true; st1 = AST_Structure::narrow_from_decl (t); if (st1 == 0) { return false; // NOT ILLEGAL. } } else if (t->node_type () == AST_Decl::NT_union) { check_for_union = true; un1 = AST_Union::narrow_from_decl (t); if (un1 == 0) { return false; // NOT ILLEGAL. } } UTL_Scope *s = 0; AST_Structure *st2 = 0; AST_Union *un2 = 0; // OK, iterate up the stack. for (UTL_ScopeStackActiveIterator i (idl_global->scopes ()); !i.is_done (); i.next ()) { s = i.item (); // If we hit a NULL we're done since it means that we're nested inside // a sequence, where recursive types may be used. if (s == 0) { return false; // NOT ILLEGAL. } // OK, must check this scope. if (s->scope_node_type () == AST_Decl::NT_struct && check_for_struct == true) { st2 = AST_Structure::narrow_from_scope (s); if (st2 != 0 && st2 == st1) { return true; // ILLEGAL RECURSIVE TYPE USE. } } else if (s->scope_node_type () == AST_Decl::NT_union && check_for_union == true) { un2 = AST_Union::narrow_from_scope (s); if (un2 != 0 && un2 == un1) { return true; // ILLEGAL RECURSIVE TYPE USE. } } } // No more scopes to check. This type was used legally. return false; // NOT ILLEGAL. }
// Are we or the parameter node involved in any recursion? bool AST_Exception::in_recursion (ACE_Unbounded_Queue<AST_Type *> &list) { bool self_test = (list.size () == 0); // We should calculate this only once. If it has already been // done, just return it. if (self_test && this->in_recursion_ != -1) { return (this->in_recursion_ == 1); } if (list.size () > 1) { if (match_names (this, list)) { // this happens when we are not recursed ourselves but instead // are part of another recursive type return false; } } list.enqueue_tail(this); // Proceed if the number of members in our scope is greater than 0. if (this->nmembers () > 0) { // Continue until each element is visited. for (UTL_ScopeActiveIterator i (this, IK_decls);!i.is_done ();i.next ()) { AST_Field *field = AST_Field::narrow_from_decl (i.item ()); if (field == 0) // This will be an enum value or other legitimate non-field // member - in any case, no recursion. { continue; } AST_Type *type = field->field_type (); if (type->node_type () == AST_Decl::NT_typedef) { AST_Typedef *td = AST_Typedef::narrow_from_decl (type); type = td->primitive_base_type (); } if (type == 0) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%N:%l) AST_Exception::") ACE_TEXT ("in_recursion - ") ACE_TEXT ("bad field type\n")), 0); } if (type->in_recursion (list)) { if (self_test) this->in_recursion_ = 1; idl_global->recursive_type_seen_ = true; return true; } } } // Not in recursion. if (self_test) this->in_recursion_ = 0; return 0; //this->in_recursion_; }
// Specialized visit_scope method for stucts only. int ifr_adding_visitor_structure::visit_scope (UTL_Scope *node) { // If the struct has members that are scopes but not structs, // the regular visit_scope method should be called instead. if (node->scope_node_type () != AST_Decl::NT_struct) { return ifr_adding_visitor::visit_scope (node); } AST_Structure *s = AST_Structure::narrow_from_scope (node); CORBA::ULong nfields = static_cast<CORBA::ULong> (s->nfields ()); this->members_.length (nfields); AST_Field **f = 0; try { // Visit each field. for (CORBA::ULong i = 0; i < nfields; ++i) { if (s->field (f, i) != 0) { ORBSVCS_ERROR_RETURN (( LM_ERROR, ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::") ACE_TEXT ("visit_scope -") ACE_TEXT (" field node access failed\n")), -1); } AST_Type *ft = (*f)->field_type (); bool defined_here = ft->is_child (this->scope_); // If the struct member is defined in the struct, we have to // do some visiting - otherwise we can just look up the entry. if (defined_here) { if (ft->node_type () == AST_Decl::NT_struct) { // Since the enclosing scope hasn't been created yet, // we make a special visitor to create this member // at global scope and move it into the struct later. ifr_adding_visitor_structure visitor (ft); if (ft->ast_accept (&visitor) == -1) { ORBSVCS_ERROR_RETURN (( LM_ERROR, ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::") ACE_TEXT ("visit_scope -") ACE_TEXT (" failed to accept visitor\n")), -1); } this->ir_current_ = CORBA::IDLType::_duplicate (visitor.ir_current ()); } else { if (ft->ast_accept (this) == -1) { ORBSVCS_ERROR_RETURN (( LM_ERROR, ACE_TEXT ("(%N:%l) ifr_adding_visitor_structure::") ACE_TEXT ("visit_scope -") ACE_TEXT (" failed to accept visitor\n")), -1); } } } else { // Updates ir_current_. this->get_referenced_type (ft); } this->members_[i].name = CORBA::string_dup ((*f)->local_name ()->get_string ()); // IfR method create_struct does not use this - it just needs // to be non-zero for marshaling. this->members_[i].type = CORBA::TypeCode::_duplicate (CORBA::_tc_void); this->members_[i].type_def = CORBA::IDLType::_duplicate (this->ir_current_.in ()); } } catch (const CORBA::Exception& ex) { ex._tao_print_exception ( ACE_TEXT ( "ifr_adding_visitor_structure::visit_scope")); return -1; } return 0; }
int be_visitor_arg_traits::visit_argument (be_argument *node) { if (this->ctx_->alias () != 0 || this->generated (node)) { return 0; } AST_Type *bt = node->field_type (); AST_Decl::NodeType nt = bt->node_type (); // We are interested here only in unaliased, bounded // (w)strings. if (nt != AST_Decl::NT_string && nt != AST_Decl::NT_wstring) { return 0; } be_string *st = be_string::narrow_from_decl (bt); ACE_CDR::ULong bound = st->max_size ()->ev ()->u.ulval; if (bound == 0) { return 0; } TAO_OutStream *os = this->ctx_->stream (); *os << be_nl_2 << "// TAO_IDL - Generated from" << be_nl << "// " << __FILE__ << ":" << __LINE__; std::string guard_suffix = std::string (this->S_) + std::string ("arg_traits"); // The guard should be generated to prevent multiple declarations, // since a bounded (w)string of the same length may be used or typedef'd // more than once. os->gen_ifdef_macro (node->flat_name (), guard_suffix.c_str (), false); bool wide = (st->width () != 1); // It is legal IDL to declare a bounded (w)string as an operation // parameter type. There could be any number of identical // declarations in the same build, translation unit, or even in // the same operation, so we use the argument's flat name to // declare an empty struct, and use that struct as the template // parameter for Arg_Traits<>. *os << be_nl_2; AST_Decl *op = ScopeAsDecl (node->defined_in ()); AST_Decl *intf = ScopeAsDecl (op->defined_in ()); ACE_CString arg_flat_name (intf->flat_name ()); arg_flat_name += '_'; arg_flat_name += op->local_name ()->get_string (); arg_flat_name += '_'; arg_flat_name += node->local_name ()->get_string (); // Avoid generating a duplicate structure in the skeleton. if (ACE_OS::strlen (this->S_) == 0) { *os << "struct " << arg_flat_name.c_str () << " {};" << be_nl_2; } *os << "template<>" << be_nl << "class " << this->S_ << "Arg_Traits<" << arg_flat_name.c_str () << ">" << be_idt_nl << ": public" << be_idt << be_idt_nl << "BD_String_" << this->S_ << "Arg_Traits_T<" << be_nl << "CORBA::" << (wide ? "W" : "") << "String_var," << be_nl << bound << "," << be_nl << this->insert_policy() << be_uidt_nl << ">" << be_uidt << be_uidt << be_uidt_nl << "{" << be_nl << "};"; os->gen_endif (); this->generated (node, true); return 0; }
int be_visitor_arg_traits::visit_operation (be_operation *node) { if (this->generated (node) || node->is_local () || node->imported ()) { return 0; } AST_Type *rt = node->return_type (); AST_Decl::NodeType nt = rt->node_type (); // If our return type is an unaliased bounded (w)string, we create // an empty struct using the operation's flat name for the type, // and use this type as the Arg_Traits<> template parameter. All // this is necessary because there could be any number of such // return types, all identical, in the same interface, valuetype, // translation unit, or build, and we need a unique type for the // Arg_Traits<> template parameter. if (nt == AST_Decl::NT_string || nt == AST_Decl::NT_wstring) { AST_String *str = AST_String::narrow_from_decl (rt); ACE_CDR::ULong bound = str->max_size ()->ev ()->u.ulval; if (bound > 0) { TAO_OutStream *os = this->ctx_->stream (); *os << be_nl_2 << "// TAO_IDL - Generated from" << be_nl << "// " << __FILE__ << ":" << __LINE__; std::string guard_suffix = std::string (this->S_) + std::string ("arg_traits"); // The guard should be generated to prevent multiple declarations, // since a bounded (w)string of the same length may be used or typedef'd // more than once. os->gen_ifdef_macro (node->flat_name (), guard_suffix.c_str (), false); bool wide = (str->width () != 1); *os << be_nl_2; // Avoid generating a duplicate structure in the skeleton. if (ACE_OS::strlen (this->S_) == 0) { *os << "struct " << node->flat_name () << " {};" << be_nl_2; } *os << "template<>" << be_nl << "class " << this->S_ << "Arg_Traits<" << node->flat_name () << ">" << be_idt_nl << ": public" << be_idt << be_idt_nl << "BD_String_" << this->S_ << "Arg_Traits_T<" << be_nl << "CORBA::" << (wide ? "W" : "") << "String_var," << be_nl << bound << "," << be_nl << this->insert_policy() << ">" << be_uidt << be_uidt << be_uidt_nl << "{" << be_nl << "};"; os->gen_endif (); } } // This will catch (in visit_argument() below) any parameters that // are unaliased, bounded (w)strings. if (this->visit_scope (node) != 0) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("be_visitor_arg_traits::") ACE_TEXT ("visit_operation - visit scope failed\n")), -1); } this->generated (node, true); return 0; }
// Specialized visit_scope method for unions only. int ifr_adding_visitor_union::visit_scope (UTL_Scope *node) { // If the union has members that are scopes but not unions, // the regular visit_scope method should be called instead. if (node->scope_node_type () != AST_Decl::NT_union) { return ifr_adding_visitor::visit_scope (node); } AST_Union *u = AST_Union::narrow_from_scope (node); CORBA::ULong nfields = static_cast<CORBA::ULong> (u->nfields ()); this->members_.length (nfields); AST_Field **f = 0; // Index into members_. CORBA::ULong index = 0; try { // Visit each field. for (CORBA::ULong i = 0; i < nfields; ++i) { if (u->field (f, i) != 0) { ORBSVCS_ERROR_RETURN (( LM_ERROR, ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::") ACE_TEXT ("visit_scope -") ACE_TEXT (" field node access failed\n") ), -1 ); } AST_Type *ft = (*f)->field_type (); bool defined_here = ft->is_child (this->scope_); // If the union member is defined in the union, we have to // do some visiting - otherwise we can just look up the entry. if (defined_here) { if (ft->node_type () == AST_Decl::NT_union) { // Since the enclosing scope hasn't been created yet, // we make a special visitor to create this member // at global scope and move it into the union later. ifr_adding_visitor_union visitor (ft); if (ft->ast_accept (&visitor) == -1) { ORBSVCS_ERROR_RETURN (( LM_ERROR, ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::") ACE_TEXT ("visit_scope -") ACE_TEXT (" failed to accept visitor\n")), -1); } this->ir_current_ = CORBA::IDLType::_duplicate (visitor.ir_current ()); } else { if (ft->ast_accept (this) == -1) { ORBSVCS_ERROR_RETURN (( LM_ERROR, ACE_TEXT ("(%N:%l) ifr_adding_visitor_union::") ACE_TEXT ("visit_scope -") ACE_TEXT (" failed to accept visitor\n")), -1); } } } else { // Updates ir_current_. this->get_referenced_type (ft); } // Get the case label(s). AST_UnionLabel *case_label = 0; AST_UnionBranch *ub = AST_UnionBranch::narrow_from_decl (*f); unsigned long len = ub->label_list_length (); // If there are multiple case labels, we will have an element // in the UnionMemberSeq for each label, not just for each member, // so the list length and the loop terminator must both be // increased accordingly. if (len > 1) { this->members_.length (this->members_.length () + len - 1); } for (unsigned long j = 0; j < len; ++j) { case_label = ub->label (j); // Is this a regular label or default label? if (case_label->label_kind () == AST_UnionLabel::UL_label) { AST_Expression::AST_ExprValue *ev = case_label->label_val ()->ev (); // If the discriminator is an enum, we can't just insert // a ulong into the Any member of struct UnionMember. if (u->disc_type ()->node_type () == AST_Decl::NT_enum) { TAO_OutputCDR cdr; cdr.write_ulong (ev->u.ulval); TAO_InputCDR in_cdr (cdr); TAO::Unknown_IDL_Type *unk = 0; ACE_NEW_RETURN (unk, TAO::Unknown_IDL_Type ( this->disc_tc_.in (), in_cdr), -1); this->members_[index].label.replace (unk); } else { this->load_any (ev, this->members_[index].label); } } else // Default case label. { this->members_[index].label <<= CORBA::Any::from_octet (0); } this->members_[index].name = CORBA::string_dup ((*f)->local_name ()->get_string ()); // IfR method create_union does not use this - it just needs // to be non-zero for marshaling. this->members_[index].type = CORBA::TypeCode::_duplicate (CORBA::_tc_void); this->members_[index++].type_def = CORBA::IDLType::_duplicate (this->ir_current_.in ()); } } } catch (const CORBA::Exception& ex) { ex._tao_print_exception ( ACE_TEXT ( "ifr_adding_visitor_union::visit_scope")); return -1; } return 0; }