diff --git a/compiler2/AST.cc b/compiler2/AST.cc index 3f57d065e5d7c6a3e70f24ae8691186a8eef1288..291f03c0382eb409a00068a51309c2287645abc8 100644 --- a/compiler2/AST.cc +++ b/compiler2/AST.cc @@ -177,7 +177,8 @@ namespace Common { // run delayed Type::chk_coding() calls if (!delayed_type_enc_v.empty()) { for (size_t i = 0; i < delayed_type_enc_v.size(); ++i) { - delayed_type_enc_v[i]->t->chk_coding(delayed_type_enc_v[i]->enc, true); + delayed_type_enc_v[i]->t->chk_coding(delayed_type_enc_v[i]->enc, + delayed_type_enc_v[i]->mod, true); delete delayed_type_enc_v[i]; } delayed_type_enc_v.clear(); @@ -303,10 +304,11 @@ namespace Common { } } - void Modules::delay_type_encode_check(Type* p_type, bool p_encode) + void Modules::delay_type_encode_check(Type* p_type, Module* p_module, bool p_encode) { for (size_t i = 0; i < delayed_type_enc_v.size(); ++i) { if (delayed_type_enc_v[i]->t == p_type && + delayed_type_enc_v[i]->mod == p_module && delayed_type_enc_v[i]->enc == p_encode) { // it's already in the list of delayed checks return; @@ -314,6 +316,7 @@ namespace Common { } type_enc_t* elem = new type_enc_t; elem->t = p_type; + elem->mod = p_module; elem->enc = p_encode; delayed_type_enc_v.add(elem); } diff --git a/compiler2/AST.hh b/compiler2/AST.hh index f92c90a625345134f996cae6efc8ea5d90994ff4..4a7c5a05841a8cf24d442ecb0add82658f4661cc 100644 --- a/compiler2/AST.hh +++ b/compiler2/AST.hh @@ -100,6 +100,7 @@ namespace Common { /** Contains info needed for delayed type encoding checks */ struct type_enc_t { Type* t; + Module* mod; bool enc; }; static vector<type_enc_t> delayed_type_enc_v; @@ -152,12 +153,12 @@ namespace Common { * info related to each type */ void generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs); - /** Called if a Type::chk_coding() call could not be resolved (because the - * needed custom coding function was not found yet, but it might be among - * the functions that have not been checked yet). + /** Called if a Type::chk_coding() call could not be resolved (the check for + * custom and PER coding requires the checks of all external functions to + * be completed). * This stores the info needed to call the function again after everything * else has been checked. */ - static void delay_type_encode_check(Type* p_type, bool p_encode); + static void delay_type_encode_check(Type* p_type, Module* p_module, bool p_encode); }; /** diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 58e901530dd551122c9733484dd0108a075992ed..94757c41f73e6a92e7c485802519f4f888d44c0e 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -4428,16 +4428,32 @@ namespace Common { } } - void Type::chk_coding(bool encode, bool delayed /* = false */) { + void Type::chk_coding(bool encode, Module* usage_mod, bool delayed /* = false */) { coding_t& coding = encode ? default_encoding : default_decoding; switch (coding.type) { case CODING_BY_FUNCTION: + { + Module* func_mod = coding.function_def->get_my_scope()->get_scope_mod(); + if (usage_mod != func_mod) { + // add a phantom import for the coder function's module, to make sure + // it is visible from the module that requested the coding + Ttcn::Module* usage_mod_ttcn = dynamic_cast<Ttcn::Module*>(usage_mod); + if (usage_mod_ttcn == NULL) { + FATAL_ERROR("Type::chk_coding"); + } + Ttcn::ImpMod* new_imp = new Ttcn::ImpMod(func_mod->get_modid().clone()); + new_imp->set_mod(func_mod); + new_imp->set_imptype(Ttcn::ImpMod::I_DEPENDENCY); + usage_mod_ttcn->get_imports().add_impmod(new_imp); + } + } + // fall through case CODING_BUILT_IN: if (!delayed) { // a coding method has been set by an external function's checker, // but there might still be unchecked external functions out there; // delay this function until everything else has been checked - Modules::delay_type_encode_check(this, encode); + Modules::delay_type_encode_check(this, usage_mod, encode); } return; case CODING_UNSET: @@ -4550,7 +4566,7 @@ namespace Common { // the type has a custom encoding attribute, but no external coder // function with that encoding has been found yet; // delay this function until everything else has been checked - Modules::delay_type_encode_check(this, encode); + Modules::delay_type_encode_check(this, usage_mod, encode); // set the coding type back to UNSET for delayed call coding.type = CODING_UNSET; } @@ -4562,7 +4578,7 @@ namespace Common { else { // ASN.1 type // delay this function until everything else has been checked, in case // there is an encoder/decoder external function out there for this type - Modules::delay_type_encode_check(this, encode); + Modules::delay_type_encode_check(this, usage_mod, encode); } } diff --git a/compiler2/Type.hh b/compiler2/Type.hh index b24291fb35159d6638d432780c246c98a54e5c6e..759b8742764eb801b43c82143152897d0619e506 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -692,7 +692,7 @@ namespace Common { * @note Because this check depends on the checks of other AST elements * (external functions), it is sometimes delayed to the end of the semantic * analysis. */ - void chk_coding(bool encode, bool delayed = false); + void chk_coding(bool encode, Module* usage_mod, bool delayed = false); /** Indicates whether the type is encoded/decoded by a function or by a * built-in codec. */ diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index 3ab69888c8ff543ad6bcb72a555e53dd6ee463fb..1e6028737cae7f08b5a3b3ea882640c0cd1788a8 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -5782,7 +5782,8 @@ bool Type::chk_this_template_Str(Template *t, namedbool implicit_omit, target->get_Template(), (target->get_DerivedRef() != NULL) ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs); - target_type->get_type_refd_last()->chk_coding(false); + target_type->get_type_refd_last()->chk_coding(false, + t->get_my_scope()->get_scope_mod()); } { Value* str_enc = t->get_string_encoding(); diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 470a6870f73b8189194caa5b7337453160f033de..7e48312eeec7e266a202a2b12a901cef1775dc4c 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -5658,7 +5658,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, }*/ if(!disable_attribute_validation()) { - t_type->chk_coding(true); + t_type->chk_coding(true, my_scope->get_scope_mod()); } switch (t_type->get_typetype()) { @@ -5810,7 +5810,7 @@ error: } if(!disable_attribute_validation()) { - t_type->chk_coding(false); + t_type->chk_coding(false, my_scope->get_scope_mod()); } return; diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 008b08571330784769452c8f0c3637521fe9d726..fdd64d15229f945d321e17be690ab86de53c6ca8 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -1288,6 +1288,10 @@ namespace Ttcn { void ImpMod::chk_imp(ReferenceChain& refch, vector<Common::Module>& moduleStack) { + if (imptype == I_DEPENDENCY) { + // these are added during semantic analysis, including their module pointer + return; + } Error_Context cntxt(this, "In import definition"); if (!modules->has_mod_withId(*modid)) { @@ -1399,6 +1403,8 @@ namespace Ttcn { break; } + case I_DEPENDENCY: + return false; default: FATAL_ERROR("ImpMod::get_imported_def"); } @@ -1489,6 +1495,8 @@ namespace Ttcn { return result; break; } + case I_DEPENDENCY: + return NULL; default: FATAL_ERROR("ImpMod::get_imported_def"); } @@ -1579,6 +1587,16 @@ namespace Ttcn { void Imports::add_impmod(ImpMod *p_impmod) { if (!p_impmod) FATAL_ERROR("Ttcn::Imports::add_impmod()"); + if (p_impmod->get_imptype() == ImpMod::I_DEPENDENCY) { + // this is just an extra dependency, not an actual 'import' in TTCN-3 code, + // only insert it if it's needed + for (size_t i = 0; i < impmods_v.size(); ++i) { + if (p_impmod->get_mod() == impmods_v[i]->get_mod()) { + delete p_impmod; + return; + } + } + } impmods_v.add(p_impmod); p_impmod->set_my_mod(my_mod); } diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh index d98e435642ce75fed5a946268d6ab1e9ba6c1507..dd1cda7c3f05063d9d489e90bfe63e9e4acf42f0 100644 --- a/compiler2/ttcn3/AST_ttcn3.hh +++ b/compiler2/ttcn3/AST_ttcn3.hh @@ -646,7 +646,7 @@ namespace Ttcn { void set_with_attr(MultiWithAttrib* p_attrib); WithAttribPath* get_attrib_path(); void set_parent_path(WithAttribPath* p_path); - const Imports& get_imports() const { return *imp; } + Imports& get_imports() { return *imp; } bool is_visible(const Identifier& id, visibility_t visibility); @@ -719,7 +719,14 @@ namespace Ttcn { I_ERROR, I_ALL, I_IMPORTSPEC, - I_IMPORTIMPORT + I_IMPORTIMPORT, + /** Phantom import for when the 'include' is needed in the generated C++ + * code, but the TTCN-3 'import' statement is optional. + * Currently this can only happen when using coding values of a type that + * has custom or PER coder functions set (the module containing the coder + * function declarations does not have to be imported to the module that + * contains the coding operation). */ + I_DEPENDENCY }; private: /** Points to the target (imported) module. This is initially NULL; diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index a10b05ba7302b165f5955110fa91e15f3f1c249a..a111df363f46a5d0e058f248a9602e3b53d68345 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -8939,7 +8939,8 @@ error: if (!error_flag && t_var_type != NULL) { // make sure the variable's type has a decoding type set, and store it t_parass->set_dec_type(t_var_type->get_type_refd()); - t_parass->get_dec_type()->chk_coding(false); + t_parass->get_dec_type()->chk_coding(false, + t_parass->get_ref()->get_my_scope()->get_scope_mod()); } } else { @@ -9745,7 +9746,8 @@ error: // store the variable type in case it's decoded (since this cannot // be extracted from the value type with the sub-references) v[i]->set_dec_type(var_type->get_type_refd()); - v[i]->get_dec_type()->chk_coding(false); + v[i]->get_dec_type()->chk_coding(false, + v[i]->get_var_ref()->get_my_scope()->get_scope_mod()); } } else { diff --git a/regression_test/customEncoding/Coders.cc b/regression_test/customEncoding/Coders.cc index 4318f4ed87d9a6496486ed4cd8d93119bd9eeac1..93da8c5ea3ba444aed7e4f12b4ffccca5b2fc959 100644 --- a/regression_test/customEncoding/Coders.cc +++ b/regression_test/customEncoding/Coders.cc @@ -161,3 +161,50 @@ INTEGER f__dec__choice(BITSTRING& x, Types::Choice& y) } } // namespace Custom1 + +namespace Custom5 { + +BITSTRING f__enc__set(const Custom3::Set& x) +{ + return int2bit(x.num(), 8); +} + +INTEGER f__dec__set(BITSTRING& b, Custom3::Set& x) +{ + x.num() = bit2int(b); + x.str() = "c++"; + b = BITSTRING(0, NULL); + return 0; +} + +BITSTRING f__enc__setof(const Types::SetOf& x) +{ + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_Buffer buf; + x.encode(Types::SetOf_descr_, buf, TTCN_EncDec::CT_JSON, false); + OCTETSTRING tmp; + buf.get_string(tmp); + return oct2bit(tmp); +} + +INTEGER f__dec__setof(BITSTRING& x, Types::SetOf& y) +{ + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_Buffer buf(bit2oct(x)); + y.decode(Types::SetOf_descr_, buf, TTCN_EncDec::CT_JSON); + switch (TTCN_EncDec::get_last_error_type()) { + case TTCN_EncDec::ET_NONE: { + buf.cut(); + OCTETSTRING tmp; + buf.get_string(tmp); + x = oct2bit(tmp); + return 0; } + case TTCN_EncDec::ET_INCOMPL_MSG: + case TTCN_EncDec::ET_LEN_ERR: + return 2; + default: + return 1; + } +} + +} // namespace Custom5 diff --git a/regression_test/customEncoding/Coders.hh b/regression_test/customEncoding/Coders.hh index ca2af2acf901afb62790ad063a4e338915741973..9902fa454473e5a306553a01c35e731732a0513d 100644 --- a/regression_test/customEncoding/Coders.hh +++ b/regression_test/customEncoding/Coders.hh @@ -13,6 +13,7 @@ #include "Custom2.hh" #include "Custom1.hh" +#include "Custom5.hh" #ifndef CODERS_HH #define CODERS_HH @@ -27,6 +28,7 @@ INTEGER f__dec__rec(BITSTRING& b, Custom3::Rec& x); BITSTRING f__enc__uni(const Custom1::Uni& x); INTEGER f__dec__uni(BITSTRING& b, Custom1::Uni& x); +// Coding functions for the bitstring type in test 4 BITSTRING f__enc__bs(const BITSTRING& x); INTEGER f__dec__bs(BITSTRING& b, BITSTRING& x); @@ -45,4 +47,16 @@ extern INTEGER f__dec__choice(BITSTRING& x, Types::Choice& y); } +namespace Custom5 { + +// Coding functions for the set type in test 5 +BITSTRING f__enc__set(const Custom3::Set& x); +INTEGER f__dec__set(BITSTRING& b, Custom3::Set& x); + +// "PER" coder functions, using the built-in JSON codec +extern BITSTRING f__enc__setof(const Types::SetOf& x); +extern INTEGER f__dec__setof(BITSTRING& x, Types::SetOf& y); + +} + #endif diff --git a/regression_test/customEncoding/Custom1.ttcn b/regression_test/customEncoding/Custom1.ttcn index 4832eadb9123a958fa788834e725a21fe3940025..e6f8357c3f397860fe6fc5b6b19698d4d1d18264 100644 --- a/regression_test/customEncoding/Custom1.ttcn +++ b/regression_test/customEncoding/Custom1.ttcn @@ -165,6 +165,30 @@ testcase tc_custom4() runs on CT } // Test 5. +// The encoded type is a set defined in another module +// The coding functions are declared in a 3rd module (which is not imported in this module) +testcase tc_custom5() runs on CT +{ + var Set x := { num := 3, str := "ttcn" }; + var bitstring enc_exp := int2bit(x.num, 8); + var Set dec_exp := { num := 3, str := "c++" }; + + var bitstring enc := encvalue(x); + if (enc != enc_exp) { + setverdict(fail, "Expected: ", enc_exp, ", got: ", enc); + } + var Set dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Failed to decode ", enc_exp); + } + if (dec != dec_exp) { + setverdict(fail, "Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +// Test 6. // Using encvalue on templates and template variables // Same type and encoding function as test 1 testcase tc_custom_temp() runs on CT @@ -185,7 +209,7 @@ testcase tc_custom_temp() runs on CT setverdict(pass); } -// Test 6. +// Test 7. // Same as test 2, but with encvalue_unichar and decvalue_unichar. // The input RecOf has also been adjusted, so it doesn't cause problems for the UTF-8 decoder. testcase tc_custom_unichar() runs on CT @@ -209,7 +233,7 @@ testcase tc_custom_unichar() runs on CT setverdict(pass); } -// Test 7. +// Test 8. // Using custom encoding on a decoded parameter redirect. // Same input value as in test 5. testcase tc_custom_param_redirect() runs on CT @@ -240,7 +264,7 @@ testcase tc_custom_param_redirect() runs on CT } } -// Test 8. +// Test 9. // Using custom encoding in a template with decoded content matching. // Same input as test 3. testcase tc_custom_decmatch() runs on CT @@ -272,7 +296,7 @@ external function f_enc_seq(in Seq x) return octetstring external function f_dec_seq(in octetstring x) return Seq with { extension "prototype(convert) decode(JSON)" }; -// Test 9. +// Test 10. // Using encvalue and decvalue on the ASN.1 type Seq (with JSON encoding). testcase tc_asn() runs on CT { @@ -295,7 +319,31 @@ testcase tc_asn() runs on CT setverdict(pass); } -// Test 10. +// Test 11. +// Using encvalue and decvalue on the ASN.1 type Set (with JSON encoding). +// The external functions indicating the type's coding are in a different module, which is not imported. +testcase tc_asn2() runs on CT +{ + var Set2 x := { num := 10, str := "abc" }; + var bitstring enc_exp := oct2bit(char2oct("{\"num\":10,\"str\":\"abc\"}")); + var Set2 dec_exp := x; + + var bitstring enc := encvalue(x); + if (enc != enc_exp) { + setverdict(fail, "Expected: ", enc_exp, ", got: ", enc); + } + var Set2 dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Failed to decode ", enc_exp); + } + if (dec != dec_exp) { + setverdict(fail, "Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +// Test 12. // The redirected parameter is decoded into a value of ASN.1 type Seq. // Same input value as in test 8. testcase tc_asn_param_redirect() runs on CT @@ -326,7 +374,7 @@ testcase tc_asn_param_redirect() runs on CT } } -// Test 11. +// Test 13. // Decoded content matching against a value of ASN.1 type Seq. // Same input value as in test 8. testcase tc_asn_decmatch() runs on CT @@ -359,7 +407,7 @@ external function f_enc_seqof(in SeqOf x) return bitstring external function f_dec_seqof(inout bitstring x, out SeqOf y) return integer with { extension "prototype(sliding) decode(PER)" }; -// Test 12. +// Test 14. // PER coder with encvalue and decvalue. testcase tc_per() runs on CT { @@ -383,7 +431,32 @@ testcase tc_per() runs on CT setverdict(pass); } -// Test 13. +// Test 15. +// PER coder with encvalue and decvalue. +// The PER coder functions are declared in a module, which is not imported into this one. +testcase tc_per2() runs on CT +{ + var SetOf x := { 1, 2, 3 }; + // the manually written "PER" coder for this module uses the built-in JSON coder + var bitstring enc_exp := oct2bit(char2oct("[1,2,3]")); + var SetOf dec_exp := x; + + var bitstring enc := encvalue(x); + if (enc != enc_exp) { + setverdict(fail, "Expected: ", enc_exp, ", got: ", enc); + } + var SetOf dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Failed to decode ", enc_exp); + } + if (dec != dec_exp) { + setverdict(fail, "Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +// Test 16. // The redirected parameter is decoded using the PER coder. // Same input value as in test 11. testcase tc_per_param_redirect() runs on CT @@ -414,7 +487,7 @@ testcase tc_per_param_redirect() runs on CT } } -// Test 14. +// Test 17. // Decoded content matching with the PER coder. // Same input value as in test 11. testcase tc_per_decmatch() runs on CT @@ -447,7 +520,7 @@ external function f_enc_choice(in Choice x) return bitstring external function f_dec_choice(inout bitstring x, out Choice y) return integer with { extension "prototype(sliding) decode(PER)" }; -// Test 15. +// Test 18. // Encoding an ASN.1 type with JSON (built-in) and decoding the same type with PER (manual). testcase tc_asn_mixed() runs on CT { @@ -478,14 +551,17 @@ control { execute(tc_custom2()); execute(tc_custom3()); execute(tc_custom4()); + execute(tc_custom5()); execute(tc_custom_temp()); execute(tc_custom_unichar()); execute(tc_custom_param_redirect()); execute(tc_custom_decmatch()); execute(tc_asn()); + execute(tc_asn2()); execute(tc_asn_param_redirect()); execute(tc_asn_decmatch()); execute(tc_per()); + execute(tc_per2()); execute(tc_per_param_redirect()); execute(tc_per_decmatch()); execute(tc_asn_mixed()); diff --git a/regression_test/customEncoding/Custom3.ttcn b/regression_test/customEncoding/Custom3.ttcn index bd3db629b5523279f59087913e32758753c811f1..2b876d4e3c619a94d96d8c0d5b97862e02e9d001 100644 --- a/regression_test/customEncoding/Custom3.ttcn +++ b/regression_test/customEncoding/Custom3.ttcn @@ -22,4 +22,13 @@ with { encode "localCustom"; } +// Set type for test 5 +type set Set { + integer num, + charstring str +} +with { + encode "localCustom"; +} + } diff --git a/regression_test/customEncoding/Custom4.ttcn b/regression_test/customEncoding/Custom4.ttcn index aa9cec62b677fa8160b8172abf16d7e209c7d9f7..5eb3a78272ecb0fda87fd611799199fb674e3b79 100644 --- a/regression_test/customEncoding/Custom4.ttcn +++ b/regression_test/customEncoding/Custom4.ttcn @@ -19,7 +19,7 @@ import from Custom2 all; import from Custom3 all; import from Types all; -// Test 16 (RT2 only). +// Test 19 (RT2 only). // Using custom encoding on a decoded value redirect. // Same input value as in test 1. testcase tc_custom_value_redirect() runs on CT @@ -50,7 +50,7 @@ testcase tc_custom_value_redirect() runs on CT } } -// Test 17 (RT2 only). +// Test 20 (RT2 only). // The redirected value is decoded into a value of ASN.1 type Seq. // Same input value as in test 8. testcase tc_asn_value_redirect() runs on CT @@ -80,7 +80,7 @@ testcase tc_asn_value_redirect() runs on CT } } -// Test 18 (RT2 only). +// Test 21 (RT2 only). // The redirected value is decoded using the PER coder. // Same input value as in test 11. testcase tc_per_value_redirect() runs on CT diff --git a/regression_test/customEncoding/Custom5.ttcn b/regression_test/customEncoding/Custom5.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..a15dc54be4c56588e8ef8628d54f6877d6abb376 --- /dev/null +++ b/regression_test/customEncoding/Custom5.ttcn @@ -0,0 +1,40 @@ +/****************************************************************************** + * Copyright (c) 2000-2016 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: + * Baranyi, Botond + * + ******************************************************************************/ + +module Custom5 { + +import from Custom3 all; +import from Types all; + +// Coding function declarations for test 5 +external function f_enc_set(in Set x) return bitstring + with { extension "prototype(convert) encode(localCustom)" } + +external function f_dec_set(inout bitstring b, out Set x) return integer + with { extension "prototype(sliding) decode(localCustom)" } + +// these let encvalue and decvalue know which encoding to use for the ASN.1 type +external function f_enc_set2(in Set2 x) return octetstring + with { extension "prototype(convert) encode(JSON)" }; + +external function f_dec_set2(in octetstring x) return Set2 + with { extension "prototype(convert) decode(JSON)" }; + +// PER coder functions, these need to be implemented manually, just like custom +// coder functions +external function f_enc_setof(in SetOf x) return bitstring + with { extension "prototype(convert) encode(PER)" }; + +external function f_dec_setof(inout bitstring x, out SetOf y) return integer + with { extension "prototype(sliding) decode(PER)" }; + +} diff --git a/regression_test/customEncoding/Makefile b/regression_test/customEncoding/Makefile index fee2198833b40b7655a1230a50cd0bb7655a999a..d5918ca7a2e932fe641f236287116ed815951592 100644 --- a/regression_test/customEncoding/Makefile +++ b/regression_test/customEncoding/Makefile @@ -19,7 +19,7 @@ include $(TOPDIR)/Makefile.regression TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) -TTCN3_MODULES = Custom1.ttcn Custom2.ttcn Custom3.ttcn +TTCN3_MODULES = Custom1.ttcn Custom2.ttcn Custom3.ttcn Custom5.ttcn ASN1_MODULES = Types.asn ifdef RT2 diff --git a/regression_test/customEncoding/Types.asn b/regression_test/customEncoding/Types.asn index 19381f6f7671fb6209bb9e5a1e1e153b1b297ba7..985b9be590bdf0247abb33646bd33f13d71019d6 100644 --- a/regression_test/customEncoding/Types.asn +++ b/regression_test/customEncoding/Types.asn @@ -23,8 +23,15 @@ Seq ::= SEQUENCE { str VisibleString } +Set2 ::= SET { + num INTEGER, + str VisibleString +} + SeqOf ::= SEQUENCE OF INTEGER +SetOf ::= SEQUENCE OF INTEGER + Choice ::= CHOICE { num INTEGER, str VisibleString diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index bcc45dba3bec8710cc977b1a0f89f11f560850f0..15fc4ee927bfaf29d17338f71fc9d0a6530809b7 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ