diff --git a/compiler2/Type.cc b/compiler2/Type.cc index d87e9642fe38d86da08139ccf2abff8fe4f6bba4..863a334c68bdeea21a97c90608092130a6fd7d4d 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -4544,7 +4544,8 @@ namespace Common { ea.get_encdecvalue_mappings(inmaps, maps); maps = encode ? maps : inmaps; maps->set_my_scope(this->get_my_scope()); - maps->chk(); + // The first param should be true, the other is not important if the first is true + maps->chk(true, false); // look for coding settings t = encode ? this : Type::get_pooltype(T_BSTR); mapping = maps->get_mapping_byType(t); diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc index 9876b05cbb37ee58b0517d195e07b4fa805c3496..aa26b3bce08a74d472477b6db2213425831be519 100644 --- a/compiler2/ttcn3/Ttcnstuff.cc +++ b/compiler2/ttcn3/Ttcnstuff.cc @@ -12,6 +12,7 @@ * Kovacs, Ferenc * Raduly, Csaba * Szabados, Kristof + * Szabo, Bence Janos * Zalanyi, Balazs Andor * ******************************************************************************/ @@ -374,7 +375,7 @@ namespace Ttcn { } } - void TypeMappingTarget::chk_function(Type *source_type) + void TypeMappingTarget::chk_function(Type *source_type, bool legacy, bool incoming) { Error_Context cntxt(this, "In `function' mapping"); Assignment *t_ass = u.func.function_ref->get_refd_assignment(false); @@ -384,26 +385,38 @@ namespace Ttcn { case Assignment::A_FUNCTION: case Assignment::A_FUNCTION_RVAL: case Assignment::A_FUNCTION_RTEMP: + break; case Assignment::A_EXT_FUNCTION: case Assignment::A_EXT_FUNCTION_RVAL: case Assignment::A_EXT_FUNCTION_RTEMP: - break; + // External functions are not allowed when the standard like behaviour is used + if (legacy) { + break; + } default: - u.func.function_ref->error("Reference to a function or external " - "function was expected instead of %s", + u.func.function_ref->error("Reference to a function%s" + " was expected instead of %s", + legacy ? " or external function" : "", t_ass->get_description().c_str()); return; } u.func.function_ptr = dynamic_cast<Ttcn::Def_Function_Base*>(t_ass); if (!u.func.function_ptr) FATAL_ERROR("TypeMappingTarget::chk_function()"); - if (u.func.function_ptr->get_prototype() == + if (legacy && u.func.function_ptr->get_prototype() == Ttcn::Def_Function_Base::PROTOTYPE_NONE) { u.func.function_ref->error("The referenced %s does not have `prototype' " "attribute", u.func.function_ptr->get_description().c_str()); return; } + + if (!legacy && u.func.function_ptr->get_prototype() != + Ttcn::Def_Function_Base::PROTOTYPE_FAST) { + u.func.function_ref->error("The referenced %s does not have `prototype' " + "fast attribute", u.func.function_ptr->get_description().c_str()); + return; + } Type *input_type = u.func.function_ptr->get_input_type(); - if (input_type && !source_type->is_identical(input_type)) { + if (legacy && input_type && !source_type->is_identical(input_type)) { source_type->error("The input type of %s must be the same as the source " "type of the mapping: `%s' was expected instead of `%s'", u.func.function_ptr->get_description().c_str(), @@ -411,13 +424,61 @@ namespace Ttcn { input_type->get_typename().c_str()); } Type *output_type = u.func.function_ptr->get_output_type(); - if (output_type && !target_type->is_identical(output_type)) { + if (legacy && output_type && !target_type->is_identical(output_type)) { target_type->error("The output type of %s must be the same as the " "target type of the mapping: `%s' was expected instead of `%s'", u.func.function_ptr->get_description().c_str(), target_type->get_typename().c_str(), output_type->get_typename().c_str()); } + + // The standard like behaviour has different function param checking + if (!legacy) { + // In the error message the source type is the target_type + // and the target type is the source_type for a reason. + // Reason: In the new standard like behaviour the conversion functions + // has the correct param order for in and out parameters + // (which is more logical than the old behaviour) + // For example: + // in octetstring from integer with int_to_oct() + // | | | + // target_type source_type conv. func. + if (incoming) { + if (input_type && !target_type->is_identical(input_type)) { + target_type->error("The input type of %s must be the same as the " + "source type of the mapping: `%s' was expected instead of `%s'", + u.func.function_ptr->get_description().c_str(), + target_type->get_typename().c_str(), + input_type->get_typename().c_str()); + } + if (output_type && !source_type->is_identical(output_type)) { + target_type->error("The output type of %s must be the same as the " + "target type of the mapping: `%s' was expected instead of `%s'", + u.func.function_ptr->get_description().c_str(), + source_type->get_typename().c_str(), + output_type->get_typename().c_str()); + } + } else { + // For example: + // out octetstring to integer with oct_to_int() + // | | | + // source_type target_type conv. func. + if (input_type && !source_type->is_identical(input_type)) { + target_type->error("The input type of %s must be the same as the " + "source type of the mapping: `%s' was expected instead of `%s'", + u.func.function_ptr->get_description().c_str(), + source_type->get_typename().c_str(), + input_type->get_typename().c_str()); + } + if (output_type && !target_type->is_identical(output_type)) { + target_type->error("The output type of %s must be the same as the " + "target type of the mapping: `%s' was expected instead of `%s'", + u.func.function_ptr->get_description().c_str(), + target_type->get_typename().c_str(), + output_type->get_typename().c_str()); + } + } + } } void TypeMappingTarget::chk_encode(Type *source_type) @@ -456,7 +517,7 @@ namespace Ttcn { if (u.encdec.eb_list) u.encdec.eb_list->chk(); } - void TypeMappingTarget::chk(Type *source_type) + void TypeMappingTarget::chk(Type *source_type, bool legacy, bool incoming) { if (checked) return; checked = true; @@ -471,7 +532,7 @@ namespace Ttcn { case TM_DISCARD: break; case TM_FUNCTION: - chk_function(source_type); + chk_function(source_type, legacy, incoming); break; case TM_ENCODE: chk_encode(source_type); @@ -663,7 +724,7 @@ namespace Ttcn { targets->set_my_scope(p_scope); } - void TypeMapping::chk() + void TypeMapping::chk(bool legacy, bool incoming) { Error_Context cntxt(this, "In type mapping"); { @@ -674,7 +735,7 @@ namespace Ttcn { bool has_sliding = false, has_non_sliding = false; for (size_t i = 0; i < nof_targets; i++) { TypeMappingTarget *target = targets->get_target_byIndex(i); - target->chk(source_type); + target->chk(source_type, legacy, incoming); if (nof_targets > 1) { switch (target->get_mapping_type()) { case TypeMappingTarget::TM_DISCARD: @@ -689,13 +750,18 @@ namespace Ttcn { if (t_function) { switch (t_function->get_prototype()) { case Ttcn::Def_Function_Base::PROTOTYPE_NONE: - break; + break; case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK: has_non_sliding = true; break; case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING: has_sliding = true; break; + case Ttcn::Def_Function_Base::PROTOTYPE_FAST: + // New standard like behaviour has no such limit + if (!legacy) { + break; + } default: target->error("The referenced %s must have the attribute " "`prototype(backtrack)' or `prototype(sliding)' when more " @@ -794,14 +860,14 @@ namespace Ttcn { return mappings_m[p_type->get_typename()]; } - void TypeMappings::chk() + void TypeMappings::chk(bool legacy, bool incoming) { if (checked) return; checked = true; size_t nof_mappings = mappings_v.size(); for (size_t i = 0; i < nof_mappings; i++) { TypeMapping *mapping = mappings_v[i]; - mapping->chk(); + mapping->chk(legacy, incoming); Type *source_type = mapping->get_source_type(); if (source_type->get_type_refd_last()->get_typetype() != Type::T_ERROR) { const string& source_type_name = source_type->get_typename(); @@ -959,10 +1025,10 @@ namespace Ttcn { : Node(), Location(), my_type(0), operation_mode(p_operation_mode), in_list(p_in_list), out_list(p_out_list), inout_list(p_inout_list), in_all(p_in_all), out_all(p_out_all), inout_all(p_inout_all), - checked(false), + checked(false), legacy(true), in_msgs(0), out_msgs(0), in_sigs(0), out_sigs(0), testport_type(TP_REGULAR), port_type(PT_REGULAR), - provider_ref(0), provider_type(0), in_mappings(0), out_mappings(0) + provider_refs(), provider_types(), in_mappings(0), out_mappings(0) { } @@ -975,7 +1041,11 @@ namespace Ttcn { delete out_msgs; delete in_sigs; delete out_sigs; - delete provider_ref; + for (size_t i = 0; i < provider_refs.size(); i++) { + delete provider_refs[i]; + } + provider_refs.clear(); + provider_types.clear(); delete in_mappings; delete out_mappings; } @@ -995,8 +1065,9 @@ namespace Ttcn { if (out_msgs) out_msgs->set_fullname(p_fullname + ".<outgoing_messages>"); if (in_sigs) in_sigs->set_fullname(p_fullname + ".<incoming_signatures>"); if (out_sigs) out_sigs->set_fullname(p_fullname + ".<outgoing_signatures>"); - if (provider_ref) - provider_ref->set_fullname(p_fullname + ".<provider_ref>"); + for (size_t i = 0; i < provider_refs.size(); i++) { + provider_refs[i]->set_fullname(p_fullname + ".<provider_ref>"); + } if (in_mappings) in_mappings->set_fullname(p_fullname + ".<in_mappings>"); if (out_mappings) out_mappings->set_fullname(p_fullname + ".<out_mappings>"); @@ -1007,7 +1078,9 @@ namespace Ttcn { if (in_list) in_list->set_my_scope(p_scope); if (out_list) out_list->set_my_scope(p_scope); if (inout_list) inout_list->set_my_scope(p_scope); - if (provider_ref) provider_ref->set_my_scope(p_scope); + for (size_t i = 0; i < provider_refs.size(); i++) { + provider_refs[i]->set_my_scope(p_scope); + } if (in_mappings) in_mappings->set_my_scope(p_scope); if (out_mappings) out_mappings->set_my_scope(p_scope); } @@ -1097,7 +1170,8 @@ namespace Ttcn { Type *t; // in case of 'user' port types the address visible and supported by the // 'provider' port type is relevant - if (port_type == PT_USER && provider_type) t = provider_type; + // TODO: currently not supported the address in the new standard like behaviour + if (port_type == PT_USER && provider_types.size() > 0) t = provider_types[0]; else t = my_type; return t->get_my_scope()->get_scope_mod()->get_address_type(); } else { @@ -1109,28 +1183,36 @@ namespace Ttcn { void PortTypeBody::add_provider_attribute() { port_type = PT_PROVIDER; - delete provider_ref; - provider_ref = 0; - provider_type = 0; + for (size_t i = 0; i < provider_refs.size(); i++) { + delete provider_refs[i]; + } + provider_refs.clear(); + provider_types.clear(); delete in_mappings; in_mappings = 0; delete out_mappings; out_mappings = 0; } - void PortTypeBody::add_user_attribute(Ttcn::Reference *p_provider_ref, - TypeMappings *p_in_mappings, TypeMappings *p_out_mappings) + void PortTypeBody::add_user_attribute(Ttcn::Reference **p_provider_refs, + size_t n_provider_refs, TypeMappings *p_in_mappings, TypeMappings *p_out_mappings, + bool p_legacy) { - if (!p_provider_ref || !my_type) + if (!p_provider_refs || n_provider_refs == 0 || !my_type) FATAL_ERROR("PortTypeBody::add_user_attribute()"); Scope *t_scope = my_type->get_my_scope(); const string& t_fullname = get_fullname(); port_type = PT_USER; - delete provider_ref; - provider_ref = p_provider_ref; - provider_ref->set_fullname(t_fullname + ".<provider_ref>"); - provider_ref->set_my_scope(t_scope); - provider_type = 0; + for (size_t i = 0; i < provider_refs.size(); i++) { + delete provider_refs[i]; + } + provider_refs.clear(); + for (size_t i = 0; i < n_provider_refs; i++) { + provider_refs.add(p_provider_refs[i]); + provider_refs[i]->set_fullname(t_fullname + ".<provider_ref>"); + provider_refs[i]->set_my_scope(t_scope); + } + provider_types.clear(); // Do not delete provider_types delete in_mappings; in_mappings = p_in_mappings; if (in_mappings) { @@ -1143,13 +1225,14 @@ namespace Ttcn { out_mappings->set_fullname(t_fullname + ".<out_mappings>"); out_mappings->set_my_scope(t_scope); } + legacy = p_legacy; } Type *PortTypeBody::get_provider_type() const { if (!checked || port_type != PT_USER) FATAL_ERROR("PortTypeBody::get_provider_type()"); - return provider_type; + return provider_types[0]; // TODO, called in check coonn endpoint } void PortTypeBody::chk_list(const Types *list, bool is_in, bool is_out) @@ -1249,60 +1332,190 @@ namespace Ttcn { } } + void PortTypeBody::chk_map_translation() { + + if (port_type != PT_USER || legacy) { + FATAL_ERROR("PortTypeBody::chk_map_translation()"); + } + + vector<Type> provider_ins; + + TypeSet mapping_ins; + + if (in_mappings) { + for (size_t i = 0; i < in_mappings->get_nof_mappings(); i++) { + TypeMapping * mapping = in_mappings->get_mapping_byIndex(i); + for (size_t j = 0; j < mapping->get_nof_targets(); j++) { + if (!mapping_ins.has_type(mapping->get_target_byIndex(j)->get_target_type())) { + mapping_ins.add_type(mapping->get_target_byIndex(j)->get_target_type()); + } + } + } + } + + for (size_t i = 0; i < provider_types.size(); i++) { + PortTypeBody *provider_body = provider_types[i]->get_PortBody(); + if (provider_body->in_msgs) { + for (size_t j = 0; j < provider_body->in_msgs->get_nof_types(); j++) { + provider_ins.add(provider_body->in_msgs->get_type_byIndex(j)); + } + } + + for (size_t j = 0; j < provider_ins.size(); j++) { + bool found = false; + if (inout_list) { + for (size_t k = 0; k < inout_list->get_nof_types(); k++) { + if (provider_ins[j]->get_typename() == inout_list->get_type_byIndex(k)->get_typename()) { + found = true; + break; + } + } + } + if (((in_msgs && in_msgs->has_type(provider_ins[j])) // Provider in message is present in the port in message + || mapping_ins.has_type(provider_ins[j]) // Provider in message is present in one of the in mappings + || found // Provider in message is present in the inout list of the port + ) == false) { + error("Incoming message type `%s' is not present in the in(out) message list or in the from mapping types, coming from port: `%s'.", + provider_ins[j]->get_typename().c_str(), + provider_types[i]->get_dispname().c_str()); // in mapping snull + } + } + + if (inout_list) { + for (size_t j = 0; j < inout_list->get_nof_types(); j++) { + if (provider_body->inout_list) { + bool found = false; + // If the inout message of the port is present on the provider inout message list + for (size_t k = 0; k < provider_body->inout_list->get_nof_types(); k++) { + if (inout_list->get_type_byIndex(j)->get_typename() == + provider_body->inout_list->get_type_byIndex(k)->get_typename()) { + found = true; + break; + } + } + if (found) { + continue; + } + } + bool found_in = false; + if (provider_body->in_list) { + // If the inout message of the port is present on the provider in message list + for (size_t k = 0; k < provider_body->in_list->get_nof_types(); k++) { + if (inout_list->get_type_byIndex(j)->get_typename() == + provider_body->in_list->get_type_byIndex(k)->get_typename()) { + found_in = true; + break; + } + } + } + bool found_out = false; + if (provider_body->out_list) { + // If the inout message of the port is present on the provider out message list + for (size_t k = 0; k < provider_body->out_list->get_nof_types(); k++) { + if (inout_list->get_type_byIndex(j)->get_typename() == + provider_body->out_list->get_type_byIndex(k)->get_typename()) { + found_out = true; + break; + } + } + } + + // Error if the inout message of the port is not present on the in and out message list + if (!found_in || !found_out) { + error("Inout message type `%s' is not present on the in and out messages or the inout messages of port `%s'.", + inout_list->get_type_byIndex(j)->get_typename().c_str(), + provider_types[i]->get_dispname().c_str()); + } + } + } + + if (out_list) { + for (size_t j = 0; j < out_list->get_nof_types(); j++) { + bool found = false; + if (provider_body->out_list) { + for (size_t k = 0; k < provider_body->out_list->get_nof_types(); k++) { + if (out_list->get_type_byIndex(j)->get_typename() == + provider_body->out_list->get_type_byIndex(k)->get_typename()) { + found = true; + break; + } + } + } + if (!found) { + error("Out message type `%s' is not present in the out message list of the port `%s'.", + out_list->get_type_byIndex(j)->get_typename().c_str(), + provider_types[i]->get_dispname().c_str()); + } + } + } + provider_ins.clear(); + } // provider_types.size() + } + + void PortTypeBody::chk_connect_translation() { + FATAL_ERROR("PortTypeBody::chk_connect_translation(): Not implemented"); + } + void PortTypeBody::chk_user_attribute() { - Error_Context cntxt(this, "In extension attribute `user'"); + Error_Context cntxt(this, + legacy ? "In extension attribute `user'" : "In translation capability"); // check the reference that points to the provider type - provider_type = 0; + provider_types.clear(); PortTypeBody *provider_body = 0; - Assignment *t_ass = provider_ref->get_refd_assignment(); // provider port - if (t_ass) { - if (t_ass->get_asstype() == Assignment::A_TYPE) { - Type *t = t_ass->get_Type()->get_type_refd_last(); - if (t->get_typetype() == Type::T_PORT) { - provider_type = t; - provider_body = t->get_PortBody(); + size_t n_prov_t = 0; + for (size_t p = 0; p < provider_refs.size(); p++) { + provider_body = 0; + Assignment *t_ass = provider_refs[p]->get_refd_assignment(); // provider port + if (t_ass) { + if (t_ass->get_asstype() == Assignment::A_TYPE) { + Type *t = t_ass->get_Type()->get_type_refd_last(); + if (t->get_typetype() == Type::T_PORT) { + provider_types.add(t); + n_prov_t++; + provider_body = t->get_PortBody(); + } else { + provider_refs[p]->error("Type reference `%s' does not refer to a port " + "type", provider_refs[p]->get_dispname().c_str()); + } } else { - provider_ref->error("Type reference `%s' does not refer to a port " - "type", provider_ref->get_dispname().c_str()); + provider_refs[p]->error("Reference `%s' does not refer to a type", + provider_refs[p]->get_dispname().c_str()); } - } else { - provider_ref->error("Reference `%s' does not refer to a type", - provider_ref->get_dispname().c_str()); } - } - // checking the consistency of attributes in this and provider_body - if (provider_body && testport_type != TP_INTERNAL) { - if (provider_body->port_type != PT_PROVIDER) { - provider_ref->error("The referenced port type `%s' must have the " - "`provider' attribute", provider_type->get_typename().c_str()); - } - switch (provider_body->testport_type) { - case TP_REGULAR: - if (testport_type == TP_ADDRESS) { - provider_ref->error("Attribute `address' cannot be used because the " - "provider port type `%s' does not have attribute `address'", - provider_type->get_typename().c_str()); + // checking the consistency of attributes in this and provider_body + if (provider_body && testport_type != TP_INTERNAL) { + if (provider_body->port_type != PT_PROVIDER) { + provider_refs[p]->error("The referenced port type `%s' must have the " + "`provider' attribute", provider_types[n_prov_t-1]->get_typename().c_str()); } - break; - case TP_INTERNAL: - provider_ref->error("Missing attribute `internal'. Provider port " - "type `%s' has attribute `internal', which must be also present here", - provider_type->get_typename().c_str()); - case TP_ADDRESS: - break; - default: - FATAL_ERROR("PortTypeBody::chk_attributes()"); + switch (provider_body->testport_type) { + case TP_REGULAR: + if (testport_type == TP_ADDRESS) { + provider_refs[p]->error("Attribute `address' cannot be used because the " + "provider port type `%s' does not have attribute `address'", + provider_types[n_prov_t-1]->get_typename().c_str()); + } + break; + case TP_INTERNAL: + provider_refs[p]->error("Missing attribute `internal'. Provider port " + "type `%s' has attribute `internal', which must be also present here", + provider_types[n_prov_t-1]->get_typename().c_str()); + case TP_ADDRESS: + break; + default: + FATAL_ERROR("PortTypeBody::chk_attributes()"); + } + // inherit the test port API type from the provider + testport_type = provider_body->testport_type; } - // inherit the test port API type from the provider - testport_type = provider_body->testport_type; - } - + } // for + // checking the incoming mappings - if (in_mappings) { + if (legacy && in_mappings) { Error_Context cntxt2(in_mappings, "In `in' mappings"); - in_mappings->chk(); + in_mappings->chk(legacy, true); // checking source types if (provider_body) { if (provider_body->in_msgs) { @@ -1316,7 +1529,7 @@ namespace Ttcn { source_type->error("Source type `%s' of the `in' mapping is not " "present on the list of incoming messages in provider port " "type `%s'", source_type->get_typename().c_str(), - provider_type->get_typename().c_str()); + provider_types[0]->get_typename().c_str()); } } // check if all types of the `in' list of the provider are handled by @@ -1328,13 +1541,13 @@ namespace Ttcn { in_mappings->error("Incoming message type `%s' of provider " "port type `%s' is not handled by the incoming mappings", msg_type->get_typename().c_str(), - provider_type->get_typename().c_str()); + provider_types[0]->get_typename().c_str()); } } } else { in_mappings->error("Invalid incoming mappings. Provider port type " "`%s' does not have incoming message types", - provider_type->get_typename().c_str()); + provider_types[0]->get_typename().c_str()); } } // checking target types @@ -1353,15 +1566,15 @@ namespace Ttcn { } } } - } else if (provider_body && provider_body->in_msgs) { + } else if (legacy && provider_body && provider_body->in_msgs) { error("Missing `in' mappings to handle the incoming message types of " - "provider port type `%s'", provider_type->get_typename().c_str()); + "provider port type `%s'", provider_types[0]->get_typename().c_str()); } // checking the outgoing mappings - if (out_mappings) { + if (legacy && out_mappings) { Error_Context cntxt2(out_mappings, "In `out' mappings"); - out_mappings->chk(); + out_mappings->chk(legacy, false); // checking source types if (out_msgs) { // check if all source types are present on the `out' list @@ -1406,18 +1619,18 @@ namespace Ttcn { target_type->error("Target type `%s' of the `out' mapping is " "not present on the list of outgoing messages in provider " "port type `%s'", target_type->get_typename().c_str(), - provider_type->get_typename().c_str()); + provider_types[0]->get_typename().c_str()); } } } } - } else if (out_msgs) { + } else if (legacy && out_msgs) { error("Missing `out' mappings to handle the outgoing message types of " "user port type `%s'", my_type->get_typename().c_str()); } // checking the compatibility of signature lists - if (provider_body) { + if (legacy && provider_body) { if (in_sigs) { size_t nof_sigs = in_sigs->get_nof_types(); for (size_t i = 0; i < nof_sigs; i++) { @@ -1431,7 +1644,7 @@ namespace Ttcn { "not present on the list of incoming signatures in provider " "port type `%s'", t_sig->get_typename().c_str(), my_type->get_typename().c_str(), - provider_type->get_typename().c_str()); + provider_types[0]->get_typename().c_str()); } } } @@ -1444,7 +1657,7 @@ namespace Ttcn { error("Incoming signature `%s' of provider port type `%s' is not " "present on the list of incoming signatures in user port type " "`%s'", t_sig->get_typename().c_str(), - provider_type->get_typename().c_str(), + provider_types[0]->get_typename().c_str(), my_type->get_typename().c_str()); } } @@ -1460,7 +1673,7 @@ namespace Ttcn { "not present on the list of outgoing signatures in provider port " "type `%s'", t_sig->get_typename().c_str(), my_type->get_typename().c_str(), - provider_type->get_typename().c_str()); + provider_types[0]->get_typename().c_str()); } } } @@ -1476,12 +1689,21 @@ namespace Ttcn { error("Outgoing signature `%s' of provider port type `%s' is not " "present on the list of outgoing signatures in user port type " "`%s'", t_sig->get_typename().c_str(), - provider_type->get_typename().c_str(), + provider_types[0]->get_typename().c_str(), my_type->get_typename().c_str()); } } } } + if (!legacy) { + if (out_mappings) { + out_mappings->chk(legacy, false); + } + if (in_mappings) { + in_mappings->chk(legacy, true); + } + chk_map_translation(); + } } void PortTypeBody::chk() @@ -1584,7 +1806,7 @@ namespace Ttcn { add_provider_attribute(); break; - case ExtensionAttribute::PORT_TYPE_USER: + case ExtensionAttribute::PORT_TYPE_USER: { switch (port_type) { case PortTypeBody::PT_REGULAR: break; @@ -1602,8 +1824,11 @@ namespace Ttcn { TypeMappings *in; TypeMappings *out; ea.get_user(ref, in, out); - add_user_attribute(ref, in, out); - break; + Reference **refs = (Reference**)Malloc(sizeof(Reference*)); + refs[0] = ref; + add_user_attribute(refs, 1, in, out); + Free(refs); + break; } case ExtensionAttribute::ANYTYPELIST: break; // ignore it @@ -1793,6 +2018,7 @@ namespace Ttcn { stringpool pool; port_def pdef; memset(&pdef, 0, sizeof(pdef)); + pdef.legacy = legacy; const string& t_genname = my_type->get_genname_own(); pdef.name = t_genname.c_str(); pdef.dispname = my_type->get_fullname().c_str(); @@ -1832,16 +2058,26 @@ namespace Ttcn { port_msg_mapped_type *mapped_type = pdef.msg_out.elements + i; mapped_type->name = pool.add(type->get_genname_value(my_scope)); mapped_type->dispname = pool.add(type->get_typename()); - if (port_type == PT_USER) { + // When legacy behaviour is used and out_mappings is null then error later + if (port_type == PT_USER && (legacy || out_mappings)) { if (!out_mappings) FATAL_ERROR("PortTypeBody::generate_code()"); - TypeMapping *mapping = out_mappings->get_mapping_byType(type); - mapped_type->nTargets = mapping->get_nof_targets(); - mapped_type->targets = (port_msg_type_mapping_target*) - Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets)); - for (size_t j = 0; j < mapped_type->nTargets; j++) { - mapping->get_target_byIndex(j)->fill_type_mapping_target( - mapped_type->targets + j, type, my_scope, pool); - mapped_type->targets[j].target_index = static_cast<size_t>(-1); + if (legacy || out_mappings->has_mapping_for_type(type)) { + TypeMapping *mapping = out_mappings->get_mapping_byType(type); + mapped_type->nTargets = mapping->get_nof_targets(); + mapped_type->targets = (port_msg_type_mapping_target*) + Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets)); + for (size_t j = 0; j < mapped_type->nTargets; j++) { + mapping->get_target_byIndex(j)->fill_type_mapping_target( + mapped_type->targets + j, type, my_scope, pool); + mapped_type->targets[j].target_index = static_cast<size_t>(-1); + } + } else if (!legacy) { + mapped_type->nTargets = 1; + mapped_type->targets = (port_msg_type_mapping_target*) + Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets)); + mapped_type->targets[0].target_name = pool.add(type->get_genname_value(my_scope)); + mapped_type->targets[0].target_dispname = pool.add(type->get_typename()); + mapped_type->targets[0].mapping_type = M_SIMPLE; } } else { mapped_type->nTargets = 0; @@ -1911,46 +2147,128 @@ namespace Ttcn { if (port_type == PT_USER) { pdef.port_type = USER; - if (!provider_type) FATAL_ERROR("PortTypeBody::generate_code()"); - pdef.provider_name = - pool.add(provider_type->get_genname_value(my_scope)); - PortTypeBody *provider_body = provider_type->get_PortBody(); - if (provider_body->in_msgs) { - if (!in_mappings) // !this->in_msgs OK for an all-discard mapping - FATAL_ERROR("PortTypeBody::generate_code()"); - pdef.provider_msg_in.nElements = - provider_body->in_msgs->get_nof_types(); - pdef.provider_msg_in.elements = (port_msg_mapped_type*) - Malloc(pdef.provider_msg_in.nElements * - sizeof(*pdef.provider_msg_in.elements)); - for (size_t i = 0; i < pdef.provider_msg_in.nElements; i++) { - Type *type = provider_body->in_msgs->get_type_byIndex(i); - port_msg_mapped_type *mapped_type = pdef.provider_msg_in.elements + i; - mapped_type->name = pool.add(type->get_genname_value(my_scope)); - mapped_type->dispname = pool.add(type->get_typename()); - TypeMapping *mapping = in_mappings->get_mapping_byType(type); - mapped_type->nTargets = mapping->get_nof_targets(); - mapped_type->targets = (port_msg_type_mapping_target*) - Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets)); - for (size_t j = 0; j < mapped_type->nTargets; j++) { - TypeMappingTarget *t_target = mapping->get_target_byIndex(j); - pdef.has_sliding |= t_target->fill_type_mapping_target( - mapped_type->targets + j, type, my_scope, pool); - Type *target_type = t_target->get_target_type(); - if (target_type) { - if (!in_msgs) FATAL_ERROR("PortTypeBody::generate_code()"); - mapped_type->targets[j].target_index = - in_msgs->get_index_byType(target_type); - } else { - // the message will be discarded: fill in a dummy index - mapped_type->targets[j].target_index = static_cast<size_t>(-1); + if (provider_types.size() == 0) FATAL_ERROR("PortTypeBody::generate_code()"); + if (legacy) { + pdef.provider_name = + pool.add(provider_types[0]->get_genname_value(my_scope)); + PortTypeBody *provider_body = provider_types[0]->get_PortBody(); + if (provider_body->in_msgs) { + if (!in_mappings) // !this->in_msgs OK for an all-discard mapping + FATAL_ERROR("PortTypeBody::generate_code()"); + pdef.provider_msg_in.nElements = + provider_body->in_msgs->get_nof_types(); + pdef.provider_msg_in.elements = (port_msg_mapped_type*) + Malloc(pdef.provider_msg_in.nElements * + sizeof(*pdef.provider_msg_in.elements)); + for (size_t i = 0; i < pdef.provider_msg_in.nElements; i++) { + Type *type = provider_body->in_msgs->get_type_byIndex(i); + port_msg_mapped_type *mapped_type = pdef.provider_msg_in.elements + i; + mapped_type->name = pool.add(type->get_genname_value(my_scope)); + mapped_type->dispname = pool.add(type->get_typename()); + TypeMapping *mapping = in_mappings->get_mapping_byType(type); + mapped_type->nTargets = mapping->get_nof_targets(); + mapped_type->targets = (port_msg_type_mapping_target*) + Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets)); + for (size_t j = 0; j < mapped_type->nTargets; j++) { + TypeMappingTarget *t_target = mapping->get_target_byIndex(j); + pdef.has_sliding |= t_target->fill_type_mapping_target( + mapped_type->targets + j, type, my_scope, pool); + Type *target_type = t_target->get_target_type(); + if (target_type) { + if (!in_msgs) FATAL_ERROR("PortTypeBody::generate_code()"); + if (in_msgs->has_type(target_type)) { + mapped_type->targets[j].target_index = + in_msgs->get_index_byType(target_type); + } else { + mapped_type->targets[j].target_index = static_cast<size_t>(-1); + } + } else { + // the message will be discarded: fill in a dummy index + mapped_type->targets[j].target_index = static_cast<size_t>(-1); + } } } + } else { + pdef.provider_msg_in.nElements = 0; + pdef.provider_msg_in.elements = NULL; } - } else { + } else { // non-legacy standard like behaviour + pdef.provider_name = 0; // For non legacy generation it is not needed pdef.provider_msg_in.nElements = 0; pdef.provider_msg_in.elements = NULL; - } + if (in_msgs) { + // First we insert the in messages with simple conversion (no conversion) + // into a set called pdef.provider_msg_in.elements + for (size_t i = 0; i < in_msgs->get_nof_types(); i++) { + Type* type = in_msgs->get_type_byIndex(i); + pdef.provider_msg_in.nElements++; + pdef.provider_msg_in.elements = (port_msg_mapped_type*)Realloc(pdef.provider_msg_in.elements, pdef.provider_msg_in.nElements * sizeof(*pdef.provider_msg_in.elements)); + port_msg_mapped_type* mapped_type = pdef.provider_msg_in.elements + (pdef.provider_msg_in.nElements - 1); + mapped_type->name = pool.add(type->get_genname_value(my_scope)); + mapped_type->dispname = pool.add(type->get_typename()); + mapped_type->nTargets = 1; + mapped_type->targets = (port_msg_type_mapping_target*) + Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets)); + mapped_type->targets[0].target_name = pool.add(type->get_genname_value(my_scope)); + mapped_type->targets[0].target_dispname = pool.add(type->get_typename()); + mapped_type->targets[0].mapping_type = M_SIMPLE; + mapped_type->targets[0].target_index = + in_msgs->get_index_byType(type); + } // for in_msgs->get_nof_types() + } // if in_msgs + + if (in_mappings) { + // Secondly we insert the mappings into the pdef. + // We collect the mapping sources for each distinct mapping targets. + // Kind of reverse what we did in the legacy behaviour. + for (size_t j = 0; j < in_mappings->get_nof_mappings(); j++) { + TypeMapping* mapping = in_mappings->get_mapping_byIndex(j); + for (size_t u = 0; u < mapping->get_nof_targets(); u++) { + TypeMappingTarget* mapping_target = mapping->get_target_byIndex(u); + + port_msg_mapped_type *mapped_type = NULL; + // Do not insert the same mapped_type. The key is the dispname. + for (size_t k = 0; k < pdef.provider_msg_in.nElements; k++) { + if (pdef.provider_msg_in.elements[k].dispname == mapping_target->get_target_type()->get_typename()) { + mapped_type = pdef.provider_msg_in.elements + k; + break; + } + } + + // Mapping target not found. Create new port_msg_mapped_type + if (mapped_type == NULL) { + pdef.provider_msg_in.nElements++; + pdef.provider_msg_in.elements = (port_msg_mapped_type*)Realloc(pdef.provider_msg_in.elements, pdef.provider_msg_in.nElements * sizeof(*pdef.provider_msg_in.elements)); + mapped_type = pdef.provider_msg_in.elements + (pdef.provider_msg_in.nElements - 1); + mapped_type->name = pool.add(mapping_target->get_target_type()->get_genname_value(my_scope)); + mapped_type->dispname = pool.add(mapping_target->get_target_type()->get_typename()); + mapped_type->nTargets = 0; + mapped_type->targets = NULL; + } + + // Insert the mapping source as the mapped target's target. + mapped_type->nTargets++; + mapped_type->targets = (port_msg_type_mapping_target*) + Realloc(mapped_type->targets, mapped_type->nTargets * sizeof(*mapped_type->targets)); + size_t ind = mapped_type->nTargets - 1; + + mapped_type->targets[ind].mapping_type = M_FUNCTION; + mapped_type->targets[ind].mapping.function.prototype = PT_FAST; + mapped_type->targets[ind].mapping.function.name = mapping_target->get_function()->get_genname_from_scope(my_scope).c_str(); + + mapped_type->targets[ind].target_name = pool.add(mapping->get_source_type()->get_genname_value(my_scope)); + mapped_type->targets[ind].target_dispname = pool.add(mapping->get_source_type()->get_typename()); + + if (in_msgs->has_type(mapping->get_source_type())) { + mapped_type->targets[ind].target_index = + in_msgs->get_index_byType(mapping->get_source_type()); + } else { + FATAL_ERROR("PortTypeBody::generate_code()"); + } + } // for mapping->get_nof_targets() + } // for in_mappings->get_nof_mappings() + } // if in_mappings // todo inout? + } // if legacy } else { // "internal provider" is the same as "internal" if (port_type == PT_PROVIDER && testport_type != TP_INTERNAL) @@ -1963,7 +2281,7 @@ namespace Ttcn { defPortClass(&pdef, target); if (generate_skeleton && testport_type != TP_INTERNAL && - port_type != PT_USER) generateTestPortSkeleton(&pdef); + (port_type != PT_USER || !legacy)) generateTestPortSkeleton(&pdef); Free(pdef.msg_in.elements); for (size_t i = 0; i < pdef.msg_out.nElements; i++) @@ -2046,8 +2364,10 @@ namespace Ttcn { default: DEBUG(level, "attribute: <unknown>"); } - if (provider_ref) - DEBUG(level, "provider type: %s", provider_ref->get_dispname().c_str()); + if (provider_refs.size() > 0) + for (size_t i = 0; i < provider_refs.size(); i++) { + DEBUG(level, "provider type %i: %s", (int)i, provider_refs[i]->get_dispname().c_str()); + } if (in_mappings) { DEBUG(level, "in mappings:"); in_mappings->dump(level + 1); diff --git a/compiler2/ttcn3/Ttcnstuff.hh b/compiler2/ttcn3/Ttcnstuff.hh index 639db5ad18f479b1f9c4bd5964d182fdb427c194..dab0d4cdec528b81c3d8709e48d3b2d237c66e4e 100644 --- a/compiler2/ttcn3/Ttcnstuff.hh +++ b/compiler2/ttcn3/Ttcnstuff.hh @@ -11,6 +11,7 @@ * Delic, Adam * Raduly, Csaba * Szabados, Kristof + * Szabo, Bence Janos * Zalanyi, Balazs Andor * ******************************************************************************/ @@ -174,14 +175,22 @@ private: /** Check function mapping. * The function must have "prototype()", the function's input parameter * must match the source_type and its return type must match the target_type - * of this mapping. */ - void chk_function(Common::Type *source_type); + * of this mapping. + * Param legacy: true if the old user attribute was used or false when the + * syntax in the standard was used. + Param incoming: true if the mapping is in the in list of port, false if the + * mapping is in the out list of the port.*/ + void chk_function(Common::Type *source_type, bool legacy, bool incoming); /** Check "encode()" mapping. */ void chk_encode(Common::Type *source_type); /** Check "decode()" mapping. */ void chk_decode(Common::Type *source_type); public: - void chk(Common::Type *source_type); + /* Param legacy: true if the old user attribute was used or false when the + * syntax in the standard was used. + Param incoming: true if the mapping is in the in list of port, false if the + * mapping is in the out list of the port.*/ + void chk(Common::Type *source_type, bool legacy, bool incoming); /** Fills the appropriate data structure \a target for code generation. */ bool fill_type_mapping_target(port_msg_type_mapping_target *target, Common::Type *source_type, Common::Scope *p_scope, stringpool& pool); @@ -236,7 +245,11 @@ public: size_t get_nof_targets() const { return targets->get_nof_targets(); } TypeMappingTarget *get_target_byIndex(size_t n) const { return targets->get_target_byIndex(n); } - void chk(); + /* Param legacy: true if the old user attribute was used or false when the + * syntax in the standard was used. + Param incoming: true if the mapping is in the in list of port, false if the + * mapping is in the out list of the port.*/ + void chk(bool legacy, bool incoming); virtual void dump(unsigned level) const; }; @@ -261,7 +274,11 @@ public: TypeMapping *get_mapping_byIndex(size_t n) const { return mappings_v[n]; } bool has_mapping_for_type(Common::Type *p_type) const; TypeMapping *get_mapping_byType(Common::Type *p_type) const; - void chk(); + /* Param legacy: true if the old user attribute was used or false when the + * syntax in the standard was used. + Param incoming: true if the mapping is in the in list of port, false if the + * mapping is in the out list of the port.*/ + void chk(bool legacy, bool incoming); virtual void dump(unsigned level) const; }; @@ -373,6 +390,7 @@ private: Types *in_list, *out_list, *inout_list; bool in_all, out_all, inout_all; // whether "(in|out|inout) all" was used bool checked; + bool legacy; // Old extension syntax or new standard syntax /* Types and signatures that can be sent and received. * These are initially empty; filled by PortTypeBody::chk_list based on * in_list, out_list, inout_list. @@ -381,8 +399,8 @@ private: TypeSet *in_msgs, *out_msgs, *in_sigs, *out_sigs; TestPortAPI_t testport_type; // regular|internal|address PortType_t port_type; // regular|provider|user - Ttcn::Reference *provider_ref; ///< reference to provider port, for PT_USER - Common::Type *provider_type; ///< the type that provider_ref refers to + vector<Ttcn::Reference>provider_refs; ///< references to provider ports, for PT_USER + vector<Common::Type> provider_types; ///< the types that provider_refs refers to TypeMappings *in_mappings, *out_mappings; ///< mappings for PT_USER /** Copy constructor not implemented */ PortTypeBody(const PortTypeBody& p); @@ -415,14 +433,16 @@ public: { testport_type = p_testport_type; } PortType_t get_type() const { return port_type; } void add_provider_attribute(); - void add_user_attribute(Ttcn::Reference *p_provider_ref, - TypeMappings *p_in_mappings, TypeMappings *p_out_mappings); + void add_user_attribute(Ttcn::Reference **p_provider_refs, size_t n_provider_refs, + TypeMappings *p_in_mappings, TypeMappings *p_out_mappings, bool p_legacy = true); Common::Type *get_provider_type() const; private: void chk_list(const Types *list, bool is_in, bool is_out); void chk_user_attribute(); public: void chk(); + void chk_map_translation(); + void chk_connect_translation(); void chk_attributes(Ttcn::WithAttribPath *w_attrib_path); /** Returns whether the outgoing messages and signatures of \a this are * on the incoming lists of \a p_other. */ diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y index fae8af54b724656649bd62c2f66a1902824b8300..5b096d7457cc92b47158cb1608eb0fc6be6d731d 100644 --- a/compiler2/ttcn3/compiler.y +++ b/compiler2/ttcn3/compiler.y @@ -216,6 +216,7 @@ static const string anyname("anytype"); ValueRedirect* value_redirect; SingleValueRedirect* single_value_redirect; param_eval_t eval; + TypeMappingTargets *typemappingtargets; struct { bool is_raw; @@ -283,7 +284,13 @@ static const string anyname("anytype"); struct { Ttcn::Types *in_list, *out_list, *inout_list; bool in_all, out_all, inout_all; + TypeMappings *in_mappings, *out_mappings; } portdefbody; + + struct { + Types * types; + TypeMappings *mappings; + } types_with_mapping; struct { Ttcn::Reference *ref; @@ -569,6 +576,11 @@ static const string anyname("anytype"); Ttcn::Reference* reference; bool any_from; } reference_or_any; + + struct { + size_t nElements; + Ttcn::Reference** elements; + } reference_list; } /* Tokens of TTCN-3 */ @@ -1013,7 +1025,8 @@ static const string anyname("anytype"); NestedSetOfDef NestedTypeDef NestedUnionDef PortDefAttribs ReferencedType Type TypeOrNestedTypeDef NestedFunctionTypeDef NestedAltstepTypeDef NestedTestcaseTypeDef -%type <types> TypeList AllOrTypeList +%type <types_with_mapping> TypeList AllOrTypeList AllOrTypeListWithFrom +AllOrTypeListWithTo TypeListWithFrom TypeListWithTo %type <value> AddressValue AliveOp AllPortsSpec AltGuardChar ArrayBounds ArrayExpression ArrayExpressionList BitStringValue BooleanExpression BooleanValue CharStringValue ComponentRef ComponentReferenceOrLiteral @@ -1098,6 +1111,8 @@ static const string anyname("anytype"); %type <value_redirect> ValueSpec %type <single_value_redirect> SingleValueSpec %type <single_value_redirect_list> SingleValueSpecList +%type <typemappingtargets> WithList +%type <reference_list> PortTypeList /********************************************************************* * Destructors @@ -1123,11 +1138,21 @@ PatternChunkList } ActivateOp +%destructor { + delete $$.types; + delete $$.mappings; +} +AllOrTypeList +AllOrTypeListWithFrom +AllOrTypeListWithTo +TypeList +TypeListWithFrom +TypeListWithTo + %destructor {delete $$;} AddressRef AddressValue AliveOp -AllOrTypeList AllPortsSpec AltConstruct AltGuard @@ -1375,7 +1400,6 @@ TriggerStatement Type TypeDef TypeDefBody -TypeList TypeOrNestedTypeDef UnionDef UnionFieldDef @@ -1401,6 +1425,7 @@ VerdictStatements VerdictValue WhileStatement WithAttribList +WithList WithStatement optAltstepFormalParList optAttribQualifier @@ -1473,6 +1498,7 @@ optExtendedFieldReference FriendModuleDef USI UIDlike +PortTypeList %destructor { @@ -1504,6 +1530,8 @@ StructOfDefBody delete $$.in_list; delete $$.out_list; delete $$.inout_list; + delete $$.in_mappings; + delete $$.out_mappings; } PortDefList PortDefLists @@ -1837,7 +1865,7 @@ optDecodedModifier %left '*' '/' ModKeyword RemKeyword %left UnarySign -%expect 57 +%expect 59 %start GrammarRoot @@ -1897,6 +1925,7 @@ with "->" (reduce). TODO: Find out what the index redirect conflicts with. It's probably something that would cause a semantic error anyway, but it would be good to know. +9.) 2 conflicts in the rule TypeListWithTo. Note that the parser implemented by bison always chooses to shift instead of reduce in case of conflicts. @@ -2729,6 +2758,22 @@ PortType: // 55 } ; +PortTypeList: + PortType + { + $$.nElements = 1; + $$.elements = (Ttcn::Reference**)Malloc(sizeof(*$$.elements)); + $$.elements[0] = $1; + } +| PortTypeList ',' optError PortType + { + $$.nElements = $1.nElements + 1; + $$.elements = (Ttcn::Reference**) + Realloc($1.elements, $$.nElements * sizeof(*$$.elements)); + $$.elements[$$.nElements - 1] = $4; + } +; + PortDef: // 56 PortKeyword PortDefBody { $$ = $2; } ; @@ -2749,6 +2794,20 @@ PortDefAttribs: // 60 body->set_location(infile, @$); $$ = new Type(Type::T_PORT, body); $$->set_location(infile, @$); + delete $2.in_mappings; + delete $2.out_mappings; + } +| + PortOperationMode MapKeyword ToKeyword PortTypeList PortDefLists + { + PortTypeBody *body = new PortTypeBody($1, + $5.in_list, $5.out_list, $5.inout_list, + $5.in_all, $5.out_all, $5.inout_all); + body->set_location(infile, @$); + $$ = new Type(Type::T_PORT, body); + body->add_user_attribute($4.elements, $4.nElements, $5.in_mappings, $5.out_mappings, false); + delete $4.elements; + $$->set_location(infile, @$); } ; @@ -2769,6 +2828,8 @@ PortDefLists: $$.in_all = false; $$.out_all = false; $$.inout_all = false; + $$.in_mappings = 0; + $$.out_mappings = 0; } ; @@ -2779,71 +2840,101 @@ seqPortDefList: $$ = $1; if ($2.in_list) { if ($$.in_list) { - $$.in_list->steal_types($2.in_list); - delete $2.in_list; + $$.in_list->steal_types($2.in_list); + delete $2.in_list; } else $$.in_list = $2.in_list; } + if ($2.in_mappings) { + if ($$.in_mappings) { + $$.in_mappings->steal_mappings($2.in_mappings); + delete $2.in_mappings; + } else { + $$.in_mappings = $2.in_mappings; + } + } if ($2.out_list) { if ($$.out_list) { - $$.out_list->steal_types($2.out_list); - delete $2.out_list; + $$.out_list->steal_types($2.out_list); + delete $2.out_list; } else $$.out_list = $2.out_list; } + if ($2.out_mappings) { + if ($$.out_mappings) { + $$.out_mappings->steal_mappings($2.out_mappings); + delete $2.out_mappings; + } else { + $$.out_mappings = $2.out_mappings; + } + } if ($2.inout_list) { if ($$.inout_list) { - $$.inout_list->steal_types($2.inout_list); - delete $2.inout_list; + $$.inout_list->steal_types($2.inout_list); + delete $2.inout_list; } else $$.inout_list = $2.inout_list; } if ($2.in_all) { if ($$.in_all) { - Location loc(infile, @2); - loc.warning("Duplicate directive `in all' in port type definition"); + Location loc(infile, @2); + loc.warning("Duplicate directive `in all' in port type definition"); } else $$.in_all = true; } if ($2.out_all) { if ($$.out_all) { - Location loc(infile, @2); - loc.warning("Duplicate directive `out all' in port type definition"); + Location loc(infile, @2); + loc.warning("Duplicate directive `out all' in port type definition"); } else $$.out_all = true; } if ($2.inout_all) { if ($$.inout_all) { - Location loc(infile, @2); - loc.warning("Duplicate directive `inout all' in port type definition"); + Location loc(infile, @2); + loc.warning("Duplicate directive `inout all' in port type definition"); } else $$.inout_all = true; } } ; PortDefList: - InParKeyword AllOrTypeList + InParKeyword AllOrTypeListWithFrom { - if ($2) { - $$.in_list = $2; + if ($2.types) { + $$.in_list = $2.types; $$.in_list->set_location(infile, @$); $$.in_all = false; + if ($2.mappings) { + $$.in_mappings = $2.mappings; + } else { + $$.in_mappings = 0; + } } else { $$.in_list = 0; $$.in_all = true; + $$.in_mappings = 0; } $$.out_list = 0; $$.out_all = false; $$.inout_list = 0; + $$.out_mappings = 0; $$.inout_all = false; } -| OutParKeyword AllOrTypeList +| OutParKeyword AllOrTypeListWithTo { - $$.in_list = 0; - $$.in_all = false; - if ($2) { - $$.out_list = $2; + if ($2.types) { + $$.out_list = $2.types; $$.out_list->set_location(infile, @$); $$.out_all = false; + if ($2.mappings) { + $$.out_mappings = $2.mappings; + } else { + $$.out_mappings = 0; + } } else { $$.out_list = 0; $$.out_all = true; + $$.out_mappings = 0; } + $$.in_list = 0; + $$.in_all = false; + $$.in_mappings = 0; $$.inout_list = 0; $$.inout_all = false; } @@ -2853,14 +2944,17 @@ PortDefList: $$.in_all = false; $$.out_list = 0; $$.out_all = false; - if ($2) { - $$.inout_list = $2; + if ($2.types) { + $$.inout_list = $2.types; $$.inout_list->set_location(infile, @$); $$.inout_all = false; } else { $$.inout_list = 0; $$.inout_all = true; } + delete $2.mappings; + $$.in_mappings = 0; + $$.out_mappings = 0; } | InParKeyword error { @@ -2870,6 +2964,8 @@ PortDefList: $$.in_all = false; $$.out_all = false; $$.inout_all = false; + $$.in_mappings = 0; + $$.out_mappings = 0; } | OutParKeyword error { @@ -2879,6 +2975,8 @@ PortDefList: $$.in_all = false; $$.out_all = false; $$.inout_all = false; + $$.in_mappings = 0; + $$.out_mappings = 0; } | InOutParKeyword error { @@ -2888,28 +2986,114 @@ PortDefList: $$.in_all = false; $$.out_all = false; $$.inout_all = false; + $$.in_mappings = 0; + $$.out_mappings = 0; + } +; + +WithList: + Type WithKeyword FunctionRef '(' optError ')' + { + $$ = new TypeMappingTargets(); + Ttcn::Reference *func_ref = new Ttcn::Reference($3.modid, $3.id); + TypeMappingTarget * tm = new TypeMappingTarget($1, TypeMappingTarget::TM_FUNCTION, func_ref); + $$->add_target(tm); + } +| WithList ':' optError Type WithKeyword FunctionRef '(' optError ')' + { + Ttcn::Reference *func_ref = new Ttcn::Reference($6.modid, $6.id); + TypeMappingTarget * tm = new TypeMappingTarget($4, TypeMappingTarget::TM_FUNCTION, func_ref); + $$ = $1; + $$->add_target(tm); } ; AllOrTypeList: // 65 - AllKeyword { $$ = 0; } + AllKeyword { $$.types = 0; $$.mappings = 0; } | TypeList { $$ = $1; } ; TypeList: // 67 optError Type { - $$ = new Types; - $$->add_type($2); + $$.types = new Types; + $$.types->add_type($2); + $$.mappings = new TypeMappings(); } | TypeList optError ',' optError Type { $$ = $1; - $$->add_type($5); + $$.types->add_type($5); } | TypeList optError ',' error { $$ = $1; } ; +AllOrTypeListWithFrom: + AllKeyword { $$.types = 0; $$.mappings = 0; } +| TypeListWithFrom { $$ = $1; } +; + +TypeListWithFrom: + optError Type + { + $$.types = new Types; + $$.types->add_type($2); + $$.mappings = new TypeMappings(); + } +| optError Type optError FromKeyword WithList + { + $$.types = new Types; + $$.types->add_type($2); + $$.mappings = new TypeMappings(); + $$.mappings->add_mapping(new TypeMapping($2->clone(), $5)); + } +| TypeListWithFrom optError ',' optError Type + { + $$ = $1; + $$.types->add_type($5); + } +| TypeListWithFrom optError ',' optError Type FromKeyword WithList + { + $$ = $1; + $$.types->add_type($5); + $$.mappings->add_mapping(new TypeMapping($5->clone(), $7)); + } +| TypeListWithFrom optError ',' error { $$ = $1; } +; + +AllOrTypeListWithTo: + AllKeyword { $$.types = 0; $$.mappings = 0; } +| TypeListWithTo { $$ = $1; } +; + +TypeListWithTo: + optError Type + { + $$.types = new Types; + $$.types->add_type($2); + $$.mappings = new TypeMappings(); + } +| optError Type optError ToKeyword WithList + { + $$.types = new Types; + $$.types->add_type($2); + $$.mappings = new TypeMappings(); + $$.mappings->add_mapping(new TypeMapping($2->clone(), $5)); + } +| TypeListWithTo optError ',' optError Type + { + $$ = $1; + $$.types->add_type($5); + } +| TypeListWithTo optError ',' optError Type ToKeyword WithList + { + $$ = $1; + $$.types->add_type($5); + $$.mappings->add_mapping(new TypeMapping($5->clone(), $7)); + } +| TypeListWithTo optError ',' error { $$ = $1; } +; + ComponentDef: // 78 ComponentKeyword IDentifier optExtendsDef diff --git a/compiler2/ttcn3/port.c b/compiler2/ttcn3/port.c index 98ff96c9da4bb7529fec7fd374137d30f4de6acd..2391790b7eed5e704a836dde45f6e2e16c3a58b5 100644 --- a/compiler2/ttcn3/port.c +++ b/compiler2/ttcn3/port.c @@ -85,6 +85,9 @@ static char *generate_send_mapping(char *src, const port_def *pdef, src = mputprintf(src, "%s mapped_par;\n" "%s(send_par, mapped_par);\n", target->target_name, target->mapping.function.name); + if (!pdef->legacy) { + has_condition = TRUE; + } break; case PT_SLIDING: /* Yes, it is possible to use a "prototype(sliding)" decoder @@ -146,6 +149,9 @@ static char *generate_send_mapping(char *src, const port_def *pdef, default: FATAL_ERROR("generate_send_mapping(): invalid mapping type"); } + if (!pdef->legacy) { + src = mputstr(src, "if (mapped_par.is_bound()) {\n"); // temporary solution instead of setstate + } src = mputprintf(src, "if (TTCN_Logger::log_this_event(" "TTCN_Logger::PORTEVENT_DUALSEND)) {\n" "TTCN_Logger::log_dualport_map(0, \"%s\",\n" @@ -169,10 +175,15 @@ static char *generate_send_mapping(char *src, const port_def *pdef, if (pdef->testport_type != INTERNAL) src = mputstr(src, "}\n"); } if (has_condition) { - src = mputstr(src, "return;\n" - "}\n"); + src = mputstr(src, "return;\n"); + if (pdef->legacy) { + src = mputstr(src, "}\n"); + } report_error = TRUE; } + if (!pdef->legacy) { + src = mputstr(src, "}\n"); + } if (mapped_type->nTargets > 1) src = mputstr(src, "}\n"); } if (has_discard) { @@ -196,11 +207,13 @@ static char *generate_send_mapping(char *src, const port_def *pdef, } static char *generate_incoming_mapping(char *src, const port_def *pdef, - const port_msg_mapped_type *mapped_type) + const port_msg_mapped_type *mapped_type, boolean has_simple) { - size_t i; + // If has simple is true, then always the first one is the simple mapping, + // and the first mapping is taken care elsewhere + size_t i = has_simple ? 1 : 0; boolean has_buffer = FALSE, has_discard = FALSE, report_error = FALSE; - for (i = 0; i < mapped_type->nTargets; i++) { + for (; i < mapped_type->nTargets; i++) { const port_msg_type_mapping_target *target = mapped_type->targets + i; boolean has_condition = FALSE; @@ -237,6 +250,9 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, "throw;\n" "}\n", target->target_name, target->target_name, target->mapping.function.name); + if (!pdef->legacy) { + has_condition = TRUE; + } break; case PT_SLIDING: src = mputprintf(src, @@ -319,6 +335,7 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, FATAL_ERROR("generate_incoming_mapping(): invalid mapping type"); } src = mputprintf(src, "msg_tail_count++;\n" + "%s" "if (TTCN_Logger::log_this_event(TTCN_Logger::PORTEVENT_DUALRECV)) " "{\n" "TTCN_Logger::log_dualport_map(1, \"%s\",\n" @@ -330,7 +347,9 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, "new_item->item_selection = MESSAGE_%lu;\n" "new_item->message_%lu = mapped_par;\n" "new_item->sender_component = sender_component;\n", - target->target_dispname, (unsigned long) target->target_index, + !pdef->legacy ? "if (mapped_par->is_bound()) {\n" : "", //temporary solution instead of setstate + target->target_dispname, + (unsigned long) target->target_index, (unsigned long) target->target_index); if (pdef->testport_type == ADDRESS) { src = mputprintf(src, "if (sender_address != NULL) " @@ -368,7 +387,7 @@ static char *generate_incoming_mapping(char *src, const port_def *pdef, "TTCN_Logger::log_dualport_discard(1, \"%s\", port_name, FALSE);\n" , mapped_type->dispname); } - } else if (report_error) { + } else if (report_error && !has_simple) { // only report error if no simple mapping is present src = mputprintf(src, "TTCN_error(\"Incoming message of type %s could " "not be handled by the type mapping rules on port %%s.\", " "port_name);\n", mapped_type->dispname); @@ -1370,6 +1389,13 @@ void defPortClass(const port_def* pdef, output_struct* output) base_class_name = mcopystr("PORT"); } else { switch (pdef->port_type) { + case USER: + if (pdef->legacy) { + class_name = mcopystr(pdef->name); + base_class_name = mprintf("%s_PROVIDER", pdef->provider_name); + break; + } + // else fall through case REGULAR: class_name = mprintf("%s_BASE", pdef->name); base_class_name = mcopystr("PORT"); @@ -1378,10 +1404,6 @@ void defPortClass(const port_def* pdef, output_struct* output) class_name = mcopystr(pdef->name); base_class_name = mprintf("%s_PROVIDER", pdef->name); break; - case USER: - class_name = mcopystr(pdef->name); - base_class_name = mprintf("%s_PROVIDER", pdef->provider_name); - break; default: FATAL_ERROR("defPortClass(): invalid port type"); } @@ -1582,8 +1604,8 @@ void defPortClass(const port_def* pdef, output_struct* output) "sliding_buffer = OCTETSTRING(0, 0);\n"); src = mputstr(src, "}\n\n"); } - - + + def = mputstr(def, "public:\n"); /* constructor */ @@ -1963,19 +1985,58 @@ void defPortClass(const port_def* pdef, output_struct* output) "}\n\n", class_name, sig->name); } - if (pdef->testport_type != INTERNAL && pdef->port_type == REGULAR) { + if (pdef->testport_type != INTERNAL && + (pdef->port_type == REGULAR || (pdef->port_type == USER && !pdef->legacy))) { /* virtual functions for transmission (implemented by the test port) */ def = mputstr(def, "protected:\n"); /* outgoing_send functions */ + size_t n_used = 0; + const char** used = NULL; + // Only print one outgoing_send for each type for (i = 0; i < pdef->msg_out.nElements; i++) { - def = mputprintf(def, "virtual void outgoing_send(" - "const %s& send_par", pdef->msg_out.elements[i].name); - if (pdef->testport_type == ADDRESS) { - def = mputprintf(def, ", const %s *destination_address", - pdef->address_name); + used = (const char**)Realloc(used, (n_used + pdef->msg_out.elements[i].nTargets + 1) * sizeof(const char*)); + boolean found = FALSE; + for (size_t k = 0; k < n_used; k++) { + if (strcmp(used[k], pdef->msg_out.elements[i].name) == 0) { + found = TRUE; + break; + } + } + if (!found) { + def = mputprintf(def, "virtual void outgoing_send(" + "const %s& send_par", pdef->msg_out.elements[i].name); + if (pdef->testport_type == ADDRESS) { + def = mputprintf(def, ", const %s *destination_address", + pdef->address_name); + } + def = mputstr(def, ") = 0;\n"); + used[n_used] = pdef->msg_out.elements[i].name; + n_used++; + } + if (pdef->port_type == USER && !pdef->legacy) { + for (size_t j = 0; j < pdef->msg_out.elements[i].nTargets; j++) { + found = FALSE; + for (size_t k = 0; k < n_used; k++) { + if (strcmp(used[k], pdef->msg_out.elements[i].targets[j].target_name) == 0) { + found = TRUE; + break; + } + } + if (!found) { + def = mputprintf(def, "virtual void outgoing_send(" + "const %s& send_par", pdef->msg_out.elements[i].targets[j].target_name); + if (pdef->testport_type == ADDRESS) { + def = mputprintf(def, ", const %s *destination_address", + pdef->address_name); + } + def = mputstr(def, ") = 0;\n"); + used[n_used] = pdef->msg_out.elements[i].targets[j].target_name; + n_used++; + } + } } - def = mputstr(def, ") = 0;\n"); } + Free(used); // do not delete pointers /* outgoing_call functions */ for (i = 0; i < pdef->proc_out.nElements; i++) { def = mputprintf(def, "virtual void outgoing_call(" @@ -2160,7 +2221,7 @@ void defPortClass(const port_def* pdef, output_struct* output) for (i = 0; i < pdef->provider_msg_in.nElements; i++) { const port_msg_mapped_type *mapped_type = pdef->provider_msg_in.elements + i; - boolean is_simple = mapped_type->nTargets == 1 && + boolean is_simple = (!pdef->legacy || mapped_type->nTargets == 1) && mapped_type->targets[0].mapping_type == M_SIMPLE; def = mputprintf(def, "void incoming_message(const %s& " "incoming_par, component sender_component%s", @@ -2211,6 +2272,10 @@ void defPortClass(const port_def* pdef, output_struct* output) " TTCN_Logger::log_event_str(\" %s : \")," " incoming_par.log(), TTCN_Logger::end_event_log2str()));\n" "}\n", mapped_type->dispname); + // Print the simple mapping after the not simple mappings + if (!is_simple || !pdef->legacy) { + src = generate_incoming_mapping(src, pdef, mapped_type, is_simple); + } if (is_simple) { src = mputprintf(src, #ifndef NDEBUG @@ -2230,7 +2295,7 @@ void defPortClass(const port_def* pdef, output_struct* output) pdef->address_name); } src = mputstr(src, "append_to_msg_queue(new_item);\n"); - } else src = generate_incoming_mapping(src, pdef, mapped_type); + } src = mputstr(src, "}\n\n"); } } else { /* not user */ @@ -2744,7 +2809,8 @@ void defPortClass(const port_def* pdef, output_struct* output) output->header.class_decls = mputprintf(output->header.class_decls, "class %s;\n", class_name); - if (pdef->testport_type != INTERNAL && pdef->port_type == REGULAR) + if (pdef->testport_type != INTERNAL && + (pdef->port_type == REGULAR || (pdef->port_type == USER && !pdef->legacy))) output->header.class_decls = mputprintf(output->header.class_decls, "class %s;\n", pdef->name); @@ -2753,6 +2819,11 @@ void defPortClass(const port_def* pdef, output_struct* output) if (pdef->testport_type != INTERNAL) { switch (pdef->port_type) { + case USER: + if (pdef->legacy) { + break; + } + // else fall through case REGULAR: output->header.testport_includes = mputprintf( output->header.testport_includes, "#include \"%s.hh\"\n", @@ -2857,15 +2928,54 @@ void generateTestPortSkeleton(const port_def *pdef) class_name, base_class_name, class_name, pdef->port_type == REGULAR ? " = NULL" : "", class_name); + // Only print each outgoing_send for each type + size_t n_used = 0; + const char** used = NULL; for (i = 0; i < pdef->msg_out.nElements; i++) { - fprintf(fp, "\tvoid outgoing_send(const %s& send_par", - pdef->msg_out.elements[i].name); - if (pdef->testport_type == ADDRESS) { - fprintf(fp, ",\n" - "\t\tconst %s *destination_address", pdef->address_name); + boolean found = FALSE; + used = (const char**)Realloc(used, (n_used + pdef->provider_msg_in.nElements + pdef->msg_out.elements[i].nTargets + 1) * sizeof(const char*)); + for (size_t k = 0; k < n_used; k++) { + if (strcmp(used[k], pdef->msg_out.elements[i].name) == 0) { + found = TRUE; + break; + } + } + if (!found) { + fprintf(fp, "\tvoid outgoing_send(const %s& send_par", + pdef->msg_out.elements[i].name); + if (pdef->testport_type == ADDRESS) { + fprintf(fp, ",\n" + "\t\tconst %s *destination_address", pdef->address_name); + } + fputs(");\n", fp); + used[n_used] = pdef->msg_out.elements[i].name; + n_used++; + } + if (pdef->port_type == USER && !pdef->legacy) { + for (size_t j = 0; j < pdef->msg_out.elements[i].nTargets; j++) { + found = FALSE; + for (size_t k = 0; k < n_used; k++) { + if (strcmp(used[k], pdef->msg_out.elements[i].targets[j].target_name) == 0) { + found = TRUE; + break; + } + } + if (!found) { + fprintf(fp, "\tvoid outgoing_send(" + "const %s& send_par", pdef->msg_out.elements[i].targets[j].target_name); + if (pdef->testport_type == ADDRESS) { + fprintf(fp, ",\n" + "\t\tconst %s *destination_address", pdef->address_name); + } + fputs(");\n", fp); + + used[n_used] = pdef->msg_out.elements[i].targets[j].target_name; + n_used++; + } + } } - fputs(");\n", fp); } + Free(used); // do not delete pointers for (i = 0; i < pdef->proc_out.nElements; i++) { fprintf(fp, "\tvoid outgoing_call(const %s_call& call_par", pdef->proc_out.elements[i].name); @@ -3014,18 +3124,58 @@ void generateTestPortSkeleton(const port_def *pdef) class_name, class_name, class_name, class_name, class_name, class_name, class_name, class_name, class_name, class_name, class_name); - + // Only print one outgoing_send for each type + // TODO: It is done three times, so maybe we can refactor it in the Ttfcnstuff.cc + size_t n_used = 0; + const char** used = NULL; for (i = 0; i < pdef->msg_out.nElements; i++) { - fprintf(fp, "void %s::outgoing_send(const %s& /*send_par*/", - class_name, pdef->msg_out.elements[i].name); - if (pdef->testport_type == ADDRESS) { - fprintf(fp, ",\n" - "\tconst %s * /*destination_address*/", pdef->address_name); + used = (const char**)Realloc(used, (n_used + pdef->msg_out.elements[i].nTargets + 1) * sizeof(const char*)); + boolean found = FALSE; + for (size_t k = 0; k < n_used; k++) { + if (strcmp(used[k], pdef->msg_out.elements[i].name) == 0) { + found = TRUE; + break; + } + } + if (!found) { + fprintf(fp, "void %s::outgoing_send(const %s& /*send_par*/", + class_name, pdef->msg_out.elements[i].name); + if (pdef->testport_type == ADDRESS) { + fprintf(fp, ",\n" + "\tconst %s * /*destination_address*/", pdef->address_name); + } + fputs(")\n" + "{\n\n" + "}\n\n", fp); + used[n_used] = pdef->msg_out.elements[i].name; + n_used++; + } + if (pdef->port_type == USER && !pdef->legacy) { + for (size_t j = 0; j < pdef->msg_out.elements[i].nTargets; j++) { + found = FALSE; + for (size_t k = 0; k < n_used; k++) { + if (strcmp(used[k], pdef->msg_out.elements[i].targets[j].target_name) == 0) { + found = TRUE; + break; + } + } + if (!found) { + fprintf(fp, "void %s::outgoing_send(const %s& /*send_par*/", + class_name, pdef->msg_out.elements[i].targets[j].target_name); + if (pdef->testport_type == ADDRESS) { + fprintf(fp, ",\n" + "\tconst %s * /*destination_address*/", pdef->address_name); + } + fputs(")\n" + "{\n\n" + "}\n\n", fp); + used[n_used] = pdef->msg_out.elements[i].targets[j].target_name; + n_used++; + } + } } - fputs(")\n" - "{\n\n" - "}\n\n", fp); } + Free(used); // do not delete pointers for (i = 0; i < pdef->proc_out.nElements; i++) { fprintf(fp, "void %s::outgoing_call(const %s_call& /*call_par*/", class_name, pdef->proc_out.elements[i].name); diff --git a/compiler2/ttcn3/port.h b/compiler2/ttcn3/port.h index 91384157dbde3b9f527ad20d1f786e7f22b4287f..c22ba2ff091d00966acad5b23d30cd7fd6044198 100644 --- a/compiler2/ttcn3/port.h +++ b/compiler2/ttcn3/port.h @@ -12,6 +12,7 @@ * Delic, Adam * Kremer, Peter * Raduly, Csaba + * Szabo, Bence Janos * Szabo, Janos Zoltan – initial implementation * ******************************************************************************/ @@ -104,6 +105,7 @@ typedef struct port_def_tag { const char *provider_name; port_msg_mapped_type_list provider_msg_in; boolean has_sliding; + boolean legacy; } port_def; #ifdef __cplusplus diff --git a/function_test/Semantic_Analyser/Makefile.semantic b/function_test/Semantic_Analyser/Makefile.semantic index 70d89e865797ec76c04db3d603cef7c2ac9e1fff..41866d230c5d3df4b0d4ec0c2612c6edc5c748db 100644 --- a/function_test/Semantic_Analyser/Makefile.semantic +++ b/function_test/Semantic_Analyser/Makefile.semantic @@ -12,7 +12,8 @@ # Szabo, Bence Janos # ############################################################################## -SADIRS := ver xer encode param template any_from pattern_ref float recof_index +SADIRS := ver xer encode param template any_from pattern_ref float recof_index \ +port_translation ifeq ($(RT2), yes) SADIRS += deprecated erroneous_attributes endif diff --git a/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn b/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..4767247b8f8b6dea0a44bb5f5775274f136588d2 --- /dev/null +++ b/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn @@ -0,0 +1,180 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ +module PortTranslate_SE { //^In TTCN-3 module// + + type integer MyInt; + + type port PT1 message map to //In translation capability\:// //^In type definition \`PT1\'\:// + P1, //^error\: The referenced port type \`\@PortTranslate_SE\.P1\' must have the \`provider\' attribute// + MyInt, //error\: Type reference \`MyInt\' does not refer to a port type// + P1 { //^error\: The referenced port type \`\@PortTranslate_SE\.P1\' must have the \`provider\' attribute// + in integer + } + + type port PT2 message map to //In translation capability\:// //^In type definition \`PT2\'\:// + P1, //error\: The referenced port type \`\@PortTranslate_SE\.P1\' must have the \`provider\' attribute// + P2 { + in integer + } + + type port P1 message { + in integer + } + + type port P2 message { + in integer + } with { + extension "provider" + } + + type port P3 message { + in integer, charstring + out integer + } with { + extension "provider" + } + + type port P4 message { + out charstring + } with { + extension "provider" + } + + type port P5 message { + in integer + } with { + extension "provider" + } + + type port P6 message { + inout charstring + } with { + extension "provider" + } + + type port P7 message { + in charstring + } with { + extension "provider" + } + + type port P8 message { + in charstring + out integer + } with { + extension "provider" + } + + + + type port PT3 message map to P3 { //^In translation capability\:// //^In type definition \`PT3\'\:// //error\: Incoming message type \`charstring\' is not present in the in\(out\) message list or in the from mapping types\, coming from port\: \`P3\'\.// + in integer + } + + type port PT4 message map to P3 { //^In translation capability\:// //^In type definition \`PT4\'\:// //error\: Incoming message type \`charstring\' is not present in the in\(out\) message list or in the from mapping types\, coming from port\: \`P3\'\.// //error\: Incoming message type \`integer\' is not present in the in\(out\) message list or in the from mapping types\, coming from port\: \`P3\'\.// + out integer + } + + type port PT5 message map to P4 { //^In translation capability\:// //^In type definition \`PT5\'\:// //error\: Inout message type \`integer\' is not present on the in and out messages or the inout messages of port \`P4\'\.// + inout integer + } + + type port PT6 message map to P5 { //^In translation capability\:// //^In type definition \`PT6\'\:// //error\: Inout message type \`integer\' is not present on the in and out messages or the inout messages of port \`P5\'\.// + inout integer + } + + type port PT7 message map to P6 { //^In translation capability\:// //^In type definition \`PT7\'\:// //^error\: Incoming message type \`charstring\' is not present in the in\(out\) message list or in the from mapping types\, coming from port\: \`P6\'\.// //^error\: Inout message type \`integer\' is not present on the in and out messages or the inout messages of port \`P6\'\.// + inout integer + } + + type port PT8 message map to P7 { //^In translation capability\:// //^In type definition \`PT8\'\:// //error\: Out message type \`integer\' is not present in the out message list of the port \`P7\'\.// + out integer + in charstring + } + + + type port PT9 message map to P8 { //^In translation capability\:// //^In type definition \`PT9\'\:// //^In type mapping\:// //^In \`function\' mapping\:// //error\: The referenced function \`\@PortTranslate_SE\.bad_int_to_char\' does not have \`prototype\' fast attribute// + in charstring from integer with bad_int_to_char() : integer with int_to_char() + out integer + } + + type port PT10 message map to P8 { //^In translation capability\:// //^In type definition \`PT10\'\:// //^In type mapping\:// //^In \`function\' mapping\:// //error\: The referenced function \`\@PortTranslate_SE\.bad_int_to_char\' does not have \`prototype\' fast attribute// + in charstring + out integer to charstring with bad_int_to_char() : charstring with int_to_char() + } + + function bad_int_to_char(in integer a, out charstring b) { + + } + + function int_to_char(in integer a, out charstring b) { + + } with { + extension "prototype(fast)" + } + + type port PT11 message map to P8 { //^In translation capability\:// //^In type definition \`PT11\'\:// //^In type mapping\:// //^In \`function\' mapping\:// + in charstring + out integer to charstring with bad_int_to_char2() : charstring with bad_int_to_char3() //^In \`function\' mapping\:// //error\: The input type of function \`\@PortTranslate_SE\.bad_int_to_char2\' must be the same as the source type of the mapping\: \`integer\' was expected instead of \`octetstring\'// //^error\: The output type of function \`\@PortTranslate_SE\.bad_int_to_char3\' must be the same as the target type of the mapping\: \`charstring\' was expected instead of \`octetstring\'// + } + + function bad_int_to_char2(in octetstring a, out charstring b) { + + } with { + extension "prototype(fast)" + } + + function bad_int_to_char3(in integer a, out octetstring b) { + + } with { + extension "prototype(fast)" + } + + type port PT12 message map to P8 { //^In translation capability\:// //^In type definition \`PT12\'\:// //^In type mapping\:// //^In \`function\' mapping\:// + in charstring from integer with bad_int_to_char4() : integer with bad_int_to_char5() //^In \`function\' mapping\:// //^error\: The input type of function \`\@PortTranslate_SE\.bad_int_to_char4\' must be the same as the source type of the mapping\: \`integer\' was expected instead of \`octetstring\'// //^error\: The output type of function \`\@PortTranslate_SE\.bad_int_to_char5\' must be the same as the target type of the mapping\: \`charstring\' was expected instead of \`octetstring\'// + out integer + } + + function bad_int_to_char4(in octetstring a, out charstring b) { + + } with { + extension "prototype(fast)" + } + + function bad_int_to_char5(in integer a, out octetstring b) { + + } with { + extension "prototype(fast)" + } + + + type port PT13 message map to P8 { //^In translation capability\:// //^In type definition \`PT13\'\:// //^In type mapping\:// //^In \`function\' mapping\:// //^error\: Reference to a function was expected instead of external function \`\@PortTranslate_SE\.bad_char_to_int6\'// + in charstring from integer with bad_char_to_int6() + out integer + } + + external function bad_char_to_int6(in integer a, out octetstring b) + with { + extension "prototype(fast)" + } + + type port PT14 message map to P8 { //^In translation capability\:// //^In type definition \`PT14\'\:// //^In type mapping\:// //^In \`function\' mapping\:// //^error\: Reference to a function was expected instead of external function \`\@PortTranslate_SE\.bad_int_to_char6\'// + in charstring + out integer to charstring with bad_int_to_char6() + } + + external function bad_int_to_char6(in charstring a, out integer b) + with { + extension "prototype(fast)" + } + +} \ No newline at end of file diff --git a/function_test/Semantic_Analyser/port_translation/run_test_all b/function_test/Semantic_Analyser/port_translation/run_test_all new file mode 100755 index 0000000000000000000000000000000000000000..f524a62f4722b00e9bbceca4f404e718915d75d8 --- /dev/null +++ b/function_test/Semantic_Analyser/port_translation/run_test_all @@ -0,0 +1,3 @@ +#!/bin/bash + +make run || echo "makeitfail" >float_TD.script_error && exit 42 diff --git a/function_test/Semantic_Analyser/port_translation/t b/function_test/Semantic_Analyser/port_translation/t new file mode 100755 index 0000000000000000000000000000000000000000..3a4b58ec16cf2f1390a36c7a92f8823e3b94b425 --- /dev/null +++ b/function_test/Semantic_Analyser/port_translation/t @@ -0,0 +1,9 @@ +#!/usr/bin/perl +# note this is called through "perl -w" +use strict; + +my $self = $0; +$self =~ s!/t!!; + +exec('make check --no-print-directory -s -C ' . $self); + diff --git a/regression_test/Makefile b/regression_test/Makefile index 3a0c80212c53410d10d42e2136209e9257e8a1a7..e5f72dcb23f2ddec3ce4c57017551b4e8a75203d 100644 --- a/regression_test/Makefile +++ b/regression_test/Makefile @@ -48,7 +48,7 @@ XML ipv6 implicitOmit testcase_defparam transparent HQ16404 cfgFile \ all_from lazyEval tryCatch text2ttcn json ttcn2json profiler templateOmit \ customEncoding makefilegen uidChars checkstate hostid templateIstemplatekind \ selectUnion templateExclusiveRange any_from templatePatternRef indexWithRecofArray \ -connectMapOperTest fuzzy +connectMapOperTest fuzzy portTranslation ifdef DYN DIRS += loggerplugin junitlogger diff --git a/regression_test/compileonly/Makefile b/regression_test/compileonly/Makefile index 1d565b43c935acc750af1f60b81ffdc825fb30f6..faa264f9640f3889c0b23c9f9533a4576cf3c2fe 100644 --- a/regression_test/compileonly/Makefile +++ b/regression_test/compileonly/Makefile @@ -28,7 +28,7 @@ CODIRS := dynamicTemplate styleGuide topLevelPdu \ isbound namedActualParameters assignmentNotation \ attribQualif HT48786 selectCase openTypeNames \ defaultParamUsageBeforeDecl deterministic readFromFile \ - asn1_hyphen nameClash + asn1_hyphen nameClash portTranslation ifdef DYN CODIRS += mfgen-xsd diff --git a/regression_test/compileonly/portTranslation/Makefile b/regression_test/compileonly/portTranslation/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..94867088c4069da3319ab2c2d5c2071fc10f3dd8 --- /dev/null +++ b/regression_test/compileonly/portTranslation/Makefile @@ -0,0 +1,33 @@ +############################################################################## +# Copyright (c) 2000-2017 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Szabo, Bence Janos +# +############################################################################## +TOPDIR := ../.. +include $(TOPDIR)/Makefile.regression + +ifdef LCOV +COVERAGE_FLAG := -C +endif + + +MAKEPROG := ${MAKE} + +all: + rm -rf bin && mkdir -p bin && cd bin && compiler -t ../*.ttcn && makefilegen -f ../*.ttcn *.cc *.hh && make + + +clean: + -rm -rf bin + +distclean: clean + -rm -f *.out + +.PHONY: all clean distclean Normal Recursive RecursiveDynamic + diff --git a/regression_test/compileonly/portTranslation/PortTranslate.ttcn b/regression_test/compileonly/portTranslation/PortTranslate.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..f39f8215169c2e0bf49890297785fb13c021da0f --- /dev/null +++ b/regression_test/compileonly/portTranslation/PortTranslate.ttcn @@ -0,0 +1,362 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ +module PortTranslate { + + type port P1 message { + in integer + } with { + extension "provider" + } + + type port PT1 message map to P1 { + in integer from charstring with str_to_int() : charstring with str_to_int() : octetstring with oct_to_int() + } + + type port PT2 message map to P1 { + in integer from charstring with str_to_int() : charstring with str_to_int() : octetstring with oct_to_int() + in charstring from integer with int_to_str() : integer with int_to_str() : octetstring with oct_to_str() + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P1_ message { + in integer, hexstring + } with { + extension "provider" + } + + type port P2_ message { + in charstring, octetstring + } with { + extension "provider" + } + + type port PT2_ message map to P1_, P2_ { + in integer from octetstring with oct_to_int() : hexstring with hex_to_int() : charstring with str_to_int() + in charstring from octetstring with oct_to_str() : hexstring with hex_to_str() : integer with int_to_str() + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P2 message { + in integer , charstring + } with { + extension "provider" + } + + type port PT3 message map to P2 { + in integer from charstring with str_to_int() + in charstring from integer with int_to_str() + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P3 message { + in integer, charstring + inout octetstring + } with { + extension "provider" + } + + type port PT4 message map to P3 { + in integer + in charstring + inout octetstring + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P4 message { + in integer, charstring + in octetstring + out octetstring + } with { + extension "provider" + } + + type port PT5 message map to P4 { + in integer + in charstring + inout octetstring + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P5 message { + in integer, charstring + in octetstring + out octetstring + } with { + extension "provider" + } + + type port PT6 message map to P5 { + in integer + in charstring + in octetstring + out octetstring + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P6 message { + in integer, charstring + in octetstring + out octetstring, integer + } with { + extension "provider" + } + + type port PT7 message map to P6 { + in integer + in charstring + in octetstring + out octetstring to hexstring with oct_to_hex() : hexstring with oct_to_hex(), integer to hexstring with int_to_hex() : hexstring with int_to_hex() + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P7 message { + in integer + } with { + extension "provider" + } + + type port P8 message { + in integer + } with { + extension "provider" + } + + type port PT9 message map to P7, P8 { + in integer + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P9 message { + in integer + out charstring, octetstring + } with { + extension "provider" + } + + type port P10 message { + in integer + out octetstring, charstring + } with { + extension "provider" + } + + type port PT10 message map to P9, P10 { + in integer + out charstring to octetstring with str_to_oct(), octetstring to charstring with oct_to_str() + } + + +/////////////////////////////////////////////////////////////////////////////// + + type port P13 message { + in integer, hexstring + out charstring, octetstring + } with { + extension "provider" + } + + type port P14 message { + in integer + out octetstring, charstring + } with { + extension "provider" + } + + type port PT12 message map to P13, P14 { + in integer, hexstring + out charstring, octetstring + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P15 message { + in integer, hexstring + out charstring, octetstring + inout bitstring + } with { + extension "provider" + } + + type port P16 message { + in integer, bitstring + out octetstring, charstring, bitstring + } with { + extension "provider" + } + + type port PT13 message map to P15, P16 { + in integer, hexstring + out charstring, octetstring + inout bitstring + } + +/////////////////////////////////////////////////////////////////////////////// + + type port P17 message { + out integer, hexstring, charstring + } with { + extension "provider" + } + + type port P18 message { + out charstring, octetstring, integer + } with { + extension "provider" + } + + type port PT14 message map to P17, P18 { + out integer to bitstring with int_to_bit() : hexstring with int_to_hex() + out charstring to bitstring with str_to_bit() : hexstring with str_to_hex() + } + + + + + /* Conversion functions */ + + function int_to_str(in integer i, out charstring j) { + + } with { + extension "prototype(fast)"; + } + + function int_to_oct(in integer i, out octetstring j) { + + } with { + extension "prototype(fast)"; + } + + function int_to_bit(in integer i, out bitstring j) { + + } with { + extension "prototype(fast)"; + } + + function int_to_hex(in integer i, out hexstring j) { + + } with { + extension "prototype(fast)"; + } + + ///////////////////////////////////////////////////// + + function str_to_int(in charstring i, out integer j) { + + } with { + extension "prototype(fast)"; + } + + function str_to_oct(in charstring i, out octetstring j) { + + } with { + extension "prototype(fast)"; + } + + function str_to_bit(in charstring i, out bitstring j) { + + } with { + extension "prototype(fast)"; + } + + function str_to_hex(in charstring i, out hexstring j) { + + } with { + extension "prototype(fast)"; + } + + ///////////////////////////////////////////////////// + + function oct_to_int(in octetstring i, out integer j) { + + } with { + extension "prototype(fast)"; + } + + function oct_to_str(in octetstring i, out charstring j) { + + } with { + extension "prototype(fast)"; + } + + function oct_to_bit(in octetstring i, out bitstring j) { + + } with { + extension "prototype(fast)"; + } + + function oct_to_hex(in octetstring i, out hexstring j) { + + } with { + extension "prototype(fast)"; + } + + ///////////////////////////////////////////////////// + + function bit_to_int(in bitstring i, out integer j) { + + } with { + extension "prototype(fast)"; + } + + function bit_to_str(in bitstring i, out charstring j) { + + } with { + extension "prototype(fast)"; + } + + function bit_to_oct(in bitstring i, out octetstring j) { + + } with { + extension "prototype(fast)"; + } + + function bit_to_hex(in bitstring i, out hexstring j) { + + } with { + extension "prototype(fast)"; + } + + ///////////////////////////////////////////////////// + + function hex_to_int(in hexstring i, out integer j) { + + } with { + extension "prototype(fast)"; + } + + function hex_to_str(in hexstring i, out charstring j) { + + } with { + extension "prototype(fast)"; + } + + function hex_to_oct(in hexstring i, out octetstring j) { + + } with { + extension "prototype(fast)"; + } + + function hex_to_bit(in hexstring i, out bitstring j) { + + } with { + extension "prototype(fast)"; + } + +} \ No newline at end of file diff --git a/regression_test/portTranslation/Makefile b/regression_test/portTranslation/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..91bf361afafbfe1504be5af8a740e81ab312c895 --- /dev/null +++ b/regression_test/portTranslation/Makefile @@ -0,0 +1,138 @@ +############################################################################## +# Copyright (c) 2000-2017 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Szabo, Bence Janos +# +############################################################################## +TOPDIR := .. +include ../Makefile.regression + +# +# Do NOT touch this line... +# +.PHONY: all run archive check clean dep objects + +.SUFFIXES: .d + +# +# Set these variables... +# + +#CXXFLAGS += -save-temps +CXXFLAGS += -g + +# Flags for dependency generation +CXXDEPFLAGS = -MM + +#COMPILER_FLAGS += + +# Flags for the linker: +LDFLAGS += -g + +ifeq ($(PLATFORM), WIN32) +# Silence linker warnings. +LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc +endif + +# Flags for the TTCN-3 and ASN.1 compiler: +#COMPILER_FLAGS += -L + +# Execution mode: (either ttcn3 or ttcn3-parallel) +TTCN3_LIB = ttcn3$(RT2_SUFFIX)-parallel$(DYNAMIC_SUFFIX) + + +# TTCN-3 modules of this project: +TTCN3_MODULES = PortTranslation.ttcn + +# ASN.1 modules of this project: +ASN1_MODULES = + +# C++ source & header files generated from the TTCN-3 & ASN.1 modules of +# this project: +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef SPLIT_TO_SLICES +POSTFIXES := $(foreach file, $(SPLIT_TO_SLICES), $(addsuffix $(file), _part_)) +POSTFIXES := $(foreach file, $(POSTFIXES), $(addprefix $(file), .cc)) +GENERATED_SOURCES2 := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), $(POSTFIXES))) +GENERATED_SOURCES += $(GENERATED_SOURCES2) +endif +# C/C++ Source & header files of Test Ports, external functions and +# other modules: +USER_SOURCES = PT2.cc P1.cc P2.cc +USER_HEADERS = $(USER_SOURCES:.cc=.hh) + +# Object files of this project that are needed for the executable test suite: +OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS) + +GENERATED_OBJECTS = $(GENERATED_SOURCES:.cc=.o) + +USER_OBJECTS = $(USER_SOURCES:.cc=.o) + +DEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d) + +# Other files of the project (Makefile, configuration files, etc.) +# that will be added to the archived source files: +OTHER_FILES = Makefile + +# The name of the executable test suite: +TARGET = PortTranslation$(EXESUFFIX) + +# +# Rules for building the executable... +# + +all: $(TARGET) ; + +objects: $(OBJECTS) ; + +$(TARGET): $(OBJECTS) + $(TTCN3_DIR)/bin/titanver $(OBJECTS) + $(CXX) $(LDFLAGS) -o $@ $^ \ + -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \ + -L$(OPENSSL_DIR)/lib -lcrypto \ + -L$(XMLDIR)/lib $($(PLATFORM)_LIBS) + +.cc.o .c.o: + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< + +.cc.d .c.d: + @echo Creating dependency file for '$<'; set -e; \ + $(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \ + | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ + [ -s $@ ] || rm -f $@ + +$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile + @if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi + +compile:: $(TTCN3_DIR)/bin/compiler # $(TTCN3_COMPILER) + @if [ -f $@ ]; then $(RM) compile; $(MAKE) compile; fi + +compile:: $(TTCN3_MODULES) $(ASN1_MODULES) + $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ - $? + touch $@ + +clean distclean: + -$(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) compile $(DEPFILES) \ + tags *.log $(RT2CFG) + +dep: $(GENERATED_SOURCES) $(USER_SOURCES) ; + +ifeq ($(findstring n,$(MAKEFLAGS)),) +ifeq ($(filter clean distclean check compile archive diag,$(MAKECMDGOALS)),) +-include $(DEPFILES) +endif +endif + + +# +# Add your rules here if necessary... +# +run: $(TARGET) config.cfg + ttcn3_start $^ diff --git a/regression_test/portTranslation/P1.cc b/regression_test/portTranslation/P1.cc new file mode 100644 index 0000000000000000000000000000000000000000..65c6611350cb7534e370f23b5fa89831e62cc674 --- /dev/null +++ b/regression_test/portTranslation/P1.cc @@ -0,0 +1,91 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +#include "P1.hh" +#include "PortTranslation.hh" + +namespace PortTranslation { + +P1_PROVIDER::P1_PROVIDER(const char *par_port_name) + : PORT(par_port_name) +{ + +} + +P1_PROVIDER::~P1_PROVIDER() +{ + +} + +void P1_PROVIDER::set_parameter(const char * /*parameter_name*/, + const char * /*parameter_value*/) +{ + +} + +/*void P1_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + +void P1_PROVIDER::Handle_Fd_Event_Error(int /*fd*/) +{ + +} + +void P1_PROVIDER::Handle_Fd_Event_Writable(int /*fd*/) +{ + +} + +void P1_PROVIDER::Handle_Fd_Event_Readable(int /*fd*/) +{ + +} + +/*void P1_PROVIDER::Handle_Timeout(double time_since_last_call) {}*/ + +void P1_PROVIDER::user_map(const char * /*system_port*/) +{ + +} + +void P1_PROVIDER::user_unmap(const char * /*system_port*/) +{ + +} + +void P1_PROVIDER::user_start() +{ + +} + +void P1_PROVIDER::user_stop() +{ + +} + +void P1_PROVIDER::outgoing_send(const MyRec& /*send_par*/) +{ + +} + +void P1_PROVIDER::outgoing_send(const OCTETSTRING& /*send_par*/) +{ + +} + +void P1_PROVIDER::outgoing_send(const BITSTRING& /*send_par*/) +{ + +} + +} /* end of namespace */ + diff --git a/regression_test/portTranslation/P1.hh b/regression_test/portTranslation/P1.hh new file mode 100644 index 0000000000000000000000000000000000000000..48fc4d8bcf259308b9da777732258c12cc3da26b --- /dev/null +++ b/regression_test/portTranslation/P1.hh @@ -0,0 +1,57 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +#ifndef P1_HH +#define P1_HH + +#include <TTCN3.hh> + +// Note: Header file PortTranslation.hh must not be included into this file! +// (because it includes this file) +// Please add the declarations of message types manually. + +namespace PortTranslation { + +class MyRec; + +class P1_PROVIDER : public PORT { +public: + P1_PROVIDER(const char *par_port_name); + ~P1_PROVIDER(); + + void set_parameter(const char *parameter_name, + const char *parameter_value); + +private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ +protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const MyRec& send_par); + void outgoing_send(const OCTETSTRING& send_par); + void outgoing_send(const BITSTRING& send_par); + virtual void incoming_message(const INTEGER& incoming_par) = 0; + virtual void incoming_message(const BITSTRING& incoming_par) = 0; +}; + +} /* end of namespace */ + +#endif diff --git a/regression_test/portTranslation/P2.cc b/regression_test/portTranslation/P2.cc new file mode 100644 index 0000000000000000000000000000000000000000..f78cd618d50c6ec9d14939c4ee86efe02a14017f --- /dev/null +++ b/regression_test/portTranslation/P2.cc @@ -0,0 +1,91 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +#include "P2.hh" +#include "PortTranslation.hh" + +namespace PortTranslation { + +P2_PROVIDER::P2_PROVIDER(const char *par_port_name) + : PORT(par_port_name) +{ + +} + +P2_PROVIDER::~P2_PROVIDER() +{ + +} + +void P2_PROVIDER::set_parameter(const char * /*parameter_name*/, + const char * /*parameter_value*/) +{ + +} + +/*void P2_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + +void P2_PROVIDER::Handle_Fd_Event_Error(int /*fd*/) +{ + +} + +void P2_PROVIDER::Handle_Fd_Event_Writable(int /*fd*/) +{ + +} + +void P2_PROVIDER::Handle_Fd_Event_Readable(int /*fd*/) +{ + +} + +/*void P2_PROVIDER::Handle_Timeout(double time_since_last_call) {}*/ + +void P2_PROVIDER::user_map(const char * /*system_port*/) +{ + +} + +void P2_PROVIDER::user_unmap(const char * /*system_port*/) +{ + +} + +void P2_PROVIDER::user_start() +{ + +} + +void P2_PROVIDER::user_stop() +{ + +} + +void P2_PROVIDER::outgoing_send(const OCTETSTRING& /*send_par*/) +{ + +} + +void P2_PROVIDER::outgoing_send(const MyRec& /*send_par*/) +{ + +} + +void P2_PROVIDER::outgoing_send(const BITSTRING& /*send_par*/) +{ + +} + +} /* end of namespace */ + diff --git a/regression_test/portTranslation/P2.hh b/regression_test/portTranslation/P2.hh new file mode 100644 index 0000000000000000000000000000000000000000..1471914fc11af0758f747085e3e0dc771967cdcb --- /dev/null +++ b/regression_test/portTranslation/P2.hh @@ -0,0 +1,57 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +#ifndef P2_HH +#define P2_HH + +#include <TTCN3.hh> + +// Note: Header file PortTranslation.hh must not be included into this file! +// (because it includes this file) +// Please add the declarations of message types manually. + +namespace PortTranslation { + +class MyRec; + +class P2_PROVIDER : public PORT { +public: + P2_PROVIDER(const char *par_port_name); + ~P2_PROVIDER(); + + void set_parameter(const char *parameter_name, + const char *parameter_value); + +private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ +protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const OCTETSTRING& send_par); + void outgoing_send(const MyRec& send_par); + void outgoing_send(const BITSTRING& send_par); + virtual void incoming_message(const INTEGER& incoming_par) = 0; + virtual void incoming_message(const BITSTRING& incoming_par) = 0; +}; + +} /* end of namespace */ + +#endif diff --git a/regression_test/portTranslation/PT2.cc b/regression_test/portTranslation/PT2.cc new file mode 100644 index 0000000000000000000000000000000000000000..bd291d11c6e373240d0c71124d9e37b4271efbf6 --- /dev/null +++ b/regression_test/portTranslation/PT2.cc @@ -0,0 +1,102 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +#include "PT2.hh" + +namespace PortTranslation { + +PT2::PT2(const char *par_port_name) + : PT2_BASE(par_port_name) +{ + +} + +PT2::~PT2() +{ + +} + +void PT2::set_parameter(const char * /*parameter_name*/, + const char * /*parameter_value*/) +{ + +} + +/*void PT2::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + +void PT2::Handle_Fd_Event_Error(int /*fd*/) +{ + +} + +void PT2::Handle_Fd_Event_Writable(int /*fd*/) +{ + +} + +void PT2::Handle_Fd_Event_Readable(int /*fd*/) +{ + +} + +/*void PT2::Handle_Timeout(double time_since_last_call) {}*/ + +void PT2::user_map(const char * /*system_port*/) +{ + +} + +void PT2::user_unmap(const char * /*system_port*/) +{ + +} + +void PT2::user_start() +{ + +} + +void PT2::user_stop() +{ + +} + +void PT2::outgoing_send(const MyRec& send_par) +{ + OCTETSTRING os = send_par.val(); + incoming_message(os); +} + +void PT2::outgoing_send(const OCTETSTRING& send_par) +{ + INTEGER integer = send_par.lengthof(); + incoming_message(integer); +} + +void PT2::outgoing_send(const INTEGER& send_par) +{ + incoming_message(send_par); +} + +void PT2::outgoing_send(const CHARSTRING& send_par) +{ + incoming_message(send_par); +} + +void PT2::outgoing_send(const BITSTRING& send_par) +{ + incoming_message(send_par); +} + +} /* end of namespace */ + diff --git a/regression_test/portTranslation/PT2.hh b/regression_test/portTranslation/PT2.hh new file mode 100644 index 0000000000000000000000000000000000000000..f1857f5fa70cd1aa9c9dd200b4b8ed770e82a162 --- /dev/null +++ b/regression_test/portTranslation/PT2.hh @@ -0,0 +1,51 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +#ifndef PT2_HH +#define PT2_HH + +#include "PortTranslation.hh" + +namespace PortTranslation { + +class PT2 : public PT2_BASE { +public: + PT2(const char *par_port_name); + ~PT2(); + + void set_parameter(const char *parameter_name, + const char *parameter_value); + +private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ +protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const MyRec& send_par); + void outgoing_send(const OCTETSTRING& send_par); + void outgoing_send(const INTEGER& send_par); + void outgoing_send(const CHARSTRING& send_par); + void outgoing_send(const BITSTRING& send_par); +}; + +} /* end of namespace */ + +#endif diff --git a/regression_test/portTranslation/PortTranslation.ttcn b/regression_test/portTranslation/PortTranslation.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..ffc6010e84301f5813696f1e14f376e5f19fa260 --- /dev/null +++ b/regression_test/portTranslation/PortTranslation.ttcn @@ -0,0 +1,246 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ +module PortTranslation { + +/* Converter functions */ + + // Temporarily if the out param of the mapping functions are unbound it will + // try the next one in order + + function MyRec_to_oct(in MyRec i, out octetstring j) { + if (i.types == Oct) { + j := i.val; + } + } with { + extension "prototype(fast)"; + } + + function MyRec_to_int(in MyRec i, out integer j) { + if (i.types == Int) { + j := oct2int(i.val); + } + } with { + extension "prototype(fast)"; + } + + function MyRec_to_MyRec(in MyRec i, out MyRec j) { + if (i.types == MyRec) { + j := i; + } + } with { + extension "prototype(fast)"; + } + + function MyRec_to_char(in MyRec i, out charstring j) { + if (i.types == Char) { + j := oct2str(i.val); + } + } with { + extension "prototype(fast)"; + } + + function char_to_hex(in charstring i, out hexstring j) { + if (i == "0001") { + j := str2hex(i); + } + } with { + extension "prototype(fast)"; + } + + function char_to_hex2(in charstring i, out hexstring j) { + if (i == "0002") { + j := str2hex(i); + } + } with { + extension "prototype(fast)"; + } + +/////////////////////////////////////////////////////////////////////////////// + + /* Types */ + + type enumerated Types { + Int, Char, Oct, Hex, Bit, MyRec, None + } + + type record MyRec { + octetstring val, + Types types + } + + type port P1 message { + in integer, bitstring + out MyRec, octetstring, bitstring + } with { + extension "provider" + } + + type port P2 message { + in integer, bitstring + out octetstring, MyRec, bitstring + } with { + extension "provider" + } + + type port PT2 message map to P1, P2 { + in charstring + in integer, octetstring, hexstring from charstring with char_to_hex() : charstring with char_to_hex2() + out MyRec to octetstring with MyRec_to_oct() : integer with MyRec_to_int() : MyRec with MyRec_to_MyRec() : charstring with MyRec_to_char() + out octetstring + inout bitstring + } + + + type component MyComp { + port PT2 p; + } + + type component System { + port P1 p1 + port P2 p2 + } + +/////////////////////////////////////////////////////////////////////////////// + + + testcase tc_send() runs on MyComp system System { + map(self:p, system:p1); + var MyRec v_rec := { 'ABCDEF'O, Oct }; + + // Send octetstring with Oct, so the first mapping function will be successful + p.send(v_rec); + timer t := 1.0; + t.start; + alt { + [] p.receive(3) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + // Send octetstring with Int so the second mapping function will be successfull + v_rec := { '12'O, Int }; + p.send(v_rec); + t.start; + alt { + [] p.receive(18) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + // Send octetstring with MyRec so the second mapping function will be successfull + v_rec := { '123456'O, MyRec }; + p.send(v_rec); + t.start; + alt { + [] p.receive('123456'O) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + // Send octetstring with None so it will be generate an error because no mapping can handle the message + v_rec := { '123456'O, None }; + @try{ + p.send(v_rec); + } @catch (e) { + if (match(e, "Dynamic test case error: Outgoing message of type @PortTranslation.MyRec could not be handled by the type mapping rules on port p.")) { + setverdict(pass); + } else { + setverdict(fail); + } + } + + // This should be sent too and the implementation of PT2 will send back the length of it. + var octetstring os := '12345678'O; + p.send(os); + t.start; + alt { + [] p.receive(4) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + var bitstring bs := '010101'B; + p.send(bs); + t.start; + alt { + [] p.receive(bs) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + } + +/////////////////////////////////////////////////////////////////////////////// + + testcase tc_receive() runs on MyComp system System { + map(self:p, system:p1); + var MyRec v_rec := { str2oct("0001"), Char }; + + // Send octetstring with Char, so the it will receive the str2hex("0001") hexstring because first it it will be mapped to + // charstring with the sending mapping, and it will send back to the port and the charstring will be mapped to hexstring using: char_to_hex + p.send(v_rec); + timer t := 1.0; + t.start; + alt { + [] p.receive(str2hex("0001")) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + v_rec := { str2oct("0002"), Char }; + + // Send octetstring with Char, so the it will receive the str2hex("0002") hexstring because first it it will be mapped to + // charstring with the sending mapping, and it will send back to the port and the charstring will be mapped to hexstring using: char_to_hex2 + p.send(v_rec); + t.start; + alt { + [] p.receive(str2hex("0002")) { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + v_rec := { str2oct("0003"), Char }; + + // Send octetstring with Char, so the it will receive the "0003" charstring because first it it will be mapped to + // charstring with the sending mapping, and it will send back to the port and the charstring will not be mapped + p.send(v_rec); + t.start; + alt { + [] p.receive(charstring:"0003") { setverdict(pass); } + [] p.receive(integer:?) { setverdict(fail); } + [] p.receive(octetstring:?) { setverdict(fail); } + [] t.timeout { setverdict(fail); } + } + t.stop; + + } + + + control { + execute(tc_send()) + execute(tc_receive()) + } + +} \ No newline at end of file diff --git a/regression_test/portTranslation/config.cfg b/regression_test/portTranslation/config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..cb3e7ee1b8d66fbce3bf42b86b5fcd3cdc368919 --- /dev/null +++ b/regression_test/portTranslation/config.cfg @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2000-2017 Ericsson Telecom AB +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Szabo, Bence Janos +# +############################################################################### +[EXECUTE] +PortTranslation.control