diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 51d99b69fa9fd320617b6e0db7f01a20c4b73fc2..648250cd6434cc50087508472fcf50234dffc261 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -773,6 +773,16 @@ namespace Common { for (size_t i = 0; i < coding_table.size(); ++i) { if (!coding_table[i]->built_in) { Free(coding_table[i]->custom_coding.name); + for (size_t j = 0; j < coding_table[i]->custom_coding.encoders->size(); ++j) { + delete coding_table[i]->custom_coding.encoders->get_nth_elem(j); + } + coding_table[i]->custom_coding.encoders->clear(); + delete coding_table[i]->custom_coding.encoders; + for (size_t j = 0; j < coding_table[i]->custom_coding.decoders->size(); ++j) { + delete coding_table[i]->custom_coding.decoders->get_nth_elem(j); + } + coding_table[i]->custom_coding.decoders->clear(); + delete coding_table[i]->custom_coding.decoders; } delete coding_table[i]; } @@ -3128,7 +3138,7 @@ namespace Common { if (err) { if (last->typetype == T_ENUM_T) { error("Invalid JSON default value for enumerated type `%s'", - last->get_stringRepr().c_str()); + last->get_typename().c_str()); } else { error("Invalid %s JSON default value", get_typename_builtin(last->typetype)); } @@ -3293,11 +3303,9 @@ namespace Common { else { coding_t* new_coding = new coding_t; new_coding->built_in = FALSE; - new_coding->custom_coding.enc_func = NULL; - new_coding->custom_coding.enc_conflict = FALSE; - new_coding->custom_coding.dec_func = NULL; - new_coding->custom_coding.dec_conflict = FALSE; new_coding->custom_coding.name = mcopystr(name.c_str()); + new_coding->custom_coding.encoders = new map<Type*, coder_function_t>; + new_coding->custom_coding.decoders = new map<Type*, coder_function_t>; coding_table.add(new_coding); } } @@ -3308,19 +3316,24 @@ namespace Common { if (legacy_codec_handling) { FATAL_ERROR("Type::set_coding_function"); } - // TODO: the coding table might be in a referenced type - for (size_t i = 0; i < coding_table.size(); ++i) { - if (!coding_table[i]->built_in && - strcmp(coding_table[i]->custom_coding.name, coding_name) == 0) { - Assignment*& func_ptr = encode ? coding_table[i]->custom_coding.enc_func : - coding_table[i]->custom_coding.dec_func; - boolean& conflict = encode ? coding_table[i]->custom_coding.enc_conflict : - coding_table[i]->custom_coding.dec_conflict; - if (func_ptr != NULL) { - conflict = TRUE; + Type* t = get_type_w_coding_table(); + if (t == NULL) { + return; + } + for (size_t i = 0; i < t->coding_table.size(); ++i) { + if (!t->coding_table[i]->built_in && + strcmp(t->coding_table[i]->custom_coding.name, coding_name) == 0) { + map<Type*, coder_function_t>* coders = encode ? + t->coding_table[i]->custom_coding.encoders : + t->coding_table[i]->custom_coding.decoders; + if (coders->has_key(this)) { + (*coders)[this]->conflict = TRUE; } - else if (!conflict) { - func_ptr = function_def; + else { + coder_function_t* new_coder = new coder_function_t; + new_coder->func_def = function_def; + new_coder->conflict = FALSE; + coders->add(this, new_coder); Common::Module* func_mod = function_def->get_my_scope()->get_scope_mod(); Common::Module* type_mod = my_scope->get_scope_mod(); if (func_mod != type_mod) { @@ -3347,6 +3360,32 @@ namespace Common { } } + Type::coder_function_t* Type::get_coding_function(size_t index, boolean encode) + { + if (legacy_codec_handling) { + FATAL_ERROR("Type::get_coding_function"); + } + Type* t_ct = get_type_w_coding_table(); + if (t_ct == NULL || t_ct->coding_table.size() <= index || + t_ct->coding_table[index]->built_in) { + FATAL_ERROR("Type::get_coding_function"); + } + map<Type*, coder_function_t>* coders = encode ? + t_ct->coding_table[index]->custom_coding.encoders : + t_ct->coding_table[index]->custom_coding.decoders; + if (coders->has_key(this)) { + return (*coders)[this]; + } + Type* t = this; + while (t->is_ref()) { + t = t->get_type_refd(); + if (coders->has_key(t)) { + return (*coders)[t]; + } + } + return NULL; // not found + } + Type* Type::get_type_w_coding_table() { // only return the type if it has a non-empty coding table @@ -4957,25 +4996,22 @@ namespace Common { if (!t->coding_table[i]->built_in) { // all user-defined encodings must have exactly one encoder/decoder // function set - boolean& conflict = encode ? t->coding_table[i]->custom_coding.enc_conflict : - t->coding_table[i]->custom_coding.dec_conflict; - if (conflict) { - error("Multiple `%s' %scoder functions defined for type `%s'", - t->coding_table[i]->custom_coding.name, encode ? "en" : "de", - get_typename().c_str()); - // TODO: don't display this twice (once in the normal call and once in the delayed call) - continue; - } if (!delayed) { // there might still be unchecked external functions, so the check // must be delayed until everything else has been checked Modules::delay_type_encode_check(this, usage_mod, encode); return; } - Assignment* func_def = encode ? t->coding_table[i]->custom_coding.enc_func : - t->coding_table[i]->custom_coding.dec_func; - if (func_def == NULL && !is_asn1()) { - warning("No `%s' %scoder function defined for type `%s'", + coder_function_t* coding_func = get_coding_function(i, encode); + if (coding_func == NULL) { + if (!t->is_asn1()) { + warning("No `%s' %scoder function defined for type `%s'", + t->coding_table[i]->custom_coding.name, encode ? "en" : "de", + get_typename().c_str()); + } + } + else if (coding_func->conflict) { + warning("Multiple `%s' %scoder functions defined for type `%s'", t->coding_table[i]->custom_coding.name, encode ? "en" : "de", get_typename().c_str()); } @@ -5187,7 +5223,7 @@ namespace Common { } } - Assignment* Type::get_coding_function(bool encode) const + Assignment* Type::get_legacy_coding_function(bool encode) const { if (!legacy_codec_handling) { FATAL_ERROR("Type::get_coding_function"); @@ -6220,8 +6256,10 @@ namespace Common { } } Type* last = get_type_refd_last(); - if (last->is_structured_type() || last->get_typetype_ttcn3() == T_ENUM_T) { - // these types need an 'encode' attribute + if (encoding_type == CT_CUSTOM || + last->is_structured_type() || last->get_typetype_ttcn3() == T_ENUM_T) { + // these types need an 'encode' attribute for built-in codecs, and all + // types need an 'encode' attribute for user-defined codecs return false; } return last->can_have_coding(encoding_type); @@ -7147,6 +7185,10 @@ namespace Common { FATAL_ERROR("Type::get_genname_coder"); } Type* t = this; + Type* t_ct = get_type_w_coding_table(); + if (t_ct == NULL) { + return string(); + } for ( ; ; ) { // if the type has an 'encode' or 'variant' attribute, then it needs its // own coder functions @@ -7155,6 +7197,15 @@ namespace Common { (t->xerattrib && !t->xerattrib->empty())) { return t->get_genname_own(p_scope); } + // if it has its own custom encoder or decoder functions set, then it needs + // its own coder functions + for (size_t i = 0; i < t_ct->coding_table.size(); ++i) { + if (!t_ct->coding_table[i]->built_in && + (t_ct->coding_table[i]->custom_coding.encoders->has_key(t) || + t_ct->coding_table[i]->custom_coding.decoders->has_key(t))) { + return t->get_genname_own(p_scope); + } + } if (t->is_ref()) { t = t->get_type_refd(); } @@ -7648,12 +7699,24 @@ namespace Common { get_encoding_name(coding_table[i]->built_in_coding)); } else { - Assignment* enc_func = coding_table[i]->custom_coding.enc_func; - Assignment* def_func = coding_table[i]->custom_coding.dec_func; - DEBUG(level + 1, "%s (encoder: %s, decoder: %s)", - coding_table[i]->custom_coding.name, - (enc_func != NULL) ? enc_func->get_fullname().c_str() : "<unset>", - (def_func != NULL) ? def_func->get_fullname().c_str() : "<unset>"); + DEBUG(level + 1, "%s (user-defined)", + coding_table[i]->custom_coding.name); + DEBUG(level + 1, "Encoders:"); + map<Type*, coder_function_t>* encoders = coding_table[i]->custom_coding.encoders; + for (size_t j = 0; j < encoders->size(); ++j) { + DEBUG(level + 2, "Type: %s, function: %s", + encoders->get_nth_key(j)->get_fullname().c_str(), + encoders->get_nth_elem(j)->conflict ? "<multiple>" : + encoders->get_nth_elem(j)->func_def->get_fullname().c_str()); + } + DEBUG(level + 1, "Decoders:"); + map<Type*, coder_function_t>* decoders = coding_table[i]->custom_coding.decoders; + for (size_t j = 0; j < decoders->size(); ++j) { + DEBUG(level + 2, "Type: %s, function: %s", + decoders->get_nth_key(j)->get_fullname().c_str(), + decoders->get_nth_elem(j)->conflict ? "<multiple>" : + decoders->get_nth_elem(j)->func_def->get_fullname().c_str()); + } } } } diff --git a/compiler2/Type.hh b/compiler2/Type.hh index eab00c40c349de9e0f8b0e0cb92601ad71e9c25f..6dfcc32256abfe8fa8b34cfca6ef70924acfdd07 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -292,6 +292,12 @@ namespace Common { }; }; + /** Stores information about the custom encoder or decoder function of a type */ + struct coder_function_t { + Assignment* func_def; ///< definition of the encoder or decoder function + boolean conflict; ///< indicates whether there are multiple encoder/decoder functions for this type and codec + }; + /** Stores information related to an encoding type (codec), when using new * codec handling. */ struct coding_t { @@ -300,10 +306,9 @@ namespace Common { MessageEncodingType_t built_in_coding; ///< built-in codec struct { char* name; ///< name of the user defined codec (the string in the 'encode' attribute) - Assignment* enc_func; ///< definition of the encoder function - boolean enc_conflict; ///< indicates whether there are multiple encoder functions for this type and codec - Assignment* dec_func; ///< definition of the decoder function - boolean dec_conflict; ///< indicates whether there are multiple decoder functions for this type and codec + // note: other types that use this type's coding table may have their own encoder/decoder functions + map<Type*, coder_function_t>* encoders; ///< the map of encoder functions per type + map<Type*, coder_function_t>* decoders; ///< the map of decoder functions per type } custom_coding; }; }; @@ -628,6 +633,19 @@ namespace Common { * encoding, if set by the compiler option. */ void chk_encodings(); + /** Checks the type's variant attributes (when using the new codec handling). */ + void chk_variants(); + + /** Parses the specified variant attribute and checks its validity (when + * using the new codec handling). */ + void chk_this_variant(const Ttcn::SingleWithAttrib* swa, bool global); + + /** Checks the coding instructions set by the parsed variant attributes. + * The check is performed recursively on the type's fields and elements + * when using the new codec handling. + * The check is only performed on this type, when using legacy codec handling. */ + void chk_coding_attribs(); + /** Adds support for an encoding by the type (when using new codec handling), * if the type can have that encoding. * @param name name of the encoding as it appears in the 'encode' attribute; @@ -639,6 +657,10 @@ namespace Common { void set_coding_function(const char* coding_name, boolean encode, Assignment* function_def); + /** Returns the custom encoder or decoder function at the specified index in + * the coding table related to this type (when using the new codec handling). */ + coder_function_t* get_coding_function(size_t index, boolean encode); + /** Returns the type that contains this type's coding table (since types * with no 'encode' attributes of their own inherit the 'encode' attributes * of a referenced type or a parent type). @@ -784,8 +806,9 @@ namespace Common { 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; + * Used during code generation for types encoded/decoded by functions. + * Only used with legacy codec handling. */ + Assignment* get_legacy_coding_function(bool encode) const; static MessageEncodingType_t get_enc_type(const string& enc); diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index e81f9e06ff3bc40d1712c1df9efdd570fb239cf5..df40be874e96b1dddc789ab4c9bab0b5ecad75c8 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -48,7 +48,9 @@ using Ttcn::Qualifiers; void Type::chk() { if(w_attrib_path) w_attrib_path->chk_global_attrib(); - parse_attributes(); + if (legacy_codec_handling) { + parse_attributes(); + } if(!tags_checked) { tags_checked = true; if(tags) tags->chk(); @@ -112,28 +114,14 @@ void Type::chk() case T_SEQ_T: case T_SET_T: case T_CHOICE_T: - chk_SeCho_T(); - // If this sequence type has no attributes but one of its fields does, - // create an empty attribute structure. - if(!rawattrib && hasVariantAttrs() && hasNeedofRawAttrs()) - rawattrib = new RawAST(get_default_raw_fieldlength()); - if(!textattrib && hasVariantAttrs() && hasNeedofTextAttrs()) - textattrib = new TextAST; - if(!xerattrib && hasVariantAttrs() && hasNeedofXerAttrs()) - xerattrib = new XerAttributes; - if (!jsonattrib && hasVariantAttrs() && hasNeedofJsonAttrs()) { - jsonattrib = new JsonAST; - } + chk_SeCho_T(); break; case T_CHOICE_A: chk_Choice_A(); - // TODO create an empty XerAttrib as above, when ASN.1 gets XER ? - // The code was originally for TTCN-only encodings. break; case T_SEQ_A: case T_SET_A: chk_Se_A(); - // TODO create an empty XerAttrib as above, when ASN.1 gets XER ? break; case T_SEQOF: case T_SETOF: @@ -187,9 +175,6 @@ void Type::chk() break; } } - if (!legacy_codec_handling && my_scope != NULL) { - chk_encodings(); - } checked = true; if(tags) tags->set_plicit(this); @@ -208,14 +193,46 @@ void Type::chk() */ if (!parent_type) chk_table_constraints(); - if(rawattrib || is_root_basic()){ + if (legacy_codec_handling) { + chk_coding_attribs(); + } + else if (my_scope != NULL) { + chk_encodings(); + chk_variants(); + } + + chk_finished = true; +} + +void Type::chk_coding_attribs() +{ + if (typetype == T_SEQ_T || typetype == T_SET_T || typetype == T_CHOICE_T) { + // If this record/set/union type has no attributes but one of its fields does, + // create an empty attribute structure. + // TODO: do the same for ASN.1 sequence/set/choice types, when ASN.1 gets XER ? + // The code was originally for TTCN-only encodings. + if (!rawattrib && hasVariantAttrs() && hasNeedofRawAttrs()) { + rawattrib = new RawAST(get_default_raw_fieldlength()); + } + if (!textattrib && hasVariantAttrs() && hasNeedofTextAttrs()) { + textattrib = new TextAST; + } + if (!xerattrib && hasVariantAttrs() && hasNeedofXerAttrs()) { + xerattrib = new XerAttributes; + } + if (!jsonattrib && hasVariantAttrs() && hasNeedofJsonAttrs()) { + jsonattrib = new JsonAST; + } + } + + if (rawattrib != NULL || is_root_basic()) { chk_raw(); } - if(textattrib || is_root_basic()) { + if (textattrib != NULL || is_root_basic()) { chk_text(); } - if (jsonattrib || is_root_basic()) { + if (jsonattrib != NULL || is_root_basic()) { chk_json(); } @@ -223,7 +240,31 @@ void Type::chk() // XER attributes from parent types. chk_xer(); - chk_finished = true; + if (!legacy_codec_handling) { + switch (typetype) { + case T_SEQ_T: + case T_SEQ_A: + case T_SET_T: + case T_SET_A: + case T_CHOICE_T: + case T_CHOICE_A: + case T_ANYTYPE: + case T_OPENTYPE: + for (size_t i = 0; i < get_nof_comps(); ++i) { + get_comp_byIndex(i)->get_type()->chk_coding_attribs(); + } + break; + + case T_ARRAY: + case T_SEQOF: + case T_SETOF: + get_ofType()->chk_coding_attribs(); + break; + + default: + break; + } + } } void Type::parse_attributes() @@ -558,9 +599,10 @@ void Type::parse_attributes() // Special case when trying to reference the inner type // of a record-of when it wasn't a record-of. if (tmp_id == underscore_zero) temp_qualifier->error( - "Invalid field qualifier [-]"); - else temp_qualifier->error("Invalid field qualifier %s", - tmp_id.get_dispname().c_str()); + "Type `%s' cannot be indexed", get_typename().c_str()); + else temp_qualifier->error( + "Reference to non-existent field `%s' in type `%s'", + tmp_id.get_dispname().c_str(), get_typename().c_str()); } self_attribs->delete_element(i); }else{ @@ -666,8 +708,16 @@ void Type::chk_encodings() for (size_t j = 0; j < quals->get_nof_qualifiers(); ++j) { Ttcn::Qualifier* qual = const_cast<Ttcn::Qualifier*>( quals->get_qualifier(j)); - get_field_type(qual, EXPECTED_CONSTANT)-> - add_coding(swa->get_attribSpec().get_spec()); + Type* t = get_field_type(qual, EXPECTED_CONSTANT); + if (t != NULL) { + if (t->my_scope != my_scope) { + qual->warning("Encode attribute is ignored, because it " + "refers to a type from a different type definition"); + } + else { + t->add_coding(swa->get_attribSpec().get_spec()); + } + } } } else { @@ -676,7 +726,9 @@ void Type::chk_encodings() } } } - if (coding_table.size() == 0) { + if (get_type_w_coding_table() == NULL) { + // if there are no 'encode' attributes in this type, the referenced + // types, or the parent type, then try the nearest group or the module const vector<SingleWithAttrib>& real = ap->get_real_attrib(); for (size_t i = 0; i < real.size(); ++i) { const SingleWithAttrib* swa = real[i]; @@ -713,6 +765,249 @@ void Type::chk_encodings() } } +void Type::chk_variants() +{ + if (legacy_codec_handling) { + FATAL_ERROR("Type::chk_encodings"); + } + if (is_asn1() || ownertype != OT_TYPE_DEF) { + return; + } + // check global (group/module) variant attributes first + WithAttribPath* global_ap = NULL; + Ttcn::Def_Type* def = static_cast<Ttcn::Def_Type*>(owner); + Ttcn::Group* nearest_group = def->get_parent_group(); + + if (nearest_group != NULL) { // there is a group + global_ap = nearest_group->get_attrib_path(); + } + else { // no group, use the module + Common::Module* mymod = my_scope->get_scope_mod(); + // OT_TYPE_DEF is always from a TTCN-3 module + Ttcn::Module* my_ttcn_module = static_cast<Ttcn::Module *>(mymod); + global_ap = my_ttcn_module->get_attrib_path(); + } + if (global_ap != NULL) { + MultiWithAttrib* mwa = global_ap->get_with_attr(); + if (mwa != NULL) { + for (size_t i = 0; i < mwa->get_nof_elements(); ++i) { + const SingleWithAttrib* swa = mwa->get_element(i); + if (swa->get_attribKeyword() == SingleWithAttrib::AT_VARIANT) { + chk_this_variant(swa, true); + } + } + } + } + // check local variant attributes second, so they overwrite global ones if they + // conflict with each other + WithAttribPath* ap = get_attrib_path(); + if (ap != NULL) { + MultiWithAttrib* mwa = ap->get_with_attr(); + if (mwa != NULL) { + for (size_t i = 0; i < mwa->get_nof_elements(); ++i) { + const SingleWithAttrib* swa = mwa->get_element(i); + if (swa->get_attribKeyword() == SingleWithAttrib::AT_VARIANT) { + Ttcn::Qualifiers* quals = swa->get_attribQualifiers(); + if (quals != NULL && quals->get_nof_qualifiers() != 0) { + for (size_t j = 0; j < quals->get_nof_qualifiers(); ++j) { + Ttcn::Qualifier* qual = const_cast<Ttcn::Qualifier*>( + quals->get_qualifier(j)); + Type* t = get_field_type(qual, EXPECTED_CONSTANT); + if (t != NULL) { + if (t->my_scope != my_scope) { + qual->warning("Variant attribute is ignored, because it refers " + "to a type from a different type definition"); + } + else { + t->chk_this_variant(swa, false); + } + } + } + } + else { + chk_this_variant(swa, false); + } + } + } + } + } + // check the coding attributes set by the variants + chk_coding_attribs(); +} + +void Type::chk_this_variant(const Ttcn::SingleWithAttrib* swa, bool global) +{ + // TODO: use something other than get_typename... + Type* t = get_type_w_coding_table(); + if (t == NULL) { + if (!global) { + swa->error("No encoding rules defined for type `%s'", + get_typename().c_str()); + } + } + else { + const string& enc_str = swa->get_attribSpec().get_encoding(); + MessageEncodingType_t coding = get_enc_type(enc_str); + bool erroneous = false; + if (enc_str.empty()) { + if (t->coding_table.size() > 1) { + if (!global) { + swa->error("The encoding reference is mandatory for variant attributes " + "of type `%s', which has multiple encodings", get_typename().c_str()); + } + erroneous = true; + } + else if (t->coding_table[0]->built_in) { + coding = t->coding_table[0]->built_in_coding; + } + else if (strcmp(t->coding_table[0]->custom_coding.name, "PER") == 0) { + coding = CT_PER; + } + // else leave it as CT_CUSTOM + } + else { + if (!has_encoding(coding, &enc_str)) { + erroneous = true; + if (!global) { + if (coding != CT_CUSTOM) { + swa->error("Type `%s' does not support %s encoding", + get_typename().c_str(), get_encoding_name(coding)); + } + else { + swa->error("Type `%s' does not support custom encoding `%s'", + get_typename().c_str(), enc_str.c_str()); + } + } + } + } + if (!erroneous && coding != CT_PER && coding != CT_CUSTOM) { + bool new_ber = false; // a BerAST object was allocated here + bool new_raw = false; // a RawAST object was allocated here + bool new_text = false; // a TextAST object was allocated here + bool new_xer = false; // a XerAttribute object was allocated here + bool new_json = false; // a JsonAST object was allocated here + bool ber_found = false; // a BER attribute was found by the parser + bool raw_found = false; // a RAW attribute was found by the parser + bool text_found = false; // a TEXT attribute was found by the parser + bool xer_found = false; // a XER attribute was found by the parser + bool json_found = false; // a JSON attribute was found by the parser + if (berattrib == NULL) { + berattrib = new BerAST; + new_ber = true; + } + if (rawattrib == NULL) { + Type* t_refd = this; + while (t_refd->rawattrib == NULL && t_refd->is_ref()) { + t_refd = t_refd->get_type_refd(); + } + rawattrib = new RawAST(t_refd->rawattrib, get_default_raw_fieldlength()); + new_raw = true; + } + if (textattrib == NULL) { + Type* t_refd = this; + while (t_refd->textattrib == NULL && t_refd->is_ref()) { + t_refd = t_refd->get_type_refd(); + } + textattrib = new TextAST(t_refd->textattrib); + new_text = true; + } + if (xerattrib == NULL) { + xerattrib = new XerAttributes; + new_xer = true; + } + if (jsonattrib == NULL) { + Type* t_refd = this; + while (t_refd->jsonattrib == NULL && t_refd->is_ref()) { + t_refd = t_refd->get_type_refd(); + } + jsonattrib = new JsonAST(t_refd->jsonattrib); + new_json = true; + } + int ret = parse_rawAST(rawattrib, textattrib, xerattrib, berattrib, jsonattrib, + swa->get_attribSpec(), get_length_multiplier(), my_scope->get_scope_mod(), + raw_found, text_found, xer_found, ber_found, json_found); + bool mismatch = false; + switch (coding) { + case CT_BER: + mismatch = !ber_found; + break; + case CT_RAW: + mismatch = !raw_found; + break; + case CT_TEXT: + mismatch = !text_found; + break; + case CT_XER: + mismatch = !xer_found; + break; + case CT_JSON: + mismatch = !json_found; + break; + default: + FATAL_ERROR("Type::chk_this_variant"); + break; + } + if (mismatch && ret == 0) { + if (!global || !enc_str.empty()) { + // don't display this if there were parsing errors in the variant attribute + swa->error("Variant attribute is not related to %s encoding", + get_encoding_name(coding)); + } + } + if (new_ber && !ber_found) { + delete berattrib; + berattrib = NULL; + } + if (new_raw && !raw_found) { + delete rawattrib; + rawattrib = NULL; + } + if (new_text && !text_found) { + delete textattrib; + textattrib = NULL; + } + if (new_xer && !xer_found) { + delete xerattrib; + xerattrib = NULL; + } + if (new_json && !json_found) { + delete jsonattrib; + jsonattrib = NULL; + } + } + else if (!erroneous && !global) { // PER or custom encoding + swa->warning("Variant attributes related to %s encoding are ignored", + get_encoding_name(coding)); + } + } // if t != NULL + if (global) { + // send global variant attributes to field/element types + switch (typetype) { + case T_SEQ_T: + case T_SEQ_A: + case T_SET_T: + case T_SET_A: + case T_CHOICE_T: + case T_CHOICE_A: + case T_ANYTYPE: + case T_OPENTYPE: + for (size_t i = 0; i < get_nof_comps(); ++i) { + get_comp_byIndex(i)->get_type()->chk_this_variant(swa, global); + } + break; + + case T_ARRAY: + case T_SEQOF: + case T_SETOF: + get_ofType()->chk_this_variant(swa, global); + break; + + default: + break; + } + } +} + void Type::chk_xer_any_attributes() { Type * const last = get_type_refd_last(); @@ -926,7 +1221,7 @@ Value *Type::new_value_for_dfe(Type *last, const char *dfe_str, Common::Referenc same_mod = true; } if (!is_compatible_tt_tt(last->typetype, t->typetype, last->is_asn1(), t->is_asn1(), same_mod)) { - v->get_reference()->error("Incompatible types were given to defaultForEmpty variant: `%s' instead of `%s'.\n", + v->get_reference()->error("Incompatible types were given to defaultForEmpty variant: `%s' instead of `%s'.", v->get_expr_governor_last()->get_typename().c_str(), last->get_typename().c_str()); delete v; return 0; @@ -1153,7 +1448,7 @@ void Type::chk_xer_dfe() } else { error("DEFAULT-FOR-EMPTY not supported for character-encodable type %s", - last->get_stringRepr().c_str()); + get_typename().c_str()); } } else if (last->typetype == T_SEQ_A || last->typetype == T_SEQ_T) { @@ -1177,7 +1472,7 @@ void Type::chk_xer_dfe() } else { error("DEFAULT-FOR-EMPTY not supported for fields of type %s", - cft->get_stringRepr().c_str()); + cft->get_typename().c_str()); } } // endif comps >0 } // if SEQ/SET @@ -2147,7 +2442,7 @@ void Type::chk_xer_use_union() error("USE-UNION cannot be applied to anytype"); break; default: - error("USE-UNION can only applied to a CHOICE/union type"); // 38.2.1 + error("USE-UNION can only be applied to a CHOICE/union type"); // 38.2.1 break; } @@ -6126,8 +6421,9 @@ 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, - t->get_my_scope()->get_scope_mod()); + Type* coding_type = legacy_codec_handling ? + target_type->get_type_refd_last() : target_type; + coding_type->chk_coding(false, t->get_my_scope()->get_scope_mod()); } { Value* str_enc = t->get_string_encoding(); diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index f54a4b70709b46ffe96472221c7c7d0fd9e93eb4..1a098d783d77f45ae7df71d574cc3b6d19f07417 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -2372,12 +2372,20 @@ void Type::generate_code_coding_handlers(output_struct* target) // encoder enc_str = mputprintf(enc_str, "if (coding_name == \"%s\") {\n", t->coding_table[i]->custom_coding.name); - Assignment* enc_func = t->coding_table[i]->custom_coding.enc_func; - if (enc_func != NULL && t == this) { - enc_str = mputprintf(enc_str, - "output_stream = bit2oct(%s(input_value));\n" - "return;\n", - enc_func->get_genname_from_scope(my_scope).c_str()); + coder_function_t* enc_func = get_coding_function(i, TRUE); + if (enc_func != NULL) { + if (enc_func->conflict) { + enc_str = mputprintf(enc_str, + "TTCN_error(\"Multiple `%s' encoding functions defined for type " + "`%s'\");\n", + t->coding_table[i]->custom_coding.name, get_typename().c_str()); + } + else { + enc_str = mputprintf(enc_str, + "output_stream = bit2oct(%s(input_value));\n" + "return;\n", + enc_func->func_def->get_genname_from_scope(my_scope).c_str()); + } } else { enc_str = mputprintf(enc_str, @@ -2389,14 +2397,22 @@ void Type::generate_code_coding_handlers(output_struct* target) // decoder dec_str = mputprintf(dec_str, "if (coding_name == \"%s\") {\n", t->coding_table[i]->custom_coding.name); - Assignment* dec_func = t->coding_table[i]->custom_coding.dec_func; - if (dec_func != NULL && t == this) { - dec_str = mputprintf(dec_str, - "BITSTRING bit_stream(oct2bit(input_stream));\n" - "INTEGER ret_val = %s(bit_stream, output_value);\n" - "input_stream = bit2oct(bit_stream);\n" - "return ret_val;\n", - dec_func->get_genname_from_scope(my_scope).c_str()); + coder_function_t* dec_func = get_coding_function(i, FALSE); + if (dec_func != NULL) { + if (dec_func->conflict) { + enc_str = mputprintf(enc_str, + "TTCN_error(\"Multiple `%s' decoding functions defined for type " + "`%s'\");\n", + t->coding_table[i]->custom_coding.name, get_typename().c_str()); + } + else { + dec_str = mputprintf(dec_str, + "BITSTRING bit_stream(oct2bit(input_stream));\n" + "INTEGER ret_val = %s(bit_stream, output_value);\n" + "input_stream = bit2oct(bit_stream);\n" + "return ret_val;\n", + dec_func->func_def->get_genname_from_scope(my_scope).c_str()); + } } else { dec_str = mputprintf(dec_str, diff --git a/compiler2/Value.cc b/compiler2/Value.cc index fa470b3e209ecf234178f872f54beb81ed7c92b6..10b33f7799bac54f99d484705cefc0dc98d5d3a6 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -5907,6 +5907,47 @@ void Value::chk_expr_operand_execute_refd(Value *v1, } if (error_flag) set_valuetype(V_ERROR); } + + void Value::chk_dyn_enc_str(Type* type) + { + if (legacy_codec_handling) { + FATAL_ERROR("Value::chk_dyn_enc_str()"); + } + Type* t_ct = type->get_type_w_coding_table(); + if (t_ct == NULL) { + return; // an error has already been displayed + } + bool val_error = false; + ustring us = get_val_ustr(); + for (size_t i = 0; i < us.size(); ++i) { + const ustring::universal_char& uc = us[i]; + if (uc.group != 0 || uc.plane != 0 || uc.row != 0) { + // this surely won't match any of the type's encodings, since + // 'encode' attributes cannot contain multi-byte characters + val_error = true; + break; + } + } + if (!val_error) { + string s(us); + Type::MessageEncodingType_t coding = Type::get_enc_type(s); + bool built_in = (coding != Type::CT_PER && coding != Type::CT_CUSTOM); + val_error = true; + const vector<Common::Type::coding_t>& ct = t_ct->get_coding_table(); + for (size_t i = 0; i < ct.size(); ++i) { + if (built_in == ct[i]->built_in && + ((built_in && coding == ct[i]->built_in_coding) || + (!built_in && s == ct[i]->custom_coding.name))) { + val_error = false; + break; + } + } + } + if (val_error) { + error("The encoding string does not match any encodings of type `%s'", + type->get_typename().c_str()); + } + } void Value::chk_expr_operand_encode(ReferenceChain *refch, Type::expected_value_t exp_val) @@ -5914,9 +5955,10 @@ void Value::chk_expr_operand_execute_refd(Value *v1, const char* opname = u.expr.v_optype == OPTYPE_ENCODE ? "encvalue" : "encvalue_unichar"; Type t_chk(Type::T_ERROR); + Type* t_type; { Error_Context cntxt(this, "In the first parameter of %s()", opname); - Type* t_type; + Type* t_type_last; Type::expected_value_t ti_exp_val = exp_val; if (ti_exp_val == Type::EXPECTED_DYNAMIC_VALUE) @@ -5927,7 +5969,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, chk_expr_eval_ti(u.expr.ti1, t_type, refch, ti_exp_val); if (valuetype!=V_ERROR) u.expr.ti1->get_Template()->chk_specific_value(false); - t_type = t_type->get_type_refd_last(); + t_type_last = t_type->get_type_refd_last(); } else { error("Cannot determine type of value"); set_valuetype(V_ERROR); @@ -5943,10 +5985,11 @@ void Value::chk_expr_operand_execute_refd(Value *v1, }*/ if(!disable_attribute_validation()) { - t_type->chk_coding(true, my_scope->get_scope_mod()); + Type* t_type_coding = legacy_codec_handling ? t_type_last : t_type; + t_type_coding->chk_coding(true, my_scope->get_scope_mod()); } - switch (t_type->get_typetype()) { + switch (t_type_last->get_typetype()) { case Type::T_UNDEF: case Type::T_ERROR: case Type::T_NULL: @@ -5962,7 +6005,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case Type::T_ALTSTEP: case Type::T_TESTCASE: error("Type of parameter of encvalue() cannot be '%s'", - t_type->get_typename().c_str()); + t_type_last->get_typename().c_str()); set_valuetype(V_ERROR); return; default: @@ -5999,7 +6042,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1, chk_expr_operandtype_charstr(tt, u.expr.v_optype == OPTYPE_ENCODE ? "Third" : "Fourth", opname, v_dyn_enc); chk_expr_eval_value(v_dyn_enc, t_chk, refch, exp_val); - // TODO: if foldable, check value against coding table + if (!legacy_codec_handling && !v_dyn_enc->is_unfoldable(refch, exp_val)) { + v_dyn_enc->chk_dyn_enc_str(t_type); + } } } @@ -6008,127 +6053,131 @@ void Value::chk_expr_operand_execute_refd(Value *v1, { const char* opname = u.expr.v_optype == OPTYPE_DECODE ? "decvalue" : "decvalue_unichar"; - Error_Context cntxt(this, "In the parameters of %s()", opname); - Ttcn::Ref_base* ref = u.expr.r1; - Ttcn::FieldOrArrayRefs* t_subrefs = ref->get_subrefs(); Type* t_type = 0; - Assignment* t_ass = ref->get_refd_assignment(); - - if (!t_ass) { - error("Could not determine the assignment for first parameter"); - goto error; - } - switch (t_ass->get_asstype()) { - case Assignment::A_PAR_VAL_IN: - t_ass->use_as_lvalue(*this); - break; - case Assignment::A_CONST: - case Assignment::A_EXT_CONST: - case Assignment::A_MODULEPAR: - case Assignment::A_MODULEPAR_TEMP: - case Assignment::A_TEMPLATE: - ref->error("Reference to '%s' cannot be used as the first operand of " - "the 'decvalue' operation", t_ass->get_assname()); - goto error; - break; - case Assignment::A_VAR: - case Assignment::A_PAR_VAL_OUT: - case Assignment::A_PAR_VAL_INOUT: - break; - case Assignment::A_VAR_TEMPLATE: - case Assignment::A_PAR_TEMPL_IN: - case Assignment::A_PAR_TEMPL_OUT: - case Assignment::A_PAR_TEMPL_INOUT: { - Template* t = new Template(ref->clone()); - t->set_location(*ref); - t->set_my_scope(get_my_scope()); - t->set_fullname(get_fullname()+".<operand>"); - Template* t_last = t->get_template_refd_last(); - if (t_last->get_templatetype() != Template::SPECIFIC_VALUE - && t_last != t) { - ref->error("Specific value template was expected instead of '%s'.", - t->get_template_refd_last()->get_templatetype_str()); - delete t; + { + Error_Context cntxt(this, "In the parameters of %s()", opname); + Ttcn::Ref_base* ref = u.expr.r1; + Ttcn::FieldOrArrayRefs* t_subrefs = ref->get_subrefs(); + Type* t_type_last = 0; + Assignment* t_ass = ref->get_refd_assignment(); + + if (!t_ass) { + error("Could not determine the assignment for first parameter"); goto error; } - delete t; - break; } - default: - ref->error("Reference to '%s' cannot be used.", t_ass->get_assname()); - goto error; - } - t_type = t_ass->get_Type()->get_field_type(t_subrefs, - Type::EXPECTED_DYNAMIC_VALUE); - if (!t_type) { - goto error; - } - switch(u.expr.v_optype) { - case OPTYPE_DECODE: - if (t_type->get_type_refd_last()->get_typetype() != Type::T_BSTR){ - error("First parameter has to be a bitstring"); - goto error; - } + switch (t_ass->get_asstype()) { + case Assignment::A_PAR_VAL_IN: + t_ass->use_as_lvalue(*this); break; - case OPTYPE_DECVALUE_UNICHAR: - if (t_type->get_type_refd_last()->get_typetype() != Type::T_USTR){ - error("First parameter has to be a universal charstring"); + case Assignment::A_CONST: + case Assignment::A_EXT_CONST: + case Assignment::A_MODULEPAR: + case Assignment::A_MODULEPAR_TEMP: + case Assignment::A_TEMPLATE: + ref->error("Reference to '%s' cannot be used as the first operand of " + "the 'decvalue' operation", t_ass->get_assname()); + goto error; + break; + case Assignment::A_VAR: + case Assignment::A_PAR_VAL_OUT: + case Assignment::A_PAR_VAL_INOUT: + break; + case Assignment::A_VAR_TEMPLATE: + case Assignment::A_PAR_TEMPL_IN: + case Assignment::A_PAR_TEMPL_OUT: + case Assignment::A_PAR_TEMPL_INOUT: { + Template* t = new Template(ref->clone()); + t->set_location(*ref); + t->set_my_scope(get_my_scope()); + t->set_fullname(get_fullname()+".<operand>"); + Template* t_last = t->get_template_refd_last(); + if (t_last->get_templatetype() != Template::SPECIFIC_VALUE + && t_last != t) { + ref->error("Specific value template was expected instead of '%s'.", + t->get_template_refd_last()->get_templatetype_str()); + delete t; goto error; } - break; + delete t; + break; } default: - FATAL_ERROR("Value::chk_expr_decode_operands()"); - break; - } + ref->error("Reference to '%s' cannot be used.", t_ass->get_assname()); + goto error; + } + t_type = t_ass->get_Type()->get_field_type(t_subrefs, + Type::EXPECTED_DYNAMIC_VALUE); + if (!t_type) { + goto error; + } + switch(u.expr.v_optype) { + case OPTYPE_DECODE: + if (t_type->get_type_refd_last()->get_typetype() != Type::T_BSTR){ + error("First parameter has to be a bitstring"); + goto error; + } + break; + case OPTYPE_DECVALUE_UNICHAR: + if (t_type->get_type_refd_last()->get_typetype() != Type::T_USTR){ + error("First parameter has to be a universal charstring"); + goto error; + } + break; + default: + FATAL_ERROR("Value::chk_expr_decode_operands()"); + break; + } - ref = u.expr.r2; - t_subrefs = ref->get_subrefs(); - t_ass = ref->get_refd_assignment(); + ref = u.expr.r2; + t_subrefs = ref->get_subrefs(); + t_ass = ref->get_refd_assignment(); - if (!t_ass) { - error("Could not determine the assignment for second parameter"); - goto error; - } - // Extra check for HM59355. - switch (t_ass->get_asstype()) { - case Assignment::A_VAR: - case Assignment::A_PAR_VAL_IN: - case Assignment::A_PAR_VAL_OUT: - case Assignment::A_PAR_VAL_INOUT: - break; - default: - ref->error("Reference to '%s' cannot be used.", t_ass->get_assname()); - goto error; - } - t_type = t_ass->get_Type()->get_field_type(t_subrefs, - Type::EXPECTED_DYNAMIC_VALUE); - if (!t_type) { - goto error; - } - t_type = t_type->get_type_refd_last(); - switch (t_type->get_typetype()) { - case Type::T_UNDEF: - case Type::T_ERROR: - case Type::T_NULL: - case Type::T_REFD: - case Type::T_REFDSPEC: - case Type::T_SELTYPE: - case Type::T_VERDICT: - case Type::T_PORT: - case Type::T_COMPONENT: - case Type::T_DEFAULT: - case Type::T_SIGNATURE: - case Type::T_FUNCTION: - case Type::T_ALTSTEP: - case Type::T_TESTCASE: - error("Type of second parameter cannot be %s", - t_type->get_typename().c_str()); - goto error; - default: - break; - } + if (!t_ass) { + error("Could not determine the assignment for second parameter"); + goto error; + } + // Extra check for HM59355. + switch (t_ass->get_asstype()) { + case Assignment::A_VAR: + case Assignment::A_PAR_VAL_IN: + case Assignment::A_PAR_VAL_OUT: + case Assignment::A_PAR_VAL_INOUT: + break; + default: + ref->error("Reference to '%s' cannot be used.", t_ass->get_assname()); + goto error; + } + t_type = t_ass->get_Type()->get_field_type(t_subrefs, + Type::EXPECTED_DYNAMIC_VALUE); + if (!t_type) { + goto error; + } + t_type_last = t_type->get_type_refd_last(); + switch (t_type_last->get_typetype()) { + case Type::T_UNDEF: + case Type::T_ERROR: + case Type::T_NULL: + case Type::T_REFD: + case Type::T_REFDSPEC: + case Type::T_SELTYPE: + case Type::T_VERDICT: + case Type::T_PORT: + case Type::T_COMPONENT: + case Type::T_DEFAULT: + case Type::T_SIGNATURE: + case Type::T_FUNCTION: + case Type::T_ALTSTEP: + case Type::T_TESTCASE: + error("Type of second parameter cannot be %s", + t_type_last->get_typename().c_str()); + goto error; + default: + break; + } - if(!disable_attribute_validation()) { - t_type->chk_coding(false, my_scope->get_scope_mod()); + if(!disable_attribute_validation()) { + Type* t_type_coding = legacy_codec_handling ? t_type_last : t_type; + t_type_coding->chk_coding(false, my_scope->get_scope_mod()); + } } { @@ -6162,7 +6211,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1, chk_expr_operandtype_charstr(tt, u.expr.v_optype == OPTYPE_DECODE ? "Fourth" : "Fifth", opname, v_dyn_enc); chk_expr_eval_value(v_dyn_enc, t_chk, refch, exp_val); - // TODO: if foldable, check value against coding table + if (!legacy_codec_handling && !v_dyn_enc->is_unfoldable(refch, exp_val)) { + v_dyn_enc->chk_dyn_enc_str(t_type); + } } } @@ -11300,28 +11351,46 @@ void Value::chk_expr_operand_execute_refd(Value *v1, if (u.expr.v2) return create_stringRepr_predef2("unichar2oct"); else return create_stringRepr_predef1("unichar2oct"); } - case OPTYPE_ENCVALUE_UNICHAR: { // TODO: update with new parameters - if (u.expr.v2) return create_stringRepr_predef2("encvalue_unichar"); - else return create_stringRepr_predef1("encvalue_unichar"); - } + case OPTYPE_ENCVALUE_UNICHAR: { + string ret_val("encvalue_unichar("); + u.expr.ti1->append_stringRepr(ret_val); + if (u.expr.v2 != NULL) { + ret_val += ", "; + ret_val += u.expr.v2->get_stringRepr(); + if (u.expr.v3 != NULL) { + ret_val += ", "; + ret_val += u.expr.v3->get_stringRepr(); + if (u.expr.v4 != NULL) { + ret_val += ", "; + ret_val += u.expr.v4->get_stringRepr(); + } + } + } + ret_val += ')'; + return ret_val; } case OPTYPE_HOSTID: { if (u.expr.v1) return create_stringRepr_predef1("hostid"); else return string("hostid()"); } - case OPTYPE_DECVALUE_UNICHAR: { // TODO: update with new parameters - if (u.expr.v3) { - string ret_val("decvalue_unichar"); - ret_val += '('; - ret_val += u.expr.v1->get_stringRepr(); - ret_val += ", "; - ret_val += u.expr.v2->get_stringRepr(); - ret_val += ", "; - ret_val += u.expr.v3->get_stringRepr(); - ret_val += ')'; - return ret_val; - } - else return create_stringRepr_predef2("decvalue_unichar"); - } + case OPTYPE_DECVALUE_UNICHAR: { + string ret_val("decvalue_unichar("); + ret_val += u.expr.r1->get_dispname(); + ret_val += ", "; + ret_val += u.expr.r2->get_dispname(); + if (u.expr.v3 != NULL) { + ret_val += ", "; + ret_val += u.expr.v3->get_stringRepr(); + if (u.expr.v4 != NULL) { + ret_val += ", "; + ret_val += u.expr.v4->get_stringRepr(); + if (u.expr.v5 != NULL) { + ret_val += ", "; + ret_val += u.expr.v5->get_stringRepr(); + } + } + } + ret_val += ')'; + return ret_val; } case OPTYPE_STR2BIT: return create_stringRepr_predef1("str2bit"); case OPTYPE_STR2FLOAT: @@ -11338,10 +11407,34 @@ void Value::chk_expr_operand_execute_refd(Value *v1, return create_stringRepr_predef1("unichar2char"); case OPTYPE_ENUM2INT: return create_stringRepr_predef1("enum2int"); - case OPTYPE_ENCODE: - return create_stringRepr_predef1("encvalue"); // TODO: update with new parameters - case OPTYPE_DECODE: - return create_stringRepr_predef2("decvalue"); // TODO: update with new parameters + case OPTYPE_ENCODE: { + string ret_val("encvalue("); + u.expr.ti1->append_stringRepr(ret_val); + if (u.expr.v2 != NULL) { + ret_val += ", "; + ret_val += u.expr.v2->get_stringRepr(); + if (u.expr.v3 != NULL) { + ret_val += ", "; + ret_val += u.expr.v3->get_stringRepr(); + } + } + ret_val += ')'; + return ret_val; } + case OPTYPE_DECODE: { + string ret_val("decvalue("); + ret_val += u.expr.r1->get_dispname(); + ret_val += ", "; + ret_val += u.expr.r2->get_dispname(); + if (u.expr.v3 != NULL) { + ret_val += ", "; + ret_val += u.expr.v3->get_stringRepr(); + if (u.expr.v4 != NULL) { + ret_val += ", "; + ret_val += u.expr.v4->get_stringRepr(); + } + } + ret_val += ')'; + return ret_val; } case OPTYPE_RNDWITHVAL: return create_stringRepr_predef1("rnd"); case OPTYPE_ADD: @@ -11730,10 +11823,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, { string ret_val(function_name); ret_val += '('; - if (u.expr.v_optype == OPTYPE_ENCODE || u.expr.v_optype == OPTYPE_ENCVALUE_UNICHAR) { // ti1, not v1 - ret_val += u.expr.ti1->get_specific_value()->get_stringRepr(); - } - else ret_val += u.expr.v1->get_stringRepr(); + ret_val += u.expr.v1->get_stringRepr(); ret_val += ')'; return ret_val; } @@ -13521,7 +13611,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, expr->postamble = mputstr(expr->postamble, expr2.postamble); } else expr->expr = mputprintf(expr->expr, "%s(%s%s)", - gov_last->get_coding_function(true)->get_genname_from_scope(scope).c_str(), + gov_last->get_legacy_coding_function(true)->get_genname_from_scope(scope).c_str(), expr2.expr, is_templ ? ".valueof()" : ""); } else { // new codec handling @@ -13636,7 +13726,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1, expr->expr = mputprintf(expr->expr, "%s", retval_id.c_str()); } else expr->expr = mputprintf(expr->expr, "%s(%s, %s)", - _type_last->get_coding_function(false)->get_genname_from_scope(scope).c_str(), expr1.expr, expr2.expr); + _type_last->get_legacy_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) @@ -13770,7 +13861,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, expr->postamble = mputstr(expr->postamble, expr2.postamble); } else { expr->expr = mputprintf(expr->expr, "oct2unichar(bit2oct(%s(%s%s)), %s)", - gov_last->get_coding_function(true)->get_genname_from_scope(scope).c_str(), + gov_last->get_legacy_coding_function(true)->get_genname_from_scope(scope).c_str(), expr2.expr, is_templ ? ".valueof()" : "", v2_code); } } @@ -13904,7 +13995,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ustr_ref_id.c_str(), expr1.expr, bstr_id.c_str(), ustr_ref_id.c_str(), v3_code, ret_val_id.c_str(), - _type_last->get_coding_function(false)->get_genname_from_scope(scope).c_str(), + _type_last->get_legacy_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(), v3_code); expr->expr = mputprintf(expr->expr, "%s", ret_val_id.c_str()); diff --git a/compiler2/Value.hh b/compiler2/Value.hh index 66e94f7ec05d3376ddd1079baea45083a12e4a02..9d08a84985392ee5227182f5ff981dfa5d2706db 100644 --- a/compiler2/Value.hh +++ b/compiler2/Value.hh @@ -737,6 +737,10 @@ namespace Common { /** Checks that the value is (or evaluates to) a valid universal charstring * encoding format. */ bool chk_string_encoding(Common::Assignment* lhs); + + /** Checks that the value is a valid dynamic encoding string for the + * specified type. */ + void chk_dyn_enc_str(Type* type); /* if "infinity" or "-infinity" was parsed then this is a real value or a unary - expression containing a real value, where the real value is diff --git a/compiler2/main.cc b/compiler2/main.cc index 693655592a1c440aa1f2ea06cbd0a303dd1dc49b..0a31a2a748745b248f7ca6ce9e31b56b39f59031 100644 --- a/compiler2/main.cc +++ b/compiler2/main.cc @@ -99,7 +99,7 @@ boolean generate_skeleton = FALSE, force_overwrite = FALSE, force_gen_seof = FALSE, omit_in_value_list = FALSE, warnings_for_bad_variants = FALSE, debugger_active = FALSE, legacy_unbound_union_fields = FALSE, split_to_slices = FALSE, - legacy_untagged_union, disable_user_info, legacy_codec_handling = TRUE/*FALSE*/; + legacy_untagged_union, disable_user_info, legacy_codec_handling = FALSE; // use legacy codec handling until the implementation of the new one is finished // Default code splitting mode is set to 'no splitting'. diff --git a/compiler2/ttcn3/Attributes.cc b/compiler2/ttcn3/Attributes.cc index 49091320f1fd7d0ec3ac99c39895f3b58976dbed..4614bbdfd88f16f33d64286e792098e227c603f6 100644 --- a/compiler2/ttcn3/Attributes.cc +++ b/compiler2/ttcn3/Attributes.cc @@ -1401,7 +1401,8 @@ namespace Ttcn { } } - if(!par_has_encode && self_encode_index == -1 && self_has_variant) + if(legacy_codec_handling && + !par_has_encode && self_encode_index == -1 && self_has_variant) { // There is no encode, but there is at least one variant. // Find them and issue warnings. diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 58b76a1dcd133892713da0a9f51d0183bfa160f0..f4196210a5f9d3c480ea9adb74d5d49f588f16aa 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -5791,39 +5791,9 @@ error: Common::Type::get_pooltype(Type::T_USTR)->chk_this_value(enc_str, NULL, Common::Type::EXPECTED_DYNAMIC_VALUE, INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, NO_SUB_CHK); - bool val_error = false; if (!type_error && enc_str->get_valuetype() != Common::Value::V_ERROR && !enc_str->is_unfoldable()) { - ustring us = enc_str->get_val_ustr(); - for (size_t i = 0; i < us.size(); ++i) { - const ustring::universal_char& uc = us[i]; - if (uc.group != 0 || uc.plane != 0 || uc.row != 0) { - // this surely won't match any of the type's encodings, since - // 'encode' attributes cannot contain multi-byte characters - val_error = true; - break; - } - } - if (!val_error) { - string s(us); - Common::Type::MessageEncodingType_t coding = Common::Type::get_enc_type(s); - bool built_in = (coding != Common::Type::CT_PER && - coding != Common::Type::CT_CUSTOM); - val_error = true; - const vector<Common::Type::coding_t>& ct = t_ct->get_coding_table(); - for (size_t i = 0; i < ct.size(); ++i) { - if (built_in == ct[i]->built_in && - ((built_in && coding == ct[i]->built_in_coding) || - (!built_in && s == ct[i]->custom_coding.name))) { - val_error = false; - break; - } - } - } - if (val_error) { - enc_str->error("The encoding string does not match any encodings of " - "type `%s'", type->get_typename().c_str()); - } + enc_str->chk_dyn_enc_str(type); } } RunsOnScope* runs_on_scope = my_sb->get_scope_runs_on(); @@ -9872,7 +9842,7 @@ 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_function(false)-> + "}\n", ve->get_dec_type()->get_legacy_coding_function(false)-> get_genname_from_scope(scope).c_str(), par_name, par_name, par_name); } else if (legacy_codec_handling) { // legacy codec handling with built-in decoding @@ -10700,7 +10670,7 @@ 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_function(false)-> + "}\n", member_type->get_legacy_coding_function(false)-> get_genname_from_scope(scope).c_str(), static_cast<int>(i), static_cast<int>(i), static_cast<int>(i + 1), static_cast<int>(i), static_cast<int>(i + 1), static_cast<int>(i)); diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index dfa43924c92aaa538e1b8fb1df77f27728e462fd..49f7c02c85b0dce9e8ad0b325f04b14acfabac14 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -4929,7 +4929,7 @@ compile_time: "}\n" // make sure the bitstring is empty after decoding, display a warning otherwise "else if (bs.lengthof() != 0) {\n", - target_type_last->get_coding_function(false)->get_genname_from_scope(my_scope).c_str()); + target_type_last->get_legacy_coding_function(false)->get_genname_from_scope(my_scope).c_str()); } else { str = mputprintf(str, diff --git a/function_test/RAW_EncDec/RAW_EncDec_TD.fast_script b/function_test/RAW_EncDec/RAW_EncDec_TD.fast_script index e7ad559e72312f9202308a019c4ea6131537f8b9..8dafe4f06de5a83180fde4f1291f52149948b42d 100644 --- a/function_test/RAW_EncDec/RAW_EncDec_TD.fast_script +++ b/function_test/RAW_EncDec/RAW_EncDec_TD.fast_script @@ -6361,7 +6361,7 @@ if ((enc_RAW_PDU_170(i) == o)and(dec_RAW_PDU_170(o) == i)) {setverdict(pass);} //================================= // group raw attribute test 3 //================================= - +/* temporarily removed, because the new codec handling only takes the nearest group's variants into consideration group RAW_group47 { group grp_v1 { @@ -6478,7 +6478,7 @@ testcase TC_group_raw_attribute_test_6() runs on TempComp{ if ((enc_RAW_PDU_174(i) == o)and(dec_RAW_PDU_174(o) == i)) {setverdict(pass);} else {setverdict(fail);} -} +}*/ //================================= // group raw attribute test 7 //================================= @@ -7044,10 +7044,10 @@ control { execute(TC_Raw_update_test_16()); execute(TC_group_raw_attribute_test_1()); execute(TC_group_raw_attribute_test_2()); - execute(TC_group_raw_attribute_test_3()); + /*execute(TC_group_raw_attribute_test_3()); execute(TC_group_raw_attribute_test_4()); execute(TC_group_raw_attribute_test_5()); - execute(TC_group_raw_attribute_test_6()); + execute(TC_group_raw_attribute_test_6());*/ execute(TC_group_raw_attribute_test_7()); execute(TC_Fast_enc_dec_function()); execute(TC_Backtrack_decode_function()); diff --git a/function_test/Semantic_Analyser/Makefile.semantic b/function_test/Semantic_Analyser/Makefile.semantic index 3a1908f6ac24180f38e934008a0db98e65046d6f..9ddf3b0d32bc5ae11f82bdea769355d0e366cce0 100644 --- a/function_test/Semantic_Analyser/Makefile.semantic +++ b/function_test/Semantic_Analyser/Makefile.semantic @@ -12,11 +12,18 @@ # Szabo, Bence Janos # ############################################################################## -SADIRS := ver xer encode param template any_from pattern_ref float recof_index \ +SADIRS := ver param template any_from pattern_ref float recof_index \ port_translation mtc_and_system_clause ifdef RT2 SADIRS += deprecated erroneous_attributes template_concat endif + +ifdef LEGACY_CODEC_HANDLING +SADIRS += encode_legacy xer +else +SADIRS += encode +endif + #$(wildcard TTCN3_[a0-9]* ASN_[a0-9]*) ver xer all run check clean distclean: diff --git a/function_test/Semantic_Analyser/TTCN3_SA_1_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_1_TD.script index 385322c207844550a846fc7362022b1be7372a32..edc47e240c0a3ad44bd8b8ec5cb6797d46c63ad7 100644 --- a/function_test/Semantic_Analyser/TTCN3_SA_1_TD.script +++ b/function_test/Semantic_Analyser/TTCN3_SA_1_TD.script @@ -10549,7 +10549,7 @@ module ModuleA { } <END_MODULE> <RESULT IF_FAIL COUNT 2> -(?im)\berror\b.+Invalid field qualifier +(?im)\berror\b.+Reference to non-existent field <END_RESULT> <RESULT IF_PASS NEGATIVE> (?im)\bwarning\b @@ -10581,7 +10581,7 @@ module ModuleA { } <END_MODULE> <RESULT IF_FAIL COUNT 1> -(?im)\berror\b.+Invalid field qualifier +(?im)\berror\b.+Reference to non-existent field <END_RESULT> <RESULT IF_PASS NEGATIVE> (?im)\bwarning\b diff --git a/function_test/Semantic_Analyser/common.mk b/function_test/Semantic_Analyser/common.mk index e549557aeccb1770d846ff44fc8fe0f0fb3c7d8d..558c5f1d86a7494bc0e62919397afecabef1a3a8 100644 --- a/function_test/Semantic_Analyser/common.mk +++ b/function_test/Semantic_Analyser/common.mk @@ -21,9 +21,10 @@ ifdef RT2 COMPILER_FLAGS += -R endif -# Use the legacy handling of 'encode' and 'variant' for now. -# Tests will be updated when the new handling is fully implemented (TODO). +# Use the legacy handling of 'encode' and 'variant' in tests. +ifdef LEGACY_CODEC_HANDLING COMPILER_FLAGS += -e +endif # TTCN-3 modules of this project: TTCN3_MODULES := $(sort $(wildcard *A.ttcn *S[WE].ttcn *OK.ttcn)) diff --git a/function_test/Semantic_Analyser/encode/.gitignore b/function_test/Semantic_Analyser/encode/.gitignore index f34a2637bfccb7aebc3061599c6c7931140a05f9..e2d293255e6d2f314e34950e486a48630d873491 100644 --- a/function_test/Semantic_Analyser/encode/.gitignore +++ b/function_test/Semantic_Analyser/encode/.gitignore @@ -1,2 +1,2 @@ !Makefile -!*.ttcn \ No newline at end of file +!*.ttcn diff --git a/function_test/Semantic_Analyser/encode/Makefile b/function_test/Semantic_Analyser/encode/Makefile index 3013e127cda91ca39ffc2e2bc75bf7257617e677..3f369041a92da0cee70b4c0706e820636e205fde 100644 --- a/function_test/Semantic_Analyser/encode/Makefile +++ b/function_test/Semantic_Analyser/encode/Makefile @@ -6,7 +6,6 @@ # http://www.eclipse.org/legal/epl-v10.html # # Contributors: -# Balasko, Jeno # Baranyi, Botond # ############################################################################## diff --git a/function_test/Semantic_Analyser/encode/encode_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_SE.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..9aa460c1271a4ce7945f688cfdf9cf5c8fa05f74 --- /dev/null +++ b/function_test/Semantic_Analyser/encode/encode_SE.ttcn @@ -0,0 +1,140 @@ +/****************************************************************************** + * 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: + * Baranyi, Botond + * + ******************************************************************************/ + +module encode_SE { //^In TTCN-3 module// + +type record Rec1 { //^In type definition// + integer f1 +} +with { + variant "name as uncapitalized"; //No encoding rules defined for type// +} + +type record Rec2 { //^In type definition// + integer f1 +} +with { + encode "XML"; + variant "name as uncapitalizeded"; //in variant attribute, at or before token `uncapitalizeded'\: syntax error, unexpected XIdentifier// +} + +type record Rec3 { //^In type definition// + integer f1 +} +with { + encode "JSON"; + variant "name as uncapitalized"; //Variant attribute is not related to JSON encoding// +} + +type record Rec4 { //^In type definition// + charstring f1, + Rec2 f2, + Rec3 f3 +} +with { + encode "XML"; + variant "name as uncapitalized"; + variant (f1) "16 bit"; //Variant attribute is not related to XER encoding// + encode (f2) "RAW"; + encode (f2) "JSON"; + variant (f2) "FIELDLENGTH(16)"; //The encoding reference is mandatory for variant attributes of type `@encode_SE.Rec2', which has multiple encodings// + variant (f2) "RAW"."ALIGN(left)"; + variant (f2) "JSON"."untagged"; //Variant attribute is not related to JSON encoding// + variant (f2) "XML"."name as 'abc'"; //Type `@encode_SE.Rec2' does not support XER encoding// + variant (f3) "untagged"; //Variant attribute is not related to JSON encoding// +} + +type record Rec5 { //^In type definition// //Invalid attribute, 'as value' is only allowed for unions, the anytype, or records or sets with one field// + integer f1, //Invalid attribute, 'omit as null' requires optional field of a record or set.// + Rec4 f2, //USE-UNION can only be applied to a CHOICE/union type// + record of Rec3 f3 //Invalid attribute, 'name as ...' requires field of a record, set or union.// //JSON default values are not available for type `Rec5_f3'// +} +with { + encode "RAW"; + encode "JSON"; + variant "RAW"."FIELDLENGTH(50)"; + variant "JSON"."JSON: as value"; + variant (f1) "RAW"."COMP(nosign)"; + variant (f1) "JSON"."JSON: omit as null"; + variant (f2) "useUnion"; + variant (f3) "RAW"."BYTEORDER(first)"; + variant (f3) "JSON"."JSON: default(30)"; + variant (f3[-]) "JSON: name as def"; + encode (f3[-].f1) "TEXT"; //Encode attribute is ignored, because it refers to a type from a different type definition// + variant (f3[-].f1) "TEXT_CODING(length=5;leading0=true)"; //Variant attribute is ignored, because it refers to a type from a different type definition// +} + +type set of integer SetOf1 //^In type definition// +with { + encode "abc"; + encode "XML"; + variant "abc"."some variant"; //Variant attributes related to custom encoding are ignored// + variant ([-]) "abc"."FIELDLENGTH(20)"; //Variant attributes related to custom encoding are ignored// + variant ([-]) "xyz"."some other variant"; //Type `integer' does not support custom encoding `xyz'// +} + +external function f_enc_xy1(in SetOf2 x) return bitstring + with { extension "prototype(convert) encode(xy)" } + +type set of Rec3 SetOf2 +with { + encode "xy"; +} + +external function f_enc_xy2(in SetOf2 x) return bitstring + with { extension "prototype(convert) encode(xy)" } + +external function f_dec_xy1(inout bitstring x, out SetOf2 y) return integer + with { extension "prototype(sliding) decode(xy)" } + +type set of SetOf2 SetOf3 +with { + encode "xy"; +} + +external function f_dec_xy2(inout bitstring x, out SetOf3[-] y) return integer + with { extension "prototype(sliding) decode(xy)" } + +function f1() { //^In function definition// + var bitstring bs; + var universal charstring ucs; + var integer i; + var Rec3 r3; + var Rec4 r4; + var SetOf2 so2; //Multiple `xy' encoder functions defined for type// + var SetOf3 so3; //No `xy' decoder function defined for type// + const universal charstring c_enc := "JSON"; + bs := encvalue(Rec1: { 1 }, "", "XML"); //^In variable assignment// //^In the first parameter of encvalue// //No coding rule specified for type// + ucs := encvalue_unichar(Rec2: { 2 }, "UTF-8", "qqqqqqqqq", c_enc); //^In variable assignment// //In the fourth operand of encvalue_unichar// //The encoding string does not match any encodings of type// + i := decvalue(bs, r3, i, "abc"); //^In variable assignment// //^In the third parameter of decvalue// //Third operand of operation `decvalue' should be \(universal\) charstring value// //In the fourth operand of decvalue// //The encoding string does not match any encodings of type// + i := decvalue_unichar(ucs, r4, "UTF-8", "...", r3); //^In variable assignment// //^In the fifth operand of decvalue_unichar// //Fifth operand of operation `decvalue_unichar' should be \(universal\) charstring value// + bs := encvalue(so2); + i := decvalue(bs, so3[-]); + var template charstring dm := decmatch so3; +} + +external function f_enc_xy3(in SetOf2 x) return bitstring + with { extension "prototype(convert) encode(xy)" } + +external function f_dec_xy3(inout bitstring x, out SetOf2 y) return integer + with { extension "prototype(sliding) decode(xy)" } + +type component CT {} + +function f2() runs on CT { //^In function definition// + self.setencode(Rec1, "BER:2002"); //^In setencode statement// //The type argument has no encoding rules defined// + self.setencode(Rec2, "RAW"); //^In setencode statement// //The type argument has only one encoding rule defined. The 'setencode' statement will be ignored// //^In the second argument// //The encoding string does not match any encodings of type// + self.setencode(Rec3, 12); //^In setencode statement// //The type argument has only one encoding rule defined. The 'setencode' statement will be ignored// //^In the second argument// //character string value was expected// + self.setencode(Rec4.f2, "TEXT"); //^In setencode statement// //^In the second argument// //The encoding string does not match any encodings of type// +} + +} diff --git a/function_test/Semantic_Analyser/encode/encode_grp_mod_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_grp_mod_SE.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..b1c32b9d000b01abf41b025d8939af0eb8f2d931 --- /dev/null +++ b/function_test/Semantic_Analyser/encode/encode_grp_mod_SE.ttcn @@ -0,0 +1,69 @@ +/****************************************************************************** + * 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: + * Baranyi, Botond + * + ******************************************************************************/ + +module encode_grp_mod { //^In TTCN-3 module// + +type union Uni1 { //^In type definition// + integer f1 +} +with { + variant "JSON: as value"; + variant (f1) "FIELDLENGTH(20)"; //Variant attribute is not related to JSON encoding// +} + +type union Uni2 { //^In type definition// + integer f1 //Attribute 'name as ...' will be ignored, because parent union is encoded without field names.// +} +with { + encode "RAW"; + variant "JSON: as value"; //Variant attribute is not related to RAW encoding// + variant (f1) "FIELDLENGTH(16)"; + variant (f1) "JSON: name as f2"; //Variant attribute is not related to RAW encoding// +} + +group Group1 { + type union Uni3 { //^In type definition// + integer f1 + } + with { + variant "JSON: as value"; //Variant attribute is not related to XER encoding// + variant (f1) "FIELDLENGTH(20)"; //Variant attribute is not related to XER encoding// + } +} +with { + encode "XML"; +} + +type Uni2 Uni4 //^In type definition// +with { + variant "name as uncapitalized"; //Variant attribute is not related to RAW encoding// +} + +type record of integer RecOf1 +with { + encode "TEXT"; +} + +type record of RecOf1 RecOf2 //^In type definition// +with { + variant ([-]) "list"; //Variant attribute is not related to TEXT encoding// +} + +type RecOf1 RecOf3 //^In type definition// +with { + variant "BYTEORDER(first)"; //Variant attribute is not related to TEXT encoding// +} + +} +with { + encode "JSON"; +} diff --git a/function_test/Semantic_Analyser/encode_legacy/.gitignore b/function_test/Semantic_Analyser/encode_legacy/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f34a2637bfccb7aebc3061599c6c7931140a05f9 --- /dev/null +++ b/function_test/Semantic_Analyser/encode_legacy/.gitignore @@ -0,0 +1,2 @@ +!Makefile +!*.ttcn \ No newline at end of file diff --git a/function_test/Semantic_Analyser/encode_legacy/Makefile b/function_test/Semantic_Analyser/encode_legacy/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3013e127cda91ca39ffc2e2bc75bf7257617e677 --- /dev/null +++ b/function_test/Semantic_Analyser/encode_legacy/Makefile @@ -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: +# Balasko, Jeno +# Baranyi, Botond +# +############################################################################## +include ../common.mk diff --git a/function_test/Semantic_Analyser/encode/Types_A.asn b/function_test/Semantic_Analyser/encode_legacy/Types_A.asn similarity index 100% rename from function_test/Semantic_Analyser/encode/Types_A.asn rename to function_test/Semantic_Analyser/encode_legacy/Types_A.asn diff --git a/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn b/function_test/Semantic_Analyser/encode_legacy/encode_asn_SE.ttcn similarity index 100% rename from function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn rename to function_test/Semantic_Analyser/encode_legacy/encode_asn_SE.ttcn diff --git a/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn b/function_test/Semantic_Analyser/encode_legacy/encode_ttcn_SE.ttcn similarity index 100% rename from function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn rename to function_test/Semantic_Analyser/encode_legacy/encode_ttcn_SE.ttcn diff --git a/function_test/Semantic_Analyser/encode_legacy/t b/function_test/Semantic_Analyser/encode_legacy/t new file mode 100755 index 0000000000000000000000000000000000000000..3a4b58ec16cf2f1390a36c7a92f8823e3b94b425 --- /dev/null +++ b/function_test/Semantic_Analyser/encode_legacy/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/function_test/Semantic_Analyser/xer/dfe_ref_SE.ttcn b/function_test/Semantic_Analyser/xer/dfe_ref_SE.ttcn index 376a321382679249146bfdaf91dd6541e327cd66..7e1e9e3bc53d81a483e96ee5f6a45b188a7c1a5d 100644 --- a/function_test/Semantic_Analyser/xer/dfe_ref_SE.ttcn +++ b/function_test/Semantic_Analyser/xer/dfe_ref_SE.ttcn @@ -14,12 +14,12 @@ module dfe_ref_SE { //^In TTCN-3 module `dfe_ref_SE':// const octetstring c_oct := 'AA'O; type record DFEConst { //^In type definition// - charstring cs, //^In record field \`cs\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type DFEConst_cs// - universal charstring us, //^In record field \`us\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type DFEConst_us// - integer i, //^In record field \`i\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type DFEConst_i// - float f, //^In record field \`f\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type DFEConst_f// - boolean b, //^In record field \`b\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type DFEConst_b// - charstring csmissing //^In record field \`csmissing\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type DFEConst_csmissing// + charstring cs, //^In record field \`cs\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type charstring// + universal charstring us, //^In record field \`us\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type universal charstring// + integer i, //^In record field \`i\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type integer// + float f, //^In record field \`f\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type float// + boolean b, //^In record field \`b\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type boolean// + charstring csmissing //^In record field \`csmissing\'\:// //^error: DEFAULT\-FOR\-EMPTY not supported for character\-encodable type charstring// } with { variant "element"; diff --git a/function_test/Semantic_Analyser/xer/useunion_not_union_SE.ttcn b/function_test/Semantic_Analyser/xer/useunion_not_union_SE.ttcn index 2ef06a832102e3ae7324837b45f84722625c0e0b..573716061a222e2f97bd91750d5b7966830a0a47 100644 --- a/function_test/Semantic_Analyser/xer/useunion_not_union_SE.ttcn +++ b/function_test/Semantic_Analyser/xer/useunion_not_union_SE.ttcn @@ -13,7 +13,7 @@ module useunion_not_union_SE { //^In TTCN-3 module `useunion_not_union_SE':// type record uu { //^In type definition// \ - //^error: USE-UNION can only applied to a CHOICE/union type// + //^error: USE-UNION can only be applied to a CHOICE/union type// } with { variant "useUnion" @@ -21,7 +21,7 @@ with { } type enumerated truth { //^In type definition// \ - //^error: USE-UNION can only applied to a CHOICE/union type// + //^error: USE-UNION can only be applied to a CHOICE/union type// TRUE, FALSE, FILE_NOT_FOUND } with { @@ -30,7 +30,7 @@ with { } type record of integer ints //^In type definition// \ - //^error: USE-UNION can only applied to a CHOICE/union type// + //^error: USE-UNION can only be applied to a CHOICE/union type// with { variant "useUnion" } diff --git a/regression_test/Makefile.regression b/regression_test/Makefile.regression index 78abcdc0ad2581464016050e7605142d5ab881cb..39dc262bce28a997c1b0f90273052490d24ddec7 100644 --- a/regression_test/Makefile.regression +++ b/regression_test/Makefile.regression @@ -58,7 +58,7 @@ LTTNGUSTLOGGER := no #SPLIT_TO_SLICES := 30 # Use legacy codec handling when running the tests -LEGACY_CODEC_HANDLING := yes +#LEGACY_CODEC_HANDLING := yes ifdef RT2 # add command line option to generate code for alternative runtime diff --git a/regression_test/XML/UseNilLong/UsefulTtcn3Types.ttcn b/regression_test/XML/UseNilLong/UsefulTtcn3Types.ttcn index bb0af9214a614fee6933466fad86c66df0a0560b..448c6504a22acd8e3a59d5980f702744dbe41ac0 100644 --- a/regression_test/XML/UseNilLong/UsefulTtcn3Types.ttcn +++ b/regression_test/XML/UseNilLong/UsefulTtcn3Types.ttcn @@ -91,5 +91,5 @@ module UsefulTtcn3Types { } with { -encode "X"; +encode "XML"; } diff --git a/regression_test/json/SemanticCheck.ttcn b/regression_test/json/SemanticCheck.ttcn index d53c275a0062b9da7c03ffa68ff9793fc208f7f4..1377704cfea05de9cdcb1460cf50bb7d93d74d17 100644 --- a/regression_test/json/SemanticCheck.ttcn +++ b/regression_test/json/SemanticCheck.ttcn @@ -47,6 +47,7 @@ type union EmbeddedUnion octetstring bytes } with { + encode "JSON"; variant "JSON: as value"; } diff --git a/regression_test/multipleEncodings/Coders.cc b/regression_test/multipleEncodings/Coders.cc index b55da3834c83db514519a3db6b9af2e585d2c23c..4b909763c81abda16393e017c2a33b5a1c82e998 100644 --- a/regression_test/multipleEncodings/Coders.cc +++ b/regression_test/multipleEncodings/Coders.cc @@ -56,5 +56,20 @@ namespace TtcnTypes { return 1; } } + + INTEGER f__dec__abc2(BITSTRING& x, R1& y) + { + if (x == oct2bit(char2oct("abc"))) { + y.f1() = E1::val2; + x = BITSTRING(0, NULL); + return 0; + } + else if (x.lengthof() < 24) { + return 2; + } + else { + return 1; + } + } } diff --git a/regression_test/multipleEncodings/Testcases.ttcn b/regression_test/multipleEncodings/Testcases.ttcn index ae0249ca032ee9a21a029f5fa694f8c4c16d8094..a9fca73c7810a97e31dc55a7d1ec7e256d3f9f10 100644 --- a/regression_test/multipleEncodings/Testcases.ttcn +++ b/regression_test/multipleEncodings/Testcases.ttcn @@ -61,7 +61,8 @@ testcase tc_ttcn_encvalue_negtest() runs on CT { } @try { - var bitstring dummy := encvalue(x, "", "ab" & char(0, 1, 2, 3)); // invalid encoding + var universal charstring bad_coding := "ab" & char(0, 1, 2, 3); + var bitstring dummy := encvalue(x, "", bad_coding); // invalid encoding setverdict(fail, "Error expected."); } @catch (msg) { @@ -184,6 +185,24 @@ testcase tc_ttcn_param_redirect() runs on CT { } } +// Testing encvalue_unichar and decvalue unichar with custom encoding on a type reference, +// that has its own decoder function, separate from the referenced type +testcase tc_ttcn_custom_coding_w_ref_types() runs on CT { + var R3 x := { f1 := val2 }; + var universal charstring exp := "abc"; + var universal charstring enc := encvalue_unichar(x, "UTF-8", "", "abc"); // uses R1's encoder: f_enc_abc + if (exp != enc) { + setverdict(fail, "Expected: ", exp, ", got: ", enc); + } + + var R3 dec; + var integer res := decvalue_unichar(exp, dec, "UTF-8", "", "abc"); // uses its own decoder: f_dec_abc2 + if (x != dec) { + setverdict(fail, "Expected: ", x, ", got: ", dec); + } + setverdict(pass); +} + // Testing setencode on encvalue and decvalue, with a type that has 2 encodings. testcase tc_ttcn_setencode() runs on CT { var R1 x := { f1 := val1 }; @@ -446,6 +465,7 @@ control { execute(tc_ttcn_decvalue_unichar()); execute(tc_ttcn_decmatch()); execute(tc_ttcn_param_redirect()); + execute(tc_ttcn_custom_coding_w_ref_types()); execute(tc_ttcn_setencode()); execute(tc_ttcn_setencode_negtest()); execute(tc_ttcn_setencode_ref_type()); diff --git a/regression_test/multipleEncodings/TtcnTypes.ttcn b/regression_test/multipleEncodings/TtcnTypes.ttcn index 15881cb3529e190fa104c40de84761c9fed70eb0..22560d2171b6cc21a5e503903915793670103409 100644 --- a/regression_test/multipleEncodings/TtcnTypes.ttcn +++ b/regression_test/multipleEncodings/TtcnTypes.ttcn @@ -15,6 +15,9 @@ module TtcnTypes { external function f_dec_abc(inout bitstring x, out R1 y) return integer with { extension "prototype(sliding) decode(abc)" } +external function f_dec_abc2(inout bitstring x, out R3 y) return integer + with { extension "prototype(sliding) decode(abc)" } + type enumerated E1 { val1, val2, val3 } with { encode "TEXT"; @@ -34,6 +37,8 @@ with { type R1 R2; +type R2 R3; + type union U1 { integer alt1 }