Commit 78a82971 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

Implemented operation 'port.getref()' (bug 533006)



Change-Id: I9158d29e0e81ed2265a148081d8bcea6f3e82025
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 39400ac7
......@@ -171,6 +171,9 @@ namespace Common {
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_GET_PORT_REF:
u.expr.type = p.u.expr.type; // the type is not owned, don't copy it
break;
case OPTYPE_COMP_RUNNING: // v1 [r2] b4
case OPTYPE_COMP_ALIVE:
u.expr.r2 = p.u.expr.r2 != NULL ? p.u.expr.r2->clone() : NULL;
......@@ -526,6 +529,7 @@ namespace Common {
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
case OPTYPE_GET_PORT_REF: // type (not owned)
break;
case OPTYPE_COMP_RUNNING: // v1 [r2] b4
case OPTYPE_COMP_ALIVE:
......@@ -928,6 +932,9 @@ namespace Common {
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_GET_PORT_REF:
u.expr.type = NULL; // will be set during semantic analysis
break;
default:
FATAL_ERROR("Value::Value()");
} // switch
......@@ -1751,6 +1758,7 @@ namespace Common {
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
case OPTYPE_GET_PORT_REF:
break;
case OPTYPE_UNARYPLUS: // v1
case OPTYPE_UNARYMINUS:
......@@ -1998,6 +2006,7 @@ namespace Common {
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
case OPTYPE_GET_PORT_REF:
break;
case OPTYPE_COMP_RUNNING: // v1 [r2] b4
case OPTYPE_COMP_ALIVE:
......@@ -2373,6 +2382,7 @@ namespace Common {
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
case OPTYPE_GET_PORT_REF:
break;
case OPTYPE_COMP_RUNNING: // v1 [r2] b4
case OPTYPE_COMP_ALIVE:
......@@ -3345,6 +3355,8 @@ namespace Common {
return Type::T_BOOL;
case OPTYPE_GETVERDICT:
return Type::T_VERDICT;
case OPTYPE_GET_PORT_REF:
return Type::T_PORT;
case OPTYPE_VALUEOF: {
Error_Context cntxt(this, "In the operand of operation `%s'",
get_opname());
......@@ -3790,6 +3802,9 @@ namespace Common {
} else return 0;
case OPTYPE_COMP_CREATE:
return chk_expr_operand_comptyperef_create();
case OPTYPE_GET_PORT_REF:
chk_expr_operands(NULL, exp_val); // calculate the port type
return u.expr.type;
default:
break;
}
......@@ -4079,6 +4094,8 @@ namespace Common {
return "ttcn2string()";
case OPTYPE_PROF_RUNNING:
return "@profiler.running";
case OPTYPE_GET_PORT_REF:
return "port.getref()";
default:
FATAL_ERROR("Value::get_opname()");
} // switch
......@@ -6876,6 +6893,26 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
break;
case OPTYPE_GET_PORT_REF:
if (u.expr.type == NULL) {
Ttcn::PortScope* port_scope = my_scope->get_scope_port();
if (port_scope == NULL) {
error("Operation `%s' can only be used in a function with a port clause.",
opname);
set_valuetype(V_ERROR);
break;
}
u.expr.type = port_scope->get_port_type();
if (u.expr.type == NULL) {
FATAL_ERROR("Value::chk_expr_operands");
}
if (my_governor != NULL && !u.expr.type->is_identical(my_governor)) {
error("Type mismatch: A value of type `%s' was expected instead of `%s'",
my_governor->get_typename().c_str(), u.expr.type->get_typename().c_str());
set_valuetype(V_ERROR);
}
}
break;
case OPTYPE_COMP_MTC:
case OPTYPE_COMP_SYSTEM:
chk_expr_comptype_compat();
......@@ -7951,6 +7988,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_TMR_RUNNING_ANY:
case OPTYPE_GETVERDICT:
case OPTYPE_PROF_RUNNING:
case OPTYPE_GET_PORT_REF:
case OPTYPE_RNDWITHVAL: // v1
case OPTYPE_COMP_RUNNING: // v1
case OPTYPE_COMP_ALIVE:
......@@ -9275,6 +9313,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_GETVERDICT:
case OPTYPE_TESTCASENAME:
case OPTYPE_PROF_RUNNING:
case OPTYPE_GET_PORT_REF:
case OPTYPE_RNDWITHVAL: // v1
case OPTYPE_MATCH: // v1 t2
case OPTYPE_UNDEF_RUNNING: // v1
......@@ -10949,6 +10988,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_TMR_RUNNING_ANY: // -
case OPTYPE_GETVERDICT: // -
case OPTYPE_PROF_RUNNING: // -
case OPTYPE_GET_PORT_REF: // -
case OPTYPE_CHECKSTATE_ANY:
case OPTYPE_CHECKSTATE_ALL:
break; // nothing to do
......@@ -11825,6 +11865,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
return ret_val; }
case OPTYPE_PROF_RUNNING:
return string("@profiler.running");
case OPTYPE_GET_PORT_REF:
return string("port.getref()");
default:
return string("<unsupported optype>");
} // switch u.expr.v_optype
......@@ -13419,6 +13461,17 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_PROF_RUNNING:
expr->expr = mputstr(expr->expr, "ttcn3_prof.is_running()");
break;
case OPTYPE_GET_PORT_REF: {
string tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id();
expr->preamble = mputprintf(expr->preamble,
"%s* %s = dynamic_cast<%s*>(TTCN_Runtime::get_translation_port());\n"
"if (%s == NULL) TTCN_error(\"Internal error: Conversion of port "
"reference to type `%s' failed.\");\n",
u.expr.type->get_genname_value(my_scope).c_str(), tmp_id.c_str(),
u.expr.type->get_genname_value(my_scope).c_str(), tmp_id.c_str(),
u.expr.type->get_typename().c_str());
expr->expr = mputprintf(expr->expr, "(*%s)", tmp_id.c_str());
break; }
default:
FATAL_ERROR("Value::generate_code_expr_expr()");
}
......@@ -15099,6 +15152,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
case OPTYPE_TTCN2STRING:
case OPTYPE_ENCVALUE_UNICHAR:
case OPTYPE_DECVALUE_UNICHAR:
case OPTYPE_GET_PORT_REF:
return false;
case OPTYPE_COMP_RUNNING: // v1 [r2] b4
case OPTYPE_COMP_ALIVE:
......
......@@ -278,6 +278,8 @@ namespace Common {
OPTYPE_JSON2CBOR, // v1
OPTYPE_BSON2JSON, // v1
OPTYPE_JSON2BSON, // v1
OPTYPE_GET_PORT_REF, // -
NUMBER_OF_OPTYPES // must be last
};
......@@ -343,6 +345,7 @@ namespace Common {
TemplateInstance *ti1;
Ttcn::Ref_base *r1; /**< timer or component */
LogArguments *logargs; /**< arguments of log2str() */
Type* type;
};
union {
Value *v2;
......@@ -413,7 +416,7 @@ namespace Common {
/** Constructor used by V_EXPR "-": RND, TESTCASENAME, COMP_NULL, COMP_MTC,
* COMP_SYSTEM, COMP_SELF, COMP_RUNNING_ANY, COMP_RUNNING_ALL,
* COMP_ALIVE_ALL, COMP_ALIVE_ANY, TMR_RUNNING_ANY, GETVERDICT,
* PROF_RUNNING */
* PROF_RUNNING, OPTYPE_GET_PORT_REF */
Value(operationtype_t p_optype);
/** Constructor used by V_EXPR "v1" or [v1] */
Value(operationtype_t p_optype, Value *p_v1);
......
......@@ -8382,11 +8382,10 @@ namespace Ttcn {
if (!type) FATAL_ERROR("FormalPar::get_Type()");
return type;
}
void FormalPar::chk()
{
if (checked) return;
checked = true;
TemplateInstance *default_value = defval.ti;
defval.ti = 0;
if (type) {
......@@ -8400,6 +8399,8 @@ namespace Ttcn {
case A_PAR_VAL_INOUT:
asstype = A_PAR_PORT;
break;
case A_PAR_PORT:
break; // should only happen in recursive calls
default:
error("Port type `%s' cannot be used as %s",
t->get_fullname().c_str(), get_assname());
......@@ -8428,7 +8429,9 @@ namespace Ttcn {
}
}
} else if (asstype != A_PAR_TIMER) FATAL_ERROR("FormalPar::chk()");
checked = true;
if (default_value) {
Error_Context cntxt(default_value, "In default value");
defval.ap = chk_actual_par(default_value, Type::EXPECTED_STATIC_VALUE);
......@@ -9016,6 +9019,18 @@ namespace Ttcn {
}
return new ActualPar(ref);
} else {
if (ap_template->get_templatetype() == Template::SPECIFIC_VALUE) {
Value* val = ap_template->get_specific_value();
if (val->get_valuetype() == Common::Value::V_EXPR &&
val->get_optype() == Common::Value::OPTYPE_GET_PORT_REF) {
Value *v = ap_template->get_Value(); // steal the value
v->set_my_governor(type);
type->chk_this_value_ref(v);
type->chk_this_value(v, 0, exp_val, INCOMPLETE_NOT_ALLOWED,
OMIT_NOT_ALLOWED, SUB_CHK);
return new ActualPar(v);
}
}
actual_par->error("Reference to a port or port parameter was expected "
"for a port parameter");
return new ActualPar();
......
......@@ -1038,7 +1038,7 @@ namespace Ttcn {
: Node(), Location(), my_type(0), operation_mode(p_operation_mode),
in_list(p_in_list), out_list(p_out_list), inout_list(p_inout_list),
in_all(p_in_all), out_all(p_out_all), inout_all(p_inout_all),
checked(false), legacy(true),
checked(false), attributes_checked(false), legacy(true),
in_msgs(0), out_msgs(0), in_sigs(0), out_sigs(0),
testport_type(TP_REGULAR), port_type(PT_REGULAR),
provider_refs(), provider_types(), mapper_types(),
......@@ -1784,6 +1784,10 @@ namespace Ttcn {
{
if (!w_attrib_path || !checked || !my_type)
FATAL_ERROR("PortTypeBody::chk_attributes()");
if (attributes_checked) {
return;
}
attributes_checked = true;
Ttcn::ExtensionAttributes * extarts = parse_extattributes(w_attrib_path);
if (extarts != 0) { // NULL means parsing error
......
......@@ -390,6 +390,7 @@ private:
Types *in_list, *out_list, *inout_list;
bool in_all, out_all, inout_all; // whether "(in|out|inout) all" was used
bool checked;
bool attributes_checked;
bool legacy; // Old extension syntax or new standard syntax
/* Types and signatures that can be sent and received.
* These are initially empty; filled by PortTypeBody::chk_list based on
......
......@@ -535,6 +535,8 @@ xor4b RETURN(Xor4bKeyword);
"@profiler" RETURN(TitanSpecificProfilerKeyword);
"@update" RETURN(TitanSpecificUpdateKeyword);
"getref" RETURN_DOT(GetRefKeyword);
/* Predefined function identifiers */
bit2hex RETURN(bit2hexKeyword);
......
......@@ -684,6 +684,7 @@ static const string anyname("anytype");
%token FromKeyword
%token FunctionKeyword
%token GetCallOpKeyword
%token GetRefKeyword
%token GetReplyOpKeyword
%token GetVerdictKeyword
%token GotoKeyword
......@@ -819,6 +820,7 @@ static const string anyname("anytype");
%token DotCreateKeyword
%token DotDoneKeyword
%token DotGetCallOpKeyword
%token DotGetRefKeyword
%token DotGetReplyOpKeyword
%token DotHaltKeyword
%token DotKillKeyword
......@@ -1899,16 +1901,16 @@ optDecodedModifier
%left '*' '/' ModKeyword RemKeyword
%left UnarySign
%expect 67
%expect 69
%start GrammarRoot
/*
XXX Source of conflicts (66 S/R):
XXX Source of conflicts (69 S/R):
1.) 9 conflicts in one state
1.) 10 conflicts in one state
The Expression after 'return' keyword is optional in ReturnStatement.
For 9 tokens the parser cannot decide whether the token is a part of
For 10 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
(reduce).
......@@ -1947,7 +1949,7 @@ non-standard language extension.
7.) 27 conflicts in one state
In the DecodedContentMatch rule a SingleExpression encased in round brackets is
followed by an in-line template. For 26 tokens (after the ')' ) the parser cannot
followed by an in-line template. For 27 tokens (after the ')' ) the parser cannot
decide whether the token is the beginning of the in-line template (shift) or
the brackets are only part of the SingleExpression itself and the conflicting
token is the next segment in the expression (reduce).
......@@ -9437,6 +9439,11 @@ OpCall: // 611
$$ = new Value(Value::OPTYPE_CHECKSTATE_ALL, r, $5);
$$->set_location(infile, @$);
}
| PortKeyword DotGetRefKeyword '(' ')'
{
$$ = new Value(Value::OPTYPE_GET_PORT_REF);
$$->set_location(infile, @$);
}
;
PredefinedOps:
......
......@@ -141,6 +141,13 @@ void TTCN_Runtime::set_port_state(const INTEGER& state, const CHARSTRING& info,
}
}
PORT* TTCN_Runtime::get_translation_port() {
if (p == NULL) {
TTCN_error("Operation 'port.getref' was called while not in a port translation procedure.");
}
return p;
}
void TTCN_Runtime::set_translation_mode(boolean enabled, PORT* port) {
if (enabled) {
translation_count++;
......
......@@ -135,6 +135,7 @@ public:
static void set_port_state(const INTEGER& state, const CHARSTRING& info, boolean by_system);
static void set_translation_mode(boolean enabled, PORT* port);
static PORT* get_translation_port();
private:
inline static boolean in_controlpart()
......
......@@ -208,8 +208,19 @@ module PortTranslation {
extension "prototype(fast)";
}
function char_to_hex3(in charstring i, out hexstring j) {
function f_port_ref_test(PT3 p1, inout PT3 p2)
{
if (log2str(p1) != "port p3") {
setverdict(fail, "First port argument is invalid. Expected port p3, got: ", p1);
}
if (log2str(p2) != "port p3") {
setverdict(fail, "First port argument is invalid. Expected port p3, got: ", p1);
}
}
function char_to_hex3(in charstring i, out hexstring j) port PT3 {
j := oct2hex(char2oct(i));
f_port_ref_test(port.getref(), port.getref());
port.setstate(0); // translated
} with {
extension "prototype(fast)";
......@@ -788,7 +799,8 @@ module PortTranslation {
}
// This tests the 'discard' option in the 'setstate' operation when receiving
testcase tc_receive_discarded() runs on MyComp system System {
// It also tests the operation 'port.getref()'
testcase tc_receive_discarded_plus_port_ref() runs on MyComp system System {
map(self:p3, system:p4);
p3.send(123);
......@@ -810,6 +822,7 @@ module PortTranslation {
// an integer (-10) and a charstring ("abc") are received on the provider port,
// the translation functions discard the integer and convert the charstring into a hexstring,
// so only the hexstring is received on the main port
// (the charstring-to-hexstring translation function also contains tests for operation 'port.getref()')
alt {
[] p3.receive(hexstring: '616263'H) { setverdict(pass); }
[] p3.receive(hexstring: ?) -> value bad { setverdict(fail, "Test #2 failed. Received invalid hexstring: ", bad); }
......@@ -836,7 +849,7 @@ module PortTranslation {
execute(tc_receive_partially_translated());
execute(tc_receive_fragmented());
execute(tc_receive_discarded());
execute(tc_receive_discarded_plus_port_ref());
}
}
......@@ -253,7 +253,7 @@ static void printUsage(const char * argv0) {
" -f|J file: the names of XSD files are taken from file instead of the command line\n"
" -g: generate TTCN-3 code disallowing element substitution\n"
" -h: generate TTCN-3 code allowing type substitution\n"
" -m: generate only the UsefulTtcn3Types and XSD predefined modules"
" -m: generate only the UsefulTtcn3Types and XSD predefined modules\n"
" -p: do not generate the UsefulTtcn3Types and XSD predefined modules\n"
" -q: quiet mode - disable the issue of status messages\n"
" -s: parse and validate only - no TTCN-3 module generation\n"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment