From 1d0599f0593976056a5de9d6972e203249e52ceb Mon Sep 17 00:00:00 2001 From: ebensza Date: Thu, 21 Apr 2016 14:45:23 +0200 Subject: [PATCH] added encvalue_unichar and decvalue_unichar built in functions (artf725502) Signed-off-by: ebensza --- compiler2/Value.cc | 413 +++++++++++++++++- compiler2/Value.hh | 17 +- compiler2/ttcn3/compiler.l | 2 + compiler2/ttcn3/compiler.y | 39 ++ .../ucharstrOper/EncDecvalueUnichar.ttcn | 142 ++++++ regression_test/ucharstrOper/Makefile | 2 +- regression_test/ucharstrOper/config.cfg | 1 + 7 files changed, 602 insertions(+), 14 deletions(-) create mode 100644 regression_test/ucharstrOper/EncDecvalueUnichar.ttcn diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 72e85de..3fb3b98 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -21,6 +21,7 @@ * Ormandi, Matyas * Raduly, Csaba * Szabados, Kristof + * Szabo, Bence Janos * Szabo, Janos Zoltan – initial implementation * Szalai, Gabor * Tatarka, Gabor @@ -278,6 +279,15 @@ namespace Common { case OPTYPE_TTCN2STRING: u.expr.ti1=p.u.expr.ti1->clone(); break; + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + u.expr.ti1=p.u.expr.ti1->clone(); + u.expr.v2=p.u.expr.v2?p.u.expr.v2->clone():0; + break; + case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] + u.expr.r1 = p.u.expr.r1->clone(); + u.expr.r2 = p.u.expr.r2->clone(); + u.expr.v3=p.u.expr.v3?p.u.expr.v3->clone():0; + break; case OPTYPE_UNDEF_RUNNING: case OPTYPE_TMR_READ: case OPTYPE_TMR_RUNNING: @@ -581,6 +591,15 @@ namespace Common { case OPTYPE_TTCN2STRING: delete u.expr.ti1; break; + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + delete u.expr.ti1; + delete u.expr.v2; + break; + case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] + delete u.expr.r1; + delete u.expr.r2; + delete u.expr.v3; + break; case OPTYPE_UNDEF_RUNNING: case OPTYPE_TMR_READ: case OPTYPE_TMR_RUNNING: @@ -909,6 +928,7 @@ namespace Common { case OPTYPE_ISVALUE: case OPTYPE_ISBOUND: case OPTYPE_ENCODE: + case OPTYPE_ENCVALUE_UNICHAR: case OPTYPE_ISPRESENT: case OPTYPE_TTCN2STRING: if(!p_ti1) FATAL_ERROR("Value::Value()"); @@ -1094,12 +1114,29 @@ namespace Common { u.expr.v1=p_v1; u.expr.v2=p_v2; u.expr.v3=p_v3; - break; + break; default: FATAL_ERROR("Value::Value()"); } // switch } + // ti1 [v2] + Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2) + : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0) + { + u.expr.v_optype = p_optype; + u.expr.state = EXPR_NOT_CHECKED; + switch(p_optype) { + case OPTYPE_ENCVALUE_UNICHAR: + if(!p_ti1 || !p_v2) FATAL_ERROR("Value::Value()"); + u.expr.ti1=p_ti1; + u.expr.v2=p_v2; + break; + default: + FATAL_ERROR("Value::Value()"); + } // switch + } + // ti1 v2 v3 Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2, Value *p_v3) : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0) @@ -1275,6 +1312,7 @@ namespace Common { u.expr.state = EXPR_NOT_CHECKED; switch(p_optype) { case OPTYPE_DECODE: + case OPTYPE_DECVALUE_UNICHAR: if(!p_r1 || !p_r2) FATAL_ERROR("Value::Value()"); u.expr.r1=p_r1; u.expr.r2=p_r2; @@ -1283,6 +1321,25 @@ namespace Common { FATAL_ERROR("Value::Value()"); } // switch } + + // r1 r2 [v3] + Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2, + Value *p_v3) + : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0) + { + u.expr.v_optype = p_optype; + u.expr.state = EXPR_NOT_CHECKED; + switch(p_optype) { + case OPTYPE_DECVALUE_UNICHAR: + if(!p_r1 || !p_r2 || !p_v3) FATAL_ERROR("Value::Value()"); + u.expr.r1=p_r1; + u.expr.r2=p_r2; + u.expr.v3=p_v3; + break; + default: + FATAL_ERROR("Value::Value()"); + } // switch + } Value::~Value() { @@ -1528,6 +1585,14 @@ namespace Common { case OPTYPE_TTCN2STRING: u.expr.ti1->set_fullname(p_fullname+"."); break; + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + u.expr.ti1->set_fullname(p_fullname+"."); + if (u.expr.v2) u.expr.v2->set_fullname(p_fullname+"."); + break; + case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] + u.expr.r1->set_fullname(p_fullname+"."); + u.expr.r2->set_fullname(p_fullname+"."); + if (u.expr.v3) u.expr.v3->set_fullname(p_fullname+"."); case OPTYPE_UNDEF_RUNNING: // r1 case OPTYPE_TMR_READ: case OPTYPE_TMR_RUNNING: @@ -1708,6 +1773,15 @@ namespace Common { case OPTYPE_TTCN2STRING: u.expr.ti1->set_my_scope(p_scope); break; + case OPTYPE_ENCVALUE_UNICHAR: //ti1 [v2] + u.expr.ti1->set_my_scope(p_scope); + if(u.expr.v2) u.expr.v2->set_my_scope(p_scope); + break; + case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] + u.expr.r1->set_my_scope(p_scope); + u.expr.r2->set_my_scope(p_scope); + if(u.expr.v3) u.expr.v3->set_my_scope(p_scope); + break; case OPTYPE_UNDEF_RUNNING: // r1 case OPTYPE_TMR_READ: case OPTYPE_TMR_RUNNING: @@ -2018,6 +2092,15 @@ namespace Common { case OPTYPE_TTCN2STRING: u.expr.ti1->set_code_section(p_code_section); break; + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + u.expr.ti1->set_code_section(p_code_section); + if (u.expr.v2) u.expr.v2->set_code_section(p_code_section); + break; + case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] + u.expr.r1->set_code_section(p_code_section); + u.expr.r2->set_code_section(p_code_section); + if (u.expr.v3) u.expr.v3->set_code_section(p_code_section); + break; case OPTYPE_UNDEF_RUNNING: // r1 case OPTYPE_TMR_READ: case OPTYPE_TMR_RUNNING: @@ -3029,6 +3112,7 @@ namespace Common { case OPTYPE_SIZEOF: case OPTYPE_DECODE: case OPTYPE_ENUM2INT: + case OPTYPE_DECVALUE_UNICHAR: return Type::T_INT; case OPTYPE_BIT2STR: case OPTYPE_FLOAT2STR: @@ -3046,6 +3130,7 @@ namespace Common { return Type::T_CSTR; case OPTYPE_INT2UNICHAR: case OPTYPE_OCT2UNICHAR: + case OPTYPE_ENCVALUE_UNICHAR: return Type::T_USTR; case OPTYPE_INT2BIT: case OPTYPE_HEX2BIT: @@ -3446,6 +3531,10 @@ namespace Common { return "int2oct()"; case OPTYPE_OCT2UNICHAR: return "oct2unichar()"; + case OPTYPE_ENCVALUE_UNICHAR: + return "encvalue_unichar()"; + case OPTYPE_DECVALUE_UNICHAR: + return "decvalue_unichar()"; case OPTYPE_SUBSTR: return "substr()"; case OPTYPE_REGEXP: @@ -5331,7 +5420,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, error("Cannot determine type of value"); goto error; } - + // todo: fix this /*if (u.expr.par1_is_value && u.expr.v1->get_valuetype() != V_REFD) { error("Expecting a value of a type with coding attributes in first" @@ -5343,7 +5432,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, if(!disable_attribute_validation()) { t_type->chk_coding(true); } - + switch (t_type->get_typetype()) { case Type::T_UNDEF: case Type::T_ERROR: @@ -5370,9 +5459,9 @@ error: set_valuetype(V_ERROR); } - void Value::chk_expr_operands_decode() + void Value::chk_expr_operands_decode(operationtype_t p_optype) { - Error_Context cntxt(this, "In the parameters of decvalue()"); + Error_Context cntxt(this, "In the parameters of decvalue()"); //todo Ttcn::Ref_base* ref = u.expr.r1; Ttcn::FieldOrArrayRefs* t_subrefs = ref->get_subrefs(); Type* t_type = 0; @@ -5426,9 +5515,22 @@ error: if (!t_type) { goto error; } - if (t_type->get_type_refd_last()->get_typetype() != Type::T_BSTR){ - error("First parameter has to be a bitstring"); - goto error; + switch(p_optype) { + case OPTYPE_DECODE: + if (t_type->get_type_refd_last()->get_typetype() != Type::T_BSTR){ + error("First parameter has to be a bitstring"); + goto error; + } + break; + case OPTYPE_DECVALUE_UNICHAR: + if (t_type->get_type_refd_last()->get_typetype() != Type::T_USTR){ + error("First parameter has to be a universal charstring"); + goto error; + } + break; + default: + FATAL_ERROR("Value::chk_expr_decode_operands()"); + break; } ref = u.expr.r2; @@ -6471,6 +6573,30 @@ error: chk_expr_eval_value(v2, t_chk, refch, exp_val); } break; + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + chk_expr_operand_encode(refch, exp_val); + v2=u.expr.v2 ? u.expr.v2 : 0; + if (v2) + { + Error_Context cntxt(this, "In the second operand of operation `%s'", opname); + v2->set_lowerid_to_ref(); + tt2=v2->get_expr_returntype(exp_val); + chk_expr_operandtype_charstr(tt2, second, opname, v2); + chk_expr_eval_value(v2, t_chk, refch, exp_val); + } + break; + case OPTYPE_DECVALUE_UNICHAR: + chk_expr_operands_decode(OPTYPE_DECVALUE_UNICHAR); + v3=u.expr.v3 ? u.expr.v3 : 0; + if (v3) + { + Error_Context cntxt(this, "In the thrid operand of operation `%s'", opname); + v3->set_lowerid_to_ref(); + tt3=v3->get_expr_returntype(exp_val); + chk_expr_operandtype_charstr(tt3, third, opname, v3); + chk_expr_eval_value(v3, t_chk, refch, exp_val); + } + break; case OPTYPE_ADD: // v1 v2 case OPTYPE_SUBTRACT: case OPTYPE_MULTIPLY: @@ -6752,7 +6878,7 @@ error: chk_expr_operands_int2binstr(); break; case OPTYPE_DECODE: - chk_expr_operands_decode(); + chk_expr_operands_decode(OPTYPE_DECODE); break; case OPTYPE_SUBSTR: { @@ -7067,6 +7193,8 @@ error: case OPTYPE_OCT2UNICHAR: case OPTYPE_ENCODE_BASE64: case OPTYPE_DECODE_BASE64: + case OPTYPE_ENCVALUE_UNICHAR: + case OPTYPE_DECVALUE_UNICHAR: break; case OPTYPE_TESTCASENAME: { // - if (!my_scope) FATAL_ERROR("Value::evaluate_value()"); @@ -8363,6 +8491,8 @@ error: case OPTYPE_UNICHAR2OCT: case OPTYPE_ENCODE_BASE64: case OPTYPE_DECODE_BASE64: + case OPTYPE_ENCVALUE_UNICHAR: + case OPTYPE_DECVALUE_UNICHAR: return true; case OPTYPE_COMP_NULL: // - return false; @@ -9682,6 +9812,25 @@ error: u.expr.ti1->chk_recursions(refch); refch.prev_state(); break; + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + refch.mark_state(); + u.expr.ti1->chk_recursions(refch); + refch.prev_state(); + if (u.expr.v2){ + refch.mark_state(); + u.expr.v2->chk_recursions(refch); + refch.prev_state(); + } + break; + case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] + chk_recursions_expr_decode(u.expr.r1, refch); + chk_recursions_expr_decode(u.expr.r2, refch); + if (u.expr.v3){ + refch.mark_state(); + u.expr.v3->chk_recursions(refch); + refch.prev_state(); + } + break; case OPTYPE_MATCH: // v1 t2 refch.mark_state(); u.expr.v1->chk_recursions(refch); @@ -9973,7 +10122,16 @@ error: case OPTYPE_TTCN2STRING: self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs); break; - + case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] + self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs); + if (u.expr.v2) self_ref |= chk_expr_self_ref_val(u.expr.v2, lhs); + break; + case OPTYPE_DECVALUE_UNICHAR: { // r1 r2 [v3] + Common::Assignment *ass = u.expr.r2->get_refd_assignment(); + self_ref |= (ass == lhs); + if (u.expr.v3) self_ref |= chk_expr_self_ref_val(u.expr.v3, lhs); + goto label_r1; + break; } case OPTYPE_COMP_CREATE: // r1 [v2] [v3] b4 // component.create -- assume no self-ref case OPTYPE_ACTIVATE: // r1 @@ -10277,6 +10435,24 @@ error: if (u.expr.v2) return create_stringRepr_predef2("unichar2oct"); else return create_stringRepr_predef1("unichar2oct"); } + case OPTYPE_ENCVALUE_UNICHAR: { + if (u.expr.v2) return create_stringRepr_predef2("encvalue_unichar"); + else return create_stringRepr_predef1("encvalue_unichar"); + } + case OPTYPE_DECVALUE_UNICHAR: { + if (u.expr.v3) { + string ret_val("decvalue_unichar"); + ret_val += '('; + ret_val += u.expr.v1->get_stringRepr(); + ret_val += ", "; + ret_val += u.expr.v2->get_stringRepr(); + ret_val += ", "; + ret_val += u.expr.v3->get_stringRepr(); + ret_val += ')'; + return ret_val; + } + else return create_stringRepr_predef2("decvalue_unichar"); + } case OPTYPE_STR2BIT: return create_stringRepr_predef1("str2bit"); case OPTYPE_STR2FLOAT: @@ -10655,7 +10831,7 @@ error: { string ret_val(function_name); ret_val += '('; - if (u.expr.v_optype == OPTYPE_ENCODE) { // ti1, not v1 + if (u.expr.v_optype == OPTYPE_ENCODE || u.expr.v_optype == OPTYPE_ENCVALUE_UNICHAR) { // ti1, not v1 ret_val += u.expr.ti1->get_specific_value()->get_stringRepr(); } else ret_val += u.expr.v1->get_stringRepr(); @@ -11272,6 +11448,20 @@ error: case OPTYPE_TTCN2STRING: str = u.expr.ti1->rearrange_init_code(str, usage_mod); break; + case OPTYPE_ENCVALUE_UNICHAR: + str = u.expr.ti1->rearrange_init_code(str, usage_mod); + if (u.expr.v2) str = u.expr.v2->rearrange_init_code(str, usage_mod); + break; + case OPTYPE_DECVALUE_UNICHAR: { + Ttcn::ActualParList *parlist = u.expr.r1->get_parlist(); + Common::Assignment *ass = u.expr.r1->get_refd_assignment(); + if (parlist) str = parlist->rearrange_init_code(str, usage_mod); + + parlist = u.expr.r2->get_parlist(); + ass = u.expr.r2->get_refd_assignment(); + if (parlist) str = parlist->rearrange_init_code(str, usage_mod); + if (u.expr.v3) str = u.expr.v3->rearrange_init_code(str, usage_mod); + break; } case OPTYPE_ISCHOSEN_T: str = u.expr.t1->rearrange_init_code(str, usage_mod); break; @@ -11496,6 +11686,12 @@ error: else generate_code_expr_predef1(expr, "unichar2oct", u.expr.v1); break; + case OPTYPE_ENCVALUE_UNICHAR: + generate_code_expr_encvalue_unichar(expr); + break; + case OPTYPE_DECVALUE_UNICHAR: + generate_code_expr_decvalue_unichar(expr); + break; case OPTYPE_OCT2HEX: generate_code_expr_predef1(expr, "oct2hex", u.expr.v1); break; @@ -12346,7 +12542,7 @@ error: is_templ ? ".valueof()" : ""); Code::free_expr(&expr2); } - + void Value::generate_code_expr_decode(expression_struct *expr) { expression_struct expr1, expr2; @@ -12431,6 +12627,197 @@ error: Code::free_expr(&expr1); Code::free_expr(&expr2); } + +void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) + { + Value* v1 = 0; + + Template* templ = u.expr.ti1->get_Template()->get_template_refd_last(); + if (templ->get_templatetype() == Template::SPECIFIC_VALUE) + v1 = templ->get_specific_value(); + Type* gov_last = templ->get_my_governor()->get_type_refd_last(); + + expression_struct expr2; + Code::init_expr(&expr2); + + bool is_templ = false; + switch (templ->get_templatetype()) { + case Template::SPECIFIC_VALUE: + v1->generate_code_expr_mandatory(&expr2); + break; + default: + u.expr.ti1->generate_code(&expr2); + is_templ = true; + break; + } + + if (!gov_last->is_coding_by_function()) { + const string& tmp_id = get_temporary_id(); + const string& tmp_buf_id = get_temporary_id(); + const string& tmp_ref_id = get_temporary_id(); + expr->preamble = mputprintf(expr->preamble, "OCTETSTRING %s;\n", + tmp_id.c_str()); + expr->preamble = mputprintf(expr->preamble, "TTCN_Buffer %s;\n", + tmp_buf_id.c_str()); + if (expr2.preamble) { // copy preamble setting up the argument, if any + expr->preamble = mputstr(expr->preamble, expr2.preamble); + expr->preamble = mputc (expr->preamble, '\n'); + } + expr->preamble = mputprintf(expr->preamble, "%s const& %s = %s", + gov_last->get_genname_typedescriptor( + u.expr.ti1->get_Template()->get_my_scope() + ).c_str(), + tmp_ref_id.c_str(), + expr2.expr); + if (is_templ) // make a value out of the template, if needed + expr->preamble = mputprintf(expr->preamble, ".valueof()"); + expr->preamble = mputprintf(expr->preamble, + ";\n%s.encode(%s_descr_, %s, TTCN_EncDec::CT_%s", + tmp_ref_id.c_str(), + gov_last->get_genname_typedescriptor( + u.expr.ti1->get_Template()->get_my_scope() + ).c_str(), + tmp_buf_id.c_str(), + gov_last->get_coding(true).c_str() + ); + expr->preamble = mputstr(expr->preamble, ");\n"); + expr->preamble = mputprintf(expr->preamble, "%s.get_string(%s);\n", + tmp_buf_id.c_str(), + tmp_id.c_str() + ); + const char * v2_code = NULL; + if(u.expr.v2) { + v2_code = generate_code_char_coding_check(expr, u.expr.v2, "encvalue_unichar"); + } + expr->expr = mputprintf(expr->expr, "oct2unichar(%s", tmp_id.c_str()); + if(u.expr.v2) { + expr->expr = mputprintf(expr->expr, ", %s", v2_code); + } else { + expr->expr = mputprintf(expr->expr, ", \"UTF-8\""); //default + } + expr->expr = mputprintf(expr->expr, ")"); + if (expr2.postamble) + expr->postamble = mputstr(expr->postamble, expr2.postamble); + } else + expr->expr = mputprintf(expr->expr, "%s(%s%s)", + gov_last->get_coding(true).c_str(), expr2.expr, + is_templ ? ".valueof()" : ""); + Code::free_expr(&expr2); + } + + void Value::generate_code_expr_decvalue_unichar(expression_struct *expr) + { + expression_struct expr1, expr2; + Code::init_expr(&expr1); + Code::init_expr(&expr2); + u.expr.r1->generate_code(&expr1); + u.expr.r2->generate_code(&expr2); + + Type* _type = u.expr.r2->get_refd_assignment()->get_Type()-> + get_field_type(u.expr.r2->get_subrefs(), Type::EXPECTED_DYNAMIC_VALUE)-> + get_type_refd_last(); + + if (expr1.preamble) + expr->preamble = mputprintf(expr->preamble, "%s", expr1.preamble); + if (expr2.preamble) + expr->preamble = mputprintf(expr->preamble, "%s", expr2.preamble); + + if (!_type->is_coding_by_function()) { + const string& tmp_id = get_temporary_id(); + const string& buffer_id = get_temporary_id(); + const string& retval_id = get_temporary_id(); + const bool optional = u.expr.r2->get_refd_assignment()->get_Type()-> + field_is_optional(u.expr.r2->get_subrefs()); + + const char* v3_code = NULL; + if(u.expr.v3) { + v3_code = generate_code_char_coding_check(expr, u.expr.v3, "decvalue_unichar"); + } + expr->preamble = mputprintf(expr->preamble, + "TTCN_Buffer %s(unichar2oct(%s, %s));\n" + "INTEGER %s;\n" + "TTCN_EncDec::set_error_behavior(" + "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n" + "TTCN_EncDec::clear_error();\n", + buffer_id.c_str(), + expr1.expr, + u.expr.v3 ? v3_code : "\"UTF-8\"", + retval_id.c_str() + ); + expr->preamble = mputprintf(expr->preamble, + "%s%s.decode(%s_descr_, %s, TTCN_EncDec::CT_%s);\n", + expr2.expr, + optional ? "()" : "", + _type->get_genname_typedescriptor( + u.expr.r2->get_my_scope() + ).c_str(), + buffer_id.c_str(), + _type->get_coding(false).c_str() + ); + expr->preamble = mputprintf(expr->preamble, + "switch (TTCN_EncDec::get_last_error_type()) {\n" + "case TTCN_EncDec::ET_NONE: {\n" + "%s.cut();\n" + "OCTETSTRING %s;\n" + "%s.get_string(%s);\n" + "%s = oct2unichar(%s, %s);\n" + "%s = 0;\n" + "}break;\n" + "case TTCN_EncDec::ET_INCOMPL_MSG:\n" + "case TTCN_EncDec::ET_LEN_ERR:\n" + "%s = 2;\n" + "break;\n" + "default:\n" + "%s = 1;\n" + "}\n" + "TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL," + "TTCN_EncDec::EB_DEFAULT);\n" + "TTCN_EncDec::clear_error();\n", + buffer_id.c_str(), + tmp_id.c_str(), + buffer_id.c_str(), + tmp_id.c_str(), + expr1.expr, + tmp_id.c_str(), + u.expr.v3 ? v3_code : "\"UTF-8\"", + retval_id.c_str(), + retval_id.c_str(), + retval_id.c_str() + ); + expr->expr = mputprintf(expr->expr, "%s", retval_id.c_str()); + } else + expr->expr = mputprintf(expr->expr, "%s(%s, %s)", + _type->get_coding(false).c_str(), expr1.expr, expr2.expr); + if (expr1.postamble) + expr->postamble = mputprintf(expr->postamble, "%s", expr1.postamble); + if (expr2.postamble) + expr->postamble = mputprintf(expr->postamble, "%s", expr2.postamble); + Code::free_expr(&expr1); + Code::free_expr(&expr2); + } + + char* Value::generate_code_char_coding_check(expression_struct *expr, Value *v, const char *name) + { + expression_struct expr2; + Code::init_expr(&expr2); + v->generate_code_expr_mandatory(&expr2); + expr->preamble = mputprintf(expr->preamble, + "if (\"UTF-8\" != %s && \"UTF-16\" != %s && \"UTF-16LE\" != %s && \n" + " \"UTF-16BE\" != %s && \"UTF-32\" != %s && \"UTF-32LE\" != %s && \n" + " \"UTF-32BE\" != %s) {\n" + " TTCN_error(\"%s: Invalid encoding parameter: %%s\", (const char*)%s);\n" + "}\n", //todo errorbehaviour? + expr2.expr, + expr2.expr, + expr2.expr, + expr2.expr, + expr2.expr, + expr2.expr, + expr2.expr, + name, + expr2.expr); + return expr2.expr; + } char *Value::generate_code_init_choice(char *str, const char *name) { @@ -13091,6 +13478,8 @@ error: case OPTYPE_ISBOUND: case OPTYPE_ISPRESENT: case OPTYPE_TTCN2STRING: + case OPTYPE_ENCVALUE_UNICHAR: + case OPTYPE_DECVALUE_UNICHAR: return false; case OPTYPE_UNARYPLUS: // v1 case OPTYPE_UNARYMINUS: diff --git a/compiler2/Value.hh b/compiler2/Value.hh index 60b0a18..dd75c42 100644 --- a/compiler2/Value.hh +++ b/compiler2/Value.hh @@ -18,6 +18,7 @@ * Kovacs, Ferenc * Raduly, Csaba * Szabados, Kristof + * Szabo, Bence Janos * Szabo, Janos Zoltan – initial implementation * Tatarka, Gabor * Zalanyi, Balazs Andor @@ -259,6 +260,9 @@ namespace Common { OPTYPE_LOG2STR, // logagrs OPTYPE_PROF_RUNNING, // - 99 + + OPTYPE_ENCVALUE_UNICHAR, // ti1 [v2] + OPTYPE_DECVALUE_UNICHAR, // r1 r2 [v3] NUMBER_OF_OPTYPES // must be last }; @@ -414,6 +418,8 @@ namespace Common { Value(operationtype_t p_optype, Value *p_v1, Value *p_v2); /** Constructor used by V_EXPR "v1 v2 v3" */ Value(operationtype_t p_optype, Value *p_v1, Value *p_v2, Value *p_v3); + /** Constructor used by encvalue_unichar "ti1 [v2]" */ + Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2); /** Constructor used by V_EXPR "ti1 v2 v3" */ Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2, Value *p_v3); /** Constructor used by V_EXPR "ti1 t2 v3" */ @@ -435,6 +441,8 @@ namespace Common { Value(valuetype_t p_vt, verdict_t p_verdict); /** Constructor used by decode */ 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); virtual ~Value(); virtual Value* clone() const; valuetype_t get_valuetype() const {return valuetype;} @@ -628,7 +636,8 @@ namespace Common { Type::expected_value_t exp_val); void chk_expr_operand_encode(ReferenceChain *refch, Type::expected_value_t exp_val); - void chk_expr_operands_decode(); + /** \a has two possible value: OPTYPE_DECODE | OPTYPE_DECVALUE_UNICHAR */ + void chk_expr_operands_decode(operationtype_t p_optype); /** Checks whether \a this can be compared with omit value (i.e. \a this * should be a referenced value pointing to a optional record/set field. */ void chk_expr_omit_comparison(Type::expected_value_t exp_val); @@ -907,6 +916,12 @@ namespace Common { void generate_code_expr_encode(expression_struct *expr); void generate_code_expr_decode(expression_struct *expr); + + void generate_code_expr_encvalue_unichar(expression_struct *expr); + + void generate_code_expr_decvalue_unichar(expression_struct *expr); + + char* generate_code_char_coding_check(expression_struct *expr, Value *v, const char *name); /** Helper function for \a generate_code_init(). It handles the * union (CHOICE) values. */ diff --git a/compiler2/ttcn3/compiler.l b/compiler2/ttcn3/compiler.l index 4fe0e83..47682da 100644 --- a/compiler2/ttcn3/compiler.l +++ b/compiler2/ttcn3/compiler.l @@ -585,6 +585,8 @@ remove_bom RETURN(remove_bomKeyWord); get_stringencoding RETURN(get_stringencodingKeyWord); encode_base64 RETURN(encode_base64KeyWord); decode_base64 RETURN(decode_base64KeyWord); +encvalue_unichar RETURN(encvalue_unicharKeyWord); +decvalue_unichar RETURN(decvalue_unicharKeyWord); /* Values */ diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y index 194a48e..f6f16f3 100644 --- a/compiler2/ttcn3/compiler.y +++ b/compiler2/ttcn3/compiler.y @@ -832,6 +832,8 @@ static const string anyname("anytype"); %token get_stringencodingKeyWord %token encode_base64KeyWord %token decode_base64KeyWord +%token encvalue_unicharKeyWord +%token decvalue_unicharKeyWord /* Multi-character operators */ @@ -8739,6 +8741,43 @@ PredefinedOps: $$ = new Value(Value::V_ERROR); $$->set_location(infile, @$); } +| encvalue_unicharKeyWord '(' optError TemplateInstance optError ',' optError + Expression optError ')' + { + $$ = new Value(Value::OPTYPE_ENCVALUE_UNICHAR, $4, $8); + $$->set_location(infile, @$); + } +| encvalue_unicharKeyWord '(' optError TemplateInstance optError ')' + { + $$ = new Value(Value::OPTYPE_ENCVALUE_UNICHAR, $4); + $$->set_location(infile, @$); + } +| encvalue_unicharKeyWord '(' error ')' + { + Template *t1 = new Template(Template::TEMPLATE_ERROR); + t1->set_location(infile, @3); + TemplateInstance *ti1 = new TemplateInstance(0, 0, t1); + ti1->set_location(infile, @3); + $$ = new Value(Value::OPTYPE_ENCVALUE_UNICHAR, ti1); + $$->set_location(infile, @$); + } +| decvalue_unicharKeyWord '(' optError DecValueArg optError ',' optError + DecValueArg optError ')' + { + $$ = new Value(Value::OPTYPE_DECVALUE_UNICHAR, $4, $8); + $$->set_location(infile, @$); + } +| decvalue_unicharKeyWord '(' optError DecValueArg optError ',' optError + DecValueArg optError ',' optError Expression optError ')' + { + $$ = new Value(Value::OPTYPE_DECVALUE_UNICHAR, $4, $8, $12); + $$->set_location(infile, @$); + } +| decvalue_unicharKeyWord '(' error ')' + { + $$ = new Value(Value::V_ERROR); + $$->set_location(infile, @$); + } ; DecValueArg: diff --git a/regression_test/ucharstrOper/EncDecvalueUnichar.ttcn b/regression_test/ucharstrOper/EncDecvalueUnichar.ttcn new file mode 100644 index 0000000..d5f1699 --- /dev/null +++ b/regression_test/ucharstrOper/EncDecvalueUnichar.ttcn @@ -0,0 +1,142 @@ +/****************************************************************************** + * Copyright (c) 2000-2016 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Szabo, Bence Janos + * + ******************************************************************************/ + +module EncDecvalueUnichar { + +type integer Byte (-128 .. 127) with { variant "8 bit" }; + +type bitstring BStr16 with { variant "16 bit" }; + +type hexstring HStr; + +type octetstring OStr; + +type charstring CStr; + +type universal charstring UStr; + +// Component type +type component CT {} + +// Test cases +testcase tc_byte() runs on CT +{ + + var Byte x := 30; + var universal charstring enc := encvalue_unichar(x, "UTF-8"); + var Byte x_exp; + var integer res := decvalue_unichar(enc, x_exp, "UTF-8"); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } +} + +testcase tc_bstr() runs on CT +{ + var BStr16 x := '0100010101110011'B; + var universal charstring enc := encvalue_unichar(x, "UTF-8"); + var BStr16 x_exp; + var integer res := decvalue_unichar(enc, x_exp, "UTF-8"); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } + + // with default UTF-8 coding + x := '0100010101110011'B; + enc := encvalue_unichar(x); + res := decvalue_unichar(enc, x_exp); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } +} + +testcase tc_hstr() runs on CT +{ + var HStr x := '44'H; + var universal charstring enc := encvalue_unichar(x, "UTF-8"); + var HStr x_exp; + var integer res := decvalue_unichar(enc, x_exp, "UTF-8"); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } +} + +testcase tc_ostr() runs on CT +{ + var OStr x := '1255'O; + var universal charstring enc := encvalue_unichar(x, "UTF-8"); + var OStr x_exp; + var integer res := decvalue_unichar(enc, x_exp, "UTF-8"); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } +} + +testcase tc_cstr() runs on CT +{ + var CStr x := "CdVsBgAa"; + var universal charstring enc := encvalue_unichar(x, "UTF-8"); + var CStr x_exp; + var integer res := decvalue_unichar(enc, x_exp, "UTF-8"); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } +} + +testcase tc_ustr() runs on CT +{ + var UStr x := "CdVsBgAa"; + var universal charstring enc := encvalue_unichar(x, "UTF-8"); + var UStr x_exp; + var integer res := decvalue_unichar(enc, x_exp, "UTF-8"); + if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) { + setverdict(pass); + } + else { + setverdict(fail); + } +} + + +// Control part +control { + execute(tc_byte()); + execute(tc_bstr()); + execute(tc_hstr()); + execute(tc_ostr()); + execute(tc_cstr()); + execute(tc_ustr()); +} + +} +with { + encode "RAW"; +} + diff --git a/regression_test/ucharstrOper/Makefile b/regression_test/ucharstrOper/Makefile index e5ddf9f..2b40fb9 100644 --- a/regression_test/ucharstrOper/Makefile +++ b/regression_test/ucharstrOper/Makefile @@ -20,7 +20,7 @@ include $(TOPDIR)/Makefile.regression TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) -TTCN3_MODULES = TucharstrOper.ttcn cstr_content.ttcn Common.ttcn UTF8Testcases.ttcn UTF16Testcases.ttcn UTF32Testcases.ttcn Base64Testcases.ttcn +TTCN3_MODULES = TucharstrOper.ttcn cstr_content.ttcn Common.ttcn UTF8Testcases.ttcn UTF16Testcases.ttcn UTF32Testcases.ttcn Base64Testcases.ttcn EncDecvalueUnichar.ttcn GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) diff --git a/regression_test/ucharstrOper/config.cfg b/regression_test/ucharstrOper/config.cfg index 7fdafe8..f50ffe8 100644 --- a/regression_test/ucharstrOper/config.cfg +++ b/regression_test/ucharstrOper/config.cfg @@ -30,3 +30,4 @@ UTF8Testcases.control UTF16Testcases.control UTF32Testcases.control Base64Testcases.control +EncDecvalueUnichar.control -- 2.34.1