diff --git a/compiler2/AST.cc b/compiler2/AST.cc index 77b889de39ca18d17cadbddd0abbf254a3a56234..3f57d065e5d7c6a3e70f24ae8691186a8eef1288 100644 --- a/compiler2/AST.cc +++ b/compiler2/AST.cc @@ -305,6 +305,13 @@ namespace Common { void Modules::delay_type_encode_check(Type* p_type, 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]->enc == p_encode) { + // it's already in the list of delayed checks + return; + } + } type_enc_t* elem = new type_enc_t; elem->t = p_type; elem->enc = p_encode; diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 491eed4ce7146d8f9b06271bc4e1e6950a1a085b..58e901530dd551122c9733484dd0108a075992ed 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -607,10 +607,8 @@ namespace Common { chk_finished = false; pard_type_instance = false; needs_any_from_done = false; - encoding_by_function = false; - decoding_by_function = false; - asn_encoding = CT_UNDEF; - asn_decoding = CT_UNDEF; + default_encoding.type = CODING_UNSET; + default_decoding.type = CODING_UNSET; } void Type::clean_up() @@ -4396,60 +4394,70 @@ namespace Common { } } - void Type::set_coding_function(bool encode, const string& function_name) - { - string& coding_function = encode ? encoding_function : decoding_function; - MessageEncodingType_t& asn_coding = encode ? asn_encoding : asn_decoding; - bool& coding_by_function = encode ? - encoding_by_function : decoding_by_function; - if (!coding_function.empty()) { - // leave coding_by_function as true, this will indicate that there are - // multiple coding functions set - coding_function.clear(); + void Type::set_coding_function(bool encode, Assignment* function_def) + { + if (function_def == NULL) { + FATAL_ERROR("Type::set_coding_function"); } - else if (asn_coding != CT_UNDEF) { - // a different encoding type is already set for the ASN.1 type - asn_coding = CT_MULTIPLE; - coding_function.clear(); - return; + coding_t& coding = encode ? default_encoding : default_decoding; + if (coding.type == CODING_UNSET) { + // no coding method has been set yet -> OK + coding.type = CODING_BY_FUNCTION; + coding.function_def = function_def; } else { - if (is_asn1()) { - asn_coding = CT_PER; - } - coding_function = function_name; - coding_by_function = true; + // something has already been set -> not OK + // (the type might never be encoded/decoded, so don't report an error yet) + coding.type = CODING_MULTIPLE; } } void Type::set_asn_coding(bool encode, Type::MessageEncodingType_t new_coding) { - MessageEncodingType_t& coding = encode ? asn_encoding : asn_decoding; - bool& coding_by_function = encode ? - encoding_by_function : decoding_by_function; // true = PER coder is set - string& coding_function = encode ? encoding_function : decoding_function; // PER coder - if (coding == CT_UNDEF && !coding_by_function) { - // this is the first encoding/decoding function for this type, store it - // (also, no PER coders have been set for the type yet) - coding = new_coding; + coding_t& coding = encode ? default_encoding : default_decoding; + if (coding.type == CODING_UNSET) { + // no coding method has been set yet -> OK + coding.type = CODING_BUILT_IN; + coding.built_in_coding = new_coding; } - else if (coding != new_coding || coding_by_function) { - // there are several encoding/decoding functions declared for this type - // with different codings (encvalue/decvalue cannot be used in this case) - coding_function.clear(); - coding = CT_MULTIPLE; + else if (coding.type != CODING_BUILT_IN || + coding.built_in_coding != new_coding) { + // a different codec or a coder function has already been set -> not OK + // (the type might never be encoded/decoded, so don't report an error yet) + coding.type = CODING_MULTIPLE; } } void Type::chk_coding(bool encode, bool delayed /* = false */) { - string& coding_str = encode ? encoding_str : decoding_str; - if (!coding_str.empty()) + coding_t& coding = encode ? default_encoding : default_decoding; + switch (coding.type) { + case CODING_BY_FUNCTION: + 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); + } return; - bool& coding_by_function = encode ? - encoding_by_function : decoding_by_function; - Type::MessageEncodingType_t coding = CT_UNDEF; + case CODING_UNSET: + if (!delayed) { + // this is the only case in the switch that doesn't return immediately + break; + } + // else fall through + case CODING_MULTIPLE: + error("Cannot determine the %s rules for type `%s'. " + "%s %s external functions found%s", encode ? "encoding" : "decoding", + get_typename().c_str(), coding.type == CODING_UNSET ? "No" : "Multiple", + encode ? "encoding" : "decoding", + (coding.type == CODING_MULTIPLE && is_asn1()) ? " with different rules" : ""); + return; + default: + FATAL_ERROR("Type::chk_coding"); + } - if (!is_asn1()) { + if (!is_asn1()) { // TTCN-3 types if (!w_attrib_path) { error("No coding rule specified for type '%s'", get_typename().c_str()); return; @@ -4484,17 +4492,19 @@ namespace Common { { if (target->get_mapping_type() == Ttcn::TypeMappingTarget::TM_FUNCTION) { - if (!coding_str.empty()) + if (coding.type != CODING_UNSET) { target->error("Multiple definition of this target"); - coding_str = target->get_function()-> - get_genname_from_scope(my_scope); - coding_by_function = true; + } + else { + coding.type = CODING_BY_FUNCTION; + coding.function_def = target->get_function(); + } } else { target->error("Only function is supported to do this mapping"); } } } - if (coding_str.empty()) { + if (coding.type == CODING_UNSET) { ea.warning("Extension attribute is found for %s but without " "typemappings", encode ? "encvalue" : "decvalue"); } @@ -4516,7 +4526,7 @@ namespace Common { delete extatrs; } - if (!coding_str.empty()) + if (coding.type != CODING_UNSET) return; end_ext: @@ -4527,107 +4537,83 @@ namespace Common { if (real_attribs[i-1]->get_attribKeyword() == SingleWithAttrib::AT_ENCODE) { found = true; - coding = get_enc_type(*real_attribs[i-1]); + coding.type = CODING_BUILT_IN; + coding.built_in_coding = get_enc_type(*real_attribs[i-1]); } } - if (coding == CT_UNDEF) { + if (coding.type == CODING_UNSET) { // no "encode" attribute found error("No coding rule specified for type '%s'", get_typename().c_str()); return; } - } - else { // ASN.1 type - coding = encode ? asn_encoding : asn_decoding; - if ((coding == CT_UNDEF && delayed) || coding == CT_MULTIPLE) { - // either this is the delayed call and no external functions have been - // found, or there was already more than one function - error("Cannot determine the %s rules for ASN.1 type `%s'. " - "%s %s external functions found%s", encode ? "encoding" : "decoding", - get_typename().c_str(), coding == CT_UNDEF ? "No" : "Multiple", - encode ? "encoding" : "decoding", - coding == CT_UNDEF ? "" : " with different rules"); - return; - } - if (!delayed) { - // there have been no errors so far in determining the coding type, - // but there might still be unchecked external functions out there; + if (coding.built_in_coding == CT_CUSTOM) { + // 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); - return; + // set the coding type back to UNSET for delayed call + coding.type = CODING_UNSET; + } + else if (!has_encoding(coding.built_in_coding)) { + error("Type '%s' cannot be coded with the selected method '%s'", + get_typename().c_str(), get_encoding_name(coding.built_in_coding)); } } - if (coding != CT_CUSTOM && !has_encoding(coding)) { - error("Type '%s' cannot be coded with the selected method '%s'", - get_typename().c_str(), - get_encoding_name(coding)); - return; - } - switch (coding) { - case CT_RAW: - coding_str = "RAW"; - break; - case CT_TEXT: - coding_str = "TEXT"; - break; - case CT_XER: - coding_str = "XER, XER_EXTENDED"; // TODO: fine tuning this parameter - break; - case CT_JSON: - coding_str = "JSON, FALSE"; // with compact printing - break; - case CT_BER: { - coding_str = "BER, "; - BerAST* ber = berattrib; - if (!ber) // use default settings if attributes are not specified - ber = new BerAST; - if (encode) - coding_str += ber->get_encode_str(); - else - coding_str += ber->get_decode_str(); - if (!berattrib) - delete ber; - break; } - case CT_PER: - case CT_CUSTOM: { - // the coding function is set by its semantic checker in this case - string& coding_function = encode ? encoding_function : decoding_function; - if (coding_function.empty() && coding_by_function) { - error("Multiple %s %s functions set for type `%s'", - get_encoding_name(coding), encode ? "encoding" : "decoding", - get_typename().c_str()); - } - else if (!delayed) { - // there have been no errors so far in determining the coding function, - // 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); - } - else if (coding_function.empty()) { - // this is the delayed call, and the coding function has still not been set - error("No %s %s function found for type `%s'", get_encoding_name(coding), - encode ? "encoding" : "decoding", get_typename().c_str()); - } - else { - // this is the delayed call, and exactly one coding function has been set - coding_str = coding_function; - } - return; } - default: - error("Unknown coding selected for type '%s'", get_typename().c_str()); - break; + 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); } - coding_by_function = false; } bool Type::is_coding_by_function(bool encode) const { - return encode ? encoding_by_function : decoding_by_function; + return (encode ? default_encoding : default_decoding).type == CODING_BY_FUNCTION; } - - const string& Type::get_coding(bool encode) const { - if (encode) - return encoding_str; - else - return decoding_str; + + string Type::get_coding(bool encode) const + { + const coding_t& coding = encode ? default_encoding : default_decoding; + if (coding.type != CODING_BUILT_IN) { + FATAL_ERROR("Type::get_built_in_coding"); + } + switch (coding.built_in_coding) { + case CT_RAW: + return string("RAW"); + case CT_TEXT: + return string("TEXT"); + case CT_XER: + return string("XER, XER_EXTENDED"); // TODO: fine tuning this parameter + case CT_JSON: + if (encode) { + return string("JSON, FALSE"); // with compact printing + } + else { + return string("JSON"); + } + case CT_BER: { + string coding_str = string("BER, "); + BerAST* ber = berattrib; + if (!ber) // use default settings if attributes are not specified + ber = new BerAST; + if (encode) + coding_str += ber->get_encode_str(); + else + coding_str += ber->get_decode_str(); + if (!berattrib) + delete ber; + return coding_str; } + default: + FATAL_ERROR("Type::get_built_in_coding"); + } + } + + Assignment* Type::get_coding_function(bool encode) const + { + const coding_t& coding = encode ? default_encoding : default_decoding; + if (coding.type != CODING_BY_FUNCTION) { + FATAL_ERROR("Type::get_coding_function"); + } + return coding.function_def; } namespace { // unnamed diff --git a/compiler2/Type.hh b/compiler2/Type.hh index c1e442cc4ef96eeeaa3b239ef39dab592df1cbdf..b24291fb35159d6638d432780c246c98a54e5c6e 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -114,6 +114,7 @@ namespace Common { class SignatureParamList; class SignatureExceptions; class CodeGenHelper; + class Assignment; /** * This is the base class for types. @@ -195,14 +196,13 @@ namespace Common { */ enum MessageEncodingType_t { CT_UNDEF, /**< undefined/unused */ - CT_BER, /**< ASN.1 BER */ - CT_PER, /**< ASN.1 PER (not supported yet) */ - CT_RAW, /**< TTCN-3 RAW */ - CT_TEXT, /**< TTCN-3 TEXT */ - CT_XER, /**< ASN.1 XER */ - CT_JSON, /**< TTCN-3 JSON */ - CT_CUSTOM, /**< user defined encoding */ - CT_MULTIPLE /**< multiple codings defined for an ASN.1 type */ + CT_BER, /**< ASN.1 BER (built-in) */ + CT_PER, /**< ASN.1 PER (through user defined coder functions) */ + CT_RAW, /**< TTCN-3 RAW (built-in) */ + CT_TEXT, /**< TTCN-3 TEXT (built-in) */ + CT_XER, /**< TTCN-3 XER (built-in) */ + CT_JSON, /**< TTCN-3 and ASN.1 JSON (built-in) */ + CT_CUSTOM /**< user defined encoding (through user defined coder functions) */ }; /** selector for value checking algorithms */ @@ -225,7 +225,7 @@ namespace Common { }; /** Enumeration to represent the owner of the type. - * Also align OT_UNKNOWN at line 200. */ + */ enum TypeOwner_t { OT_UNKNOWN, OT_TYPE_ASS, ///< ASN.1 type assignment (Ass_T) @@ -261,6 +261,31 @@ namespace Common { OT_SIG_PAR, ///< signature parameter (SignatureParam) OT_POOL ///< It's a pool type, owned by the type pool }; + + /** + * Enumeration to represent the default method of encoding or decoding for a type. + */ + enum coding_type_t { + CODING_UNSET, ///< No encoding/decoding method has been set for the type. + CODING_BUILT_IN, ///< The type uses a built-in codec for encoding/decoding. + CODING_BY_FUNCTION, ///< The type uses a user defined function for encoding/decoding. + CODING_MULTIPLE ///< Multiple encoding/decoding methods have been set for the type. + }; + + /** + * Structure containing the default encoding or decoding settings for a type. + * These settings determine how values of the type are encoded or decoded by + * the following TTCN-3 language elements: + * 'encvalue' (encode), 'encvalue_unichar' (encode), 'decvalue' (decode), + * 'decvalue_unichar' (decode), 'decmatch' (decode) and '@decoded' (decode). + */ + struct coding_t { + coding_type_t type; ///< Type of encoding/decoding + union { + MessageEncodingType_t built_in_coding; ///< Built-in codec (if type is CODING_BUILT_IN) + Assignment* function_def; ///< Pointer to external function definition (if type is CODING_BY_FUNCTION) + }; + }; /** Returns the display string of \a encoding_type. */ static const char *get_encoding_name(MessageEncodingType_t encoding_type); @@ -305,14 +330,9 @@ namespace Common { vector<SubTypeParse> *parsed_restr; ///< parsed subtype restrictions are stored here until they are moved to the sub_type member SubType *sub_type; ///< effective/aggregate subtype of this type, NULL if neither inherited nor own subtype restrictions exist - string encoding_str; // needed by codegen for encvalue() and decvalue() - string decoding_str; - bool encoding_by_function; // false - coding attribute is set, true - coding via coding function - bool decoding_by_function; // same for decoding - string encoding_function; // name of custom or PER encoder - string decoding_function; // name of custom or PER decoder - MessageEncodingType_t asn_encoding; // set by the semantic analysis of encoding - MessageEncodingType_t asn_decoding; // and decoding external functions for ASN.1 types + coding_t default_encoding; ///< default settings for encoding values of this type + coding_t default_decoding; ///< default settings for decoding values of this type + /** What kind of AST element owns the type. * It may not be known at creation type, so it's initially OT_UNKNOWN. * We want this information so we don't have to bother with XER @@ -658,12 +678,35 @@ namespace Common { bool is_list_type(bool allow_array); /** Sets the encoding or decoding function for the type (in case of custom - * encoding). */ - void set_coding_function(bool encode, const string& function_name); + * or PER encoding). */ + void set_coding_function(bool encode, Assignment* function_def); + + /** Sets the codec to use when encoding or decoding the ASN.1 type */ void set_asn_coding(bool encode, MessageEncodingType_t new_coding); + + /** Determines the method of encoding or decoding for values of this type + * based on its attributes and on encoder or decoder function definitions + * with this type as their input or output. An error is displayed if the + * coding method cannot be determined. + * + * @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); + + /** Indicates whether the type is encoded/decoded by a function or by a + * built-in codec. */ bool is_coding_by_function(bool encode) const; - const string& get_coding(bool encode) const; + + /** Returns the string representation of the type's default codec. + * Used during code generation for types encoded/decoded by a built-in + * codec. */ + string get_coding(bool encode) const; + + /** Returns the function definition of the type's encoder/decoder function. + * Used during code generation for types encoded/decoded by functions. */ + Assignment* get_coding_function(bool encode) const; + private: static MessageEncodingType_t get_enc_type(const Ttcn::SingleWithAttrib& enc); diff --git a/compiler2/Value.cc b/compiler2/Value.cc index cf273f8a624020f5947d76cbde328a935dc11495..470a6870f73b8189194caa5b7337453160f033de 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -12970,6 +12970,7 @@ error: break; } + Scope* scope = u.expr.ti1->get_Template()->get_my_scope(); if (!gov_last->is_coding_by_function(true)) { const string& tmp_id = get_temporary_id(); const string& tmp_buf_id = get_temporary_id(); @@ -12983,9 +12984,7 @@ error: expr->preamble = mputc (expr->preamble, '\n'); } expr->preamble = mputprintf(expr->preamble, "%s const& %s = %s", - gov_last->get_genname_typedescriptor( - u.expr.ti1->get_Template()->get_my_scope() - ).c_str(), + gov_last->get_genname_typedescriptor(scope).c_str(), tmp_ref_id.c_str(), expr2.expr); if (is_templ) // make a value out of the template, if needed @@ -12993,9 +12992,7 @@ error: expr->preamble = mputprintf(expr->preamble, ";\n%s.encode(%s_descr_, %s, TTCN_EncDec::CT_%s", tmp_ref_id.c_str(), - gov_last->get_genname_typedescriptor( - u.expr.ti1->get_Template()->get_my_scope() - ).c_str(), + gov_last->get_genname_typedescriptor(scope).c_str(), tmp_buf_id.c_str(), gov_last->get_coding(true).c_str() ); @@ -13009,8 +13006,8 @@ error: expr->postamble = mputstr(expr->postamble, expr2.postamble); } else expr->expr = mputprintf(expr->expr, "%s(%s%s)", - gov_last->get_coding(true).c_str(), expr2.expr, - is_templ ? ".valueof()" : ""); + gov_last->get_coding_function(true)->get_genname_from_scope(scope).c_str(), + expr2.expr, is_templ ? ".valueof()" : ""); Code::free_expr(&expr2); } @@ -13031,6 +13028,7 @@ error: if (expr2.preamble) expr->preamble = mputprintf(expr->preamble, "%s", expr2.preamble); + Scope* scope = u.expr.r2->get_my_scope(); if (!_type->is_coding_by_function(false)) { const string& tmp_id = get_temporary_id(); const string& buffer_id = get_temporary_id(); @@ -13052,9 +13050,7 @@ error: "%s%s.decode(%s_descr_, %s, TTCN_EncDec::CT_%s);\n", expr2.expr, optional ? "()" : "", - _type->get_genname_typedescriptor( - u.expr.r2->get_my_scope() - ).c_str(), + _type->get_genname_typedescriptor(scope).c_str(), buffer_id.c_str(), _type->get_coding(false).c_str() ); @@ -13090,7 +13086,7 @@ error: expr->expr = mputprintf(expr->expr, "%s", retval_id.c_str()); } else expr->expr = mputprintf(expr->expr, "%s(%s, %s)", - _type->get_coding(false).c_str(), expr1.expr, expr2.expr); + _type->get_coding_function(false)->get_genname_from_scope(scope).c_str(), expr1.expr, expr2.expr); if (expr1.postamble) expr->postamble = mputprintf(expr->postamble, "%s", expr1.postamble); if (expr2.postamble) @@ -13127,6 +13123,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) v2_code = generate_code_char_coding_check(expr, u.expr.v2, "encvalue_unichar"); } + Scope* scope = u.expr.ti1->get_Template()->get_my_scope(); if (!gov_last->is_coding_by_function(true)) { const string& tmp_id = get_temporary_id(); const string& tmp_buf_id = get_temporary_id(); @@ -13140,9 +13137,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) expr->preamble = mputc (expr->preamble, '\n'); } expr->preamble = mputprintf(expr->preamble, "%s const& %s = %s", - gov_last->get_genname_typedescriptor( - u.expr.ti1->get_Template()->get_my_scope() - ).c_str(), + gov_last->get_genname_typedescriptor(scope).c_str(), tmp_ref_id.c_str(), expr2.expr); if (is_templ) // make a value out of the template, if needed @@ -13150,9 +13145,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) expr->preamble = mputprintf(expr->preamble, ";\n%s.encode(%s_descr_, %s, TTCN_EncDec::CT_%s", tmp_ref_id.c_str(), - gov_last->get_genname_typedescriptor( - u.expr.ti1->get_Template()->get_my_scope() - ).c_str(), + gov_last->get_genname_typedescriptor(scope).c_str(), tmp_buf_id.c_str(), gov_last->get_coding(true).c_str() ); @@ -13172,8 +13165,8 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) expr->postamble = mputstr(expr->postamble, expr2.postamble); } else { expr->expr = mputprintf(expr->expr, "oct2unichar(bit2oct(%s(%s%s))", - gov_last->get_coding(true).c_str(), expr2.expr, - is_templ ? ".valueof()" : ""); + gov_last->get_coding_function(true)->get_genname_from_scope(scope).c_str(), + expr2.expr, is_templ ? ".valueof()" : ""); if(u.expr.v2) { expr->expr = mputprintf(expr->expr, ", %s", v2_code); } else { @@ -13205,6 +13198,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) v3_code = generate_code_char_coding_check(expr, u.expr.v3, "decvalue_unichar"); } + Scope* scope = u.expr.r2->get_my_scope(); if (!_type->is_coding_by_function(false)) { const string& tmp_id = get_temporary_id(); const string& buffer_id = get_temporary_id(); @@ -13227,9 +13221,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) "%s%s.decode(%s_descr_, %s, TTCN_EncDec::CT_%s);\n", expr2.expr, optional ? "()" : "", - _type->get_genname_typedescriptor( - u.expr.r2->get_my_scope() - ).c_str(), + _type->get_genname_typedescriptor(scope).c_str(), buffer_id.c_str(), _type->get_coding(false).c_str() ); @@ -13275,7 +13267,9 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) "%s = oct2unichar(bit2oct(%s), %s);\n", ustr_ref_id.c_str(), expr1.expr, bstr_id.c_str(), ustr_ref_id.c_str(), u.expr.v3 ? v3_code : "\"UTF-8\"", - ret_val_id.c_str(), _type->get_coding(false).c_str(), bstr_id.c_str(), expr2.expr, + ret_val_id.c_str(), + _type->get_coding_function(false)->get_genname_from_scope(scope).c_str(), + bstr_id.c_str(), expr2.expr, ustr_ref_id.c_str(), bstr_id.c_str(), u.expr.v3 ? v3_code : "\"UTF-8\""); expr->expr = mputprintf(expr->expr, "%s", ret_val_id.c_str()); } diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 38453629180a4e1b29b828ba92afdeaf88e3576f..aa181479c96824820c7eec28c79565cc9296a425 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -6569,8 +6569,7 @@ namespace Ttcn { } else { // let the input type know that this is its encoding function - input_type->get_type_refd()->set_coding_function(true, - get_genname_from_scope(input_type->get_type_refd()->get_my_scope())); + input_type->get_type_refd()->set_coding_function(true, this); // treat this as a manual external function during code generation function_type = EXTFUNC_MANUAL; } @@ -6692,8 +6691,7 @@ namespace Ttcn { } else if (output_type) { // let the output type know that this is its decoding function - output_type->get_type_refd()->set_coding_function(false, - get_genname_from_scope(output_type->get_type_refd()->get_my_scope())); + output_type->get_type_refd()->set_coding_function(false, this); // treat this as a manual external function during code generation function_type = EXTFUNC_MANUAL; } diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 8452c0229be9c81d4cdec46ba79079dbad0c11c0..a10b05ba7302b165f5955110fa91e15f3f1c249a 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -9350,8 +9350,8 @@ error: "TTCN_error(\"Parameter redirect (for parameter '%s') failed, " "because the buffer was not empty after decoding. " "Remaining bits: %%d.\", buff.lengthof());\n" - "}\n", ve->get_dec_type()->get_coding(false).c_str(), - par_name, par_name, par_name); + "}\n", ve->get_dec_type()->get_coding_function(false)-> + get_genname_from_scope(scope).c_str(), par_name, par_name, par_name); } else { // built-in decoding switch (tt) { @@ -10097,7 +10097,8 @@ error: "TTCN_error(\"Value redirect #%d failed, because the buffer was " "not empty after decoding. Remaining bits: %%d.\", " "buff_%d.lengthof());\n" - "}\n", member_type->get_coding(false).c_str(), + "}\n", member_type->get_coding_function(false)-> + get_genname_from_scope(scope).c_str(), (int)i, (int)i, (int)(i + 1), (int)i, (int)(i + 1), (int)i); } else { // built-in decoding diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index 0dc39effb84bef0efe83045f8fde3a3419f8d44f..330316ffcc92c5dfb57d43013a227202a0f56202 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -4597,7 +4597,7 @@ compile_time: "}\n" // make sure the bitstring is empty after decoding, display a warning otherwise "else if (bs.lengthof() != 0) {\n", - target_type->get_coding(false).c_str()); + target_type->get_coding_function(false)->get_genname_from_scope(my_scope).c_str()); } else { str = mputprintf(str, diff --git a/function_test/Semantic_Analyser/encode/Types_A.asn b/function_test/Semantic_Analyser/encode/Types_A.asn index 4a7fbdcdda566b8f3b262615211c702e4ed731bd..c9913de00a9c5bcf98e7bc01cfdff14496e7e826 100644 --- a/function_test/Semantic_Analyser/encode/Types_A.asn +++ b/function_test/Semantic_Analyser/encode/Types_A.asn @@ -20,7 +20,7 @@ IMPORTS; Int ::= INTEGER -Seq ::= SEQUENCE { --//Cannot determine the encoding rules for ASN.1 type `@Types-A.Seq'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for ASN.1 type `@Types-A.Seq'. Multiple decoding external functions found with different rules// +Seq ::= SEQUENCE { --//Cannot determine the encoding rules for type `@Types-A.Seq'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for type `@Types-A.Seq'. Multiple decoding external functions found with different rules// num INTEGER, str VisibleString } @@ -30,11 +30,11 @@ Set ::= SET { str VisibleString } -SeqOf ::= SEQUENCE OF INTEGER --//Multiple PER encoding functions set for type// //Multiple PER decoding functions set for type// +SeqOf ::= SEQUENCE OF INTEGER --//Cannot determine the encoding rules for type `@Types-A.SeqOf'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for type `@Types-A.SeqOf'. Multiple decoding external functions found with different rules// SetOf ::= SET OF INTEGER -Choice ::= CHOICE { --//Cannot determine the encoding rules for ASN.1 type `@Types-A.Choice'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for ASN.1 type `@Types-A.Choice'. No decoding external functions found// +Choice ::= CHOICE { --//Cannot determine the encoding rules for type `@Types-A.Choice'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for type `@Types-A.Choice'. No decoding external functions found// num INTEGER, str VisibleString } diff --git a/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn index 74ad46d660c70d02027d1378e143f3694ae7c4b8..ad675829bf74878bdb76d237fe8d8575cca76afd 100644 --- a/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn +++ b/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn @@ -84,9 +84,9 @@ external function f_enc_seqof2(in SeqOf x) return bitstring external function f_dec_seqof1(inout bitstring x, out SeqOf y) return integer with { extension "prototype(sliding) decode(PER)" } -function f3() { +function f3() { //^In function definition// var SeqOf x := { 1, 2 }; - var bitstring y := encvalue(x); + var bitstring y := encvalue(x); //^In variable definition// //^In the parameter of encvalue// var integer res := decvalue(y, x); } diff --git a/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn index 1de761b6d15f61ff095bcb69eaa84066fceb3a7a..e59db46b6ce82dc2b88bc28a161614a2d2768068 100644 --- a/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn +++ b/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn @@ -14,9 +14,9 @@ module encode_ttcn_SE { //^In TTCN-3 module// /* types with no coder functions */ -type integer AnInt with { encode "nonexistent" }; //^error\: No custom decoding function found for type// +type integer AnInt with { encode "nonexistent" }; //Cannot determine the decoding rules for type `integer'. No decoding external functions found// -type record ARecord { //^error\: No custom decoding function found for type// +type record ARecord { //Cannot determine the decoding rules for type `@encode_ttcn_SE.ARecord'. No decoding external functions found// integer i, octetstring os } @@ -54,7 +54,7 @@ external function f_dec_list4(inout charstring x, out AList y) return integer // /* type with multiple custom coding functions */ -type union AUnion { //Multiple custom encoding functions set for type// //Multiple custom decoding functions set for type// +type union AUnion { //Cannot determine the encoding rules for type `@encode_ttcn_SE.AUnion'. Multiple encoding external functions found// //Cannot determine the decoding rules for type `@encode_ttcn_SE.AUnion'. Multiple decoding external functions found// octetstring field } with { diff --git a/regression_test/customEncoding/Coders.cc b/regression_test/customEncoding/Coders.cc index 9fc5647d3b42ca6aeaac7591b7cd63c1ce2f1bbe..4318f4ed87d9a6496486ed4cd8d93119bd9eeac1 100644 --- a/regression_test/customEncoding/Coders.cc +++ b/regression_test/customEncoding/Coders.cc @@ -58,6 +58,18 @@ INTEGER f__dec__uni(BITSTRING& b, Custom1::Uni& x) } } +BITSTRING f__enc__bs(const BITSTRING& x) +{ + return x; +} + +INTEGER f__dec__bs(BITSTRING& b, BITSTRING& x) +{ + x = b; + b = BITSTRING(0, NULL); + return 0; +} + } // namespace Custom2 namespace Custom1 { diff --git a/regression_test/customEncoding/Coders.hh b/regression_test/customEncoding/Coders.hh index ba40254300d3fd9d0c9b47c77d4f3c9f1ea06480..ca2af2acf901afb62790ad063a4e338915741973 100644 --- a/regression_test/customEncoding/Coders.hh +++ b/regression_test/customEncoding/Coders.hh @@ -27,6 +27,9 @@ 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); +BITSTRING f__enc__bs(const BITSTRING& x); +INTEGER f__dec__bs(BITSTRING& b, BITSTRING& x); + } namespace Custom1 { diff --git a/regression_test/customEncoding/Custom1.ttcn b/regression_test/customEncoding/Custom1.ttcn index 168ecaef8cce7f72b53fd6a56ff0aa3b87679370..4832eadb9123a958fa788834e725a21fe3940025 100644 --- a/regression_test/customEncoding/Custom1.ttcn +++ b/regression_test/customEncoding/Custom1.ttcn @@ -142,6 +142,29 @@ testcase tc_custom3() runs on CT } // Test 4. +// The encoded type and the coding functions are in another module (in the same other module). +testcase tc_custom4() runs on CT +{ + var BitString x := '10010110'B; + var bitstring enc_exp := x; + var BitString dec_exp := x; + + var bitstring enc := encvalue(x); + if (enc != enc_exp) { + setverdict(fail, "Expected: ", enc_exp, ", got: ", enc); + } + var BitString 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 5. // Using encvalue on templates and template variables // Same type and encoding function as test 1 testcase tc_custom_temp() runs on CT @@ -162,7 +185,7 @@ testcase tc_custom_temp() runs on CT setverdict(pass); } -// Test 5. +// Test 6. // 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 @@ -186,7 +209,7 @@ testcase tc_custom_unichar() runs on CT setverdict(pass); } -// Test 6. +// Test 7. // Using custom encoding on a decoded parameter redirect. // Same input value as in test 5. testcase tc_custom_param_redirect() runs on CT @@ -217,7 +240,7 @@ testcase tc_custom_param_redirect() runs on CT } } -// Test 7. +// Test 8. // Using custom encoding in a template with decoded content matching. // Same input as test 3. testcase tc_custom_decmatch() runs on CT @@ -249,7 +272,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 8. +// Test 9. // Using encvalue and decvalue on the ASN.1 type Seq (with JSON encoding). testcase tc_asn() runs on CT { @@ -272,7 +295,7 @@ testcase tc_asn() runs on CT setverdict(pass); } -// Test 9. +// Test 10. // 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 @@ -303,7 +326,7 @@ testcase tc_asn_param_redirect() runs on CT } } -// Test 10. +// Test 11. // 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 @@ -336,7 +359,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 11. +// Test 12. // PER coder with encvalue and decvalue. testcase tc_per() runs on CT { @@ -360,7 +383,7 @@ testcase tc_per() runs on CT setverdict(pass); } -// Test 12. +// Test 13. // The redirected parameter is decoded using the PER coder. // Same input value as in test 11. testcase tc_per_param_redirect() runs on CT @@ -391,7 +414,7 @@ testcase tc_per_param_redirect() runs on CT } } -// Test 13. +// Test 14. // Decoded content matching with the PER coder. // Same input value as in test 11. testcase tc_per_decmatch() runs on CT @@ -424,7 +447,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 14. +// Test 15. // Encoding an ASN.1 type with JSON (built-in) and decoding the same type with PER (manual). testcase tc_asn_mixed() runs on CT { @@ -454,6 +477,7 @@ control { execute(tc_custom1()); execute(tc_custom2()); execute(tc_custom3()); + execute(tc_custom4()); execute(tc_custom_temp()); execute(tc_custom_unichar()); execute(tc_custom_param_redirect()); diff --git a/regression_test/customEncoding/Custom2.ttcn b/regression_test/customEncoding/Custom2.ttcn index 0b30a289f41cecc60b8d883931d9959b1c40496d..b14a6b5054914906837b95884565f7cf0d91370b 100644 --- a/regression_test/customEncoding/Custom2.ttcn +++ b/regression_test/customEncoding/Custom2.ttcn @@ -30,4 +30,14 @@ external function f_enc_uni(in Uni x) return bitstring external function f_dec_uni(inout bitstring b, out Uni x) return integer with { extension "prototype(sliding) decode(globalCustom)" } +// Type for test 4 +type bitstring BitString with { encode "nothing" }; + +// Coding function declarations for test 4 +external function f_enc_bs(in BitString x) return bitstring + with { extension "prototype(convert) encode(nothing)" } + +external function f_dec_bs(inout bitstring b, out BitString x) return integer + with { extension "prototype(sliding) decode(nothing)" } + } diff --git a/regression_test/customEncoding/Custom4.ttcn b/regression_test/customEncoding/Custom4.ttcn index 9a6bfbe50f5a180d92d7efb22f9ec0b4d251ad8b..aa9cec62b677fa8160b8172abf16d7e209c7d9f7 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 15 (RT2 only). +// Test 16 (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 16 (RT2 only). +// Test 17 (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 17 (RT2 only). +// Test 18 (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