diff --git a/README.md b/README.md index 64d00bbde20526845485928141a7adbaf2aab8ce..f6790aa7441ec8314cec0ff6da851b5a24ad13f8 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,19 @@ ASN.1 (Abstract Syntax Notation One). * https://www.eclipse.org/forums/index.php/f/297/ +# Bugzilla + +* https://bugs.eclipse.org/bugs/buglist.cgi?field0-0-0=product&field0-0-1=component&list_id=15328562&order=changeddate%2Cbug_status%20DESC%2Creporter%20DESC%2Ccomponent%2Cassigned_to%2Cpriority%2Cbug_severity&query_based_on=&query_format=advanced&type0-0-0=substring&type0-0-1=substring&value0-0-0=Titan&value0-0-1=Titan + # Openhub page: * https://www.openhub.net/p/eclipse_titan/ -##Introductory video of a presentation about Titan held at EclipseCon 2014: +## Introductory video of a presentation about Titan held at EclipseCon 2014: * https://www.youtube.com/watch?v=2knzZuwzn-Y. -##Titan Datasheet on polarsys.org: +## Titan Datasheet on polarsys.org: http://polarsys.org/sites/default/files/custom_uploads/TITAN%20Datasheet%20A4%202.1.pdf ## Ericsson TTCN-3 Course, Presentation material @@ -36,7 +40,7 @@ https://www.eclipse.org/downloads/download.php?file=/titan/TITAN_User_P.pdf -##Binaries and SHA512 checksums for a number of Linux platforms can be downloaded from: +## Binaries for a number of Linux platforms can be downloaded from: * https://projects.eclipse.org/projects/tools.titan/downloads @@ -44,7 +48,7 @@ https://www.eclipse.org/downloads/download.php?file=/titan/TITAN_User_P.pdf # Related products: -##Eclipse IDE plug-ins (Designer, Executor, LogViewer, Titanium): +## Eclipse IDE plug-ins (Designer, Executor, LogViewer, Titanium): Source code: diff --git a/common/ttcn3float.hh b/common/ttcn3float.hh index 63ccb75edac2e26410cc34de5145bbbcd6597d85..104a893fd13995f490f0a3e0b33a9fc85b692c50 100644 --- a/common/ttcn3float.hh +++ b/common/ttcn3float.hh @@ -67,6 +67,10 @@ struct ttcn3float { /// Address-of, for scanf double* operator&() { return &value; } + + double operator+(const ttcn3float& x) const { + return value + x.value; + } const ttcn3float& operator+=(double d) { value += d; diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 55715514829b345bd678e25031852c30a4f15b21..1885e5d2f99e7d05257bb9c3fba12bd0a1264f3e 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -3110,7 +3110,8 @@ namespace Common { /** \todo review, especially the string types... */ bool Type::is_compatible_tt_tt(typetype_t p_tt1, typetype_t p_tt2, - bool p_is_asn11, bool p_is_asn12) + bool p_is_asn11, bool p_is_asn12, + bool same_module) { if (p_tt2 == T_ERROR) return true; switch (p_tt1) { @@ -3253,6 +3254,8 @@ namespace Common { return p_tt2==T_SET_A || p_tt2==T_SET_T; case T_ANY: return p_tt2 == T_ANY || p_tt2 == T_OSTR; + case T_ANYTYPE: + return p_tt2 == T_ANYTYPE && same_module; // Need same module // these should never appear? case T_REFD: case T_REFDSPEC: @@ -3265,7 +3268,7 @@ namespace Common { } } - bool Type::is_compatible_tt(typetype_t p_tt, bool p_is_asn1) + bool Type::is_compatible_tt(typetype_t p_tt, bool p_is_asn1, Type* p_type) { chk(); Type *t1=get_type_refd_last(); @@ -3278,8 +3281,16 @@ namespace Common { case T_ADDRESS: FATAL_ERROR("Type::is_compatible_tt()"); return false; - default: - return is_compatible_tt_tt(t1->typetype, p_tt, is_asn1(), p_is_asn1); + default: { + bool same_mod = false; + if (p_type && p_type->get_my_scope()) { + if (t1->get_my_scope()->get_scope_mod() == + p_type->get_my_scope()->get_scope_mod()) { + same_mod = true; + } + } + return is_compatible_tt_tt(t1->typetype, p_tt, is_asn1(), p_is_asn1, same_mod); + } } } @@ -5713,7 +5724,6 @@ namespace Common { case T_FUNCTION: // TTCN-3 case T_ALTSTEP: // TTCN-3 case T_TESTCASE: // TTCN-3 - case T_ANYTYPE: // TTCN-3 anytype return memory.remember(t, ANSWER_NO); case T_UNDEF: @@ -5723,7 +5733,9 @@ namespace Common { case T_SEQ_T: case T_SET_T: - case T_CHOICE_T: { + case T_CHOICE_T: + case T_ANYTYPE: // TTCN-3 anytype + { // No field may reject XER size_t ncomp = t->get_nof_comps(); for (size_t i = 0; i < ncomp; ++i) { diff --git a/compiler2/Type.hh b/compiler2/Type.hh index dabb1b70e4ff6393bab37eb962da2b2198e8bd3d..1715ce1ff14d1dda8b69a292e63fe73deea1cb4a 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -582,15 +582,17 @@ namespace Common { /** Return whether the two typetypes are compatible. Sometimes, this is * just a question of \p p_tt1 == \p p_tt2. When there are multiple * typetypes for a type (e.g. T_ENUM_A and T_ENUM_T) then all - * combinations of those are compatible. */ + * combinations of those are compatible. In case of anytype the + * module has to be the same */ static bool is_compatible_tt_tt(typetype_t p_tt1, typetype_t p_tt2, - bool p_is_asn11, bool p_is_asn12); + bool p_is_asn11, bool p_is_asn12, + bool same_module); /** Returns whether the type is compatible with \a p_tt. Used if the * other value is unfoldable, but we can determine its expr_typetype. * Note: The compatibility relation is asymmetric. The function returns * true if the set of possible values in \a p_type is a subset of * possible values in \a this. */ - bool is_compatible_tt(typetype_t p_tt, bool p_is_asn1); + bool is_compatible_tt(typetype_t p_tt, bool p_is_asn1, Type* p_type = 0); /** Returns whether this type is compatible with \a p_type. Note: The * compatibility relation is asymmetric. The function returns true if * the set of possible values in \a p_type is a subset of possible values diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index e9ec54f99ae99aa4c1bc75c0f65c9b2d4fc27f55..5e0c32a48a7676c396e05a102202d127a66bf877 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -105,6 +105,10 @@ void Type::chk() break; case T_ANYTYPE: // TODO maybe check for address type and add it automagically, then fall through + if(!xerattrib) { + xerattrib = new XerAttributes; + } + xerattrib->untagged_ = true; case T_SEQ_T: case T_SET_T: case T_CHOICE_T: @@ -833,7 +837,11 @@ Value *Type::new_value_for_dfe(Type *last, const char *dfe_str, Common::Referenc delete v; return 0; } - if (!is_compatible_tt_tt(last->typetype, v->get_expr_governor_last()->typetype, last->is_asn1(), t->is_asn1())) { + bool same_mod = false; + if (last->get_my_scope()->get_scope_mod() == t->get_my_scope()->get_scope_mod()) { + 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_expr_governor_last()->get_typename().c_str(), last->get_typename().c_str()); delete v; @@ -933,8 +941,7 @@ Value *Type::new_value_for_dfe(Type *last, const char *dfe_str, Common::Referenc return new Value(Common::Value::V_ENUM, val_id); } - - case T_CHOICE_A: case T_CHOICE_T: { + case T_CHOICE_A: case T_CHOICE_T: case T_ANYTYPE: { // Try to guess which alternative the given DFE text belongs to. // Sort the fields based on typetype, so BOOL, INT, REAL, ENUM // are tried before the various string types @@ -1548,6 +1555,7 @@ void Type::chk_xer_untagged() // fall through case T_SEQ_A: case T_SEQ_T: case T_SET_A: case T_SET_T: + case T_ANYTYPE: case T_CHOICE_A: case T_CHOICE_T: case T_SEQOF: case T_SETOF: break; // acceptable @@ -1598,7 +1606,8 @@ void Type::chk_xer_untagged() "the member of a sequence-of or set-of"); // X.693amd1, 32.2.4 b) break; - case T_CHOICE_T: { + case T_CHOICE_T: + case T_ANYTYPE: { size_t num_fields = parent_type->get_nof_comps(); size_t num_empty = 0; for (size_t i = 0; i < num_fields; ++i) { @@ -1756,6 +1765,7 @@ void Type::chk_xer_use_nil() case T_SEQ_A: case T_SET_T: case T_SET_A: + case T_ANYTYPE: case T_CHOICE_T: case T_CHOICE_A: case T_SEQOF: @@ -1995,7 +2005,6 @@ void Type::chk_xer_use_type() if (!prefix) error("Type has USE-TYPE, but the module has no control namespace set"); switch (last->typetype) { - // USE-TYPE applied to anytype ? Just say no. case T_CHOICE_A: case T_CHOICE_T: { // must be CHOICE; 37.2.1 if (xerattrib->untagged_ || xerattrib->useUnion_) { // 37.2.5 error("A type with USE-TYPE encoding instruction shall not also have" @@ -2022,6 +2031,9 @@ void Type::chk_xer_use_type() } } break; } + case T_ANYTYPE: + error("USE-TYPE cannot be applied to anytype"); + break; default: error("USE-TYPE can only applied to a CHOICE/union type"); break; @@ -2047,6 +2059,9 @@ void Type::chk_xer_use_union() else cf->error("Alternative of a CHOICE/union with USE-UNION must be character-encodable"); } break; } + case T_ANYTYPE: + error("USE-UNION cannot be applied to anytype"); + break; default: error("USE-UNION can only applied to a CHOICE/union type"); // 38.2.1 break; @@ -2408,6 +2423,7 @@ void Type::chk_xer() { // XERSTUFF semantic check switch (cft->get_type_refd_last()->typetype) { case T_SEQ_A: case T_SEQ_T: case T_SET_A: case T_SET_T: + case T_ANYTYPE: case T_CHOICE_A: case T_CHOICE_T: case T_SEQOF: case T_SETOF: @@ -2449,7 +2465,7 @@ void Type::chk_xer() { // XERSTUFF semantic check } // if the_one if (empties.size() > 1 - && (typetype==T_CHOICE_A || typetype==T_CHOICE_T)) { + && (typetype==T_CHOICE_A || typetype==T_CHOICE_T || typetype==T_ANYTYPE)) { warning("More than one field can have empty XML. Decoding of empty" " XML is ambiguous, %s chosen arbitrarily.", empties.get_nth_elem(empties.size()-1)->get_name().get_name().c_str()); @@ -3210,14 +3226,14 @@ bool Type::chk_this_value(Value *value, Common::Assignment *lhs, expected_value_ return chk_this_refd_value(value, lhs, expected_value, 0, is_str_elem); case Value::V_INVOKE: chk_this_invoked_value(value, lhs, expected_value); - return false; // assumes no self-ref in invoke + return false; // assumes no self-reference in invoke case Value::V_EXPR: if (lhs) self_ref = value->chk_expr_self_ref(lhs); // no break case Value::V_MACRO: if (value->is_unfoldable(0, expected_value)) { typetype_t tt = value->get_expr_returntype(expected_value); - if (!is_compatible_tt(tt, value->is_asn1())) { + if (!is_compatible_tt(tt, value->is_asn1(), value->get_expr_governor_last())) { value->error("Incompatible value: `%s' value was expected", get_typename().c_str()); value->set_valuetype(Value::V_ERROR); @@ -5871,6 +5887,32 @@ bool Type::chk_this_template_Str(Template *t, namedbool implicit_omit, } } break; + case Ttcn::Template::TEMPLATE_CONCAT: + { + Error_Context cntxt(t, "In template concatenation"); + t->set_lowerid_to_ref(); + Template* t_left = t->get_concat_operand(true); + Template* t_right = t->get_concat_operand(false); + if (tt == T_CSTR || tt == T_USTR) { + if (t_left->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE && + t_left->get_templatetype() != Ttcn::Template::TEMPLATE_CONCAT && + t_left->get_templatetype() != Ttcn::Template::TEMPLATE_REFD) { + t_left->error("Operands of %s template concatenation must be " + "specific value templates", get_typename_builtin(tt)); + } + if (t_right->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE && + t_right->get_templatetype() != Ttcn::Template::TEMPLATE_CONCAT && + t_right->get_templatetype() != Ttcn::Template::TEMPLATE_REFD) { + t_right->error("Operands of %s template concatenation must be " + "specific value templates", get_typename_builtin(tt)); + } + } + self_ref = chk_this_template_generic(t_left, INCOMPLETE_NOT_ALLOWED, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs); + self_ref = chk_this_template_generic(t_right, INCOMPLETE_NOT_ALLOWED, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs); + } + break; default: report_error = true; break; @@ -6398,6 +6440,18 @@ bool Type::chk_this_template_SeqOf(Template *t, namedbool incomplete_allowed, delete index_map.get_nth_elem(i); index_map.clear(); break; } + case Ttcn::Template::TEMPLATE_CONCAT: + { + Error_Context cntxt(t, "In template concatenation"); + Template* t_left = t->get_concat_operand(true); + Template* t_right = t->get_concat_operand(false); + t->set_lowerid_to_ref(); + self_ref = chk_this_template_generic(t_left, incomplete_allowed, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs); + self_ref = chk_this_template_generic(t_right, incomplete_allowed, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs); + } + break; default: t->error("%s cannot be used for `record of' type `%s'", t->get_templatetype_str(), get_typename().c_str()); @@ -6532,6 +6586,18 @@ bool Type::chk_this_template_SetOf(Template *t, namedbool incomplete_allowed, delete index_map.get_nth_elem(i); index_map.clear(); break; } + case Ttcn::Template::TEMPLATE_CONCAT: + { + Error_Context cntxt(t, "In template concatenation"); + Template* t_left = t->get_concat_operand(true); + Template* t_right = t->get_concat_operand(false); + t->set_lowerid_to_ref(); + self_ref = chk_this_template_generic(t_left, incomplete_allowed, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs); + self_ref = chk_this_template_generic(t_right, incomplete_allowed, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs); + } + break; default: t->error("%s cannot be used for `set of' type `%s'", t->get_templatetype_str(), get_typename().c_str()); diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index b86aba055f824e07a6ab3bda280e222bf43a0eaa..0e7fd7ce97b5fa4ccffcd0b4bcd75d7673e63d0b 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -606,9 +606,7 @@ void Type::generate_code_xerdescriptor(output_struct* target) size_t last_len = 2 + last_s.size(); // 2 for > \n size_t bxer_len = 2 + bxer_name.size(); // 2 for > \n - if ((T_SEQOF == last->typetype || T_SETOF == last->typetype) && - T_ANYTYPE != last->u.seof.ofType->get_type_refd_last()->typetype) { - // anytypes don't have XER descriptors + if ((T_SEQOF == last->typetype || T_SETOF == last->typetype)) { oftype_descr_name = mprintf("&%s_xer_", last->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str()); } diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 2784f2a63206707085ad6003626925b930cc0a2f..587800c6ca7701826e5c394b52d3ad0151cbd2e6 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -375,6 +375,10 @@ namespace Common { case V_REFER: u.refered = p.u.refered->clone(); break; + case V_ANY_VALUE: + case V_ANY_OR_OMIT: + u.len_res = p.u.len_res != NULL ? p.u.len_res->clone() : NULL; + break; default: FATAL_ERROR("Value::Value()"); } // switch @@ -467,6 +471,10 @@ namespace Common { case V_UNDEF_BLOCK: delete u.block; break; + case V_ANY_VALUE: + case V_ANY_OR_OMIT: + delete u.len_res; + break; default: FATAL_ERROR("Value::clean_up()"); } // switch @@ -1419,6 +1427,20 @@ namespace Common { FATAL_ERROR("Value::Value()"); } // switch } + + // V_ANY_VALUE, V_ANY_OR_OMIT + Value::Value(valuetype_t p_vt, Ttcn::LengthRestriction* p_len_res) + : GovernedSimple(S_V), valuetype(p_vt), my_governor(0) + { + switch(p_vt) { + case V_ANY_VALUE: + case V_ANY_OR_OMIT: + u.len_res = p_len_res; + break; + default: + FATAL_ERROR("Value::Value()"); + } // switch + } Value::~Value() { @@ -1436,6 +1458,24 @@ namespace Common { FATAL_ERROR("Value::get_optype()"); return u.expr.v_optype; } + + Value* Value::get_concat_operand(bool first_operand) const + { + if (valuetype != V_EXPR || u.expr.v_optype != OPTYPE_CONCAT) { + FATAL_ERROR("Value::get_concat_operand()"); + } + return first_operand ? u.expr.v1 : u.expr.v2; + } + + Ttcn::LengthRestriction* Value::take_length_restriction() + { + if (valuetype != V_ANY_VALUE && valuetype != V_ANY_OR_OMIT) { + FATAL_ERROR("Value::take_length_restriction()"); + } + Ttcn::LengthRestriction* ptr = u.len_res; + u.len_res = NULL; + return ptr; + } void Value::set_my_governor(Type *p_gov) { @@ -4234,8 +4274,9 @@ namespace Common { } // Deny type compatibility if no governors found. The typetype_t must // be the same. TODO: How can this happen? - if (!Type::is_compatible_tt_tt(tt1, tt2, false, false) - && !Type::is_compatible_tt_tt(tt2, tt1, false, false)) { + // Default false the 5th param + if (!Type::is_compatible_tt_tt(tt1, tt2, false, false, false) + && !Type::is_compatible_tt_tt(tt2, tt1, false, false, false)) { error("The operands of operation `%s' should be of compatible types", get_opname()); set_valuetype(V_ERROR); @@ -10355,6 +10396,10 @@ error: case Ttcn::Template::TEMPLATE_ERROR: //FATAL_ERROR("Value::chk_expr_self_ref_templ()"); break; + case Ttcn::Template::TEMPLATE_CONCAT: + self_ref |= chk_expr_self_ref_templ(t->get_concat_operand(true), lhs); + self_ref |= chk_expr_self_ref_templ(t->get_concat_operand(false), lhs); + break; // default: // FATAL_ERROR("todo ttype %d", t->get_templatetype()); // break; // and hope for the best diff --git a/compiler2/Value.hh b/compiler2/Value.hh index 73297fea041c1a63e9dd07d38edea8579200d32e..363142a351eaba4fe20a99756c1ddd2455ce8ca5 100644 --- a/compiler2/Value.hh +++ b/compiler2/Value.hh @@ -50,6 +50,7 @@ namespace Ttcn { class ParsedActualParameters; class LogArguments; class JsonOmitCombination; + class LengthRestriction; } namespace Common { @@ -125,7 +126,9 @@ namespace Common { V_ALTSTEP, /**< altstep */ V_TESTCASE, /**< testcase */ V_INVOKE, /**< invoke operation */ - V_REFER /**< refer(function) */ + V_REFER, /**< refer(function) */ + V_ANY_VALUE, /**< any value (?) - used by template concatenation */ + V_ANY_OR_OMIT /**< any or omit (*) - used by template concatenation */ }; enum verdict_t { @@ -359,6 +362,7 @@ namespace Common { Block *block; verdict_t verdict; Common::Assignment *refd_fat; /** function, altstep, testcase */ + Ttcn::LengthRestriction* len_res; /** any value, any or omit */ } u; /** Used to avoid infinite recursions of is_unfoldable() */ @@ -454,11 +458,15 @@ namespace Common { Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2); /** Constructor used by decvalue_unichar*/ Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2, Value *p_v3); + /** Constructor used by V_ANY_VALUE and V_ANY_OR_OMIT */ + Value(valuetype_t p_vt, Ttcn::LengthRestriction* p_len_res); virtual ~Value(); virtual Value* clone() const; valuetype_t get_valuetype() const {return valuetype;} /** it it is not V_EXPR then fatal error. */ operationtype_t get_optype() const; + Value* get_concat_operand(bool first_operand) const; + Ttcn::LengthRestriction* take_length_restriction(); /** Sets the governor type. */ virtual void set_my_governor(Type *p_gov); /** Gets the governor type. */ diff --git a/compiler2/Valuestuff.cc b/compiler2/Valuestuff.cc index 232da36c42abc4abd844625d5adfec9fdffb2db6..9847c2fc42e11801ac6c0491bb33049d0e172b0d 100644 --- a/compiler2/Valuestuff.cc +++ b/compiler2/Valuestuff.cc @@ -39,6 +39,22 @@ namespace Common { if (!p_indexed) vs = new vector<Value>(); else ivs = new vector<IndexedValue>(); } + + Values::Values(const Values& p) : Node(p), indexed(p.indexed) + { + if (indexed) { + ivs = new vector<IndexedValue>(); + for (size_t i = 0; i < p.ivs->size(); ++i) { + ivs->add((*p.ivs)[i]->clone()); + } + } + else { + vs = new vector<Value>(); + for (size_t i = 0; i < p.vs->size(); ++i) { + vs->add((*p.vs)[i]->clone()); + } + } + } Values::~Values() { @@ -55,7 +71,7 @@ namespace Common { Values *Values::clone() const { - FATAL_ERROR("Values::clone"); + return new Values(*this); } void Values::set_fullname(const string& p_fullname) @@ -165,6 +181,12 @@ namespace Common { if (!p_index || !p_value) FATAL_ERROR("NULL parameter: IndexedValue::IndexedValue()"); } + + IndexedValue::IndexedValue(const IndexedValue& p) : Node(p), Location(p) + { + index = p.index->clone(); + value = p.value->clone(); + } IndexedValue::~IndexedValue() { @@ -174,7 +196,7 @@ namespace Common { IndexedValue *IndexedValue::clone() const { - FATAL_ERROR("IndexedValue::clone"); + return new IndexedValue(*this); } void IndexedValue::set_fullname(const string& p_fullname) diff --git a/compiler2/record_of.c b/compiler2/record_of.c index f38d96e67d55e1abd0cbd915b64913f43a1b17b6..bc060444ab1be7742a8f4d28f392f97710c0fbb5 100644 --- a/compiler2/record_of.c +++ b/compiler2/record_of.c @@ -408,6 +408,17 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "}\n" "return ret_val;\n" "}\n\n", name, name, name, dispname, name, type, type); + + def = mputprintf(def, + "%s operator+(const OPTIONAL<%s>& other_value) const;\n\n", name, name); + src = mputprintf(src, + "%s %s::operator+(const OPTIONAL<%s>& other_value) const\n" + "{\n" + "if (other_value.is_present()) {\n" + "return *this + (const %s&)other_value;\n" + "}\n" + "TTCN_error(\"Unbound or omitted right operand of %s concatenation.\");\n" + "}\n\n", name, name, name, name, dispname); /* substr() */ def = mputprintf(def, @@ -1962,6 +1973,17 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct "}\n" "return ret_val;\n" "}\n\n", name, name, name, dispname, name); + + def = mputprintf(def, + "%s operator+(const OPTIONAL<%s>& other_value) const;\n\n", name, name); + src = mputprintf(src, + "%s %s::operator+(const OPTIONAL<%s>& other_value) const\n" + "{\n" + "if (other_value.is_present()) {\n" + "return *this + (const %s&)other_value;\n" + "}\n" + "TTCN_error(\"Unbound or omitted right operand of %s concatenation.\");\n" + "}\n\n", name, name, name, name, dispname); /* substr() */ def = mputprintf(def, @@ -3214,6 +3236,17 @@ void defRecordOfClass2(const struct_of_def *sdef, output_struct *output) "%s rec_of;\n" "return *((%s*)concat(&other_value, &rec_of));\n" "}\n\n", name, name, name, name, name); + + def = mputprintf(def, + "%s operator+(const OPTIONAL<%s>& other_value) const;\n\n", name, name); + src = mputprintf(src, + "%s %s::operator+(const OPTIONAL<%s>& other_value) const\n" + "{\n" + "if (other_value.is_present()) {\n" + "return *this + (const %s&)other_value;\n" + "}\n" + "TTCN_error(\"Unbound or omitted right operand of %s concatenation.\");\n" + "}\n\n", name, name, name, name, sdef->dispname); /* substr() */ def = mputprintf(def, @@ -3372,6 +3405,22 @@ void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output) "} value_set;\n", type); } def = mputstr(def, "};\n"); + + /* friend functions */ + def = mputprintf(def, "friend %s_template operator+(template_sel left_template, " + "const %s_template& right_template);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(const %s& left_value, " + "const %s_template& right_template);\n", name, name, name); + def = mputprintf(def, "friend %s_template operator+(const OPTIONAL<%s>& left_value, " + "const %s_template& right_template);\n", name, name, name); + def = mputprintf(def, "friend %s_template operator+(template_sel left_template, " + "const %s& right_value);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(template_sel left_template, " + "const OPTIONAL<%s>& right_value);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(const %s& left_value, " + "template_sel right_template);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(const OPTIONAL<%s>& left_value, " + "template_sel right_template);\n", name, name); /* private member functions */ @@ -3507,6 +3556,143 @@ void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output) "->single_value.value_elements[index_template]->log();\n" "}\n\n", name, name, name, name, name); } + + /* helper functions for template concatenation */ + def = mputstr(def, "int get_length_for_concat(boolean& is_any_value) const;\n"); + src = mputprintf(src, + "int %s_template::get_length_for_concat(boolean& is_any_value) const\n" + "{\n" + "switch (template_selection) {\n" + "case SPECIFIC_VALUE:\n" + "return single_value.n_elements;\n" + "case ANY_VALUE:\n" + "case ANY_OR_OMIT:\n" + "switch (length_restriction_type) {\n" + "case NO_LENGTH_RESTRICTION:\n" + "if (template_selection == ANY_VALUE) {\n" + // ? => { * } + "is_any_value = TRUE;\n" + "return 1;\n" + "}\n" + "TTCN_error(\"Operand of %s of template concatenation is an " + "AnyValueOrNone (*) matching mechanism with no length restriction\");\n" + "case RANGE_LENGTH_RESTRICTION:\n" + "if (!length_restriction.range_length.max_length || " + "length_restriction.range_length.max_length != " + "length_restriction.range_length.min_length) {\n" + "TTCN_error(\"Operand of %s of template concatenation is an %%s matching " + "mechanism with non-fixed length restriction\", " + "template_selection == ANY_VALUE ? \"AnyValue (?)\" : \"AnyValueOrNone (*)\");\n" + "}\n" + // else fall through (range length restriction is allowed if the minimum + // and maximum value are the same) + "case SINGLE_LENGTH_RESTRICTION:\n" + // ? length(N) or * length(N) => { ?, ?, ... ? } N times + "return length_restriction_type == SINGLE_LENGTH_RESTRICTION ? " + "length_restriction.single_length : length_restriction.range_length.min_length;\n" + "}\n" + "default:\n" + "TTCN_error(\"Operand of %s of template concatenation is an " + "uninitialized or unsupported template.\");\n" + "}\n" + "}\n\n", name, sdef->kind == RECORD_OF ? "record" : "set", + sdef->kind == RECORD_OF ? "record" : "set", + sdef->kind == RECORD_OF ? "record" : "set"); + + def = mputprintf(def, "static int get_length_for_concat(const %s& operand);\n", + name); + src = mputprintf(src, + "int %s_template::get_length_for_concat(const %s& operand)\n" + "{\n" + "if (!operand.is_bound()) {\n" + "TTCN_error(\"Operand of %s of template concatenation is an unbound value.\");\n" + "}\n" + "return operand.size_of();\n" + "}\n\n", name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + def = mputstr(def, "static int get_length_for_concat(template_sel operand);\n"); + src = mputprintf(src, + "int %s_template::get_length_for_concat(template_sel operand)\n" + "{\n" + "if (operand == ANY_VALUE) {\n" + // ? => { * } + "return 1;\n" + "}\n" + "TTCN_error(\"Operand of %s of template concatenation is an " + "uninitialized or unsupported template.\");\n" + "}\n\n", name, sdef->kind == RECORD_OF ? "record" : "set"); + + def = mputprintf(def, "void concat(int& pos, const %s_template& operand);\n", + name); + src = mputprintf(src, + "void %s_template::concat(int& pos, const %s_template& operand)\n" + "{\n" + // all errors should have already been caught by the operand's + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + "switch (operand.template_selection) {\n" + "case SPECIFIC_VALUE:\n" + "for (int i = 0; i < operand.single_value.n_elements; ++i) {\n" + "single_value.value_elements[pos + i] = " + "new %s_template(*operand.single_value.value_elements[i]);\n" + "}\n" + "pos += operand.single_value.n_elements;\n" + "break;\n" + "case ANY_VALUE:\n" + "case ANY_OR_OMIT:\n" + "switch (operand.length_restriction_type) {\n" + "case NO_LENGTH_RESTRICTION:\n" + // ? => { * } + "single_value.value_elements[pos] = new %s_template(ANY_OR_OMIT);\n" + "++pos;\n" + "break;\n" + "case RANGE_LENGTH_RESTRICTION:\n" + "case SINGLE_LENGTH_RESTRICTION: {\n" + // ? length(N) or * length(N) => { ?, ?, ... ? } N times + "int N = operand.length_restriction_type == SINGLE_LENGTH_RESTRICTION ? " + "operand.length_restriction.single_length : " + "operand.length_restriction.range_length.min_length;\n" + "for (int i = 0; i < N; ++i) {\n" + "single_value.value_elements[pos + i] = new %s_template(ANY_VALUE);\n" + "}\n" + "pos += N;\n" + "break; }\n" + "}\n" + "default:\n" + "break;\n" + "}\n" + "}\n\n", name, name, type, type, type); + + def = mputprintf(def, "void concat(int& pos, const %s& operand);\n", name); + src = mputprintf(src, + "void %s_template::concat(int& pos, const %s& operand)\n" + "{\n" + // all errors should have already been caught by the + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + "int len = operand.size_of();\n" + "for (int i = 0; i < len; ++i) {\n" + "single_value.value_elements[pos + i] = new %s_template(operand[i]);\n" + "}\n" + "pos += len;\n" + "}\n\n", name, name, type); + + def = mputstr(def, "void concat(int& pos);\n"); + src = mputprintf(src, + "void %s_template::concat(int& pos)\n" + "{\n" + // this concatenates a template_sel to the result template; + // there is no need for a template_sel parameter, since the only template + // selection that can be concatenated is ANY_VALUE; + // the template selection has already been checked in the + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + "single_value.value_elements[pos] = new %s_template(ANY_OR_OMIT);\n" + "++pos;\n" + "}\n\n", name, type); /* public member functions */ def = mputstr(def, "\npublic:\n"); @@ -3668,6 +3854,83 @@ void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output) "}\n" "return *this;\n" "}\n\n", name, name, name); + + /* concatenation operators */ + def = mputprintf(def, "%s_template operator+(const %s_template& " + "other_value) const;\n", name, name); + src = mputprintf(src, + "%s_template %s_template::operator+(const %s_template& other_value) const\n" + "{\n" + "boolean left_is_any_value = FALSE;\n" + "boolean right_is_any_value = FALSE;\n" + "int res_length = get_length_for_concat(left_is_any_value) + " + "other_value.get_length_for_concat(right_is_any_value);\n" + "if (left_is_any_value && right_is_any_value) {\n" + "return %s_template(ANY_VALUE);\n" // special case: ? & ? => ? + "}\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, *this);\n" + "ret_val.concat(pos, other_value);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name, type); + + def = mputprintf(def, "%s_template operator+(const %s& other_value) const;\n", + name, name); + src = mputprintf(src, + "%s_template %s_template::operator+(const %s& other_value) const\n" + "{\n" + "boolean dummy = FALSE;\n" + "int res_length = get_length_for_concat(dummy) + " + "get_length_for_concat(other_value);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, *this);\n" + "ret_val.concat(pos, other_value);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, type); + + def = mputprintf(def, "%s_template operator+(" + "const OPTIONAL<%s>& other_value) const;\n", name, name); + src = mputprintf(src, + "%s_template %s_template::operator+(const OPTIONAL<%s>& other_value) const\n" + "{\n" + "if (other_value.is_present()) {\n" + "return *this + (const %s&)other_value;\n" + "}\n" + "TTCN_error(\"Operand of %s of template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + def = mputprintf(def, "%s_template operator+(template_sel other_value) const;\n", + name); + src = mputprintf(src, + "%s_template %s_template::operator+(template_sel other_value) const\n" + "{\n" + "boolean left_is_any_value = FALSE;\n" + "int res_length = get_length_for_concat(left_is_any_value) + " + "get_length_for_concat(other_value);\n" + "if (left_is_any_value) {\n" // other_value can only be ANY_VALUE at this point + "return %s_template(ANY_VALUE);\n" // special case: ? & ? => ? + "}\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, *this);\n" + "ret_val.concat(pos);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, type); /* indexing operators */ /* Non-const operator[] is allowed to extend */ @@ -4526,6 +4789,146 @@ void defRecordOfTemplate1(const struct_of_def *sdef, output_struct *output) Free(def); output->source.methods = mputstr(output->source.methods, src); Free(src); + + /* global functions */ + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(template_sel left_template, " + "const %s_template& right_template);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(template_sel left_template, " + "const %s_template& right_template)\n" + "{\n" + "boolean right_is_any_value = FALSE;\n" + "int res_length = %s_template::get_length_for_concat(left_template) + " + "right_template.get_length_for_concat(right_is_any_value);\n" + "if (right_is_any_value) {\n" // left_template can only be ANY_VALUE at this point + "return %s_template(ANY_VALUE);\n" // special case: ? & ? => ? + "}\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos);\n" + "ret_val.concat(pos, right_template);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name, type); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const %s& left_value, " + "const %s_template& right_template);\n", name, name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const %s& left_value, " + "const %s_template& right_template)\n" + "{\n" + "boolean dummy = FALSE;\n" + "int res_length = %s_template::get_length_for_concat(left_value) + " + "right_template.get_length_for_concat(dummy);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, left_value);\n" + "ret_val.concat(pos, right_template);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name, type); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const OPTIONAL<%s>& left_value, " + "const %s_template& right_template);\n", name, name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const OPTIONAL<%s>& left_value, " + "const %s_template& right_template)\n" + "{\n" + "if (left_value.is_present()) {\n" + "return (const %s&)left_value + right_template;\n" + "}\n" + "TTCN_error(\"Operand of %s of template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(template_sel left_template, " + "const %s& right_value);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(template_sel left_template, const %s& right_value)\n" + "{\n" + "int res_length = %s_template::get_length_for_concat(left_template) + " + "%s_template::get_length_for_concat(right_value);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos);\n" + "ret_val.concat(pos, right_value);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name, type); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(template_sel left_template, " + "const OPTIONAL<%s>& right_value);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(template_sel left_template, " + "const OPTIONAL<%s>& right_value)\n" + "{\n" + "if (right_value.is_present()) {\n" + "return left_template + (const %s&)right_value;\n" + "}\n" + "TTCN_error(\"Operand of %s template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const %s& left_value, " + "template_sel right_template);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const %s& left_value, template_sel right_template)\n" + "{\n" + "int res_length = %s_template::get_length_for_concat(left_value) + " + "%s_template::get_length_for_concat(right_template);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(%s_template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, left_value);\n" + "ret_val.concat(pos);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name, type); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const OPTIONAL<%s>& left_value, " + "template_sel right_template);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const OPTIONAL<%s>& left_value, " + "template_sel right_template)\n" + "{\n" + "if (left_value.is_present()) {\n" + "return (const %s&)left_value + right_template;\n" + "}\n" + "TTCN_error(\"Operand of %s template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -4539,6 +4942,22 @@ void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *output) /* Class definition */ def = mputprintf(def, "class %s_template : public %s {\n", name, base_class); + + /* friend functions */ + def = mputprintf(def, "friend %s_template operator+(template_sel left_template, " + "const %s_template& right_template);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(const %s& left_value, " + "const %s_template& right_template);\n", name, name, name); + def = mputprintf(def, "friend %s_template operator+(const OPTIONAL<%s>& left_value, " + "const %s_template& right_template);\n", name, name, name); + def = mputprintf(def, "friend %s_template operator+(template_sel left_template, " + "const %s& right_value);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(template_sel left_template, " + "const OPTIONAL<%s>& right_value);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(const %s& left_value, " + "template_sel right_template);\n", name, name); + def = mputprintf(def, "friend %s_template operator+(const OPTIONAL<%s>& left_value, " + "template_sel right_template);\n", name, name); /* public member functions */ def = mputstr(def, "\npublic:\n"); @@ -4622,6 +5041,83 @@ void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *output) "return *this;\n" "}\n\n", name, name, name); + /* concatenation operators */ + def = mputprintf(def, "%s_template operator+(const %s_template& " + "other_value) const;\n", name, name); + src = mputprintf(src, + "%s_template %s_template::operator+(const %s_template& other_value) const\n" + "{\n" + "boolean left_is_any_value = FALSE;\n" + "boolean right_is_any_value = FALSE;\n" + "int res_length = get_length_for_concat(left_is_any_value) + " + "other_value.get_length_for_concat(right_is_any_value);\n" + "if (left_is_any_value && right_is_any_value) {\n" + "return %s_template(ANY_VALUE);\n" // special case: ? & ? => ? + "}\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, *this);\n" + "ret_val.concat(pos, other_value);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name); + + def = mputprintf(def, "%s_template operator+(const %s& other_value) const;\n", + name, name); + src = mputprintf(src, + "%s_template %s_template::operator+(const %s& other_value) const\n" + "{\n" + "boolean dummy = FALSE;\n" + "int res_length = get_length_for_concat(dummy) + " + "get_length_for_concat(other_value);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, *this);\n" + "ret_val.concat(pos, other_value);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name); + + def = mputprintf(def, "%s_template operator+(" + "const OPTIONAL<%s>& other_value) const;\n", name, name); + src = mputprintf(src, + "%s_template %s_template::operator+(const OPTIONAL<%s>& other_value) const\n" + "{\n" + "if (other_value.is_present()) {\n" + "return *this + (const %s&)other_value;\n" + "}\n" + "TTCN_error(\"Operand of %s of template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + def = mputprintf(def, "%s_template operator+(template_sel other_value) const;\n", + name); + src = mputprintf(src, + "%s_template %s_template::operator+(template_sel other_value) const\n" + "{\n" + "boolean left_is_any_value = FALSE;\n" + "int res_length = get_length_for_concat(left_is_any_value) + " + "get_length_for_concat(other_value);\n" + "if (left_is_any_value) {\n" // other_value can only be ANY_VALUE at this point + "return %s_template(ANY_VALUE);\n" // special case: ? & ? => ? + "}\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, *this);\n" + "ret_val.concat(pos);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name); + /* indexing operators */ def = mputprintf(def, "%s_template& operator[](int index_value);\n" @@ -4729,4 +5225,140 @@ void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *output) Free(def); output->source.methods = mputstr(output->source.methods, src); Free(src); + + /* global functions */ + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(template_sel left_template, " + "const %s_template& right_template);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(template_sel left_template, " + "const %s_template& right_template)\n" + "{\n" + "boolean right_is_any_value = FALSE;\n" + "int res_length = %s_template::get_length_for_concat(left_template) + " + "right_template.get_length_for_concat(right_is_any_value);\n" + "if (right_is_any_value) {\n" // left_template can only be ANY_VALUE at this point + "return %s_template(ANY_VALUE);\n" // special case: ? & ? => ? + "}\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos);\n" + "ret_val.concat(pos, right_template);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name); + + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const %s& left_value, " + "const %s_template& right_template)\n" + "{\n" + "boolean dummy = FALSE;\n" + "int res_length = %s_template::get_length_for_concat(left_value) + " + "right_template.get_length_for_concat(dummy);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, left_value);\n" + "ret_val.concat(pos, right_template);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const OPTIONAL<%s>& left_value, " + "const %s_template& right_template);\n", name, name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const OPTIONAL<%s>& left_value, " + "const %s_template& right_template)\n" + "{\n" + "if (left_value.is_present()) {\n" + "return (const %s&)left_value + right_template;\n" + "}\n" + "TTCN_error(\"Operand of %s of template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(template_sel left_template, " + "const %s& right_value);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(template_sel left_template, const %s& right_value)\n" + "{\n" + "int res_length = %s_template::get_length_for_concat(left_template) + " + "%s_template::get_length_for_concat(right_value);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos);\n" + "ret_val.concat(pos, right_value);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(template_sel left_template, " + "const OPTIONAL<%s>& right_value);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(template_sel left_template, " + "const OPTIONAL<%s>& right_value)\n" + "{\n" + "if (right_value.is_present()) {\n" + "return left_template + (const %s&)right_value;\n" + "}\n" + "TTCN_error(\"Operand of %s template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const %s& left_value, " + "template_sel right_template);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const %s& left_value, template_sel right_template)\n" + "{\n" + "int res_length = %s_template::get_length_for_concat(left_value) + " + "%s_template::get_length_for_concat(right_template);\n" + "%s_template ret_val;\n" + "ret_val.template_selection = SPECIFIC_VALUE;\n" + "ret_val.single_value.n_elements = res_length;\n" + "ret_val.single_value.value_elements = " + "(Base_Template**)allocate_pointers(res_length);\n" + "int pos = 0;\n" + "ret_val.concat(pos, left_value);\n" + "ret_val.concat(pos);\n" + "return ret_val;\n" + "}\n\n", name, name, name, name, name); + + output->header.function_prototypes = + mputprintf(output->header.function_prototypes, + "extern %s_template operator+(const OPTIONAL<%s>& left_value, " + "template_sel right_template);\n", name, name); + output->source.function_bodies = + mputprintf(output->source.function_bodies, + "%s_template operator+(const OPTIONAL<%s>& left_value, " + "template_sel right_template)\n" + "{\n" + "if (left_value.is_present()) {\n" + "return (const %s&)left_value + right_template;\n" + "}\n" + "TTCN_error(\"Operand of %s template concatenation is an unbound or " + "omitted record/set field.\");\n" + "}\n\n", name, name, name, sdef->kind == RECORD_OF ? "record" : "set"); } diff --git a/compiler2/subtype.cc b/compiler2/subtype.cc index e1a226370146915345d91857d299ac6c1c90fe25..322aaa6bbae7136c5ccce8e32f1252b8c4cf2faf 100644 --- a/compiler2/subtype.cc +++ b/compiler2/subtype.cc @@ -1953,6 +1953,7 @@ void SubType::chk_this_template(Template *templ) case Template::ALL_FROM: case Template::VALUE_LIST_ALL_FROM: case Template::DECODE_MATCH: + case Template::TEMPLATE_CONCAT: break; case Template::SUPERSET_MATCH: case Template::SUBSET_MATCH: diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 1c37fdf5357ad33441dfdbc76d3271e718fd8699..d39f5e771a9b7a714697e85e1639de4efd212b52 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -1211,7 +1211,7 @@ namespace Ttcn { return component_defs->has_ass_withId(p_id) || parent_scope->has_ass_withId(p_id); } - + // ================================= // ===== FriendMod // ================================= @@ -6231,7 +6231,7 @@ namespace Ttcn { if (!my_module) FATAL_ERROR("Def_Function::get_runs_on_scope()"); return my_module->get_runs_on_scope(comptype); } - + void Def_Function::chk() { if (checked) return; @@ -6662,10 +6662,16 @@ namespace Ttcn { } } else { - if (Common::Type::CT_XER == encoding_type - && input_type->get_type_refd_last()->is_untagged()) { - // "untagged" on the (toplevel) input type will have no effect. - warning("UNTAGGED encoding attribute is ignored on top-level type"); + if (Common::Type::CT_XER == encoding_type) { + Type* last = input_type->get_type_refd_last(); + if (last->is_untagged() && + last->get_typetype() != Type::T_CHOICE_A && + last->get_typetype() != Type::T_CHOICE_T && + last->get_typetype() != Type::T_ANYTYPE) { + // "untagged" on the (toplevel) input type will have no effect, + // unless it is union or anytype + warning("UNTAGGED encoding attribute is ignored on top-level type"); + } } if (Common::Type::CT_CUSTOM == encoding_type || Common::Type::CT_PER == encoding_type) { @@ -8358,6 +8364,10 @@ namespace Ttcn { case Template::DECODE_MATCH: chk_defpar_template(body->get_decode_target()->get_Template(), exp_val); break; + case Template::TEMPLATE_CONCAT: + chk_defpar_template(body->get_concat_operand(true), exp_val); + chk_defpar_template(body->get_concat_operand(false), exp_val); + break; } // switch templatetype } diff --git a/compiler2/ttcn3/PatternString.cc b/compiler2/ttcn3/PatternString.cc index ee176525e9dd3011d8b099799f84dbdc748c7a1d..a8ea4f82bd4bac361c2eea5256803187f277c600 100644 --- a/compiler2/ttcn3/PatternString.cc +++ b/compiler2/ttcn3/PatternString.cc @@ -169,6 +169,22 @@ namespace Ttcn { case Template::SPECIFIC_VALUE: v_last = templ->get_specific_value(); break; + case Template::TEMPLATE_CONCAT: + if (templ->is_Value()) { + v = templ->get_Value(); + v->set_my_governor(refcheckertype); + v->set_my_scope(ref->get_my_scope()); + v->set_location(*ref); + refcheckertype->chk_this_value(v, 0, expected_value, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); + v_last = v->get_value_refd_last(); + } + else { + TTCN_pattern_error("Unable to resolve referenced '%s' to character " + "string type. Result of template concatenation is not a specific " + "value.", ref->get_dispname().c_str()); + } + break; case Template::CSTR_PATTERN: if (!with_N) { Ttcn::PatternString* ps = templ->get_cstr_pattern(); diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index fcabbcc30851f86a9cc898a56db04ae2e42fd3da..bc7dc9ed58638a28a3066e349ce7f66cb71bcb11 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -6587,7 +6587,8 @@ error: str = mputstr(str, expr.preamble); } str = mputprintf(str, "switch(%s.get_selection()) {\n", expr.expr); - const char* type_name = select_union.expr->get_expr_governor_last()->get_genname_value(select_union.expr->get_my_scope()).c_str(); + string type_name_str = select_union.expr->get_expr_governor_last()->get_genname_value(select_union.expr->get_my_scope()); + const char* type_name = type_name_str.c_str(); char* loc = NULL; loc = select_union.expr->update_location_object(loc); str = select_union.sus->generate_code(str, def_glob_vars, src_glob_vars, type_name, loc); @@ -6963,7 +6964,8 @@ error: str = mputstr(str, expr.preamble); } str = mputprintf(str, "switch(%s.get_selection()) {\n", expr.expr); - const char* type_name = select_union.expr->get_expr_governor_last()->get_genname_value(select_union.expr->get_my_scope()).c_str(); + string type_name_str = select_union.expr->get_expr_governor_last()->get_genname_value(select_union.expr->get_my_scope()); + const char* type_name = type_name_str.c_str(); char* loc = NULL; loc = select_union.expr->update_location_object(loc); str = select_union.sus->generate_code(str, ilt->get_out_def_glob_vars(), @@ -10654,6 +10656,31 @@ error: if (!p_ti) FATAL_ERROR("LogArgument::LogArgument()"); ti = p_ti; } + + LogArgument::LogArgument(const LogArgument& p) : logargtype(p.logargtype) + { + switch (logargtype) { + case L_ERROR: + break; + case L_UNDEF: + case L_TI: + ti = p.ti->clone(); + break; + case L_VAL: + case L_MATCH: + case L_MACRO: + val = p.val->clone(); + break; + case L_REF: + ref = p.ref->clone(); + break; + case L_STR: + cstr = new string(*cstr); + break; + default: + FATAL_ERROR("LogArgument::LogArgument()"); + } // switch + } LogArgument::~LogArgument() { @@ -10682,7 +10709,7 @@ error: LogArgument *LogArgument::clone() const { - FATAL_ERROR("LogArgument::clone"); + return new LogArgument(*this); } void LogArgument::set_my_scope(Scope *p_scope) @@ -11113,6 +11140,13 @@ error: // ===== LogArguments // ================================= + LogArguments::LogArguments(const LogArguments& p) + { + for (size_t i = 0; i < logargs.size(); ++i) { + logargs[i] = p.logargs[i]->clone(); + } + } + LogArguments::~LogArguments() { for(size_t i=0; i<logargs.size(); i++) delete logargs[i]; @@ -11121,7 +11155,7 @@ error: LogArguments *LogArguments::clone() const { - FATAL_ERROR("LogArguments::clone"); + return new LogArguments(*this); } void LogArguments::add_logarg(LogArgument *p_logarg) diff --git a/compiler2/ttcn3/Templatestuff.cc b/compiler2/ttcn3/Templatestuff.cc index 931f2fab79963f94980c6bd08ae2864591287912..6efd490f8b497890f4ccb6c038f1fa03d8c90404 100644 --- a/compiler2/ttcn3/Templatestuff.cc +++ b/compiler2/ttcn3/Templatestuff.cc @@ -520,6 +520,18 @@ namespace Ttcn { range.lower = p_lower; range.upper = p_upper; } + + LengthRestriction::LengthRestriction(const LengthRestriction& p) + : Node(), checked(p.checked), is_range(p.is_range) + { + if (is_range) { + range.lower = p.range.lower->clone(); + range.upper = p.range.upper != NULL ? p.range.upper->clone() : NULL; + } + else { + single = p.single->clone(); + } + } LengthRestriction::~LengthRestriction() { @@ -531,7 +543,7 @@ namespace Ttcn { LengthRestriction *LengthRestriction::clone() const { - FATAL_ERROR("LengthRestriction::clone"); + return new LengthRestriction(*this); } void LengthRestriction::set_fullname(const string& p_fullname) diff --git a/compiler2/ttcn3/Templatestuff.hh b/compiler2/ttcn3/Templatestuff.hh index 8e424274809ff82a1657e9bcbd28a4cda545e183..fcd9cbcda438144e97c4c5e9875e25a10088594e 100644 --- a/compiler2/ttcn3/Templatestuff.hh +++ b/compiler2/ttcn3/Templatestuff.hh @@ -238,7 +238,6 @@ namespace Ttcn { } range; }; - /** Copy constructor disabled. */ LengthRestriction(const LengthRestriction& p); /** Copy assignment disabled */ LengthRestriction& operator=(const LengthRestriction& p); diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index 0984e98dc2d0863df4aca13c3c3cfc1edeea9118..f84a83b9dbfb605d48d8f4373b0d09a6cbd43bef 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -97,6 +97,10 @@ namespace Ttcn { p.u.dec_match.str_enc->clone() : NULL; u.dec_match.target = p.u.dec_match.target->clone(); break; + case TEMPLATE_CONCAT: + u.concat.op1 = p.u.concat.op1->clone(); + u.concat.op2 = p.u.concat.op2->clone(); + break; // default: // FATAL_ERROR("Template::Template()"); } @@ -160,6 +164,10 @@ namespace Ttcn { } delete u.dec_match.target; break; + case TEMPLATE_CONCAT: + delete u.concat.op1; + delete u.concat.op2; + break; // default: // FATAL_ERROR("Template::clean_up()"); } @@ -299,6 +307,11 @@ namespace Ttcn { ret_val += ": "; ret_val += u.dec_match.target->get_Template()->create_stringRepr(); break; + case TEMPLATE_CONCAT: + ret_val += u.concat.op1->create_stringRepr(); + ret_val += " & "; + ret_val += u.concat.op2->create_stringRepr(); + break; default: ret_val += "<unknown template>"; break; @@ -318,8 +331,8 @@ namespace Ttcn { case TEMPLATE_ERROR: case TEMPLATE_NOTUSED: case OMIT_VALUE: - case ANY_VALUE: - case ANY_OR_OMIT: + //case ANY_VALUE: + //case ANY_OR_OMIT: break; default: FATAL_ERROR("Template::Template()"); @@ -328,12 +341,40 @@ namespace Ttcn { Template::Template(Value *v) : GovernedSimple(S_TEMPLATE), - templatetype(SPECIFIC_VALUE), my_governor(0), length_restriction(0), + templatetype(TEMPLATE_ERROR), my_governor(0), length_restriction(0), is_ifpresent(false), specific_value_checked(false), has_permutation(false), flattened(true), base_template(0) { if (!v) FATAL_ERROR("Template::Template()"); - u.specific_value = v; + switch (v->get_valuetype()) { + case Value::V_ANY_VALUE: + case Value::V_ANY_OR_OMIT: + templatetype = v->get_valuetype() == Value::V_ANY_VALUE ? + ANY_VALUE : ANY_OR_OMIT; + set_length_restriction(v->take_length_restriction()); + delete v; + break; + case Value::V_OMIT: + templatetype = OMIT_VALUE; + delete v; + break; + case Value::V_EXPR: + if (v->get_optype() == Value::OPTYPE_CONCAT) { + // convert the operands to templates with recursive calls to this constructor + templatetype = TEMPLATE_CONCAT; + u.concat.op1 = new Template(v->get_concat_operand(true)->clone()); + u.concat.op1->set_location(*v->get_concat_operand(true)); + u.concat.op2 = new Template(v->get_concat_operand(false)->clone()); + u.concat.op2->set_location(*v->get_concat_operand(false)); + delete v; + break; + } + // other expressions are specific value templates + default: + templatetype = SPECIFIC_VALUE; + u.specific_value = v; + break; + } } Template::Template(Ref_base *p_ref) @@ -559,6 +600,10 @@ namespace Ttcn { } u.dec_match.target->set_fullname(p_fullname + ".<decoding_target>"); break; + case TEMPLATE_CONCAT: + u.concat.op1->set_fullname(p_fullname + ".operand1"); + u.concat.op2->set_fullname(p_fullname + ".operand2"); + break; // default: // FATAL_ERROR("Template::set_fullname()"); } @@ -621,6 +666,10 @@ namespace Ttcn { } u.dec_match.target->set_my_scope(p_scope); break; + case TEMPLATE_CONCAT: + u.concat.op1->set_my_scope(p_scope); + u.concat.op2->set_my_scope(p_scope); + break; // default: // FATAL_ERROR("Template::set_my_scope()"); } @@ -739,6 +788,10 @@ namespace Ttcn { } u.dec_match.target->set_code_section(p_code_section); break; + case TEMPLATE_CONCAT: + u.concat.op1->set_code_section(p_code_section); + u.concat.op2->set_code_section(p_code_section); + break; default: break; } @@ -909,6 +962,8 @@ namespace Ttcn { return "universal string pattern"; case DECODE_MATCH: return "decoded content match"; + case TEMPLATE_CONCAT: + return "template concatenation"; default: return "unknown template"; } @@ -953,6 +1008,10 @@ namespace Ttcn { case VALUE_RANGE: u.value_range->set_lowerid_to_ref(); break; + case TEMPLATE_CONCAT: + u.concat.op1->set_lowerid_to_ref(); + u.concat.op2->set_lowerid_to_ref(); + break; default: break; } @@ -996,6 +1055,29 @@ namespace Ttcn { return Type::T_CSTR; case USTR_PATTERN: return Type::T_USTR; + case TEMPLATE_CONCAT: { + Type::typetype_t tt1 = u.concat.op1->get_expr_returntype(exp_val); + Type::typetype_t tt2 = u.concat.op2->get_expr_returntype(exp_val); + if (tt1 == Type::T_UNDEF) { + if (tt2 == Type::T_UNDEF) { + return Type::T_UNDEF; + } + return tt2; + } + else { + if (tt2 == Type::T_UNDEF) { + return tt1; + } + if ((tt1 == Type::T_CSTR && tt2 == Type::T_USTR) || + (tt1 == Type::T_USTR && tt2 == Type::T_CSTR)) { + return Type::T_USTR; + } + if (tt1 != tt2) { + return Type::T_ERROR; + } + return tt1; + } + } default: return Type::T_UNDEF; } @@ -1047,6 +1129,35 @@ namespace Ttcn { goto error; } break; } + case TEMPLATE_CONCAT: { + Type* t1 = u.concat.op1->get_expr_governor(exp_val); + Type* t2 = u.concat.op2->get_expr_governor(exp_val); + if (t1 == NULL) { + if (t2 == NULL) { + return NULL; + } + return t2; + } + else { + if (t2 == NULL) { + return t1; + } + Type::typetype_t tt1 = t1->get_type_refd_last()->get_typetype_ttcn3(); + Type::typetype_t tt2 = t2->get_type_refd_last()->get_typetype_ttcn3(); + if (tt1 == Type::T_CSTR && tt2 == Type::T_USTR) { + return t2; + } + if (tt1 == Type::T_USTR && tt2 == Type::T_CSTR) { + return t1; + } + if (tt1 != tt2) { + error("Operands of template concatenation are not compatible with " + "each other"); + goto error; + } + return t1; + } + } default: return Type::get_pooltype(get_expr_returntype(exp_val)); } @@ -1069,6 +1180,7 @@ namespace Ttcn { void Template::set_length_restriction(LengthRestriction *p_lr) { + if (p_lr == NULL) return; if (length_restriction) FATAL_ERROR("Template::set_length_restriction()"); length_restriction = p_lr; } @@ -1372,7 +1484,7 @@ namespace Ttcn { Value* Template::get_string_encoding() const { if (templatetype != DECODE_MATCH) { - FATAL_ERROR("Template::get_decode_target()"); + FATAL_ERROR("Template::get_string_encoding()"); } return u.dec_match.str_enc; } @@ -1384,6 +1496,14 @@ namespace Ttcn { } return u.dec_match.target; } + + Template* Template::get_concat_operand(bool first) const + { + if (templatetype != TEMPLATE_CONCAT) { + FATAL_ERROR("Template::get_concat_operand"); + } + return first ? u.concat.op1 : u.concat.op2; + } Template* Template::get_template_refd(ReferenceChain *refch) { @@ -1817,6 +1937,8 @@ namespace Ttcn { return false; } } + case TEMPLATE_CONCAT: + return u.concat.op1->is_Value() && u.concat.op2->is_Value(); default: return false; } @@ -1885,6 +2007,10 @@ namespace Ttcn { if (gov) gov = gov->get_parent_type(); if (gov) ret_val->set_my_governor(gov); break; } + case TEMPLATE_CONCAT: + ret_val = new Value(Value::OPTYPE_CONCAT, u.concat.op1->get_Value(), + u.concat.op2->get_Value()); + break; default: FATAL_ERROR("Template::get_Value()"); ret_val = 0; @@ -1974,6 +2100,14 @@ namespace Ttcn { case DECODE_MATCH: t->u.dec_match.target->chk_recursions(refch); break; + case TEMPLATE_CONCAT: + refch.mark_state(); + t->u.concat.op1->chk_recursions(refch); + refch.prev_state(); + refch.mark_state(); + t->u.concat.op2->chk_recursions(refch); + refch.prev_state(); + break; default: break; } @@ -2029,6 +2163,10 @@ end: break; case OMIT_VALUE: break; + case TEMPLATE_CONCAT: + t->u.concat.op1->chk_specific_value_generic(); + t->u.concat.op2->chk_specific_value_generic(); + break; default: t->error("A specific value was expected instead of %s", t->get_templatetype_str()); @@ -2659,6 +2797,7 @@ end: case ALL_FROM: case BSTR_PATTERN: case HSTR_PATTERN: case OSTR_PATTERN: case CSTR_PATTERN: case USTR_PATTERN: case DECODE_MATCH: + case TEMPLATE_CONCAT: // not implemented yet break; // NOP } @@ -2945,6 +3084,12 @@ end: } needs_runtime_check = true; // only basic check, needs runtime check break; + case TEMPLATE_CONCAT: + u.concat.op1->chk_restriction(definition_name, template_restriction, + usage_loc); + u.concat.op2->chk_restriction(definition_name, template_restriction, + usage_loc); + break; case OMIT_VALUE: if (template_restriction==TR_OMIT) break; // Else restriction is TR_VALUE, but template type is OMIT: @@ -3002,6 +3147,12 @@ end: definition_name, get_templatetype_str()); erroneous = true; break; + case TEMPLATE_CONCAT: + u.concat.op1->chk_restriction(definition_name, template_restriction, + usage_loc); + u.concat.op2->chk_restriction(definition_name, template_restriction, + usage_loc); + break; default: break; // all others are ok } @@ -3164,6 +3315,9 @@ end: case DECODE_MATCH: str = generate_code_init_dec_match(str, name); break; + case TEMPLATE_CONCAT: + str = generate_code_init_concat(str, name); + break; case TEMPLATE_NOTUSED: break; case TEMPLATE_ERROR: @@ -3213,6 +3367,10 @@ end: case VALUE_RANGE: str = u.value_range->rearrange_init_code(str, usage_mod); break; + case TEMPLATE_CONCAT: + str = u.concat.op1->rearrange_init_code(str, usage_mod); + str = u.concat.op2->rearrange_init_code(str, usage_mod); + break; default: break; } @@ -3477,6 +3635,9 @@ end: if (!u.indexed_templates->get_it_byIndex(i)->get_template()->compile_time()) return false; return true; + case TEMPLATE_CONCAT: + //return u.concat.op1->compile_time() && u.concat.op2->compile_time(); + return false; } return true; // not reached @@ -4098,7 +4259,7 @@ compile_time: str = t->generate_code_init(str, embedded_name); Free(embedded_name); } - Free(fieldname_str); + Free(const_cast<char*>(fieldname_str)); } } else { str = mputprintf(str, "%s = NULL_VALUE;\n", name); @@ -4684,6 +4845,34 @@ compile_time: str = mputstr(str, "}\n"); return str; } + + char* Template::generate_code_init_concat(char* str, const char* name) + { + string left_expr; + string right_expr; + if (u.concat.op1->has_single_expr()) { + left_expr = u.concat.op1->get_single_expr(false); + } + else { + left_expr = my_scope->get_scope_mod_gen()->get_temporary_id(); + str = mputprintf(str, "%s %s;\n", + my_governor->get_genname_template(my_scope).c_str(), left_expr.c_str()); + str = u.concat.op1->generate_code_init(str, left_expr.c_str()); + } + if (u.concat.op2->has_single_expr()) { + right_expr = u.concat.op2->get_single_expr(false); + } + else { + right_expr = my_scope->get_scope_mod_gen()->get_temporary_id(); + str = mputprintf(str, "%s %s;\n", + my_governor->get_genname_template(my_scope).c_str(), right_expr.c_str()); + str = u.concat.op2->generate_code_init(str, right_expr.c_str()); + } + + str = mputprintf(str, "%s = %s + %s;\n", name, left_expr.c_str(), + right_expr.c_str()); + return str; + } void Template::generate_code_expr_invoke(expression_struct *expr) { @@ -4823,6 +5012,8 @@ compile_time: case PERMUTATION_MATCH: // FIXME return false; + case TEMPLATE_CONCAT: + return u.concat.op1->needs_temp_ref() || u.concat.op2->needs_temp_ref(); } return false; } @@ -4880,6 +5071,8 @@ compile_time: case ALL_FROM: case VALUE_LIST_ALL_FROM: return false; + case TEMPLATE_CONCAT: + return u.concat.op1->has_single_expr() && u.concat.op2->has_single_expr(); default: FATAL_ERROR("Template::has_single_expr()"); return false; @@ -4967,6 +5160,10 @@ compile_time: case OSTR_PATTERN: return get_my_scope()->get_scope_mod_gen() ->add_octetstring_pattern(*u.pattern); + case TEMPLATE_CONCAT: + ret_val = u.concat.op1->get_single_expr(false) + " + " + + u.concat.op2->get_single_expr(false); + break; default: FATAL_ERROR("Template::get_single_expr()"); } @@ -5036,6 +5233,12 @@ compile_time: DEBUG(level, "decoding target:"); u.dec_match.target->dump(level + 1); break; + case TEMPLATE_CONCAT: + DEBUG(level, "operand #1:"); + u.concat.op1->dump(level + 1); + DEBUG(level, "operand #2:"); + u.concat.op2->dump(level + 1); + break; default: break; } diff --git a/compiler2/ttcn3/TtcnTemplate.hh b/compiler2/ttcn3/TtcnTemplate.hh index 46fab7a48c95c51fa6f7c842150fcb91b12edbf5..b55d19fda53c8d80d031c3691b08983b1afee3f6 100644 --- a/compiler2/ttcn3/TtcnTemplate.hh +++ b/compiler2/ttcn3/TtcnTemplate.hh @@ -69,7 +69,8 @@ namespace Ttcn { OSTR_PATTERN, /**< octetstring pattern */ CSTR_PATTERN, /**< character string pattern */ USTR_PATTERN, /**< universal charstring pattern */ - DECODE_MATCH /**< decoded content match */ + DECODE_MATCH, /**< decoded content match */ + TEMPLATE_CONCAT /**< concatenation of two templates */ }; /** Status codes for the verification of template body completeness. */ @@ -128,6 +129,11 @@ namespace Ttcn { Value* str_enc; TemplateInstance* target; } dec_match; + /** Used by TEMPLATE_CONCAT */ + struct { + Template* op1; + Template* op2; + } concat; } u; /** This points to the type of the template */ @@ -173,11 +179,11 @@ namespace Ttcn { string create_stringRepr(); public: - /** Constructor for TEMPLATE_ERROR, TEMPLATE_NOTUSED, OMIT_VALUE, - * ANY_VALUE, ANY_OR_OMIT and */ + /** Constructor for TEMPLATE_ERROR and TEMPLATE_NOTUSED */ Template(templatetype_t tt); - /** Constructor for SPECIFIC_VALUE */ + /** Constructor for SPECIFIC_VALUE, ANY_VALUE, ANY_OR_OMIT, OMIT_VALUE and + * TEMPLATE_CONCAT (in which case it's recursive). */ Template(Value *v); /** Constructor for TEMPLATE_REFD */ @@ -212,7 +218,7 @@ namespace Ttcn { /** Constructor for DECODE_MATCH */ Template(Value* v, TemplateInstance* ti); - + virtual ~Template(); virtual Template* clone() const; @@ -302,6 +308,7 @@ namespace Ttcn { bool silent = false); Value* get_string_encoding() const; TemplateInstance* get_decode_target() const; + Template* get_concat_operand(bool first) const; private: Template* get_template_refd(ReferenceChain *refch); Template* get_refd_field_template(const Identifier& field_id, @@ -477,6 +484,7 @@ namespace Ttcn { bool is_superset); char* generate_code_init_dec_match(char* str, const char* name); + char* generate_code_init_concat(char* str, const char* name); char *generate_code_init_all_from(char *str, const char *name); char *generate_code_init_all_from_list(char *str, const char *name); diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y index 5d771c1fc2571aaa1a67789711b31460927943c9..476095e5d8db49c00fe8153409e3574b42841ca9 100644 --- a/compiler2/ttcn3/compiler.y +++ b/compiler2/ttcn3/compiler.y @@ -1867,12 +1867,12 @@ optDecodedModifier %left '*' '/' ModKeyword RemKeyword %left UnarySign -%expect 59 +%expect 63 %start GrammarRoot /* -XXX Source of conflicts (57 S/R): +XXX Source of conflicts (63 S/R): 1.) 9 conflicts in one state The Expression after 'return' keyword is optional in ReturnStatement. @@ -1929,6 +1929,15 @@ that would cause a semantic error anyway, but it would be good to know. 9.) 2 conflicts in the rule TypeListWithTo. +10.) 4 conflicts in 4 states +In the Expression and SingleExpression rules when an AnyValue or AnyOrOmit is +followed by a LengthMatch, the parser cannot decide whether the LengthMatch token +belongs to the AnyValue/AnyOrOmit (shift) or the resulting template (reduce). +This is only relevant for template concatenation: +ex.: template octetstring t := 'AB'O & ? length (3); +Because the parser shifts, the length restriction here is applied to the '?' +instead of the concatenation result, which is the expected behavior. + Note that the parser implemented by bison always chooses to shift instead of reduce in case of conflicts. */ @@ -3589,10 +3598,9 @@ SingleValueOrAttrib: // 111 MatchingSymbol { $$ = $1; } | SingleExpression { - if ($1->get_valuetype() == Value::V_OMIT) { - delete $1; - $$ = new Template(Template::OMIT_VALUE); - } else $$ = new Template($1); // SPECIFIC_VALUE; SingleExpr is a Template* + // SingleExpr is a Template* + // this constructor determines the template type based on the value + $$ = new Template($1); $$->set_location(infile, @$); } /* | TemplateRefWithParList -- covered by SingleExpression */ @@ -3649,7 +3657,7 @@ MatchingSymbol: // 116 is a Template* $$ = new Template(Template::COMPLEMENTED_LIST, $1); $$->set_location(infile, @$); } -| AnyValue +/*| AnyValue // these are in the SingleExpression and Expression rules now { $$ = new Template(Template::ANY_VALUE); $$->set_location(infile, @$); @@ -3658,7 +3666,7 @@ MatchingSymbol: // 116 is a Template* { $$ = new Template(Template::ANY_OR_OMIT); $$->set_location(infile, @$); - } + }*/ | ValueOrAttribList { $$ = new Template(Template::VALUE_LIST, $1); @@ -8800,6 +8808,27 @@ Expression: // 579 | OpCall { $$ = $1; } | Value { $$ = $1; } | CompoundExpression { $$ = $1; } +/* These are needed for template concatenation */ +| AnyValue + { + $$ = new Value(Value::V_ANY_VALUE, (LengthRestriction*)NULL); + $$->set_location(infile, @$); + } +| AnyValue LengthMatch + { + $$ = new Value(Value::V_ANY_VALUE, $2); + $$->set_location(infile, @$); + } +| AnyOrOmit + { + $$ = new Value(Value::V_ANY_OR_OMIT, (LengthRestriction*)NULL); + $$->set_location(infile, @$); + } +| AnyOrOmit LengthMatch + { + $$ = new Value(Value::V_ANY_OR_OMIT, $2); + $$->set_location(infile, @$); + } ; CompoundExpression: // 565 @@ -9083,6 +9112,27 @@ SingleExpression: // 595 } | OpCall { $$ = $1; } | Value { $$ = $1; } +/* These are needed for template concatenation */ +| AnyValue + { + $$ = new Value(Value::V_ANY_VALUE, (LengthRestriction*)NULL); + $$->set_location(infile, @$); + } +| AnyValue LengthMatch + { + $$ = new Value(Value::V_ANY_VALUE, $2); + $$->set_location(infile, @$); + } +| AnyOrOmit + { + $$ = new Value(Value::V_ANY_OR_OMIT, (LengthRestriction*)NULL); + $$->set_location(infile, @$); + } +| AnyOrOmit LengthMatch + { + $$ = new Value(Value::V_ANY_OR_OMIT, $2); + $$->set_location(infile, @$); + } ; optExtendedFieldReference: diff --git a/compiler2/union.c b/compiler2/union.c index 7bf83ffb3d611ac57b82578fe42ea1331f6050ab..3223e47d0600ec2dfe79371486c63a0062cb88ac 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -1520,7 +1520,9 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " if (is_exer(p_flavor)) flavor_1 &= ~XER_RECOF;\n" " if (!(p_flavor & XER_LIST)) flavor_2 |= FROM_UNION_USETYPE;\n" " boolean omit_tag = begin_xml(p_td, p_buf, flavor_1, p_indent, FALSE, " - "(collector_fn)&%s::collect_ns%s, flavor_2);\n" + "(collector_fn)&%s::collect_ns%s, flavor_2 | THIS_UNION);\n" + // Top level union can be untagged, so don't increase the indentation + " int p_indent_tmp = (is_exer(p_flavor) && p_indent == 0 && (p_td.xer_bits & UNTAGGED)) ? p_indent : p_indent + (!p_indent || !omit_tag);\n" , sdef->name , sdef->xerUseTypeAttr ? ", type_atr" : ", 0"); src = mputprintf(src, @@ -1531,7 +1533,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " case %s_%s:\n" " ec_1.set_msg(\"%s': \");\n" " field_%s->XER_encode(%s_xer_, p_buf, flavor_0, " - "flavor_2, p_indent + (!p_indent || !omit_tag), 0);\n" + "flavor_2, p_indent_tmp, 0);\n" " break;\n", selection_prefix, sdef->elements[i].name, sdef->elements[i].dispname, @@ -1546,7 +1548,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputstr(src, " if (p_buf.get_data()[p_buf.get_len()-1] != '\\n') flavor_1 |= SIMPLE_TYPE;\n"); } src = mputstr(src, - " end_xml(p_td, p_buf, flavor_1, p_indent, 0);\n" + " end_xml(p_td, p_buf, flavor_1, p_indent, 0, flavor_2 | THIS_UNION);\n" " return (int)p_buf.get_len() - encoded_length;\n" "}\n\n"); @@ -1739,7 +1741,6 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " int rd_ok=1, xml_depth=-1;\n" "%s%s" " unsigned long xerbits = p_td.xer_bits;\n" - " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" " if (xerbits & USE_TYPE_ATTR) p_flavor &= ~XER_RECOF;\n" " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT | UNTAGGED)) " "|| (p_flavor & (USE_NIL|(e_xer ? XER_LIST : XER_RECOF)))));\n" diff --git a/core/Basetype.cc b/core/Basetype.cc index eba72a6c2e21f481c6147f2e23419a35de46fe39..3d1386ae8ad27783b9955886b93f33d71fe960d5 100644 --- a/core/Basetype.cc +++ b/core/Basetype.cc @@ -235,7 +235,9 @@ int Base_Type::begin_xml(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, collector_fn collector, const char *type_atr, unsigned int flavor2) const { const int exer = is_exer(flavor); - int omit_tag = (indent != 0) // can never omit the tag at the toplevel + int omit_tag = + // can never omit the tag at the toplevel, except when the type is union + (indent != 0 || (flavor2 & THIS_UNION)) && ( ((flavor & XER_RECOF) // can remove the tag even if not EXER && !(exer && (flavor & BXER_EMPTY_ELEM))) // except 26.6, 26.7 || (exer /*&& */ @@ -335,10 +337,12 @@ int Base_Type::begin_xml(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, } void Base_Type::end_xml (const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent, boolean empty) const + unsigned int flavor, int indent, boolean empty, unsigned int flavor2) const { int exer = is_exer(flavor); - boolean omit_tag = (indent != 0) // can never omit the tag at the toplevel + boolean omit_tag = + // can never omit the tag at the toplevel, except when the type is union + (indent != 0 || (flavor2 & THIS_UNION)) && ( ((flavor & XER_RECOF) // can remove the tag even if not EXER && !(exer && (flavor & BXER_EMPTY_ELEM))) // except 26.6, 26.7 || (exer /*&& */ diff --git a/core/Basetype.hh b/core/Basetype.hh index 3fb85a51606dc20032d71242a2290d465864ccdc..b927adaf832ff80ac0386afef470f2187090fc4e 100644 --- a/core/Basetype.hh +++ b/core/Basetype.hh @@ -588,7 +588,7 @@ public: * @param[in] empty true if an empty-element tag is needed */ VIRTUAL_IF_RUNTIME_2 void end_xml (const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent, boolean empty) const; + unsigned int flavor, int indent, boolean empty, unsigned int flavor2 = 0) const; /** Encode JSON. * @return encoded length diff --git a/core/Bitstring.cc b/core/Bitstring.cc index af9acb3a9cb6f57b747b672eeb23adb210f8ea39..e6189ecbe135cf216832840c5163af6ae80ac4a4 100644 --- a/core/Bitstring.cc +++ b/core/Bitstring.cc @@ -256,6 +256,14 @@ BITSTRING BITSTRING::operator+(const BITSTRING_ELEMENT& other_value) const return ret_val; } +BITSTRING BITSTRING::operator+(const OPTIONAL<BITSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const BITSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of bitstring concatenation."); +} + BITSTRING BITSTRING::operator~() const { must_bound("Unbound bitstring operand of operator not4b."); @@ -1333,6 +1341,15 @@ BITSTRING BITSTRING_ELEMENT::operator+(const BITSTRING_ELEMENT& other_value) return BITSTRING(2, &result); } +BITSTRING BITSTRING_ELEMENT::operator+( + const OPTIONAL<BITSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const BITSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of bitstring concatenation."); +} + BITSTRING BITSTRING_ELEMENT::operator~() const { must_bound("Unbound bitstring element operand of operator not4b."); @@ -1688,6 +1705,251 @@ BITSTRING_template& BITSTRING_template::operator= return *this; } +void BITSTRING_template::concat(Vector<unsigned char>& v) const +{ + switch (template_selection) { + case ANY_VALUE: + case ANY_OR_OMIT: + switch (length_restriction_type) { + case NO_LENGTH_RESTRICTION: + if (template_selection == ANY_VALUE) { + // ? => '*' + if (v.size() == 0 || v[v.size() - 1] != 3) { + // '**' == '*', so just ignore the second '*' + v.push_back(3); + } + } + else { + TTCN_error("Operand of bitstring template concatenation is an " + "AnyValueOrNone (*) matching mechanism with no length restriction"); + } + break; + case RANGE_LENGTH_RESTRICTION: + if (!length_restriction.range_length.max_length || + length_restriction.range_length.max_length != length_restriction.range_length.min_length) { + TTCN_error("Operand of bitstring template concatenation is an %s " + "matching mechanism with non-fixed length restriction", + template_selection == ANY_VALUE ? "AnyValue (?)" : "AnyValueOrNone (*)"); + } + // else fall through (range length restriction is allowed if the minimum + // and maximum value are the same) + case SINGLE_LENGTH_RESTRICTION: { + // ? length(N) or * length(N) => '??...?' N times + int len = length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + length_restriction.single_length : length_restriction.range_length.min_length; + for (int i = 0; i < len; ++i) { + v.push_back(2); + } + break; } + } + break; + case SPECIFIC_VALUE: + concat(v, single_value); + break; + case STRING_PATTERN: + for (unsigned int i = 0; i < pattern_value->n_elements; ++i) { + v.push_back(pattern_value->elements_ptr[i]); + } + break; + default: + TTCN_error("Operand of bitstring template concatenation is an " + "uninitialized or unsupported template."); + } +} + +void BITSTRING_template::concat(Vector<unsigned char>& v, const BITSTRING& val) +{ + if (!val.is_bound()) { + TTCN_error("Operand of bitstring template concatenation is an " + "unbound value."); + } + for (int i = 0; i < val.val_ptr->n_bits; ++i) { + v.push_back(val.get_bit(i)); + } +} + +void BITSTRING_template::concat(Vector<unsigned char>& v, template_sel sel) +{ + if (sel == ANY_VALUE) { + // ? => '*' + if (v.size() == 0 || v[v.size() - 1] != 3) { + // '**' == '*', so just ignore the second '*' + v.push_back(3); + } + } + else { + TTCN_error("Operand of bitstring template concatenation is an " + "uninitialized or unsupported template."); + } +} + + +BITSTRING_template BITSTRING_template::operator+( + const BITSTRING_template& other_value) const +{ + if (template_selection == SPECIFIC_VALUE && + other_value.template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return single_value + other_value.single_value; + } + if (template_selection == ANY_VALUE && + other_value.template_selection == ANY_VALUE && + length_restriction_type == NO_LENGTH_RESTRICTION && + other_value.length_restriction_type == NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return BITSTRING_template(ANY_VALUE); + } + // otherwise the result is an bitstring pattern + Vector<unsigned char> v; + concat(v); + other_value.concat(v); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template BITSTRING_template::operator+( + const BITSTRING& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return single_value + other_value; + } + // otherwise the result is an bitstring pattern + Vector<unsigned char> v; + concat(v); + concat(v, other_value); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template BITSTRING_template::operator+( + const BITSTRING_ELEMENT& other_value) const +{ + return *this + BITSTRING(other_value); +} + +BITSTRING_template BITSTRING_template::operator+( + const OPTIONAL<BITSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const BITSTRING&)other_value; + } + TTCN_error("Operand of bitstring template concatenation is an " + "unbound or omitted record/set field."); +} + +BITSTRING_template BITSTRING_template::operator+( + template_sel other_template_sel) const +{ + if (template_selection == ANY_VALUE && other_template_sel == ANY_VALUE && + length_restriction_type == NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return BITSTRING_template(ANY_VALUE); + } + // the result is always an bitstring pattern + Vector<unsigned char> v; + concat(v); + concat(v, other_template_sel); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template operator+(const BITSTRING& left_value, + const BITSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return left_value + right_template.single_value; + } + // otherwise the result is an bitstring pattern + Vector<unsigned char> v; + BITSTRING_template::concat(v, left_value); + right_template.concat(v); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template operator+(const BITSTRING_ELEMENT& left_value, + const BITSTRING_template& right_template) +{ + return BITSTRING(left_value) + right_template; +} + +BITSTRING_template operator+(const OPTIONAL<BITSTRING>& left_value, + const BITSTRING_template& right_template) +{ + if (left_value.is_present()) { + return (const BITSTRING&)left_value + right_template; + } + TTCN_error("Operand of bitstring template concatenation is an " + "unbound or omitted record/set field."); +} + +BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_template& right_template) +{ + if (left_template_sel == ANY_VALUE && + right_template.template_selection == ANY_VALUE && + right_template.length_restriction_type == + Restricted_Length_Template::NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return BITSTRING_template(ANY_VALUE); + } + // the result is always an bitstring pattern + Vector<unsigned char> v; + BITSTRING_template::concat(v, left_template_sel); + right_template.concat(v); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template operator+(const BITSTRING& left_value, + template_sel right_template_sel) +{ + // the result is always an bitstring pattern + Vector<unsigned char> v; + BITSTRING_template::concat(v, left_value); + BITSTRING_template::concat(v, right_template_sel); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template operator+(const BITSTRING_ELEMENT& left_value, + template_sel right_template_sel) +{ + return BITSTRING(left_value) + right_template_sel; +} + +BITSTRING_template operator+(const OPTIONAL<BITSTRING>& left_value, + template_sel right_template_sel) +{ + if (left_value.is_present()) { + return (const BITSTRING&)left_value + right_template_sel; + } + TTCN_error("Operand of bitstring template concatenation is an " + "unbound or omitted record/set field."); +} + +BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING& right_value) +{ + // the result is always an bitstring pattern + Vector<unsigned char> v; + BITSTRING_template::concat(v, left_template_sel); + BITSTRING_template::concat(v, right_value); + return BITSTRING_template(v.size(), v.data_ptr()); +} + +BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_ELEMENT& right_value) +{ + return left_template_sel + BITSTRING(right_value); +} + +BITSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<BITSTRING>& right_value) +{ + if (right_value.is_present()) { + return left_template_sel + (const BITSTRING&)right_value; + } + TTCN_error("Operand of bitstring template concatenation is an " + "unbound or omitted record/set field."); +} + BITSTRING_ELEMENT BITSTRING_template::operator[](int index_value) { if (template_selection != SPECIFIC_VALUE || is_ifpresent) diff --git a/core/Bitstring.hh b/core/Bitstring.hh index 9f9276f45970f1aa043da1d798ca0e7ac2b3ff0e..0db9f0cc69044a5f2fe4d6a553dfc0bccaa89a7a 100644 --- a/core/Bitstring.hh +++ b/core/Bitstring.hh @@ -30,6 +30,7 @@ #include "RAW.hh" #include "BER.hh" #include "Error.hh" +#include "Vector.hh" class INTEGER; class HEXSTRING; @@ -109,6 +110,7 @@ public: BITSTRING operator+(const BITSTRING& other_value) const; BITSTRING operator+(const BITSTRING_ELEMENT& other_value) const; + BITSTRING operator+(const OPTIONAL<BITSTRING>& other_value) const; BITSTRING operator~() const; BITSTRING operator&(const BITSTRING& other_value) const; @@ -227,6 +229,7 @@ public: BITSTRING operator+(const BITSTRING& other_value) const; BITSTRING operator+(const BITSTRING_ELEMENT& other_value) const; + BITSTRING operator+(const OPTIONAL<BITSTRING>& other_value) const; BITSTRING operator~() const; BITSTRING operator&(const BITSTRING& other_value) const; @@ -256,6 +259,27 @@ public: #endif struct bitstring_pattern_struct; private: + friend BITSTRING_template operator+(const BITSTRING& left_value, + const BITSTRING_template& right_template); + friend BITSTRING_template operator+(const BITSTRING_ELEMENT& left_value, + const BITSTRING_template& right_template); + friend BITSTRING_template operator+(const OPTIONAL<BITSTRING>& left_value, + const BITSTRING_template& right_template); + friend BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_template& right_template); + friend BITSTRING_template operator+(const BITSTRING& left_value, + template_sel right_template_sel); + friend BITSTRING_template operator+(const BITSTRING_ELEMENT& left_value, + template_sel right_template_sel); + friend BITSTRING_template operator+(const OPTIONAL<BITSTRING>& left_value, + template_sel right_template_sel); + friend BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING& right_value); + friend BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_ELEMENT& right_value); + friend BITSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<BITSTRING>& right_value); + BITSTRING single_value; union { struct { @@ -270,6 +294,10 @@ private: static boolean match_pattern(const bitstring_pattern_struct *string_pattern, const BITSTRING::bitstring_struct *string_value); + void concat(Vector<unsigned char>& v) const; + static void concat(Vector<unsigned char>& v, const BITSTRING& val); + static void concat(Vector<unsigned char>& v, template_sel sel); + public: BITSTRING_template(); BITSTRING_template(template_sel other_value); @@ -287,6 +315,12 @@ public: BITSTRING_template& operator=(const BITSTRING_ELEMENT& other_value); BITSTRING_template& operator=(const OPTIONAL<BITSTRING>& other_value); BITSTRING_template& operator=(const BITSTRING_template& other_value); + + BITSTRING_template operator+(const BITSTRING_template& other_value) const; + BITSTRING_template operator+(const BITSTRING& other_value) const; + BITSTRING_template operator+(const BITSTRING_ELEMENT& other_value) const; + BITSTRING_template operator+(const OPTIONAL<BITSTRING>& other_value) const; + BITSTRING_template operator+(template_sel other_template_sel) const; BITSTRING_ELEMENT operator[](int index_value); BITSTRING_ELEMENT operator[](const INTEGER& index_value); @@ -330,4 +364,25 @@ public: #endif }; +extern BITSTRING_template operator+(const BITSTRING& left_value, + const BITSTRING_template& right_template); +extern BITSTRING_template operator+(const BITSTRING_ELEMENT& left_value, + const BITSTRING_template& right_template); +extern BITSTRING_template operator+(const OPTIONAL<BITSTRING>& left_value, + const BITSTRING_template& right_template); +extern BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_template& right_template); +extern BITSTRING_template operator+(const BITSTRING& left_value, + template_sel right_template_sel); +extern BITSTRING_template operator+(const BITSTRING_ELEMENT& left_value, + template_sel right_template_sel); +extern BITSTRING_template operator+(const OPTIONAL<BITSTRING>& left_value, + template_sel right_template_sel); +extern BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING& right_value); +extern BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_ELEMENT& right_value); +extern BITSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<BITSTRING>& right_value); + #endif diff --git a/core/Charstring.cc b/core/Charstring.cc index 71d898e165ea4cba32ece3fa61128f08299a4aa0..241bdbf5c07a2932845f7fc6324e9b2d97f99927 100644 --- a/core/Charstring.cc +++ b/core/Charstring.cc @@ -323,6 +323,14 @@ CHARSTRING CHARSTRING::operator+(const CHARSTRING_ELEMENT& other_value) const return ret_val; } +CHARSTRING CHARSTRING::operator+(const OPTIONAL<CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of charstring concatenation."); +} + UNIVERSAL_CHARSTRING CHARSTRING::operator+ (const UNIVERSAL_CHARSTRING& other_value) const { @@ -377,6 +385,16 @@ UNIVERSAL_CHARSTRING CHARSTRING::operator+ } } +UNIVERSAL_CHARSTRING CHARSTRING::operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const UNIVERSAL_CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); +} + CHARSTRING& CHARSTRING::operator+=(char other_value) { must_bound("Appending a character to an unbound charstring value."); @@ -1900,6 +1918,15 @@ CHARSTRING CHARSTRING_ELEMENT::operator+(const CHARSTRING_ELEMENT& return CHARSTRING(2, result); } +CHARSTRING CHARSTRING_ELEMENT::operator+( + const OPTIONAL<CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of charstring concatenation."); +} + UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+ (const UNIVERSAL_CHARSTRING& other_value) const { @@ -1940,6 +1967,16 @@ UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+ return UNIVERSAL_CHARSTRING(2, result); } +UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const UNIVERSAL_CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); +} + char CHARSTRING_ELEMENT::get_char() const { return str_val.val_ptr->chars_ptr[char_pos]; @@ -2005,6 +2042,60 @@ CHARSTRING operator+(const char* string_value, return ret_val; } +CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING& right_value) +{ + if (left_value.is_present()) { + return (const CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of charstring " + "concatenation."); +} + +CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING_ELEMENT& right_value) +{ + if (left_value.is_present()) { + return (const CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING& right_value) +{ + if (left_value.is_present()) { + return (const CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_ELEMENT& right_value) +{ + if (left_value.is_present()) { + return (const CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const OPTIONAL<UNIVERSAL_CHARSTRING>& right_value) +{ + if (!left_value.is_present()) { + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); + } + if (!right_value.is_present()) { + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); + } + return (const CHARSTRING&)left_value + (const UNIVERSAL_CHARSTRING&)right_value; +} + CHARSTRING operator<<=(const char *string_value, const INTEGER& rotate_count) { return CHARSTRING(string_value) <<= rotate_count; @@ -2203,6 +2294,154 @@ CHARSTRING_template& CHARSTRING_template::operator= return *this; } +CHARSTRING_template CHARSTRING_template::operator+( + const CHARSTRING_template& other_value) const +{ + if (template_selection == SPECIFIC_VALUE && + other_value.template_selection == SPECIFIC_VALUE) { + return single_value + other_value.single_value; + } + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +CHARSTRING_template CHARSTRING_template::operator+(const CHARSTRING& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + return single_value + other_value; + } + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +CHARSTRING_template CHARSTRING_template::operator+( + const CHARSTRING_ELEMENT& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + return single_value + other_value; + } + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +CHARSTRING_template CHARSTRING_template::operator+( + const OPTIONAL<CHARSTRING>& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + if (!other_value.is_present()) { + TTCN_error("Operand of charstring template concatenation is an " + "unbound or omitted record/set field."); + } + return single_value + (const CHARSTRING&)other_value; +} + +UNIVERSAL_CHARSTRING_template CHARSTRING_template::operator+( + const UNIVERSAL_CHARSTRING& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return single_value + other_value; +} + +UNIVERSAL_CHARSTRING_template CHARSTRING_template::operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return single_value + other_value; +} + +UNIVERSAL_CHARSTRING_template CHARSTRING_template::operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + if (!other_value.is_present()) { + TTCN_error("Operand of universal charstring template concatenation is an " + "unbound or omitted record/set field."); + } + return single_value + (const UNIVERSAL_CHARSTRING&)other_value; +} + +CHARSTRING_template operator+(const CHARSTRING& left_value, + const CHARSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + return left_value + right_template.single_value; + } + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +CHARSTRING_template operator+(const CHARSTRING_ELEMENT& left_value, + const CHARSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + return left_value + right_template.single_value; + } + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +CHARSTRING_template operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING_template& right_template) +{ + if (!left_value.is_present()) { + TTCN_error("Operand of charstring template concatenation is an " + "unbound or omitted record/set field."); + } + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return (const CHARSTRING&)left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+(const UNIVERSAL_CHARSTRING& left_value, + const CHARSTRING_template& right_template) +{ + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& left_value, + const CHARSTRING_template& right_template) +{ + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING_template& right_template) +{ + if (!left_value.is_present()) { + TTCN_error("Operand of universal charstring template concatenation is an " + "unbound or omitted record/set field."); + } + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return (const UNIVERSAL_CHARSTRING&)left_value + right_template.single_value; +} + CHARSTRING_ELEMENT CHARSTRING_template::operator[](int index_value) { if (template_selection != SPECIFIC_VALUE || is_ifpresent) diff --git a/core/Charstring.hh b/core/Charstring.hh index 65dbb8053a0dc9b719a5b2e7fa93db9af37c22c4..2aa0b3d00480df453219462b02f47619a7402452 100644 --- a/core/Charstring.hh +++ b/core/Charstring.hh @@ -40,6 +40,7 @@ class OCTETSTRING; class CHARSTRING_ELEMENT; class UNIVERSAL_CHARSTRING; class UNIVERSAL_CHARSTRING_ELEMENT; +class UNIVERSAL_CHARSTRING_template; class Module_Param; @@ -158,9 +159,12 @@ public: CHARSTRING operator+(const char* other_value) const; CHARSTRING operator+(const CHARSTRING& other_value) const; CHARSTRING operator+(const CHARSTRING_ELEMENT& other_value) const; + CHARSTRING operator+(const OPTIONAL<CHARSTRING>& other_value) const; UNIVERSAL_CHARSTRING operator+(const UNIVERSAL_CHARSTRING& other_value) const; UNIVERSAL_CHARSTRING operator+ (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const; CHARSTRING& operator+=(char other_value); CHARSTRING& operator+=(const char *other_value); @@ -308,9 +312,12 @@ public: CHARSTRING operator+(const char *other_value) const; CHARSTRING operator+(const CHARSTRING& other_value) const; CHARSTRING operator+(const CHARSTRING_ELEMENT& other_value) const; + CHARSTRING operator+(const OPTIONAL<CHARSTRING>& other_value) const; UNIVERSAL_CHARSTRING operator+(const UNIVERSAL_CHARSTRING& other_value) const; UNIVERSAL_CHARSTRING operator+ (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const; inline boolean is_bound() const { return bound_flag; } inline boolean is_present() const { return bound_flag; } @@ -344,6 +351,16 @@ extern CHARSTRING operator+(const char* string_value, const CHARSTRING& other_value); extern CHARSTRING operator+(const char* string_value, const CHARSTRING_ELEMENT& other_value); +extern CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING& right_value); +extern CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING_ELEMENT& right_value); +extern UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING& right_value); +extern UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_ELEMENT& right_value); +extern UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& left_value, + const OPTIONAL<UNIVERSAL_CHARSTRING>& right_value); extern CHARSTRING operator<<=(const char *string_value, const INTEGER& rotate_count); @@ -357,6 +374,25 @@ struct unichar_decmatch_struct; class CHARSTRING_template : public Restricted_Length_Template { friend class UNIVERSAL_CHARSTRING_template; + + friend CHARSTRING_template operator+(const CHARSTRING& left_value, + const CHARSTRING_template& right_template); + friend CHARSTRING_template operator+(const CHARSTRING_ELEMENT& left_value, + const CHARSTRING_template& right_template); + friend CHARSTRING_template operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING& left_value, + const CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& left_value, + const CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const CHARSTRING_template& left_template, + const UNIVERSAL_CHARSTRING_template& right_template); private: CHARSTRING single_value; @@ -420,6 +456,17 @@ public: CHARSTRING_template& operator=(const CHARSTRING_ELEMENT& other_value); CHARSTRING_template& operator=(const OPTIONAL<CHARSTRING>& other_value); CHARSTRING_template& operator=(const CHARSTRING_template& other_value); + + CHARSTRING_template operator+(const CHARSTRING_template& other_value) const; + CHARSTRING_template operator+(const CHARSTRING& other_value) const; + CHARSTRING_template operator+(const CHARSTRING_ELEMENT& other_value) const; + CHARSTRING_template operator+(const OPTIONAL<CHARSTRING>& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const; CHARSTRING_ELEMENT operator[](int index_value); CHARSTRING_ELEMENT operator[](const INTEGER& index_value); @@ -472,6 +519,22 @@ public: const CHARSTRING& get_single_value() const; }; +extern CHARSTRING_template operator+(const CHARSTRING& left_value, + const CHARSTRING_template& right_template); +extern CHARSTRING_template operator+(const CHARSTRING_ELEMENT& left_value, + const CHARSTRING_template& right_template); +extern CHARSTRING_template operator+(const OPTIONAL<CHARSTRING>& left_value, + const CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING& left_value, + const CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& left_value, + const CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING_template& right_template); + typedef CHARSTRING NumericString; typedef CHARSTRING PrintableString; typedef CHARSTRING IA5String; diff --git a/core/Hexstring.cc b/core/Hexstring.cc index 4242a016270a46a1cb7711e84687a53a53066aab..e8a86dc2eff46039f1afeaf62a917909787ede15 100644 --- a/core/Hexstring.cc +++ b/core/Hexstring.cc @@ -263,6 +263,14 @@ HEXSTRING HEXSTRING::operator+(const HEXSTRING_ELEMENT& other_value) const return ret_val; } +HEXSTRING HEXSTRING::operator+(const OPTIONAL<HEXSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const HEXSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of hexstring concatenation."); +} + HEXSTRING HEXSTRING::operator~() const { must_bound("Unbound hexstring operand of operator not4b."); @@ -1225,6 +1233,15 @@ HEXSTRING HEXSTRING_ELEMENT::operator+(const HEXSTRING_ELEMENT& other_value) con return HEXSTRING(2, &result); } +HEXSTRING HEXSTRING_ELEMENT::operator+( + const OPTIONAL<HEXSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const HEXSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of hexstring concatenation."); +} + HEXSTRING HEXSTRING_ELEMENT::operator~() const { must_bound("Unbound hexstring element operand of operator not4b."); @@ -1577,6 +1594,251 @@ HEXSTRING_template& HEXSTRING_template::operator=( return *this; } +void HEXSTRING_template::concat(Vector<unsigned char>& v) const +{ + switch (template_selection) { + case ANY_VALUE: + case ANY_OR_OMIT: + switch (length_restriction_type) { + case NO_LENGTH_RESTRICTION: + if (template_selection == ANY_VALUE) { + // ? => '*' + if (v.size() == 0 || v[v.size() - 1] != 17) { + // '**' == '*', so just ignore the second '*' + v.push_back(17); + } + } + else { + TTCN_error("Operand of hexstring template concatenation is an " + "AnyValueOrNone (*) matching mechanism with no length restriction"); + } + break; + case RANGE_LENGTH_RESTRICTION: + if (!length_restriction.range_length.max_length || + length_restriction.range_length.max_length != length_restriction.range_length.min_length) { + TTCN_error("Operand of hexstring template concatenation is an %s " + "matching mechanism with non-fixed length restriction", + template_selection == ANY_VALUE ? "AnyValue (?)" : "AnyValueOrNone (*)"); + } + // else fall through (range length restriction is allowed if the minimum + // and maximum value are the same) + case SINGLE_LENGTH_RESTRICTION: { + // ? length(N) or * length(N) => '??...?' N times + int len = length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + length_restriction.single_length : length_restriction.range_length.min_length; + for (int i = 0; i < len; ++i) { + v.push_back(16); + } + break; } + } + break; + case SPECIFIC_VALUE: + concat(v, single_value); + break; + case STRING_PATTERN: + for (unsigned int i = 0; i < pattern_value->n_elements; ++i) { + v.push_back(pattern_value->elements_ptr[i]); + } + break; + default: + TTCN_error("Operand of hexstring template concatenation is an " + "uninitialized or unsupported template."); + } +} + +void HEXSTRING_template::concat(Vector<unsigned char>& v, const HEXSTRING& val) +{ + if (!val.is_bound()) { + TTCN_error("Operand of hexstring template concatenation is an " + "unbound value."); + } + for (int i = 0; i < val.val_ptr->n_nibbles; ++i) { + v.push_back(val.get_nibble(i)); + } +} + +void HEXSTRING_template::concat(Vector<unsigned char>& v, template_sel sel) +{ + if (sel == ANY_VALUE) { + // ? => '*' + if (v.size() == 0 || v[v.size() - 1] != 17) { + // '**' == '*', so just ignore the second '*' + v.push_back(17); + } + } + else { + TTCN_error("Operand of hexstring template concatenation is an " + "uninitialized or unsupported template."); + } +} + + +HEXSTRING_template HEXSTRING_template::operator+( + const HEXSTRING_template& other_value) const +{ + if (template_selection == SPECIFIC_VALUE && + other_value.template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return single_value + other_value.single_value; + } + if (template_selection == ANY_VALUE && + other_value.template_selection == ANY_VALUE && + length_restriction_type == NO_LENGTH_RESTRICTION && + other_value.length_restriction_type == NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return HEXSTRING_template(ANY_VALUE); + } + // otherwise the result is an hexstring pattern + Vector<unsigned char> v; + concat(v); + other_value.concat(v); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template HEXSTRING_template::operator+( + const HEXSTRING& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return single_value + other_value; + } + // otherwise the result is an hexstring pattern + Vector<unsigned char> v; + concat(v); + concat(v, other_value); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template HEXSTRING_template::operator+( + const HEXSTRING_ELEMENT& other_value) const +{ + return *this + HEXSTRING(other_value); +} + +HEXSTRING_template HEXSTRING_template::operator+( + const OPTIONAL<HEXSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const HEXSTRING&)other_value; + } + TTCN_error("Operand of hexstring template concatenation is an " + "unbound or omitted record/set field."); +} + +HEXSTRING_template HEXSTRING_template::operator+( + template_sel other_template_sel) const +{ + if (template_selection == ANY_VALUE && other_template_sel == ANY_VALUE && + length_restriction_type == NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return HEXSTRING_template(ANY_VALUE); + } + // the result is always an hexstring pattern + Vector<unsigned char> v; + concat(v); + concat(v, other_template_sel); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template operator+(const HEXSTRING& left_value, + const HEXSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return left_value + right_template.single_value; + } + // otherwise the result is an hexstring pattern + Vector<unsigned char> v; + HEXSTRING_template::concat(v, left_value); + right_template.concat(v); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template operator+(const HEXSTRING_ELEMENT& left_value, + const HEXSTRING_template& right_template) +{ + return HEXSTRING(left_value) + right_template; +} + +HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& left_value, + const HEXSTRING_template& right_template) +{ + if (left_value.is_present()) { + return (const HEXSTRING&)left_value + right_template; + } + TTCN_error("Operand of hexstring template concatenation is an " + "unbound or omitted record/set field."); +} + +HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_template& right_template) +{ + if (left_template_sel == ANY_VALUE && + right_template.template_selection == ANY_VALUE && + right_template.length_restriction_type == + Restricted_Length_Template::NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return HEXSTRING_template(ANY_VALUE); + } + // the result is always an hexstring pattern + Vector<unsigned char> v; + HEXSTRING_template::concat(v, left_template_sel); + right_template.concat(v); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template operator+(const HEXSTRING& left_value, + template_sel right_template_sel) +{ + // the result is always an hexstring pattern + Vector<unsigned char> v; + HEXSTRING_template::concat(v, left_value); + HEXSTRING_template::concat(v, right_template_sel); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template operator+(const HEXSTRING_ELEMENT& left_value, + template_sel right_template_sel) +{ + return HEXSTRING(left_value) + right_template_sel; +} + +HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& left_value, + template_sel right_template_sel) +{ + if (left_value.is_present()) { + return (const HEXSTRING&)left_value + right_template_sel; + } + TTCN_error("Operand of hexstring template concatenation is an " + "unbound or omitted record/set field."); +} + +HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING& right_value) +{ + // the result is always an hexstring pattern + Vector<unsigned char> v; + HEXSTRING_template::concat(v, left_template_sel); + HEXSTRING_template::concat(v, right_value); + return HEXSTRING_template(v.size(), v.data_ptr()); +} + +HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_ELEMENT& right_value) +{ + return left_template_sel + HEXSTRING(right_value); +} + +HEXSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<HEXSTRING>& right_value) +{ + if (right_value.is_present()) { + return left_template_sel + (const HEXSTRING&)right_value; + } + TTCN_error("Operand of hexstring template concatenation is an " + "unbound or omitted record/set field."); +} + HEXSTRING_ELEMENT HEXSTRING_template::operator[](int index_value) { if (template_selection != SPECIFIC_VALUE || is_ifpresent) diff --git a/core/Hexstring.hh b/core/Hexstring.hh index 0639e106aba37105276b530e718441829dadf2ec..f2fd315d1f46bfb74fb9cb08c0d8d4c6c58a60af 100644 --- a/core/Hexstring.hh +++ b/core/Hexstring.hh @@ -27,6 +27,7 @@ #include "Basetype.hh" #include "Template.hh" #include "Error.hh" +#include "Vector.hh" class INTEGER; class BITSTRING; @@ -82,6 +83,7 @@ public: HEXSTRING operator+(const HEXSTRING& other_value) const; HEXSTRING operator+(const HEXSTRING_ELEMENT& other_value) const; + HEXSTRING operator+(const OPTIONAL<HEXSTRING>& other_value) const; HEXSTRING operator~() const; HEXSTRING operator&(const HEXSTRING& other_value) const; @@ -180,6 +182,7 @@ public: HEXSTRING operator+(const HEXSTRING& other_value) const; HEXSTRING operator+(const HEXSTRING_ELEMENT& other_value) const; + HEXSTRING operator+(const OPTIONAL<HEXSTRING>& other_value) const; HEXSTRING operator~() const; HEXSTRING operator&(const HEXSTRING& other_value) const; @@ -209,6 +212,27 @@ public: #endif struct hexstring_pattern_struct; private: + friend HEXSTRING_template operator+(const HEXSTRING& left_value, + const HEXSTRING_template& right_template); + friend HEXSTRING_template operator+(const HEXSTRING_ELEMENT& left_value, + const HEXSTRING_template& right_template); + friend HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& left_value, + const HEXSTRING_template& right_template); + friend HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_template& right_template); + friend HEXSTRING_template operator+(const HEXSTRING& left_value, + template_sel right_template_sel); + friend HEXSTRING_template operator+(const HEXSTRING_ELEMENT& left_value, + template_sel right_template_sel); + friend HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& left_value, + template_sel right_template_sel); + friend HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING& right_value); + friend HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_ELEMENT& right_value); + friend HEXSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<HEXSTRING>& right_value); + HEXSTRING single_value; union { struct { @@ -223,6 +247,10 @@ private: static boolean match_pattern(const hexstring_pattern_struct *string_pattern, const HEXSTRING::hexstring_struct *string_value); + void concat(Vector<unsigned char>& v) const; + static void concat(Vector<unsigned char>& v, const HEXSTRING& val); + static void concat(Vector<unsigned char>& v, template_sel sel); + public: HEXSTRING_template(); HEXSTRING_template(template_sel other_value); @@ -240,6 +268,12 @@ public: HEXSTRING_template& operator=(const HEXSTRING_ELEMENT& other_value); HEXSTRING_template& operator=(const OPTIONAL<HEXSTRING>& other_value); HEXSTRING_template& operator=(const HEXSTRING_template& other_value); + + HEXSTRING_template operator+(const HEXSTRING_template& other_value) const; + HEXSTRING_template operator+(const HEXSTRING& other_value) const; + HEXSTRING_template operator+(const HEXSTRING_ELEMENT& other_value) const; + HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& other_value) const; + HEXSTRING_template operator+(template_sel other_template_sel) const; HEXSTRING_ELEMENT operator[](int index_value); HEXSTRING_ELEMENT operator[](const INTEGER& index_value); @@ -283,4 +317,25 @@ public: #endif }; +extern HEXSTRING_template operator+(const HEXSTRING& left_value, + const HEXSTRING_template& right_template); +extern HEXSTRING_template operator+(const HEXSTRING_ELEMENT& left_value, + const HEXSTRING_template& right_template); +extern HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& left_value, + const HEXSTRING_template& right_template); +extern HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_template& right_template); +extern HEXSTRING_template operator+(const HEXSTRING& left_value, + template_sel right_template_sel); +extern HEXSTRING_template operator+(const HEXSTRING_ELEMENT& left_value, + template_sel right_template_sel); +extern HEXSTRING_template operator+(const OPTIONAL<HEXSTRING>& left_value, + template_sel right_template_sel); +extern HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING& right_value); +extern HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_ELEMENT& right_value); +extern HEXSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<HEXSTRING>& right_value); + #endif diff --git a/core/Octetstring.cc b/core/Octetstring.cc index 1a757f3798fb68da65b576c0aeed66947184d384..ec3416c18b81826eeae4297d83f8781f878a1c4e 100644 --- a/core/Octetstring.cc +++ b/core/Octetstring.cc @@ -185,6 +185,14 @@ OCTETSTRING OCTETSTRING::operator+(const OCTETSTRING_ELEMENT& other_value) const return ret_val; } +OCTETSTRING OCTETSTRING::operator+(const OPTIONAL<OCTETSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const OCTETSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of octetstring concatenation."); +} + OCTETSTRING& OCTETSTRING::operator+=(const OCTETSTRING& other_value) { must_bound("Appending an octetstring value to an unbound octetstring value."); @@ -1454,6 +1462,15 @@ OCTETSTRING OCTETSTRING_ELEMENT::operator+ return OCTETSTRING(2, result); } +OCTETSTRING OCTETSTRING_ELEMENT::operator+( + const OPTIONAL<OCTETSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const OCTETSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of octetstring concatenation."); +} + OCTETSTRING OCTETSTRING_ELEMENT::operator~() const { must_bound("Unbound octetstring element operand of operator not4b."); @@ -1819,6 +1836,251 @@ OCTETSTRING_template& OCTETSTRING_template::operator= return *this; } +void OCTETSTRING_template::concat(Vector<unsigned short>& v) const +{ + switch (template_selection) { + case ANY_VALUE: + case ANY_OR_OMIT: + switch (length_restriction_type) { + case NO_LENGTH_RESTRICTION: + if (template_selection == ANY_VALUE) { + // ? => '*' + if (v.size() == 0 || v[v.size() - 1] != 257) { + // '**' == '*', so just ignore the second '*' + v.push_back(257); + } + } + else { + TTCN_error("Operand of octetstring template concatenation is an " + "AnyValueOrNone (*) matching mechanism with no length restriction"); + } + break; + case RANGE_LENGTH_RESTRICTION: + if (!length_restriction.range_length.max_length || + length_restriction.range_length.max_length != length_restriction.range_length.min_length) { + TTCN_error("Operand of octetstring template concatenation is an %s " + "matching mechanism with non-fixed length restriction", + template_selection == ANY_VALUE ? "AnyValue (?)" : "AnyValueOrNone (*)"); + } + // else fall through (range length restriction is allowed if the minimum + // and maximum value are the same) + case SINGLE_LENGTH_RESTRICTION: { + // ? length(N) or * length(N) => '??...?' N times + int len = length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + length_restriction.single_length : length_restriction.range_length.min_length; + for (int i = 0; i < len; ++i) { + v.push_back(256); + } + break; } + } + break; + case SPECIFIC_VALUE: + concat(v, single_value); + break; + case STRING_PATTERN: + for (unsigned int i = 0; i < pattern_value->n_elements; ++i) { + v.push_back(pattern_value->elements_ptr[i]); + } + break; + default: + TTCN_error("Operand of octetstring template concatenation is an " + "uninitialized or unsupported template."); + } +} + +void OCTETSTRING_template::concat(Vector<unsigned short>& v, const OCTETSTRING& val) +{ + if (!val.is_bound()) { + TTCN_error("Operand of octetstring template concatenation is an " + "unbound value."); + } + for (int i = 0; i < val.val_ptr->n_octets; ++i) { + v.push_back(val.val_ptr->octets_ptr[i]); + } +} + +void OCTETSTRING_template::concat(Vector<unsigned short>& v, template_sel sel) +{ + if (sel == ANY_VALUE) { + // ? => '*' + if (v.size() == 0 || v[v.size() - 1] != 257) { + // '**' == '*', so just ignore the second '*' + v.push_back(257); + } + } + else { + TTCN_error("Operand of octetstring template concatenation is an " + "uninitialized or unsupported template."); + } +} + + +OCTETSTRING_template OCTETSTRING_template::operator+( + const OCTETSTRING_template& other_value) const +{ + if (template_selection == SPECIFIC_VALUE && + other_value.template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return single_value + other_value.single_value; + } + if (template_selection == ANY_VALUE && + other_value.template_selection == ANY_VALUE && + length_restriction_type == NO_LENGTH_RESTRICTION && + other_value.length_restriction_type == NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return OCTETSTRING_template(ANY_VALUE); + } + // otherwise the result is an octetstring pattern + Vector<unsigned short> v; + concat(v); + other_value.concat(v); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template OCTETSTRING_template::operator+( + const OCTETSTRING& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return single_value + other_value; + } + // otherwise the result is an octetstring pattern + Vector<unsigned short> v; + concat(v); + concat(v, other_value); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template OCTETSTRING_template::operator+( + const OCTETSTRING_ELEMENT& other_value) const +{ + return *this + OCTETSTRING(other_value); +} + +OCTETSTRING_template OCTETSTRING_template::operator+( + const OPTIONAL<OCTETSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const OCTETSTRING&)other_value; + } + TTCN_error("Operand of octetstring template concatenation is an " + "unbound or omitted record/set field."); +} + +OCTETSTRING_template OCTETSTRING_template::operator+( + template_sel other_template_sel) const +{ + if (template_selection == ANY_VALUE && other_template_sel == ANY_VALUE && + length_restriction_type == NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return OCTETSTRING_template(ANY_VALUE); + } + // the result is always an octetstring pattern + Vector<unsigned short> v; + concat(v); + concat(v, other_template_sel); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template operator+(const OCTETSTRING& left_value, + const OCTETSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + // result is a specific value template + return left_value + right_template.single_value; + } + // otherwise the result is an octetstring pattern + Vector<unsigned short> v; + OCTETSTRING_template::concat(v, left_value); + right_template.concat(v); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& left_value, + const OCTETSTRING_template& right_template) +{ + return OCTETSTRING(left_value) + right_template; +} + +OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& left_value, + const OCTETSTRING_template& right_template) +{ + if (left_value.is_present()) { + return (const OCTETSTRING&)left_value + right_template; + } + TTCN_error("Operand of octetstring template concatenation is an " + "unbound or omitted record/set field."); +} + +OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_template& right_template) +{ + if (left_template_sel == ANY_VALUE && + right_template.template_selection == ANY_VALUE && + right_template.length_restriction_type == + Restricted_Length_Template::NO_LENGTH_RESTRICTION) { + // special case: ? & ? => ? + return OCTETSTRING_template(ANY_VALUE); + } + // the result is always an octetstring pattern + Vector<unsigned short> v; + OCTETSTRING_template::concat(v, left_template_sel); + right_template.concat(v); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template operator+(const OCTETSTRING& left_value, + template_sel right_template_sel) +{ + // the result is always an octetstring pattern + Vector<unsigned short> v; + OCTETSTRING_template::concat(v, left_value); + OCTETSTRING_template::concat(v, right_template_sel); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& left_value, + template_sel right_template_sel) +{ + return OCTETSTRING(left_value) + right_template_sel; +} + +OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& left_value, + template_sel right_template_sel) +{ + if (left_value.is_present()) { + return (const OCTETSTRING&)left_value + right_template_sel; + } + TTCN_error("Operand of octetstring template concatenation is an " + "unbound or omitted record/set field."); +} + +OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING& right_value) +{ + // the result is always an octetstring pattern + Vector<unsigned short> v; + OCTETSTRING_template::concat(v, left_template_sel); + OCTETSTRING_template::concat(v, right_value); + return OCTETSTRING_template(v.size(), v.data_ptr()); +} + +OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_ELEMENT& right_value) +{ + return left_template_sel + OCTETSTRING(right_value); +} + +OCTETSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<OCTETSTRING>& right_value) +{ + if (right_value.is_present()) { + return left_template_sel + (const OCTETSTRING&)right_value; + } + TTCN_error("Operand of octetstring template concatenation is an " + "unbound or omitted record/set field."); +} + OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value) { if (template_selection != SPECIFIC_VALUE || is_ifpresent) diff --git a/core/Octetstring.hh b/core/Octetstring.hh index a7b3a586a28512143e17868adcae2de96cfa8647..9fe7ca8165e84765e2ecc445f16bafb8697e0fdc 100644 --- a/core/Octetstring.hh +++ b/core/Octetstring.hh @@ -29,6 +29,7 @@ #include "Basetype.hh" #include "Template.hh" #include "Error.hh" +#include "Vector.hh" class INTEGER; class BITSTRING; @@ -86,6 +87,7 @@ public: OCTETSTRING operator+(const OCTETSTRING& other_value) const; OCTETSTRING operator+(const OCTETSTRING_ELEMENT& other_value) const; + OCTETSTRING operator+(const OPTIONAL<OCTETSTRING>& other_value) const; OCTETSTRING& operator+=(const OCTETSTRING& other_value); OCTETSTRING& operator+=(const OCTETSTRING_ELEMENT& other_value); @@ -210,7 +212,8 @@ public: OCTETSTRING operator+(const OCTETSTRING& other_value) const; OCTETSTRING operator+(const OCTETSTRING_ELEMENT& other_value) const; - + OCTETSTRING operator+(const OPTIONAL<OCTETSTRING>& other_value) const; + OCTETSTRING operator~() const; OCTETSTRING operator&(const OCTETSTRING& other_value) const; OCTETSTRING operator&(const OCTETSTRING_ELEMENT& other_value) const; @@ -240,6 +243,27 @@ public: #endif struct octetstring_pattern_struct; private: + friend OCTETSTRING_template operator+(const OCTETSTRING& left_value, + const OCTETSTRING_template& right_template); + friend OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& left_value, + const OCTETSTRING_template& right_template); + friend OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& left_value, + const OCTETSTRING_template& right_template); + friend OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_template& right_template); + friend OCTETSTRING_template operator+(const OCTETSTRING& left_value, + template_sel right_template_sel); + friend OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& left_value, + template_sel right_template_sel); + friend OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& left_value, + template_sel right_template_sel); + friend OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING& right_value); + friend OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_ELEMENT& right_value); + friend OCTETSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<OCTETSTRING>& right_value); + OCTETSTRING single_value; union { struct { @@ -254,6 +278,10 @@ private: static boolean match_pattern(const octetstring_pattern_struct *string_pattern, const OCTETSTRING::octetstring_struct *string_value); + void concat(Vector<unsigned short>& v) const; + static void concat(Vector<unsigned short>& v, const OCTETSTRING& val); + static void concat(Vector<unsigned short>& v, template_sel sel); + public: OCTETSTRING_template(); OCTETSTRING_template(template_sel other_value); @@ -271,6 +299,12 @@ public: OCTETSTRING_template& operator=(const OCTETSTRING_ELEMENT& other_value); OCTETSTRING_template& operator=(const OPTIONAL<OCTETSTRING>& other_value); OCTETSTRING_template& operator=(const OCTETSTRING_template& other_value); + + OCTETSTRING_template operator+(const OCTETSTRING_template& other_value) const; + OCTETSTRING_template operator+(const OCTETSTRING& other_value) const; + OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& other_value) const; + OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& other_value) const; + OCTETSTRING_template operator+(template_sel other_template_sel) const; OCTETSTRING_ELEMENT operator[](int index_value); OCTETSTRING_ELEMENT operator[](const INTEGER& index_value); @@ -314,4 +348,25 @@ public: #endif }; +extern OCTETSTRING_template operator+(const OCTETSTRING& left_value, + const OCTETSTRING_template& right_template); +extern OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& left_value, + const OCTETSTRING_template& right_template); +extern OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& left_value, + const OCTETSTRING_template& right_template); +extern OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_template& right_template); +extern OCTETSTRING_template operator+(const OCTETSTRING& left_value, + template_sel right_template_sel); +extern OCTETSTRING_template operator+(const OCTETSTRING_ELEMENT& left_value, + template_sel right_template_sel); +extern OCTETSTRING_template operator+(const OPTIONAL<OCTETSTRING>& left_value, + template_sel right_template_sel); +extern OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING& right_value); +extern OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_ELEMENT& right_value); +extern OCTETSTRING_template operator+(template_sel left_template_sel, + const OPTIONAL<OCTETSTRING>& right_value); + #endif diff --git a/core/Template.cc b/core/Template.cc index 75e1fc7b07e297b6f13590d2168a5efbb8cd9eee..a39af902e49486c9c43aef5b0e55162b3d275ce1 100644 --- a/core/Template.cc +++ b/core/Template.cc @@ -505,6 +505,15 @@ boolean Restricted_Length_Template::is_any_or_omit() const length_restriction_type == NO_LENGTH_RESTRICTION; } +template_sel operator+(template_sel left_template_sel, template_sel right_template_sel) +{ + if (left_template_sel == ANY_VALUE && right_template_sel == ANY_VALUE) { + return ANY_VALUE; + } + TTCN_error("Operand of template concatenation is an uninitialized or " + "unsupported template."); +} + //////////////////////////////////////////////////////////////////////////////// struct Record_Of_Template::Pair_of_elements{ @@ -888,6 +897,129 @@ const Base_Template* Record_Of_Template::get_at( return get_at((int)index_value); } +int Record_Of_Template::get_length_for_concat(boolean& is_any_value) const +{ + switch (template_selection) { + case SPECIFIC_VALUE: + return single_value.n_elements; + case ANY_VALUE: + case ANY_OR_OMIT: + switch (length_restriction_type) { + case NO_LENGTH_RESTRICTION: + if (template_selection == ANY_VALUE) { + // ? => { * } + is_any_value = TRUE; + return 1; + } + TTCN_error("Operand of record of template concatenation is an " + "AnyValueOrNone (*) matching mechanism with no length restriction"); + case RANGE_LENGTH_RESTRICTION: + if (!length_restriction.range_length.max_length || + length_restriction.range_length.max_length != length_restriction.range_length.min_length) { + TTCN_error("Operand of record of template concatenation is an %s " + "matching mechanism with non-fixed length restriction", + template_selection == ANY_VALUE ? "AnyValue (?)" : "AnyValueOrNone (*)"); + } + // else fall through (range length restriction is allowed if the minimum + // and maximum value are the same) + case SINGLE_LENGTH_RESTRICTION: + // ? length(N) or * length(N) => { ?, ?, ... ? } N times + return length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + length_restriction.single_length : length_restriction.range_length.min_length; + } + default: + TTCN_error("Operand of record of template concatenation is an " + "uninitialized or unsupported template."); + } +} + +int Record_Of_Template::get_length_for_concat(const Record_Of_Type& operand) +{ + if (!operand.is_bound()) { + TTCN_error("Operand of record of template concatenation is an " + "unbound value."); + } + return operand.val_ptr->n_elements; +} + +int Record_Of_Template::get_length_for_concat(template_sel operand) +{ + if (operand == ANY_VALUE) { + // ? => { * } + return 1; + } + TTCN_error("Operand of record of template concatenation is an " + "uninitialized or unsupported template."); +} + +void Record_Of_Template::concat(int& pos, const Record_Of_Template& operand) +{ + // all errors should have already been caught by the operand's + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + switch (operand.template_selection) { + case SPECIFIC_VALUE: + for (int i = 0; i < operand.single_value.n_elements; ++i) { + single_value.value_elements[pos + i] = + operand.single_value.value_elements[i]->clone(); + } + pos += operand.single_value.n_elements; + break; + case ANY_VALUE: + case ANY_OR_OMIT: + switch (operand.length_restriction_type) { + case NO_LENGTH_RESTRICTION: + // ? => { * } + single_value.value_elements[pos] = create_elem(); + single_value.value_elements[pos]->set_value(ANY_OR_OMIT); + ++pos; + break; + case RANGE_LENGTH_RESTRICTION: + case SINGLE_LENGTH_RESTRICTION: { + // ? length(N) or * length(N) => { ?, ?, ... ? } N times + int N = operand.length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + operand.length_restriction.single_length : + operand.length_restriction.range_length.min_length; + for (int i = 0; i < N; ++i) { + single_value.value_elements[pos + i] = create_elem(); + single_value.value_elements[pos + i]->set_value(ANY_VALUE); + } + pos += N; + break; } + } + default: + break; + } +} + +void Record_Of_Template::concat(int& pos, const Record_Of_Type& operand) +{ + // all errors should have already been caught by the + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + for (int i = 0; i < operand.val_ptr->n_elements; ++i) { + single_value.value_elements[pos + i] = create_elem(); + single_value.value_elements[pos + i]->copy_value(operand.get_at(i)); + } + pos += operand.val_ptr->n_elements; +} + +void Record_Of_Template::concat(int& pos) +{ + // this concatenates a template_sel to the result template; + // there is no need for a template_sel parameter, since the only template + // selection that can be concatenated is ANY_VALUE; + // the template selection has already been checked in the + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + single_value.value_elements[pos] = create_elem(); + single_value.value_elements[pos]->set_value(ANY_OR_OMIT); + ++pos; +} + void Record_Of_Template::set_size(int new_size) { if (new_size < 0) @@ -1650,6 +1782,129 @@ const Base_Template* Set_Of_Template::get_at(const INTEGER& index_value) const return get_at((int)index_value); } +int Set_Of_Template::get_length_for_concat(boolean& is_any_value) const +{ + switch (template_selection) { + case SPECIFIC_VALUE: + return single_value.n_elements; + case ANY_VALUE: + case ANY_OR_OMIT: + switch (length_restriction_type) { + case NO_LENGTH_RESTRICTION: + if (template_selection == ANY_VALUE) { + // ? => { * } + is_any_value = TRUE; + return 1; + } + TTCN_error("Operand of record of template concatenation is an " + "AnyValueOrNone (*) matching mechanism with no length restriction"); + case RANGE_LENGTH_RESTRICTION: + if (!length_restriction.range_length.max_length || + length_restriction.range_length.max_length != length_restriction.range_length.min_length) { + TTCN_error("Operand of record of template concatenation is an %s " + "matching mechanism with non-fixed length restriction", + template_selection == ANY_VALUE ? "AnyValue (?)" : "AnyValueOrNone (*)"); + } + // else fall through (range length restriction is allowed if the minimum + // and maximum value are the same) + case SINGLE_LENGTH_RESTRICTION: + // ? length(N) or * length(N) => { ?, ?, ... ? } N times + return length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + length_restriction.single_length : length_restriction.range_length.min_length; + } + default: + TTCN_error("Operand of record of template concatenation is an " + "uninitialized or unsupported template."); + } +} + +int Set_Of_Template::get_length_for_concat(const Record_Of_Type& operand) +{ + if (!operand.is_bound()) { + TTCN_error("Operand of record of template concatenation is an " + "unbound value."); + } + return operand.val_ptr->n_elements; +} + +int Set_Of_Template::get_length_for_concat(template_sel operand) +{ + if (operand == ANY_VALUE) { + // ? => { * } + return 1; + } + TTCN_error("Operand of record of template concatenation is an " + "uninitialized or unsupported template."); +} + +void Set_Of_Template::concat(int& pos, const Set_Of_Template& operand) +{ + // all errors should have already been caught by the operand's + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + switch (operand.template_selection) { + case SPECIFIC_VALUE: + for (int i = 0; i < operand.single_value.n_elements; ++i) { + single_value.value_elements[pos + i] = + operand.single_value.value_elements[i]->clone(); + } + pos += operand.single_value.n_elements; + break; + case ANY_VALUE: + case ANY_OR_OMIT: + switch (operand.length_restriction_type) { + case NO_LENGTH_RESTRICTION: + // ? => { * } + single_value.value_elements[pos] = create_elem(); + single_value.value_elements[pos]->set_value(ANY_OR_OMIT); + ++pos; + break; + case RANGE_LENGTH_RESTRICTION: + case SINGLE_LENGTH_RESTRICTION: { + // ? length(N) or * length(N) => { ?, ?, ... ? } N times + int N = operand.length_restriction_type == SINGLE_LENGTH_RESTRICTION ? + operand.length_restriction.single_length : + operand.length_restriction.range_length.min_length; + for (int i = 0; i < N; ++i) { + single_value.value_elements[pos + i] = create_elem(); + single_value.value_elements[pos + i]->set_value(ANY_VALUE); + } + pos += N; + break; } + } + default: + break; + } +} + +void Set_Of_Template::concat(int& pos, const Record_Of_Type& operand) +{ + // all errors should have already been caught by the + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + for (int i = 0; i < operand.val_ptr->n_elements; ++i) { + single_value.value_elements[pos + i] = create_elem(); + single_value.value_elements[pos + i]->copy_value(operand.get_at(i)); + } + pos += operand.val_ptr->n_elements; +} + +void Set_Of_Template::concat(int& pos) +{ + // this concatenates a template_sel to the result template; + // there is no need for a template_sel parameter, since the only template + // selection that can be concatenated is ANY_VALUE; + // the template selection has already been checked in the + // get_length_for_concat() call; + // the result template (this) should already be set to SPECIFIC_VALUE and + // single_value.value_elements should already be allocated + single_value.value_elements[pos] = create_elem(); + single_value.value_elements[pos]->set_value(ANY_OR_OMIT); + ++pos; +} + void Set_Of_Template::set_size(int new_size) { if (new_size < 0) diff --git a/core/Template.hh b/core/Template.hh index 88574c6416ce9db200fd16d1bc8ed222d17796c0..3fd498b74b18d69cfe00b2c26dd866c17c698a9b 100644 --- a/core/Template.hh +++ b/core/Template.hh @@ -36,6 +36,9 @@ class Text_Buf; class Module_Param; class Module_Param_Name; class Module_Param_Length_Restriction; +class OCTETSTRING_template; +class HEXSTRING_template; +class BITSTRING_template; enum template_sel { UNINITIALIZED_TEMPLATE = -1, @@ -158,6 +161,13 @@ class Restricted_Length_Template : public Base_Template , public RefdIndexInterface #endif { + friend OCTETSTRING_template operator+(template_sel left_template_sel, + const OCTETSTRING_template& right_template); + friend HEXSTRING_template operator+(template_sel left_template_sel, + const HEXSTRING_template& right_template); + friend BITSTRING_template operator+(template_sel left_template_sel, + const BITSTRING_template& right_template); + protected: enum length_restriction_type_t { NO_LENGTH_RESTRICTION = 0, @@ -207,6 +217,9 @@ public: boolean is_any_or_omit() const; }; +template_sel operator+(template_sel left_template_sel, + template_sel right_template_sel); + #ifndef TITAN_RUNTIME_2 class Record_Of_Template : public Restricted_Length_Template { @@ -293,6 +306,14 @@ protected: Base_Template* get_at(const INTEGER& index_value); const Base_Template* get_at(int index_value) const; const Base_Template* get_at(const INTEGER& index_value) const; + + int get_length_for_concat(boolean& is_any_value) const; + static int get_length_for_concat(const Record_Of_Type& operand); + static int get_length_for_concat(template_sel operand); + + void concat(int& pos, const Set_Of_Template& operand); + void concat(int& pos, const Record_Of_Type& operand); + void concat(int& pos); int size_of(boolean is_size) const; Set_Of_Template* get_list_item(int list_index); @@ -405,6 +426,14 @@ protected: Base_Template* get_at(const INTEGER& index_value); const Base_Template* get_at(int index_value) const; const Base_Template* get_at(const INTEGER& index_value) const; + + int get_length_for_concat(boolean& is_any_value) const; + static int get_length_for_concat(const Record_Of_Type& operand); + static int get_length_for_concat(template_sel operand); + + void concat(int& pos, const Record_Of_Template& operand); + void concat(int& pos, const Record_Of_Type& operand); + void concat(int& pos); int size_of(boolean is_size) const; Record_Of_Template* get_list_item(int list_index); diff --git a/core/Universal_charstring.cc b/core/Universal_charstring.cc index e16af4de17bc0087a51c64d9c86579cbe1e47fee..3da7ad767223ef0fd5b0ea2cc85449879c1be233 100644 --- a/core/Universal_charstring.cc +++ b/core/Universal_charstring.cc @@ -542,6 +542,16 @@ UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+ return ret_val; } +UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+( + const OPTIONAL<CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); +} + UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+ (const UNIVERSAL_CHARSTRING& other_value) const { @@ -643,6 +653,16 @@ UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+ } } +UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const UNIVERSAL_CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); +} + UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator<<= (int rotate_count) const { @@ -3351,6 +3371,16 @@ UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+ } } +UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+( + const OPTIONAL<CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); +} + UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+ (const UNIVERSAL_CHARSTRING& other_value) const { @@ -3440,6 +3470,16 @@ UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+ } } +UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const +{ + if (other_value.is_present()) { + return *this + (const UNIVERSAL_CHARSTRING&)other_value; + } + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); +} + const universal_char& UNIVERSAL_CHARSTRING_ELEMENT::get_uchar() const { if (str_val.charstring) @@ -3556,6 +3596,60 @@ UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value, } } +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING& right_value) +{ + if (left_value.is_present()) { + return (const UNIVERSAL_CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_ELEMENT& right_value) +{ + if (left_value.is_present()) { + return (const UNIVERSAL_CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING& right_value) +{ + if (left_value.is_present()) { + return (const UNIVERSAL_CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING_ELEMENT& right_value) +{ + if (left_value.is_present()) { + return (const UNIVERSAL_CHARSTRING&)left_value + right_value; + } + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); +} + +UNIVERSAL_CHARSTRING operator+(const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const OPTIONAL<CHARSTRING>& right_value) +{ + if (!left_value.is_present()) { + TTCN_error("Unbound or omitted left operand of universal charstring " + "concatenation."); + } + if (!right_value.is_present()) { + TTCN_error("Unbound or omitted right operand of universal charstring " + "concatenation."); + } + return (const UNIVERSAL_CHARSTRING&)left_value + (const CHARSTRING&)right_value; +} + boolean operator==(const char *string_value, const UNIVERSAL_CHARSTRING& other_value) { @@ -3983,6 +4077,183 @@ UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator= return *this; } +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const UNIVERSAL_CHARSTRING_template& other_value) const +{ + if (template_selection == SPECIFIC_VALUE && + other_value.template_selection == SPECIFIC_VALUE) { + return single_value + other_value.single_value; + } + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const UNIVERSAL_CHARSTRING& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + return single_value + other_value; + } + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const +{ + if (template_selection == SPECIFIC_VALUE) { + return single_value + other_value; + } + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + if (!other_value.is_present()) { + TTCN_error("Operand of universal charstring template concatenation is an " + "unbound or omitted record/set field."); + } + return single_value + (const UNIVERSAL_CHARSTRING&)other_value; +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const CHARSTRING& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return single_value + other_value; +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const CHARSTRING_ELEMENT& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return single_value + other_value; +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const OPTIONAL<CHARSTRING>& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + if (!other_value.is_present()) { + TTCN_error("Operand of universal charstring template concatenation is an " + "unbound or omitted record/set field."); + } + return single_value + (const CHARSTRING&)other_value; +} + +UNIVERSAL_CHARSTRING_template UNIVERSAL_CHARSTRING_template::operator+( + const CHARSTRING_template& other_value) const +{ + if (template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + if (other_value.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return single_value + other_value.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+(const UNIVERSAL_CHARSTRING& left_value, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + return left_value + right_template.single_value; + } + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& left_value, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (right_template.template_selection == SPECIFIC_VALUE) { + return left_value + right_template.single_value; + } + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); +} + +UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (!left_value.is_present()) { + TTCN_error("Operand of universal charstring template concatenation is an " + "unbound or omitted record/set field."); + } + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return (const UNIVERSAL_CHARSTRING&)left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING& left_value, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING_ELEMENT& left_value, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+(const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (!left_value.is_present()) { + TTCN_error("Operand of universal charstring template concatenation is an " + "unbound or omitted record/set field."); + } + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return (const CHARSTRING&)left_value + right_template.single_value; +} + +UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING_template& left_template, + const UNIVERSAL_CHARSTRING_template& right_template) +{ + if (left_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of charstring template concatenation is an " + "uninitialized or unsupported template."); + } + if (right_template.template_selection != SPECIFIC_VALUE) { + TTCN_error("Operand of universal charstring template concatenation is an " + "uninitialized or unsupported template."); + } + return left_template.single_value + right_template.single_value; +} + UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value) { if (template_selection != SPECIFIC_VALUE || is_ifpresent) diff --git a/core/Universal_charstring.hh b/core/Universal_charstring.hh index 50ded9ecdd20ef11eb9dbc6c97f5908128317ad9..5ac1955648a0b94b84bd4e9ddaf9fa23f475eb72 100644 --- a/core/Universal_charstring.hh +++ b/core/Universal_charstring.hh @@ -228,9 +228,12 @@ public: UNIVERSAL_CHARSTRING operator+(const char* other_value) const; UNIVERSAL_CHARSTRING operator+(const CHARSTRING& other_value) const; UNIVERSAL_CHARSTRING operator+(const CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& other_value) const; UNIVERSAL_CHARSTRING operator+(const UNIVERSAL_CHARSTRING& other_value) const; UNIVERSAL_CHARSTRING operator+(const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const; /** @} */ /** @name Rotation @@ -471,9 +474,12 @@ public: UNIVERSAL_CHARSTRING operator+(const char* other_value) const; UNIVERSAL_CHARSTRING operator+(const CHARSTRING& other_value) const; UNIVERSAL_CHARSTRING operator+(const CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING operator+(const OPTIONAL<CHARSTRING>& other_value) const; UNIVERSAL_CHARSTRING operator+(const UNIVERSAL_CHARSTRING& other_value) const; UNIVERSAL_CHARSTRING operator+(const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const; inline boolean is_bound() const { return bound_flag; } inline boolean is_present() const { return bound_flag; } @@ -512,6 +518,21 @@ extern UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value, const UNIVERSAL_CHARSTRING& other_value); extern UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value, const UNIVERSAL_CHARSTRING_ELEMENT& other_value); +extern UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING& right_value); +extern UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_ELEMENT& right_value); +extern UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING& right_value); +extern UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const CHARSTRING_ELEMENT& right_value); +extern UNIVERSAL_CHARSTRING operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const OPTIONAL<CHARSTRING>& right_value); extern boolean operator==(const char *string_value, const UNIVERSAL_CHARSTRING& other_value); @@ -540,6 +561,27 @@ struct unichar_decmatch_struct; class UNIVERSAL_CHARSTRING_template : public Restricted_Length_Template { private: + friend UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const CHARSTRING_ELEMENT& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); + friend UNIVERSAL_CHARSTRING_template operator+( + const CHARSTRING_template& left_template, + const UNIVERSAL_CHARSTRING_template& right_template); + UNIVERSAL_CHARSTRING single_value; CHARSTRING* pattern_string; union { @@ -600,6 +642,22 @@ public: (const CHARSTRING_template& other_value); UNIVERSAL_CHARSTRING_template& operator= (const UNIVERSAL_CHARSTRING_template& other_value); + + UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_template& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value) const; + UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const CHARSTRING_ELEMENT& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<CHARSTRING>& other_value) const; + UNIVERSAL_CHARSTRING_template operator+( + const CHARSTRING_template& other_value) const; UNIVERSAL_CHARSTRING_ELEMENT operator[](int index_value); UNIVERSAL_CHARSTRING_ELEMENT operator[](const INTEGER& index_value); @@ -653,6 +711,24 @@ public: const CHARSTRING& get_single_value() const; }; +extern UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+( + const UNIVERSAL_CHARSTRING_ELEMENT& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+( + const OPTIONAL<UNIVERSAL_CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING_ELEMENT& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+(const OPTIONAL<CHARSTRING>& left_value, + const UNIVERSAL_CHARSTRING_template& right_template); +extern UNIVERSAL_CHARSTRING_template operator+(const CHARSTRING_template& left_template, + const UNIVERSAL_CHARSTRING_template& right_template); + typedef UNIVERSAL_CHARSTRING BMPString; typedef UNIVERSAL_CHARSTRING UniversalString; typedef UNIVERSAL_CHARSTRING UTF8String; diff --git a/core/Vector.hh b/core/Vector.hh index a703025e9f51f154333871ece855a9efe86ae92d..585ab6ee8fe9ce604c383a48ea5da0a36ab500d7 100644 --- a/core/Vector.hh +++ b/core/Vector.hh @@ -62,6 +62,7 @@ public: boolean empty() const { return nof_elem == 0; } void reserve(size_t n); void shrink_to_fit(); + T* data_ptr() const { return data; } // Element access T& operator[](size_t idx); diff --git a/core/XER.hh b/core/XER.hh index e4838ab779c38d0665f4078009ee044541b5c653..5904edfbaae9f114d8aeef1af36fb98792ad363e 100644 --- a/core/XER.hh +++ b/core/XER.hh @@ -107,7 +107,8 @@ enum XER_flavor { enum XER_flavor2 { USE_NIL_PARENT_TAG = 1U << 0, // Content field has attribute that was read by parent - FROM_UNION_USETYPE = 1U << 1 // When the parent of a useUnion field is a union with useType + FROM_UNION_USETYPE = 1U << 1, // When the parent of a useUnion field is a union with useType + THIS_UNION = 1U << 2 // When the type is a union }; /** WHITESPACE actions. diff --git a/function_test/Semantic_Analyser/TTCN3_SA_5_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_5_TD.script index e920eafed12bda08b562f6689e35976d8bd4d9a4..067a72794de07d893c1bd687f3b4d083a5798147 100644 --- a/function_test/Semantic_Analyser/TTCN3_SA_5_TD.script +++ b/function_test/Semantic_Analyser/TTCN3_SA_5_TD.script @@ -3594,10 +3594,10 @@ template integer i1 := 1 & 2 } <END_MODULE> -<RESULT COUNT 2> -(?im)operand.+?should.+?be.+?string.+?value +<RESULT COUNT 1> +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`integer' <END_RESULT> -<RESULT COUNT 2> +<RESULT COUNT 1> (?is)\berror: <END_RESULT> <RESULT> @@ -3754,10 +3754,10 @@ template float f1 := 1.0 & 2E-1 } <END_MODULE> -<RESULT COUNT 2> -(?im)operand.+?should.+?be.+?string.+?value +<RESULT COUNT 1> +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`float' <END_RESULT> -<RESULT COUNT 2> +<RESULT COUNT 1> (?is)\berror: <END_RESULT> <RESULT> @@ -3963,10 +3963,10 @@ template boolean b1 := true & false } <END_MODULE> -<RESULT COUNT 2> -(?im)operand.+?should.+?be.+?string.+?value +<RESULT COUNT 1> +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`boolean' <END_RESULT> -<RESULT COUNT 2> +<RESULT COUNT 1> (?is)\berror: <END_RESULT> <RESULT> @@ -4715,13 +4715,10 @@ template rtype r3 := r1 & r2 } <END_MODULE> -<RESULT COUNT 2> -(?im)operand.+?should.+?be.+?string.+?value -<END_RESULT> -<RESULT COUNT 2> -(?im)reference.+?to.+?value.+?expected.+?instead.+?of.+?template +<RESULT COUNT 1> +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`@Temp.rtype' <END_RESULT> -<RESULT COUNT 4> +<RESULT COUNT 1> (?is)\berror: <END_RESULT> <RESULT> @@ -9209,7 +9206,7 @@ module ModuleA { } <END_MODULE> <RESULT IF_PASS COUNT 5> -(?im)integer.+?value.+?expected +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`integer' <END_RESULT> <RESULT COUNT 5> (?is)\berror: @@ -9334,7 +9331,7 @@ module ModuleA { } <END_MODULE> <RESULT IF_PASS COUNT 5> -(?im)integer.+?value.+?expected +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`integer' <END_RESULT> <RESULT COUNT 5> (?is)\berror: @@ -9565,7 +9562,7 @@ module ModuleA { } <END_MODULE> <RESULT IF_PASS COUNT 5> -(?im)integer.+?value.+?expected +(?im)template.+?concatenation.+?cannot.+?be.+?used.+?for.+?type.+?`integer' <END_RESULT> <RESULT COUNT 5> (?is)\berror: diff --git a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script index 32742e23ebbeabe05eb6788818f30fd3c13dd293..7ef1b30b58b27790511f4d9eb552e0fc62c06a51 100644 --- a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script +++ b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script @@ -5663,7 +5663,7 @@ module module1 const myu1 c_myu1 := char(0, 0, 1, 0) const myu2 c_myu2 := char(0, 0, 1, 0) & char(0, 0, 1, 0) template myu1 t_myu1 := char(0, 0, 1, 0) - template myu2 t_myu2 := char(0, 0, 1, 0) & char(0, 0, 1, 0) + template myu2 t_myu2 := char(0, 0, 1, 0) & char(0, 0, 1, 0) // type restrictions are currently not checked for concatenated templates template myu2 t_myu3 := t_myu1 template myu1 t_myu4 := (char(0, 0, 1, 0)) @@ -5672,7 +5672,7 @@ module module1 control { var template myu1 vt_myu1 := char(0, 0, 1, 0) - var template myu2 vt_myu2 := char(0, 0, 1, 0) & char(0, 0, 1, 0) + var template myu2 vt_myu2 := char(0, 0, 1, 0) & char(0, 0, 1, 0) // type restrictions are currently not checked for concatenated templates var template myu2 vt_myu3 := fu1() var myu1 v_myu1 := char(0, 0, 1, 0) var myu2 v_myu2 := char(0, 0, 1, 0) & char(0, 0, 1, 0) @@ -5683,7 +5683,7 @@ module module1 <RESULT COUNT 5> (?is)\berror: char\(0, 0, 1, 0\) is not a valid value for type `universal charstring' which has subtype \(char\(0, 0, 0, 0\),char\(0, 0, 0, 1\)\) <END_RESULT> -<RESULT COUNT 4> +<RESULT COUNT 2> (?is)\berror: char\(0, 0, 1, 0\) & char\(0, 0, 1, 0\) is not a valid value for type `universal charstring' which has subtype length\(1\) <END_RESULT> <RESULT COUNT 2> @@ -5692,7 +5692,7 @@ module module1 <RESULT COUNT 1> (?is)\berror: The subtype is an empty set <END_RESULT> -<RESULT COUNT 12> +<RESULT COUNT 10> (?is)\berror: <END_RESULT> <END_TC> diff --git a/function_test/Semantic_Analyser/pattern_ref/pattern_ref_SE.ttcn b/function_test/Semantic_Analyser/pattern_ref/pattern_ref_SE.ttcn index 024896ea08d1106ad084a0ab9da1ab766fd3ddb5..f77733d6b1569aae519c8185d1acffcd904efd7e 100644 --- a/function_test/Semantic_Analyser/pattern_ref/pattern_ref_SE.ttcn +++ b/function_test/Semantic_Analyser/pattern_ref/pattern_ref_SE.ttcn @@ -30,8 +30,9 @@ template universal charstring c_u4 := char(1,2,3,4) & char(5,6,7,8); template universal charstring tu := pattern "\N{c_u}"; template universal charstring tu2 := pattern "\N{c_u2}"; //^In template definition \`tu2\'// //^In universal string pattern// //^error\: The length of the universal charstring must be of length one\, when it is being referenced in a pattern with \\N\{ref\}// template universal charstring tu3 := pattern "\N{c_u3}"; -template universal charstring tu4 := pattern "\N{c_u4}"; //^In template definition \`tu4\'// //^In universal string pattern// //^error\: The length of the universal charstring must be of length one\, when it is being referenced in a pattern with \\N\{ref\}// - +/* template concatenations are currently not evaluated at compile-time +template universal charstring tu4 := pattern "\N{c_u4}"; /^In template definition \`tu4\'/ /^In universal string pattern/ /^error\: The length of the universal charstring must be of length one\, when it is being referenced in a pattern with \\N\{ref\}/ +*/ modulepar charstring c_m := "a"; modulepar charstring c_m2 := "aa"; diff --git a/function_test/Semantic_Analyser/xer/untagged_charenc_optional_SE.ttcn b/function_test/Semantic_Analyser/xer/untagged_charenc_optional_SE.ttcn index 58cf7495e8b648b60742ea5ac61f36e98c22a1ed..a28a1a98a06c34ed16020cc1f3e68ab8f513f44a 100644 --- a/function_test/Semantic_Analyser/xer/untagged_charenc_optional_SE.ttcn +++ b/function_test/Semantic_Analyser/xer/untagged_charenc_optional_SE.ttcn @@ -8,6 +8,7 @@ * Contributors: * Balasko, Jeno * Raduly, Csaba + * Szabo, Bence Janos * ******************************************************************************/ module untagged_charenc_optional_SE { //^In TTCN-3 module `untagged_charenc_optional_SE':// @@ -32,7 +33,21 @@ type record parent2 { unt trouble optional // no message } +type union uni { + integer i +} with { + variant "untagged"; +} + +// No top level untagged warning for unions and anytype +external function enc_uni(in uni u) return octetstring +with { extension "prototype(convert) encode(XER:XER_EXTENDED)" } + +external function enc_anytype(in anytype u) return octetstring +with { extension "prototype(convert) encode(XER:XER_EXTENDED)" } + } with { encode "XML"; +extension "anytype integer"; } diff --git a/regression_test/Makefile b/regression_test/Makefile index e5f72dcb23f2ddec3ce4c57017551b4e8a75203d..93760511ad77d9382387612f42aa73233b835eb0 100644 --- a/regression_test/Makefile +++ b/regression_test/Makefile @@ -48,7 +48,7 @@ XML ipv6 implicitOmit testcase_defparam transparent HQ16404 cfgFile \ all_from lazyEval tryCatch text2ttcn json ttcn2json profiler templateOmit \ customEncoding makefilegen uidChars checkstate hostid templateIstemplatekind \ selectUnion templateExclusiveRange any_from templatePatternRef indexWithRecofArray \ -connectMapOperTest fuzzy portTranslation +connectMapOperTest fuzzy portTranslation templateConcat ifdef DYN DIRS += loggerplugin junitlogger diff --git a/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp b/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp index a30132a8adf8a185d33930d213727c158e226cdb..ba4930d3d8175159bc1084016ff7d3a23ad6a9fa 100644 --- a/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp +++ b/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp @@ -9,6 +9,7 @@ * Balasko, Jeno * Baranyi, Botond * Raduly, Csaba + * Szabo, Bence Janos * ******************************************************************************/ module Untagged { @@ -696,7 +697,94 @@ testcase decode_ut_recof() runs on UTA CHECK_DECODE(exer_dec_recof, s_recof, r_recof, c_recof); } +// ------- untagged top level union +type integer MyInt +with { + variant "element"; +} + +type charstring MyChar +with { + variant "element"; +} + +type union UntaggedUnion { + MyInt i, + MyChar c +} with { + variant "untagged"; +} + +DECLARE_EXER_ENCODERS(UntaggedUnion, untunion); + +const UntaggedUnion c_untunion := { i := 44 }; + +const universal charstring s_untunion := "<i>44</i>\n\n"; + +testcase encode_ut_union() runs on UTA +{ + CHECK_METHOD(exer_enc_untunion, c_untunion, s_untunion); +} + +testcase decode_ut_union() runs on UTA +{ + CHECK_DECODE(exer_dec_untunion, s_untunion, UntaggedUnion, c_untunion); +} + +// ------- untagged top level record of union +type record of UntaggedUnion UntaggedRecofUnion +with { + variant "untagged"; +} + + +DECLARE_EXER_ENCODERS(UntaggedRecofUnion, untunionrecof); + +const UntaggedRecofUnion c_untunionrecof := { { i := 44 }, {c := "asdf"} }; + +const universal charstring s_untunionrecof := +"<UntaggedRecofUnion>\n"& +"\t<i>44</i>\n"& +"\t<c>asdf</c>\n"& +"</UntaggedRecofUnion>\n\n"; + +testcase encode_ut_union_recof() runs on UTA +{ + CHECK_METHOD(exer_enc_untunionrecof, c_untunionrecof, s_untunionrecof); +} + +testcase decode_ut_union_recof() runs on UTA +{ + CHECK_DECODE(exer_dec_untunionrecof, s_untunionrecof, UntaggedRecofUnion, c_untunionrecof); +} + +// ------- untagged top level union with nested untagged union + +type union UntaggedUnion2 { + UntaggedUnion unt, + MyInt i, + MyChar c +} with { + variant "untagged"; + variant (unt) "untagged"; +} + +DECLARE_EXER_ENCODERS(UntaggedUnion2, untunion2); + +const UntaggedUnion2 c_untunion2 := { unt := { i := 44 } }; + +const universal charstring s_untunion2 := "<i>44</i>\n\n"; + +testcase encode_ut_union2() runs on UTA +{ + CHECK_METHOD(exer_enc_untunion2, c_untunion2, s_untunion2); +} + +testcase decode_ut_union2() runs on UTA +{ + CHECK_DECODE(exer_dec_untunion2, s_untunion2, UntaggedUnion2, c_untunion2); +} /* * * * * * * * * * * Run it! * * * * * * * * * * */ @@ -736,6 +824,15 @@ control { execute(encode_ut_recof()); execute(decode_ut_recof()); + + execute(encode_ut_union()); + execute(decode_ut_union()); + + execute(encode_ut_union2()); + execute(decode_ut_union2()); + + execute(encode_ut_union_recof()); + execute(decode_ut_union_recof()); } } diff --git a/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp b/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp index 20aeabe378d8ee558f8fdfa740a9c64f640362c5..31e703b8ca56368303438a6e5efa97fafa0dd9a6 100644 --- a/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp +++ b/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp @@ -8,6 +8,7 @@ * Contributors: * Balasko, Jeno * Raduly, Csaba + * Szabo, Bence Janos * ******************************************************************************/ module Untagged1 { @@ -336,7 +337,7 @@ testcase tc_dec_ints() runs on Unt CHECK_DECODE(exer_dec_ints, estr_twoints, Ints, twoints); } -// Untagged at toplevel (ignored) for union +// not Untagged at toplevel for union // HM71472 type union Choice { @@ -345,7 +346,6 @@ type union Choice } with { variant "element" - variant "untagged" variant "namespace as 'foo:bar' prefix 'baz'"; } @@ -375,6 +375,83 @@ testcase tc_dec_choice() runs on Unt CHECK_DECODE(exer_dec_ch, estr_itg, Choice, itg); } +// Untagged at toplevel for union +// HM71472 +type union Choice2 +{ + integer answer, + charstring s +} +with { + variant "element" + variant "untagged" + // the namespace as variant will be not visible because it will be lost due to + // untagged + variant "namespace as 'foo:bar' prefix 'baz'"; +} + +DECLARE_XER_ENCODERS(Choice2, ch2); +DECLARE_EXER_ENCODERS(Choice2, ch2); + +const Choice2 itg2 := { answer := 42 }; +const universal charstring bstr_itg2 := +"<Choice2>\n" & +"\t<answer>42</answer>\n" & +"</Choice2>\n\n"; +const universal charstring estr_itg2 := +"<answer>42</answer>\n\n"; + + +testcase tc_enc_choice2() runs on Unt +{ + CHECK_METHOD(bxer_enc_ch2, itg2, bstr_itg2); + CHECK_METHOD(exer_enc_ch2, itg2, estr_itg2); +} + +testcase tc_dec_choice2() runs on Unt +{ + CHECK_DECODE(bxer_dec_ch2, bstr_itg2, Choice2, itg2); + CHECK_DECODE(exer_dec_ch2, estr_itg2, Choice2, itg2); +} + +// Untagged at toplevel for union +// HM71472 +type union Choice3 +{ + integer answer, + charstring s +} +with { + variant "element" + variant "untagged" + variant (answer) "namespace as 'foo:bar' prefix 'baz'"; + variant (answer) "element"; +} + +DECLARE_XER_ENCODERS(Choice3, ch3); +DECLARE_EXER_ENCODERS(Choice3, ch3); + +const Choice3 itg3 := { answer := 42 }; +const universal charstring bstr_itg3 := +"<Choice3>\n" & +"\t<answer>42</answer>\n" & +"</Choice3>\n\n"; +const universal charstring estr_itg3 := +"<baz:answer xmlns:baz='foo:bar'>42</baz:answer>\n\n"; + + +testcase tc_enc_choice3() runs on Unt +{ + CHECK_METHOD(bxer_enc_ch3, itg3, bstr_itg3); + CHECK_METHOD(exer_enc_ch3, itg3, estr_itg3); +} + +testcase tc_dec_choice3() runs on Unt +{ + CHECK_DECODE(bxer_dec_ch3, bstr_itg3, Choice3, itg3); + CHECK_DECODE(exer_dec_ch3, estr_itg3, Choice3, itg3); +} + // HM80553 type record AddRequest @@ -476,6 +553,12 @@ control { execute(tc_enc_choice()); execute(tc_dec_choice()); + execute(tc_enc_choice2()); + execute(tc_dec_choice2()); + + execute(tc_enc_choice3()); + execute(tc_dec_choice3()); + execute(tc_enc_widget()); execute(tc_dec_widget()); } diff --git a/regression_test/XML/TTCNandXML/AnytypeTest.ttcnpp b/regression_test/XML/TTCNandXML/AnytypeTest.ttcnpp new file mode 100644 index 0000000000000000000000000000000000000000..d6428860511caba7d83e5c2631667c8831f4062e --- /dev/null +++ b/regression_test/XML/TTCNandXML/AnytypeTest.ttcnpp @@ -0,0 +1,277 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ +module AnytypeTest { + +modulepar boolean Anytype_verbose := false; +#define verbose Anytype_verbose + +#include "../macros.ttcnin" + + + +type component SAP {} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +DECLARE_XER_ENCODERS(anytype, at); +DECLARE_EXER_ENCODERS(anytype, at); + +const anytype c_anytype := {charstring := "str"}; + +const universal charstring c_anytype_str_b := +"<anytype>\n\t<charstring>str</charstring>\n</anytype>\n\n"; + +const universal charstring c_anytype_str := +"<charstring>str</charstring>\n\n"; + +testcase enc_anytype() runs on SAP +{ + CHECK_METHOD(bxer_enc_at, c_anytype, c_anytype_str_b); + CHECK_METHOD(exer_enc_at, c_anytype, c_anytype_str); +} + +testcase dec_anytype() runs on SAP +{ + CHECK_DECODE(bxer_dec_at, c_anytype_str_b, anytype, c_anytype); + CHECK_DECODE(exer_dec_at, c_anytype_str, anytype, c_anytype); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +type anytype MyAnytype; + +DECLARE_XER_ENCODERS(MyAnytype, atal); +DECLARE_EXER_ENCODERS(MyAnytype, atal); + +const MyAnytype c_anytypeal := {charstring := "str"}; + +const universal charstring c_anytypeal_str_b := +"<MyAnytype>\n\t<charstring>str</charstring>\n</MyAnytype>\n\n"; + +const universal charstring c_anytypeal_str := +"<charstring>str</charstring>\n\n"; + +testcase enc_anytypealias() runs on SAP +{ + CHECK_METHOD(bxer_enc_atal, c_anytypeal, c_anytypeal_str_b); + CHECK_METHOD(exer_enc_atal, c_anytypeal, c_anytypeal_str); +} + +testcase dec_anytypealias() runs on SAP +{ + CHECK_DECODE(bxer_dec_atal, c_anytypeal_str_b, MyAnytype, c_anytypeal); + CHECK_DECODE(exer_dec_atal, c_anytypeal_str, MyAnytype, c_anytypeal); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +type record of anytype RoAnytype; + +DECLARE_XER_ENCODERS(RoAnytype, roat); +DECLARE_EXER_ENCODERS(RoAnytype, roat); + +const RoAnytype c_roanytype := { {charstring := "str"}, {integer := 4}, {octetstring := '012345'O}, {integer := 3}}; + +const universal charstring c_roanytype_str_b := +"<RoAnytype>\n"& +"\t<charstring>str</charstring>\n"& +"\t<integer>4</integer>\n"& +"\t<octetstring>012345</octetstring>\n"& +"\t<integer>3</integer>\n"& +"</RoAnytype>\n\n"; + +const universal charstring c_roanytype_str := +"<RoAnytype>\n"& +"\t<charstring>str</charstring>\n"& +"\t<integer>4</integer>\n"& +"\t<octetstring>012345</octetstring>\n"& +"\t<integer>3</integer>\n"& +"</RoAnytype>\n\n"; + +testcase enc_roanytype() runs on SAP +{ + CHECK_METHOD(bxer_enc_roat, c_roanytype, c_roanytype_str_b); + CHECK_METHOD(exer_enc_roat, c_roanytype, c_roanytype_str); +} + +testcase dec_roanytype() runs on SAP +{ + CHECK_DECODE(bxer_dec_roat, c_roanytype_str_b, RoAnytype, c_roanytype); + CHECK_DECODE(exer_dec_roat, c_roanytype_str, RoAnytype, c_roanytype); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +type record MyAnytypeRec { + anytype anytype_field, + MyAnytype anytype_field_alias, + anytype anytype_field2, + MyAnytype anytype_field_alias2, + RoAnytype anytype_field_ro, + charstring str +} + +DECLARE_XER_ENCODERS(MyAnytypeRec, recat); +DECLARE_EXER_ENCODERS(MyAnytypeRec, recat); + +const MyAnytypeRec c_myanytyperec := +{anytype_field := {charstring := "abc"}, +anytype_field_alias := {charstring := "def"}, +anytype_field2 := {charstring := "abcdef"}, +anytype_field_alias2 := {charstring := "defghi"}, +anytype_field_ro := { {charstring := "ttt"}, {integer := 4}}, +str := "ghi"}; + +const universal charstring c_myanytyperec_str_b := +"<MyAnytypeRec>\n"& +"\t<anytype_field>\n"& +"\t\t<charstring>abc</charstring>\n"& +"\t</anytype_field>\n"& +"\t<anytype_field_alias>\n"& +"\t\t<charstring>def</charstring>\n"& +"\t</anytype_field_alias>\n"& +"\t<anytype_field2>\n"& +"\t\t<charstring>abcdef</charstring>\n"& +"\t</anytype_field2>\n"& +"\t<anytype_field_alias2>\n"& +"\t\t<charstring>defghi</charstring>\n"& +"\t</anytype_field_alias2>\n"& +"\t<anytype_field_ro>\n"& +"\t\t<charstring>ttt</charstring>\n"& +"\t\t<integer>4</integer>\n"& +"\t</anytype_field_ro>\n"& +"\t<str>ghi</str>\n"& +"</MyAnytypeRec>\n\n"; + +const universal charstring c_myanytyperec_str := +"<MyAnytypeRec>\n"& +"\t<charstring>abc</charstring>\n"& +"\t<charstring>def</charstring>\n"& +"\t<charstring>abcdef</charstring>\n"& +"\t<charstring>defghi</charstring>\n"& +"\t<anytype_field_ro>\n"& +"\t\t<charstring>ttt</charstring>\n"& +"\t\t<integer>4</integer>\n"& +"\t</anytype_field_ro>\n"& +"\t<str>ghi</str>\n"& +"</MyAnytypeRec>\n\n"; + +testcase enc_myanytyperec() runs on SAP +{ + CHECK_METHOD(bxer_enc_recat, c_myanytyperec, c_myanytyperec_str_b); + CHECK_METHOD(exer_enc_recat, c_myanytyperec, c_myanytyperec_str); +} + +testcase dec_myanytyperec() runs on SAP +{ + CHECK_DECODE(bxer_dec_recat, c_myanytyperec_str_b, MyAnytypeRec, c_myanytyperec); + CHECK_DECODE(exer_dec_recat, c_myanytyperec_str, MyAnytypeRec, c_myanytyperec); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + +type record of anytype AnyTypeRo2 +with { + variant "untagged"; +} + +type record MyAnytypeRec2 { + AnyTypeRo2 anytype_field_ro +} + + +DECLARE_XER_ENCODERS(MyAnytypeRec2, recat2); +DECLARE_EXER_ENCODERS(MyAnytypeRec2, recat2); + +const MyAnytypeRec2 c_myanytyperec2 := {anytype_field_ro := {{charstring := "gdf"}, {integer := 44}}}; + +const universal charstring c_myanytyperec2_str_b := +"<MyAnytypeRec2>\n"& +"\t<anytype_field_ro>\n"& +"\t\t<charstring>gdf</charstring>\n"& +"\t\t<integer>44</integer>\n"& +"\t</anytype_field_ro>"& +"\n</MyAnytypeRec2>\n\n"; + +const universal charstring c_myanytyperec2_str := +"<MyAnytypeRec2>\n"& +"\t<charstring>gdf</charstring>\n"& +"\t<integer>44</integer>\n"& +"</MyAnytypeRec2>\n\n"; + +testcase tc_enc_anytype_ro_untagged() runs on SAP { + CHECK_METHOD(bxer_enc_recat2, c_myanytyperec2, c_myanytyperec2_str_b); + CHECK_METHOD(exer_enc_recat2, c_myanytyperec2, c_myanytyperec2_str); +} + +testcase tc_dec_anytype_ro_untagged() runs on SAP +{ + CHECK_DECODE(bxer_dec_recat2, c_myanytyperec2_str_b, MyAnytypeRec2, c_myanytyperec2); + CHECK_DECODE(exer_dec_recat2, c_myanytyperec2_str, MyAnytypeRec2, c_myanytyperec2); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +type boolean MyBool +with { + variant "defaultForEmpty as 'true'"; + variant "XSD:boolean"; +} + +type record DFERecAnyType { + anytype at +} + +DECLARE_XER_ENCODERS(DFERecAnyType, dferec); +DECLARE_EXER_ENCODERS(DFERecAnyType, dferec); + +const DFERecAnyType c_dferec := {at := {MyBool := true}}; + +const universal charstring c_dferec_str := +"<DFERecAnyType>\n"& +"\t<MyBool/>\n"& +"</DFERecAnyType>\n\n"; + +testcase tc_dec_anytype_DFE() runs on SAP { + CHECK_DECODE(exer_dec_dferec, c_dferec_str, DFERecAnyType, c_dferec); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +control { + execute(enc_anytype()); + execute(dec_anytype()); + + execute(enc_anytypealias()); + execute(dec_anytypealias()); + + execute(enc_roanytype()); + execute(dec_roanytype()); + + execute(enc_myanytyperec()); + execute(dec_myanytyperec()); + + execute(tc_enc_anytype_ro_untagged()); + execute(tc_dec_anytype_ro_untagged()); + + execute(tc_dec_anytype_DFE()); +} + + + +} +with { + encode "XML" + variant "controlNamespace 'http://www.w3.org/2001/XMLSchema-instance' prefix 'xsi'"; + extension "anytype integer, MyBool, charstring, octetstring"} + diff --git a/regression_test/XML/TTCNandXML/config.cfg b/regression_test/XML/TTCNandXML/config.cfg index 5265c71391cdfe678a17131090fdee1d989cb47a..eac8038352baae35c0bf58b83565b259a285964b 100644 --- a/regression_test/XML/TTCNandXML/config.cfg +++ b/regression_test/XML/TTCNandXML/config.cfg @@ -8,6 +8,7 @@ # Contributors: # Balasko, Jeno # Raduly, Csaba +# Szabo, Bence Janos # ############################################################################### [EXECUTE] @@ -30,6 +31,7 @@ DFEAttribTest Marx Regressions FractionDigitsTest +AnytypeTest [LOGGING] FileMask := LOG_ALL | USER | DEBUG_ENCDEC diff --git a/regression_test/predefFunction/length_of_SW.ttcn b/regression_test/predefFunction/length_of_SW.ttcn index 974f9fa5ab86ab59b9c20522447464e9c10e8bb4..adcc3a8b4c9bf90f21a46cee665448d9974f1cfe 100644 --- a/regression_test/predefFunction/length_of_SW.ttcn +++ b/regression_test/predefFunction/length_of_SW.ttcn @@ -27,12 +27,13 @@ const integer lofbi4 := lengthof(lofb1 & lofb1) const integer lofbi5 := lengthof(substr(lofb1,0,lengthof(lofb1))) testcase lengthof_bitstr() runs on PDTestComponent{ //In testcase definition// - + /* some of these tests are temporarily disabled, because template concatenation is not evaluated yet at compile-time if ((lofbi == 2*lengthof(lofb)) and (lofbi == lengthof(lofb & lofb))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofbi1 == lengthof(lofb)) and (lofbi1 == lengthof(substr(lofb,0,lengthof(lofb))))) {setverdict(pass);} @@ -43,16 +44,17 @@ testcase lengthof_bitstr() runs on PDTestComponent{ //In testcase definition// {setverdict(pass);} else {setverdict(fail);} //^In else statement// \ //^warning\: Control never reaches this code because of previous effective condition\(s\)// - if ((lofbi3 == 10) + /*if ((lofbi3 == 10) and (lofbi3 == lengthof(lofb & lofb1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if ((lofbi4 == 0) and (lofbi4 == lengthof(lofb1 & lofb1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofbi5 == 0) and (lofbi5 == lengthof(substr(lofb1,0,lengthof(lofb1))))) {setverdict(pass);} @@ -73,12 +75,13 @@ const integer lofhi4 := lengthof(lofh1 & lofh1) const integer lofhi5 := lengthof(substr(lofh1,0,lengthof(lofh1))) testcase lengthof_hexstr() runs on PDTestComponent{ //In testcase definition// - + /* some of these tests are temporarily disabled, because template concatenation is not evaluated yet at compile-time if ((lofhi == 2*lengthof(lofh)) and (lofhi == lengthof(lofh & lofh))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofhi1 == lengthof(lofh)) and (lofhi1 == lengthof(substr(lofh,0,lengthof(lofh))))) {setverdict(pass);} @@ -89,16 +92,17 @@ testcase lengthof_hexstr() runs on PDTestComponent{ //In testcase definition// {setverdict(pass);} else {setverdict(fail);} //^In else statement// \ //^warning\: Control never reaches this code because of previous effective condition\(s\)// - if ((lofhi3 == 10) + /*if ((lofhi3 == 10) and (lofhi3 == lengthof(lofh & lofh1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if ((lofhi4 == 0) and (lofhi4 == lengthof(lofh1 & lofh1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofhi5 == 0) and (lofhi5 == lengthof(substr(lofh1,0,lengthof(lofh1))))) {setverdict(pass);} @@ -119,12 +123,13 @@ const integer lofoi4 := lengthof(lofo1 & lofo1) const integer lofoi5 := lengthof(substr(lofo1,0,lengthof(lofo1))) testcase lengthof_octetstr() runs on PDTestComponent{ //In testcase definition// - + /* some of these tests are temporarily disabled, because template concatenation is not evaluated yet at compile-time if ((lofoi == 2*lengthof(lofo)) and (lofoi == lengthof(lofo & lofo))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofoi1 == lengthof(lofo)) and (lofoi1 == lengthof(substr(lofo,0,lengthof(lofo))))) {setverdict(pass);} @@ -135,16 +140,17 @@ testcase lengthof_octetstr() runs on PDTestComponent{ //In testcase definition// {setverdict(pass);} else {setverdict(fail);} //^In else statement// \ //^warning\: Control never reaches this code because of previous effective condition\(s\)// - if ((lofoi3 == 10) + /*if ((lofoi3 == 10) and (lofoi3 == lengthof(lofo & lofo1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if ((lofoi4 == 0) and (lofoi4 == lengthof(lofo1 & lofo1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofoi5 == 0) and (lofoi5 == lengthof(substr(lofo1,0,lengthof(lofo1))))) {setverdict(pass);} @@ -166,12 +172,13 @@ const integer lofci4 := lengthof(lofc1 & lofc1) const integer lofci5 := lengthof(substr(lofc1,0,lengthof(lofc1))) testcase lengthof_charstr() runs on PDTestComponent{ //In testcase definition// - + /* some of these tests are temporarily disabled, because template concatenation is not evaluated yet at compile-time if ((lofci == 2*lengthof(lofc)) and (lofci == lengthof(lofc & lofc))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofci1 == lengthof(lofc)) and (lofci1 == lengthof(substr(lofc,0,lengthof(lofc))))) {setverdict(pass);} @@ -182,16 +189,17 @@ testcase lengthof_charstr() runs on PDTestComponent{ //In testcase definition// {setverdict(pass);} else {setverdict(fail);} //^In else statement// \ //^warning\: Control never reaches this code because of previous effective condition\(s\)// - if ((lofci3 == 10) + /*if ((lofci3 == 10) and (lofci3 == lengthof(lofc & lofc1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if ((lofci4 == 0) and (lofci4 == lengthof(lofc1 & lofc1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofci5 == 0) and (lofci5 == lengthof(substr(lofc1,0,lengthof(lofc1))))) {setverdict(pass);} @@ -213,12 +221,13 @@ const integer lofuci4 := lengthof(lofuc1 & lofuc1) const integer lofuci5 := lengthof(substr(lofuc1,0,lengthof(lofuc1))) testcase lengthof_ucharstr() runs on PDTestComponent{ //In testcase definition// - + /* some of these tests are temporarily disabled, because template concatenation is not evaluated yet at compile-time if ((lofuci == 2*lengthof(lofuc)) and (lofuci == lengthof(lofuc & lofuc))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofuci1 == lengthof(lofuc)) and (lofuci1 == lengthof(substr(lofuc,0,lengthof(lofuc))))) {setverdict(pass);} @@ -229,16 +238,17 @@ testcase lengthof_ucharstr() runs on PDTestComponent{ //In testcase definition// {setverdict(pass);} else {setverdict(fail);} //^In else statement// \ //^warning\: Control never reaches this code because of previous effective condition\(s\)// - if ((lofuci3 == 10) + /*if ((lofuci3 == 10) and (lofuci3 == lengthof(lofuc & lofuc1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if ((lofuci4 == 0) and (lofuci4 == lengthof(lofuc1 & lofuc1))) {setverdict(pass);} - else {setverdict(fail);} //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else {setverdict(fail);} /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + */ if ((lofuci5 == 0) and (lofuci5 == lengthof(substr(lofuc1,0,lengthof(lofuc1))))) {setverdict(pass);} diff --git a/regression_test/predefFunction/replacer_SW.ttcn b/regression_test/predefFunction/replacer_SW.ttcn index c610c185c30e4e765e67835a54088ed50f4fb67e..a11a704ca0fa42de77f558e34ad8a18bc50bb968 100644 --- a/regression_test/predefFunction/replacer_SW.ttcn +++ b/regression_test/predefFunction/replacer_SW.ttcn @@ -120,39 +120,40 @@ const universal charstring us_4 := replace(char(0, 0, 0, 77) & "y name is JJ", b const universal charstring us_5 := replace(char(0, 0, 0, 77) & "y name is JJ", 13, 0, char(0, 0, 0, 120) & "x") // returns "My name is JJxx" const universal charstring us_6 := replace(us_0, 13, a, char(0, 0, 0, 120) & "x") // returns "My name is JJxx" -testcase replace_ucharstr() runs on PDTestComponent { //In testcase definition// +/* these tests are temporarily disabled, because template concatenation is not evaluated yet at compile-time +testcase replace_ucharstr() runs on PDTestComponent { /In testcase definition/ if (us_1 == char(0, 0, 0, 77) & "y name is xxJ") { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if (us_2 == char(0, 0, 0, 77) & "y name is xxJJ") { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if (us_3 == char(0, 0, 0, 77) & "yxame is JJ") { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// - if (us_4 == char(0, 0, 0, 77) & "yxame is JJ") { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ + if (us_4 == char(0, 0, 0, 7) & "yxame is JJ") { setverdict(pass) } + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if (us_3 == us_4) { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if (us_5 == char(0, 0, 0, 77) & "y name is JJxx") { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if (us_6 == char(0, 0, 0, 77) & "y name is JJxx") { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ if (us_5 == us_6) { setverdict(pass) } - else { setverdict(fail) } //^In else statement// \ - //^warning\: Control never reaches this code because of previous effective condition\(s\)// -} + else { setverdict(fail) } /^In else statement/ \ + /^warning\: Control never reaches this code because of previous effective condition\(s\)/ +}*/ control { execute (replace_bitstr()); execute (replace_hexstr()); execute (replace_octetstr()); execute (replace_charstr()); - execute (replace_ucharstr()); + //execute (replace_ucharstr()); } } diff --git a/regression_test/templateConcat/Makefile b/regression_test/templateConcat/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..aff3b4f3286d726a456cab63facc3ff5573ca195 --- /dev/null +++ b/regression_test/templateConcat/Makefile @@ -0,0 +1,68 @@ +############################################################################## +# 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 +# +############################################################################## +TOPDIR := .. +include $(TOPDIR)/Makefile.regression + +.SUFFIXES: .ttcn .asn .hh +.PHONY: all clean dep run + +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +TTCN3_MODULES = Types.ttcn TemplateConcatOct.ttcn TemplateConcatHex.ttcn TemplateConcatBit.ttcn TemplateConcatChar.ttcn \ +TemplateConcatUnichar.ttcn TemplateConcatMixed.ttcn TemplateConcatRecof.ttcn TemplateConcatSetof.ttcn + +ASN1_MODULES = + +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef CODE_SPLIT +GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc _seqof.cc _setof.cc _union.cc)) +else ifdef SPLIT_TO_SLICES +POSTFIXES := $(foreach file, $(SPLIT_TO_SLICES), $(addsuffix $(file), _part_)) +POSTFIXES := $(foreach file, $(POSTFIXES), $(addprefix $(file), .cc)) +GENERATED_SOURCES2 := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), $(POSTFIXES))) +GENERATED_SOURCES += $(GENERATED_SOURCES2) +endif + +USER_SOURCES = + +OBJECTS = $(GENERATED_SOURCES:.cc=.o) $(USER_SOURCES:.cc=.o) + +TARGET = templateConcat$(EXESUFFIX) + +all: $(TARGET) + +$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS) + +$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile + @if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi + +compile: $(TTCN3_MODULES) $(ASN1_MODULES) + $(filter-out -Nold -E, $(TTCN3_COMPILER)) $(COMPILER_FLAGS) $^ + touch compile + +clean distclean: + -rm -rf $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) *.log Makefile.bak compile logs + +dep: $(GENERATED_SOURCES) + makedepend $(CPPFLAGS) $(GENERATED_SOURCES) + +run: $(TARGET) config.cfg + ./$^ + +.NOTPARALLEL: + +ifdef SRCDIR +$(foreach src, $(USER_SOURCES), $(eval vpath $(src) $(ABS_SRC))) +endif diff --git a/regression_test/templateConcat/TemplateConcatBit.ttcn b/regression_test/templateConcat/TemplateConcatBit.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..629bbac4f923fc07050eed537c26e1709a3e792e --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatBit.ttcn @@ -0,0 +1,353 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 Ericsson Telecom 10 + * All rights reserved. This program and the accompanying materials + * are made avail10le under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is avail10le at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Baranyi, Botond + * + ******************************************************************************/ + +// This module contains tests for concatenating bitstring templates +module TemplateConcatBit { + +import from Types all; + +const bitstring c_bit := '1011'B; + +template bitstring t_bit := ? length(2..2); + +template bitstring t_bit1 := '1011'B & ? length (2) & '01'B; +template bitstring t_bit1_exp := '1011??01'B; + +template bitstring t_bit2 := '1011'B & '01'B & ? & ? length(1) & '01'B; +template bitstring t_bit2_exp := '101101*?01'B; + +template bitstring t_bit3 := ('1011'B & ? length(2..2)) length(6); +template bitstring t_bit3_exp := '1011??'B length(6); + +template bitstring t_bit4 := c_bit & ? length (2) & '01'B; +template bitstring t_bit4_exp := '1011??01'B; + +template bitstring t_bit5 := ('1011'B & t_bit) length(6); +template bitstring t_bit5_exp := '1011??'B length(6); + +template bitstring t_bit6 := '1011'B & ?; +template bitstring t_bit6_exp := '1011*'B; + +template bitstring t_bit7 := ? & '01'B; +template bitstring t_bit7_exp := '*01'B; + +template bitstring t_bit8 := '1011'B & ? & '01'B; +template bitstring t_bit8_exp := '1011*01'B; + +template bitstring t_bit9 := ? & ?; +template bitstring t_bit9_exp := ?; + +template bitstring t_bit10 := ? & ? & '01'B; +template bitstring t_bit10_exp := '*01'B; + +template bitstring t_bit11 := '1011'B & '01'B & ? & ? & ? length(1) & '01'B; +template bitstring t_bit11_exp := '101101*?01'B; + +testcase tc_bit_t_w_literals() runs on CT { + if (log2str(t_bit1) != log2str(t_bit1_exp)) { + setverdict(fail, "Expected: ", t_bit1_exp, ", got: ", t_bit1); + } + else if (log2str(t_bit2) != log2str(t_bit2_exp)) { + setverdict(fail, "Expected: ", t_bit2_exp, ", got: ", t_bit2); + } + else if (log2str(t_bit3) != log2str(t_bit3_exp)) { + setverdict(fail, "Expected: ", t_bit3_exp, ", got: ", t_bit3); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_t_w_refs() runs on CT { + if (log2str(t_bit4) != log2str(t_bit4_exp)) { + setverdict(fail, "Expected: ", t_bit4_exp, ", got: ", t_bit4); + } + else if (log2str(t_bit5) != log2str(t_bit5_exp)) { + setverdict(fail, "Expected: ", t_bit5_exp, ", got: ", t_bit5); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_t_w_any_value() runs on CT { + if (log2str(t_bit6) != log2str(t_bit6_exp)) { + setverdict(fail, "Expected: ", t_bit6_exp, ", got: ", t_bit6); + } + else if (log2str(t_bit7) != log2str(t_bit7_exp)) { + setverdict(fail, "Expected: ", t_bit7_exp, ", got: ", t_bit7); + } + else if (log2str(t_bit8) != log2str(t_bit8_exp)) { + setverdict(fail, "Expected: ", t_bit8_exp, ", got: ", t_bit8); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_t_dbl_any_value() runs on CT { + if (log2str(t_bit9) != log2str(t_bit9_exp)) { + setverdict(fail, "Expected: ", t_bit9_exp, ", got: ", t_bit9); + } + else if (log2str(t_bit10) != log2str(t_bit10_exp)) { + setverdict(fail, "Expected: ", t_bit10_exp, ", got: ", t_bit10); + } + else if (log2str(t_bit11) != log2str(t_bit11_exp)) { + setverdict(fail, "Expected: ", t_bit11_exp, ", got: ", t_bit11); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_w_literals() runs on CT { + var template bitstring vt_bit1 := '1011'B & ? length (2) & '01'B; + var template bitstring vt_bit1_exp := '1011??01'B; + + var template bitstring vt_bit2 := '1011'B & '01'B & ? & ? length(1) & '01'B; + var template bitstring vt_bit2_exp := '101101*?01'B; + + var template bitstring vt_bit3 := ('1011'B & ? length(2..2)) length(6); + var template bitstring vt_bit3_exp := '1011??'B length(6); + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_w_refs() runs on CT { + var integer v_len := 3; + var bitstring v_bit := '01'B; + var template bitstring vt_bit := ?; + + var template bitstring vt_bit1 := c_bit & ? length (2) & '01'B; + var template bitstring vt_bit1_exp := '1011??01'B; + + var template bitstring vt_bit2 := '1011'B & v_bit & vt_bit & ? length(v_len) & v_bit; + var template bitstring vt_bit2_exp := '101101*???01'B; + + var template bitstring vt_bit3 := ('1011'B & t_bit) length(6); + var template bitstring vt_bit3_exp := '1011??'B length(6); + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_w_any_value() runs on CT { + var template bitstring vt_bit1 := '1011'B & ?; + var template bitstring vt_bit1_exp := '1011*'B; + + var template bitstring vt_bit2 := ? & '01'B; + var template bitstring vt_bit2_exp := '*01'B; + + var template bitstring vt_bit3 := '1011'B & ? & '01'B; + var template bitstring vt_bit3_exp := '1011*01'B; + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_dbl_any_value() runs on CT { + var integer v_len := 3; + + var template bitstring vt_bit1 := ? & ?; + var template bitstring vt_bit1_exp := ?; + + var template bitstring vt_bit2 := ? & ? & '01'B; + var template bitstring vt_bit2_exp := '*01'B; + + var template bitstring vt_bit3 := '1011'B & '01'B & ? & ? & ? length(v_len - 1) & '01'B; + var template bitstring vt_bit3_exp := '101101*??01'B; + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_dbl_any_value_w_refs() runs on CT { + var template bitstring vt_bit := ?; + + var template bitstring vt_bit1 := vt_bit & ?; + var template bitstring vt_bit1_exp := ?; + + var template bitstring vt_bit2 := ? & vt_bit; + var template bitstring vt_bit2_exp := ?; + + var template bitstring vt_bit3 := vt_bit & vt_bit; + var template bitstring vt_bit3_exp := ?; + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "1st test. Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "2nd test. Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "3rd test. Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_w_str_elem() runs on CT { + var bitstring v_bit := '01'B; + var bitstring v_bit2 := '1011'B; + + var template bitstring vt_bit1 := v_bit[0] & ?; + var template bitstring vt_bit1_exp := '0*'B; + + var template bitstring vt_bit2 := '10'B & ? length(3) & v_bit2[2]; + var template bitstring vt_bit2_exp := '10???1'B; + + var template bitstring vt_bit3 := ? & v_bit2[0]; + var template bitstring vt_bit3_exp := '*1'B; + + var template bitstring vt_bit4 := v_bit2[2] & vt_bit1_exp; + var template bitstring vt_bit4_exp := '10*'B; + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else if (log2str(vt_bit4) != log2str(vt_bit4_exp)) { + setverdict(fail, "Expected: ", vt_bit4_exp, ", got: ", vt_bit4); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, omit, '0110'B, omit, omit, omit, omit }; + + var template bitstring vt_bit1 := '01'B & ? length(1) & v_rec.bs; + var template bitstring vt_bit1_exp := '01?0110'B; + + var template bitstring vt_bit2 := v_rec.bs & vt_bit1_exp; + var template bitstring vt_bit2_exp := '011001?0110'B; + + var template bitstring vt_bit3 := ? & v_rec.bs; + var template bitstring vt_bit3_exp := '*0110'B; + + var template bitstring vt_bit4 := v_rec.bs & ?; + var template bitstring vt_bit4_exp := '0110*'B; + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else if (log2str(vt_bit4) != log2str(vt_bit4_exp)) { + setverdict(fail, "Expected: ", vt_bit4_exp, ", got: ", vt_bit4); + } + else { + setverdict(pass); + } +} + +testcase tc_bit_vt_extra() runs on CT { + var bitstring v_bit2 := '1011'B; + var Rec v_rec := { omit, omit, '0110'B, omit, omit, omit, omit }; + + var template bitstring vt_bit1 := v_rec.bs & '11'B; + var template bitstring vt_bit1_exp := '011011'B; + + var template bitstring vt_bit2 := '11'B & v_rec.bs & '11'B; + var template bitstring vt_bit2_exp := '11011011'B; + + var template bitstring vt_bit3 := v_bit2[3] & v_rec.bs; + var template bitstring vt_bit3_exp := '10110'B; + + var template bitstring vt_bit4 := v_rec.bs & v_bit2[3]; + var template bitstring vt_bit4_exp := '01101'B; + + if (log2str(vt_bit1) != log2str(vt_bit1_exp)) { + setverdict(fail, "Expected: ", vt_bit1_exp, ", got: ", vt_bit1); + } + else if (log2str(vt_bit2) != log2str(vt_bit2_exp)) { + setverdict(fail, "Expected: ", vt_bit2_exp, ", got: ", vt_bit2); + } + else if (log2str(vt_bit3) != log2str(vt_bit3_exp)) { + setverdict(fail, "Expected: ", vt_bit3_exp, ", got: ", vt_bit3); + } + else if (log2str(vt_bit4) != log2str(vt_bit4_exp)) { + setverdict(fail, "Expected: ", vt_bit4_exp, ", got: ", vt_bit4); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_bit_t_w_literals()); + execute(tc_bit_t_w_refs()); + execute(tc_bit_t_w_any_value()); + execute(tc_bit_t_dbl_any_value()); + execute(tc_bit_vt_w_literals()); + execute(tc_bit_vt_w_refs()); + execute(tc_bit_vt_w_any_value()); + execute(tc_bit_vt_dbl_any_value()); + execute(tc_bit_vt_dbl_any_value_w_refs()); + execute(tc_bit_vt_w_str_elem()); + execute(tc_bit_vt_w_opt_fields()); + execute(tc_bit_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatChar.ttcn b/regression_test/templateConcat/TemplateConcatChar.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..0fd97d3568caaf7155c3f56126d13dcc13fd2909 --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatChar.ttcn @@ -0,0 +1,176 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating charstring templates +module TemplateConcatChar { + +import from Types all; + +const charstring c_char := "abc"; + +template charstring t_char := "def"; + +template charstring t_char1 := "abc" & "def"; +template charstring t_char1_exp := "abcdef"; + +template charstring t_char2 := c_char & "def"; +template charstring t_char2_exp := "abcdef"; + +template charstring t_char3 := t_char & "ghi"; +template charstring t_char3_exp := "defghi"; + +template charstring t_char4 := "xx" & t_char & "xx"; +template charstring t_char4_exp := "xxdefxx"; + + +testcase tc_char_t_values() runs on CT { + if (log2str(t_char1) != log2str(t_char1_exp)) { + setverdict(fail, "Expected: ", t_char1_exp, ", got: ", t_char1); + } + else if (log2str(t_char2) != log2str(t_char2_exp)) { + setverdict(fail, "Expected: ", t_char2_exp, ", got: ", t_char2); + } + else if (log2str(t_char3) != log2str(t_char3_exp)) { + setverdict(fail, "Expected: ", t_char3_exp, ", got: ", t_char3); + } + else if (log2str(t_char4) != log2str(t_char4_exp)) { + setverdict(fail, "Expected: ", t_char4_exp, ", got: ", t_char4); + } + else { + setverdict(pass); + } +} + +testcase tc_char_vt_values() runs on CT { + var template charstring vt_char1 := "abc" & "def"; + var template charstring vt_char1_exp := "abcdef"; + + var template charstring vt_char2 := c_char & "def"; + var template charstring vt_char2_exp := "abcdef"; + + var template charstring vt_char3 := t_char & "ghi"; + var template charstring vt_char3_exp := "defghi"; + + var template charstring vt_char4 := "xx" & t_char & "xx"; + var template charstring vt_char4_exp := "xxdefxx"; + + if (log2str(vt_char1) != log2str(vt_char1_exp)) { + setverdict(fail, "Expected: ", vt_char1_exp, ", got: ", vt_char1); + } + else if (log2str(vt_char2) != log2str(vt_char2_exp)) { + setverdict(fail, "Expected: ", vt_char2_exp, ", got: ", vt_char2); + } + else if (log2str(vt_char3) != log2str(vt_char3_exp)) { + setverdict(fail, "Expected: ", vt_char3_exp, ", got: ", vt_char3); + } + else if (log2str(vt_char4) != log2str(vt_char4_exp)) { + setverdict(fail, "Expected: ", vt_char4_exp, ", got: ", vt_char4); + } + else { + setverdict(pass); + } +} + +testcase tc_char_vt_w_str_elem() runs on CT { + var charstring v_char := "xyz"; + + var template charstring vt_char1 := t_char & v_char[2]; + var template charstring vt_char1_exp := "defz"; + + var template charstring vt_char2 := v_char[2] & t_char; + var template charstring vt_char2_exp := "zdef"; + + var template charstring vt_char3 := "abc" & v_char[1]; + var template charstring vt_char3_exp := "abcy" + + var template charstring vt_char4 := v_char[1] & "abc"; + var template charstring vt_char4_exp := "yabc"; + + if (log2str(vt_char1) != log2str(vt_char1_exp)) { + setverdict(fail, "Expected: ", vt_char1_exp, ", got: ", vt_char1); + } + else if (log2str(vt_char2) != log2str(vt_char2_exp)) { + setverdict(fail, "Expected: ", vt_char2_exp, ", got: ", vt_char2); + } + else if (log2str(vt_char3) != log2str(vt_char3_exp)) { + setverdict(fail, "Expected: ", vt_char3_exp, ", got: ", vt_char3); + } + else if (log2str(vt_char4) != log2str(vt_char4_exp)) { + setverdict(fail, "Expected: ", vt_char4_exp, ", got: ", vt_char4); + } + else { + setverdict(pass); + } +} + +testcase tc_char_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, omit, omit, "aeiou", omit, omit, omit }; + + var template charstring vt_char1 := t_char & v_rec.cs; + var template charstring vt_char1_exp := "defaeiou"; + + var template charstring vt_char2 := v_rec.cs & t_char; + var template charstring vt_char2_exp := "aeioudef"; + + var template charstring vt_char3 := "xx" & v_rec.cs; + var template charstring vt_char3_exp := "xxaeiou"; + + var template charstring vt_char4 := v_rec.cs & "xx"; + var template charstring vt_char4_exp := "aeiouxx"; + + if (log2str(vt_char1) != log2str(vt_char1_exp)) { + setverdict(fail, "Expected: ", vt_char1_exp, ", got: ", vt_char1); + } + else if (log2str(vt_char2) != log2str(vt_char2_exp)) { + setverdict(fail, "Expected: ", vt_char2_exp, ", got: ", vt_char2); + } + else if (log2str(vt_char3) != log2str(vt_char3_exp)) { + setverdict(fail, "Expected: ", vt_char3_exp, ", got: ", vt_char3); + } + else if (log2str(vt_char4) != log2str(vt_char4_exp)) { + setverdict(fail, "Expected: ", vt_char4_exp, ", got: ", vt_char4); + } + else { + setverdict(pass); + } +} + +testcase tc_char_vt_extra() runs on CT { + var charstring v_char := "xyz"; + var Rec v_rec := { omit, omit, omit, "aeiou", omit, omit, omit }; + + var template charstring vt_char1 := v_char[0] & v_rec.cs; + var template charstring vt_char1_exp := "xaeiou"; + + var template charstring vt_char2 := v_rec.cs & v_char[0]; + var template charstring vt_char2_exp := "aeioux"; + + if (log2str(vt_char1) != log2str(vt_char1_exp)) { + setverdict(fail, "Expected: ", vt_char1_exp, ", got: ", vt_char1); + } + else if (log2str(vt_char2) != log2str(vt_char2_exp)) { + setverdict(fail, "Expected: ", vt_char2_exp, ", got: ", vt_char2); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_char_t_values()); + execute(tc_char_vt_values()); + execute(tc_char_vt_w_str_elem()); + execute(tc_char_vt_w_opt_fields()); + execute(tc_char_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatHex.ttcn b/regression_test/templateConcat/TemplateConcatHex.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..d0da1540472319bf8c660f546efd59cc33a88267 --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatHex.ttcn @@ -0,0 +1,353 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating hexstring templates +module TemplateConcatHex { + +import from Types all; + +const hexstring c_hex := 'ABCD'H; + +template hexstring t_hex := ? length(2..2); + +template hexstring t_hex1 := 'ABCD'H & ? length (2) & 'EF'H; +template hexstring t_hex1_exp := 'ABCD??EF'H; + +template hexstring t_hex2 := 'ABCD'H & 'EF'H & ? & ? length(1) & 'EF'H; +template hexstring t_hex2_exp := 'ABCDEF*?EF'H; + +template hexstring t_hex3 := ('ABCD'H & ? length(2..2)) length(6); +template hexstring t_hex3_exp := 'ABCD??'H length(6); + +template hexstring t_hex4 := c_hex & ? length (2) & 'EF'H; +template hexstring t_hex4_exp := 'ABCD??EF'H; + +template hexstring t_hex5 := ('ABCD'H & t_hex) length(6); +template hexstring t_hex5_exp := 'ABCD??'H length(6); + +template hexstring t_hex6 := 'ABCD'H & ?; +template hexstring t_hex6_exp := 'ABCD*'H; + +template hexstring t_hex7 := ? & 'EF'H; +template hexstring t_hex7_exp := '*EF'H; + +template hexstring t_hex8 := 'ABCD'H & ? & 'EF'H; +template hexstring t_hex8_exp := 'ABCD*EF'H; + +template hexstring t_hex9 := ? & ?; +template hexstring t_hex9_exp := ?; + +template hexstring t_hex10 := ? & ? & 'EF'H; +template hexstring t_hex10_exp := '*EF'H; + +template hexstring t_hex11 := 'ABCD'H & 'EF'H & ? & ? & ? length(1) & 'EF'H; +template hexstring t_hex11_exp := 'ABCDEF*?EF'H; + +testcase tc_hex_t_w_literals() runs on CT { + if (log2str(t_hex1) != log2str(t_hex1_exp)) { + setverdict(fail, "Expected: ", t_hex1_exp, ", got: ", t_hex1); + } + else if (log2str(t_hex2) != log2str(t_hex2_exp)) { + setverdict(fail, "Expected: ", t_hex2_exp, ", got: ", t_hex2); + } + else if (log2str(t_hex3) != log2str(t_hex3_exp)) { + setverdict(fail, "Expected: ", t_hex3_exp, ", got: ", t_hex3); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_t_w_refs() runs on CT { + if (log2str(t_hex4) != log2str(t_hex4_exp)) { + setverdict(fail, "Expected: ", t_hex4_exp, ", got: ", t_hex4); + } + else if (log2str(t_hex5) != log2str(t_hex5_exp)) { + setverdict(fail, "Expected: ", t_hex5_exp, ", got: ", t_hex5); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_t_w_any_value() runs on CT { + if (log2str(t_hex6) != log2str(t_hex6_exp)) { + setverdict(fail, "Expected: ", t_hex6_exp, ", got: ", t_hex6); + } + else if (log2str(t_hex7) != log2str(t_hex7_exp)) { + setverdict(fail, "Expected: ", t_hex7_exp, ", got: ", t_hex7); + } + else if (log2str(t_hex8) != log2str(t_hex8_exp)) { + setverdict(fail, "Expected: ", t_hex8_exp, ", got: ", t_hex8); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_t_dbl_any_value() runs on CT { + if (log2str(t_hex9) != log2str(t_hex9_exp)) { + setverdict(fail, "Expected: ", t_hex9_exp, ", got: ", t_hex9); + } + else if (log2str(t_hex10) != log2str(t_hex10_exp)) { + setverdict(fail, "Expected: ", t_hex10_exp, ", got: ", t_hex10); + } + else if (log2str(t_hex11) != log2str(t_hex11_exp)) { + setverdict(fail, "Expected: ", t_hex11_exp, ", got: ", t_hex11); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_w_literals() runs on CT { + var template hexstring vt_hex1 := 'ABCD'H & ? length (2) & 'EF'H; + var template hexstring vt_hex1_exp := 'ABCD??EF'H; + + var template hexstring vt_hex2 := 'ABCD'H & 'EF'H & ? & ? length(1) & 'EF'H; + var template hexstring vt_hex2_exp := 'ABCDEF*?EF'H; + + var template hexstring vt_hex3 := ('ABCD'H & ? length(2..2)) length(6); + var template hexstring vt_hex3_exp := 'ABCD??'H length(6); + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_w_refs() runs on CT { + var integer v_len := 3; + var hexstring v_hex := 'EF'H; + var template hexstring vt_hex := ?; + + var template hexstring vt_hex1 := c_hex & ? length (2) & 'EF'H; + var template hexstring vt_hex1_exp := 'ABCD??EF'H; + + var template hexstring vt_hex2 := 'ABCD'H & v_hex & vt_hex & ? length(v_len) & v_hex; + var template hexstring vt_hex2_exp := 'ABCDEF*???EF'H; + + var template hexstring vt_hex3 := ('ABCD'H & t_hex) length(6); + var template hexstring vt_hex3_exp := 'ABCD??'H length(6); + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_w_any_value() runs on CT { + var template hexstring vt_hex1 := 'ABCD'H & ?; + var template hexstring vt_hex1_exp := 'ABCD*'H; + + var template hexstring vt_hex2 := ? & 'EF'H; + var template hexstring vt_hex2_exp := '*EF'H; + + var template hexstring vt_hex3 := 'ABCD'H & ? & 'EF'H; + var template hexstring vt_hex3_exp := 'ABCD*EF'H; + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_dbl_any_value() runs on CT { + var integer v_len := 3; + + var template hexstring vt_hex1 := ? & ?; + var template hexstring vt_hex1_exp := ?; + + var template hexstring vt_hex2 := ? & ? & 'EF'H; + var template hexstring vt_hex2_exp := '*EF'H; + + var template hexstring vt_hex3 := 'ABCD'H & 'EF'H & ? & ? & ? length(v_len - 1) & 'EF'H; + var template hexstring vt_hex3_exp := 'ABCDEF*??EF'H; + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_dbl_any_value_w_refs() runs on CT { + var template hexstring vt_hex := ?; + + var template hexstring vt_hex1 := vt_hex & ?; + var template hexstring vt_hex1_exp := ?; + + var template hexstring vt_hex2 := ? & vt_hex; + var template hexstring vt_hex2_exp := ?; + + var template hexstring vt_hex3 := vt_hex & vt_hex; + var template hexstring vt_hex3_exp := ?; + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "1st test. Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "2nd test. Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "3rd test. Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_w_str_elem() runs on CT { + var hexstring v_hex := 'EF'H; + var hexstring v_hex2 := 'ABCD'H; + + var template hexstring vt_hex1 := v_hex[0] & ?; + var template hexstring vt_hex1_exp := 'E*'H; + + var template hexstring vt_hex2 := 'AB'H & ? length(3) & v_hex2[2]; + var template hexstring vt_hex2_exp := 'AB???C'H; + + var template hexstring vt_hex3 := ? & v_hex2[0]; + var template hexstring vt_hex3_exp := '*A'H; + + var template hexstring vt_hex4 := v_hex2[1] & vt_hex1_exp; + var template hexstring vt_hex4_exp := 'BE*'H; + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else if (log2str(vt_hex4) != log2str(vt_hex4_exp)) { + setverdict(fail, "Expected: ", vt_hex4_exp, ", got: ", vt_hex4); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, '12A'H, omit, omit, omit, omit, omit }; + + var template hexstring vt_hex1 := 'EF'H & ? length(1) & v_rec.hs; + var template hexstring vt_hex1_exp := 'EF?12A'H; + + var template hexstring vt_hex2 := v_rec.hs & vt_hex1_exp; + var template hexstring vt_hex2_exp := '12AEF?12A'H; + + var template hexstring vt_hex3 := ? & v_rec.hs; + var template hexstring vt_hex3_exp := '*12A'H; + + var template hexstring vt_hex4 := v_rec.hs & ?; + var template hexstring vt_hex4_exp := '12A*'H; + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else if (log2str(vt_hex4) != log2str(vt_hex4_exp)) { + setverdict(fail, "Expected: ", vt_hex4_exp, ", got: ", vt_hex4); + } + else { + setverdict(pass); + } +} + +testcase tc_hex_vt_extra() runs on CT { + var hexstring v_hex2 := 'ABCD'H; + var Rec v_rec := { omit, '12A'H, omit, omit, omit, omit, omit }; + + var template hexstring vt_hex1 := v_rec.hs & 'FF'H; + var template hexstring vt_hex1_exp := '12AFF'H; + + var template hexstring vt_hex2 := 'FF'H & v_rec.hs & 'FF'H; + var template hexstring vt_hex2_exp := 'FF12AFF'H; + + var template hexstring vt_hex3 := v_hex2[3] & v_rec.hs; + var template hexstring vt_hex3_exp := 'D12A'H; + + var template hexstring vt_hex4 := v_rec.hs & v_hex2[3]; + var template hexstring vt_hex4_exp := '12AD'H; + + if (log2str(vt_hex1) != log2str(vt_hex1_exp)) { + setverdict(fail, "Expected: ", vt_hex1_exp, ", got: ", vt_hex1); + } + else if (log2str(vt_hex2) != log2str(vt_hex2_exp)) { + setverdict(fail, "Expected: ", vt_hex2_exp, ", got: ", vt_hex2); + } + else if (log2str(vt_hex3) != log2str(vt_hex3_exp)) { + setverdict(fail, "Expected: ", vt_hex3_exp, ", got: ", vt_hex3); + } + else if (log2str(vt_hex4) != log2str(vt_hex4_exp)) { + setverdict(fail, "Expected: ", vt_hex4_exp, ", got: ", vt_hex4); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_hex_t_w_literals()); + execute(tc_hex_t_w_refs()); + execute(tc_hex_t_w_any_value()); + execute(tc_hex_t_dbl_any_value()); + execute(tc_hex_vt_w_literals()); + execute(tc_hex_vt_w_refs()); + execute(tc_hex_vt_w_any_value()); + execute(tc_hex_vt_dbl_any_value()); + execute(tc_hex_vt_dbl_any_value_w_refs()); + execute(tc_hex_vt_w_str_elem()); + execute(tc_hex_vt_w_opt_fields()); + execute(tc_hex_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatMixed.ttcn b/regression_test/templateConcat/TemplateConcatMixed.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..7f729bfa03b56811677d9d34a631ca80476c8781 --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatMixed.ttcn @@ -0,0 +1,312 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating charstring and universal charstring templates +module TemplateConcatMixed { + +import from Types all; + +template charstring t_char := "def"; + +template universal charstring t_unichar := char(0, 0, 1, 2); + +// there is no other way to recreate these universal charstring templates, than concatenation, +// so use constants and variable for the expected values +template universal charstring t_mixed1 := "abc" & char(0, 1, 2, 3); +const universal charstring c_mixed1_exp := "abc" & char(0, 1, 2, 3); + +template universal charstring t_mixed2 := char(0, 1, 2, 3) & "abc"; +const universal charstring c_mixed2_exp := char(0, 1, 2, 3) & "abc"; + +template universal charstring t_mixed3 := t_char & char(0, 0, 1, 117); +const universal charstring c_mixed3_exp := "def" & char(0, 0, 1, 117); + +template universal charstring t_mixed4 := char(0, 0, 1, 117) & t_char; +const universal charstring c_mixed4_exp := char(0, 0, 1, 117) & "def"; + +template universal charstring t_mixed5 := t_unichar & "xx"; +const universal charstring c_mixed5_exp := char(0, 0, 1, 2) & "xx"; + +template universal charstring t_mixed6 := "xx" & t_unichar; +const universal charstring c_mixed6_exp := "xx" & char(0, 0, 1, 2); + +template universal charstring t_mixed7 := t_char & t_unichar; +const universal charstring c_mixed7_exp := "def" & char(0, 0, 1, 2); + +template universal charstring t_mixed8 := t_unichar & t_char; +const universal charstring c_mixed8_exp := char(0, 0, 1, 2) & "def"; + + +testcase tc_mixed_t_values() runs on CT { + if (log2str(t_mixed1) != log2str(c_mixed1_exp)) { + setverdict(fail, "Expected: ", c_mixed1_exp, ", got: ", t_mixed1); + } + else if (log2str(t_mixed2) != log2str(c_mixed2_exp)) { + setverdict(fail, "Expected: ", c_mixed2_exp, ", got: ", t_mixed2); + } + else if (log2str(t_mixed3) != log2str(c_mixed3_exp)) { + setverdict(fail, "Expected: ", c_mixed3_exp, ", got: ", t_mixed3); + } + else if (log2str(t_mixed4) != log2str(c_mixed4_exp)) { + setverdict(fail, "Expected: ", c_mixed4_exp, ", got: ", t_mixed4); + } + else if (log2str(t_mixed5) != log2str(c_mixed5_exp)) { + setverdict(fail, "Expected: ", c_mixed5_exp, ", got: ", t_mixed5); + } + else if (log2str(t_mixed6) != log2str(c_mixed6_exp)) { + setverdict(fail, "Expected: ", c_mixed6_exp, ", got: ", t_mixed6); + } + else if (log2str(t_mixed7) != log2str(c_mixed7_exp)) { + setverdict(fail, "Expected: ", c_mixed7_exp, ", got: ", t_mixed7); + } + else if (log2str(t_mixed8) != log2str(c_mixed8_exp)) { + setverdict(fail, "Expected: ", c_mixed8_exp, ", got: ", t_mixed8); + } + else { + setverdict(pass); + } +} + +testcase tc_mixed_vt_values() runs on CT { + var template universal charstring vt_mixed1 := "abc" & char(0, 1, 2, 3); + var universal charstring v_mixed1_exp := "abc" & char(0, 1, 2, 3); + + var template universal charstring vt_mixed2 := char(0, 1, 2, 3) & "abc"; + var universal charstring v_mixed2_exp := char(0, 1, 2, 3) & "abc"; + + var template universal charstring vt_mixed3 := t_char & char(0, 0, 1, 117); + var universal charstring v_mixed3_exp := "def" & char(0, 0, 1, 117); + + var template universal charstring vt_mixed4 := char(0, 0, 1, 117) & t_char; + var universal charstring v_mixed4_exp := char(0, 0, 1, 117) & "def"; + + var template universal charstring vt_mixed5 := t_unichar & "xx"; + var universal charstring v_mixed5_exp := char(0, 0, 1, 2) & "xx"; + + var template universal charstring vt_mixed6 := "xx" & t_unichar; + var universal charstring v_mixed6_exp := "xx" & char(0, 0, 1, 2); + + var template universal charstring vt_mixed7 := t_char & t_unichar; + var universal charstring v_mixed7_exp := "def" & char(0, 0, 1, 2); + + var template universal charstring vt_mixed8 := t_unichar & t_char; + var universal charstring v_mixed8_exp := char(0, 0, 1, 2) & "def"; + + if (log2str(vt_mixed1) != log2str(v_mixed1_exp)) { + setverdict(fail, "Expected: ", v_mixed1_exp, ", got: ", vt_mixed1); + } + else if (log2str(vt_mixed2) != log2str(v_mixed2_exp)) { + setverdict(fail, "Expected: ", v_mixed2_exp, ", got: ", vt_mixed2); + } + else if (log2str(vt_mixed3) != log2str(v_mixed3_exp)) { + setverdict(fail, "Expected: ", v_mixed3_exp, ", got: ", vt_mixed3); + } + else if (log2str(vt_mixed4) != log2str(v_mixed4_exp)) { + setverdict(fail, "Expected: ", v_mixed4_exp, ", got: ", vt_mixed4); + } + else if (log2str(vt_mixed5) != log2str(v_mixed5_exp)) { + setverdict(fail, "Expected: ", v_mixed5_exp, ", got: ", vt_mixed5); + } + else if (log2str(vt_mixed6) != log2str(v_mixed6_exp)) { + setverdict(fail, "Expected: ", v_mixed6_exp, ", got: ", vt_mixed6); + } + else if (log2str(vt_mixed7) != log2str(v_mixed7_exp)) { + setverdict(fail, "Expected: ", v_mixed7_exp, ", got: ", vt_mixed7); + } + else if (log2str(vt_mixed8) != log2str(v_mixed8_exp)) { + setverdict(fail, "Expected: ", v_mixed8_exp, ", got: ", vt_mixed8); + } + else { + setverdict(pass); + } +} + +testcase tc_mixed_vt_w_str_elem() runs on CT { + var charstring v_char := "abc"; + var universal charstring v_unichar := "xyz"; + + var template universal charstring vt_mixed1 := "abc" & v_unichar[1]; + var universal charstring v_mixed1_exp := "abcy"; + + var template universal charstring vt_mixed2 := v_unichar[1] & "abc"; + var universal charstring v_mixed2_exp := "yabc"; + + var template universal charstring vt_mixed3 := char(0, 1, 2, 3) & v_char[0]; + var universal charstring v_mixed3_exp := char(0, 1, 2, 3) & "a"; + + var template universal charstring vt_mixed4 := v_char[0] & char(0, 1, 2, 3); + var universal charstring v_mixed4_exp := "a" & char(0, 1, 2, 3); + + var template universal charstring vt_mixed5 := t_char & v_unichar[1]; + var universal charstring v_mixed5_exp := "defy"; + + var template universal charstring vt_mixed6 := v_unichar[1] & t_char; + var universal charstring v_mixed6_exp := "ydef"; + + var template universal charstring vt_mixed7 := t_unichar & v_char[0]; + var universal charstring v_mixed7_exp := char(0, 0, 1, 2) & "a"; + + var template universal charstring vt_mixed8 := v_char[0] & t_unichar; + var universal charstring v_mixed8_exp := "a" & char(0, 0, 1, 2); + + if (log2str(vt_mixed1) != log2str(v_mixed1_exp)) { + setverdict(fail, "Expected: ", v_mixed1_exp, ", got: ", vt_mixed1); + } + else if (log2str(vt_mixed2) != log2str(v_mixed2_exp)) { + setverdict(fail, "Expected: ", v_mixed2_exp, ", got: ", vt_mixed2); + } + else if (log2str(vt_mixed3) != log2str(v_mixed3_exp)) { + setverdict(fail, "Expected: ", v_mixed3_exp, ", got: ", vt_mixed3); + } + else if (log2str(vt_mixed4) != log2str(v_mixed4_exp)) { + setverdict(fail, "Expected: ", v_mixed4_exp, ", got: ", vt_mixed4); + } + else if (log2str(vt_mixed5) != log2str(v_mixed5_exp)) { + setverdict(fail, "Expected: ", v_mixed5_exp, ", got: ", vt_mixed5); + } + else if (log2str(vt_mixed6) != log2str(v_mixed6_exp)) { + setverdict(fail, "Expected: ", v_mixed6_exp, ", got: ", vt_mixed6); + } + else if (log2str(vt_mixed7) != log2str(v_mixed7_exp)) { + setverdict(fail, "Expected: ", v_mixed7_exp, ", got: ", vt_mixed7); + } + else if (log2str(vt_mixed8) != log2str(v_mixed8_exp)) { + setverdict(fail, "Expected: ", v_mixed8_exp, ", got: ", vt_mixed8); + } + else { + setverdict(pass); + } +} + +testcase tc_mixed_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, omit, omit, "xx", "yy", omit, omit }; + + var template universal charstring vt_mixed1 := "abc" & v_rec.ucs; + var universal charstring v_mixed1_exp := "abcyy"; + + var template universal charstring vt_mixed2 := v_rec.ucs & "abc"; + var universal charstring v_mixed2_exp := "yyabc"; + + var template universal charstring vt_mixed3 := char(0, 1, 2, 3) & v_rec.cs; + var universal charstring v_mixed3_exp := char(0, 1, 2, 3) & "xx"; + + var template universal charstring vt_mixed4 := v_rec.cs & char(0, 1, 2, 3); + var universal charstring v_mixed4_exp := "xx" & char(0, 1, 2, 3); + + var template universal charstring vt_mixed5 := t_char & v_rec.ucs; + var universal charstring v_mixed5_exp := "defyy"; + + var template universal charstring vt_mixed6 := v_rec.ucs & t_char; + var universal charstring v_mixed6_exp := "yydef"; + + var template universal charstring vt_mixed7 := t_unichar & v_rec.cs; + var universal charstring v_mixed7_exp := char(0, 0, 1, 2) & "xx"; + + var template universal charstring vt_mixed8 := v_rec.cs & t_unichar; + var universal charstring v_mixed8_exp := "xx" & char(0, 0, 1, 2); + + if (log2str(vt_mixed1) != log2str(v_mixed1_exp)) { + setverdict(fail, "Expected: ", v_mixed1_exp, ", got: ", vt_mixed1); + } + else if (log2str(vt_mixed2) != log2str(v_mixed2_exp)) { + setverdict(fail, "Expected: ", v_mixed2_exp, ", got: ", vt_mixed2); + } + else if (log2str(vt_mixed3) != log2str(v_mixed3_exp)) { + setverdict(fail, "Expected: ", v_mixed3_exp, ", got: ", vt_mixed3); + } + else if (log2str(vt_mixed4) != log2str(v_mixed4_exp)) { + setverdict(fail, "Expected: ", v_mixed4_exp, ", got: ", vt_mixed4); + } + else if (log2str(vt_mixed5) != log2str(v_mixed5_exp)) { + setverdict(fail, "Expected: ", v_mixed5_exp, ", got: ", vt_mixed5); + } + else if (log2str(vt_mixed6) != log2str(v_mixed6_exp)) { + setverdict(fail, "Expected: ", v_mixed6_exp, ", got: ", vt_mixed6); + } + else if (log2str(vt_mixed7) != log2str(v_mixed7_exp)) { + setverdict(fail, "Expected: ", v_mixed7_exp, ", got: ", vt_mixed7); + } + else if (log2str(vt_mixed8) != log2str(v_mixed8_exp)) { + setverdict(fail, "Expected: ", v_mixed8_exp, ", got: ", vt_mixed8); + } + else { + setverdict(pass); + } +} + +testcase tc_mixed_vt_extra() runs on CT { + var charstring v_char := "abc"; + var universal charstring v_unichar := "xyz"; + var Rec v_rec := { omit, omit, omit, "xx", "yy", omit, omit }; + + var template universal charstring vt_mixed1 := v_char[0] & v_rec.ucs; + var universal charstring v_mixed1_exp := "ayy"; + + var template universal charstring vt_mixed2 := v_rec.ucs & v_char[0]; + var universal charstring v_mixed2_exp := "yya"; + + var template universal charstring vt_mixed3 := v_rec.cs & v_unichar[1]; + var universal charstring v_mixed3_exp := "xxy"; + + var template universal charstring vt_mixed4 := v_unichar[1] & v_rec.cs; + var universal charstring v_mixed4_exp := "yxx"; + + var template universal charstring vt_mixed5 := v_char[0] & v_unichar[1]; + var universal charstring v_mixed5_exp := "ay"; + + var template universal charstring vt_mixed6 := v_unichar[1] & v_char[0]; + var universal charstring v_mixed6_exp := "ya"; + + var template universal charstring vt_mixed7 := v_rec.cs & v_rec.ucs; + var universal charstring v_mixed7_exp := "xxyy"; + + var template universal charstring vt_mixed8 := v_rec.ucs & v_rec.cs; + var universal charstring v_mixed8_exp := "yyxx"; + + if (log2str(vt_mixed1) != log2str(v_mixed1_exp)) { + setverdict(fail, "Expected: ", v_mixed1_exp, ", got: ", vt_mixed1); + } + else if (log2str(vt_mixed2) != log2str(v_mixed2_exp)) { + setverdict(fail, "Expected: ", v_mixed2_exp, ", got: ", vt_mixed2); + } + else if (log2str(vt_mixed3) != log2str(v_mixed3_exp)) { + setverdict(fail, "Expected: ", v_mixed3_exp, ", got: ", vt_mixed3); + } + else if (log2str(vt_mixed4) != log2str(v_mixed4_exp)) { + setverdict(fail, "Expected: ", v_mixed4_exp, ", got: ", vt_mixed4); + } + else if (log2str(vt_mixed5) != log2str(v_mixed5_exp)) { + setverdict(fail, "Expected: ", v_mixed5_exp, ", got: ", vt_mixed5); + } + else if (log2str(vt_mixed6) != log2str(v_mixed6_exp)) { + setverdict(fail, "Expected: ", v_mixed6_exp, ", got: ", vt_mixed6); + } + else if (log2str(vt_mixed7) != log2str(v_mixed7_exp)) { + setverdict(fail, "Expected: ", v_mixed7_exp, ", got: ", vt_mixed7); + } + else if (log2str(vt_mixed8) != log2str(v_mixed8_exp)) { + setverdict(fail, "Expected: ", v_mixed8_exp, ", got: ", vt_mixed8); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_mixed_t_values()); + execute(tc_mixed_vt_values()); + execute(tc_mixed_vt_w_str_elem()); + execute(tc_mixed_vt_w_opt_fields()); + execute(tc_mixed_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatOct.ttcn b/regression_test/templateConcat/TemplateConcatOct.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..c69766769ef510e787a90fbafd5295c7b42d21e7 --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatOct.ttcn @@ -0,0 +1,353 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating octetstring templates +module TemplateConcatOct { + +import from Types all; + +const octetstring c_oct := 'ABCD'O; + +template octetstring t_oct := ? length(2..2); + +template octetstring t_oct1 := 'ABCD'O & ? length (2) & 'EF'O; +template octetstring t_oct1_exp := 'ABCD??EF'O; + +template octetstring t_oct2 := 'ABCD'O & 'EF'O & ? & ? length(1) & 'EF'O; +template octetstring t_oct2_exp := 'ABCDEF*?EF'O; + +template octetstring t_oct3 := ('ABCD'O & ? length(2..2)) length(4); +template octetstring t_oct3_exp := 'ABCD??'O length(4); + +template octetstring t_oct4 := c_oct & ? length (2) & 'EF'O; +template octetstring t_oct4_exp := 'ABCD??EF'O; + +template octetstring t_oct5 := ('ABCD'O & t_oct) length(4); +template octetstring t_oct5_exp := 'ABCD??'O length(4); + +template octetstring t_oct6 := 'ABCD'O & ?; +template octetstring t_oct6_exp := 'ABCD*'O; + +template octetstring t_oct7 := ? & 'EF'O; +template octetstring t_oct7_exp := '*EF'O; + +template octetstring t_oct8 := 'ABCD'O & ? & 'EF'O; +template octetstring t_oct8_exp := 'ABCD*EF'O; + +template octetstring t_oct9 := ? & ?; +template octetstring t_oct9_exp := ?; + +template octetstring t_oct10 := ? & ? & 'EF'O; +template octetstring t_oct10_exp := '*EF'O; + +template octetstring t_oct11 := 'ABCD'O & 'EF'O & ? & ? & ? length(1) & 'EF'O; +template octetstring t_oct11_exp := 'ABCDEF*?EF'O; + +testcase tc_oct_t_w_literals() runs on CT { + if (log2str(t_oct1) != log2str(t_oct1_exp)) { + setverdict(fail, "Expected: ", t_oct1_exp, ", got: ", t_oct1); + } + else if (log2str(t_oct2) != log2str(t_oct2_exp)) { + setverdict(fail, "Expected: ", t_oct2_exp, ", got: ", t_oct2); + } + else if (log2str(t_oct3) != log2str(t_oct3_exp)) { + setverdict(fail, "Expected: ", t_oct3_exp, ", got: ", t_oct3); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_t_w_refs() runs on CT { + if (log2str(t_oct4) != log2str(t_oct4_exp)) { + setverdict(fail, "Expected: ", t_oct4_exp, ", got: ", t_oct4); + } + else if (log2str(t_oct5) != log2str(t_oct5_exp)) { + setverdict(fail, "Expected: ", t_oct5_exp, ", got: ", t_oct5); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_t_w_any_value() runs on CT { + if (log2str(t_oct6) != log2str(t_oct6_exp)) { + setverdict(fail, "Expected: ", t_oct6_exp, ", got: ", t_oct6); + } + else if (log2str(t_oct7) != log2str(t_oct7_exp)) { + setverdict(fail, "Expected: ", t_oct7_exp, ", got: ", t_oct7); + } + else if (log2str(t_oct8) != log2str(t_oct8_exp)) { + setverdict(fail, "Expected: ", t_oct8_exp, ", got: ", t_oct8); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_t_dbl_any_value() runs on CT { + if (log2str(t_oct9) != log2str(t_oct9_exp)) { + setverdict(fail, "Expected: ", t_oct9_exp, ", got: ", t_oct9); + } + else if (log2str(t_oct10) != log2str(t_oct10_exp)) { + setverdict(fail, "Expected: ", t_oct10_exp, ", got: ", t_oct10); + } + else if (log2str(t_oct11) != log2str(t_oct11_exp)) { + setverdict(fail, "Expected: ", t_oct11_exp, ", got: ", t_oct11); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_w_literals() runs on CT { + var template octetstring vt_oct1 := 'ABCD'O & ? length (2) & 'EF'O; + var template octetstring vt_oct1_exp := 'ABCD??EF'O; + + var template octetstring vt_oct2 := 'ABCD'O & 'EF'O & ? & ? length(1) & 'EF'O; + var template octetstring vt_oct2_exp := 'ABCDEF*?EF'O; + + var template octetstring vt_oct3 := ('ABCD'O & ? length(2..2)) length(4); + var template octetstring vt_oct3_exp := 'ABCD??'O length(4); + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_w_refs() runs on CT { + var integer v_len := 3; + var octetstring v_oct := 'EF'O; + var template octetstring vt_oct := ?; + + var template octetstring vt_oct1 := c_oct & ? length (2) & 'EF'O; + var template octetstring vt_oct1_exp := 'ABCD??EF'O; + + var template octetstring vt_oct2 := 'ABCD'O & v_oct & vt_oct & ? length(v_len) & v_oct; + var template octetstring vt_oct2_exp := 'ABCDEF*???EF'O; + + var template octetstring vt_oct3 := ('ABCD'O & t_oct) length(4); + var template octetstring vt_oct3_exp := 'ABCD??'O length(4); + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_w_any_value() runs on CT { + var template octetstring vt_oct1 := 'ABCD'O & ?; + var template octetstring vt_oct1_exp := 'ABCD*'O; + + var template octetstring vt_oct2 := ? & 'EF'O; + var template octetstring vt_oct2_exp := '*EF'O; + + var template octetstring vt_oct3 := 'ABCD'O & ? & 'EF'O; + var template octetstring vt_oct3_exp := 'ABCD*EF'O; + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_dbl_any_value() runs on CT { + var integer v_len := 3; + + var template octetstring vt_oct1 := ? & ?; + var template octetstring vt_oct1_exp := ?; + + var template octetstring vt_oct2 := ? & ? & 'EF'O; + var template octetstring vt_oct2_exp := '*EF'O; + + var template octetstring vt_oct3 := 'ABCD'O & 'EF'O & ? & ? & ? length(v_len - 1) & 'EF'O; + var template octetstring vt_oct3_exp := 'ABCDEF*??EF'O; + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_dbl_any_value_w_refs() runs on CT { + var template octetstring vt_oct := ?; + + var template octetstring vt_oct1 := vt_oct & ?; + var template octetstring vt_oct1_exp := ?; + + var template octetstring vt_oct2 := ? & vt_oct; + var template octetstring vt_oct2_exp := ?; + + var template octetstring vt_oct3 := vt_oct & vt_oct; + var template octetstring vt_oct3_exp := ?; + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "1st test. Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "2nd test. Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "3rd test. Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_w_str_elem() runs on CT { + var octetstring v_oct := 'EF'O; + var octetstring v_oct2 := 'ABCD'O; + + var template octetstring vt_oct1 := v_oct[0] & ?; + var template octetstring vt_oct1_exp := 'EF*'O; + + var template octetstring vt_oct2 := 'AB'O & ? length(3) & v_oct2[1]; + var template octetstring vt_oct2_exp := 'AB???CD'O; + + var template octetstring vt_oct3 := ? & v_oct2[0]; + var template octetstring vt_oct3_exp := '*AB'O; + + var template octetstring vt_oct4 := v_oct2[1] & vt_oct1_exp; + var template octetstring vt_oct4_exp := 'CDEF*'O; + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else if (log2str(vt_oct4) != log2str(vt_oct4_exp)) { + setverdict(fail, "Expected: ", vt_oct4_exp, ", got: ", vt_oct4); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_w_opt_fields() runs on CT { + var Rec v_rec := { '12AB'O, omit, omit, omit, omit, omit, omit }; + + var template octetstring vt_oct1 := 'EF'O & ? length(1) & v_rec.os; + var template octetstring vt_oct1_exp := 'EF?12AB'O; + + var template octetstring vt_oct2 := v_rec.os & vt_oct1_exp; + var template octetstring vt_oct2_exp := '12ABEF?12AB'O; + + var template octetstring vt_oct3 := ? & v_rec.os; + var template octetstring vt_oct3_exp := '*12AB'O; + + var template octetstring vt_oct4 := v_rec.os & ?; + var template octetstring vt_oct4_exp := '12AB*'O; + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else if (log2str(vt_oct4) != log2str(vt_oct4_exp)) { + setverdict(fail, "Expected: ", vt_oct4_exp, ", got: ", vt_oct4); + } + else { + setverdict(pass); + } +} + +testcase tc_oct_vt_extra() runs on CT { + var octetstring v_oct2 := 'ABCD'O; + var Rec v_rec := { '12AB'O, omit, omit, omit, omit, omit, omit }; + + var template octetstring vt_oct1 := v_rec.os & 'FF'O; + var template octetstring vt_oct1_exp := '12ABFF'O; + + var template octetstring vt_oct2 := 'FF'O & v_rec.os & 'FF'O; + var template octetstring vt_oct2_exp := 'FF12ABFF'O; + + var template octetstring vt_oct3 := v_oct2[1] & v_rec.os; + var template octetstring vt_oct3_exp := 'CD12AB'O; + + var template octetstring vt_oct4 := v_rec.os & v_oct2[1]; + var template octetstring vt_oct4_exp := '12ABCD'O; + + if (log2str(vt_oct1) != log2str(vt_oct1_exp)) { + setverdict(fail, "Expected: ", vt_oct1_exp, ", got: ", vt_oct1); + } + else if (log2str(vt_oct2) != log2str(vt_oct2_exp)) { + setverdict(fail, "Expected: ", vt_oct2_exp, ", got: ", vt_oct2); + } + else if (log2str(vt_oct3) != log2str(vt_oct3_exp)) { + setverdict(fail, "Expected: ", vt_oct3_exp, ", got: ", vt_oct3); + } + else if (log2str(vt_oct4) != log2str(vt_oct4_exp)) { + setverdict(fail, "Expected: ", vt_oct4_exp, ", got: ", vt_oct4); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_oct_t_w_literals()); + execute(tc_oct_t_w_refs()); + execute(tc_oct_t_w_any_value()); + execute(tc_oct_t_dbl_any_value()); + execute(tc_oct_vt_w_literals()); + execute(tc_oct_vt_w_refs()); + execute(tc_oct_vt_w_any_value()); + execute(tc_oct_vt_dbl_any_value()); + execute(tc_oct_vt_dbl_any_value_w_refs()); + execute(tc_oct_vt_w_str_elem()); + execute(tc_oct_vt_w_opt_fields()); + execute(tc_oct_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatRecof.ttcn b/regression_test/templateConcat/TemplateConcatRecof.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..8f6cf6ae1656c150ff1c9cddd0f1c411b6fdf52f --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatRecof.ttcn @@ -0,0 +1,255 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating record of templates +module TemplateConcatRecof { + +import from Types all; + +const RecOfInt c_recof := { 1, 2 }; + +template RecOfInt t_recof_op1 := { 1, 2, 3 }; +template RecOfInt t_recof_op2 := { 4, 5 }; +template RecOfInt t_recof_op3 := ?; +template RecOfInt t_recof_op4 := ? length(2..2); +template RecOfInt t_recof_op5 := * length(3); + +template RecOfInt t_recof1 := t_recof_op1 & { 4, 5 }; +template RecOfInt t_recof1_exp := { 1, 2, 3, 4, 5}; + +template RecOfInt t_recof2 := t_recof_op1 & ?; +template RecOfInt t_recof2_exp := { 1, 2, 3, * }; + +template RecOfInt t_recof3 := ? & t_recof_op2; +template RecOfInt t_recof3_exp := { *, 4, 5 }; + +template RecOfInt t_recof4 := ? length(2..2) & { 4, 5 } & * length(3); +template RecOfInt t_recof4_exp := { ?, ?, 4, 5, ?, ?, ? }; + +template RecOfInt t_recof5 := t_recof_op1 & t_recof_op2; +template RecOfInt t_recof5_exp := { 1, 2, 3, 4, 5 }; + +template RecOfInt t_recof6 := t_recof_op1 & t_recof_op3; +template RecOfInt t_recof6_exp := { 1, 2, 3, * }; + +template RecOfInt t_recof7 := t_recof_op3 & t_recof_op1; +template RecOfInt t_recof7_exp := { *, 1, 2, 3 }; + +template RecOfInt t_recof8 := t_recof_op4 & t_recof_op2 & t_recof_op5; +template RecOfInt t_recof8_exp := { ?, ?, 4, 5, ?, ?, ? }; + + +testcase tc_recof_t_w_refs_and_literals() runs on CT { + if (log2str(t_recof1) != log2str(t_recof1_exp)) { + setverdict(fail, "Expected: ", t_recof1_exp, ", got: ", t_recof1); + } + else if (log2str(t_recof2) != log2str(t_recof2_exp)) { + setverdict(fail, "Expected: ", t_recof2_exp, ", got: ", t_recof2); + } + else if (log2str(t_recof3) != log2str(t_recof3_exp)) { + setverdict(fail, "Expected: ", t_recof3_exp, ", got: ", t_recof3); + } + else if (log2str(t_recof4) != log2str(t_recof4_exp)) { + setverdict(fail, "Expected: ", t_recof4_exp, ", got: ", t_recof4); + } + else { + setverdict(pass); + } +} + +testcase tc_recof_t_w_refs() runs on CT { + if (log2str(t_recof5) != log2str(t_recof5_exp)) { + setverdict(fail, "Expected: ", t_recof5_exp, ", got: ", t_recof5); + } + else if (log2str(t_recof6) != log2str(t_recof6_exp)) { + setverdict(fail, "Expected: ", t_recof6_exp, ", got: ", t_recof6); + } + else if (log2str(t_recof7) != log2str(t_recof7_exp)) { + setverdict(fail, "Expected: ", t_recof7_exp, ", got: ", t_recof7); + } + else if (log2str(t_recof8) != log2str(t_recof8_exp)) { + setverdict(fail, "Expected: ", t_recof8_exp, ", got: ", t_recof8); + } + else { + setverdict(pass); + } +} + +testcase tc_recof_vt_w_refs_and_literals() runs on CT { + var template RecOfInt vt_recof1 := t_recof_op1 & { 4, 5 }; + var template RecOfInt vt_recof1_exp := { 1, 2, 3, 4, 5}; + + var template RecOfInt vt_recof2 := t_recof_op1 & ?; + var template RecOfInt vt_recof2_exp := { 1, 2, 3, * }; + + var template RecOfInt vt_recof3 := ? & t_recof_op2; + var template RecOfInt vt_recof3_exp := { *, 4, 5 }; + + var template RecOfInt vt_recof4 := ? length(2..2) & { 4, 5 } & * length(3); + var template RecOfInt vt_recof4_exp := { ?, ?, 4, 5, ?, ?, ? }; + + if (log2str(vt_recof1) != log2str(vt_recof1_exp)) { + setverdict(fail, "Expected: ", vt_recof1_exp, ", got: ", vt_recof1); + } + else if (log2str(vt_recof2) != log2str(vt_recof2_exp)) { + setverdict(fail, "Expected: ", vt_recof2_exp, ", got: ", vt_recof2); + } + else if (log2str(vt_recof3) != log2str(vt_recof3_exp)) { + setverdict(fail, "Expected: ", vt_recof3_exp, ", got: ", vt_recof3); + } + else if (log2str(vt_recof4) != log2str(vt_recof4_exp)) { + setverdict(fail, "Expected: ", vt_recof4_exp, ", got: ", vt_recof4); + } + else { + setverdict(pass); + } +} + +testcase tc_recof_vt_w_refs() runs on CT { + var template RecOfInt vt_recof1 := t_recof_op1 & t_recof_op2; + var template RecOfInt vt_recof1_exp := { 1, 2, 3, 4, 5 }; + + var template RecOfInt vt_recof2 := t_recof_op1 & t_recof_op3; + var template RecOfInt vt_recof2_exp := { 1, 2, 3, * }; + + var template RecOfInt vt_recof3 := t_recof_op3 & t_recof_op1; + var template RecOfInt vt_recof3_exp := { *, 1, 2, 3 }; + + var template RecOfInt vt_recof4 := t_recof_op4 & t_recof_op2 & t_recof_op5; + var template RecOfInt vt_recof4_exp := { ?, ?, 4, 5, ?, ?, ? }; + + if (log2str(vt_recof1) != log2str(vt_recof1_exp)) { + setverdict(fail, "Expected: ", vt_recof1_exp, ", got: ", vt_recof1); + } + else if (log2str(vt_recof2) != log2str(vt_recof2_exp)) { + setverdict(fail, "Expected: ", vt_recof2_exp, ", got: ", vt_recof2); + } + else if (log2str(vt_recof3) != log2str(vt_recof3_exp)) { + setverdict(fail, "Expected: ", vt_recof3_exp, ", got: ", vt_recof3); + } + else if (log2str(vt_recof4) != log2str(vt_recof4_exp)) { + setverdict(fail, "Expected: ", vt_recof4_exp, ", got: ", vt_recof4); + } + else { + setverdict(pass); + } +} + +testcase tc_recof_vt_dbl_any_value() runs on CT { + var template RecOfInt vt_recof1 := ? & ?; + var template RecOfInt vt_recof1_exp := ?; + + var template RecOfInt vt_recof2 := ? & ? & t_recof_op1; + var template RecOfInt vt_recof2_exp := { *, 1, 2, 3 }; + + var template RecOfInt vt_recof3 := t_recof_op3 & ?; + var template RecOfInt vt_recof3_exp := ?; + + var template RecOfInt vt_recof4 := ? & t_recof_op3; + var template RecOfInt vt_recof4_exp := ?; + + if (log2str(vt_recof1) != log2str(vt_recof1_exp)) { + setverdict(fail, "Expected: ", vt_recof1_exp, ", got: ", vt_recof1); + } + else if (log2str(vt_recof2) != log2str(vt_recof2_exp)) { + setverdict(fail, "Expected: ", vt_recof2_exp, ", got: ", vt_recof2); + } + else if (log2str(vt_recof3) != log2str(vt_recof3_exp)) { + setverdict(fail, "Expected: ", vt_recof3_exp, ", got: ", vt_recof3); + } + else if (log2str(vt_recof4) != log2str(vt_recof4_exp)) { + setverdict(fail, "Expected: ", vt_recof4_exp, ", got: ", vt_recof4); + } + else { + setverdict(pass); + } +} + +testcase tc_recof_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, omit, omit, omit, omit, { 9, 8 }, omit }; + + var template RecOfInt vt_recof1 := t_recof_op1 & v_rec.roi; + var template RecOfInt vt_recof1_exp := { 1, 2, 3, 9, 8 }; + + var template RecOfInt vt_recof2 := v_rec.roi & t_recof_op1; + var template RecOfInt vt_recof2_exp := { 9, 8, 1, 2, 3 }; + + var template RecOfInt vt_recof3 := c_recof & v_rec.roi; + var template RecOfInt vt_recof3_exp := { 1, 2, 9, 8 }; + + var template RecOfInt vt_recof4 := v_rec.roi & c_recof; + var template RecOfInt vt_recof4_exp := { 9, 8, 1, 2 }; + + var template RecOfInt vt_recof5 := ? & v_rec.roi; + var template RecOfInt vt_recof5_exp := { *, 9, 8 }; + + var template RecOfInt vt_recof6 := v_rec.roi & ?; + var template RecOfInt vt_recof6_exp := { 9, 8, * }; + + if (log2str(vt_recof1) != log2str(vt_recof1_exp)) { + setverdict(fail, "Expected: ", vt_recof1_exp, ", got: ", vt_recof1); + } + else if (log2str(vt_recof2) != log2str(vt_recof2_exp)) { + setverdict(fail, "Expected: ", vt_recof2_exp, ", got: ", vt_recof2); + } + else if (log2str(vt_recof3) != log2str(vt_recof3_exp)) { + setverdict(fail, "Expected: ", vt_recof3_exp, ", got: ", vt_recof3); + } + else if (log2str(vt_recof4) != log2str(vt_recof4_exp)) { + setverdict(fail, "Expected: ", vt_recof4_exp, ", got: ", vt_recof4); + } + else if (log2str(vt_recof5) != log2str(vt_recof5_exp)) { + setverdict(fail, "Expected: ", vt_recof5_exp, ", got: ", vt_recof5); + } + else if (log2str(vt_recof6) != log2str(vt_recof6_exp)) { + setverdict(fail, "Expected: ", vt_recof6_exp, ", got: ", vt_recof6); + } + else { + setverdict(pass); + } +} + +testcase tc_recof_vt_extra() runs on CT { + var template RecOfInt vt_recof1 := c_recof & { 4, 5 }; + var template RecOfInt vt_recof1_exp := { 1, 2, 4, 5 }; + + var template RecOfInt vt_recof2 := c_recof & ?; + var template RecOfInt vt_recof2_exp := { 1, 2, * }; + + var template RecOfInt vt_recof3 := ? & c_recof; + var template RecOfInt vt_recof3_exp := { *, 1, 2 }; + + if (log2str(vt_recof1) != log2str(vt_recof1_exp)) { + setverdict(fail, "Expected: ", vt_recof1_exp, ", got: ", vt_recof1); + } + else if (log2str(vt_recof2) != log2str(vt_recof2_exp)) { + setverdict(fail, "Expected: ", vt_recof2_exp, ", got: ", vt_recof2); + } + else if (log2str(vt_recof3) != log2str(vt_recof3_exp)) { + setverdict(fail, "Expected: ", vt_recof3_exp, ", got: ", vt_recof3); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_recof_t_w_refs_and_literals()); + execute(tc_recof_t_w_refs()); + execute(tc_recof_vt_w_refs_and_literals()); + execute(tc_recof_vt_w_refs()); + execute(tc_recof_vt_dbl_any_value()); + execute(tc_recof_vt_w_opt_fields()); + execute(tc_recof_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatSetof.ttcn b/regression_test/templateConcat/TemplateConcatSetof.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..cf9d7121d2aedf1da334a9a75e9f587d1eb11654 --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatSetof.ttcn @@ -0,0 +1,255 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating set of templates +module TemplateConcatSetof { + +import from Types all; + +const SetOfInt c_setof := { 1, 2 }; + +template SetOfInt t_setof_op1 := { 1, 2, 3 }; +template SetOfInt t_setof_op2 := { 4, 5 }; +template SetOfInt t_setof_op3 := ?; +template SetOfInt t_setof_op4 := ? length(2..2); +template SetOfInt t_setof_op5 := * length(3); + +template SetOfInt t_setof1 := t_setof_op1 & { 4, 5 }; +template SetOfInt t_setof1_exp := { 1, 2, 3, 4, 5}; + +template SetOfInt t_setof2 := t_setof_op1 & ?; +template SetOfInt t_setof2_exp := { 1, 2, 3, * }; + +template SetOfInt t_setof3 := ? & t_setof_op2; +template SetOfInt t_setof3_exp := { *, 4, 5 }; + +template SetOfInt t_setof4 := ? length(2..2) & { 4, 5 } & * length(3); +template SetOfInt t_setof4_exp := { ?, ?, 4, 5, ?, ?, ? }; + +template SetOfInt t_setof5 := t_setof_op1 & t_setof_op2; +template SetOfInt t_setof5_exp := { 1, 2, 3, 4, 5 }; + +template SetOfInt t_setof6 := t_setof_op1 & t_setof_op3; +template SetOfInt t_setof6_exp := { 1, 2, 3, * }; + +template SetOfInt t_setof7 := t_setof_op3 & t_setof_op1; +template SetOfInt t_setof7_exp := { *, 1, 2, 3 }; + +template SetOfInt t_setof8 := t_setof_op4 & t_setof_op2 & t_setof_op5; +template SetOfInt t_setof8_exp := { ?, ?, 4, 5, ?, ?, ? }; + + +testcase tc_setof_t_w_refs_and_literals() runs on CT { + if (log2str(t_setof1) != log2str(t_setof1_exp)) { + setverdict(fail, "Expected: ", t_setof1_exp, ", got: ", t_setof1); + } + else if (log2str(t_setof2) != log2str(t_setof2_exp)) { + setverdict(fail, "Expected: ", t_setof2_exp, ", got: ", t_setof2); + } + else if (log2str(t_setof3) != log2str(t_setof3_exp)) { + setverdict(fail, "Expected: ", t_setof3_exp, ", got: ", t_setof3); + } + else if (log2str(t_setof4) != log2str(t_setof4_exp)) { + setverdict(fail, "Expected: ", t_setof4_exp, ", got: ", t_setof4); + } + else { + setverdict(pass); + } +} + +testcase tc_setof_t_w_refs() runs on CT { + if (log2str(t_setof5) != log2str(t_setof5_exp)) { + setverdict(fail, "Expected: ", t_setof5_exp, ", got: ", t_setof5); + } + else if (log2str(t_setof6) != log2str(t_setof6_exp)) { + setverdict(fail, "Expected: ", t_setof6_exp, ", got: ", t_setof6); + } + else if (log2str(t_setof7) != log2str(t_setof7_exp)) { + setverdict(fail, "Expected: ", t_setof7_exp, ", got: ", t_setof7); + } + else if (log2str(t_setof8) != log2str(t_setof8_exp)) { + setverdict(fail, "Expected: ", t_setof8_exp, ", got: ", t_setof8); + } + else { + setverdict(pass); + } +} + +testcase tc_setof_vt_w_refs_and_literals() runs on CT { + var template SetOfInt vt_setof1 := t_setof_op1 & { 4, 5 }; + var template SetOfInt vt_setof1_exp := { 1, 2, 3, 4, 5}; + + var template SetOfInt vt_setof2 := t_setof_op1 & ?; + var template SetOfInt vt_setof2_exp := { 1, 2, 3, * }; + + var template SetOfInt vt_setof3 := ? & t_setof_op2; + var template SetOfInt vt_setof3_exp := { *, 4, 5 }; + + var template SetOfInt vt_setof4 := ? length(2..2) & { 4, 5 } & * length(3); + var template SetOfInt vt_setof4_exp := { ?, ?, 4, 5, ?, ?, ? }; + + if (log2str(vt_setof1) != log2str(vt_setof1_exp)) { + setverdict(fail, "Expected: ", vt_setof1_exp, ", got: ", vt_setof1); + } + else if (log2str(vt_setof2) != log2str(vt_setof2_exp)) { + setverdict(fail, "Expected: ", vt_setof2_exp, ", got: ", vt_setof2); + } + else if (log2str(vt_setof3) != log2str(vt_setof3_exp)) { + setverdict(fail, "Expected: ", vt_setof3_exp, ", got: ", vt_setof3); + } + else if (log2str(vt_setof4) != log2str(vt_setof4_exp)) { + setverdict(fail, "Expected: ", vt_setof4_exp, ", got: ", vt_setof4); + } + else { + setverdict(pass); + } +} + +testcase tc_setof_vt_w_refs() runs on CT { + var template SetOfInt vt_setof1 := t_setof_op1 & t_setof_op2; + var template SetOfInt vt_setof1_exp := { 1, 2, 3, 4, 5 }; + + var template SetOfInt vt_setof2 := t_setof_op1 & t_setof_op3; + var template SetOfInt vt_setof2_exp := { 1, 2, 3, * }; + + var template SetOfInt vt_setof3 := t_setof_op3 & t_setof_op1; + var template SetOfInt vt_setof3_exp := { *, 1, 2, 3 }; + + var template SetOfInt vt_setof4 := t_setof_op4 & t_setof_op2 & t_setof_op5; + var template SetOfInt vt_setof4_exp := { ?, ?, 4, 5, ?, ?, ? }; + + if (log2str(vt_setof1) != log2str(vt_setof1_exp)) { + setverdict(fail, "Expected: ", vt_setof1_exp, ", got: ", vt_setof1); + } + else if (log2str(vt_setof2) != log2str(vt_setof2_exp)) { + setverdict(fail, "Expected: ", vt_setof2_exp, ", got: ", vt_setof2); + } + else if (log2str(vt_setof3) != log2str(vt_setof3_exp)) { + setverdict(fail, "Expected: ", vt_setof3_exp, ", got: ", vt_setof3); + } + else if (log2str(vt_setof4) != log2str(vt_setof4_exp)) { + setverdict(fail, "Expected: ", vt_setof4_exp, ", got: ", vt_setof4); + } + else { + setverdict(pass); + } +} + +testcase tc_setof_vt_dbl_any_value() runs on CT { + var template SetOfInt vt_setof1 := ? & ?; + var template SetOfInt vt_setof1_exp := ?; + + var template SetOfInt vt_setof2 := ? & ? & t_setof_op1; + var template SetOfInt vt_setof2_exp := { *, 1, 2, 3 }; + + var template SetOfInt vt_setof3 := t_setof_op3 & ?; + var template SetOfInt vt_setof3_exp := ?; + + var template SetOfInt vt_setof4 := ? & t_setof_op3; + var template SetOfInt vt_setof4_exp := ?; + + if (log2str(vt_setof1) != log2str(vt_setof1_exp)) { + setverdict(fail, "Expected: ", vt_setof1_exp, ", got: ", vt_setof1); + } + else if (log2str(vt_setof2) != log2str(vt_setof2_exp)) { + setverdict(fail, "Expected: ", vt_setof2_exp, ", got: ", vt_setof2); + } + else if (log2str(vt_setof3) != log2str(vt_setof3_exp)) { + setverdict(fail, "Expected: ", vt_setof3_exp, ", got: ", vt_setof3); + } + else if (log2str(vt_setof4) != log2str(vt_setof4_exp)) { + setverdict(fail, "Expected: ", vt_setof4_exp, ", got: ", vt_setof4); + } + else { + setverdict(pass); + } +} + +testcase tc_setof_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, omit, omit, omit, omit, omit, { 9, 8 } }; + + var template SetOfInt vt_setof1 := t_setof_op1 & v_rec.soi; + var template SetOfInt vt_setof1_exp := { 1, 2, 3, 9, 8 }; + + var template SetOfInt vt_setof2 := v_rec.soi & t_setof_op1; + var template SetOfInt vt_setof2_exp := { 9, 8, 1, 2, 3 }; + + var template SetOfInt vt_setof3 := c_setof & v_rec.soi; + var template SetOfInt vt_setof3_exp := { 1, 2, 9, 8 }; + + var template SetOfInt vt_setof4 := v_rec.soi & c_setof; + var template SetOfInt vt_setof4_exp := { 9, 8, 1, 2 }; + + var template SetOfInt vt_setof5 := ? & v_rec.soi; + var template SetOfInt vt_setof5_exp := { *, 9, 8 }; + + var template SetOfInt vt_setof6 := v_rec.soi & ?; + var template SetOfInt vt_setof6_exp := { 9, 8, * }; + + if (log2str(vt_setof1) != log2str(vt_setof1_exp)) { + setverdict(fail, "Expected: ", vt_setof1_exp, ", got: ", vt_setof1); + } + else if (log2str(vt_setof2) != log2str(vt_setof2_exp)) { + setverdict(fail, "Expected: ", vt_setof2_exp, ", got: ", vt_setof2); + } + else if (log2str(vt_setof3) != log2str(vt_setof3_exp)) { + setverdict(fail, "Expected: ", vt_setof3_exp, ", got: ", vt_setof3); + } + else if (log2str(vt_setof4) != log2str(vt_setof4_exp)) { + setverdict(fail, "Expected: ", vt_setof4_exp, ", got: ", vt_setof4); + } + else if (log2str(vt_setof5) != log2str(vt_setof5_exp)) { + setverdict(fail, "Expected: ", vt_setof5_exp, ", got: ", vt_setof5); + } + else if (log2str(vt_setof6) != log2str(vt_setof6_exp)) { + setverdict(fail, "Expected: ", vt_setof6_exp, ", got: ", vt_setof6); + } + else { + setverdict(pass); + } +} + +testcase tc_setof_vt_extra() runs on CT { + var template SetOfInt vt_setof1 := c_setof & { 4, 5 }; + var template SetOfInt vt_setof1_exp := { 1, 2, 4, 5 }; + + var template SetOfInt vt_setof2 := c_setof & ?; + var template SetOfInt vt_setof2_exp := { 1, 2, * }; + + var template SetOfInt vt_setof3 := ? & c_setof; + var template SetOfInt vt_setof3_exp := { *, 1, 2 }; + + if (log2str(vt_setof1) != log2str(vt_setof1_exp)) { + setverdict(fail, "Expected: ", vt_setof1_exp, ", got: ", vt_setof1); + } + else if (log2str(vt_setof2) != log2str(vt_setof2_exp)) { + setverdict(fail, "Expected: ", vt_setof2_exp, ", got: ", vt_setof2); + } + else if (log2str(vt_setof3) != log2str(vt_setof3_exp)) { + setverdict(fail, "Expected: ", vt_setof3_exp, ", got: ", vt_setof3); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_setof_t_w_refs_and_literals()); + execute(tc_setof_t_w_refs()); + execute(tc_setof_vt_w_refs_and_literals()); + execute(tc_setof_vt_w_refs()); + execute(tc_setof_vt_dbl_any_value()); + execute(tc_setof_vt_w_opt_fields()); + execute(tc_setof_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/TemplateConcatUnichar.ttcn b/regression_test/templateConcat/TemplateConcatUnichar.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..9467a69d30568d1ca8c9905e914398c0fa625070 --- /dev/null +++ b/regression_test/templateConcat/TemplateConcatUnichar.ttcn @@ -0,0 +1,178 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ + +// This module contains tests for concatenating universal charstring templates +module TemplateConcatUnichar { + +import from Types all; + +const universal charstring c_unichar := char(0, 1, 2, 3); + +template universal charstring t_unichar := char(0, 0, 1, 2); + +// there is no other way to recreate these universal charstring templates, than concatenation, +// so use constants and variable for the expected values +template universal charstring t_unichar1 := char(0, 1, 2, 3) & char(0, 0, 1, 2); +const universal charstring c_unichar1_exp := char(0, 1, 2, 3) & char(0, 0, 1, 2); + +template universal charstring t_unichar2 := c_unichar & char(0, 0, 1, 2); +const universal charstring c_unichar2_exp := char(0, 1, 2, 3) & char(0, 0, 1, 2); + +template universal charstring t_unichar3 := t_unichar & char(0, 0, 0, 241); +const universal charstring c_unichar3_exp := char(0, 0, 1, 2) & char(0, 0, 0, 241); + +template universal charstring t_unichar4 := char(0, 0, 1, 117) & t_unichar & char(0, 0, 1, 117); +const universal charstring c_unichar4_exp := char(0, 0, 1, 117) & char(0, 0, 1, 2) & char(0, 0, 1, 117); + + +testcase tc_unichar_t_values() runs on CT { + if (log2str(t_unichar1) != log2str(c_unichar1_exp)) { + setverdict(fail, "Expected: ", c_unichar1_exp, ", got: ", t_unichar1); + } + else if (log2str(t_unichar2) != log2str(c_unichar2_exp)) { + setverdict(fail, "Expected: ", c_unichar2_exp, ", got: ", t_unichar2); + } + else if (log2str(t_unichar3) != log2str(c_unichar3_exp)) { + setverdict(fail, "Expected: ", c_unichar3_exp, ", got: ", t_unichar3); + } + else if (log2str(t_unichar4) != log2str(c_unichar4_exp)) { + setverdict(fail, "Expected: ", c_unichar4_exp, ", got: ", t_unichar4); + } + else { + setverdict(pass); + } +} + +testcase tc_unichar_vt_values() runs on CT { + var template universal charstring vt_unichar1 := char(0, 1, 2, 3) & char(0, 0, 1, 2); + var universal charstring v_unichar1_exp := char(0, 1, 2, 3) & char(0, 0, 1, 2); + + var template universal charstring vt_unichar2 := c_unichar & char(0, 0, 1, 2); + var universal charstring v_unichar2_exp := char(0, 1, 2, 3) & char(0, 0, 1, 2); + + var template universal charstring vt_unichar3 := t_unichar & char(0, 0, 0, 241); + var universal charstring v_unichar3_exp := char(0, 0, 1, 2) & char(0, 0, 0, 241); + + var template universal charstring vt_unichar4 := char(0, 0, 1, 117) & t_unichar & char(0, 0, 1, 117); + var universal charstring v_unichar4_exp := char(0, 0, 1, 117) & char(0, 0, 1, 2) & char(0, 0, 1, 117); + + if (log2str(vt_unichar1) != log2str(v_unichar1_exp)) { + setverdict(fail, "Expected: ", v_unichar1_exp, ", got: ", vt_unichar1); + } + else if (log2str(vt_unichar2) != log2str(v_unichar2_exp)) { + setverdict(fail, "Expected: ", v_unichar2_exp, ", got: ", vt_unichar2); + } + else if (log2str(vt_unichar3) != log2str(v_unichar3_exp)) { + setverdict(fail, "Expected: ", v_unichar3_exp, ", got: ", vt_unichar3); + } + else if (log2str(vt_unichar4) != log2str(v_unichar4_exp)) { + setverdict(fail, "Expected: ", v_unichar4_exp, ", got: ", vt_unichar4); + } + else { + setverdict(pass); + } +} + +testcase tc_unichar_vt_w_str_elem() runs on CT { + var universal charstring v_unichar := "xyz"; + + var template universal charstring vt_unichar1 := t_unichar & v_unichar[2]; + var universal charstring v_unichar1_exp := char(0, 0, 1, 2) & "z"; + + var template universal charstring vt_unichar2 := v_unichar[2] & t_unichar; + var universal charstring v_unichar2_exp := "z" & char(0, 0, 1, 2); + + var template universal charstring vt_unichar3 := char(0, 1, 2, 3) & v_unichar[1]; + var universal charstring v_unichar3_exp := char(0, 1, 2, 3) & "y"; + + var template universal charstring vt_unichar4 := v_unichar[1] & char(0, 1, 2, 3); + var universal charstring v_unichar4_exp := "y" & char(0, 1, 2, 3); + + if (log2str(vt_unichar1) != log2str(v_unichar1_exp)) { + setverdict(fail, "Expected: ", v_unichar1_exp, ", got: ", vt_unichar1); + } + else if (log2str(vt_unichar2) != log2str(v_unichar2_exp)) { + setverdict(fail, "Expected: ", v_unichar2_exp, ", got: ", vt_unichar2); + } + else if (log2str(vt_unichar3) != log2str(v_unichar3_exp)) { + setverdict(fail, "Expected: ", v_unichar3_exp, ", got: ", vt_unichar3); + } + else if (log2str(vt_unichar4) != log2str(v_unichar4_exp)) { + setverdict(fail, "Expected: ", v_unichar4_exp, ", got: ", vt_unichar4); + } + else { + setverdict(pass); + } +} + +testcase tc_unichar_vt_w_opt_fields() runs on CT { + var Rec v_rec := { omit, omit, omit, "aeiou", omit, omit, omit }; + + var template universal charstring vt_unichar1 := t_unichar & v_rec.cs; + var universal charstring v_unichar1_exp := char(0, 0, 1, 2) & "aeiou"; + + var template universal charstring vt_unichar2 := v_rec.cs & t_unichar; + var universal charstring v_unichar2_exp := "aeiou" & char(0, 0, 1, 2); + + var template universal charstring vt_unichar3 := char(0, 0, 1, 117) & v_rec.cs; + var universal charstring v_unichar3_exp := char(0, 0, 1, 117) & "aeiou"; + + var template universal charstring vt_unichar4 := v_rec.cs & char(0, 0, 1, 117); + var universal charstring v_unichar4_exp := "aeiou" & char(0, 0, 1, 117); + + if (log2str(vt_unichar1) != log2str(v_unichar1_exp)) { + setverdict(fail, "Expected: ", v_unichar1_exp, ", got: ", vt_unichar1); + } + else if (log2str(vt_unichar2) != log2str(v_unichar2_exp)) { + setverdict(fail, "Expected: ", v_unichar2_exp, ", got: ", vt_unichar2); + } + else if (log2str(vt_unichar3) != log2str(v_unichar3_exp)) { + setverdict(fail, "Expected: ", v_unichar3_exp, ", got: ", vt_unichar3); + } + else if (log2str(vt_unichar4) != log2str(v_unichar4_exp)) { + setverdict(fail, "Expected: ", v_unichar4_exp, ", got: ", vt_unichar4); + } + else { + setverdict(pass); + } +} + +testcase tc_unichar_vt_extra() runs on CT { + var universal charstring v_unichar := "xyz"; + var Rec v_rec := { omit, omit, omit, "aeiou", omit, omit, omit }; + + var template universal charstring vt_unichar1 := v_unichar[0] & v_rec.cs; + var universal charstring v_unichar1_exp := "xaeiou"; + + var template universal charstring vt_unichar2 := v_rec.cs & v_unichar[0]; + var universal charstring v_unichar2_exp := "aeioux"; + + if (log2str(vt_unichar1) != log2str(v_unichar1_exp)) { + setverdict(fail, "Expected: ", v_unichar1_exp, ", got: ", vt_unichar1); + } + else if (log2str(vt_unichar2) != log2str(v_unichar2_exp)) { + setverdict(fail, "Expected: ", v_unichar2_exp, ", got: ", vt_unichar2); + } + else { + setverdict(pass); + } +} + +control { + execute(tc_unichar_t_values()); + execute(tc_unichar_vt_values()); + execute(tc_unichar_vt_w_str_elem()); + execute(tc_unichar_vt_w_opt_fields()); + execute(tc_unichar_vt_extra()); +} + +} diff --git a/regression_test/templateConcat/Types.ttcn b/regression_test/templateConcat/Types.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..db28bd0e0958e8b95fa5eb55ea36eac7a2b9e828 --- /dev/null +++ b/regression_test/templateConcat/Types.ttcn @@ -0,0 +1,31 @@ +/****************************************************************************** + * 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 Types { + +type record of integer RecOfInt; + +type set of integer SetOfInt; + +type record Rec { + octetstring os optional, + hexstring hs optional, + bitstring bs optional, + charstring cs optional, + universal charstring ucs optional, + RecOfInt roi optional, + SetOfInt soi optional +} + +type component CT {} + +} diff --git a/regression_test/templateConcat/config.cfg b/regression_test/templateConcat/config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..945952eb4d15b26b6926fa639e78e23ebb3c743f --- /dev/null +++ b/regression_test/templateConcat/config.cfg @@ -0,0 +1,32 @@ +############################################################################### +# 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_PARAMETERS] +[LOGGING] +LogFile := "templateConcat.log" +FileMask := LOG_ALL | DEBUG | MATCHING +ConsoleMask := ERROR | WARNING | TESTCASE | STATISTICS | PORTEVENT +LogSourceInfo := Yes +AppendFile := No +TimeStampFormat := DateTime +LogEventTypes := Yes +SourceInfoFormat := Single +LogEntityName := Yes + +[EXECUTE] +TemplateConcatOct +TemplateConcatHex +TemplateConcatBit +TemplateConcatChar +TemplateConcatUnichar +TemplateConcatMixed +TemplateConcatRecof +TemplateConcatSetof diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index fa672711a88cc9941c948046c1fdff2e87621ea7..2462211d5907da75d408eaaadb448e8ef8cf05ad 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ