Commit 02a6776e authored by Botond Baranyi's avatar Botond Baranyi
Browse files

Added support for subreferences following valueof (artf577127)


Fixed ASN.1 named bits with length restrictions (bug 521410)

Change-Id: I53743e878e8840d0c9bafdc5ca51f85da08e5f6e
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent d0f6e30d
...@@ -4393,6 +4393,12 @@ void Type::chk_this_value_namedbits(Value *value) ...@@ -4393,6 +4393,12 @@ void Type::chk_this_value_namedbits(Value *value)
if(bstring->size() < bitnum + 1) bstring->resize(bitnum + 1, '0'); if(bstring->size() < bitnum + 1) bstring->resize(bitnum + 1, '0');
(*bstring)[bitnum] = '1'; (*bstring)[bitnum] = '1';
} }
if (sub_type != NULL) {
size_t min_length = sub_type->get_min_length();
if (bstring->size() < min_length) {
bstring->resize(min_length, '0');
}
}
value->set_valuetype(Value::V_BSTR, bstring); value->set_valuetype(Value::V_BSTR, bstring);
} }
......
...@@ -291,9 +291,11 @@ namespace Common { ...@@ -291,9 +291,11 @@ namespace Common {
u.expr.v3 = p.u.expr.v3->clone(); u.expr.v3 = p.u.expr.v3->clone();
u.expr.ti4 = p.u.expr.ti4->clone(); u.expr.ti4 = p.u.expr.ti4->clone();
break; break;
case OPTYPE_VALUEOF: // ti1 [subrefs2]
u.expr.subrefs2 = p.u.expr.subrefs2 != NULL ? u.expr.subrefs2->clone() : NULL;
// fall through
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
case OPTYPE_TTCN2STRING: case OPTYPE_TTCN2STRING:
case OPTYPE_ISVALUE: case OPTYPE_ISVALUE:
...@@ -637,9 +639,11 @@ namespace Common { ...@@ -637,9 +639,11 @@ namespace Common {
delete u.expr.v3; delete u.expr.v3;
delete u.expr.ti4; delete u.expr.ti4;
break; break;
case OPTYPE_VALUEOF: // ti1 [subrefs2]
delete u.expr.subrefs2;
// fall through
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
case OPTYPE_ISVALUE: case OPTYPE_ISVALUE:
case OPTYPE_ISBOUND: case OPTYPE_ISBOUND:
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
...@@ -1030,6 +1034,29 @@ namespace Common { ...@@ -1030,6 +1034,29 @@ namespace Common {
case OPTYPE_TTCN2STRING: case OPTYPE_TTCN2STRING:
if(!p_ti1) FATAL_ERROR("Value::Value()"); if(!p_ti1) FATAL_ERROR("Value::Value()");
u.expr.ti1=p_ti1; u.expr.ti1=p_ti1;
if (p_optype == OPTYPE_VALUEOF) {
u.expr.subrefs2 = NULL;
}
break;
default:
FATAL_ERROR("Value::Value()");
} // switch
}
// ti1 subrefs2
Value::Value(operationtype_t p_optype, TemplateInstance* p_ti1,
Ttcn::FieldOrArrayRefs* p_subrefs2)
: GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
{
u.expr.v_optype = p_optype;
u.expr.state = EXPR_NOT_CHECKED;
switch (p_optype) {
case OPTYPE_VALUEOF:
if (p_ti1 == NULL || p_subrefs2 == NULL) {
FATAL_ERROR("Value::Value()");
}
u.expr.ti1 = p_ti1;
u.expr.subrefs2 = p_subrefs2;
break; break;
default: default:
FATAL_ERROR("Value::Value()"); FATAL_ERROR("Value::Value()");
...@@ -1841,9 +1868,13 @@ namespace Common { ...@@ -1841,9 +1868,13 @@ namespace Common {
u.expr.v3->set_fullname(p_fullname+".<operand3>"); u.expr.v3->set_fullname(p_fullname+".<operand3>");
u.expr.ti4->set_fullname(p_fullname+".<operand4>"); u.expr.ti4->set_fullname(p_fullname+".<operand4>");
break; break;
case OPTYPE_VALUEOF: // ti1 [subrefs2]
if (u.expr.subrefs2 != NULL) {
u.expr.subrefs2->set_fullname(p_fullname + ".<subrefs>");
}
// fall through
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
case OPTYPE_ISVALUE: case OPTYPE_ISVALUE:
case OPTYPE_ISBOUND: case OPTYPE_ISBOUND:
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
...@@ -2097,9 +2128,13 @@ namespace Common { ...@@ -2097,9 +2128,13 @@ namespace Common {
u.expr.v3->set_my_scope(p_scope); u.expr.v3->set_my_scope(p_scope);
u.expr.ti4->set_my_scope(p_scope); u.expr.ti4->set_my_scope(p_scope);
break; break;
case OPTYPE_VALUEOF: // ti1 [subrefs2]
if (u.expr.subrefs2 != NULL) {
u.expr.subrefs2->set_my_scope(p_scope);
}
// fall through
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
case OPTYPE_ISVALUE: case OPTYPE_ISVALUE:
case OPTYPE_ISBOUND: case OPTYPE_ISBOUND:
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
...@@ -2470,7 +2505,7 @@ namespace Common { ...@@ -2470,7 +2505,7 @@ namespace Common {
break; break;
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1 case OPTYPE_VALUEOF: // ti1 [subrefs2]
case OPTYPE_ISVALUE: case OPTYPE_ISVALUE:
case OPTYPE_ISBOUND: case OPTYPE_ISBOUND:
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
...@@ -3312,7 +3347,17 @@ namespace Common { ...@@ -3312,7 +3347,17 @@ namespace Common {
case OPTYPE_VALUEOF: { case OPTYPE_VALUEOF: {
Error_Context cntxt(this, "In the operand of operation `%s'", Error_Context cntxt(this, "In the operand of operation `%s'",
get_opname()); get_opname());
return u.expr.ti1->get_expr_returntype(Type::EXPECTED_TEMPLATE);} if (u.expr.subrefs2 != NULL) {
Type* t = u.expr.ti1->get_expr_governor(Type::EXPECTED_TEMPLATE);
if (t != NULL) {
t = t->get_type_refd_last()->get_field_type(u.expr.subrefs2, exp_val);
return t->get_type_refd_last()->get_typetype();
}
return Type::T_UNDEF;
}
else {
return u.expr.ti1->get_expr_returntype(Type::EXPECTED_TEMPLATE);
} }
case OPTYPE_TMR_READ: case OPTYPE_TMR_READ:
case OPTYPE_INT2FLOAT: case OPTYPE_INT2FLOAT:
case OPTYPE_STR2FLOAT: case OPTYPE_STR2FLOAT:
...@@ -3718,6 +3763,10 @@ namespace Common { ...@@ -3718,6 +3763,10 @@ namespace Common {
case OPTYPE_REPLACE:{ case OPTYPE_REPLACE:{
Type *tmp_type = u.expr.ti1->get_expr_governor(exp_val == Type *tmp_type = u.expr.ti1->get_expr_governor(exp_val ==
Type::EXPECTED_DYNAMIC_VALUE ? Type::EXPECTED_TEMPLATE : exp_val); Type::EXPECTED_DYNAMIC_VALUE ? Type::EXPECTED_TEMPLATE : exp_val);
if (u.expr.v_optype == OPTYPE_VALUEOF && tmp_type != NULL) {
tmp_type = tmp_type->get_type_refd_last()->
get_field_type(u.expr.subrefs2, exp_val);
}
if(tmp_type) tmp_type = tmp_type->get_type_refd_last(); if(tmp_type) tmp_type = tmp_type->get_type_refd_last();
return tmp_type; return tmp_type;
} }
...@@ -3986,7 +4035,7 @@ namespace Common { ...@@ -3986,7 +4035,7 @@ namespace Common {
return "decomp()"; return "decomp()";
case OPTYPE_REPLACE: case OPTYPE_REPLACE:
return "replace()"; return "replace()";
case OPTYPE_VALUEOF: // t1 case OPTYPE_VALUEOF: // t1 [subrefs2]
return "valueof()"; return "valueof()";
case OPTYPE_UNDEF_RUNNING: case OPTYPE_UNDEF_RUNNING:
return "<timer or component> running"; return "<timer or component> running";
...@@ -7649,16 +7698,17 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -7649,16 +7698,17 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_ISCHOSEN_T: // t1 i2 case OPTYPE_ISCHOSEN_T: // t1 i2
chk_expr_operands_ischosen(refch, exp_val); chk_expr_operands_ischosen(refch, exp_val);
break; break;
case OPTYPE_VALUEOF: { // ti1 case OPTYPE_VALUEOF: { // ti1 [subrefs2]
if (exp_val == Type::EXPECTED_DYNAMIC_VALUE) if (exp_val == Type::EXPECTED_DYNAMIC_VALUE)
exp_val = Type::EXPECTED_TEMPLATE; exp_val = Type::EXPECTED_TEMPLATE;
Error_Context cntxt(this, "In the operand of operation `%s'", opname); Error_Context cntxt(this, "In the operand of operation `%s'", opname);
Type *governor = my_governor; Type *governor = (u.expr.subrefs2 == NULL) ? my_governor : NULL;
if (!governor) governor = chk_expr_operands_ti(u.expr.ti1, exp_val); if (!governor) governor = chk_expr_operands_ti(u.expr.ti1, exp_val);
if (!governor) return; if (!governor) return;
chk_expr_eval_ti(u.expr.ti1, governor, refch, exp_val); chk_expr_eval_ti(u.expr.ti1, governor, refch, exp_val);
if (valuetype == V_ERROR) return; if (valuetype == V_ERROR) return;
u.expr.ti1->get_Template()->chk_specific_value(false); u.expr.ti1->get_Template()->chk_specific_value(false);
// the subreferences have already been checked by get_expr_returntype
break; } break; }
case OPTYPE_ISPRESENT: // TODO: rename UsedInIsbound to better name case OPTYPE_ISPRESENT: // TODO: rename UsedInIsbound to better name
case OPTYPE_ISBOUND: { case OPTYPE_ISBOUND: {
...@@ -8751,17 +8801,20 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -8751,17 +8801,20 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
valuetype = V_BOOL; valuetype = V_BOOL;
u.val_bool = b; u.val_bool = b;
break; } break; }
case OPTYPE_VALUEOF: // ti1 case OPTYPE_VALUEOF: // ti1 [subrefs2]
if (!u.expr.ti1->get_DerivedRef() && if (!u.expr.ti1->get_DerivedRef() &&
u.expr.ti1->get_Template()->is_Value() && u.expr.ti1->get_Template()->is_Value() &&
!u.expr.ti1->get_Type()) { !u.expr.ti1->get_Type()) {
// FIXME actually if the template instance has a type // FIXME actually if the template instance has a type
// it might still be foldable. // it might still be foldable.
// the argument is a single specific value // the argument is a single specific value
v1 = u.expr.ti1->get_Template()->get_Value(); v1 = u.expr.ti1->get_Template()->get_Value()->
get_refd_sub_value(u.expr.subrefs2, 0, false, refch);
Type *governor = my_governor; Type *governor = my_governor;
if (governor == NULL) { if (governor == NULL) {
governor = u.expr.ti1->get_expr_governor(exp_val); governor = u.expr.ti1->get_expr_governor(exp_val);
if (governor != NULL) governor = governor->get_type_refd_last()->
get_field_type(u.expr.subrefs2, exp_val);
if (governor != NULL) governor = governor->get_type_refd_last(); if (governor != NULL) governor = governor->get_type_refd_last();
} }
if (governor == NULL) governor = v1->get_my_governor()->get_type_refd_last(); if (governor == NULL) governor = v1->get_my_governor()->get_type_refd_last();
...@@ -9360,7 +9413,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -9360,7 +9413,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
|| u.expr.v3->is_unfoldable(refch, exp_val) || u.expr.v3->is_unfoldable(refch, exp_val)
|| u.expr.ti4->get_specific_value()->is_unfoldable(refch, exp_val); || u.expr.ti4->get_specific_value()->is_unfoldable(refch, exp_val);
} }
case OPTYPE_VALUEOF: // ti1 case OPTYPE_VALUEOF: // ti1 [subrefs2]
/* \todo if you have motivation to implement the eval function /* \todo if you have motivation to implement the eval function
for valueof()... */ for valueof()... */
return true; return true;
...@@ -10627,9 +10680,20 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -10627,9 +10680,20 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
u.expr.ti4->chk_recursions(refch); u.expr.ti4->chk_recursions(refch);
refch.prev_state(); refch.prev_state();
break; break;
case OPTYPE_VALUEOF: // ti1 [subrefs2]
if (u.expr.subrefs2 != NULL) {
for (size_t i = 0; i < u.expr.subrefs2->get_nof_refs(); ++i) {
Ttcn::FieldOrArrayRef* subref = u.expr.subrefs2->get_ref(i);
if (subref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
refch.mark_state();
subref->get_val()->chk_recursions(refch);
refch.prev_state();
}
}
}
// fall through
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
case OPTYPE_TTCN2STRING: case OPTYPE_TTCN2STRING:
refch.mark_state(); refch.mark_state();
...@@ -10985,10 +11049,19 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -10985,10 +11049,19 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_REGEXP: // ti1 t2 v3 case OPTYPE_REGEXP: // ti1 t2 v3
self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs); self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs);
self_ref |= chk_expr_self_ref_templ(u.expr.t2 ->get_Template(), lhs); self_ref |= chk_expr_self_ref_templ(u.expr.t2 ->get_Template(), lhs);
// no break break;
case OPTYPE_VALUEOF: // ti1 [subrefs2]
if (u.expr.subrefs2 != NULL) {
for (size_t i = 0; i < u.expr.subrefs2->get_nof_refs(); ++i) {
Ttcn::FieldOrArrayRef* subref = u.expr.subrefs2->get_ref(i);
if (subref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
self_ref |= chk_expr_self_ref_val(subref->get_val(), lhs);
}
}
}
// fall through
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
case OPTYPE_TTCN2STRING: case OPTYPE_TTCN2STRING:
self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs); self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs);
break; break;
...@@ -11575,6 +11648,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -11575,6 +11648,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
string ret_val("valueof("); string ret_val("valueof(");
u.expr.ti1->append_stringRepr(ret_val); u.expr.ti1->append_stringRepr(ret_val);
ret_val += ')'; ret_val += ')';
if (u.expr.subrefs2 != NULL) {
u.expr.subrefs2->append_stringRepr(ret_val);
}
return ret_val; } return ret_val; }
case OPTYPE_LOG2STR: case OPTYPE_LOG2STR:
return string("log2str(...)"); return string("log2str(...)");
...@@ -12445,9 +12521,18 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -12445,9 +12521,18 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
str = u.expr.ti1->rearrange_init_code(str, usage_mod); str = u.expr.ti1->rearrange_init_code(str, usage_mod);
str = u.expr.v2->rearrange_init_code(str, usage_mod); str = u.expr.v2->rearrange_init_code(str, usage_mod);
break; break;
case OPTYPE_VALUEOF:
if (u.expr.subrefs2 != NULL) {
for (size_t i = 0; i < u.expr.subrefs2->get_nof_refs(); ++i) {
Ttcn::FieldOrArrayRef* subref = u.expr.subrefs2->get_ref(i);
if (subref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
str = subref->get_val()->rearrange_init_code(str, usage_mod);
}
}
}
// fall through
case OPTYPE_LENGTHOF: case OPTYPE_LENGTHOF:
case OPTYPE_SIZEOF: case OPTYPE_SIZEOF:
case OPTYPE_VALUEOF:
case OPTYPE_ISPRESENT: case OPTYPE_ISPRESENT:
case OPTYPE_TTCN2STRING: case OPTYPE_TTCN2STRING:
str = u.expr.ti1->rearrange_init_code(str, usage_mod); str = u.expr.ti1->rearrange_init_code(str, usage_mod);
...@@ -12980,9 +13065,13 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -12980,9 +13065,13 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
FATAL_ERROR("Value::generate_code_expr_expr()"); FATAL_ERROR("Value::generate_code_expr_expr()");
} }
break; } break; }
case OPTYPE_VALUEOF: // ti1 case OPTYPE_VALUEOF: // ti1 [subrefs2]
u.expr.ti1->generate_code(expr); u.expr.ti1->generate_code(expr);
expr->expr = mputstr(expr->expr, ".valueof()"); expr->expr = mputstr(expr->expr, ".valueof()");
if (u.expr.subrefs2 != NULL) {
u.expr.subrefs2->generate_code(expr,
u.expr.ti1->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE));
}
break; break;
case OPTYPE_ISTEMPLATEKIND: // ti1 v2 case OPTYPE_ISTEMPLATEKIND: // ti1 v2
u.expr.ti1->generate_code(expr); u.expr.ti1->generate_code(expr);
...@@ -14904,10 +14993,20 @@ void Value::chk_expr_operand_execute_refd(Value *v1, ...@@ -14904,10 +14993,20 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
return u.expr.ti1->has_single_expr() && return u.expr.ti1->has_single_expr() &&
u.expr.v2->has_single_expr() && u.expr.v3->has_single_expr() && u.expr.v2->has_single_expr() && u.expr.v3->has_single_expr() &&
u.expr.ti4->has_single_expr(); u.expr.ti4->has_single_expr();
case OPTYPE_VALUEOF: // ti1 [subrefs2]
if (u.expr.subrefs2 != NULL) {
for (size_t i = 0; i < u.expr.subrefs2->get_nof_refs(); ++i) {
Ttcn::FieldOrArrayRef* subref = u.expr.subrefs2->get_ref(i);
if (subref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF &&
!subref->get_val()->has_single_expr()) {
return false;
}
}
}
// fall through
case OPTYPE_ISVALUE: // ti1 case OPTYPE_ISVALUE: // ti1
case OPTYPE_LENGTHOF: // ti1 case OPTYPE_LENGTHOF: // ti1
case OPTYPE_SIZEOF: // ti1 case OPTYPE_SIZEOF: // ti1
case OPTYPE_VALUEOF: // ti1
return u.expr.ti1->has_single_expr(); return u.expr.ti1->has_single_expr();
case OPTYPE_LOG2STR: case OPTYPE_LOG2STR:
case OPTYPE_ANY2UNISTR: case OPTYPE_ANY2UNISTR:
......
...@@ -51,6 +51,7 @@ namespace Ttcn { ...@@ -51,6 +51,7 @@ namespace Ttcn {
class LogArguments; class LogArguments;
class JsonOmitCombination; class JsonOmitCombination;
class LengthRestriction; class LengthRestriction;
class FieldOrArrayRefs;
} }
namespace Common { namespace Common {
...@@ -350,6 +351,7 @@ namespace Common { ...@@ -350,6 +351,7 @@ namespace Common {
Ttcn::ParsedActualParameters *t_list2; Ttcn::ParsedActualParameters *t_list2;
Ttcn::ActualParList *ap_list2; Ttcn::ActualParList *ap_list2;
Ttcn::Ref_base *r2; Ttcn::Ref_base *r2;
Ttcn::FieldOrArrayRefs* subrefs2;
}; };
Value *v3; Value *v3;
union { union {
...@@ -419,6 +421,9 @@ namespace Common { ...@@ -419,6 +421,9 @@ namespace Common {
Value(operationtype_t p_optype, Value* p_v1, Ttcn::Ref_base* p_r2, bool p_b4); Value(operationtype_t p_optype, Value* p_v1, Ttcn::Ref_base* p_r2, bool p_b4);
/** Constructor used by V_EXPR "ti1": LENGTHOF, SIZEOF, VALUEOF, TTCN2STRING */ /** Constructor used by V_EXPR "ti1": LENGTHOF, SIZEOF, VALUEOF, TTCN2STRING */
Value(operationtype_t p_optype, TemplateInstance *p_ti1); Value(operationtype_t p_optype, TemplateInstance *p_ti1);
/** Constructor used by V_EXPR "ti1 subrefs2": VALUEOF */
Value(operationtype_t p_optype, TemplateInstance *p_ti1,
Ttcn::FieldOrArrayRefs* p_subrefs2);
/** Constructor used by V_EXPR "r1": TMR_READ, ACTIVATE */ /** Constructor used by V_EXPR "r1": TMR_READ, ACTIVATE */
Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1); Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1);
/** Constructor used by V_EXPR "r1 [r2] b4": UNDEF_RUNNING */ /** Constructor used by V_EXPR "r1 [r2] b4": UNDEF_RUNNING */
......
...@@ -1285,6 +1285,14 @@ bool SubtypeConstraint::is_lower_limit_infinity() const ...@@ -1285,6 +1285,14 @@ bool SubtypeConstraint::is_lower_limit_infinity() const
return false; return false;
} }
size_t SubtypeConstraint::get_min_length() const
{
if (subtype != ST_BITSTRING) {
FATAL_ERROR("SubtypeConstraint::get_min_length()");
}
return bitstring_st != NULL ? bitstring_st->get_min_length() : 0;
}
void SubtypeConstraint::except(const SubtypeConstraint* other) void SubtypeConstraint::except(const SubtypeConstraint* other)
{ {
......
...@@ -237,6 +237,7 @@ public: ...@@ -237,6 +237,7 @@ public:
universal_charstring_st->get_size_limit(false, sl) == TTRUE && universal_charstring_st->get_size_limit(false, sl) == TTRUE &&
universal_charstring_st->get_size_limit(true, sl) == TTRUE); universal_charstring_st->get_size_limit(true, sl) == TTRUE);
} }
size_t get_min_length() const;
}; };
/** /**
......
...@@ -751,6 +751,8 @@ public: ...@@ -751,6 +751,8 @@ public:
tribool get_size_limit(bool is_upper, size_limit_t& limit) const; tribool get_size_limit(bool is_upper, size_limit_t& limit) const;
string to_string() const; string to_string() const;
size_t get_min_length() const;
}; };
template<unsigned char BITCNT, unsigned short ELEMSIZE> template<unsigned char BITCNT, unsigned short ELEMSIZE>
...@@ -1028,6 +1030,15 @@ string StringSizeAndValueListConstraint<BITCNT,ELEMSIZE>::to_string() const ...@@ -1028,6 +1030,15 @@ string StringSizeAndValueListConstraint<BITCNT,ELEMSIZE>::to_string() const
return ret_val; return ret_val;
} }
template <unsigned char BITCNT, unsigned short ELEMSIZE>
size_t StringSizeAndValueListConstraint<BITCNT, ELEMSIZE>::get_min_length() const
{
if (size_constraint.is_empty() == TTRUE) {
return 0;
}
return size_constraint.get_minimal().get_size();
}
typedef StringSizeAndValueListConstraint<1,1> BitstringConstraint; typedef StringSizeAndValueListConstraint<1,1> BitstringConstraint;
typedef StringSizeAndValueListConstraint<4,1> HexstringConstraint; typedef StringSizeAndValueListConstraint<4,1> HexstringConstraint;
typedef StringSizeAndValueListConstraint<8,2> OctetstringConstraint; // one char is half octet typedef StringSizeAndValueListConstraint<8,2> OctetstringConstraint; // one char is half octet
......
...@@ -1896,7 +1896,7 @@ optDecodedModifier ...@@ -1896,7 +1896,7 @@ optDecodedModifier
%left '*' '/' ModKeyword RemKeyword %left '*' '/' ModKeyword RemKeyword
%left UnarySign %left UnarySign
%expect 66 %expect 67
%start GrammarRoot %start GrammarRoot
...@@ -1909,7 +1909,7 @@ For 9 tokens the parser cannot decide whether the token is a part of ...@@ -1909,7 +1909,7 @@ For 9 tokens the parser cannot decide whether the token is a part of
the return expression (shift) or it is the beginning of the next statement the return expression (shift) or it is the beginning of the next statement
(reduce). (reduce).
2.) 10 distinct states, each with one conflict caused by token '[' 2.) 11 distinct states, each with one conflict caused by token '['
The local definitions in altsteps can be followed immediately by the guard The local definitions in altsteps can be followed immediately by the guard
expression. When the parser sees the '[' token it cannot decide whether it expression. When the parser sees the '[' token it cannot decide whether it
belongs to the local definition as array dimension or array subreference belongs to the local definition as array dimension or array subreference
...@@ -1925,6 +1925,7 @@ The situations are the following: ...@@ -1925,6 +1925,7 @@ The situations are the following:
- var template t v <here> [ - var template t v <here> [
- var t v := function(...)<subrefs> <here> [ - var t v := function(...)<subrefs> <here> [
- var template t v := decmatch (...) ref <here> [ - var template t v := decmatch (...) ref <here> [
- var t v := valueof(...)<subrefs> <here> [
3.) 1 conflict 3.) 1 conflict
The sequence identifier.objid can be either the beginning of a module name The sequence identifier.objid can be either the beginning of a module name
...@@ -4177,8 +4178,19 @@ MatchOp: // 160 ...@@ -4177,8 +4178,19 @@ MatchOp: // 160
ValueofOp: // 162 ValueofOp: // 162
ValueofKeyword '(' optError TemplateInstance optError ')' ValueofKeyword '(' optError TemplateInstance optError ')'
optExtendedFieldReference
{ {
if ($7.nElements == 0) {
$$ = new Value(Value::OPTYPE_VALUEOF, $4); $$ = new Value(Value::OPTYPE_VALUEOF, $4);
}
else {
FieldOrArrayRefs* subrefs = new FieldOrArrayRefs;
for (size_t i = 0; i < $7.nElements; ++i) {
subrefs->add($7.elements[i]);
}
Free($7.elements);
$$ = new Value(Value::OPTYPE_VALUEOF, $4, subrefs);
}
$$->set_location(infile, @$); $$->set_location(infile, @$);
} }
| ValueofKeyword '(' error ')' | ValueofKeyword '(' error ')'
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
TOPDIR := .. TOPDIR := ..
include $(TOPDIR)/Makefile.regression include $(TOPDIR)/Makefile.regression
ADIRS = parse errorMessages errorMessages2 transformations keyword hyphen enum1 enum2 codeGeneration2 Test38 Test303 Test307 Test308 Test309 Test310 Test338 Test340 Test342 Test344 Test346 Test348 Test350 Test352 Test354 Test356 Test358 Test360 ADIRS = parse errorMessages errorMessages2 transformations keyword hyphen enum1 enum2 codeGeneration2 Test38 Test303 Test307 Test308 Test309 Test310 Test338 Test340 Test342 Test344 Test346 Test348 Test350 Test352 Test354 Test356 Test358 Test360 namedBits
#still not OK: Test330 Test332 #still not OK: Test330 Test332
......
namedBits
namedBits.exe
NamedBits*.cc
NamedBits*.hh
Tests*.cc
Tests*.hh
namedBits*.log
##############################################################################
# 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 – initial implementation
#
##############################################################################
TOPDIR := ../..
include $(TOPDIR)/Makefile.regression
.SUFFIXES: .ttcn .asn .hh
.PHONY: all clean dep run
TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
TTCN3_MODULES = Tests.ttcn
ASN1_MODULES = NamedBits.asn
GENERATED_SOURCES