1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../../common/dbgnew.hh"
9 #include "Statement.hh"
10 #include "Ttcnstuff.hh"
11 #include "../TypeCompat.hh"
12 #include "../CompType.hh"
13 #include "../CompField.hh"
14 #include "../SigParam.hh"
15 #include "TtcnTemplate.hh"
17 #include "ArrayDimensions.hh"
20 #include "Attributes.hh"
24 // =================================
25 // ===== StatementBlock
26 // =================================
28 StatementBlock::StatementBlock()
29 : Scope(), checked(false), labels_checked(false), my_sb(0), my_def(0), exception_handling(EH_NONE
)
33 StatementBlock::~StatementBlock()
35 for(size_t i
=0; i
<stmts
.size(); i
++)
42 StatementBlock
*StatementBlock::clone() const
44 FATAL_ERROR("StatementBlock::clone");
47 void StatementBlock::dump(unsigned int level
) const
49 size_t n
= stmts
.size();
50 DEBUG(level
, "StatementBlock at %p with %lu", (const void*)this,
52 for (size_t i
= 0; i
< n
; ++i
) {
53 stmts
[i
]->dump(level
+1);
57 void StatementBlock::add_stmt(Statement
*p_stmt
, bool to_front
)
60 FATAL_ERROR("StatementBlock::add_stmt()");
62 stmts
.add_front(p_stmt
);
66 p_stmt
->set_my_scope(this);
67 p_stmt
->set_my_sb(this, stmts
.size()-1);
70 void StatementBlock::set_my_scope(Scope
*p_scope
)
72 set_parent_scope(p_scope
);
73 for(size_t i
=0; i
<stmts
.size(); i
++)
74 stmts
[i
]->set_my_scope(this);
77 void StatementBlock::set_fullname(const string
& p_fullname
)
79 Node::set_fullname(p_fullname
);
80 for(size_t i
=0; i
<stmts
.size(); i
++)
81 stmts
[i
]->set_fullname(p_fullname
+".stmt_"+Int2string(i
+1));
84 /** \todo handle loops and conditional statements */
85 Statement
*StatementBlock::get_first_stmt() const
87 size_t nof_stmts
= stmts
.size();
88 for (size_t i
= 0; i
< nof_stmts
; i
++) {
89 Statement
*stmt
= stmts
[i
];
90 switch (stmt
->get_statementtype()) {
91 case Statement::S_LABEL
:
92 // ignore and go to the next statement
94 case Statement::S_BLOCK
: {
95 // if the block is not empty return its first statement
96 // otherwise go to the next statement
97 Statement
*first_stmt
= stmt
->get_block()->get_first_stmt();
98 if (first_stmt
) return first_stmt
;
100 case Statement::S_DOWHILE
: {
101 // if the block is not empty return its first statement
102 // otherwise return the whole do-while statement
103 Statement
*first_stmt
= stmt
->get_block()->get_first_stmt();
104 if (first_stmt
) return first_stmt
;
113 void StatementBlock::register_def(Definition
*p_def
)
115 if(!p_def
) FATAL_ERROR("StatementBlock::register_def()");
116 const Identifier
& id
=p_def
->get_id();
117 if (defs
.has_key(id
)) {
118 const char *dispname
= id
.get_dispname().c_str();
119 p_def
->error("Duplicate definition with identifier `%s'", dispname
);
120 defs
[id
]->note("Previous definition with identifier `%s' is here",
125 if (parent_scope
->has_ass_withId(id
)) {
126 const char *dispname
= id
.get_dispname().c_str();
127 p_def
->error("Definition with identifier `%s' is not unique"
128 " in the scope hierarchy", dispname
);
129 Reference
ref(0, id
.clone());
130 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
131 if (!ass
) FATAL_ERROR("StatementBlock::register_def()");
132 ass
->note("Previous definition with identifier `%s' in higher "
133 "scope unit is here", dispname
);
134 } else if (parent_scope
->is_valid_moduleid(id
)) {
135 p_def
->warning("Definition with name `%s' hides a module identifier",
136 id
.get_dispname().c_str());
142 bool StatementBlock::has_ass_withId(const Identifier
& p_id
)
144 return defs
.has_key(p_id
) || get_parent_scope()->has_ass_withId(p_id
);
147 Common::Assignment
* StatementBlock::get_ass_bySRef(Ref_simple
*p_ref
)
149 if(p_ref
->get_modid()) return get_parent_scope()->get_ass_bySRef(p_ref
);
150 const Identifier
& id
=*p_ref
->get_id();
151 if(defs
.has_key(id
)) return defs
[id
];
152 else return get_parent_scope()->get_ass_bySRef(p_ref
);
155 Type
*StatementBlock::get_mtc_system_comptype(bool is_system
, bool is_connecting
)
157 // return NULL outside test cases
158 if (!my_def
|| ((is_system
|| !is_connecting
) &&
159 my_def
->get_asstype() != Common::Assignment::A_TESTCASE
)) {
163 Def_Testcase
*t_tc
= dynamic_cast<Def_Testcase
*>(my_def
);
164 if (!t_tc
) FATAL_ERROR("StatementBlock::get_mtc_system_comptype()");
165 Type
*system_ct
= t_tc
->get_SystemType();
166 if (system_ct
) return system_ct
;
167 // otherwise (if the testcase has no system clause) the type of 'system'
168 // is the same as the type of 'mtc' (which is given in 'runs on' clause)
170 return my_def
->get_RunsOnType();
173 Ttcn::StatementBlock
*StatementBlock::get_statementblock_scope()
178 void StatementBlock::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
182 for(size_t i
=0; i
<stmts
.size(); i
++)
183 stmts
[i
]->set_my_sb(this, i
);
186 size_t StatementBlock::get_my_sb_index() const
188 if(!my_sb
) FATAL_ERROR("StatementBlock::get_my_sb_index()");
192 void StatementBlock::set_my_def(Definition
*p_def
)
195 for(size_t i
=0; i
<stmts
.size(); i
++)
196 stmts
[i
]->set_my_def(p_def
);
199 void StatementBlock::set_my_ags(AltGuards
*p_ags
)
201 for(size_t i
=0; i
<stmts
.size(); i
++)
202 stmts
[i
]->set_my_ags(p_ags
);
205 void StatementBlock::set_my_laic_stmt(AltGuards
*p_ags
,
206 Statement
*p_loop_stmt
)
208 for(size_t i
=0; i
<stmts
.size(); i
++)
209 stmts
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
212 StatementBlock::returnstatus_t
StatementBlock::has_return() const
214 returnstatus_t ret_val
= RS_NO
;
215 size_t nof_stmts
= stmts
.size();
216 for (size_t i
= 0; i
< nof_stmts
; i
++) {
217 Statement
*stmt
= stmts
[i
];
218 if (stmt
->get_statementtype() == Statement::S_GOTO
) {
219 if (stmt
->goto_jumps_forward()) {
220 // heuristics without deep analysis of the control flow graph:
221 // skip over the next statements until a (used) label is found
222 // the behaviour will be sound (i.e. no false errors will be reported)
223 for (i
++; i
< nof_stmts
; i
++) {
225 if (stmt
->get_statementtype() == Statement::S_LABEL
&&
226 stmt
->label_is_used()) break;
228 } else return RS_YES
;
229 } else if (stmt
->get_statementtype()==Statement::S_BLOCK
&& stmt
->get_block()->exception_handling
!=EH_NONE
) {
230 switch (stmt
->get_block()->exception_handling
) {
231 case EH_TRY
: // the i-th statement is a try{} statement block, the (i+1)-th must be a catch{} block
232 if ((i
+1)<nof_stmts
&& stmts
[i
+1]->get_statementtype()==Statement::S_BLOCK
&& stmts
[i
+1]->get_block()->exception_handling
==EH_CATCH
) {
233 returnstatus_t try_block_rs
= stmt
->has_return();
234 returnstatus_t catch_block_rs
= stmts
[i
+1]->has_return();
235 // 3 x 3 combinations
236 if (try_block_rs
==catch_block_rs
) {
237 switch (try_block_rs
) {
248 } else { // if next statement is not a catch{} block then that error has already been reported
249 ret_val
= RS_MAYBE
; // assume the catch block was an RS_MAYBE
253 // logically this is part of the preceding try{} block, handle it as part of it, see above case EH_TRY
256 FATAL_ERROR("StatementBlock::has_return()");
259 switch (stmt
->has_return()) {
272 bool StatementBlock::has_receiving_stmt(size_t start_i
) const
274 for(size_t i
=start_i
; i
<stmts
.size(); i
++)
275 if(stmts
[i
]->has_receiving_stmt()) return true;
279 bool StatementBlock::has_def_stmt_i(size_t start_i
) const
281 for(size_t i
=start_i
; i
<stmts
.size(); i
++)
282 if(stmts
[i
]->get_statementtype()==Statement::S_DEF
) return true;
286 size_t StatementBlock::last_receiving_stmt_i() const
288 size_t nof_stmts
= stmts
.size();
290 size_t i
= nof_stmts
;
292 if (stmts
[--i
]->has_receiving_stmt()) return i
;
298 StatementBlock
*StatementBlock::get_parent_block() const
300 for (Scope
*s
= get_parent_scope(); s
; s
=s
->get_parent_scope()) {
301 StatementBlock
*sb
= dynamic_cast<StatementBlock
*>(s
);
307 void StatementBlock::chk_trycatch_blocks(Statement
* s1
, Statement
* s2
) {
308 if (s1
&& s1
->get_statementtype()==Statement::S_BLOCK
&& s1
->get_block()->get_exception_handling()==StatementBlock::EH_TRY
) {
309 if (!(s2
&& s2
->get_statementtype()==Statement::S_BLOCK
&& s2
->get_block()->get_exception_handling()==StatementBlock::EH_CATCH
)) {
310 s1
->error("`try' statement block must be followed by a `catch' block");
313 if (s2
&& s2
->get_statementtype()==Statement::S_BLOCK
&& s2
->get_block()->get_exception_handling()==StatementBlock::EH_CATCH
) {
314 if (!(s1
&& s1
->get_statementtype()==Statement::S_BLOCK
&& s1
->get_block()->get_exception_handling()==StatementBlock::EH_TRY
)) {
315 s2
->error("`catch' statement block must be preceded by a `try' block");
320 void StatementBlock::chk()
324 bool unreach_found
= false;
325 size_t nof_stmts
= stmts
.size();
326 Statement
*prev_stmt
= 0;
327 for (size_t i
= 0; i
< nof_stmts
; i
++) {
328 Statement
*stmt
= stmts
[i
];
330 if (!unreach_found
&& stmt
->get_statementtype() != Statement::S_LABEL
&&
331 prev_stmt
&& prev_stmt
->is_terminating()) {
332 // a statement is unreachable if:
333 // - it is not a label (i.e. goto cannot jump to it)
334 // - it is not the first statement of the block
335 // - the previous statement terminates the control flow
336 stmt
->warning("Control never reaches this statement");
337 unreach_found
= true;
339 // check try-catch statement block usage
340 chk_trycatch_blocks(prev_stmt
, stmt
);
344 chk_trycatch_blocks(prev_stmt
, 0);
349 void StatementBlock::chk_allowed_interleave()
351 size_t nof_stmts
= stmts
.size();
352 for (size_t i
= 0; i
< nof_stmts
; i
++)
353 stmts
[i
]->chk_allowed_interleave();
356 void StatementBlock::chk_labels()
358 if(labels_checked
) return;
359 for(size_t i
=0; i
<stmts
.size(); i
++) {
360 Statement
*st
=stmts
[i
];
361 if(st
->get_statementtype()!=Statement::S_LABEL
) continue;
362 const Identifier
& labelid
=st
->get_labelid();
363 if(has_label(labelid
)) {
364 const char *name
=labelid
.get_dispname().c_str();
365 st
->error("Duplicate label `%s'", name
);
366 Statement
*st2
=get_label(labelid
);
367 st2
->note("Previous definition of label `%s' is here", name
);
369 else labels
.add(labelid
, st
);
374 void StatementBlock::chk_unused_labels()
376 size_t nof_stmts
= stmts
.size();
377 for (size_t i
= 0; i
< nof_stmts
; i
++) {
378 Statement
*stmt
= stmts
[i
];
379 if (stmt
->get_statementtype() == Statement::S_LABEL
&&
380 !stmt
->label_is_used())
381 stmt
->warning("Label `%s' is defined, but not used",
382 stmt
->get_labelid().get_dispname().c_str());
386 bool StatementBlock::has_label(const Identifier
& p_id
) const
388 for (const StatementBlock
*sb
= this; sb
; sb
= sb
->get_parent_block())
389 if (sb
->labels
.has_key(p_id
)) return true;
393 Statement
*StatementBlock::get_label(const Identifier
& p_id
) const
395 for (const StatementBlock
*sb
= this; sb
; sb
= sb
->get_parent_block())
396 if (sb
->labels
.has_key(p_id
)) return sb
->labels
[p_id
];
397 FATAL_ERROR("StatementBlock::get_label()");
401 void StatementBlock::set_code_section(
402 GovernedSimple::code_section_t p_code_section
)
404 for(size_t i
= 0; i
< stmts
.size(); i
++)
405 stmts
[i
]->set_code_section(p_code_section
);
408 char* StatementBlock::generate_code(char *str
)
410 if (exception_handling
==EH_TRY
) {
411 str
= mputstr(str
, "TTCN_TryBlock try_block;\n");
413 if (stmts
.size()>0) {
414 Statement
* first_stmt
= stmts
[0];
415 str
= first_stmt
->generate_code(str
);
416 if (exception_handling
==EH_CATCH
) {
417 if (first_stmt
->get_statementtype()!=Statement::S_DEF
) FATAL_ERROR("StatementBlock::generate_code()");
418 Definition
* error_msg_def
= first_stmt
->get_def();
419 string error_msg_name
= error_msg_def
->get_id().get_name();
420 str
= mputprintf(str
, "%s = ttcn_error.get_message();\n", error_msg_name
.c_str());
423 for(size_t i
=1; i
<stmts
.size(); i
++) {
424 str
= stmts
[i
]->generate_code(str
);
429 void StatementBlock::ilt_generate_code(ILT
*ilt
)
431 size_t nof_stmts
= stmts
.size();
432 if (nof_stmts
== 0) return;
433 char*& str
=ilt
->get_out_branches();
434 size_t last_recv_stmt_i
=last_receiving_stmt_i();
435 // has no receiving stmt
436 if (last_recv_stmt_i
== nof_stmts
) {
437 bool has_def
=has_def_stmt_i();
438 if(has_def
) str
=mputstr(str
, "{\n");
439 for(size_t i
=0; i
<nof_stmts
; i
++)
440 str
=stmts
[i
]->generate_code(str
);
441 if(has_def
) str
=mputstr(str
, "}\n");
444 for(size_t i
=0; i
<=last_recv_stmt_i
; i
++)
445 stmts
[i
]->ilt_generate_code(ilt
);
446 // the last part which does not contain receiving stmt
447 if(last_recv_stmt_i
==nof_stmts
-1) return;
448 bool has_def
=has_def_stmt_i(last_recv_stmt_i
+1);
449 if(has_def
) str
=mputstr(str
, "{\n");
450 for(size_t i
=last_recv_stmt_i
+1; i
<nof_stmts
; i
++)
451 str
=stmts
[i
]->generate_code(str
);
452 if(has_def
) str
=mputstr(str
, "}\n");
455 void StatementBlock::set_parent_path(WithAttribPath
* p_path
)
457 for (size_t i
= 0; i
< stmts
.size(); i
++)
458 stmts
[i
]->set_parent_path(p_path
);
461 // =================================
463 // =================================
465 void Statement::clean_up()
467 switch (statementtype
) {
476 delete undefstartstop
.ref
;
477 delete undefstartstop
.val
;
479 case S_UNKNOWN_INSTANCE
:
480 case S_FUNCTION_INSTANCE
:
481 case S_ALTSTEP_INSTANCE
:
496 case S_STOP_TESTCASE
:
508 delete if_stmt
.elseblock
;
509 delete if_stmt
.elseblock_location
;
516 if(loop
.for_stmt
.varinst
)
517 delete loop
.for_stmt
.init_varinst
;
519 delete loop
.for_stmt
.init_ass
;
520 delete loop
.for_stmt
.finalexpr
;
521 delete loop
.for_stmt
.step
;
524 delete loop
.label_next
;
525 if (loop
.il_label_end
)
526 delete loop
.il_label_end
;
533 delete loop
.label_next
;
534 if (loop
.il_label_end
)
535 delete loop
.il_label_end
;
549 delete port_op
.portref
;
550 delete port_op
.s
.sendpar
;
551 delete port_op
.s
.toclause
;
554 delete port_op
.portref
;
555 delete port_op
.s
.sendpar
;
556 delete port_op
.s
.call
.timer
;
557 delete port_op
.s
.toclause
;
558 delete port_op
.s
.call
.body
;
561 delete port_op
.portref
;
562 delete port_op
.s
.sendpar
;
563 delete port_op
.s
.replyval
;
564 delete port_op
.s
.toclause
;
567 delete port_op
.portref
;
568 delete port_op
.s
.raise
.signature_ref
;
569 delete port_op
.s
.sendpar
;
570 delete port_op
.s
.toclause
;
573 case S_CHECK_RECEIVE
:
575 delete port_op
.portref
;
576 delete port_op
.r
.rcvpar
;
577 delete port_op
.r
.fromclause
;
578 delete port_op
.r
.redirect
.value
;
579 delete port_op
.r
.redirect
.sender
;
582 case S_CHECK_GETCALL
:
583 delete port_op
.portref
;
584 delete port_op
.r
.rcvpar
;
585 delete port_op
.r
.fromclause
;
586 delete port_op
.r
.redirect
.param
;
587 delete port_op
.r
.redirect
.sender
;
590 case S_CHECK_GETREPLY
:
591 delete port_op
.portref
;
592 delete port_op
.r
.rcvpar
;
593 delete port_op
.r
.getreply_valuematch
;
594 delete port_op
.r
.fromclause
;
595 delete port_op
.r
.redirect
.value
;
596 delete port_op
.r
.redirect
.param
;
597 delete port_op
.r
.redirect
.sender
;
601 delete port_op
.portref
;
602 delete port_op
.r
.ctch
.signature_ref
;
603 delete port_op
.r
.rcvpar
;
604 delete port_op
.r
.fromclause
;
605 delete port_op
.r
.redirect
.value
;
606 delete port_op
.r
.redirect
.sender
;
609 delete port_op
.portref
;
610 delete port_op
.r
.fromclause
;
611 delete port_op
.r
.redirect
.sender
;
617 delete port_op
.portref
;
620 delete comp_op
.compref
;
621 delete comp_op
.funcinstref
;
623 case S_START_COMP_REFD
:
624 delete comp_op
.compref
;
625 delete comp_op
.derefered
.value
;
626 delete comp_op
.derefered
.ap_list2
;
631 delete comp_op
.compref
;
634 if (comp_op
.compref
) {
635 delete comp_op
.compref
;
636 delete comp_op
.donereturn
.donematch
;
637 delete comp_op
.donereturn
.redirect
;
644 delete config_op
.compref1
;
645 delete config_op
.portref1
;
646 delete config_op
.compref2
;
647 delete config_op
.portref2
;
650 delete timer_op
.timerref
;
651 delete timer_op
.value
;
655 delete timer_op
.timerref
;
658 delete setverdict
.verdictval
;
659 delete setverdict
.logargs
;
661 case S_TESTCASE_INSTANCE
:
662 delete testcase_inst
.tcref
;
663 delete testcase_inst
.timerval
;
665 case S_TESTCASE_INSTANCE_REFD
:
666 delete execute_refd
.value
;
667 delete execute_refd
.ap_list2
;
668 delete execute_refd
.timerval
;
670 case S_ACTIVATE_REFD
:
671 case S_UNKNOWN_INVOKED
:
672 case S_FUNCTION_INVOKED
:
673 case S_ALTSTEP_INVOKED
:
674 delete fau_refd
.value
;
675 delete fau_refd
.ap_list2
;
682 FATAL_ERROR("Statement::clean_up()");
683 } // switch statementtype
686 Statement::Statement(statementtype_t p_st
)
687 : statementtype(p_st
), my_sb(0)
689 switch(statementtype
) {
701 FATAL_ERROR("Statement::Statement()");
702 } // switch statementtype
705 Statement::Statement(statementtype_t p_st
, Ref_base
*p_ref
, Value
*p_val
)
706 : statementtype(p_st
), my_sb(0)
708 switch(statementtype
) {
710 if (!p_ref
) FATAL_ERROR("Statement::Statement()");
711 undefstartstop
.ref
=p_ref
;
712 undefstartstop
.val
=p_val
;
715 if (!p_ref
|| p_val
) FATAL_ERROR("Statement::Statement()");
716 undefstartstop
.ref
=p_ref
;
717 undefstartstop
.val
=0;
720 FATAL_ERROR("Statement::Statement()");
721 } // switch statementtype
724 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
)
725 : statementtype(p_st
), my_sb(0)
727 switch(statementtype
) {
728 case S_UNKNOWN_INSTANCE
:
729 case S_FUNCTION_INSTANCE
:
730 case S_ALTSTEP_INSTANCE
:
733 FATAL_ERROR("Statement::Statement()");
737 FATAL_ERROR("Statement::Statement()");
738 } // switch statementtype
741 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
742 ParsedActualParameters
*p_ap_list
)
743 : statementtype(p_st
), my_sb(0)
745 switch(statementtype
) {
746 case S_ACTIVATE_REFD
:
747 case S_UNKNOWN_INVOKED
:
748 case S_FUNCTION_INVOKED
:
749 case S_ALTSTEP_INVOKED
:
750 if(!p_derefered_value
|| !p_ap_list
)
751 FATAL_ERROR("Statement::Statement()");
752 fau_refd
.value
= p_derefered_value
;
753 fau_refd
.t_list1
= p_ap_list
;
756 FATAL_ERROR("Statement::Statement()");
760 Statement::Statement(statementtype_t p_st
, Definition
*p_def
)
761 : statementtype(p_st
), my_sb(0)
763 switch(statementtype
) {
766 FATAL_ERROR("Statement::Statement()");
770 FATAL_ERROR("Statement::Statement()");
771 } // switch statementtype
774 Statement::Statement(statementtype_t p_st
, Assignment
*p_ass
)
775 : statementtype(p_st
), my_sb(0)
777 switch(statementtype
) {
780 FATAL_ERROR("Statement::Statement()");
784 FATAL_ERROR("Statement::Statement()");
785 } // switch statementtype
788 Statement::Statement(statementtype_t p_st
, StatementBlock
*p_block
)
789 : statementtype(p_st
), my_sb(0)
791 switch (statementtype
) {
793 if (!p_block
) FATAL_ERROR("Statement::Statement()");
797 FATAL_ERROR("Statement::Statement()");
798 } // switch statementtype
801 Statement::Statement(statementtype_t p_st
, LogArguments
*p_logargs
)
802 : statementtype(p_st
), my_sb(0)
804 switch(statementtype
) {
807 case S_STOP_TESTCASE
:
811 FATAL_ERROR("Statement::Statement()");
812 } // switch statementtype
815 Statement::Statement(statementtype_t p_st
, Identifier
*p_id
)
816 : statementtype(p_st
), my_sb(0)
819 FATAL_ERROR("Statement::Statement()");
820 switch (statementtype
) {
831 go_to
.jumps_forward
= false;
834 FATAL_ERROR("Statement::Statement()");
835 } // switch statementtype
838 Statement::Statement(statementtype_t p_st
, IfClauses
*p_ics
,
839 StatementBlock
*p_block
, Location
*p_loc
)
840 : statementtype(p_st
), my_sb(0)
842 switch(statementtype
) {
845 FATAL_ERROR("Statement::Statement()");
848 if (!p_loc
) FATAL_ERROR("Statement::Statement()");
849 if_stmt
.elseblock
= p_block
;
850 if_stmt
.elseblock_location
= p_loc
;
852 if (p_loc
) FATAL_ERROR("Statement::Statement()");
853 if_stmt
.elseblock
= 0;
854 if_stmt
.elseblock_location
= 0;
858 FATAL_ERROR("Statement::Statement()");
859 } // switch statementtype
862 Statement::Statement(statementtype_t p_st
, Value
*p_expr
, SelectCases
*p_scs
)
863 : statementtype(p_st
), my_sb(0)
865 switch(statementtype
) {
867 if(!p_expr
|| !p_scs
)
868 FATAL_ERROR("Statement::Statement()");
873 FATAL_ERROR("Statement::Statement()");
874 } // switch statementtype
877 Statement::Statement(statementtype_t p_st
, Definitions
*p_defs
,
878 Assignment
*p_ass
, Value
*p_final
,
879 Assignment
*p_step
, StatementBlock
*p_block
)
880 : statementtype(p_st
), my_sb(0)
882 switch (statementtype
) {
883 case S_FOR
: // precisely one of p_defs, p_ass allowed
885 // it came from a for loop which looked like this:
886 // for (var integer foo:=1; foo<10; foo:=foo+1) ;
887 if (p_ass
) FATAL_ERROR("Statement::Statement()");
888 loop
.for_stmt
.varinst
= true;
889 loop
.for_stmt
.init_varinst
= p_defs
;
891 // it came from a for loop which looked like this:
892 // for (foo:=1; foo<10; foo:=foo+1) ;
893 if (!p_ass
) FATAL_ERROR("Statement::Statement()");
894 loop
.for_stmt
.varinst
= false;
895 loop
.for_stmt
.init_ass
= p_ass
;
897 if(!p_final
|| !p_step
|| !p_block
)
898 FATAL_ERROR("Statement::Statement()");
899 loop
.for_stmt
.finalexpr
=p_final
;
900 loop
.for_stmt
.step
=p_step
;
906 loop
.has_cnt_in_ags
=false;
907 loop
.iterate_once
=false; // not used by for
911 FATAL_ERROR("Statement::Statement()");
912 } // switch statementtype
915 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
916 StatementBlock
*p_block
)
917 : statementtype(p_st
), my_sb(0)
919 switch(statementtype
) {
922 if(!p_val
|| !p_block
)
923 FATAL_ERROR("Statement::Statement()");
930 loop
.has_cnt_in_ags
=false;
931 loop
.iterate_once
=false; // used only by do-while
935 FATAL_ERROR("Statement::Statement()");
936 } // switch statementtype
939 Statement::Statement(statementtype_t p_st
, AltGuards
*p_ags
)
940 : statementtype(p_st
), my_sb(0)
942 switch(statementtype
) {
946 FATAL_ERROR("Statement::Statement()");
950 FATAL_ERROR("Statement::Statement()");
951 } // switch statementtype
954 Statement::Statement(statementtype_t p_st
, Template
*p_temp
)
955 : statementtype(p_st
), my_sb(0)
957 switch(statementtype
) {
963 FATAL_ERROR("Statement::Statement()");
964 } // switch statementtype
967 Statement::Statement(statementtype_t p_st
, Value
*p_val
)
968 : statementtype(p_st
), my_sb(0)
970 switch (statementtype
) {
973 FATAL_ERROR("Statement::Statement()");
977 comp_op
.compref
=p_val
;
983 FATAL_ERROR("Statement::Statement()");
984 } // switch statementtype
987 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
988 LogArguments
*p_logargs
)
989 : statementtype(p_st
), my_sb(0)
991 if (!p_val
|| statementtype
!= S_SETVERDICT
)
992 FATAL_ERROR("Statement::Statement()");
993 setverdict
.verdictval
= p_val
;
994 setverdict
.logargs
= p_logargs
;
997 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
998 TemplateInstance
*p_templinst
, Value
*p_val
)
999 : statementtype(p_st
), my_sb(0)
1001 switch(statementtype
) {
1003 if(!p_ref
|| !p_templinst
)
1004 FATAL_ERROR("Statement::Statement()");
1005 port_op
.portref
=p_ref
;
1006 port_op
.s
.sendpar
=p_templinst
;
1007 port_op
.s
.toclause
=p_val
;
1010 FATAL_ERROR("Statement::Statement()");
1011 } // switch statementtype
1014 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1015 TemplateInstance
*p_templinst
, Value
*p_timerval
,
1016 bool p_nowait
, Value
*p_toclause
, AltGuards
*p_callbody
)
1017 : statementtype(p_st
), my_sb(0)
1019 switch(statementtype
) {
1021 if(!p_ref
|| !p_templinst
|| (p_timerval
&& p_nowait
))
1022 FATAL_ERROR("Statement::Statement()");
1023 port_op
.portref
=p_ref
;
1024 port_op
.s
.sendpar
=p_templinst
;
1025 port_op
.s
.call
.timer
=p_timerval
;
1026 port_op
.s
.call
.nowait
=p_nowait
;
1027 port_op
.s
.toclause
=p_toclause
;
1028 port_op
.s
.call
.body
=p_callbody
;
1031 FATAL_ERROR("Statement::Statement()");
1032 } // switch statementtype
1035 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1036 TemplateInstance
*p_templinst
, Value
*p_replyval
,
1038 : statementtype(p_st
), my_sb(0)
1040 switch(statementtype
) {
1042 if(!p_ref
|| !p_templinst
)
1043 FATAL_ERROR("Statement::Statement()");
1044 port_op
.portref
=p_ref
;
1045 port_op
.s
.sendpar
=p_templinst
;
1046 port_op
.s
.replyval
=p_replyval
;
1047 port_op
.s
.toclause
=p_toclause
;
1050 FATAL_ERROR("Statement::Statement()");
1051 } // switch statementtype
1054 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1055 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1057 : statementtype(p_st
), my_sb(0)
1059 switch(statementtype
) {
1061 if(!p_ref
|| !p_templinst
|| !p_sig
)
1062 FATAL_ERROR("Statement::Statement()");
1063 port_op
.portref
=p_ref
;
1064 port_op
.s
.raise
.signature_ref
=p_sig
;
1065 port_op
.s
.raise
.signature
=0;
1066 port_op
.s
.sendpar
=p_templinst
;
1067 port_op
.s
.toclause
=p_toclause
;
1070 FATAL_ERROR("Statement::Statement()");
1071 } // switch statementtype
1074 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1075 TemplateInstance
*p_templinst
,
1076 TemplateInstance
*p_fromclause
,
1077 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1078 : statementtype(p_st
), my_sb(0)
1080 switch(statementtype
) {
1082 case S_CHECK_RECEIVE
:
1084 port_op
.portref
=p_ref
;
1085 port_op
.r
.rcvpar
=p_templinst
;
1086 port_op
.r
.fromclause
=p_fromclause
;
1087 port_op
.r
.redirect
.value
=p_redirectval
;
1088 port_op
.r
.redirect
.param
=0;
1089 port_op
.r
.redirect
.sender
=p_redirectsender
;
1092 FATAL_ERROR("Statement::Statement()");
1093 } // switch statementtype
1096 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1097 TemplateInstance
*p_templinst
,
1098 TemplateInstance
*p_fromclause
,
1099 ParamRedirect
*p_redirectparam
,
1100 Reference
*p_redirectsender
)
1101 : statementtype(p_st
), my_sb(0)
1103 switch(statementtype
) {
1105 case S_CHECK_GETCALL
:
1106 port_op
.portref
=p_ref
;
1107 port_op
.r
.rcvpar
=p_templinst
;
1108 port_op
.r
.fromclause
=p_fromclause
;
1109 port_op
.r
.redirect
.value
=0;
1110 port_op
.r
.redirect
.param
=p_redirectparam
;
1111 port_op
.r
.redirect
.sender
=p_redirectsender
;
1114 FATAL_ERROR("Statement::Statement()");
1115 } // switch statementtype
1118 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1119 TemplateInstance
*p_templinst
,
1120 TemplateInstance
*p_valuematch
,
1121 TemplateInstance
*p_fromclause
,
1122 Reference
*p_redirectval
, ParamRedirect
*p_redirectparam
,
1123 Reference
*p_redirectsender
)
1124 : statementtype(p_st
), my_sb(0)
1126 switch(statementtype
) {
1128 case S_CHECK_GETREPLY
:
1129 if (!p_templinst
&& p_valuematch
) FATAL_ERROR("Statement::Statement()");
1130 port_op
.portref
=p_ref
;
1131 port_op
.r
.rcvpar
=p_templinst
;
1132 port_op
.r
.getreply_valuematch
=p_valuematch
;
1133 port_op
.r
.fromclause
=p_fromclause
;
1134 port_op
.r
.redirect
.value
=p_redirectval
;
1135 port_op
.r
.redirect
.param
=p_redirectparam
;
1136 port_op
.r
.redirect
.sender
=p_redirectsender
;
1139 FATAL_ERROR("Statement::Statement()");
1140 } // switch statementtype
1143 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1144 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1145 bool p_timeout
, TemplateInstance
*p_fromclause
,
1146 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1147 : statementtype(p_st
), my_sb(0)
1149 switch(statementtype
) {
1152 if (((p_sig
|| p_templinst
) && p_timeout
) ||
1153 (p_sig
&& !p_templinst
) || (!p_sig
&& p_templinst
))
1154 FATAL_ERROR("Statement::Statement()");
1155 port_op
.portref
=p_ref
;
1156 port_op
.r
.ctch
.signature_ref
=p_sig
;
1157 port_op
.r
.ctch
.signature
=0;
1158 port_op
.r
.rcvpar
=p_templinst
;
1159 port_op
.r
.ctch
.timeout
=p_timeout
;
1160 port_op
.r
.ctch
.in_call
=false;
1161 port_op
.r
.ctch
.call_has_timer
=false;
1162 port_op
.r
.fromclause
=p_fromclause
;
1163 port_op
.r
.redirect
.value
=p_redirectval
;
1164 port_op
.r
.redirect
.param
=0;
1165 port_op
.r
.redirect
.sender
=p_redirectsender
;
1168 FATAL_ERROR("Statement::Statement()");
1169 } // switch statementtype
1172 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1173 TemplateInstance
*p_fromclause
,
1174 Reference
*p_redirectsender
)
1175 : statementtype(p_st
), my_sb(0)
1177 switch(statementtype
) {
1179 port_op
.portref
=p_ref
; // may be NULL for "any port.check"
1180 port_op
.r
.fromclause
=p_fromclause
;
1181 port_op
.r
.redirect
.value
=0;
1182 port_op
.r
.redirect
.param
=0;
1183 port_op
.r
.redirect
.sender
=p_redirectsender
;
1186 FATAL_ERROR("Statement::Statement()");
1187 } // switch statementtype
1190 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
)
1191 : statementtype(p_st
), my_sb(0)
1193 switch(statementtype
) {
1198 port_op
.portref
=p_ref
;
1202 timer_op
.timerref
=p_ref
;
1205 FATAL_ERROR("Statement::Statement()");
1206 } // switch statementtype
1209 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1210 Ref_pard
*p_funcinst
)
1211 : statementtype(p_st
), my_sb(0)
1213 switch(statementtype
) {
1215 if(!p_compref
|| !p_funcinst
)
1216 FATAL_ERROR("Statement::Statement()");
1217 comp_op
.compref
= p_compref
;
1218 comp_op
.funcinstref
= p_funcinst
;
1221 FATAL_ERROR("Statement::Statement()");
1222 } // switch statementtype
1225 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1226 Value
*p_derefered_value
, ParsedActualParameters
*p_ap_list
)
1227 : statementtype(p_st
), my_sb(0)
1229 switch(statementtype
) {
1230 case S_START_COMP_REFD
:
1231 if(!p_compref
|| !p_derefered_value
|| !p_ap_list
)
1232 FATAL_ERROR("Statement::Statement()");
1233 comp_op
.compref
= p_compref
;
1234 comp_op
.derefered
.value
= p_derefered_value
;
1235 comp_op
.derefered
.t_list1
= p_ap_list
;
1238 FATAL_ERROR("Statement::Statement()");
1242 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1243 TemplateInstance
*p_donematch
, Reference
*p_redirect
)
1244 : statementtype(p_st
), my_sb(0)
1246 switch (statementtype
) {
1248 if (!p_compref
) FATAL_ERROR("Statement::Statement()");
1249 comp_op
.compref
= p_compref
;
1250 comp_op
.donereturn
.donematch
= p_donematch
;
1251 comp_op
.donereturn
.redirect
= p_redirect
;
1254 FATAL_ERROR("Statement::Statement()");
1255 } // switch statementtype
1258 Statement::Statement(statementtype_t p_st
, component_t p_anyall
)
1259 : statementtype(p_st
), my_sb(0)
1261 switch (statementtype
) {
1264 comp_op
.compref
= 0;
1265 comp_op
.any_or_all
= p_anyall
;
1268 FATAL_ERROR("Statement::Statement()");
1269 } // switch statementtype
1272 Statement::Statement(statementtype_t p_st
,
1273 Value
*p_compref1
, Reference
*p_portref1
,
1274 Value
*p_compref2
, Reference
*p_portref2
)
1275 : statementtype(p_st
), my_sb(0)
1277 switch(statementtype
) {
1282 if(!p_compref1
|| !p_portref1
|| !p_compref2
|| !p_portref2
)
1283 FATAL_ERROR("Statement::Statement()");
1284 config_op
.compref1
=p_compref1
;
1285 config_op
.portref1
=p_portref1
;
1286 config_op
.compref2
=p_compref2
;
1287 config_op
.portref2
=p_portref2
;
1290 FATAL_ERROR("Statement::Statement()");
1291 } // switch statementtype
1294 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
, Value
*p_val
)
1295 : statementtype(p_st
), my_sb(0)
1297 switch(statementtype
) {
1298 case S_TESTCASE_INSTANCE
:
1300 FATAL_ERROR("Statement::Statement()");
1301 testcase_inst
.tcref
=p_ref
;
1302 testcase_inst
.timerval
=p_val
;
1305 FATAL_ERROR("Statement::Statement()");
1306 } // switch statementtype
1309 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
1310 TemplateInstances
*p_ap_list
, Value
*p_val
)
1311 : statementtype(p_st
), my_sb(0)
1313 switch(statementtype
) {
1314 case S_TESTCASE_INSTANCE_REFD
:
1315 if(!p_derefered_value
) FATAL_ERROR("Statement::Statement()");
1316 execute_refd
.value
= p_derefered_value
;
1317 execute_refd
.t_list1
= p_ap_list
;
1318 execute_refd
.timerval
= p_val
;
1321 FATAL_ERROR("Statement::Statement()");
1325 Statement::Statement(statementtype_t p_st
, Value
* p_val
, Reference
* p_ref
): statementtype(p_st
), my_sb(0)
1327 if (p_st
!=S_STRING2TTCN
|| p_val
==NULL
|| p_ref
==NULL
) FATAL_ERROR("Statement::Statement()");
1328 str2ttcn
.val
= p_val
;
1329 str2ttcn
.ref
= p_ref
;
1332 Statement::~Statement()
1337 Statement
*Statement::clone() const
1339 FATAL_ERROR("Statement::clone");
1342 void Statement::dump(unsigned int level
) const
1344 DEBUG(level
, "Statement at %p, a(n) %s", (const void *)this,
1346 switch (statementtype
) {
1347 case S_TESTCASE_INSTANCE
:
1348 case S_TESTCASE_INSTANCE_REFD
: {
1349 Common::Value
*v
= execute_refd
.value
;
1353 def
->dump(level
+ 1);
1356 ass
->dump(level
+ 1);
1359 block
->dump(level
+ 1);
1362 if_stmt
.ics
->dump(level
+ 1);
1363 if (if_stmt
.elseblock
) if_stmt
.elseblock
->dump(level
+ 1);
1370 size_t Statement::get_my_sb_index() const
1372 switch (statementtype
) {
1374 return label
.stmt_idx
;
1376 return go_to
.stmt_idx
;
1378 FATAL_ERROR("Statement::get_my_sb_index()");
1383 const char *Statement::get_stmt_name() const
1385 switch(statementtype
) {
1386 case S_ERROR
: return "<erroneous statement>";
1387 case S_START_UNDEF
: return "start";
1388 case S_STOP_UNDEF
: return "stop";
1389 case S_UNKNOWN_INSTANCE
: return "function or altstep instance";
1390 case S_UNKNOWN_INVOKED
: return "function or altstep type invocation";
1391 case S_DEF
: return "definition";
1392 case S_ASSIGNMENT
: return "assignment";
1393 case S_FUNCTION_INSTANCE
: return "function instance";
1394 case S_FUNCTION_INVOKED
: return "function type invocation";
1395 case S_BLOCK
: return "statement block";
1396 case S_LOG
: return "log";
1397 case S_LABEL
: return "label";
1398 case S_GOTO
: return "goto";
1399 case S_IF
: return "if";
1400 case S_SELECT
: return "select-case";
1401 case S_FOR
: return "for";
1402 case S_WHILE
: return "while";
1403 case S_DOWHILE
: return "do-while";
1404 case S_BREAK
: return "break";
1405 case S_CONTINUE
: return "continue";
1406 case S_STOP_EXEC
: return "stop";
1407 case S_STOP_TESTCASE
: return "testcase.stop";
1408 case S_ALT
: return "alt";
1409 case S_REPEAT
: return "repeat";
1410 case S_INTERLEAVE
: return "interleave";
1411 case S_ALTSTEP_INSTANCE
: return "altstep instance";
1412 case S_ALTSTEP_INVOKED
: return "altstep type invocation";
1413 case S_RETURN
: return "return";
1415 case S_ACTIVATE_REFD
:
1417 case S_DEACTIVATE
: return "deactivate";
1418 case S_SEND
: return "send";
1419 case S_CALL
: return "call";
1420 case S_REPLY
: return "reply";
1421 case S_RAISE
: return "raise";
1422 case S_RECEIVE
: return "receive";
1423 case S_TRIGGER
: return "trigger";
1424 case S_GETCALL
: return "getcall";
1425 case S_GETREPLY
: return "getreply";
1426 case S_CATCH
: return "catch";
1427 case S_CHECK
: return "check";
1428 case S_CHECK_RECEIVE
: return "check-receive";
1429 case S_CHECK_GETCALL
: return "check-getcall";
1430 case S_CHECK_GETREPLY
: return "check-getreply";
1431 case S_CHECK_CATCH
: return "check-catch";
1432 case S_CLEAR
: return "clear";
1433 case S_START_PORT
: return "start port";
1434 case S_STOP_PORT
: return "stop port";
1435 case S_HALT
: return "halt";
1437 case S_START_COMP_REFD
:
1438 return "start test component";
1439 case S_STOP_COMP
: return "stop test component";
1440 case S_DONE
: return "done";
1441 case S_KILL
: return "kill";
1442 case S_KILLED
: return "killed";
1443 case S_CONNECT
: return "connect";
1444 case S_MAP
: return "map";
1445 case S_DISCONNECT
: return "disconnect";
1446 case S_UNMAP
: return "unmap";
1447 case S_START_TIMER
: return "start timer";
1448 case S_STOP_TIMER
: return "stop timer";
1449 case S_TIMEOUT
: return "timeout";
1450 case S_SETVERDICT
: return "setverdict";
1451 case S_ACTION
: return "action";
1452 case S_TESTCASE_INSTANCE
:
1453 case S_TESTCASE_INSTANCE_REFD
:
1455 case S_STRING2TTCN
: return "string2ttcn";
1457 FATAL_ERROR("Statement::get_stmt_name()");
1459 } // switch statementtype
1462 const Identifier
& Statement::get_labelid() const
1464 switch (statementtype
) {
1470 FATAL_ERROR("Statement::get_labelid()");
1475 bool Statement::label_is_used() const
1477 if (statementtype
!= S_LABEL
) FATAL_ERROR("Statement::label_is_used()");
1481 bool Statement::goto_jumps_forward() const
1483 if (statementtype
!= S_GOTO
) FATAL_ERROR("Statement::goto_jumps_forward()");
1484 return go_to
.jumps_forward
;
1487 const string
& Statement::get_clabel()
1489 if (statementtype
!= S_LABEL
|| !my_sb
)
1490 FATAL_ERROR("Statement::get_clabel()");
1491 if (!label
.clabel
) label
.clabel
=
1492 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
1493 return *label
.clabel
;
1496 Definition
*Statement::get_def() const
1498 if (statementtype
!= S_DEF
) FATAL_ERROR("Statement::get_def()");
1502 AltGuards
*Statement::get_ags() const
1504 if (statementtype
!= S_ALT
&& statementtype
!= S_INTERLEAVE
)
1505 FATAL_ERROR("Statement::get_ags()");
1509 StatementBlock
*Statement::get_block() const
1511 switch (statementtype
) {
1519 FATAL_ERROR("Statement::get_block()");
1524 void Statement::set_my_scope(Scope
*p_scope
)
1526 switch(statementtype
) {
1537 undefstartstop
.ref
->set_my_scope(p_scope
);
1538 if (undefstartstop
.val
) undefstartstop
.val
->set_my_scope(p_scope
);
1540 case S_UNKNOWN_INSTANCE
:
1541 case S_FUNCTION_INSTANCE
:
1542 case S_ALTSTEP_INSTANCE
:
1544 ref_pard
->set_my_scope(p_scope
);
1547 def
->set_my_scope(p_scope
);
1550 ass
->set_my_scope(p_scope
);
1553 block
->set_my_scope(p_scope
);
1557 case S_STOP_TESTCASE
:
1558 if (logargs
) logargs
->set_my_scope(p_scope
);
1561 if_stmt
.ics
->set_my_scope(p_scope
);
1562 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_scope(p_scope
);
1565 select
.expr
->set_my_scope(p_scope
);
1566 select
.scs
->set_my_scope(p_scope
);
1569 if (loop
.for_stmt
.varinst
) {
1570 loop
.for_stmt
.init_varinst
->set_parent_scope(p_scope
);
1571 loop
.for_stmt
.finalexpr
->set_my_scope(loop
.for_stmt
.init_varinst
);
1572 loop
.for_stmt
.step
->set_my_scope(loop
.for_stmt
.init_varinst
);
1573 loop
.block
->set_my_scope(loop
.for_stmt
.init_varinst
);
1575 loop
.for_stmt
.init_ass
->set_my_scope(p_scope
);
1576 loop
.for_stmt
.finalexpr
->set_my_scope(p_scope
);
1577 loop
.for_stmt
.step
->set_my_scope(p_scope
);
1578 loop
.block
->set_my_scope(p_scope
);
1583 loop
.expr
->set_my_scope(p_scope
);
1584 loop
.block
->set_my_scope(p_scope
);
1588 ags
->set_my_scope(p_scope
);
1591 if (returnexpr
.v
) returnexpr
.v
->set_my_scope(p_scope
);
1592 if (returnexpr
.t
) returnexpr
.t
->set_my_scope(p_scope
);
1595 if (deactivate
) deactivate
->set_my_scope(p_scope
);
1598 port_op
.portref
->set_my_scope(p_scope
);
1599 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1600 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1603 port_op
.portref
->set_my_scope(p_scope
);
1604 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1605 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1606 if(port_op
.s
.call
.timer
) port_op
.s
.call
.timer
->set_my_scope(p_scope
);
1607 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_scope(p_scope
);
1610 port_op
.portref
->set_my_scope(p_scope
);
1611 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1612 if(port_op
.s
.replyval
) port_op
.s
.replyval
->set_my_scope(p_scope
);
1613 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1616 port_op
.portref
->set_my_scope(p_scope
);
1617 port_op
.s
.raise
.signature_ref
->set_my_scope(p_scope
);
1618 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1619 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1622 case S_CHECK_RECEIVE
:
1624 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1625 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1626 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1627 if(port_op
.r
.redirect
.value
)
1628 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1629 if(port_op
.r
.redirect
.sender
)
1630 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1633 case S_CHECK_GETCALL
:
1634 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1635 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1636 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1637 if(port_op
.r
.redirect
.param
)
1638 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1639 if(port_op
.r
.redirect
.sender
)
1640 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1643 case S_CHECK_GETREPLY
:
1644 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1645 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1646 if(port_op
.r
.getreply_valuematch
)
1647 port_op
.r
.getreply_valuematch
->set_my_scope(p_scope
);
1648 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1649 if(port_op
.r
.redirect
.value
)
1650 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1651 if(port_op
.r
.redirect
.param
)
1652 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1653 if(port_op
.r
.redirect
.sender
)
1654 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1658 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1659 if(port_op
.r
.ctch
.signature_ref
)
1660 port_op
.r
.ctch
.signature_ref
->set_my_scope(p_scope
);
1661 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1662 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1663 if(port_op
.r
.redirect
.value
)
1664 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1665 if(port_op
.r
.redirect
.sender
)
1666 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1669 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1670 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1671 if(port_op
.r
.redirect
.sender
)
1672 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1678 if (port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1681 comp_op
.compref
->set_my_scope(p_scope
);
1682 comp_op
.funcinstref
->set_my_scope(p_scope
);
1684 case S_START_COMP_REFD
:
1685 comp_op
.compref
->set_my_scope(p_scope
);
1686 comp_op
.derefered
.value
->set_my_scope(p_scope
);
1687 comp_op
.derefered
.t_list1
->set_my_scope(p_scope
);
1692 if (comp_op
.compref
) comp_op
.compref
->set_my_scope(p_scope
);
1695 if (comp_op
.compref
) {
1696 comp_op
.compref
->set_my_scope(p_scope
);
1697 if (comp_op
.donereturn
.donematch
)
1698 comp_op
.donereturn
.donematch
->set_my_scope(p_scope
);
1699 if (comp_op
.donereturn
.redirect
)
1700 comp_op
.donereturn
.redirect
->set_my_scope(p_scope
);
1707 config_op
.compref1
->set_my_scope(p_scope
);
1708 config_op
.portref1
->set_my_scope(p_scope
);
1709 config_op
.compref2
->set_my_scope(p_scope
);
1710 config_op
.portref2
->set_my_scope(p_scope
);
1713 timer_op
.timerref
->set_my_scope(p_scope
);
1714 if (timer_op
.value
) timer_op
.value
->set_my_scope(p_scope
);
1718 if (timer_op
.timerref
) timer_op
.timerref
->set_my_scope(p_scope
);
1721 setverdict
.verdictval
->set_my_scope(p_scope
);
1722 if (setverdict
.logargs
)
1723 setverdict
.logargs
->set_my_scope(p_scope
);
1725 case S_TESTCASE_INSTANCE
:
1726 testcase_inst
.tcref
->set_my_scope(p_scope
);
1727 if (testcase_inst
.timerval
) testcase_inst
.timerval
->set_my_scope(p_scope
);
1729 case S_TESTCASE_INSTANCE_REFD
:
1730 execute_refd
.value
->set_my_scope(p_scope
);
1731 execute_refd
.t_list1
->set_my_scope(p_scope
);
1732 if(execute_refd
.timerval
) execute_refd
.timerval
->set_my_scope(p_scope
);
1734 case S_ACTIVATE_REFD
:
1735 case S_UNKNOWN_INVOKED
:
1736 case S_FUNCTION_INVOKED
:
1737 case S_ALTSTEP_INVOKED
:
1738 fau_refd
.value
->set_my_scope(p_scope
);
1739 fau_refd
.t_list1
->set_my_scope(p_scope
);
1742 str2ttcn
.val
->set_my_scope(p_scope
);
1743 str2ttcn
.ref
->set_my_scope(p_scope
);
1746 FATAL_ERROR("Statement::set_my_scope()");
1747 } // switch statementtype
1750 void Statement::set_fullname(const string
& p_fullname
)
1752 Node::set_fullname(p_fullname
);
1753 switch (statementtype
) {
1764 undefstartstop
.ref
->set_fullname(p_fullname
+".ref");
1765 if (undefstartstop
.val
)
1766 undefstartstop
.val
->set_fullname(p_fullname
+".val");
1768 case S_UNKNOWN_INSTANCE
:
1769 case S_FUNCTION_INSTANCE
:
1770 case S_ALTSTEP_INSTANCE
:
1772 ref_pard
->set_fullname(p_fullname
+".ref");
1775 def
->set_fullname(p_fullname
+".def");
1778 ass
->set_fullname(p_fullname
+".ass");
1781 block
->set_fullname(p_fullname
+".block");
1785 case S_STOP_TESTCASE
:
1786 if (logargs
) logargs
->set_fullname(p_fullname
+".logargs");
1789 if_stmt
.ics
->set_fullname(p_fullname
+".ifclauses");
1790 if (if_stmt
.elseblock
)
1791 if_stmt
.elseblock
->set_fullname(p_fullname
+".elseblock");
1794 select
.expr
->set_fullname(p_fullname
+".expr");
1795 select
.scs
->set_fullname(p_fullname
+".scs");
1798 if(loop
.for_stmt
.varinst
)
1799 loop
.for_stmt
.init_varinst
->set_fullname(p_fullname
+".init");
1801 loop
.for_stmt
.init_ass
->set_fullname(p_fullname
+".init");
1802 loop
.for_stmt
.finalexpr
->set_fullname(p_fullname
+".final");
1803 loop
.for_stmt
.step
->set_fullname(p_fullname
+".step");
1804 loop
.block
->set_fullname(p_fullname
+".block");
1808 loop
.expr
->set_fullname(p_fullname
+".expr");
1809 loop
.block
->set_fullname(p_fullname
+".block");
1813 ags
->set_fullname(p_fullname
+".ags");
1816 if (returnexpr
.v
) returnexpr
.v
->set_fullname(p_fullname
+".returnexpr");
1817 if (returnexpr
.t
) returnexpr
.t
->set_fullname(p_fullname
+".returnexpr");
1820 if (deactivate
) deactivate
->set_fullname(p_fullname
+".deact");
1823 port_op
.portref
->set_fullname(p_fullname
+".portref");
1824 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1825 if(port_op
.s
.toclause
)
1826 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1829 port_op
.portref
->set_fullname(p_fullname
+".portref");
1830 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1831 if(port_op
.s
.toclause
)
1832 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1833 if(port_op
.s
.call
.timer
)
1834 port_op
.s
.call
.timer
->set_fullname(p_fullname
+".timer");
1835 if(port_op
.s
.call
.body
)
1836 port_op
.s
.call
.body
->set_fullname(p_fullname
+".body");
1839 port_op
.portref
->set_fullname(p_fullname
+".portref");
1840 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1841 if(port_op
.s
.replyval
)
1842 port_op
.s
.replyval
->set_fullname(p_fullname
+".replyval");
1843 if(port_op
.s
.toclause
)
1844 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1847 port_op
.portref
->set_fullname(p_fullname
+".portref");
1848 port_op
.s
.raise
.signature_ref
->set_fullname(p_fullname
+".sign");
1849 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1850 if(port_op
.s
.toclause
)
1851 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1854 case S_CHECK_RECEIVE
:
1856 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1857 if(port_op
.r
.rcvpar
)
1858 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1859 if(port_op
.r
.fromclause
)
1860 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1861 if(port_op
.r
.redirect
.value
)
1862 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1863 if(port_op
.r
.redirect
.sender
)
1864 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1867 case S_CHECK_GETCALL
:
1868 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1869 if(port_op
.r
.rcvpar
)
1870 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1871 if(port_op
.r
.fromclause
)
1872 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1873 if(port_op
.r
.redirect
.param
)
1874 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1875 if(port_op
.r
.redirect
.sender
)
1876 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1879 case S_CHECK_GETREPLY
:
1880 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1881 if(port_op
.r
.rcvpar
)
1882 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1883 if(port_op
.r
.getreply_valuematch
)
1884 port_op
.r
.getreply_valuematch
->set_fullname(p_fullname
+".valmatch");
1885 if(port_op
.r
.fromclause
)
1886 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1887 if(port_op
.r
.redirect
.value
)
1888 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1889 if(port_op
.r
.redirect
.param
)
1890 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1891 if(port_op
.r
.redirect
.sender
)
1892 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1896 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1897 if(port_op
.r
.ctch
.signature_ref
)
1898 port_op
.r
.ctch
.signature_ref
->set_fullname(p_fullname
+".sign");
1899 if(port_op
.r
.rcvpar
)
1900 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1901 if(port_op
.r
.fromclause
)
1902 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1903 if(port_op
.r
.redirect
.value
)
1904 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1905 if(port_op
.r
.redirect
.sender
)
1906 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1909 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1910 if(port_op
.r
.fromclause
)
1911 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1912 if(port_op
.r
.redirect
.sender
)
1913 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1919 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1922 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1923 comp_op
.funcinstref
->set_fullname(p_fullname
+".funcref");
1925 case S_START_COMP_REFD
:
1926 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1927 comp_op
.derefered
.value
->set_fullname(p_fullname
+".funcref");
1928 comp_op
.derefered
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1933 if (comp_op
.compref
) comp_op
.compref
->set_fullname(p_fullname
+".compref");
1936 if(comp_op
.compref
) {
1937 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1938 if(comp_op
.donereturn
.donematch
)
1939 comp_op
.donereturn
.donematch
->set_fullname(p_fullname
+".donematch");
1940 if(comp_op
.donereturn
.redirect
)
1941 comp_op
.donereturn
.redirect
->set_fullname(p_fullname
+".redir");
1948 config_op
.compref1
->set_fullname(p_fullname
+".compref1");
1949 config_op
.portref1
->set_fullname(p_fullname
+".portref1");
1950 config_op
.compref2
->set_fullname(p_fullname
+".compref2");
1951 config_op
.portref2
->set_fullname(p_fullname
+".portref2");
1954 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1955 if(timer_op
.value
) timer_op
.value
->set_fullname(p_fullname
+".timerval");
1959 if (timer_op
.timerref
)
1960 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1963 setverdict
.verdictval
->set_fullname(p_fullname
+".verdictval");
1964 if (setverdict
.logargs
)
1965 setverdict
.logargs
->set_fullname(p_fullname
+".verdictreason");
1967 case S_TESTCASE_INSTANCE
:
1968 testcase_inst
.tcref
->set_fullname(p_fullname
+".tcref");
1969 if (testcase_inst
.timerval
)
1970 testcase_inst
.timerval
->set_fullname(p_fullname
+".timerval");
1972 case S_TESTCASE_INSTANCE_REFD
:
1973 execute_refd
.value
->set_fullname(p_fullname
+".tcref");
1974 execute_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1975 if(execute_refd
.timerval
)
1976 execute_refd
.timerval
->set_fullname(p_fullname
+".timerval");
1978 case S_ACTIVATE_REFD
:
1979 case S_UNKNOWN_INVOKED
:
1980 case S_FUNCTION_INVOKED
:
1981 case S_ALTSTEP_INVOKED
:
1982 fau_refd
.value
->set_fullname(p_fullname
+".ref");
1983 fau_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1986 str2ttcn
.val
->set_fullname(p_fullname
+".ti");
1987 str2ttcn
.ref
->set_fullname(p_fullname
+".ref");
1990 FATAL_ERROR("Statement::set_fullname()");
1991 } // switch statementtype
1994 void Statement::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
1997 switch(statementtype
) {
1999 block
->set_my_sb(p_sb
, p_index
);
2002 label
.stmt_idx
= p_index
;
2005 go_to
.stmt_idx
= p_index
;
2008 if_stmt
.ics
->set_my_sb(p_sb
, p_index
);
2009 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_sb(p_sb
, p_index
);
2012 select
.scs
->set_my_sb(p_sb
, p_index
);
2017 loop
.block
->set_my_sb(p_sb
, p_index
);
2021 ags
->set_my_sb(p_sb
, p_index
);
2024 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_sb(p_sb
, p_index
);
2028 } // switch statementtype
2031 void Statement::set_my_def(Definition
*p_def
)
2033 switch (statementtype
) {
2035 block
->set_my_def(p_def
);
2038 if_stmt
.ics
->set_my_def(p_def
);
2039 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_def(p_def
);
2042 select
.scs
->set_my_def(p_def
);
2047 loop
.block
->set_my_def(p_def
);
2051 ags
->set_my_def(p_def
);
2054 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_def(p_def
);
2058 } // switch statementtype
2061 void Statement::set_my_ags(AltGuards
*p_ags
)
2063 switch (statementtype
) {
2065 block
->set_my_ags(p_ags
);
2068 if_stmt
.ics
->set_my_ags(p_ags
);
2069 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_ags(p_ags
);
2072 select
.scs
->set_my_ags(p_ags
);
2077 loop
.block
->set_my_ags(p_ags
);
2084 } // switch statementtype
2087 void Statement::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
2089 switch (statementtype
) {
2091 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2094 if_stmt
.ics
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2095 if (if_stmt
.elseblock
)
2096 if_stmt
.elseblock
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2099 select
.scs
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2104 ags
->set_my_laic_stmt(0, p_loop_stmt
); // ags is set later
2107 if (p_loop_stmt
&& port_op
.s
.call
.body
)
2108 port_op
.s
.call
.body
->set_my_laic_stmt(0, p_loop_stmt
);
2114 brk_cnt
.loop_stmt
=p_loop_stmt
;
2119 } // switch statementtype
2122 /** \todo handle blocks, loops and conditional statements
2123 * (i.e. investigate their last statements within the block) */
2124 bool Statement::is_terminating() const
2126 switch (statementtype
) {
2131 case S_STOP_TESTCASE
:
2137 // checking for self.stop, self.kill, mtc.stop and mtc.kill
2138 if (comp_op
.compref
) {
2139 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
2140 if (v_last
->get_valuetype() == Value::V_EXPR
) {
2141 switch (v_last
->get_optype()) {
2142 case Value::OPTYPE_COMP_SELF
:
2143 case Value::OPTYPE_COMP_MTC
:
2153 if(!loop
.expr
->is_unfoldable() && loop
.expr
->get_val_bool()) {
2154 return !loop
.has_brk
; // not endless loop if it has a break
2162 StatementBlock::returnstatus_t
Statement::has_return() const
2164 switch (statementtype
) {
2166 return block
->has_return();
2168 return if_stmt
.ics
->has_return(if_stmt
.elseblock
);
2170 return select
.scs
->has_return();
2173 if (loop
.block
->has_return() == StatementBlock::RS_NO
)
2174 return StatementBlock::RS_NO
;
2175 else return StatementBlock::RS_MAYBE
;
2177 return loop
.block
->has_return();
2179 StatementBlock::returnstatus_t ret_val
= ags
->has_return();
2180 if (ret_val
== StatementBlock::RS_YES
&& !ags
->has_else()) {
2181 // the invoked defaults may skip the entire statement
2182 ret_val
= StatementBlock::RS_MAYBE
;
2186 if (port_op
.s
.call
.body
) return port_op
.s
.call
.body
->has_return();
2187 else return StatementBlock::RS_NO
;
2189 if (is_terminating()) return StatementBlock::RS_YES
;
2190 else return StatementBlock::RS_NO
;
2194 bool Statement::is_receiving_stmt() const
2196 switch (statementtype
) {
2199 case S_ALTSTEP_INSTANCE
:
2200 case S_ALTSTEP_INVOKED
:
2202 case S_CHECK_RECEIVE
:
2205 case S_CHECK_GETCALL
:
2207 case S_CHECK_GETREPLY
:
2217 } // switch statementtype
2220 bool Statement::has_receiving_stmt() const
2222 switch (statementtype
) {
2225 case S_FUNCTION_INSTANCE
:
2226 case S_FUNCTION_INVOKED
:
2235 case S_STOP_TESTCASE
:
2239 case S_ACTIVATE_REFD
:
2249 case S_START_COMP_REFD
:
2259 case S_TESTCASE_INSTANCE
:
2260 case S_TESTCASE_INSTANCE_REFD
:
2264 case S_ALTSTEP_INSTANCE
:
2265 case S_ALTSTEP_INVOKED
:
2267 case S_CHECK_RECEIVE
:
2270 case S_CHECK_GETCALL
:
2272 case S_CHECK_GETREPLY
:
2281 return block
->has_receiving_stmt();
2283 return if_stmt
.ics
->has_receiving_stmt()
2284 || (if_stmt
.elseblock
&& if_stmt
.elseblock
->has_receiving_stmt());
2286 return select
.scs
->has_receiving_stmt();
2290 return loop
.block
->has_receiving_stmt();
2292 return port_op
.s
.call
.body
&& port_op
.s
.call
.body
->has_receiving_stmt();
2296 case S_UNKNOWN_INSTANCE
:
2297 case S_UNKNOWN_INVOKED
:
2299 FATAL_ERROR("Statement::has_receiving_stmt()");
2300 } // switch statementtype
2303 bool Statement::can_repeat() const
2305 switch (statementtype
) {
2311 case S_CHECK_RECEIVE
:
2313 case S_CHECK_GETCALL
:
2315 case S_CHECK_GETREPLY
:
2322 FATAL_ERROR("Statement::can_repeat()");
2323 } // switch statementtype
2326 void Statement::chk()
2328 switch (statementtype
) {
2337 case S_UNKNOWN_INSTANCE
:
2338 chk_unknown_instance();
2340 case S_UNKNOWN_INVOKED
:
2341 case S_FUNCTION_INVOKED
:
2342 case S_ALTSTEP_INVOKED
:
2343 chk_unknown_invoke();
2347 my_sb
->register_def(def
);
2352 case S_FUNCTION_INSTANCE
:
2360 case S_STOP_TESTCASE
:
2361 chk_log_action(logargs
);
2402 case S_ALTSTEP_INSTANCE
:
2411 case S_ACTIVATE_REFD
:
2412 chk_activate_refd();
2430 case S_CHECK_RECEIVE
:
2435 case S_CHECK_GETCALL
:
2439 case S_CHECK_GETREPLY
:
2455 chk_start_stop_port();
2460 case S_START_COMP_REFD
:
2461 chk_start_comp_refd();
2465 chk_stop_kill_comp();
2486 chk_stop_timer_timeout();
2490 chk_log_action(setverdict
.logargs
); // for checking verdictreason
2492 case S_TESTCASE_INSTANCE
:
2495 case S_TESTCASE_INSTANCE_REFD
:
2502 FATAL_ERROR("Statement::chk()");
2503 } // switch statementtype
2506 void Statement::chk_string2ttcn()
2508 Error_Context
cntxt(this, "In string2ttcn() statement");
2509 str2ttcn
.val
->chk_expr_type(Type::T_CSTR
, "charstring", Type::EXPECTED_DYNAMIC_VALUE
);
2511 Common::Assignment
* refd_ass
= str2ttcn
.ref
->get_refd_assignment();
2512 if (refd_ass
==NULL
) {
2513 error("Could not determine the assignment for second parameter");
2516 switch (refd_ass
->get_asstype()) {
2517 case Definition::A_PAR_VAL_IN
:
2518 case Definition::A_PAR_TEMPL_IN
:
2519 refd_ass
->use_as_lvalue(*str2ttcn
.ref
);
2520 case Definition::A_VAR
:
2521 case Definition::A_VAR_TEMPLATE
:
2522 case Definition::A_PAR_VAL_OUT
:
2523 case Definition::A_PAR_VAL_INOUT
:
2524 case Definition::A_PAR_TEMPL_OUT
:
2525 case Definition::A_PAR_TEMPL_INOUT
:
2526 // valid assignment types
2529 str2ttcn
.ref
->error("Reference to '%s' cannot be used as the second parameter", refd_ass
->get_assname());
2534 delete str2ttcn
.val
;
2535 delete str2ttcn
.ref
;
2536 statementtype
= S_ERROR
;
2539 void Statement::chk_allowed_interleave()
2541 switch (statementtype
) {
2543 block
->chk_allowed_interleave();
2546 error("Label statement is not allowed within an interleave statement");
2549 error("Goto statement is not allowed within an interleave statement");
2552 if_stmt
.ics
->chk_allowed_interleave();
2553 if (if_stmt
.elseblock
) if_stmt
.elseblock
->chk_allowed_interleave();
2556 select
.scs
->chk_allowed_interleave();
2561 loop
.block
->chk_allowed_interleave();
2564 ags
->chk_allowed_interleave();
2567 error("Repeat statement is not allowed within an interleave statement");
2569 case S_ALTSTEP_INSTANCE
:
2570 error("Invocation of an altstep is not allowed within an interleave "
2573 case S_ALTSTEP_INVOKED
:
2574 error("Invocation of an altstep type is not allowed within an interleave"
2578 error("Return statement is not allowed within an interleave statement");
2581 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->chk_allowed_interleave();
2584 // the other statements are allowed
2589 void Statement::chk_start_undef()
2591 Ref_base
*t_ref
= undefstartstop
.ref
;
2592 Value
*t_val
= undefstartstop
.val
;
2593 Common::Assignment
*t_ass
;
2595 Error_Context
cntxt(this, "In start statement");
2596 t_ass
= t_ref
->get_refd_assignment();
2598 if (!t_ass
) goto error
;
2599 switch (t_ass
->get_asstype()) {
2600 case Definition::A_PORT
:
2601 case Definition::A_PAR_PORT
:
2602 statementtype
= S_START_PORT
;
2603 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2604 if (!port_op
.portref
) goto error
;
2606 t_val
->error("Start port operation cannot have argument");
2609 chk_start_stop_port();
2611 case Definition::A_TIMER
:
2612 case Definition::A_PAR_TIMER
:
2613 statementtype
= S_START_TIMER
;
2614 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2615 if (!timer_op
.timerref
) goto error
;
2616 timer_op
.value
= t_val
;
2619 case Definition::A_CONST
:
2620 case Definition::A_EXT_CONST
:
2621 case Definition::A_MODULEPAR
:
2622 case Definition::A_VAR
:
2623 case Definition::A_FUNCTION_RVAL
:
2624 case Definition::A_EXT_FUNCTION_RVAL
:
2625 case Definition::A_PAR_VAL_IN
:
2626 case Definition::A_PAR_VAL_OUT
:
2627 case Definition::A_PAR_VAL_INOUT
:
2628 statementtype
= S_START_COMP
;
2630 error("The argument of start operation is missing, although it cannot "
2631 "be a start timer or start port operation");
2633 } else if (t_val
->get_valuetype() != Value::V_REFD
) {
2634 t_val
->error("The argument of start operation is not a function, "
2635 "although it cannot be a start timer or start port operation");
2638 comp_op
.funcinstref
= t_val
->steal_ttcn_ref_base();
2641 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2642 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2643 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2644 comp_op
.compref
->set_location(*t_ref
);
2648 t_ref
->error("Port, timer or component reference was expected as the "
2649 "operand of start operation instead of %s",
2650 t_ass
->get_description().c_str());
2657 statementtype
= S_ERROR
;
2660 void Statement::chk_stop_undef()
2662 Ref_base
*t_ref
= undefstartstop
.ref
;
2663 Common::Assignment
*t_ass
;
2665 Error_Context
cntxt(this, "In stop statement");
2666 t_ass
= t_ref
->get_refd_assignment();
2668 if (!t_ass
) goto error
;
2669 // Determine what it is that we are trying to stop; change statementtype
2670 switch (t_ass
->get_asstype()) {
2671 case Definition::A_PORT
:
2672 case Definition::A_PAR_PORT
:
2673 statementtype
= S_STOP_PORT
;
2674 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2675 if (!port_op
.portref
) goto error
;
2676 chk_start_stop_port();
2678 case Definition::A_TIMER
:
2679 case Definition::A_PAR_TIMER
:
2680 statementtype
= S_STOP_TIMER
;
2681 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2682 if (!timer_op
.timerref
) goto error
;
2684 chk_stop_timer_timeout();
2686 case Definition::A_CONST
:
2687 case Definition::A_EXT_CONST
:
2688 case Definition::A_MODULEPAR
:
2689 case Definition::A_VAR
:
2690 case Definition::A_FUNCTION_RVAL
:
2691 case Definition::A_EXT_FUNCTION_RVAL
:
2692 case Definition::A_PAR_VAL_IN
:
2693 case Definition::A_PAR_VAL_OUT
:
2694 case Definition::A_PAR_VAL_INOUT
:
2695 statementtype
= S_STOP_COMP
;
2696 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2697 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2698 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2699 comp_op
.compref
->set_location(*t_ref
);
2700 chk_stop_kill_comp();
2703 t_ref
->error("Port, timer or component reference was expected as the "
2704 "operand of stop operation instead of %s",
2705 t_ass
->get_description().c_str());
2711 statementtype
= S_ERROR
;
2714 void Statement::chk_unknown_instance()
2716 Common::Assignment
*t_ass
;
2718 Error_Context
cntxt(this, "In function or altstep instance");
2719 t_ass
= ref_pard
->get_refd_assignment(false);
2721 if (!t_ass
) goto error
;
2722 switch (t_ass
->get_asstype()) {
2723 case Common::Assignment::A_FUNCTION
:
2724 case Common::Assignment::A_FUNCTION_RVAL
:
2725 case Common::Assignment::A_FUNCTION_RTEMP
:
2726 case Common::Assignment::A_EXT_FUNCTION
:
2727 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2728 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2729 statementtype
= S_FUNCTION_INSTANCE
;
2732 case Common::Assignment::A_ALTSTEP
:
2733 statementtype
= S_ALTSTEP_INSTANCE
;
2737 ref_pard
->error("Reference to a function or altstep was expected "
2738 "instead of %s, which cannot be invoked",
2739 t_ass
->get_description().c_str());
2745 statementtype
= S_ERROR
;
2748 void Statement::chk_unknown_invoke()
2750 Error_Context
cntxt(this, "In apply operation");
2751 Type
*t
= fau_refd
.value
->get_expr_governor_last();
2753 switch (t
->get_typetype()) {
2756 case Type::T_FUNCTION
:
2757 statementtype
= S_FUNCTION_INVOKED
;
2758 if (t
->get_function_return_type()) warning("The value returned by "
2759 "function type `%s' is not used", t
->get_typename().c_str());
2761 case Type::T_ALTSTEP
:
2762 statementtype
= S_ALTSTEP_INVOKED
;
2765 fau_refd
.value
->error("A value of type function or altstep was "
2766 "expected instead of `%s'", t
->get_typename().c_str());
2769 my_sb
->chk_runs_on_clause(t
, *this, "call");
2771 ActualParList
*parlist
= new Ttcn::ActualParList
;
2772 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
2773 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
2775 delete fau_refd
.t_list1
;
2778 fau_refd
.ap_list2
= 0;
2780 parlist
->set_fullname(get_fullname());
2781 parlist
->set_my_scope(my_sb
);
2782 fau_refd
.ap_list2
= parlist
;
2788 statementtype
= S_ERROR
;
2791 void Statement::chk_assignment()
2793 Error_Context
cntxt(this, "In variable assignment");
2797 void Statement::chk_function()
2799 Error_Context
cntxt(this, "In function instance");
2800 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
2801 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
2802 if (t_ass
->get_Type())
2803 ref_pard
->warning("The value returned by %s is not used",
2804 t_ass
->get_description().c_str());
2807 void Statement::chk_block()
2809 Error_Context
cntxt(this, "In statement block");
2813 void Statement::chk_log_action(LogArguments
*lga
)
2815 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
2818 if (!semantic_check_only
) lga
->join_strings();
2822 void Statement::chk_goto()
2824 Error_Context
cntxt(this, "In goto statement");
2825 if (!my_sb
->has_label(*go_to
.id
)) {
2826 error("Label `%s' is used, but not defined",
2827 go_to
.id
->get_dispname().c_str());
2829 go_to
.jumps_forward
= false;
2832 Statement
*label_stmt
= my_sb
->get_label(*go_to
.id
);
2833 label_stmt
->label
.used
= true;
2834 StatementBlock
*label_sb
= label_stmt
->get_my_sb();
2835 // the index of the label in its own statement block
2836 size_t label_idx
= label_stmt
->get_my_sb_index();
2837 // the index of the goto statement (or its parent statement) in the
2838 // statement block of the label
2840 if (my_sb
== label_sb
) goto_idx
= go_to
.stmt_idx
;
2842 // the goto statement is within a nested statement block
2843 StatementBlock
*goto_sb
= my_sb
, *parent_sb
= my_sb
->get_my_sb();
2844 while (parent_sb
!= label_sb
) {
2845 // go up until the block of the label is found
2846 if (!parent_sb
) FATAL_ERROR("Statement::chk_goto()");
2847 goto_sb
= parent_sb
;
2848 parent_sb
= parent_sb
->get_my_sb();
2850 goto_idx
= goto_sb
->get_my_sb_index();
2852 if (label_idx
> goto_idx
) {
2853 bool error_flag
= false;
2854 for (size_t i
= goto_idx
+ 1; i
< label_idx
; i
++) {
2855 Statement
*stmt
= label_sb
->get_stmt_byIndex(i
);
2856 if (stmt
->get_statementtype() != S_DEF
) continue;
2858 error("Jump to label `%s' crosses local definition",
2859 go_to
.id
->get_dispname().c_str());
2862 stmt
->note("Definition of %s is here",
2863 stmt
->get_def()->get_description().c_str());
2866 label_stmt
->note("Label `%s' is here",
2867 go_to
.id
->get_dispname().c_str());
2868 go_to
.jumps_forward
= true;
2869 } else go_to
.jumps_forward
= false;
2870 go_to
.label
= label_stmt
;
2873 void Statement::chk_if()
2876 if_stmt
.ics
->chk(unreach
);
2877 if(if_stmt
.elseblock
) {
2878 Error_Context
cntxt(if_stmt
.elseblock_location
, "In else statement");
2879 if(unreach
) if_stmt
.elseblock_location
->warning
2880 ("Control never reaches this code because of previous effective"
2882 if_stmt
.elseblock
->chk();
2887 void Statement::chk_select()
2889 Error_Context
cntxt(this, "In select case statement");
2891 for(int turn
=0; turn
<2; turn
++) {
2892 if(turn
) select
.expr
->set_lowerid_to_ref();
2893 Type::typetype_t tt
=select
.expr
->get_expr_returntype();
2894 t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2895 if(!t_gov
|| tt
==Type::T_ERROR
) {
2896 SelectCases
*scs
=select
.scs
;
2897 for(size_t i
=0; i
<scs
->get_nof_scs(); i
++) {
2898 TemplateInstances
*tis
=scs
->get_sc_byIndex(i
)->get_tis();
2900 for(size_t j
=0; j
<tis
->get_nof_tis(); j
++) {
2901 TemplateInstance
*ti
=tis
->get_ti_byIndex(j
);
2902 if(turn
) ti
->get_Template()->set_lowerid_to_ref();
2903 t_gov
=ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
2904 tt
=ti
->get_expr_returntype(Type::EXPECTED_TEMPLATE
);
2905 if(t_gov
&& tt
!=Type::T_ERROR
) break;
2910 else t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2913 select
.expr
->error("Cannot determine the type of the expression");
2914 t_gov
=Type::get_pooltype(Type::T_ERROR
);
2916 select
.expr
->set_my_governor(t_gov
);
2917 t_gov
->chk_this_value_ref(select
.expr
);
2918 t_gov
->chk_this_value(select
.expr
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
2919 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2920 select
.scs
->chk(t_gov
);
2923 void Statement::chk_for()
2925 Error_Context
cntxt(this, "In for statement");
2926 if (loop
.for_stmt
.varinst
) loop
.for_stmt
.init_varinst
->chk_for();
2927 else loop
.for_stmt
.init_ass
->chk();
2928 loop
.for_stmt
.finalexpr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2929 if(!loop
.for_stmt
.finalexpr
->is_unfoldable()
2930 && !loop
.for_stmt
.finalexpr
->get_val_bool())
2931 loop
.for_stmt
.finalexpr
->warning
2932 ("Control never reaches this code because the"
2933 " final conditional expression evals to false");
2934 loop
.for_stmt
.step
->chk();
2935 loop
.block
->set_my_laic_stmt(0, this);
2939 void Statement::chk_while()
2941 Error_Context
cntxt(this, "In while statement");
2942 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2943 if(!loop
.expr
->is_unfoldable() && !loop
.expr
->get_val_bool())
2944 loop
.expr
->warning("Control never reaches this code because the"
2945 " conditional expression evals to false");
2946 loop
.block
->set_my_laic_stmt(0, this);
2950 void Statement::chk_do_while()
2952 Error_Context
cntxt(this, "In do-while statement");
2953 loop
.block
->set_my_laic_stmt(0, this);
2955 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2958 void Statement::chk_break()
2960 Error_Context
cntxt(this, "In break statement");
2961 if (!brk_cnt
.loop_stmt
&& !brk_cnt
.ags
)
2962 error("Break statement cannot be used outside loops, alt or interleave"
2963 " statements, altsteps or response and exception handling part of call"
2965 if (brk_cnt
.loop_stmt
)
2966 brk_cnt
.loop_stmt
->loop
.has_brk
=true;
2969 void Statement::chk_continue()
2971 Error_Context
cntxt(this, "In continue statement");
2972 if (brk_cnt
.loop_stmt
) {
2973 brk_cnt
.loop_stmt
->loop
.has_cnt
=true;
2974 if (brk_cnt
.ags
) brk_cnt
.loop_stmt
->loop
.has_cnt_in_ags
=true;
2976 error("Continue statement cannot be used outside loops");
2979 void Statement::chk_alt()
2981 Error_Context
cntxt(this, "In alt construct");
2982 ags
->set_my_ags(ags
);
2983 ags
->set_my_laic_stmt(ags
, 0);
2987 void Statement::chk_repeat()
2989 Error_Context
cntxt(this, "In repeat statement");
2990 if (ags
) ags
->repeat_found();
2991 else error("Repeat statement cannot be used outside alt statements, "
2992 "altsteps or response and exception handling part of call operations");
2995 void Statement::chk_interleave()
2997 Error_Context
cntxt(this, "In interleave statement");
2998 ags
->set_my_laic_stmt(ags
, 0);
3000 ags
->chk_allowed_interleave();
3003 void Statement::chk_altstep()
3005 Error_Context
cntxt(this, "In altstep instance");
3006 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
3007 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
3010 void Statement::chk_return()
3012 Error_Context
cntxt(this, "In return statement");
3013 Definition
*my_def
= my_sb
->get_my_def();
3015 error("Return statement cannot be used in the control part. "
3016 "It is allowed only in functions and altsteps");
3019 switch (my_def
->get_asstype()) {
3020 case Definition::A_FUNCTION
:
3022 returnexpr
.t
->error("Unexpected return value. The function does not "
3023 "have return type");
3027 case Definition::A_FUNCTION_RVAL
:
3028 if (!returnexpr
.t
) {
3029 error("Missing return value. The function should return a value of "
3030 "type `%s'", my_def
->get_Type()->get_typename().c_str());
3032 } else if (!returnexpr
.t
->is_Value()) {
3033 returnexpr
.t
->error("A specific value without matching symbols was "
3034 "expected as return value");
3037 returnexpr
.v
= returnexpr
.t
->get_Value();
3038 delete returnexpr
.t
;
3040 Type
*return_type
= my_def
->get_Type();
3041 returnexpr
.v
->set_my_governor(return_type
);
3042 return_type
->chk_this_value_ref(returnexpr
.v
);
3043 return_type
->chk_this_value(returnexpr
.v
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
3044 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
3047 case Definition::A_FUNCTION_RTEMP
:
3048 if (!returnexpr
.t
) {
3049 error("Missing return template. The function should return a template "
3050 "of type `%s'", my_def
->get_Type()->get_typename().c_str());
3053 Type
*return_type
= my_def
->get_Type();
3054 returnexpr
.t
->set_my_governor(return_type
);
3055 return_type
->chk_this_template_ref(returnexpr
.t
);
3056 return_type
->chk_this_template_generic(returnexpr
.t
, INCOMPLETE_NOT_ALLOWED
,
3057 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
3058 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
3059 if (!dfb
) FATAL_ERROR("Statement::chk_return()");
3060 returnexpr
.gen_restriction_check
=
3061 returnexpr
.t
->chk_restriction("return template",
3062 dfb
->get_template_restriction());
3065 case Definition::A_ALTSTEP
:
3067 returnexpr
.t
->error("An altstep cannot return a value");
3072 error("Return statement cannot be used in a %s. It is allowed only in "
3073 "functions and altsteps", my_def
->get_assname());
3078 delete returnexpr
.t
;
3082 void Statement::chk_activate()
3084 Error_Context
cntxt(this, "In activate statement");
3085 if (!ref_pard
->chk_activate_argument()) {
3087 statementtype
= S_ERROR
;
3091 void Statement::chk_activate_refd()
3093 Error_Context
cntxt(this, "In activate statement");
3094 Type
*t
= fau_refd
.value
->get_expr_governor_last();
3096 switch (t
->get_typetype()) {
3099 case Type::T_ALTSTEP
:
3102 fau_refd
.value
->error("A value of type altstep was expected in the "
3103 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
3106 if (t
->get_fat_runs_on_self()) {
3107 fau_refd
.value
->error("The argument of `derefers()' cannot be an altstep "
3108 "reference with 'runs on self' clause");
3111 my_sb
->chk_runs_on_clause(t
, *this, "activate");
3113 ActualParList
*parlist
= new ActualParList
;
3114 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
3115 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
3117 delete fau_refd
.t_list1
;
3120 fau_refd
.ap_list2
= 0;
3123 parlist
->set_fullname(get_fullname());
3124 parlist
->set_my_scope(my_sb
);
3125 fau_refd
.ap_list2
= parlist
;
3126 if (!fp_list
->chk_activate_argument(parlist
,get_fullname().c_str()))
3133 statementtype
= S_ERROR
;
3136 void Statement::chk_deactivate()
3139 Error_Context
cntxt(this, "In deactivate statement");
3140 deactivate
->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE
);
3144 void Statement::chk_send()
3146 Error_Context
cntxt(this, "In send statement");
3147 // checking the port reference
3148 Type
*port_type
= chk_port_ref(port_op
.portref
);
3149 // determining the message type
3151 bool msg_type_determined
= false;
3153 Ttcn::PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3154 TypeSet
*out_msgs
= port_type_body
->get_out_msgs();
3156 if (out_msgs
->get_nof_types() == 1) {
3157 // there is only one outgoing message type
3158 msg_type
= out_msgs
->get_type_byIndex(0);
3160 // there are more than one outgoing message types
3161 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3163 size_t nof_comp_types
=
3164 out_msgs
->get_nof_compatible_types(msg_type
);
3165 if (nof_comp_types
== 0) {
3166 port_op
.s
.sendpar
->error("Message type `%s' is not present on "
3167 "the outgoing list of port type `%s'",
3168 msg_type
->get_typename().c_str(),
3169 port_type
->get_typename().c_str());
3170 } else if (nof_comp_types
> 1) {
3171 port_op
.s
.sendpar
->error("Type of the message is ambiguous: "
3172 "`%s' is compatible with more than one outgoing message types "
3173 "of port type `%s'", msg_type
->get_typename().c_str(),
3174 port_type
->get_typename().c_str());
3177 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3178 "outgoing message");
3181 msg_type_determined
= true;
3182 } else if (port_type_body
->get_operation_mode() ==
3183 PortTypeBody::PO_PROCEDURE
) {
3184 port_op
.portref
->error("Message-based operation `send' is not "
3185 "applicable to a procedure-based port of type `%s'",
3186 port_type
->get_typename().c_str());
3188 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3189 "message types", port_type
->get_typename().c_str());
3192 // determining the message type if it is not done so far
3193 if (!msg_type_determined
) {
3194 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3196 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3197 // checking the parameter (template instance)
3198 port_op
.s
.sendpar
->chk(msg_type
);
3199 // checking for invalid message types
3200 msg_type
= msg_type
->get_type_refd_last();
3201 switch (msg_type
->get_typetype()) {
3202 case Type::T_SIGNATURE
:
3203 port_op
.s
.sendpar
->error("The type of send parameter is signature `%s', "
3204 "which cannot be a message type", msg_type
->get_typename().c_str());
3207 port_op
.s
.sendpar
->error("The type of send parameter is port type `%s', "
3208 "which cannot be a message type", msg_type
->get_typename().c_str());
3210 case Type::T_DEFAULT
:
3211 port_op
.s
.sendpar
->error("The type of send parameter is the `default' "
3212 "type, which cannot be a message type");
3216 // checking for presence of wildcards in the template body
3217 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3218 // checking to clause
3219 chk_to_clause(port_type
);
3222 void Statement::chk_call()
3224 Error_Context
cntxt(this, "In call statement");
3225 // checking the port reference
3226 Type
*port_type
= chk_port_ref(port_op
.portref
);
3227 // determining the signature of the argument
3228 Type
*signature
= 0;
3229 bool signature_determined
= false;
3231 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3232 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3234 if (out_sigs
->get_nof_types() == 1) {
3235 // there is only one outgoing signature
3236 signature
= out_sigs
->get_type_byIndex(0);
3238 // there are more than one outgoing signatures
3239 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3241 if (!out_sigs
->has_type(signature
)) {
3242 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3243 "outgoing list of port type `%s'",
3244 signature
->get_typename().c_str(),
3245 port_type
->get_typename().c_str());
3248 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3252 signature_determined
= true;
3253 } else if (port_type_body
->get_operation_mode() ==
3254 PortTypeBody::PO_MESSAGE
) {
3255 port_op
.portref
->error("Procedure-based operation `call' is not "
3256 "applicable to a message-based port of type `%s'",
3257 port_type
->get_typename().c_str());
3259 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3260 "signatures", port_type
->get_typename().c_str());
3263 if (!signature_determined
)
3264 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3265 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3266 // checking the parameter (template instance)
3267 port_op
.s
.sendpar
->chk(signature
);
3268 signature
= signature
->get_type_refd_last();
3269 bool is_noblock_sig
= false;
3270 Type::typetype_t tt
= signature
->get_typetype();
3272 case Type::T_SIGNATURE
:
3273 // the signature is known and correct
3274 is_noblock_sig
= signature
->is_nonblocking_signature();
3278 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not "
3279 "a signature", signature
->get_typename().c_str());
3281 // checking presence/absence of optional parts
3282 if (is_noblock_sig
) {
3283 if (port_op
.s
.call
.timer
) {
3284 port_op
.s
.call
.timer
->error("A call of non-blocking signature `%s' "
3285 "cannot have call timer", signature
->get_typename().c_str());
3286 } else if (port_op
.s
.call
.nowait
) {
3287 error("A call of non-blocking signature `%s' cannot use the "
3288 "`nowait' keyword", signature
->get_typename().c_str());
3290 if (port_op
.s
.call
.body
) {
3291 error("A call of non-blocking signature `%s' cannot have "
3292 "response and exception handling part",
3293 signature
->get_typename().c_str());
3295 } else if (port_op
.s
.call
.nowait
) {
3296 if (port_op
.s
.call
.body
) {
3297 error("A call with `nowait' keyword cannot have response and "
3298 "exception handling part");
3301 // do not issue any error if the signature is erroneous
3302 // because it could have been a non-blocking one
3303 if (tt
== Type::T_SIGNATURE
&& !port_op
.s
.call
.body
) {
3304 error("Response and exception handling part is missing from "
3305 "blocking call operation");
3308 // checking call timer
3309 if (port_op
.s
.call
.timer
) {
3310 Error_Context
cntxt2(port_op
.s
.call
.timer
, "In call timer value");
3311 port_op
.s
.call
.timer
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
3312 Value
*t_val
= port_op
.s
.call
.timer
->get_value_refd_last();
3313 if (t_val
->get_valuetype() == Value::V_REAL
) {
3314 ttcn3float v_real
= t_val
->get_val_Real();
3316 port_op
.s
.call
.timer
->error("The call timer has "
3317 "negative duration: `%s'", Real2string(v_real
).c_str());
3318 } else if (isSpecialFloatValue(v_real
)) {
3319 port_op
.s
.call
.timer
->error("The call timer duration cannot be %s",
3320 Real2string(v_real
).c_str());
3324 // checking to clause
3325 chk_to_clause(port_type
);
3326 // checking response and exception handling part
3327 if (port_op
.s
.call
.body
) chk_call_body(port_type
, signature
);
3330 void Statement::chk_reply()
3332 Error_Context
cntxt(this, "In reply statement");
3333 // checking the port reference
3334 Type
*port_type
= chk_port_ref(port_op
.portref
);
3335 // determining the signature of the argument
3336 Type
*signature
= 0;
3337 bool signature_determined
= false;
3339 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3340 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3342 if (in_sigs
->get_nof_types() == 1) {
3343 // there is only one incoming signature
3344 signature
= in_sigs
->get_type_byIndex(0);
3346 // there are more than one incoming signatures
3347 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3349 if (!in_sigs
->has_type(signature
)) {
3350 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3351 "incoming list of port type `%s'",
3352 signature
->get_typename().c_str(),
3353 port_type
->get_typename().c_str());
3356 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3360 signature_determined
= true;
3361 } else if (port_type_body
->get_operation_mode() ==
3362 PortTypeBody::PO_MESSAGE
) {
3363 port_op
.portref
->error("Procedure-based operation `reply' is not "
3364 "applicable to a message-based port of type `%s'",
3365 port_type
->get_typename().c_str());
3367 port_op
.portref
->error("Port type `%s' does not have any incoming "
3368 "signatures", port_type
->get_typename().c_str());
3371 if (!signature_determined
)
3372 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3373 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3374 // checking the parameter (template instance)
3375 port_op
.s
.sendpar
->chk(signature
);
3376 signature
= signature
->get_type_refd_last();
3377 Type
*return_type
= 0;
3378 switch (signature
->get_typetype()) {
3379 case Type::T_SIGNATURE
:
3380 // the signature is known and correct
3381 if (signature
->is_nonblocking_signature())
3382 error("Operation `reply' is not applicable to non-blocking signature "
3383 "`%s'", signature
->get_typename().c_str());
3384 else return_type
= signature
->get_signature_return_type();
3385 // checking the presence/absence of reply value
3386 if (port_op
.s
.replyval
) {
3388 port_op
.s
.replyval
->error("Unexpected return value. Signature "
3389 "`%s' does not have return type",
3390 signature
->get_typename().c_str());
3392 } else if (return_type
) {
3393 error("Missing return value. Signature `%s' returns type `%s'",
3394 signature
->get_typename().c_str(),
3395 return_type
->get_typename().c_str());
3400 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not a "
3401 "signature", signature
->get_typename().c_str());
3403 // checking the reply value if present
3404 if (port_op
.s
.replyval
) {
3405 Error_Context
cntxt2(port_op
.s
.replyval
, "In return value");
3406 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3407 port_op
.s
.replyval
->set_my_governor(return_type
);
3408 return_type
->chk_this_value_ref(port_op
.s
.replyval
);
3409 return_type
->chk_this_value(port_op
.s
.replyval
, 0,
3410 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
3413 // checking to clause
3414 chk_to_clause(port_type
);
3417 void Statement::chk_raise()
3419 Error_Context
cntxt(this, "In raise statement");
3420 // checking the port reference
3421 Type
*port_type
= chk_port_ref(port_op
.portref
);
3422 // determining the signature of the exception
3423 port_op
.s
.raise
.signature
=
3424 chk_signature_ref(port_op
.s
.raise
.signature_ref
);
3425 // checking whether the signature is present on the incoming list
3426 // of the respective port type
3428 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3429 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3430 if (port_type_body
->get_operation_mode() ==
3431 PortTypeBody::PO_MESSAGE
) {
3432 port_op
.portref
->error("Procedure-based operation `raise' is not "
3433 "applicable to a message-based port of type `%s'",
3434 port_type
->get_typename().c_str());
3435 } else if (in_sigs
) {
3436 if (port_op
.s
.raise
.signature
) {
3437 if (!in_sigs
->has_type(port_op
.s
.raise
.signature
)) {
3438 port_op
.s
.raise
.signature_ref
->error("Signature `%s' is not "
3439 "present on the incoming list of port type `%s'",
3440 port_op
.s
.raise
.signature
->get_typename().c_str(),
3441 port_type
->get_typename().c_str());
3443 } else if (in_sigs
->get_nof_types() == 1) {
3444 // if the signature is unknown and the port type has exactly one
3445 // incoming signature then use that for further checking
3446 port_op
.s
.raise
.signature
=
3447 in_sigs
->get_type_byIndex(0)->get_type_refd_last();
3450 port_op
.portref
->error("Port type `%s' does not have any incoming "
3451 "signatures", port_type
->get_typename().c_str());
3454 // determining the type of exception
3456 bool exc_type_determined
= false;
3457 if (port_op
.s
.raise
.signature
) {
3458 // the signature is known
3459 SignatureExceptions
*exceptions
=
3460 port_op
.s
.raise
.signature
->get_signature_exceptions();
3462 if (exceptions
->get_nof_types() == 1) {
3463 // the signature has exactly one exception type
3464 // use that for checking
3465 exc_type
= exceptions
->get_type_byIndex(0);
3467 // the signature has more than one exception types
3468 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3470 size_t nof_comp_types
=
3471 exceptions
->get_nof_compatible_types(exc_type
);
3472 if (nof_comp_types
== 0) {
3473 port_op
.s
.sendpar
->error("Type `%s' is not present on the "
3474 "exception list of signature `%s'",
3475 exc_type
->get_typename().c_str(),
3476 port_op
.s
.raise
.signature
->get_typename().c_str());
3477 } else if (nof_comp_types
> 1) {
3478 port_op
.s
.sendpar
->error("Type of the exception is ambiguous: "
3479 "`%s' is compatible with more than one exception types of "
3480 "signature `%s'", exc_type
->get_typename().c_str(),
3481 port_op
.s
.raise
.signature
->get_typename().c_str());
3484 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3488 exc_type_determined
= true;
3490 port_op
.s
.raise
.signature_ref
->error("Signature `%s' does not have "
3491 "exceptions", port_op
.s
.raise
.signature
->get_typename().c_str());
3494 // determining the type of exception if it is not done so far
3495 if (!exc_type_determined
) {
3496 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3498 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3499 // checking the exception template
3500 port_op
.s
.sendpar
->chk(exc_type
);
3501 // checking for invalid exception types
3502 exc_type
= exc_type
->get_type_refd_last();
3503 switch (exc_type
->get_typetype()) {
3504 case Type::T_SIGNATURE
:
3505 port_op
.s
.sendpar
->error("The type of raise parameter is signature `%s', "
3506 "which cannot be an exception type",
3507 exc_type
->get_typename().c_str());
3510 port_op
.s
.sendpar
->error("The type of raise parameter is port type `%s', "
3511 "which cannot be an exception type",
3512 exc_type
->get_typename().c_str());
3514 case Type::T_DEFAULT
:
3515 port_op
.s
.sendpar
->error("The type of raise parameter is the `default' "
3516 "type, which cannot be an exception type");
3520 // checking for presence of wildcards in the template body
3521 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3522 // checking to clause
3523 chk_to_clause(port_type
);
3526 void Statement::chk_receive()
3528 // determining statement type
3529 const char *stmt_name
= get_stmt_name();
3530 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3531 // checking the port reference
3532 Type
*port_type
= chk_port_ref(port_op
.portref
);
3533 // checking the parameter and/or value redirect
3534 if (port_op
.r
.rcvpar
) {
3535 // the receive parameter (template instance) is present
3536 // trying to determine type of the incoming message
3538 bool msg_type_determined
= false, value_redirect_checked
= false;
3540 // the port reference is correct and the port type is known
3541 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3542 TypeSet
*in_msgs
= port_type_body
->get_in_msgs();
3544 if (in_msgs
->get_nof_types() == 1) {
3545 // there is only one incoming message type
3546 // use that for checking
3547 msg_type
= in_msgs
->get_type_byIndex(0);
3549 // there are more than one incoming message types
3550 msg_type
= get_incoming_type(port_op
.r
.rcvpar
,
3551 port_op
.r
.redirect
.value
, value_redirect_checked
);
3553 size_t nof_comp_types
=
3554 in_msgs
->get_nof_compatible_types(msg_type
);
3555 if (nof_comp_types
== 0) {
3556 port_op
.r
.rcvpar
->error("Message type `%s' is not present on "
3557 "the incoming list of port of type `%s'",
3558 msg_type
->get_typename().c_str(),
3559 port_type
->get_typename().c_str());
3560 } else if (nof_comp_types
> 1) {
3561 port_op
.r
.rcvpar
->error("Type of the message is ambiguous: "
3562 "`%s' is compatible with more than one incoming message "
3563 "types of port type `%s'", msg_type
->get_typename().c_str(),
3564 port_type
->get_typename().c_str());
3567 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3568 "incoming message");
3571 msg_type_determined
= true;
3572 } else if (port_type_body
->get_operation_mode() ==
3573 PortTypeBody::PO_PROCEDURE
) {
3574 port_op
.portref
->error("Message-based operation `%s' is not "
3575 "applicable to a procedure-based port of type `%s'", stmt_name
,
3576 port_type
->get_typename().c_str());
3578 port_op
.portref
->error("Port type `%s' does not have any incoming "
3579 "message types", port_type
->get_typename().c_str());
3581 } else if (!port_op
.portref
) {
3582 // the statement refers to 'any port'
3583 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3585 if (port_op
.r
.redirect
.value
) {
3586 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3587 "value redirect", stmt_name
);
3590 if (!msg_type_determined
) {
3591 msg_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3592 value_redirect_checked
);
3594 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3595 // check the template instance using the message type
3596 port_op
.r
.rcvpar
->chk(msg_type
);
3597 // check the value redirect if it is not done so far
3598 if (!value_redirect_checked
)
3599 chk_value_redirect(port_op
.r
.redirect
.value
, msg_type
);
3601 // the statement does not have parameter
3603 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3604 if (!port_type_body
->get_in_msgs()) {
3605 // the port type is known and it does not have incoming messages
3606 if (port_type_body
->get_operation_mode() ==
3607 PortTypeBody::PO_PROCEDURE
) {
3608 port_op
.portref
->error("Message-based operation `%s' is not "
3609 "applicable to a procedure-based port of type `%s'", stmt_name
,
3610 port_type
->get_typename().c_str());
3612 port_op
.portref
->error("Port type `%s' does not have any incoming "
3613 "message types", port_type
->get_typename().c_str());
3617 if (port_op
.r
.redirect
.value
) {
3618 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
3619 "receive parameter");
3620 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3623 // checking from clause and sender redirect
3624 chk_from_clause(port_type
);
3627 void Statement::chk_getcall()
3629 // determining statement type
3630 const char *stmt_name
= get_stmt_name();
3631 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3632 // checking the port reference
3633 Type
*port_type
= chk_port_ref(port_op
.portref
);
3634 if (port_op
.r
.rcvpar
) {
3635 // the parameter (signature template) is present
3636 // determining the signature of the argument
3637 Type
*signature
= 0;
3638 bool signature_determined
= false;
3640 // the port reference is correct and the port type is known
3641 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3642 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3644 if (in_sigs
->get_nof_types() == 1) {
3645 // there is only one incoming signature
3646 signature
= in_sigs
->get_type_byIndex(0);
3648 // there are more than one incoming signatures
3649 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3651 if (!in_sigs
->has_type(signature
)) {
3652 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3653 "incoming list of port type `%s'",
3654 signature
->get_typename().c_str(),
3655 port_type
->get_typename().c_str());
3658 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3662 signature_determined
= true;
3663 } else if (port_type_body
->get_operation_mode() ==
3664 PortTypeBody::PO_MESSAGE
) {
3665 port_op
.portref
->error("Procedure-based operation `%s' is not "
3666 "applicable to a message-based port of type `%s'", stmt_name
,
3667 port_type
->get_typename().c_str());
3669 port_op
.portref
->error("Port type `%s' does not have any incoming "
3670 "signatures", port_type
->get_typename().c_str());
3672 } else if (!port_op
.portref
) {
3673 // the statement refers to 'any port'
3674 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3676 if (port_op
.r
.redirect
.param
) {
3677 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3678 "have parameter redirect", stmt_name
);
3681 if (!signature_determined
)
3682 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3683 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3684 // checking the parameter (template instance)
3685 port_op
.r
.rcvpar
->chk(signature
);
3686 // checking whether the argument is a signature template
3687 // and checking the parameter redirect if present
3688 signature
= signature
->get_type_refd_last();
3689 switch (signature
->get_typetype()) {
3690 case Type::T_SIGNATURE
:
3691 if (port_op
.r
.redirect
.param
)
3692 port_op
.r
.redirect
.param
->chk(signature
, false);
3695 if (port_op
.r
.redirect
.param
)
3696 port_op
.r
.redirect
.param
->chk_erroneous();
3699 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3700 "a signature", signature
->get_typename().c_str());
3701 if (port_op
.r
.redirect
.param
)
3702 port_op
.r
.redirect
.param
->chk_erroneous();
3705 // the statement does not have parameter
3707 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3708 if (!port_type_body
->get_in_sigs()) {
3709 // the port type is known and it does not have incoming signatures
3710 if (port_type_body
->get_operation_mode() ==
3711 PortTypeBody::PO_MESSAGE
) {
3712 port_op
.portref
->error("Procedure-based operation `%s' is not "
3713 "applicable to a message-based port of type `%s'", stmt_name
,
3714 port_type
->get_typename().c_str());
3716 port_op
.portref
->error("Port type `%s' does not have any incoming "
3717 "signatures", port_type
->get_typename().c_str());
3721 if (port_op
.r
.redirect
.param
) {
3722 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3723 "without signature template");
3724 port_op
.r
.redirect
.param
->chk_erroneous();
3727 // checking from clause and sender redirect
3728 chk_from_clause(port_type
);
3731 void Statement::chk_getreply()
3733 // determining statement type
3734 const char *stmt_name
= get_stmt_name();
3735 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3736 // checking the port reference
3737 Type
*port_type
= chk_port_ref(port_op
.portref
);
3738 if (port_op
.r
.rcvpar
) {
3739 // the parameter (signature template) is present
3740 // determining the signature of the argument
3741 Type
*signature
= 0;
3742 bool signature_determined
= false;
3744 // the port reference is correct and the port type is known
3745 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3746 if (port_type_body
->getreply_allowed()) {
3747 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3748 if (out_sigs
->get_nof_types() == 1) {
3749 // there is only one outgoing signature
3750 signature
= out_sigs
->get_type_byIndex(0);
3752 // there are more than one outgoing signatures
3753 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3755 if (!out_sigs
->has_type(signature
)) {
3756 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3757 "outgoing list of port type `%s'",
3758 signature
->get_typename().c_str(),
3759 port_type
->get_typename().c_str());
3762 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3766 signature_determined
= true;
3767 } else if (port_type_body
->get_operation_mode() ==
3768 PortTypeBody::PO_MESSAGE
) {
3769 port_op
.portref
->error("Procedure-based operation `%s' is not "
3770 "applicable to a message-based port of type `%s'", stmt_name
,
3771 port_type
->get_typename().c_str());
3773 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3774 "signatures that support reply", port_type
->get_typename().c_str());
3776 } else if (!port_op
.portref
) {
3777 // the statement refers to 'any port'
3778 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3780 if (port_op
.r
.getreply_valuematch
) {
3781 port_op
.r
.getreply_valuematch
->error("Operation `any port.%s' cannot "
3782 "have value match", stmt_name
);
3784 if (port_op
.r
.redirect
.value
) {
3785 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot "
3786 "have value redirect", stmt_name
);
3788 if (port_op
.r
.redirect
.param
) {
3789 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3790 "have parameter redirect", stmt_name
);
3793 if (!signature_determined
)
3794 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3795 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3796 // checking the parameter (template instance)
3797 port_op
.r
.rcvpar
->chk(signature
);
3798 // checking whether the argument is a signature template
3799 // checking the parameter redirect if present
3800 // and determining the return type of the signature
3801 signature
= signature
->get_type_refd_last();
3802 Type
*return_type
= 0;
3803 switch (signature
->get_typetype()) {
3804 case Type::T_SIGNATURE
:
3805 if (signature
->is_nonblocking_signature())
3806 error("Operation `%s' is not applicable to non-blocking signature "
3807 "`%s'", stmt_name
, signature
->get_typename().c_str());
3808 else return_type
= signature
->get_signature_return_type();
3809 if (port_op
.r
.redirect
.param
)
3810 port_op
.r
.redirect
.param
->chk(signature
, true);
3812 if (port_op
.r
.getreply_valuematch
) {
3813 port_op
.r
.getreply_valuematch
->error("Value match cannot be used "
3814 "because signature `%s' does not have return type",
3815 signature
->get_typename().c_str());
3817 if (port_op
.r
.redirect
.value
) {
3818 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3819 "because signature `%s' does not have return type",
3820 signature
->get_typename().c_str());
3825 if (port_op
.r
.redirect
.param
)
3826 port_op
.r
.redirect
.param
->chk_erroneous();
3829 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3830 "a signature", signature
->get_typename().c_str());
3831 if (port_op
.r
.redirect
.param
)
3832 port_op
.r
.redirect
.param
->chk_erroneous();
3834 // checking the value match if present
3835 if (port_op
.r
.getreply_valuematch
) {
3836 Error_Context
cntxt2(port_op
.s
.replyval
, "In value match");
3837 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3838 port_op
.r
.getreply_valuematch
->chk(return_type
);
3840 // checking the value redirect if present
3841 chk_value_redirect(port_op
.r
.redirect
.value
, return_type
);
3843 // the statement does not have parameter (value match is also omitted)
3845 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3846 if (!port_type_body
->getreply_allowed()) {
3847 // the port type is known and it does not have outgoing signatures
3848 if (port_type_body
->get_operation_mode() ==
3849 PortTypeBody::PO_MESSAGE
) {
3850 port_op
.portref
->error("Procedure-based operation `%s' is not "
3851 "applicable to a message-based port of type `%s'", stmt_name
,
3852 port_type
->get_typename().c_str());
3854 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3855 "signatures that support reply",
3856 port_type
->get_typename().c_str());
3860 if (port_op
.r
.redirect
.value
) {
3861 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3862 "without signature template");
3863 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3865 if (port_op
.r
.redirect
.param
) {
3866 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3867 "without signature template");
3868 port_op
.r
.redirect
.param
->chk_erroneous();
3871 // checking from clause and sender redirect
3872 chk_from_clause(port_type
);
3875 void Statement::chk_catch()
3877 // determining statement type
3878 const char *stmt_name
= get_stmt_name();
3879 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3880 // checking the port reference
3881 Type
*port_type
= chk_port_ref(port_op
.portref
);
3882 // checking the signature reference, parameter and/or value redirect
3883 if (port_op
.r
.ctch
.signature_ref
) {
3884 // the signature reference is present
3885 port_op
.r
.ctch
.signature
=
3886 chk_signature_ref(port_op
.r
.ctch
.signature_ref
);
3887 // checking whether the signature is present on the incoming list
3888 // of the respective port type
3890 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3891 if (port_type_body
->catch_allowed()) {
3892 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3893 if (port_op
.r
.ctch
.signature
) {
3894 if (!out_sigs
->has_type(port_op
.r
.ctch
.signature
)) {
3895 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' is not "
3896 "present on the outgoing list of port type `%s'",
3897 port_op
.r
.ctch
.signature
->get_typename().c_str(),
3898 port_type
->get_typename().c_str());
3900 } else if (out_sigs
->get_nof_types() == 1) {
3901 // if the signature is unknown and the port type has exactly one
3902 // outgoing signature then use that for further checking
3903 port_op
.r
.ctch
.signature
=
3904 out_sigs
->get_type_byIndex(0)->get_type_refd_last();
3906 } else if (port_type_body
->get_operation_mode() ==
3907 PortTypeBody::PO_MESSAGE
) {
3908 port_op
.portref
->error("Procedure-based operation `%s' is not "
3909 "applicable to a message-based port of type `%s'", stmt_name
,
3910 port_type
->get_typename().c_str());
3912 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3913 "signatures that support exceptions",
3914 port_type
->get_typename().c_str());
3916 } else if (!port_op
.portref
) {
3917 // the statement refers to 'any port'
3918 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3920 if (port_op
.r
.redirect
.value
) {
3921 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3922 "value redirect", stmt_name
);
3925 // the receive parameter (template instance) must be also present
3926 // trying to determine type of the exception
3928 bool exc_type_determined
= false, value_redirect_checked
= false;
3929 if (port_op
.r
.ctch
.signature
) {
3930 // the signature is known
3931 SignatureExceptions
*exceptions
=
3932 port_op
.r
.ctch
.signature
->get_signature_exceptions();
3934 if (exceptions
->get_nof_types() == 1) {
3935 // the signature has exactly one exception type
3936 // use that for checking
3937 exc_type
= exceptions
->get_type_byIndex(0);
3939 // the signature has more than one exception types
3940 exc_type
= get_incoming_type(port_op
.r
.rcvpar
,
3941 port_op
.r
.redirect
.value
, value_redirect_checked
);
3943 size_t nof_comp_types
=
3944 exceptions
->get_nof_compatible_types(exc_type
);
3945 if (nof_comp_types
== 0) {
3946 port_op
.r
.rcvpar
->error("Type `%s' is not present on the "
3947 "exception list of signature `%s'",
3948 exc_type
->get_typename().c_str(),
3949 port_op
.r
.ctch
.signature
->get_typename().c_str());
3950 } else if (nof_comp_types
> 1) {
3951 port_op
.r
.rcvpar
->error("Type of the exception is ambiguous: "
3952 "`%s' is compatible with more than one exception types of "
3953 "signature `%s'", exc_type
->get_typename().c_str(),
3954 port_op
.r
.ctch
.signature
->get_typename().c_str());
3957 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3961 exc_type_determined
= true;
3963 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' does not have "
3964 "exceptions", port_op
.r
.ctch
.signature
->get_typename().c_str());
3967 if (!exc_type_determined
) {
3968 exc_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3969 value_redirect_checked
);
3971 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3972 // check the template instance using the exception type
3973 port_op
.r
.rcvpar
->chk(exc_type
);
3974 // check the value redirect if it is not done so far
3975 if (!value_redirect_checked
)
3976 chk_value_redirect(port_op
.r
.redirect
.value
, exc_type
);
3977 // checking for invalid exception types
3978 exc_type
= exc_type
->get_type_refd_last();
3979 switch (exc_type
->get_typetype()) {
3980 case Type::T_SIGNATURE
:
3981 port_op
.r
.rcvpar
->error("The type of catch parameter is signature "
3982 "`%s', which cannot be an exception type",
3983 exc_type
->get_typename().c_str());
3986 port_op
.r
.rcvpar
->error("The type of catch parameter is port type "
3987 "`%s', which cannot be an exception type",
3988 exc_type
->get_typename().c_str());
3990 case Type::T_DEFAULT
:
3991 port_op
.r
.rcvpar
->error("The type of catch parameter is the `default' "
3992 "type, which cannot be an exception type");
3997 // the statement does not have signature reference
3998 if (port_op
.r
.ctch
.timeout
) {
3999 // the parameter is timeout
4000 if (port_op
.portref
) {
4001 // the port reference is present
4003 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4004 if (!port_type_body
->getreply_allowed()) {
4005 // the port type is known and it does not allow blocking calls
4006 if (port_type_body
->get_operation_mode() ==
4007 PortTypeBody::PO_MESSAGE
) {
4008 port_op
.portref
->error("Timeout exception cannot be caught on "
4009 "a message-based port of type `%s'",
4010 port_type
->get_typename().c_str());
4012 port_op
.portref
->error("Timeout exception cannot be caught on "
4013 "a port of type `%s', which does not have any outgoing "
4014 "signatures that allow blocking calls",
4015 port_type
->get_typename().c_str());
4019 } else error("Timeout exception cannot be caught on `any port'");
4020 if (!port_op
.r
.ctch
.in_call
)
4021 error("Catching of `timeout' exception is not allowed in this "
4022 "context. It is permitted only in the response and exception "
4023 "handling part of `call' operations");
4024 else if (!port_op
.r
.ctch
.call_has_timer
)
4025 error("Catching of `timeout' exception is not allowed because the "
4026 "previous `call' operation does not have timer");
4027 if (port_op
.r
.fromclause
) port_op
.r
.fromclause
->error(
4028 "Operation `catch(timeout)' cannot have from clause");
4029 if (port_op
.r
.redirect
.sender
) port_op
.r
.redirect
.sender
->error(
4030 "Operation `catch(timeout)' cannot have sender redirect");
4032 // the operation does not have any parameter
4034 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4035 if (!port_type_body
->catch_allowed()) {
4036 // the port type is known and it does not have outgoing signatures
4037 if (port_type_body
->get_operation_mode() ==
4038 PortTypeBody::PO_MESSAGE
) {
4039 port_op
.portref
->error("Procedure-based operation `%s' is not "
4040 "applicable to a message-based port of type `%s'", stmt_name
,
4041 port_type
->get_typename().c_str());
4043 port_op
.portref
->error("Port type `%s' does not have any "
4044 "outgoing signatures that support exceptions",
4045 port_type
->get_typename().c_str());
4050 if (port_op
.r
.redirect
.value
) {
4051 // the statement does not have any parameter,
4052 // but the value redirect is present
4053 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
4054 "signature and parameter");
4055 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
4058 // checking from clause and sender redirect
4059 chk_from_clause(port_type
);
4062 void Statement::chk_check()
4064 Error_Context
cntxt(this, "In check statement");
4065 Type
*port_type
= chk_port_ref(port_op
.portref
);
4066 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4067 // the port type is known and it does not have incoming queue
4068 port_op
.portref
->error("Port type `%s' does not have incoming queue "
4069 "because it has neither incoming messages nor incoming or outgoing "
4070 "signatures", port_type
->get_typename().c_str());
4072 // checking from clause and sender redirect
4073 chk_from_clause(port_type
);
4076 void Statement::chk_clear()
4078 Error_Context
cntxt(this, "In clear port statement");
4079 Type
*port_type
= chk_port_ref(port_op
.portref
);
4080 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4081 // the port type is known and it does not have incoming queue
4082 port_op
.portref
->warning("Port type `%s' does not have incoming queue "
4083 "because it has neither incoming messages nor incoming or outgoing "
4084 "signatures", port_type
->get_typename().c_str());
4088 void Statement::chk_start_stop_port()
4090 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4091 chk_port_ref(port_op
.portref
);
4094 void Statement::chk_start_comp()
4096 Error_Context
cntxt(this, "In start test component statement");
4097 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4098 Common::Assignment
*t_ass
= comp_op
.funcinstref
->get_refd_assignment();
4100 // checking whether the referred definition is a function
4101 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
4103 case Common::Assignment::A_FUNCTION
:
4104 case Common::Assignment::A_FUNCTION_RVAL
:
4105 case Common::Assignment::A_FUNCTION_RTEMP
:
4108 comp_op
.funcinstref
->error("Reference to a function was expected in the "
4109 "argument instead of %s", t_ass
->get_description().c_str());
4112 Def_Function
*t_func
= dynamic_cast<Def_Function
*>(t_ass
);
4113 if (!t_func
) FATAL_ERROR("Statement::chk_start_comp()");
4114 // checking startability
4115 if (!t_func
->chk_startable()) return;
4116 // checking the 'runs on' clause against the type of component reference
4117 Type
*runs_on_type
= t_func
->get_RunsOnType();
4118 if (!comp_type
|| !runs_on_type
) return;
4119 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4120 comp_op
.compref
->error("Component type mismatch: The component reference "
4121 "is of type `%s', but %s runs on `%s'",
4122 comp_type
->get_typename().c_str(), t_func
->get_description().c_str(),
4123 runs_on_type
->get_typename().c_str());
4124 // checking the return type
4126 case Common::Assignment::A_FUNCTION_RTEMP
:
4127 comp_op
.funcinstref
->warning("Function `%s' returns a template of type "
4128 "`%s', which cannot be retrieved when the test component terminates",
4129 t_func
->get_fullname().c_str(),
4130 t_func
->get_Type()->get_typename().c_str());
4132 case Common::Assignment::A_FUNCTION_RVAL
: {
4133 bool return_type_correct
= false;
4134 Type
*return_type
= t_func
->get_Type();
4135 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4136 if (t
->has_done_attribute()) {
4137 return_type_correct
= true;
4139 } else if (!t
->is_ref()) break;
4141 if (!return_type_correct
)
4142 comp_op
.funcinstref
->warning("The return type of %s is `%s', which "
4143 "does not have the `done' extension attribute. When the test "
4144 "component terminates the returned value cannot be retrieved with "
4145 "a `done' operation", t_func
->get_description().c_str(),
4146 return_type
->get_typename().c_str());
4153 void Statement::chk_start_comp_refd()
4155 Error_Context
cntxt(this, "In start test component statement");
4156 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4157 switch(comp_op
.derefered
.value
->get_valuetype()){
4158 case Value::V_REFER
:
4159 comp_op
.derefered
.value
->error("A value of a function type was expected "
4160 "in the argument instead of a `refers' statement,"
4161 " which does not specify any function type");
4163 case Value::V_TTCN3_NULL
:
4164 comp_op
.derefered
.value
->error("A value of a function type was expected "
4165 "in the argument instead of a `null' value,"
4166 " which does not specify any function type");
4171 Type
*f_type
= comp_op
.derefered
.value
->get_expr_governor_last();
4172 if (!f_type
) return;
4173 switch (f_type
->get_typetype()) {
4176 case Type::T_FUNCTION
:
4179 comp_op
.derefered
.value
->error("A value of type function was expected "
4180 "in the argument instead of `%s'", f_type
->get_typename().c_str());
4183 if (f_type
->get_fat_runs_on_self()) {
4184 fau_refd
.value
->error("The argument cannot be a function reference with "
4185 "'runs on self' clause");
4188 if(!f_type
->chk_startability()) return;
4189 Type
*runs_on_type
= f_type
->get_fat_runs_on_type();
4190 if (!comp_type
|| !runs_on_type
) return;
4191 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4192 comp_op
.compref
->error("Component type mismatch: The component reference "
4193 "is of type `%s', but functions of type `%s' run on `%s'",
4194 comp_type
->get_typename().c_str(), f_type
->get_typename().c_str(),
4195 runs_on_type
->get_typename().c_str());
4196 Type
*return_type
= f_type
->get_function_return_type();
4198 if (f_type
->get_returns_template()) {
4199 comp_op
.derefered
.value
->warning("Functions of type `%s' return a "
4200 "template of type `%s', which cannot be retrieved when the test "
4201 "component terminates", f_type
->get_typename().c_str(),
4202 return_type
->get_typename().c_str());
4204 bool return_type_correct
= false;
4205 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4206 if (t
->has_done_attribute()) {
4207 return_type_correct
= true;
4209 } else if (!t
->is_ref()) break;
4211 if (!return_type_correct
)
4212 comp_op
.derefered
.value
->warning("The return type of function type "
4213 "`%s' is `%s', which does not have the `done' extension attribute. "
4214 "When the test component terminates the returned value cannot be "
4215 "retrieved with a `done' operation", f_type
->get_typename().c_str(),
4216 return_type
->get_typename().c_str());
4219 ActualParList
*parlist
= new ActualParList
;
4220 Ttcn::FormalParList
*fp_list
= f_type
->get_fat_parameters();
4221 if(fp_list
->fold_named_and_chk(comp_op
.derefered
.t_list1
, parlist
)) {
4223 delete comp_op
.derefered
.t_list1
;
4224 comp_op
.derefered
.ap_list2
= 0;
4226 delete comp_op
.derefered
.t_list1
;
4227 parlist
->set_fullname(get_fullname());
4228 parlist
->set_my_scope(my_sb
);
4229 comp_op
.derefered
.ap_list2
= parlist
;
4233 void Statement::chk_stop_kill_comp()
4235 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4236 chk_comp_ref(comp_op
.compref
, true, false);
4239 void Statement::chk_done()
4241 Error_Context
cntxt(this, "In done statement");
4242 chk_comp_ref(comp_op
.compref
, false, false);
4243 if (!comp_op
.compref
) return;
4244 // value returning done can be used only when the statement contains a
4245 // specific component reference
4246 if (comp_op
.donereturn
.donematch
) {
4247 bool value_redirect_checked
= false;
4248 // try to determine the type of return value
4249 Type
*return_type
= get_incoming_type(comp_op
.donereturn
.donematch
,
4250 comp_op
.donereturn
.redirect
, value_redirect_checked
);
4252 bool return_type_correct
= false;
4253 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4254 if (t
->has_done_attribute()) {
4255 return_type_correct
= true;
4257 } else if (!t
->is_ref()) break;
4259 if (!return_type_correct
) {
4260 error("Return type `%s' does not have `done' extension attribute",
4261 return_type
->get_typename().c_str());
4262 return_type
= Type::get_pooltype(Type::T_ERROR
);
4265 comp_op
.donereturn
.donematch
->error("Cannot determine the return type "
4266 "for value returning done");
4267 return_type
= Type::get_pooltype(Type::T_ERROR
);
4269 comp_op
.donereturn
.donematch
->chk(return_type
);
4270 if (!value_redirect_checked
)
4271 chk_value_redirect(comp_op
.donereturn
.redirect
, return_type
);
4272 } else if (comp_op
.donereturn
.redirect
) {
4273 comp_op
.donereturn
.redirect
->error("Redirect cannot be used for the "
4274 "return value without a matching template");
4275 chk_value_redirect(comp_op
.donereturn
.redirect
, 0);
4279 void Statement::chk_killed()
4281 Error_Context
cntxt(this, "In killed statement");
4282 chk_comp_ref(comp_op
.compref
, false, false);
4285 void Statement::chk_connect()
4287 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4288 // checking endpoints
4290 PortTypeBody
*ptb1
, *ptb2
;
4292 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4293 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, false);
4294 ptb1
= pt1
? pt1
->get_PortBody() : 0;
4297 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4298 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, false);
4299 ptb2
= pt2
? pt2
->get_PortBody() : 0;
4301 // checking consistency
4302 if (!ptb1
|| !ptb2
) return;
4303 if (!ptb1
->is_connectable(ptb2
) ||
4304 (ptb1
!= ptb2
&& !ptb2
->is_connectable(ptb1
))) {
4305 error("The connection between port types `%s' and `%s' is not consistent",
4306 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4307 ptb1
->report_connection_errors(ptb2
);
4308 if (ptb1
!= ptb2
) ptb2
->report_connection_errors(ptb1
);
4312 void Statement::chk_map()
4314 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4315 // checking endpoints
4317 PortTypeBody
*ptb1
, *ptb2
;
4318 bool cref1_is_tc
= false, cref1_is_system
= false;
4319 bool cref2_is_tc
= false, cref2_is_system
= false;
4321 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4322 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, true);
4324 ptb1
= pt1
->get_PortBody();
4325 if (ptb1
->is_internal()) {
4326 config_op
.portref1
->warning("Port type `%s' was marked as `internal'",
4327 pt1
->get_typename().c_str());
4330 Value
*cref1
= config_op
.compref1
->get_value_refd_last();
4331 if (cref1
->get_valuetype() == Value::V_EXPR
) {
4332 switch (cref1
->get_optype()) {
4333 case Value::OPTYPE_COMP_MTC
:
4334 case Value::OPTYPE_COMP_SELF
:
4335 case Value::OPTYPE_COMP_CREATE
:
4338 case Value::OPTYPE_COMP_SYSTEM
:
4339 cref1_is_system
= true;
4346 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4347 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, true);
4349 ptb2
= pt2
->get_PortBody();
4350 if (ptb2
->is_internal()) {
4351 config_op
.portref2
->warning("Port type `%s' was marked as `internal'",
4352 pt2
->get_typename().c_str());
4355 Value
*cref2
= config_op
.compref2
->get_value_refd_last();
4356 if (cref2
->get_valuetype() == Value::V_EXPR
) {
4357 switch (cref2
->get_optype()) {
4358 case Value::OPTYPE_COMP_MTC
:
4359 case Value::OPTYPE_COMP_SELF
:
4360 case Value::OPTYPE_COMP_CREATE
:
4363 case Value::OPTYPE_COMP_SYSTEM
:
4364 cref2_is_system
= true;
4370 if (cref1_is_tc
&& cref2_is_tc
) {
4371 error("Both endpoints of the mapping are test component ports");
4374 if (cref1_is_system
&& cref2_is_system
) {
4375 error("Both endpoints of the mapping are system ports");
4378 // checking consistency
4379 if (!ptb1
|| !ptb2
) return;
4380 if (cref1_is_tc
|| cref2_is_system
) {
4381 if (!ptb1
->is_mappable(ptb2
)) {
4382 error("The mapping between test component port type `%s' and system "
4383 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4384 pt2
->get_typename().c_str());
4385 ptb1
->report_mapping_errors(ptb2
);
4387 } else if (cref2_is_tc
|| cref1_is_system
) {
4388 if (!ptb2
->is_mappable(ptb1
)) {
4389 error("The mapping between system port type `%s' and test component "
4390 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4391 pt2
->get_typename().c_str());
4392 ptb2
->report_mapping_errors(ptb1
);
4395 // we have no idea which one is the system port
4396 if (!ptb1
->is_mappable(ptb1
) && !ptb2
->is_mappable(ptb1
)) {
4397 error("The mapping between port types `%s' and `%s' is not consistent",
4398 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4403 void Statement::chk_start_timer()
4405 Error_Context
cntxt(this, "In start timer statement");
4406 chk_timer_ref(timer_op
.timerref
);
4407 if (timer_op
.value
) {
4408 // check the actual duration
4409 timer_op
.value
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4410 Value
*t_val
= timer_op
.value
->get_value_refd_last();
4411 if (t_val
->get_valuetype() == Value::V_REAL
) {
4412 ttcn3float v_real
= t_val
->get_val_Real();
4414 timer_op
.value
->error("The timer duration is negative: `%s'",
4415 Real2string(v_real
).c_str());
4416 } else if (isSpecialFloatValue(v_real
)) {
4417 timer_op
.value
->error("The timer duration cannot be %s",
4418 Real2string(v_real
).c_str());
4422 // check whether the timer has default duration
4423 Common::Assignment
*t_ass
= timer_op
.timerref
->get_refd_assignment();
4424 if (t_ass
&& t_ass
->get_asstype() == Common::Assignment::A_TIMER
) {
4425 Def_Timer
*t_def_timer
= dynamic_cast<Def_Timer
*>(t_ass
);
4426 if (!t_def_timer
) FATAL_ERROR("Statement::chk_start_timer()");
4427 if (!t_def_timer
->has_default_duration(
4428 timer_op
.timerref
->get_subrefs()))
4429 error("Missing duration: %s does not have default duration",
4430 t_ass
->get_description().c_str());
4435 void Statement::chk_stop_timer_timeout()
4437 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4438 chk_timer_ref(timer_op
.timerref
);
4441 void Statement::chk_setverdict()
4443 Error_Context
cntxt(this, "In setverdict statement");
4444 if(!my_sb
->get_my_def())
4445 error("Setverdict statement is not allowed in the control part");
4446 setverdict
.verdictval
->chk_expr_verdict(Type::EXPECTED_DYNAMIC_VALUE
);
4447 Value
*t_val
= setverdict
.verdictval
->get_value_refd_last();
4448 if (t_val
->get_valuetype() == Value::V_VERDICT
&&
4449 t_val
->get_val_verdict() == Value::Verdict_ERROR
) {
4450 setverdict
.verdictval
->error("Error verdict cannot be set by the setverdict "
4455 void Statement::chk_execute()
4457 Error_Context
cntxt(this, "In execute statement");
4458 Ref_pard
*ref
=testcase_inst
.tcref
;
4459 Common::Assignment
*t_ass
=ref
->get_refd_assignment();
4460 if(!t_ass
) goto error
;
4461 if(t_ass
->get_asstype()!=Common::Assignment::A_TESTCASE
) {
4462 ref
->error("Reference to a testcase was expected in the argument"
4463 " instead of %s", t_ass
->get_description().c_str());
4466 if(my_sb
->get_scope_runs_on()) {
4467 ref
->error("A definition that has `runs on' clause cannot "
4468 "execute testcases");
4471 if (testcase_inst
.timerval
) {
4472 testcase_inst
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4473 Value
*t_val
= testcase_inst
.timerval
->get_value_refd_last();
4474 if (t_val
->get_valuetype() == Value::V_REAL
) {
4475 ttcn3float v_real
= t_val
->get_val_Real();
4477 testcase_inst
.timerval
->error("The testcase guard "
4478 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4479 } else if (isSpecialFloatValue(v_real
)) {
4480 testcase_inst
.timerval
->error("The testcase guard "
4481 "timer duration cannot be %s", Real2string(v_real
).c_str());
4488 statementtype
=S_ERROR
;
4491 void Statement::chk_execute_refd()
4493 Error_Context
cntxt(this, "In execute statement");
4494 switch(execute_refd
.value
->get_valuetype()){
4495 case Value::V_REFER
:
4496 execute_refd
.value
->error("A value of a testcase type was expected "
4497 "in the argument instead of a `refers' statement,"
4498 " which does not specify any function type");
4500 case Value::V_TTCN3_NULL
:
4501 execute_refd
.value
->error("A value of a testcase type was expected "
4502 "in the argument instead of a `null' value,"
4503 " which does not specify any function type");
4508 Type
*t
= execute_refd
.value
->get_expr_governor_last();
4510 switch (t
->get_typetype()) {
4513 case Type::T_TESTCASE
:
4516 execute_refd
.value
->error("A value of type testcase was expected in the "
4517 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
4520 if (my_sb
->get_scope_runs_on()) {
4521 execute_refd
.value
->error("A definition that has `runs on' clause cannot "
4522 "execute testcases");
4525 ActualParList
*parlist
= new ActualParList
;
4526 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
4527 bool is_erroneous
= fp_list
->chk_actual_parlist(execute_refd
.t_list1
,
4529 delete execute_refd
.t_list1
;
4532 execute_refd
.ap_list2
= 0;
4535 parlist
->set_fullname(get_fullname());
4536 parlist
->set_my_scope(my_sb
);
4537 execute_refd
.ap_list2
= parlist
;
4539 if(execute_refd
.timerval
) {
4540 execute_refd
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4541 Value
*t_val
= execute_refd
.timerval
->get_value_refd_last();
4542 if(t_val
->get_valuetype() == Value::V_REAL
) {
4543 ttcn3float v_real
= t_val
->get_val_Real();
4545 execute_refd
.value
->error("The testcase guard "
4546 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4547 } else if (isSpecialFloatValue(v_real
)) {
4548 execute_refd
.value
->error("The testcase guard "
4549 "timer duration cannot be %s", Real2string(v_real
).c_str());
4557 statementtype
=S_ERROR
;
4560 Type
*Statement::chk_port_ref(Reference
*p_ref
)
4562 if (!my_sb
->get_my_def())
4563 error("Port operation is not allowed in the control part");
4564 if (!p_ref
) return 0;
4565 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4566 if (!t_ass
) return 0;
4567 switch (t_ass
->get_asstype()) {
4568 case Common::Assignment::A_PORT
: {
4569 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4570 if (t_dims
) t_dims
->chk_indices(p_ref
, "port", false,
4571 Type::EXPECTED_DYNAMIC_VALUE
);
4572 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4573 "cannot have field or array sub-references",
4574 t_ass
->get_description().c_str());
4576 case Common::Assignment::A_PAR_PORT
:
4577 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4578 "field or array sub-references", t_ass
->get_description().c_str());
4581 p_ref
->error("Reference to a port or port parameter was expected "
4582 "instead of %s", t_ass
->get_description().c_str());
4585 Type
*ret_val
= t_ass
->get_Type();
4586 if (!ret_val
) return 0;
4587 ret_val
= ret_val
->get_type_refd_last();
4588 if (ret_val
->get_typetype() == Type::T_PORT
) return ret_val
;
4592 void Statement::chk_to_clause(Type
*port_type
)
4594 if (!port_op
.s
.toclause
) return;
4595 // pointer to the address type
4598 // the port type is known
4599 address_type
= port_type
->get_PortBody()->get_address_type();
4601 // the port type is unknown
4602 // address is permitted if it is visible from the current module
4603 address_type
= my_sb
->get_scope_mod()->get_address_type();
4605 Error_Context
cntxt(port_op
.s
.toclause
, "In `to' clause");
4607 // detect possible enumerated values (address may be an enumerated type)
4608 address_type
->chk_this_value_ref(port_op
.s
.toclause
);
4609 // try to figure out whether the argument is a component reference or
4613 port_op
.s
.toclause
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4614 if (t_governor
) is_address
= address_type
->is_compatible(t_governor
, NULL
);
4616 port_op
.s
.toclause
->get_expr_returntype(Type::EXPECTED_DYNAMIC_VALUE
)
4617 != Type::T_COMPONENT
;
4619 // the argument is an address value
4620 port_op
.s
.toclause
->set_my_governor(address_type
);
4621 address_type
->chk_this_value(port_op
.s
.toclause
, 0,
4622 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
4625 // the argument is not an address value, treat as a component reference
4626 chk_comp_ref(port_op
.s
.toclause
, true, true);
4629 // usage of address is not allowed
4630 chk_comp_ref(port_op
.s
.toclause
, true, true);
4634 void Statement::chk_from_clause(Type
*port_type
)
4636 if (!port_op
.r
.fromclause
&& !port_op
.r
.redirect
.sender
) return;
4637 // pointer to the address type
4640 // the port type is known
4641 address_type
= port_type
->get_PortBody()->get_address_type();
4642 } else if (port_op
.portref
) {
4643 // the operation refers to a specific port, but its type is unknown
4644 // address is permitted if it is visible from the current module
4645 address_type
= my_sb
->get_scope_mod()->get_address_type();
4647 // the operation refers to 'any port'
4648 // address is not allowed
4651 bool sender_redirect_checked
= false;
4652 Type
*from_clause_type
= 0;
4653 if (port_op
.r
.fromclause
) {
4654 // the from clause is present
4655 Error_Context
cntxt(port_op
.r
.fromclause
, "In `from' clause");
4657 port_op
.r
.fromclause
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4658 Template
*templ_body
= port_op
.r
.fromclause
->get_Template();
4659 if (!from_clause_type
) {
4660 // try to detect possible enumerated values
4661 if (address_type
) address_type
->chk_this_template_ref(templ_body
);
4662 else templ_body
->set_lowerid_to_ref();
4664 templ_body
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4666 if (!from_clause_type
) {
4667 // trying to determine the type of template in from clause
4668 // based on the sender redirect
4669 from_clause_type
= chk_sender_redirect(address_type
);
4670 sender_redirect_checked
= true;
4672 if (!from_clause_type
) {
4673 // trying to figure out whether the template is a component reference
4674 // or an SUT address
4676 if (templ_body
->get_expr_returntype(Type::EXPECTED_TEMPLATE
)
4677 == Type::T_COMPONENT
) is_compref
= true;
4679 switch (templ_body
->get_templatetype()) {
4680 case Template::SPECIFIC_VALUE
:
4681 // treat 'null' as component reference
4682 if (templ_body
->get_specific_value()->get_valuetype() ==
4683 Value::V_TTCN3_NULL
) is_compref
= true;
4684 else is_compref
= false;
4686 case Template::ANY_VALUE
:
4687 case Template::ANY_OR_OMIT
:
4688 // treat generic wildcards ? and * as component references
4696 // the argument is a component reference: get a pool type
4697 from_clause_type
= Type::get_pooltype(Type::T_COMPONENT
);
4698 } else if (address_type
) {
4699 // the argument is not a component reference: try the address type
4700 from_clause_type
= address_type
;
4703 if (from_clause_type
) {
4704 // the type of from clause is known
4705 port_op
.r
.fromclause
->chk(from_clause_type
);
4707 || !address_type
->is_compatible(from_clause_type
, NULL
)) {
4708 // from_clause_type must be a component type
4709 switch (from_clause_type
->get_type_refd_last()->get_typetype()) {
4711 // to avoid further errors in sender redirect
4712 from_clause_type
= 0;
4713 case Type::T_COMPONENT
:
4714 if (templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
)
4715 chk_comp_ref(templ_body
->get_specific_value(), true, true);
4718 port_op
.r
.fromclause
->error("The type of the template should be a "
4719 "component type %sinstead of `%s'",
4720 address_type
? "or the `address' type " : "",
4721 from_clause_type
->get_typename().c_str());
4722 // to avoid further errors in sender redirect
4723 from_clause_type
= 0;
4727 // the type of from clause is unknown
4728 port_op
.r
.fromclause
->error("Cannot determine the type of the "
4732 if (!sender_redirect_checked
) {
4733 Type
*sender_redirect_type
= chk_sender_redirect(address_type
);
4734 if (from_clause_type
&& sender_redirect_type
&&
4735 !from_clause_type
->is_identical(sender_redirect_type
)) {
4736 error("The types in `from' clause and `sender' redirect are not the "
4737 "same: `%s' was expected instead of `%s'",
4738 from_clause_type
->get_typename().c_str(),
4739 sender_redirect_type
->get_typename().c_str());
4744 void Statement::chk_call_body(Type
*port_type
, Type
*signature
)
4746 bool has_catch_timeout
= false;
4747 // setting the flags whether 'catch(timeout)' statements are allowed
4748 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4749 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4750 if (t_ag
->get_type() != AltGuard::AG_OP
)
4751 FATAL_ERROR("Statement::chk_call_body()");
4752 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4753 if (t_stmt
->statementtype
== S_CATCH
) {
4754 t_stmt
->port_op
.r
.ctch
.in_call
= true;
4755 if (port_op
.s
.call
.timer
)
4756 t_stmt
->port_op
.r
.ctch
.call_has_timer
= true;
4757 if (t_stmt
->port_op
.r
.ctch
.timeout
) has_catch_timeout
= true;
4760 Error_Context
cntxt(this, "In response and exception handling part");
4761 port_op
.s
.call
.body
->set_my_laic_stmt(port_op
.s
.call
.body
, 0);
4762 port_op
.s
.call
.body
->set_my_ags(port_op
.s
.call
.body
);
4763 port_op
.s
.call
.body
->chk();
4765 // checking whether getreply/catch operations refer to the same port
4766 // and same signature as the call operation
4767 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4768 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4769 if (t_ag
->get_type() != AltGuard::AG_OP
)
4770 FATAL_ERROR("Statement::chk_call_body()");
4771 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4772 if (t_stmt
->statementtype
== S_ERROR
) continue;
4773 // checking port reference
4774 if (!t_stmt
->port_op
.portref
) {
4775 t_stmt
->error("The `%s' operation must refer to the same port as "
4776 "the previous `call' statement: `%s' was expected instead of "
4777 "`any port'", t_stmt
->get_stmt_name(),
4778 port_op
.portref
->get_id()->get_dispname().c_str());
4779 } else if (*port_op
.portref
->get_id() !=
4780 *t_stmt
->port_op
.portref
->get_id()) {
4781 t_stmt
->port_op
.portref
->error("The `%s' operation refers to a "
4782 "different port than the previous `call' statement: `%s' was "
4783 "expected instead of `%s'", t_stmt
->get_stmt_name(),
4784 port_op
.portref
->get_id()->get_dispname().c_str(),
4785 t_stmt
->port_op
.portref
->get_id()->get_dispname().c_str());
4787 // checking the signature
4788 switch (t_stmt
->statementtype
) {
4790 if (t_stmt
->port_op
.r
.rcvpar
) {
4791 Type
*t_sig
= t_stmt
->port_op
.r
.rcvpar
4792 ->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4793 if (!signature
->is_compatible(t_sig
, NULL
))
4794 t_stmt
->port_op
.r
.rcvpar
->error("The `getreply' operation refers "
4795 "to a different signature than the previous `call' statement: "
4796 "`%s' was expected instead of `%s'",
4797 signature
->get_typename().c_str(),
4798 t_sig
->get_typename().c_str());
4802 if (t_stmt
->port_op
.r
.ctch
.signature
4803 && !signature
->is_compatible(t_stmt
->port_op
.r
.ctch
.signature
, NULL
))
4804 t_stmt
->port_op
.r
.ctch
.signature_ref
->error("The `catch' "
4805 "operation refers to a different signature than the previous "
4806 "`call' statement: `%s' was expected instead of `%s'",
4807 signature
->get_typename().c_str(),
4808 t_stmt
->port_op
.r
.ctch
.signature
->get_typename().c_str());
4811 FATAL_ERROR("Statement::chk_call_body()");
4815 if (port_op
.s
.call
.timer
&& !has_catch_timeout
)
4816 warning("The call operation has a timer, but the timeout exception is "
4820 Type
*Statement::get_outgoing_type(TemplateInstance
*p_ti
)
4822 // first analyze the template instance as is
4823 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4824 // return if this step was successful
4825 if (ret_val
) return ret_val
;
4826 // try to convert the undef identifier in the template instance to
4827 // a reference because it cannot be an enum value anymore
4828 Template
*t_templ
= p_ti
->get_Template();
4829 t_templ
->set_lowerid_to_ref();
4830 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4833 Type
*Statement::get_incoming_type(TemplateInstance
*p_ti
,
4834 Reference
*p_val_redir
, bool& p_val_redir_checked
)
4836 // first analyze the template instance
4837 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4838 // return if this step was successful
4839 if (ret_val
) return ret_val
;
4840 // use the variable in value redirect in the next step
4841 ret_val
= chk_value_redirect(p_val_redir
, 0);
4842 p_val_redir_checked
= true;
4843 // return if this step was successful
4844 if (ret_val
) return ret_val
;
4845 // finally try to convert the undef identifier in the template instance to
4846 // a reference because it cannot be an enum value anymore
4847 Template
*t_templ
= p_ti
->get_Template();
4848 t_templ
->set_lowerid_to_ref();
4849 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4852 Type
*Statement::chk_value_redirect(Reference
*p_ref
, Type
*p_type
)
4854 if (!p_ref
) return NULL
;
4855 Error_Context
cntxt(p_ref
, "In `value' redirect");
4856 Type
*t_var_type
= p_ref
->chk_variable_ref();
4857 if (p_type
&& t_var_type
) {
4858 TypeCompatInfo
info(my_sb
->get_scope_mod(), p_type
, t_var_type
, true, false);
4859 if (p_ref
->get_subrefs()) info
.set_str2_elem(p_ref
->get_subrefs()->refers_to_string_element());
4862 if (!p_type
->is_compatible(t_var_type
, &info
, &l_chain
, &r_chain
)) {
4863 if (info
.is_subtype_error()) {
4864 p_ref
->error("%s", info
.get_subtype_error().c_str());
4866 if (!info
.is_erroneous()) {
4867 p_ref
->error("Type mismatch in value redirect: "
4868 "A variable of type `%s' was expected instead of `%s'",
4869 p_type
->get_typename().c_str(),
4870 t_var_type
->get_typename().c_str());
4872 p_ref
->error("%s", info
.get_error_str_str().c_str());
4879 Type
*Statement::chk_sender_redirect(Type
*address_type
)
4881 if (!port_op
.r
.redirect
.sender
) return 0;
4882 Error_Context
cntxt(port_op
.r
.redirect
.sender
, "In `sender' redirect");
4883 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
4884 if (!t_var_type
) return 0;
4885 if (!address_type
|| !address_type
->is_identical(t_var_type
)) {
4886 // t_var_type must be a component type
4887 switch (t_var_type
->get_type_refd_last()->get_typetype()) {
4888 case Type::T_COMPONENT
:
4893 port_op
.r
.redirect
.sender
->error("The type of the variable should be "
4894 "a component type %sinstead of `%s'",
4895 address_type
? "or the `address' type " : "",
4896 t_var_type
->get_typename().c_str());
4903 Type
*Statement::chk_signature_ref(Reference
*p_ref
)
4905 if (!p_ref
) FATAL_ERROR("Statement::chk_signature_ref()");
4906 Error_Context(p_ref
, "In signature");
4907 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4908 if (!t_ass
) return 0;
4909 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
) {
4910 p_ref
->error("Reference to a signature was expected instead of %s",
4911 t_ass
->get_description().c_str());
4914 Type
*ret_val
= t_ass
->get_Type();
4915 if (!ret_val
) return 0;
4916 ret_val
= ret_val
->get_field_type(p_ref
->get_subrefs(),
4917 Type::EXPECTED_DYNAMIC_VALUE
);
4918 if (!ret_val
) return 0;
4919 ret_val
= ret_val
->get_type_refd_last();
4920 switch (ret_val
->get_typetype()) {
4921 case Type::T_SIGNATURE
:
4926 p_ref
->error("Reference to a signature was expected instead of port type "
4927 "`%s'", ret_val
->get_typename().c_str());
4930 p_ref
->error("Reference to a signature was expected instead of data type "
4931 "`%s'", ret_val
->get_typename().c_str());
4937 void Statement::chk_timer_ref(Reference
*p_ref
)
4940 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4942 switch (t_ass
->get_asstype()) {
4943 case Common::Assignment::A_TIMER
: {
4944 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4945 if (t_dims
) t_dims
->chk_indices(p_ref
, "timer", false,
4946 Type::EXPECTED_DYNAMIC_VALUE
);
4947 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4948 "cannot have field or array sub-references",
4949 t_ass
->get_description().c_str());
4951 case Common::Assignment::A_PAR_TIMER
:
4952 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4953 "field or array sub-references", t_ass
->get_description().c_str());
4956 p_ref
->error("Reference to a timer or timer parameter was expected "
4957 "instead of %s", t_ass
->get_description().c_str());
4961 Type
*Statement::chk_comp_ref(Value
*p_val
, bool allow_mtc
, bool allow_system
, bool is_connecting
)
4963 if (!my_sb
->get_my_def())
4964 error("Component operation is not allowed in the control part");
4965 if (!p_val
) return 0;
4966 Value
*v
= p_val
->get_value_refd_last();
4967 switch (v
->get_valuetype()) {
4968 case Value::V_ERROR
:
4972 case Value::V_INVOKE
:
4973 if(p_val
->get_expr_returntype() != Type::T_COMPONENT
)
4974 p_val
->error("A component reference was expected as return value");
4976 case Value::V_TTCN3_NULL
:
4977 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
4980 switch (v
->get_optype()) {
4981 case Value::OPTYPE_COMP_NULL
:
4982 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
4984 case Value::OPTYPE_COMP_MTC
:
4986 p_val
->error("The `mtc' component reference shall not be used in `%s' operation", get_stmt_name());
4988 case Value::OPTYPE_COMP_SYSTEM
:
4990 p_val
->error("The `system' component reference shall not be used in `%s' operation", get_stmt_name());
4992 case Value::OPTYPE_COMP_SELF
:
4993 case Value::OPTYPE_COMP_CREATE
:
4996 p_val
->error("A component reference was expected as operand");
5001 p_val
->error("A component reference was expected as operand");
5004 Type
*ret_val
= is_connecting
? p_val
->get_component_governor() :
5005 p_val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
5006 if (!ret_val
) return 0;
5007 ret_val
= ret_val
->get_type_refd_last();
5008 switch (ret_val
->get_typetype()) {
5011 case Type::T_COMPONENT
:
5014 p_val
->error("Type mismatch: The type of the operand should be a "
5015 "component type instead of `%s'", ret_val
->get_typename().c_str());
5020 Type
*Statement::chk_conn_endpoint(Value
*p_compref
, Reference
*p_portref
,
5023 Type
*comp_type
= chk_comp_ref(p_compref
, true, allow_system
, true);
5025 ComponentTypeBody
*comp_body
= comp_type
->get_CompBody();
5026 p_portref
->set_base_scope(comp_body
);
5027 const Identifier
& t_portid
= *p_portref
->get_id();
5028 if (!comp_body
->has_local_ass_withId(t_portid
)) {
5029 p_portref
->error("Component type `%s' does not have port with name "
5030 "`%s'", comp_type
->get_typename().c_str(),
5031 t_portid
.get_dispname().c_str());
5034 Common::Assignment
*t_ass
= comp_body
->get_local_ass_byId(t_portid
);
5035 if (t_ass
->get_asstype() != Common::Assignment::A_PORT
) {
5036 p_portref
->error("Definition `%s' in component type `%s' is a %s and "
5037 "not a port", t_portid
.get_dispname().c_str(),
5038 comp_type
->get_typename().c_str(), t_ass
->get_assname());
5041 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
5042 if (t_dims
) t_dims
->chk_indices(p_portref
, "port", false,
5043 Type::EXPECTED_DYNAMIC_VALUE
);
5044 else if (p_portref
->get_subrefs()) {
5045 p_portref
->error("Port `%s' is not an array. The "
5046 "reference cannot have array indices",
5047 t_portid
.get_dispname().c_str());
5049 Type
*port_type
= t_ass
->get_Type();
5051 // check whether the external interface is provided by another port type
5052 PortTypeBody
*port_body
= port_type
->get_PortBody();
5053 if (port_body
->get_type() == PortTypeBody::PT_USER
) {
5054 Type
*provider_type
= port_body
->get_provider_type();
5055 if (provider_type
) port_type
= provider_type
;
5060 // the component type cannot be determined
5061 FieldOrArrayRefs
*t_subrefs
= p_portref
->get_subrefs();
5063 // check the array indices: they should be integers
5064 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
5065 t_subrefs
->get_ref(i
)->get_val()
5066 ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
5073 void Statement::set_code_section(
5074 GovernedSimple::code_section_t p_code_section
)
5076 switch(statementtype
) {
5087 ass
->set_code_section(p_code_section
);
5089 case S_FUNCTION_INSTANCE
:
5090 case S_ALTSTEP_INSTANCE
:
5092 ref_pard
->set_code_section(p_code_section
);
5095 block
->set_code_section(p_code_section
);
5099 case S_STOP_TESTCASE
:
5100 if (logargs
) logargs
->set_code_section(p_code_section
);
5103 if_stmt
.ics
->set_code_section(p_code_section
);
5104 if (if_stmt
.elseblock
)
5105 if_stmt
.elseblock
->set_code_section(p_code_section
);
5108 if (!loop
.for_stmt
.varinst
)
5109 loop
.for_stmt
.init_ass
->set_code_section(p_code_section
);
5110 loop
.for_stmt
.finalexpr
->set_code_section(p_code_section
);
5111 loop
.for_stmt
.step
->set_code_section(p_code_section
);
5112 loop
.block
->set_code_section(p_code_section
);
5116 loop
.expr
->set_code_section(p_code_section
);
5117 loop
.block
->set_code_section(p_code_section
);
5120 select
.expr
->set_code_section(p_code_section
);
5121 select
.scs
->set_code_section(p_code_section
);
5125 ags
->set_code_section(p_code_section
);
5128 if (returnexpr
.v
) returnexpr
.v
->set_code_section(p_code_section
);
5129 if (returnexpr
.t
) returnexpr
.t
->set_code_section(p_code_section
);
5132 if (deactivate
) deactivate
->set_code_section(p_code_section
);
5135 port_op
.portref
->set_code_section(p_code_section
);
5136 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5137 if (port_op
.s
.toclause
)
5138 port_op
.s
.toclause
->set_code_section(p_code_section
);
5141 port_op
.portref
->set_code_section(p_code_section
);
5142 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5143 if (port_op
.s
.toclause
)
5144 port_op
.s
.toclause
->set_code_section(p_code_section
);
5145 if (port_op
.s
.call
.timer
)
5146 port_op
.s
.call
.timer
->set_code_section(p_code_section
);
5147 if (port_op
.s
.call
.body
)
5148 port_op
.s
.call
.body
->set_code_section(p_code_section
);
5151 port_op
.portref
->set_code_section(p_code_section
);
5152 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5153 if (port_op
.s
.replyval
)
5154 port_op
.s
.replyval
->set_code_section(p_code_section
);
5155 if (port_op
.s
.toclause
)
5156 port_op
.s
.toclause
->set_code_section(p_code_section
);
5159 port_op
.portref
->set_code_section(p_code_section
);
5160 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5161 if (port_op
.s
.toclause
)
5162 port_op
.s
.toclause
->set_code_section(p_code_section
);
5165 case S_CHECK_RECEIVE
:
5167 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5168 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5169 if (port_op
.r
.fromclause
)
5170 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5171 if (port_op
.r
.redirect
.value
)
5172 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5173 if (port_op
.r
.redirect
.sender
)
5174 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5177 case S_CHECK_GETCALL
:
5178 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5179 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5180 if (port_op
.r
.fromclause
)
5181 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5182 if (port_op
.r
.redirect
.param
)
5183 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5184 if (port_op
.r
.redirect
.sender
)
5185 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5188 case S_CHECK_GETREPLY
:
5189 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5190 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5191 if (port_op
.r
.getreply_valuematch
)
5192 port_op
.r
.getreply_valuematch
->set_code_section(p_code_section
);
5193 if (port_op
.r
.fromclause
)
5194 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5195 if (port_op
.r
.redirect
.value
)
5196 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5197 if (port_op
.r
.redirect
.param
)
5198 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5199 if (port_op
.r
.redirect
.sender
)
5200 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5204 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5205 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5206 if (port_op
.r
.fromclause
)
5207 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5208 if (port_op
.r
.redirect
.value
)
5209 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5210 if (port_op
.r
.redirect
.sender
)
5211 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5214 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5215 if (port_op
.r
.fromclause
)
5216 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5217 if (port_op
.r
.redirect
.sender
)
5218 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5224 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5227 comp_op
.compref
->set_code_section(p_code_section
);
5228 comp_op
.funcinstref
->set_code_section(p_code_section
);
5230 case S_START_COMP_REFD
:
5231 comp_op
.compref
->set_code_section(p_code_section
);
5232 comp_op
.derefered
.value
->set_code_section(p_code_section
);
5237 if (comp_op
.compref
) comp_op
.compref
->set_code_section(p_code_section
);
5240 if (comp_op
.compref
) {
5241 comp_op
.compref
->set_code_section(p_code_section
);
5242 if (comp_op
.donereturn
.donematch
)
5243 comp_op
.donereturn
.donematch
->set_code_section(p_code_section
);
5244 if (comp_op
.donereturn
.redirect
)
5245 comp_op
.donereturn
.redirect
->set_code_section(p_code_section
);
5252 config_op
.compref1
->set_code_section(p_code_section
);
5253 config_op
.portref1
->set_code_section(p_code_section
);
5254 config_op
.compref2
->set_code_section(p_code_section
);
5255 config_op
.portref2
->set_code_section(p_code_section
);
5258 timer_op
.timerref
->set_code_section(p_code_section
);
5259 if (timer_op
.value
) timer_op
.value
->set_code_section(p_code_section
);
5263 if (timer_op
.timerref
)
5264 timer_op
.timerref
->set_code_section(p_code_section
);
5267 setverdict
.verdictval
->set_code_section(p_code_section
);
5268 if (setverdict
.logargs
)
5269 setverdict
.logargs
->set_code_section(p_code_section
);
5271 case S_TESTCASE_INSTANCE
:
5272 testcase_inst
.tcref
->set_code_section(p_code_section
);
5273 if (testcase_inst
.timerval
)
5274 testcase_inst
.timerval
->set_code_section(p_code_section
);
5276 case S_TESTCASE_INSTANCE_REFD
:
5277 execute_refd
.value
->set_code_section(p_code_section
);
5278 if(execute_refd
.timerval
)
5279 execute_refd
.timerval
->set_code_section(p_code_section
);
5281 case S_ACTIVATE_REFD
:
5282 case S_FUNCTION_INVOKED
:
5283 case S_ALTSTEP_INVOKED
:
5284 fau_refd
.value
->set_code_section(p_code_section
);
5285 if(fau_refd
.ap_list2
)
5286 for(size_t i
= 0; i
< fau_refd
.ap_list2
->get_nof_pars(); i
++)
5287 fau_refd
.ap_list2
->get_par(i
)->set_code_section(p_code_section
);
5290 str2ttcn
.val
->set_code_section(p_code_section
);
5291 str2ttcn
.ref
->set_code_section(p_code_section
);
5294 FATAL_ERROR("Statement::set_code_section()");
5295 } // switch statementtype
5298 char *Statement::generate_code(char *str
)
5300 switch (statementtype
) {
5307 // conditional and loop statements do not need single location setting
5308 // the embedded expressions, statements have their own locations
5311 str
= update_location_object(str
);
5314 switch(statementtype
) {
5316 str
=def
->generate_code_str(str
);
5319 str
=ass
->generate_code(str
);
5321 case S_FUNCTION_INSTANCE
:
5322 case S_ALTSTEP_INSTANCE
:
5323 str
=generate_code_funcinst(str
);
5325 case S_FUNCTION_INVOKED
:
5326 case S_ALTSTEP_INVOKED
:
5327 str
=generate_code_invoke(str
);
5330 str
=generate_code_block(str
);
5333 str
=generate_code_log(str
);
5336 str
= generate_code_label(str
);
5339 str
= generate_code_goto(str
);
5342 str
=generate_code_if(str
);
5345 str
=generate_code_select(str
);
5348 str
=generate_code_for(str
);
5351 str
=generate_code_while(str
);
5354 str
=generate_code_dowhile(str
);
5357 str
=generate_code_break(str
);
5360 str
=generate_code_continue(str
);
5363 str
=mputstr(str
, "TTCN_Runtime::stop_execution();\n");
5365 case S_STOP_TESTCASE
:
5366 str
=generate_code_testcase_stop(str
);
5369 str
=ags
->generate_code_alt(str
, *this);
5372 str
=generate_code_repeat(str
);
5375 str
=generate_code_interleave(str
);
5378 str
=generate_code_return(str
);
5381 str
=generate_code_activate(str
);
5383 case S_ACTIVATE_REFD
:
5384 str
=generate_code_activate_refd(str
);
5387 str
=generate_code_deactivate(str
);
5390 str
= generate_code_send(str
);
5393 str
= generate_code_call(str
);
5396 str
= generate_code_reply(str
);
5399 str
= generate_code_raise(str
);
5407 case S_CHECK_RECEIVE
:
5408 case S_CHECK_GETCALL
:
5409 case S_CHECK_GETREPLY
:
5414 str
= generate_code_standalone(str
);
5417 str
=generate_code_portop(str
, "clear");
5420 str
=generate_code_portop(str
, "start");
5423 str
=generate_code_portop(str
, "stop");
5426 str
=generate_code_portop(str
, "halt");
5429 str
=generate_code_startcomp(str
);
5431 case S_START_COMP_REFD
:
5432 str
=generate_code_startcomp_refd(str
);
5435 str
= generate_code_compop(str
, "stop");
5438 str
= generate_code_compop(str
, "kill");
5441 str
= generate_code_configop(str
, "connect");
5444 str
= generate_code_configop(str
, "map");
5447 str
= generate_code_configop(str
, "disconnect");
5450 str
= generate_code_configop(str
, "unmap");
5453 str
=generate_code_starttimer(str
);
5456 str
=generate_code_stoptimer(str
);
5459 str
=generate_code_setverdict(str
);
5462 str
=generate_code_action(str
);
5464 case S_TESTCASE_INSTANCE
:
5465 str
=generate_code_testcaseinst(str
);
5467 case S_TESTCASE_INSTANCE_REFD
:
5468 str
=generate_code_execute_refd(str
);
5471 str
=generate_code_string2ttcn(str
);
5474 FATAL_ERROR("Statement::generate_code()");
5479 char* Statement::generate_code_string2ttcn(char *str
)
5481 expression_struct val_expr
;
5482 Code::init_expr(&val_expr
);
5483 str2ttcn
.val
->generate_code_expr(&val_expr
);
5485 expression_struct ref_expr
;
5486 Code::init_expr(&ref_expr
);
5487 str2ttcn
.ref
->generate_code(&ref_expr
);
5489 str
= mputstr(str
, val_expr
.preamble
);
5490 str
= mputstr(str
, ref_expr
.preamble
);
5492 str
= mputprintf(str
, "string_to_ttcn(%s,%s);\n", val_expr
.expr
, ref_expr
.expr
);
5494 str
= mputstr(str
, val_expr
.postamble
);
5495 str
= mputstr(str
, ref_expr
.postamble
);
5497 Code::free_expr(&val_expr
);
5498 Code::free_expr(&ref_expr
);
5503 void Statement::generate_code_expr(expression_struct
*expr
)
5505 switch (statementtype
) {
5507 generate_code_expr_receive(expr
, "receive");
5510 generate_code_expr_receive(expr
, "trigger");
5512 case S_CHECK_RECEIVE
:
5513 generate_code_expr_receive(expr
, "check_receive");
5516 generate_code_expr_getcall(expr
, "getcall");
5518 case S_CHECK_GETCALL
:
5519 generate_code_expr_getcall(expr
, "check_getcall");
5522 generate_code_expr_getreply(expr
, "getreply");
5524 case S_CHECK_GETREPLY
:
5525 generate_code_expr_getreply(expr
, "check_getreply");
5529 generate_code_expr_catch(expr
);
5532 generate_code_expr_check(expr
);
5535 generate_code_expr_done(expr
);
5538 generate_code_expr_killed(expr
);
5541 generate_code_expr_timeout(expr
);
5544 FATAL_ERROR("Statement::generate_code_expr()");
5548 void Statement::ilt_generate_code(ILT
*ilt
)
5550 switch (statementtype
) {
5552 ilt_generate_code_interleave(ilt
);
5555 ilt_generate_code_alt(ilt
);
5558 ilt_generate_code_def(ilt
);
5563 if (is_receiving_stmt()) {
5564 ilt_generate_code_receiving(ilt
);
5567 if (!has_receiving_stmt()) {
5568 char*& str
=ilt
->get_out_branches();
5569 str
=generate_code(str
);
5572 switch (statementtype
) {
5574 block
->ilt_generate_code(ilt
);
5577 ilt_generate_code_if(ilt
);
5580 ilt_generate_code_select(ilt
);
5583 ilt_generate_code_call(ilt
);
5586 ilt_generate_code_for(ilt
);
5589 ilt_generate_code_while(ilt
);
5592 ilt_generate_code_dowhile(ilt
);
5595 FATAL_ERROR("Statement::ilt_generate_code()");
5596 } // switch statementtype
5599 char *Statement::generate_code_standalone(char *str
)
5601 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5602 const char *label_str
= tmplabel
.c_str();
5603 str
= mputprintf(str
, "{\n"
5604 "%s:\n", label_str
);
5605 expression_struct expr
;
5606 Code::init_expr(&expr
);
5607 generate_code_expr(&expr
);
5608 str
= mputstr(str
, expr
.preamble
);
5609 str
= mputprintf(str
, "alt_status alt_flag = ALT_UNCHECKED, "
5610 "default_flag = ALT_UNCHECKED;\n"
5611 "TTCN_Snapshot::take_new(FALSE);\n"
5613 "if (alt_flag != ALT_NO) {\n"
5615 "if (alt_flag == ALT_YES) break;\n", expr
.expr
);
5617 str
= mputprintf(str
, "else if (alt_flag == ALT_REPEAT) goto %s;\n",
5620 str
= mputprintf(str
, "}\n"
5621 "if (default_flag != ALT_NO) {\n"
5622 "default_flag = TTCN_Default::try_altsteps();\n"
5623 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) break;\n"
5624 "else if (default_flag == ALT_REPEAT) goto %s;\n"
5626 str
= update_location_object(str
);
5627 str
= mputprintf(str
, "if (alt_flag == ALT_NO && default_flag == ALT_NO) "
5628 "TTCN_error(\"Stand-alone %s statement failed in file ", get_stmt_name());
5629 str
= Code::translate_string(str
, get_filename());
5630 int first_line
= get_first_line(), last_line
= get_last_line();
5631 if (first_line
< last_line
) str
= mputprintf(str
,
5632 " between lines %d and %d", first_line
, last_line
);
5633 else str
= mputprintf(str
, ", line %d", first_line
);
5634 str
= mputstr(str
, ".\");\n"
5635 "TTCN_Snapshot::take_new(TRUE);\n"
5637 str
= mputstr(str
, expr
.postamble
);
5638 str
= mputstr(str
, "}\n");
5639 Code::free_expr(&expr
);
5643 char *Statement::generate_code_funcinst(char *str
)
5645 expression_struct expr
;
5646 Code::init_expr(&expr
);
5647 ref_pard
->generate_code_const_ref(&expr
);
5648 str
=Code::merge_free_expr(str
, &expr
);
5652 char* Statement::generate_code_invoke(char *str
)
5654 expression_struct expr
;
5655 Code::init_expr(&expr
);
5656 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
5657 switch(last_v
->get_valuetype()) {
5658 case Value::V_FUNCTION
:
5659 case Value::V_ALTSTEP
: {
5660 Common::Assignment
*t_fat
= last_v
->get_refd_fat();
5661 expr
.expr
= mputprintf(expr
.expr
, "%s(",
5662 t_fat
->get_genname_from_scope(my_sb
).c_str());
5663 fau_refd
.ap_list2
->generate_code_alias(&expr
, t_fat
->get_FormalParList(),
5664 t_fat
->get_RunsOnType(), false);
5667 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
5668 Type
*t_governor
= fau_refd
.value
->get_expr_governor_last();
5669 expr
.expr
= mputprintf(expr
.expr
, ".%s(",
5670 t_governor
->get_typetype() == Type::T_ALTSTEP
?
5671 "invoke_standalone" : "invoke");
5672 fau_refd
.ap_list2
->generate_code_alias(&expr
, 0,
5673 t_governor
->get_fat_runs_on_type(),
5674 t_governor
->get_fat_runs_on_self()); }
5676 expr
.expr
= mputc(expr
.expr
, ')');
5677 str
=Code::merge_free_expr(str
, &expr
);
5681 char *Statement::generate_code_block(char *str
)
5683 switch (block
->get_exception_handling()) {
5684 case StatementBlock::EH_NONE
:
5686 case StatementBlock::EH_TRY
:
5687 str
= mputstr(str
, "try ");
5689 case StatementBlock::EH_CATCH
:
5690 str
= mputstr(str
, "catch (const TTCN_Error& ttcn_error) ");
5693 FATAL_ERROR("Statement::generate_code_block()");
5695 if (block
->get_nof_stmts() > 0 || block
->get_exception_handling()!=StatementBlock::EH_NONE
) {
5696 str
= mputstr(str
, "{\n");
5697 str
= block
->generate_code(str
);
5698 str
= mputstr(str
, "}\n");
5699 } else str
= mputstr(str
, "/* empty block */;\n");
5703 char *Statement::generate_code_log(char *str
)
5706 bool buffered_mode
= true;
5707 if (logargs
->get_nof_logargs() == 1) {
5708 LogArgument
*first_logarg
= logargs
->get_logarg_byIndex(0);
5709 switch (first_logarg
->get_type()) {
5710 case LogArgument::L_STR
:
5711 // the argument is a simple string: use non-buffered mode
5712 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, \"");
5713 str
= Code::translate_string(str
, first_logarg
->get_str().c_str());
5714 str
= mputstr(str
, "\");\n");
5715 buffered_mode
= false;
5717 case LogArgument::L_MACRO
: {
5718 Value
*t_val
= first_logarg
->get_val();
5719 if (t_val
->has_single_expr()) {
5720 // the argument is a simple macro call: use non-buffered mode
5721 str
= mputprintf(str
, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5722 t_val
->get_single_expr().c_str());
5723 buffered_mode
= false;
5729 if (buffered_mode
) {
5730 // the argument is a complicated construct: use buffered mode
5731 str
= mputstr(str
, "try {\n"
5732 "TTCN_Logger::begin_event(TTCN_USER);\n");
5733 str
= logargs
->generate_code(str
);
5734 str
= mputstr(str
, "TTCN_Logger::end_event();\n"
5736 "TTCN_Logger::finish_event();\n"
5741 // the argument is missing
5742 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, "
5743 "\"<empty log statement>\");\n");
5748 char *Statement::generate_code_testcase_stop(char *str
)
5750 if (logargs
) str
= generate_code_log(str
);
5751 str
= mputstr(str
, "TTCN_error(\"testcase.stop\");\n");
5755 char *Statement::generate_code_label(char *str
)
5758 return mputprintf(str
, "%s: /* TTCN-3 label: %s */;\n",
5759 get_clabel().c_str(), label
.id
->get_dispname().c_str());
5761 return mputprintf(str
, "/* unused TTCN-3 label: %s */;\n",
5762 label
.id
->get_dispname().c_str());
5766 char *Statement::generate_code_goto(char *str
)
5768 if (!go_to
.label
) FATAL_ERROR("Statement::generate_code_goto()");
5769 return mputprintf(str
, "goto %s; /* TTCN-3 label: %s */\n",
5770 go_to
.label
->get_clabel().c_str(), go_to
.id
->get_dispname().c_str());
5774 char* Statement::generate_code_if(char *str
)
5776 size_t blockcount
=0;
5777 bool unreach
=false, eachfalse
=true;
5778 str
=if_stmt
.ics
->generate_code(str
, blockcount
, unreach
, eachfalse
);
5779 if(if_stmt
.elseblock
&& !unreach
) {
5780 if(!eachfalse
) str
=mputstr(str
, "else ");
5782 str
=mputstr(str
, "{\n");
5784 str
=if_stmt
.elseblock
->generate_code(str
);
5786 while(blockcount
-->0) str
=mputstr(str
, "}\n");
5787 if(eachfalse
) str
=mputstr(str
, "/* never occurs */;\n");
5791 char* Statement::generate_code_select(char *str
)
5793 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5794 char *expr_init
=memptystr();
5795 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
5796 if (expr_init
[0]) { // some init code was generated
5797 str
= update_location_object(str
);
5798 str
= mputstr(str
, "{\n");
5799 str
= mputstr(str
, expr_init
);
5801 str
=select
.scs
->generate_code(str
, tmp_prefix
.c_str(), expr_name
);
5803 if (expr_init
[0]) str
=mputstr(str
, "}\n");
5808 char *Statement::generate_code_for(char *str
)
5810 /** \todo initial does not have its own location */
5811 // statements in initial may have side effects
5812 // generate code for them anyway
5813 if (loop
.for_stmt
.varinst
) {
5814 str
= mputstr(str
, "{\n");
5815 str
= loop
.for_stmt
.init_varinst
->generate_code_str(str
);
5817 str
= loop
.for_stmt
.init_ass
->update_location_object(str
);
5818 str
= loop
.for_stmt
.init_ass
->generate_code(str
);
5820 // check whether the final expression is constant
5821 bool final_is_true
= false, final_is_false
= false;
5822 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
5823 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
5824 else final_is_false
= true;
5826 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
5830 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5831 str
= update_location_object(str
);
5832 str
= mputstr(str
, "for ( ; ; ) {\n");
5833 // do not generate the exit condition for infinite loops
5834 if (!final_is_true
) {
5835 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
5836 size_t blockcount
= 0;
5837 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
5839 str
= mputstr(str
, ") break;\n");
5840 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5842 if (loop
.label_next
) str
= mputstr(str
, "{\n");
5843 str
= loop
.block
->generate_code(str
);
5844 if (loop
.label_next
)
5845 str
= mputprintf(str
, "}\n"
5846 "%s:\n", loop
.label_next
->c_str());
5847 str
= loop
.for_stmt
.step
->update_location_object(str
);
5848 str
= loop
.for_stmt
.step
->generate_code(str
);
5849 str
= mputstr(str
, "}\n");
5851 if (loop
.for_stmt
.varinst
) str
= mputstr(str
, "}\n");
5855 char *Statement::generate_code_while(char *str
)
5857 // check whether the expression is constant
5858 bool condition_always_true
= false, condition_always_false
= false;
5859 if (!loop
.expr
->is_unfoldable()) {
5860 if (loop
.expr
->get_val_bool()) condition_always_true
= true;
5861 else condition_always_false
= true;
5863 if (condition_always_false
) str
= mputstr(str
, "/* never occurs */;\n");
5865 str
= mputstr(str
, "for ( ; ; ) {\n");
5866 if (loop
.has_cnt_in_ags
) {
5868 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5869 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5871 // do not generate the exit condition for infinite loops
5872 if (!condition_always_true
) {
5873 str
= loop
.expr
->update_location_object(str
);
5874 size_t blockcount
= 0;
5875 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5876 str
= mputstr(str
, ") break;\n");
5877 while(blockcount
-- > 0) str
= mputstr(str
, "}\n");
5879 str
= loop
.block
->generate_code(str
);
5880 str
= mputstr(str
, "}\n");
5885 char *Statement::generate_code_dowhile(char *str
)
5887 // check whether the expression is constant
5888 bool expr_is_const
= !loop
.expr
->is_unfoldable();
5889 bool is_infinite_loop
= false;
5890 if (expr_is_const
) {
5891 if (loop
.expr
->get_val_bool()) is_infinite_loop
= true;
5892 else loop
.iterate_once
= true;
5894 if (loop
.iterate_once
&& !loop
.has_brk
&& !loop
.has_cnt
) {
5895 str
= mputstr(str
, "{\n");
5896 str
= loop
.block
->generate_code(str
);
5898 str
= mputstr(str
, "for ( ; ; ) {\n");
5899 if (loop
.has_cnt_in_ags
|| (!expr_is_const
&& loop
.has_cnt
))
5901 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5902 if (loop
.label_next
&& is_infinite_loop
)
5903 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5904 if (loop
.label_next
&& !is_infinite_loop
) str
= mputstr(str
, "{\n");
5905 str
= loop
.block
->generate_code(str
);
5906 // do not generate the exit condition for infinite loops
5907 if (!is_infinite_loop
) {
5908 if (loop
.label_next
)
5909 str
= mputprintf(str
, "}\n"
5910 "%s:\n", loop
.label_next
->c_str());
5911 str
= loop
.expr
->update_location_object(str
);
5912 if (loop
.iterate_once
) str
= mputstr(str
, "break;\n");
5914 size_t blockcount
= 0;
5915 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5916 str
= mputstr(str
, ") break;\n");
5917 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5921 str
= mputstr(str
, "}\n");
5925 char *Statement::generate_code_break(char *str
)
5927 // in altstep (2 (=2nd if branch))
5928 // in alt and loops - not inside interleave (4)
5929 // in loops without receiving statement embedded in interleave (4)
5930 // in loops with receiving statement embedded in interleave (1)
5931 // in interleave when not embedded in enclosed loop or alt/interleave (4)
5932 // in alt/interleave embedded in interleave (3)
5933 if (brk_cnt
.loop_stmt
&& brk_cnt
.loop_stmt
->loop
.il_label_end
)
5934 str
=mputprintf(str
, "goto %s;\n",
5935 brk_cnt
.loop_stmt
->loop
.il_label_end
->c_str());
5936 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_is_altstep())
5937 str
=mputstr(str
, "return ALT_BREAK;\n");
5938 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_il_label_end())
5939 str
=mputprintf(str
, "goto %s;\n",
5940 brk_cnt
.ags
->get_il_label_end()->c_str());
5942 str
=mputstr(str
, "break;\n");
5946 char *Statement::generate_code_continue(char *str
)
5948 // not inside interleave when continue is not inside embedded ags (2 or 1)
5949 // continue is inside ags enclosed in the loop (3)
5950 // in interleave (3, 2 or 1)
5951 if (brk_cnt
.loop_stmt
!= 0) {
5952 if (brk_cnt
.loop_stmt
->loop
.iterate_once
&& !brk_cnt
.ags
&&
5953 !brk_cnt
.loop_stmt
->loop
.is_ilt
)
5954 str
=mputstr(str
, "break;\n");
5956 if (!brk_cnt
.loop_stmt
->loop
.label_next
)
5957 str
=mputstr(str
, "continue;\n");
5959 str
=mputprintf(str
, "goto %s;\n",
5960 brk_cnt
.loop_stmt
->loop
.label_next
->c_str());
5963 FATAL_ERROR("Statement::generate_code_continue()");
5967 char *Statement::generate_code_repeat(char *str
)
5969 string
*tmplabel
=ags
->get_label();
5970 if(!tmplabel
) str
=mputstr(str
, "return ALT_REPEAT;\n");
5971 else str
=mputprintf(str
, "goto %s;\n", tmplabel
->c_str());
5975 char* Statement::generate_code_interleave(char *str
)
5978 str
=ilt
.generate_code(str
);
5982 void Statement::ilt_generate_code_interleave(ILT
*ilt
)
5984 const string
& mytmpid
=ilt
->get_my_tmpid();
5985 bool toplevel
=ilt
->is_toplevel();
5986 size_t goto_label_num
=toplevel
?(size_t)-1:ilt
->get_new_label_num();
5987 char*& out_branches
=ilt
->get_out_branches();
5988 out_branches
=update_location_object(out_branches
);
5990 if(toplevel
) state_cond
="";
5992 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
5993 (unsigned long) goto_label_num
);
5994 ags
->set_il_label_end (label_end
);
5996 ILT_branch
*branch
=ilt
->get_as_branch();
5997 size_t state_var
=branch
->get_my_state_var();
5998 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
5999 state_cond
=branch
->get_state_cond();
6000 if(!state_cond
.empty()) state_cond
+=" && ";
6001 char *s
=mprintf("%s_state[%lu]==%lu", mytmpid
.c_str(),
6002 (unsigned long) state_var
, (unsigned long) state_var_val
);
6005 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6007 (unsigned long) state_var
, (unsigned long) state_var_val
);
6009 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6010 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6011 if(ag
->get_type()!=AltGuard::AG_OP
)
6012 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6013 size_t state_var
=ilt
->get_new_state_var(toplevel
);
6014 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6015 ilt
->add_branch(new ILT_branch(ILT_branch::BT_IL
, ag
, state_cond
,
6016 state_var
, state_var_val
,
6019 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6021 (unsigned long) state_var
, (unsigned long) state_var_val
);
6024 out_branches
=mputprintf(out_branches
, "goto %s;\n"
6027 mytmpid
.c_str(), (unsigned long) goto_label_num
);
6030 void Statement::ilt_generate_code_alt(ILT
*ilt
)
6032 const string
& mytmpid
=ilt
->get_my_tmpid();
6033 size_t goto_label_num
=ilt
->get_new_label_num();
6034 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6035 (unsigned long) goto_label_num
);
6036 ags
->set_il_label_end (label_end
);
6037 ILT_branch
*branch
=ilt
->get_as_branch();
6038 string state_cond
=branch
->get_state_cond();
6039 size_t state_var
=branch
->get_my_state_var();
6040 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6041 char*& out_branches
=ilt
->get_out_branches();
6042 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6043 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6044 if(ag
->get_type()!=AltGuard::AG_OP
)
6045 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6046 ilt
->add_branch(new ILT_branch(ILT_branch::BT_ALT
, ag
, state_cond
,
6047 state_var
, state_var_val
,
6050 out_branches
=update_location_object(out_branches
);
6051 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6054 mytmpid
.c_str(), (unsigned long) state_var
,
6055 (unsigned long) state_var_val
,
6056 mytmpid
.c_str(), label_end
);
6060 void Statement::ilt_generate_code_receiving(ILT
*ilt
)
6062 const string
& mytmpid
=ilt
->get_my_tmpid();
6063 size_t goto_label_num
=ilt
->get_new_label_num();
6064 ILT_branch
*branch
=ilt
->get_as_branch();
6065 string state_cond
=branch
->get_state_cond();
6066 size_t state_var
=branch
->get_my_state_var();
6067 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6068 char*& out_branches
=ilt
->get_out_branches();
6069 ilt
->add_branch(new ILT_branch(ILT_branch::BT_RECV
, this, state_cond
,
6070 state_var
, state_var_val
, goto_label_num
));
6071 out_branches
=update_location_object(out_branches
);
6072 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6075 mytmpid
.c_str(), (unsigned long) state_var
,
6076 (unsigned long) state_var_val
,
6077 mytmpid
.c_str(), mytmpid
.c_str(),
6078 (unsigned long) goto_label_num
);
6081 void Statement::ilt_generate_code_def(ILT
*ilt
)
6083 char*& str
=ilt
->get_out_branches();
6084 str
=update_location_object(str
);
6086 char *genname
=mprintf("%s_d%lu_%s", ilt
->get_my_tmpid().c_str(),
6087 (unsigned long) ilt
->get_new_tmpnum(),
6088 def
->get_id().get_name().c_str());
6089 def
->set_genname(string(genname
));
6092 def
->ilt_generate_code(ilt
);
6095 void Statement::ilt_generate_code_if(ILT
*ilt
)
6097 char *end_label
=mprintf("%s_l%lu",
6098 ilt
->get_my_tmpid().c_str(),
6099 (unsigned long) ilt
->get_new_label_num());
6101 if_stmt
.ics
->ilt_generate_code(ilt
, end_label
, unreach
);
6102 if(if_stmt
.elseblock
&& !unreach
)
6103 if_stmt
.elseblock
->ilt_generate_code(ilt
);
6104 char*& str
=ilt
->get_out_branches();
6105 str
=mputprintf(str
, "%s:\n", end_label
);
6109 void Statement::ilt_generate_code_select(ILT
*ilt
)
6111 char*& str
=ilt
->get_out_branches();
6112 str
=update_location_object(str
);
6113 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6114 char *expr_init
=memptystr();
6115 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
6116 select
.scs
->ilt_generate_code(ilt
, tmp_prefix
.c_str(),
6117 expr_init
, expr_name
);
6122 void Statement::ilt_generate_code_call(ILT
*ilt
)
6124 char*& str
=ilt
->get_out_branches();
6125 str
=update_location_object(str
);
6126 expression_struct expr
;
6127 Code::init_expr(&expr
);
6128 port_op
.portref
->generate_code(&expr
);
6129 expr
.expr
= mputstr(expr
.expr
, ".call(");
6130 port_op
.s
.sendpar
->generate_code(&expr
);
6131 if(port_op
.s
.toclause
) {
6132 expr
.expr
= mputstr(expr
.expr
, ", ");
6133 port_op
.s
.toclause
->generate_code_expr(&expr
);
6135 expr
.expr
= mputc(expr
.expr
, ')');
6136 str
= Code::merge_free_expr(str
, &expr
);
6137 if (port_op
.s
.call
.body
) {
6138 str
= mputstr(str
, "{\n"); // (1)
6139 if (port_op
.s
.call
.timer
) {
6140 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6141 str
= mputstr(str
, "TIMER call_timer;\n");
6142 Code::init_expr(&expr
);
6143 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6144 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6145 expr
.expr
= mputc(expr
.expr
, ')');
6146 str
= Code::merge_free_expr(str
, &expr
);
6148 // the label name is used for prefixing local variables
6149 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6150 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6151 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this, tmplabel
,
6153 const char *label_str
= tmplabel
.c_str();
6154 str
=mputprintf(str
, "goto %s_end;\n"
6157 port_op
.s
.call
.body
->ilt_generate_code_call_body(ilt
, label_str
);
6158 str
=mputprintf(str
, "%s_end:\n", label_str
);
6162 void Statement::ilt_generate_code_for(ILT
*ilt
)
6164 char*& str
= ilt
->get_out_branches();
6165 str
= update_location_object(str
);
6166 // statements in initial may have side effects
6167 // generate code for them anyway
6168 if (loop
.for_stmt
.varinst
) {
6169 char *genname
= mprintf("%s_d%lu_", ilt
->get_my_tmpid().c_str(),
6170 (unsigned long) ilt
->get_new_tmpnum());
6171 loop
.for_stmt
.init_varinst
->set_genname(string(genname
));
6173 loop
.for_stmt
.init_varinst
->ilt_generate_code(ilt
);
6174 } else str
= loop
.for_stmt
.init_ass
->generate_code(str
);
6175 // check whether the final expression is constant
6176 bool final_is_true
= false, final_is_false
= false;
6177 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
6178 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
6179 else final_is_false
= true;
6181 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6183 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6184 (unsigned long) ilt
->get_new_label_num());
6185 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6186 // do not generate the exit condition for infinite loops
6187 if (!final_is_true
) {
6188 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
6189 size_t blockcount
= 0;
6190 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
6192 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6193 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6197 loop
.il_label_end
= new string(label_prefix
);
6198 *loop
.il_label_end
+= "end";
6201 loop
.label_next
= new string(label_prefix
);
6202 *loop
.label_next
+= "next";
6204 loop
.block
->ilt_generate_code(ilt
);
6205 if (loop
.label_next
)
6206 str
= mputprintf(str
, "%snext:\n", label_prefix
);
6207 str
= update_location_object(str
);
6208 str
= loop
.for_stmt
.step
->generate_code(str
);
6209 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6210 if (!final_is_true
|| loop
.has_brk
)
6211 str
= mputprintf(str
, "%send:\n", label_prefix
);
6216 void Statement::ilt_generate_code_while(ILT
*ilt
)
6218 char*& str
= ilt
->get_out_branches();
6219 // Location need not be set here; the location is set for the expression.
6220 // check whether the expression is constant
6221 bool expr_is_true
= false, expr_is_false
= false;
6222 if (!loop
.expr
->is_unfoldable()) {
6223 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6224 else expr_is_false
= true;
6226 if (expr_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6228 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6229 (unsigned long) ilt
->get_new_label_num());
6230 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6233 loop
.il_label_end
= new string(label_prefix
);
6234 *loop
.il_label_end
+= "end";
6237 loop
.label_next
= new string(label_prefix
);
6238 *loop
.label_next
+= "begin";
6240 // do not generate the exit condition for infinite loops
6241 if (!expr_is_true
) {
6242 str
= loop
.expr
->update_location_object(str
);
6243 size_t blockcount
= 0;
6244 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6245 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6246 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6248 loop
.block
->ilt_generate_code(ilt
);
6249 str
= update_location_object(str
);
6250 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6251 if (!expr_is_true
|| loop
.has_brk
)
6252 str
= mputprintf(str
, "%send:\n", label_prefix
);
6257 void Statement::ilt_generate_code_dowhile(ILT
*ilt
)
6259 char*& str
= ilt
->get_out_branches();
6260 // Location need not be set here; there is only a label before the body.
6261 // check whether the expression is constant
6262 bool expr_is_true
= false;
6263 if (!loop
.expr
->is_unfoldable()) {
6264 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6265 else loop
.iterate_once
= true;
6267 char *label_prefix
= 0;
6268 if (!loop
.iterate_once
|| loop
.has_brk
|| loop
.has_cnt
)
6269 label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6270 (unsigned long) ilt
->get_new_label_num());
6273 loop
.il_label_end
= new string(label_prefix
);
6274 *loop
.il_label_end
+= "end";
6277 loop
.label_next
= new string(label_prefix
);
6278 if (loop
.iterate_once
) {
6279 if (loop
.label_next
) *loop
.label_next
+= "end";
6280 loop
.block
->ilt_generate_code(ilt
);
6282 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6283 if (loop
.label_next
)
6284 *loop
.label_next
+= (expr_is_true
? "begin" : "next");
6285 loop
.block
->ilt_generate_code(ilt
);
6286 if (expr_is_true
) str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6288 if (loop
.label_next
) str
= mputprintf(str
, "%snext:\n", label_prefix
);
6289 str
= loop
.expr
->update_location_object(str
);
6290 size_t blockcount
= 0;
6291 str
= loop
.expr
->generate_code_tmp(str
, "if (", blockcount
);
6292 str
= mputprintf(str
, ") goto %sbegin;\n", label_prefix
);
6293 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6296 if (loop
.il_label_end
|| (loop
.iterate_once
&& loop
.label_next
)) {
6297 str
= mputprintf(str
, "%send: ;\n", label_prefix
);
6302 char *Statement::generate_code_return(char *str
)
6304 expression_struct expr
;
6305 Code::init_expr(&expr
);
6306 expr
.expr
= mputstr(expr
.expr
, "return");
6307 Definition
*my_def
= my_sb
->get_my_def();
6309 expr
.expr
= mputc(expr
.expr
, ' ');
6310 returnexpr
.v
->generate_code_expr_mandatory(&expr
);
6311 } else if (returnexpr
.t
) {
6312 expr
.expr
= mputc(expr
.expr
, ' ');
6313 if (!my_def
) FATAL_ERROR("Statement::generate_code_return()");
6314 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
6315 if (!dfb
) FATAL_ERROR("Statement::generate_code_return()");
6316 if (dfb
->get_template_restriction() != TR_NONE
&&
6317 returnexpr
.gen_restriction_check
) {
6318 returnexpr
.t
->generate_code_expr(&expr
,
6319 dfb
->get_template_restriction());
6321 returnexpr
.t
->generate_code_expr(&expr
, TR_NONE
);
6324 if (my_def
&& my_def
->get_asstype() == Definition::A_ALTSTEP
)
6325 expr
.expr
= mputstr(expr
.expr
, " ALT_YES");
6326 // else it's a return with no value: the only case a blank is unneeded
6328 return Code::merge_free_expr(str
, &expr
);
6331 char *Statement::generate_code_activate(char *str
)
6333 expression_struct expr
;
6334 Code::init_expr(&expr
);
6335 expr
.expr
= mputprintf(expr
.expr
, "%s(", ref_pard
->get_refd_assignment()
6336 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6337 ref_pard
->get_parlist()->generate_code_noalias(&expr
, ref_pard
->get_refd_assignment()->get_FormalParList());
6338 expr
.expr
= mputc(expr
.expr
, ')');
6339 return Code::merge_free_expr(str
, &expr
);
6342 char *Statement::generate_code_activate_refd(char *str
)
6344 expression_struct expr
;
6345 Code::init_expr(&expr
);
6346 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6347 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
6348 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6349 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6351 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
6352 expr
.expr
= mputstr(expr
.expr
, ".activate(");
6354 fau_refd
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6355 expr
.expr
= mputc(expr
.expr
, ')');
6356 return Code::merge_free_expr(str
, &expr
);
6359 char *Statement::generate_code_deactivate(char *str
)
6361 if(!deactivate
) str
=mputstr(str
, "TTCN_Default::deactivate_all();\n");
6363 expression_struct expr
;
6364 Code::init_expr(&expr
);
6365 expr
.expr
=mputstr(expr
.expr
, "TTCN_Default::deactivate(");
6366 deactivate
->generate_code_expr(&expr
);
6367 expr
.expr
=mputstr(expr
.expr
, ");\n");
6368 str
=Code::merge_free_expr(str
, &expr
);
6373 char *Statement::generate_code_send(char *str
)
6375 expression_struct expr
;
6376 Code::init_expr(&expr
);
6377 port_op
.portref
->generate_code(&expr
);
6378 expr
.expr
= mputstr(expr
.expr
, ".send(");
6379 generate_code_expr_sendpar(&expr
);
6380 if (port_op
.s
.toclause
) {
6381 expr
.expr
= mputstr(expr
.expr
, ", ");
6382 port_op
.s
.toclause
->generate_code_expr(&expr
);
6384 expr
.expr
= mputc(expr
.expr
, ')');
6385 return Code::merge_free_expr(str
, &expr
);
6388 char *Statement::generate_code_call(char *str
)
6390 expression_struct expr
;
6391 Code::init_expr(&expr
);
6392 port_op
.portref
->generate_code(&expr
);
6393 expr
.expr
= mputstr(expr
.expr
, ".call(");
6394 port_op
.s
.sendpar
->generate_code(&expr
);
6395 if(port_op
.s
.toclause
) {
6396 expr
.expr
= mputstr(expr
.expr
, ", ");
6397 port_op
.s
.toclause
->generate_code_expr(&expr
);
6399 expr
.expr
= mputc(expr
.expr
, ')');
6400 str
= Code::merge_free_expr(str
, &expr
);
6401 if (port_op
.s
.call
.body
) {
6402 str
= mputstr(str
, "{\n");
6403 if (port_op
.s
.call
.timer
) {
6404 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6405 str
= mputstr(str
, "TIMER call_timer;\n");
6406 Code::init_expr(&expr
);
6407 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6408 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6409 expr
.expr
= mputc(expr
.expr
, ')');
6410 str
= Code::merge_free_expr(str
, &expr
);
6412 // the label name is used for prefixing local variables
6413 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6414 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this,
6415 my_sb
->get_scope_mod_gen()->get_temporary_id(), false);
6416 str
=mputstr(str
, "}\n");
6421 char *Statement::generate_code_reply(char *str
)
6423 expression_struct expr
;
6424 Code::init_expr(&expr
);
6425 port_op
.portref
->generate_code(&expr
);
6426 expr
.expr
=mputstr(expr
.expr
, ".reply(");
6427 port_op
.s
.sendpar
->generate_code(&expr
);
6428 if(port_op
.s
.replyval
) {
6429 expr
.expr
=mputstr(expr
.expr
, ".set_value_template(");
6430 port_op
.s
.replyval
->generate_code_expr(&expr
);
6431 expr
.expr
=mputc(expr
.expr
, ')');
6433 if(port_op
.s
.toclause
) {
6434 expr
.expr
=mputstr(expr
.expr
, ", ");
6435 port_op
.s
.toclause
->generate_code_expr(&expr
);
6437 expr
.expr
=mputc(expr
.expr
, ')');
6438 return Code::merge_free_expr(str
, &expr
);
6441 char *Statement::generate_code_raise(char *str
)
6443 expression_struct expr
;
6444 Code::init_expr(&expr
);
6445 port_op
.portref
->generate_code(&expr
);
6446 expr
.expr
=mputstr(expr
.expr
, ".raise(");
6447 port_op
.s
.raise
.signature_ref
->generate_code(&expr
);
6448 expr
.expr
=mputstr(expr
.expr
, "_exception(");
6449 generate_code_expr_sendpar(&expr
);
6450 expr
.expr
=mputc(expr
.expr
, ')');
6451 if(port_op
.s
.toclause
) {
6452 expr
.expr
=mputstr(expr
.expr
, ", ");
6453 port_op
.s
.toclause
->generate_code_expr(&expr
);
6455 expr
.expr
=mputc(expr
.expr
, ')');
6456 return Code::merge_free_expr(str
, &expr
);
6459 char *Statement::generate_code_portop(char *str
, const char *opname
)
6461 if (port_op
.portref
) {
6462 expression_struct expr
;
6463 Code::init_expr(&expr
);
6464 port_op
.portref
->generate_code(&expr
);
6465 expr
.expr
=mputprintf(expr
.expr
, ".%s()", opname
);
6466 str
=Code::merge_free_expr(str
, &expr
);
6468 str
= mputprintf(str
, "PORT::all_%s();\n", opname
);
6473 char *Statement::generate_code_startcomp(char *str
)
6475 expression_struct expr
;
6476 Code::init_expr(&expr
);
6477 Common::Assignment
*func
= comp_op
.funcinstref
->get_refd_assignment();
6478 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6479 func
->get_genname_from_scope(my_sb
, "start_").c_str());
6480 comp_op
.compref
->generate_code_expr(&expr
);
6481 FormalParList
*fplist
= func
->get_FormalParList();
6482 if (fplist
->get_nof_fps() > 0) {
6483 expr
.expr
= mputstr(expr
.expr
, ", ");
6484 comp_op
.funcinstref
->get_parlist()->generate_code_noalias(&expr
, fplist
);
6486 expr
.expr
= mputc(expr
.expr
, ')');
6487 return Code::merge_free_expr(str
, &expr
);
6490 char *Statement::generate_code_startcomp_refd(char *str
)
6492 expression_struct expr
;
6493 Code::init_expr(&expr
);
6494 Value
*last_v
= comp_op
.derefered
.value
->get_value_refd_last();
6495 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
6496 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6497 ->get_genname_from_scope(my_sb
, "start_").c_str());
6499 comp_op
.derefered
.value
->generate_code_expr_mandatory(&expr
);
6500 expr
.expr
= mputstr(expr
.expr
, ".start(");
6502 comp_op
.compref
->generate_code_expr(&expr
);
6503 if (comp_op
.derefered
.ap_list2
->get_nof_pars() > 0) {
6504 expr
.expr
= mputstr(expr
.expr
, ", ");
6505 comp_op
.derefered
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6507 expr
.expr
= mputc(expr
.expr
, ')');
6508 return Code::merge_free_expr(str
, &expr
);
6511 char *Statement::generate_code_compop(char *str
, const char *opname
)
6513 expression_struct expr
;
6514 Code::init_expr(&expr
);
6515 if (comp_op
.compref
) {
6516 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
6517 if (v_last
->get_valuetype() == Value::V_REFD
) {
6518 // the argument is a simple component reference
6519 v_last
->generate_code_expr_mandatory(&expr
);
6520 expr
.expr
= mputprintf(expr
.expr
, ".%s()", opname
);
6522 bool refers_to_self
= false;
6523 if (v_last
->get_valuetype() == Value::V_EXPR
) {
6524 // the argument is a special component reference (mtc, self, etc.)
6525 switch (v_last
->get_optype()) {
6526 case Value::OPTYPE_COMP_MTC
: {
6527 Definition
*my_def
= my_sb
->get_my_def();
6528 if (my_def
&& my_def
->get_asstype() == Definition::A_TESTCASE
)
6529 refers_to_self
= true;
6531 case Value::OPTYPE_COMP_SELF
:
6532 refers_to_self
= true;
6537 if (refers_to_self
) {
6538 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_execution()",
6541 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_component(",
6543 v_last
->generate_code_expr(&expr
);
6544 expr
.expr
= mputc(expr
.expr
, ')');
6548 // the operation refers to all component
6549 expr
.expr
= mputprintf(expr
.expr
,
6550 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname
);
6552 return Code::merge_free_expr(str
, &expr
);
6555 char *Statement::generate_code_configop(char *str
, const char *opname
)
6557 expression_struct expr
;
6558 Code::init_expr(&expr
);
6559 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_port(", opname
);
6560 config_op
.compref1
->generate_code_expr(&expr
);
6561 expr
.expr
= mputstr(expr
.expr
, ", ");
6562 if (config_op
.compref1
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6563 // the component type is known
6564 // the name of the referred port can be used
6565 config_op
.portref1
->generate_code_portref(&expr
, my_sb
);
6566 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6568 // the component type is unknown
6569 // a simple string shall be formed from the port name and array indices
6570 generate_code_portref(&expr
, config_op
.portref1
);
6572 expr
.expr
= mputstr(expr
.expr
, ", ");
6573 config_op
.compref2
->generate_code_expr(&expr
);
6574 expr
.expr
= mputstr(expr
.expr
, ", ");
6575 if (config_op
.compref2
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6576 // the component type is known
6577 // the name of the referred port can be used
6578 config_op
.portref2
->generate_code_portref(&expr
, my_sb
);
6579 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6581 // the component type is unknown
6582 // a simple string shall be formed from the port name and array indices
6583 generate_code_portref(&expr
, config_op
.portref2
);
6585 expr
.expr
= mputc(expr
.expr
, ')');
6586 return Code::merge_free_expr(str
, &expr
);
6589 char *Statement::generate_code_starttimer(char *str
)
6591 expression_struct expr
;
6592 Code::init_expr(&expr
);
6593 timer_op
.timerref
->generate_code(&expr
);
6594 expr
.expr
=mputstr(expr
.expr
, ".start(");
6595 if(timer_op
.value
) timer_op
.value
->generate_code_expr(&expr
);
6596 expr
.expr
=mputc(expr
.expr
, ')');
6597 str
=Code::merge_free_expr(str
, &expr
);
6601 char *Statement::generate_code_stoptimer(char *str
)
6603 if(!timer_op
.timerref
) str
=mputstr(str
, "TIMER::all_stop();\n");
6605 expression_struct expr
;
6606 Code::init_expr(&expr
);
6607 timer_op
.timerref
->generate_code(&expr
);
6608 expr
.expr
=mputstr(expr
.expr
, ".stop()");
6609 str
=Code::merge_free_expr(str
, &expr
);
6614 char *Statement::generate_code_setverdict(char *str
)
6616 expression_struct expr
;
6617 Code::init_expr(&expr
);
6618 expr
.expr
=mputstr(expr
.expr
, "TTCN_Runtime::setverdict(");
6619 setverdict
.verdictval
->generate_code_expr(&expr
);
6620 if (setverdict
.logargs
) {
6621 expr
.expr
=mputc(expr
.expr
, ',');
6622 expression_struct expr_reason
;
6623 Code::init_expr(&expr_reason
);
6624 setverdict
.logargs
->generate_code_expr(&expr_reason
);
6625 if (expr_reason
.preamble
)
6626 expr
.preamble
= mputprintf(expr
.preamble
, "%s;\n",
6627 expr_reason
.preamble
);
6628 if (expr_reason
.postamble
)
6629 expr
.postamble
= mputprintf(expr
.postamble
, "%s;\n",
6630 expr_reason
.postamble
);
6631 expr
.expr
= mputprintf(expr
.expr
, "%s", expr_reason
.expr
);
6632 Code::free_expr(&expr_reason
);
6634 expr
.expr
=mputc(expr
.expr
, ')');
6635 str
=Code::merge_free_expr(str
, &expr
);
6639 char *Statement::generate_code_action(char *str
)
6641 str
=mputstr(str
, "TTCN_Runtime::begin_action();\n");
6642 if(!logargs
) str
=mputstr(str
, "TTCN_Logger::log_event_str"
6643 "(\"<empty action statement>\");\n");
6644 else str
=logargs
->generate_code(str
);
6645 str
=mputstr(str
, "TTCN_Runtime::end_action();\n");
6649 char *Statement::generate_code_testcaseinst(char *str
)
6651 expression_struct expr
;
6652 Code::init_expr(&expr
);
6653 Common::Assignment
*testcase
= testcase_inst
.tcref
->get_refd_assignment();
6654 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6655 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6656 ActualParList
*t_aplist
= testcase_inst
.tcref
->get_parlist();
6657 if (t_aplist
->get_nof_pars() > 0) {
6658 t_aplist
->generate_code_alias(&expr
, testcase
->get_FormalParList(),
6660 expr
.expr
= mputstr(expr
.expr
, ", ");
6662 if (testcase_inst
.timerval
) {
6663 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6664 testcase_inst
.timerval
->generate_code_expr(&expr
);
6665 expr
.expr
= mputc(expr
.expr
, ')');
6666 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6667 return Code::merge_free_expr(str
, &expr
);
6670 char *Statement::generate_code_execute_refd(char *str
)
6672 expression_struct expr
;
6673 Code::init_expr(&expr
);
6674 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6675 if (last_v
->get_valuetype() == Value::V_TESTCASE
) {
6676 Common::Assignment
*testcase
= last_v
->get_refd_fat();
6677 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6678 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6679 execute_refd
.ap_list2
->generate_code_alias(&expr
,
6680 testcase
->get_FormalParList(), 0, false);
6682 execute_refd
.value
->generate_code_expr_mandatory(&expr
);
6683 expr
.expr
= mputstr(expr
.expr
, ".execute(");
6684 execute_refd
.ap_list2
->generate_code_alias(&expr
, 0, 0, false);
6686 if (execute_refd
.ap_list2
->get_nof_pars() > 0)
6687 expr
.expr
= mputstr(expr
.expr
, ", ");
6688 if (execute_refd
.timerval
) {
6689 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6690 execute_refd
.timerval
->generate_code_expr(&expr
);
6691 expr
.expr
= mputc(expr
.expr
, ')');
6692 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6693 return Code::merge_free_expr(str
,&expr
);
6696 void Statement::generate_code_expr_receive(expression_struct
*expr
,
6699 if (port_op
.portref
) {
6700 // The operation refers to a specific port.
6701 port_op
.portref
->generate_code(expr
);
6702 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6703 if (port_op
.r
.rcvpar
) {
6704 // The receive parameter is present.
6705 if (use_runtime_2
&& TypeConv::needs_conv_redir(port_op
.r
.rcvpar
,
6706 port_op
.r
.redirect
.value
)) {
6707 // Don't change the first parameter. Otherwise it won't receive
6708 // anything. The only thing we need is a temporary to save the
6709 // result and a conversion at the end.
6710 TypeConv::gen_conv_code_redir(expr
, port_op
.r
.rcvpar
,
6711 port_op
.r
.redirect
.value
);
6713 port_op
.r
.rcvpar
->generate_code(expr
);
6714 expr
->expr
= mputstr(expr
->expr
, ", ");
6715 if (port_op
.r
.redirect
.value
) {
6716 // Value redirect is also present.
6717 expr
->expr
= mputstr(expr
->expr
, "&(");
6718 port_op
.r
.redirect
.value
->generate_code(expr
);
6719 expr
->expr
= mputc(expr
->expr
, ')');
6720 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6722 expr
->expr
= mputstr(expr
->expr
, ", ");
6725 // the operation refers to any port
6726 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6728 generate_code_expr_fromclause(expr
);
6729 expr
->expr
= mputstr(expr
->expr
, ", ");
6730 generate_code_expr_senderredirect(expr
);
6731 expr
->expr
= mputc(expr
->expr
, ')');
6734 void Statement::generate_code_expr_getcall(expression_struct
*expr
,
6737 if (port_op
.portref
) {
6738 // the operation refers to a specific port
6739 port_op
.portref
->generate_code(expr
);
6740 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6741 if (port_op
.r
.rcvpar
) {
6742 // the signature template is present
6743 port_op
.r
.rcvpar
->generate_code(expr
);
6744 expr
->expr
= mputstr(expr
->expr
, ", ");
6745 generate_code_expr_fromclause(expr
);
6746 // a temporary object is needed for parameter redirect
6747 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6748 expr
->expr
= mputprintf(expr
->expr
, ", %s_call_redirect(",
6749 signature
->get_genname_value(my_sb
).c_str());
6750 if (port_op
.r
.redirect
.param
)
6751 port_op
.r
.redirect
.param
->generate_code(expr
);
6752 expr
->expr
= mputstr(expr
->expr
, "), ");
6753 generate_code_expr_senderredirect(expr
);
6755 // the signature parameter is not present
6756 generate_code_expr_fromclause(expr
);
6757 expr
->expr
= mputstr(expr
->expr
, ", ");
6758 generate_code_expr_senderredirect(expr
);
6761 // the operation refers to any port
6762 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6763 generate_code_expr_fromclause(expr
);
6764 expr
->expr
= mputstr(expr
->expr
, ", ");
6765 generate_code_expr_senderredirect(expr
);
6767 expr
->expr
=mputc(expr
->expr
, ')');
6770 void Statement::generate_code_expr_getreply(expression_struct
*expr
,
6773 if (port_op
.portref
) {
6774 // the operation refers to a specific port
6775 port_op
.portref
->generate_code(expr
);
6776 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6777 if (port_op
.r
.rcvpar
) {
6778 // the signature template is present
6779 port_op
.r
.rcvpar
->generate_code(expr
);
6780 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6782 signature
->get_type_refd_last()->get_signature_return_type();
6784 expr
->expr
= mputstr(expr
->expr
, ".set_value_template(");
6785 if (port_op
.r
.getreply_valuematch
) {
6786 // the value match is also present
6787 port_op
.r
.getreply_valuematch
->generate_code(expr
);
6789 // the value match is not present
6790 // we must substitute it with ? in the signature template
6791 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6792 return_type
->get_genname_template(my_sb
).c_str());
6794 expr
->expr
= mputc(expr
->expr
, ')');
6796 expr
->expr
= mputstr(expr
->expr
, ", ");
6797 generate_code_expr_fromclause(expr
);
6798 // a temporary object is needed for value and parameter redirect
6799 expr
->expr
= mputprintf(expr
->expr
, ", %s_reply_redirect(",
6800 signature
->get_genname_value(my_sb
).c_str());
6802 // the first argument of the constructor must contain
6803 // the value redirect
6804 if (port_op
.r
.redirect
.value
) {
6805 expr
->expr
= mputstr(expr
->expr
, "&(");
6806 port_op
.r
.redirect
.value
->generate_code(expr
);
6807 expr
->expr
= mputc(expr
->expr
, ')');
6808 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6809 if (port_op
.r
.redirect
.param
) expr
->expr
= mputstr(expr
->expr
, ", ");
6811 if (port_op
.r
.redirect
.param
)
6812 port_op
.r
.redirect
.param
->generate_code(expr
);
6813 expr
->expr
= mputstr(expr
->expr
, "), ");
6814 generate_code_expr_senderredirect(expr
);
6816 // the signature template is not present
6817 generate_code_expr_fromclause(expr
);
6818 expr
->expr
= mputstr(expr
->expr
, ", ");
6819 generate_code_expr_senderredirect(expr
);
6822 // the operation refers to any port
6823 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6824 generate_code_expr_fromclause(expr
);
6825 expr
->expr
= mputstr(expr
->expr
, ", ");
6826 generate_code_expr_senderredirect(expr
);
6828 expr
->expr
= mputc(expr
->expr
, ')');
6831 void Statement::generate_code_expr_catch(expression_struct
*expr
)
6833 if (port_op
.portref
) {
6834 // the operation refers to a specific port
6835 if (port_op
.r
.ctch
.timeout
) {
6836 // the operation catches the timeout exception
6837 expr
->expr
= mputstr(expr
->expr
, "call_timer.timeout()");
6840 port_op
.portref
->generate_code(expr
);
6841 expr
->expr
= mputprintf(expr
->expr
, ".%s(",
6842 statementtype
== S_CHECK_CATCH
? "check_catch" : "get_exception");
6843 if (port_op
.r
.ctch
.signature_ref
) {
6844 // the signature reference and the exception template is present
6845 expr
->expr
= mputprintf(expr
->expr
, "%s_exception_template(",
6846 port_op
.r
.ctch
.signature
->get_genname_value(my_sb
).c_str());
6847 port_op
.r
.rcvpar
->generate_code(expr
);
6848 expr
->expr
= mputstr(expr
->expr
, ", ");
6849 if (port_op
.r
.redirect
.value
) {
6850 // value redirect is also present
6851 expr
->expr
= mputstr(expr
->expr
, "&(");
6852 port_op
.r
.redirect
.value
->generate_code(expr
);
6853 expr
->expr
= mputc(expr
->expr
, ')');
6854 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6855 expr
->expr
= mputstr(expr
->expr
, "), ");
6858 // the operation refers to any port
6859 expr
->expr
= mputprintf(expr
->expr
, "PORT::%s(",
6860 statementtype
== S_CHECK_CATCH
? "any_check_catch" : "any_catch");
6862 generate_code_expr_fromclause(expr
);
6863 expr
->expr
= mputstr(expr
->expr
, ", ");
6864 generate_code_expr_senderredirect(expr
);
6865 expr
->expr
= mputc(expr
->expr
, ')');
6868 void Statement::generate_code_expr_check(expression_struct
*expr
)
6870 if (port_op
.portref
) {
6871 // the operation refers to a specific port
6872 port_op
.portref
->generate_code(expr
);
6873 expr
->expr
= mputstr(expr
->expr
, ".check");
6875 // the operation refers to any port
6876 expr
->expr
= mputstr(expr
->expr
, "PORT::any_check");
6878 expr
->expr
= mputc(expr
->expr
, '(');
6879 generate_code_expr_fromclause(expr
);
6880 expr
->expr
= mputstr(expr
->expr
, ", ");
6881 generate_code_expr_senderredirect(expr
);
6882 expr
->expr
= mputc(expr
->expr
, ')');
6885 void Statement::generate_code_expr_done(expression_struct
*expr
)
6887 if (comp_op
.compref
) {
6888 if (comp_op
.donereturn
.donematch
) {
6889 // value returning done
6890 // figure out what type the done() function belongs to
6891 Type
*t
= comp_op
.donereturn
.donematch
6892 ->get_expr_governor(Type::EXPECTED_TEMPLATE
);
6893 if (!t
) FATAL_ERROR("Statement::generate_code_expr_done()");
6894 while (t
->is_ref() && !t
->has_done_attribute())
6895 t
= t
->get_type_refd();
6896 if (!t
->has_done_attribute())
6897 FATAL_ERROR("Statement::generate_code_expr_done()");
6898 // determine whether the done() function is in the same module
6899 Common::Module
*t_mod
= t
->get_my_scope()->get_scope_mod_gen();
6900 if (t_mod
!= my_sb
->get_scope_mod_gen()) {
6901 expr
->expr
= mputprintf(expr
->expr
, "%s::",
6902 t_mod
->get_modid().get_name().c_str());
6904 expr
->expr
= mputstr(expr
->expr
, "done(");
6905 comp_op
.compref
->generate_code_expr(expr
);
6906 expr
->expr
= mputstr(expr
->expr
, ", ");
6907 comp_op
.donereturn
.donematch
->generate_code(expr
);
6908 expr
->expr
= mputstr(expr
->expr
, ", ");
6909 if (comp_op
.donereturn
.redirect
) {
6910 // value redirect is present
6911 expr
->expr
= mputstr(expr
->expr
, "&(");
6912 comp_op
.donereturn
.redirect
->generate_code(expr
);
6913 expr
->expr
= mputc(expr
->expr
, ')');
6915 // value redirect is omitted
6916 expr
->expr
= mputstr(expr
->expr
, "NULL");
6918 expr
->expr
= mputc(expr
->expr
, ')');
6921 comp_op
.compref
->generate_code_expr_mandatory(expr
);
6922 expr
->expr
= mputstr(expr
->expr
, ".done()");
6924 } else if (comp_op
.any_or_all
== C_ANY
) {
6925 // any component.done
6926 expr
->expr
= mputstr(expr
->expr
,
6927 "TTCN_Runtime::component_done(ANY_COMPREF)");
6929 // all component.done
6930 expr
->expr
= mputstr(expr
->expr
,
6931 "TTCN_Runtime::component_done(ALL_COMPREF)");
6935 void Statement::generate_code_expr_killed(expression_struct
*expr
)
6937 if (comp_op
.compref
) {
6939 comp_op
.compref
->generate_code_expr_mandatory(expr
);
6940 expr
->expr
= mputstr(expr
->expr
, ".killed()");
6941 } else if (comp_op
.any_or_all
== C_ANY
) {
6942 // any component.killed
6943 expr
->expr
= mputstr(expr
->expr
,
6944 "TTCN_Runtime::component_killed(ANY_COMPREF)");
6946 // all component.killed
6947 expr
->expr
= mputstr(expr
->expr
,
6948 "TTCN_Runtime::component_killed(ALL_COMPREF)");
6952 void Statement::generate_code_expr_timeout(expression_struct
*expr
)
6954 if (timer_op
.timerref
) {
6955 timer_op
.timerref
->generate_code(expr
);
6956 expr
->expr
=mputstr(expr
->expr
, ".timeout()");
6957 } else expr
->expr
= mputstr(expr
->expr
, "TIMER::any_timeout()");
6960 void Statement::generate_code_expr_sendpar(expression_struct
*expr
)
6962 Template
*templ_body
= port_op
.s
.sendpar
->get_Template();
6963 if (!port_op
.s
.sendpar
->get_DerivedRef() &&
6964 templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
) {
6965 // the send parameter is a value: optimization is possible
6966 Value
*t_val
= templ_body
->get_specific_value();
6967 bool cast_needed
= t_val
->explicit_cast_needed();
6969 // the ambiguous C++ expression is converted to the value class
6970 expr
->expr
= mputprintf(expr
->expr
, "%s(",
6971 t_val
->get_my_governor()->get_genname_value(my_sb
).c_str());
6973 t_val
->generate_code_expr_mandatory(expr
);
6974 if (cast_needed
) expr
->expr
= mputc(expr
->expr
, ')');
6976 // the send parameter is a real template: optimization is not possible
6977 port_op
.s
.sendpar
->generate_code(expr
);
6981 void Statement::generate_code_expr_fromclause(expression_struct
*expr
)
6983 if (port_op
.r
.fromclause
) {
6984 // the from clause is present: trivial case
6985 port_op
.r
.fromclause
->generate_code(expr
);
6986 } else if (port_op
.r
.redirect
.sender
) {
6987 // from clause is omitted, but sender redirect is present
6988 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
6990 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
6991 if (t_var_type
->get_type_refd_last()->get_typetype() ==
6992 Type::T_COMPONENT
) {
6993 // the variable can store a component reference
6994 expr
->expr
= mputstr(expr
->expr
, "any_compref");
6996 // the variable can store an address value
6997 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6998 t_var_type
->get_genname_template(my_sb
).c_str());
7001 // neither from clause nor sender redirect is present
7002 // the operation cannot refer to address type
7003 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7007 void Statement::generate_code_expr_senderredirect(expression_struct
*expr
)
7009 if (port_op
.r
.redirect
.sender
) {
7010 expr
->expr
= mputstr(expr
->expr
, "&(");
7011 port_op
.r
.redirect
.sender
->generate_code(expr
);
7012 expr
->expr
= mputc(expr
->expr
, ')');
7013 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
7016 void Statement::generate_code_portref(expression_struct
*expr
,
7019 // make a backup of the current expression
7020 char *expr_backup
= expr
->expr
;
7021 // build the equivalent of p_ref in expr->expr
7022 expr
->expr
= mprintf("\"%s\"", p_ref
->get_id()->get_dispname().c_str());
7023 FieldOrArrayRefs
*t_subrefs
= p_ref
->get_subrefs();
7025 // array indices are present
7026 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
7027 FieldOrArrayRef
*t_ref
= t_subrefs
->get_ref(i
);
7028 if (t_ref
->get_type() != FieldOrArrayRef::ARRAY_REF
)
7029 FATAL_ERROR("Statement::generate_code_portref()");
7030 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7031 char *tmp
= expr
->expr
;
7032 expr
->expr
= mcopystr("get_port_name(");
7033 expr
->expr
= mputstr(expr
->expr
, tmp
);
7035 expr
->expr
= mputstr(expr
->expr
, ", ");
7036 t_ref
->get_val()->generate_code_expr(expr
);
7037 expr
->expr
= mputc(expr
->expr
, ')');
7040 // now expr->expr contains the equivalent of p_ref
7041 // append it to the original expression and restore the result
7042 expr_backup
= mputstr(expr_backup
, expr
->expr
);
7044 expr
->expr
= expr_backup
;
7047 void Statement::set_parent_path(WithAttribPath
* p_path
) {
7048 switch (statementtype
) {
7050 def
->set_parent_path(p_path
);
7053 block
->set_parent_path(p_path
);
7056 if_stmt
.ics
->set_parent_path(p_path
);
7057 if (if_stmt
.elseblock
)
7058 if_stmt
.elseblock
->set_parent_path(p_path
);
7061 select
.scs
->set_parent_path(p_path
);
7064 loop
.block
->set_parent_path(p_path
);
7068 loop
.block
->set_parent_path(p_path
);
7079 case S_STOP_TESTCASE
:
7083 case S_UNKNOWN_INSTANCE
:
7084 case S_FUNCTION_INSTANCE
:
7085 case S_ALTSTEP_INSTANCE
:
7096 case S_CHECK_RECEIVE
:
7099 case S_CHECK_GETCALL
:
7101 case S_CHECK_GETREPLY
:
7110 case S_START_COMP_REFD
:
7123 case S_TESTCASE_INSTANCE
:
7124 case S_TESTCASE_INSTANCE_REFD
:
7125 case S_ACTIVATE_REFD
:
7126 case S_UNKNOWN_INVOKED
:
7127 case S_FUNCTION_INVOKED
:
7128 case S_ALTSTEP_INVOKED
:
7132 FATAL_ERROR("Statement::set_parent_path()");
7136 // =================================
7138 // =================================
7140 Assignment::Assignment(Reference
*p_ref
, Template
*p_templ
)
7141 : asstype(ASS_UNKNOWN
), ref(p_ref
), templ(p_templ
), self_ref(false),
7142 template_restriction(TR_NONE
), gen_restriction_check(false)
7144 if(!ref
|| !templ
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7147 Assignment::Assignment(Reference
*p_ref
, Value
*p_val
)
7148 : asstype(ASS_VAR
), ref(p_ref
), val(p_val
), self_ref(false),
7149 template_restriction(TR_NONE
), gen_restriction_check(false)
7151 if(!ref
|| !val
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7154 Assignment::~Assignment()
7169 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7173 Assignment
*Assignment::clone() const
7175 FATAL_ERROR("Assignment::clone");
7178 void Assignment::set_my_scope(Scope
*p_scope
)
7183 ref
->set_my_scope(p_scope
);
7184 templ
->set_my_scope(p_scope
);
7187 ref
->set_my_scope(p_scope
);
7188 val
->set_my_scope(p_scope
);
7193 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7197 void Assignment::set_fullname(const string
& p_fullname
)
7199 Node::set_fullname(p_fullname
);
7203 ref
->set_fullname(p_fullname
);
7204 templ
->set_fullname(p_fullname
);
7207 ref
->set_fullname(p_fullname
);
7208 val
->set_fullname(p_fullname
);
7213 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7217 void Assignment::dump(unsigned int level
) const
7219 // warning, ref is not always set (e.g. ASS_ERROR)
7227 DEBUG(level
, "*** ERROR ***");
7231 DEBUG(level
, "*** UNKNOWN ***");
7236 templ
->dump(level
+1);
7241 void Assignment::chk_unknown_ass()
7243 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7244 if (!t_ass
) goto error
;
7245 switch (t_ass
->get_asstype()) {
7246 case Common::Assignment::A_ERROR
:
7248 case Common::Assignment::A_PAR_VAL_IN
:
7249 t_ass
->use_as_lvalue(*ref
);
7251 case Common::Assignment::A_VAR
:
7252 case Common::Assignment::A_PAR_VAL_OUT
:
7253 case Common::Assignment::A_PAR_VAL_INOUT
:
7254 if (templ
->is_Value()) {
7255 Value
*t_val
= templ
->get_Value();
7261 templ
->error("A template body with matching symbols cannot be"
7262 " assigned to a variable");
7266 case Common::Assignment::A_PAR_TEMPL_IN
:
7267 t_ass
->use_as_lvalue(*ref
);
7269 case Common::Assignment::A_VAR_TEMPLATE
: {
7270 Type::typetype_t tt
= t_ass
->get_Type()->get_typetype();
7273 case Type::T_BSTR_A
:
7278 case Type::T_UTF8STRING
:
7279 case Type::T_NUMERICSTRING
:
7280 case Type::T_PRINTABLESTRING
:
7281 case Type::T_TELETEXSTRING
:
7282 case Type::T_VIDEOTEXSTRING
:
7283 case Type::T_IA5STRING
:
7284 case Type::T_GRAPHICSTRING
:
7285 case Type::T_VISIBLESTRING
:
7286 case Type::T_GENERALSTRING
:
7287 case Type::T_UNIVERSALSTRING
:
7288 case Type::T_BMPSTRING
:
7289 case Type::T_UTCTIME
:
7290 case Type::T_GENERALIZEDTIME
:
7291 case Type::T_OBJECTDESCRIPTOR
: {
7292 Ttcn::FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7293 if (!subrefs
) break;
7294 size_t nof_subrefs
= subrefs
->get_nof_refs();
7295 if (nof_subrefs
> 0) {
7296 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
7297 ->get_ref(nof_subrefs
- 1);
7298 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
7299 if (!templ
->is_Value()) {
7300 templ
->error("A template body with matching symbols cannot be "
7301 "assigned to an element of a template variable");
7311 case Common::Assignment::A_PAR_TEMPL_OUT
:
7312 case Common::Assignment::A_PAR_TEMPL_INOUT
:
7313 asstype
= ASS_TEMPLATE
;
7317 ref
->error("Reference to a variable or template variable was expected "
7318 "instead of %s", t_ass
->get_description().c_str());
7325 asstype
= ASS_ERROR
;
7329 void Assignment::chk_var_ass()
7331 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7332 Type
*var_type
= lhs
->get_Type();
7333 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7335 var_type
->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7336 if (!type
) goto error
;
7337 val
->set_my_governor(type
);
7338 type
->chk_this_value_ref(val
);
7339 if (val
->get_value_refd_last()->get_valuetype() == Value::V_OMIT
) {
7340 Identifier
*field_id
= 0;
7341 if (subrefs
) field_id
= subrefs
->remove_last_field();
7343 val
->error("Omit value can be assigned to an optional field of "
7344 "a record or set value only");
7347 Type
*base_type
= var_type
7348 ->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7349 // Putting field_id back to subrefs.
7350 subrefs
->add(new FieldOrArrayRef(field_id
));
7351 base_type
= base_type
->get_type_refd_last();
7352 switch (base_type
->get_typetype()) {
7361 val
->error("Omit value can be assigned to an optional field of "
7362 "a record or set value only");
7365 if (!base_type
->get_comp_byName(*field_id
)->get_is_optional()) {
7366 val
->error("Assignment of `omit' to mandatory field `%s' of type "
7367 "`%s'", field_id
->get_dispname().c_str(),
7368 base_type
->get_typename().c_str());
7372 bool is_string_element
= subrefs
&& subrefs
->refers_to_string_element();
7373 self_ref
|= type
->chk_this_value(val
, lhs
, Type::EXPECTED_DYNAMIC_VALUE
,
7374 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
,
7375 (is_string_element
? NO_SUB_CHK
: SUB_CHK
), NOT_IMPLICIT_OMIT
,
7376 (is_string_element
? IS_STR_ELEM
: NOT_STR_ELEM
));
7377 if (is_string_element
) {
7378 // The length of RHS value shall be 1.
7379 Value
*v_last
= val
->get_value_refd_last();
7380 switch (type
->get_type_refd_last()->get_typetype()) {
7382 case Type::T_BSTR_A
:
7383 if (v_last
->get_valuetype() != Value::V_BSTR
) v_last
= 0;
7386 if (v_last
->get_valuetype() != Value::V_HSTR
) v_last
= 0;
7389 if (v_last
->get_valuetype() != Value::V_OSTR
) v_last
= 0;
7392 case Type::T_NUMERICSTRING
:
7393 case Type::T_PRINTABLESTRING
:
7394 case Type::T_IA5STRING
:
7395 case Type::T_VISIBLESTRING
:
7396 case Type::T_UTCTIME
:
7397 case Type::T_GENERALIZEDTIME
:
7398 if (v_last
->get_valuetype() != Value::V_CSTR
) v_last
= 0;
7401 case Type::T_UTF8STRING
:
7402 case Type::T_TELETEXSTRING
:
7403 case Type::T_VIDEOTEXSTRING
:
7404 case Type::T_GRAPHICSTRING
:
7405 case Type::T_GENERALSTRING
:
7406 case Type::T_UNIVERSALSTRING
:
7407 case Type::T_BMPSTRING
:
7408 case Type::T_OBJECTDESCRIPTOR
:
7409 if (v_last
->get_valuetype() != Value::V_USTR
) v_last
= 0;
7415 size_t string_len
= v_last
->get_val_strlen();
7416 if (string_len
!= 1) {
7417 val
->error("The length of the string to be assigned to a string "
7418 "element of type `%s' should be 1 instead of %lu",
7419 type
->get_typename().c_str(),
7420 (unsigned long)string_len
);
7430 asstype
= ASS_ERROR
;
7434 void Assignment::chk_template_ass()
7436 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7437 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7438 if (!lhs
) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7439 Type
*type
= lhs
->get_Type()->
7440 get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7441 if (!type
) goto error
;
7442 if (lhs
->get_asstype() != Common::Assignment::A_VAR_TEMPLATE
&&
7443 subrefs
&& subrefs
->refers_to_string_element()) {
7444 ref
->error("It is not allowed to index template strings");
7447 templ
->set_my_governor(type
);
7449 templ
->flatten(false);
7451 type
->chk_this_template_ref(templ
);
7452 self_ref
|= type
->chk_this_template_generic(templ
, INCOMPLETE_ALLOWED
,
7453 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, lhs
);
7454 chk_template_restriction();
7459 asstype
= ASS_ERROR
;
7463 void Assignment::chk()
7478 FATAL_ERROR("Ttcn::Assignment::chk()");
7482 void Assignment::set_code_section(
7483 GovernedSimple::code_section_t p_code_section
)
7487 ref
->set_code_section(p_code_section
);
7488 val
->set_code_section(p_code_section
);
7491 ref
->set_code_section(p_code_section
);
7492 templ
->set_code_section(p_code_section
);
7498 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7502 void Assignment::chk_template_restriction()
7504 if (asstype
!=ASS_TEMPLATE
)
7505 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7506 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7507 if (!t_ass
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7508 switch (t_ass
->get_asstype()) {
7509 case Common::Assignment::A_VAR_TEMPLATE
: {
7510 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(t_ass
);
7511 if (!dvt
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7512 template_restriction
= dvt
->get_template_restriction();
7514 case Common::Assignment::A_PAR_TEMPL_IN
:
7515 case Common::Assignment::A_PAR_TEMPL_OUT
:
7516 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
7517 FormalPar
* fp
= dynamic_cast<FormalPar
*>(t_ass
);
7518 if (!fp
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7519 template_restriction
= fp
->get_template_restriction();
7522 template_restriction
= TR_NONE
;
7524 // transform the restriction if this is a subfield
7525 template_restriction
= Template::get_sub_restriction(template_restriction
, ref
);
7526 // check the template restriction
7527 gen_restriction_check
=
7528 templ
->chk_restriction("template", template_restriction
);
7531 char *Assignment::generate_code(char *str
)
7533 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
7534 const bool rhs_copied
= self_ref
;
7537 const string
& rhs_copy
= val
->get_temporary_id();
7538 string rhs_ref
= rhs_copy
;
7539 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7540 if (val
->get_my_governor()->is_optional_field()) {
7541 str
= mputprintf(str
, "{\nOPTIONAL<%s> %s;\n",
7542 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7545 str
= mputprintf(str
, "{\n%s %s;\n",
7546 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7549 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(val
);
7552 // Most complicated case. The LHS is saved in a temporary reference,
7553 // in case we need to access it more than once, e.g:
7554 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7555 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7556 // This saves having to index x2 more than once.
7557 const string
& tmp_id
= val
->get_temporary_id(); // For "ref".
7558 const char *tmp_id_str
= tmp_id
.c_str();
7559 const string
& type_genname
=
7560 val
->get_my_governor()->get_genname_value(val
->get_my_scope());
7561 const char *type_genname_str
= type_genname
.c_str();
7562 expression_struct expr
;
7563 Code::init_expr(&expr
);
7564 ref
->generate_code(&expr
);
7568 str
= TypeConv::gen_conv_code_refd(str
, rhs_ref
.c_str(), val
);
7569 else str
= val
->generate_code_init(str
, rhs_ref
.c_str());
7572 str
= mputstr(str
, "{\n");
7573 str
= mputstr(str
, expr
.preamble
);
7574 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
7575 // The LHS is a string element.
7576 str
= mputprintf(str
, "%s_ELEMENT %s(%s);\n", type_genname_str
,
7577 tmp_id_str
, expr
.expr
);
7579 // The LHS is a normal value.
7580 str
= mputprintf(str
, "%s& %s = %s; /* 7388 */\n", type_genname_str
,
7581 tmp_id_str
, expr
.expr
);
7583 str
= mputstr(str
, expr
.postamble
);
7584 // We now have a reference to the LHS. Generate the actual assignment
7586 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7590 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, val
);
7591 else str
= val
->generate_code_init(str
, tmp_id_str
);
7593 Code::free_expr(&expr
);
7594 str
= mputstr(str
, "}\n");
7598 if (!val
->has_single_expr()) goto case3
;
7599 // C++ equivalent of RHS is a single expression.
7600 expression_struct expr
;
7601 Code::init_expr(&expr
);
7602 ref
->generate_code(&expr
);// vu.s()
7604 str
= mputprintf(str
, "%s = %s;\n",
7605 rhs_copy
.c_str(), val
->get_single_expr().c_str());
7607 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7610 expr
.expr
= mputprintf(expr
.expr
,
7611 " = %s", val
->get_single_expr().c_str());
7613 str
= Code::merge_free_expr(str
, &expr
);
7616 // The LHS is a single identifier.
7617 const string
& rhs_name
= ref
->get_refd_assignment()
7618 ->get_genname_from_scope(ref
->get_my_scope());
7619 if (val
->can_use_increment(ref
)) {
7620 switch (val
->get_optype()) {
7621 case Value::OPTYPE_ADD
:
7622 str
= mputprintf(str
, "++%s;\n", rhs_name
.c_str());
7624 case Value::OPTYPE_SUBTRACT
:
7625 str
= mputprintf(str
, "--%s;\n", rhs_name
.c_str());
7628 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7631 str
= val
->generate_code_init(str
,
7632 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7635 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7641 str
= mputstr(str
, "}\n");
7644 case ASS_TEMPLATE
: {
7645 const string
& rhs_copy
= templ
->get_temporary_id();
7646 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7647 str
= mputprintf(str
, "{\n%s %s;\n",
7648 templ
->get_my_governor()->get_genname_template(templ
->get_my_scope()).c_str(), rhs_copy
.c_str()//, rhs_copy.c_str()
7651 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(templ
);
7652 if (needs_conv
) { // case 3
7654 // Most complicated case. The LHS is saved in a temporary reference.
7655 const string
& tmp_id
= templ
->get_temporary_id();
7656 const char *tmp_id_str
= tmp_id
.c_str();
7657 expression_struct expr
;
7658 Code::init_expr(&expr
);
7659 ref
->generate_code(&expr
);
7663 str
= TypeConv::gen_conv_code_refd(str
, rhs_copy
.c_str(), templ
);
7664 else str
= templ
->generate_code_init(str
, rhs_copy
.c_str());
7667 str
= mputstr(str
, "{\n");
7668 str
= mputstr(str
, expr
.preamble
);
7669 str
= mputprintf(str
, "%s& %s = %s;\n",
7670 templ
->get_my_governor()->get_genname_template(
7671 templ
->get_my_scope()
7672 ).c_str(), tmp_id_str
, expr
.expr
);
7673 str
= mputstr(str
, expr
.postamble
);
7675 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7679 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, templ
);
7681 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7682 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7683 str
= mputprintf(str
, "%s.remove_all_permutations();\n", tmp_id_str
);
7685 str
= templ
->generate_code_init(str
, tmp_id_str
);
7688 Code::free_expr(&expr
);
7690 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7691 str
= Template::generate_restriction_check_code(str
,
7692 tmp_id_str
, template_restriction
);
7693 str
= mputstr(str
, "}\n");
7695 else { // !needs_conv
7697 if ((template_restriction
== TR_NONE
|| !gen_restriction_check
)
7698 && templ
->has_single_expr()) {
7699 // C++ equivalent of RHS is a single expression and no restriction
7700 // check. Skipped if conversion needed.
7701 expression_struct expr
;
7702 Code::init_expr(&expr
);
7703 ref
->generate_code(&expr
);
7705 str
= mputprintf(str
, "%s = %s;\n",
7706 rhs_copy
.c_str(), templ
->get_single_expr(false).c_str());
7708 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7711 expr
.expr
= mputprintf(expr
.expr
,
7712 " = %s", templ
->get_single_expr(false).c_str());
7714 str
= Code::merge_free_expr(str
, &expr
); // will add a semicolon
7719 // LHS is a single identifier
7720 const string
& rhs_name
= ref
->get_refd_assignment()
7721 ->get_genname_from_scope(ref
->get_my_scope());
7722 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7723 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7724 str
= mputprintf(str
, "%s.remove_all_permutations();\n", (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7726 str
= templ
->generate_code_init(str
,
7727 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7729 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7731 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7732 str
= Template::generate_restriction_check_code(str
,
7733 ref
->get_refd_assignment()->get_genname_from_scope(
7735 ).c_str(), template_restriction
);
7739 str
= mputstr(str
, "}\n");
7743 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7748 // =================================
7749 // ===== ParamAssignment
7750 // =================================
7752 ParamAssignment::ParamAssignment(Identifier
*p_id
, Reference
*p_ref
)
7753 : Node(), Location(), id(p_id
), ref(p_ref
)
7755 if(!id
|| !ref
) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7758 ParamAssignment::~ParamAssignment()
7764 ParamAssignment
*ParamAssignment::clone() const
7766 FATAL_ERROR("ParamAssignment::clone");
7769 void ParamAssignment::set_my_scope(Scope
*p_scope
)
7771 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7772 ref
->set_my_scope(p_scope
);
7775 void ParamAssignment::set_fullname(const string
& p_fullname
)
7777 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7778 ref
->set_fullname(p_fullname
);
7781 Reference
*ParamAssignment::get_ref() const
7783 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7787 Reference
*ParamAssignment::steal_ref()
7789 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7790 Reference
*ret_val
= ref
;
7795 // =================================
7796 // ===== ParamAssignments
7797 // =================================
7799 ParamAssignments::~ParamAssignments()
7801 for(size_t i
=0; i
<parasss
.size(); i
++)
7806 ParamAssignments
*ParamAssignments::clone() const
7808 FATAL_ERROR("ParamAssignments::clone");
7811 void ParamAssignments::set_my_scope(Scope
*p_scope
)
7813 for(size_t i
=0; i
<parasss
.size(); i
++)
7814 parasss
[i
]->set_my_scope(p_scope
);
7817 void ParamAssignments::set_fullname(const string
& p_fullname
)
7819 Node::set_fullname(p_fullname
);
7820 for(size_t i
=0; i
<parasss
.size(); i
++)
7821 parasss
[i
]->set_fullname(p_fullname
+".parass_"+Int2string(i
+1));
7824 void ParamAssignments::add_parass(ParamAssignment
*p_parass
)
7827 FATAL_ERROR("ParamAssignments::add_parass()");
7828 parasss
.add(p_parass
);
7831 // =================================
7832 // ===== VariableEntry
7833 // =================================
7835 VariableEntry::VariableEntry(Reference
*p_ref
)
7836 : Node(), Location(), ref(p_ref
)
7838 if(!ref
) FATAL_ERROR("VariableEntry::VariableEntry()");
7841 VariableEntry::~VariableEntry()
7846 VariableEntry
*VariableEntry::clone() const
7848 FATAL_ERROR("VariableEntry::clone");
7851 void VariableEntry::set_my_scope(Scope
*p_scope
)
7853 if(ref
) ref
->set_my_scope(p_scope
);
7856 void VariableEntry::set_fullname(const string
& p_fullname
)
7858 Node::set_fullname(p_fullname
);
7859 if(ref
) ref
->set_fullname(p_fullname
+".ref");
7862 // =================================
7863 // ===== VariableEntries
7864 // =================================
7866 VariableEntries::~VariableEntries()
7868 for(size_t i
=0; i
<ves
.size(); i
++)
7873 VariableEntries
*VariableEntries::clone() const
7875 FATAL_ERROR("VariableEntries::clone");
7878 void VariableEntries::set_my_scope(Scope
*p_scope
)
7880 for(size_t i
=0; i
<ves
.size(); i
++)
7881 ves
[i
]->set_my_scope(p_scope
);
7884 void VariableEntries::set_fullname(const string
& p_fullname
)
7886 Node::set_fullname(p_fullname
);
7887 for(size_t i
=0; i
<ves
.size(); i
++)
7888 ves
[i
]->set_fullname(p_fullname
+".ve_"+Int2string(i
+1));
7891 void VariableEntries::add_ve(VariableEntry
*p_ve
)
7894 FATAL_ERROR("VariableEntries::add_ve()");
7898 // =================================
7899 // ===== ParamRedirect
7900 // =================================
7902 ParamRedirect::ParamRedirect(ParamAssignments
*p_parasss
)
7903 : Node(), Location(), parredirtype(P_ASS
), parasss(p_parasss
)
7905 if(!parasss
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
7908 ParamRedirect::ParamRedirect(VariableEntries
*p_ves
)
7909 : Node(), Location(), parredirtype(P_VAR
), ves(p_ves
)
7911 if(!ves
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
7914 ParamRedirect::~ParamRedirect()
7916 switch(parredirtype
) {
7924 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
7928 ParamRedirect
*ParamRedirect::clone() const
7930 FATAL_ERROR("ParamRedirect::clone");
7933 void ParamRedirect::set_my_scope(Scope
*p_scope
)
7935 switch(parredirtype
) {
7937 parasss
->set_my_scope(p_scope
);
7940 ves
->set_my_scope(p_scope
);
7943 FATAL_ERROR("ParamRedirect::set_my_scope()");
7947 void ParamRedirect::set_fullname(const string
& p_fullname
)
7949 Node::set_fullname(p_fullname
);
7950 switch(parredirtype
) {
7952 parasss
->set_fullname(p_fullname
+".parasss");
7955 ves
->set_fullname(p_fullname
+".parvars");
7958 FATAL_ERROR("ParamRedirect::set_fullname()");
7962 void ParamRedirect::chk_erroneous()
7964 Error_Context
cntxt(this, "In parameter redirect");
7965 switch(parredirtype
) {
7967 map
<string
, ParamAssignment
> parass_m
;
7968 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
7969 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
7970 const Identifier
&t_id
= t_parass
->get_id();
7971 const string
& name
= t_id
.get_name();
7972 const char *dispname_str
= t_id
.get_dispname().c_str();
7973 if (parass_m
.has_key(name
)) {
7974 t_parass
->error("Duplicate redirect for parameter `%s'",
7976 parass_m
[name
]->note("A variable entry for parameter `%s' is "
7977 "already given here", dispname_str
);
7978 } else parass_m
.add(name
, t_parass
);
7979 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
7981 chk_variable_ref(t_parass
->get_ref(), 0);
7986 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
7987 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
7988 Error_Context
cntxt2(t_ve
, "In variable entry #%lu",
7989 (unsigned long) (i
+ 1));
7990 chk_variable_ref(t_ve
->get_ref(), 0);
7994 FATAL_ERROR("ParamRedirect::chk_erroneous()");
7998 void ParamRedirect::chk(Type
*p_sig
, bool is_out
)
8000 SignatureParamList
*t_parlist
= p_sig
->get_signature_parameters();
8002 Error_Context
cntxt(this, "In parameter redirect");
8003 switch (parredirtype
) {
8005 chk_parasss(p_sig
, t_parlist
, is_out
);
8008 chk_ves(p_sig
, t_parlist
, is_out
);
8011 FATAL_ERROR("ParamRedirect::chk()");
8014 error("Parameter redirect cannot be used because signature `%s' "
8015 "does not have parameters", p_sig
->get_typename().c_str());
8020 void ParamRedirect::chk_parasss(Type
*p_sig
, SignatureParamList
*p_parlist
,
8023 map
<string
, ParamAssignment
> parass_m
;
8024 bool error_flag
= false;
8025 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8026 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8027 const Identifier
&t_id
= t_parass
->get_id();
8028 const string
& name
= t_id
.get_name();
8029 const char *dispname_str
= t_id
.get_dispname().c_str();
8030 if (parass_m
.has_key(name
)) {
8031 t_parass
->error("Duplicate redirect for parameter `%s'",
8033 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8034 "already given here", dispname_str
);
8036 } else parass_m
.add(name
, t_parass
);
8037 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8039 if (p_parlist
->has_param_withName(t_id
)) {
8040 const SignatureParam
*t_par
= p_parlist
->get_param_byName(t_id
);
8041 SignatureParam::param_direction_t t_dir
= t_par
->get_direction();
8043 if (t_dir
== SignatureParam::PARAM_IN
) {
8044 t_parass
->error("Parameter `%s' of signature `%s' has `in' "
8045 "direction", dispname_str
, p_sig
->get_typename().c_str());
8049 if (t_dir
== SignatureParam::PARAM_OUT
) {
8050 t_parass
->error("Parameter `%s' of signature `%s' has `out' "
8051 "direction", dispname_str
, p_sig
->get_typename().c_str());
8055 chk_variable_ref(t_parass
->get_ref(), t_par
->get_type());
8057 t_parass
->error("Signature `%s' does not have parameter named `%s'",
8058 p_sig
->get_typename().c_str(), dispname_str
);
8060 chk_variable_ref(t_parass
->get_ref(), 0);
8064 // converting the AssignmentList to VariableList
8065 VariableEntries
*t_ves
= new VariableEntries
;
8066 size_t upper_limit
= is_out
?
8067 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8068 for (size_t i
= 0; i
< upper_limit
; i
++) {
8069 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8070 : p_parlist
->get_in_param_byIndex(i
);
8071 const string
& name
= t_par
->get_id().get_name();
8072 if (parass_m
.has_key(name
))
8073 t_ves
->add_ve(new VariableEntry(parass_m
[name
]->steal_ref()));
8074 else t_ves
->add_ve(new VariableEntry
);
8078 parredirtype
= P_VAR
;
8083 void ParamRedirect::chk_ves(Type
*p_sig
, SignatureParamList
*p_parlist
,
8086 size_t nof_ves
= ves
->get_nof_ves();
8087 size_t nof_pars
= is_out
?
8088 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8089 if (nof_ves
!= nof_pars
) {
8090 error("Too %s variable entries compared to the number of %s/inout "
8091 "parameters in signature `%s': %lu was expected instead of %lu",
8092 nof_ves
> nof_pars
? "many" : "few", is_out
? "out" : "in",
8093 p_sig
->get_typename().c_str(), (unsigned long) nof_pars
,
8094 (unsigned long) nof_ves
);
8096 for (size_t i
= 0; i
< nof_ves
; i
++) {
8097 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8099 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8100 : p_parlist
->get_in_param_byIndex(i
);
8101 Error_Context
cntxt(t_ve
, "In variable entry #%lu (for parameter `%s')",
8102 (unsigned long) (i
+ 1), t_par
->get_id().get_dispname().c_str());
8103 chk_variable_ref(t_ve
->get_ref(), t_par
->get_type());
8105 Error_Context
cntxt(t_ve
, "In variable entry #%lu",
8106 (unsigned long) (i
+ 1));
8107 chk_variable_ref(t_ve
->get_ref(), 0);
8112 void ParamRedirect::chk_variable_ref(Reference
*p_ref
, Type
*p_type
)
8115 Type
*t_var_type
= p_ref
->chk_variable_ref();
8116 if (p_type
&& t_var_type
&& !p_type
->is_identical(t_var_type
)) {
8117 p_ref
->error("Type mismatch in parameter redirect: "
8118 "A variable of type `%s' was expected instead of `%s'",
8119 p_type
->get_typename().c_str(),
8120 t_var_type
->get_typename().c_str());
8124 void ParamRedirect::set_code_section(
8125 GovernedSimple::code_section_t p_code_section
)
8127 // code can be generated from VariableList only
8128 switch (parredirtype
) {
8132 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8133 Reference
*t_ref
= ves
->get_ve_byIndex(i
)->get_ref();
8134 if (t_ref
) t_ref
->set_code_section(p_code_section
);
8138 FATAL_ERROR("ParamRedirect::set_code_section()");
8142 void ParamRedirect::generate_code(expression_struct_t
*expr
)
8144 // AssignmentList is converted to VariableList during checking
8145 if (parredirtype
!= P_VAR
) FATAL_ERROR("ParamRedirect::generate_code()");
8146 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8147 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
8148 Reference
*ref
= ves
->get_ve_byIndex(i
)->get_ref();
8150 // the variable reference is present
8151 expr
->expr
= mputstr(expr
->expr
, "&(");
8152 ref
->generate_code(expr
);
8153 expr
->expr
= mputc(expr
->expr
, ')');
8154 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
8158 // =================================
8159 // ===== LogArgument
8160 // =================================
8162 LogArgument::LogArgument(TemplateInstance
*p_ti
)
8163 : logargtype(L_UNDEF
)
8165 if (!p_ti
) FATAL_ERROR("LogArgument::LogArgument()");
8169 LogArgument::~LogArgument()
8171 switch (logargtype
) {
8190 FATAL_ERROR("LogArgument::~LogArgument()");
8194 LogArgument
*LogArgument::clone() const
8196 FATAL_ERROR("LogArgument::clone");
8199 void LogArgument::set_my_scope(Scope
*p_scope
)
8201 switch (logargtype
) {
8206 ti
->set_my_scope(p_scope
);
8211 val
->set_my_scope(p_scope
);
8214 ref
->set_my_scope(p_scope
);
8219 FATAL_ERROR("LogArgument::set_my_scope()");
8223 void LogArgument::set_fullname(const string
& p_fullname
)
8225 Node::set_fullname(p_fullname
);
8226 switch (logargtype
) {
8231 ti
->set_fullname(p_fullname
);
8236 val
->set_fullname(p_fullname
);
8239 ref
->set_fullname(p_fullname
);
8244 FATAL_ERROR("LogArgument::set_fullname()");
8248 const string
& LogArgument::get_str() const
8250 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::get_str()");
8254 Value
*LogArgument::get_val() const
8256 switch (logargtype
) {
8262 FATAL_ERROR("LogArgument::get_val()");
8267 Ref_base
*LogArgument::get_ref() const
8269 if (logargtype
!= L_REF
) FATAL_ERROR("LogArgument::get_ref()");
8273 TemplateInstance
*LogArgument::get_ti() const
8275 if (logargtype
!= L_TI
) FATAL_ERROR("LogArgument::get_ref()");
8279 void LogArgument::append_str(const string
& p_str
)
8281 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::append_str()");
8285 void LogArgument::chk() // determine the proper type of the log argument
8287 if (logargtype
!= L_UNDEF
) return;
8288 Template
*t_templ
= ti
->get_Template();
8289 t_templ
= t_templ
->get_template_refd_last();
8290 t_templ
->set_lowerid_to_ref();
8291 if (!ti
->get_Type() && !ti
->get_DerivedRef() && t_templ
->is_Value()) {
8292 // drop the template instance and keep only the embedded value
8293 Value
*t_val
= t_templ
->get_Value();
8299 // try to obtain the governor of the template instance
8300 Type
*governor
= ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8302 // the governor is still unknown: an error occurred
8303 // try to interpret possible enum values as references
8304 t_templ
->set_lowerid_to_ref();
8305 governor
= t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8311 t_templ
->error("Cannot determine the type of the argument");
8313 logargtype
= L_ERROR
;
8318 void LogArgument::chk_ref()
8320 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
8322 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
8324 case Common::Assignment::A_FUNCTION_RVAL
:
8325 case Common::Assignment::A_FUNCTION_RTEMP
:
8326 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
8327 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
8328 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *this, "call");
8329 case Common::Assignment::A_CONST
:
8330 case Common::Assignment::A_EXT_CONST
:
8331 case Common::Assignment::A_MODULEPAR
:
8332 case Common::Assignment::A_MODULEPAR_TEMP
:
8333 case Common::Assignment::A_TEMPLATE
:
8334 case Common::Assignment::A_VAR
:
8335 case Common::Assignment::A_VAR_TEMPLATE
:
8336 case Common::Assignment::A_PAR_VAL_IN
:
8337 case Common::Assignment::A_PAR_VAL_OUT
:
8338 case Common::Assignment::A_PAR_VAL_INOUT
:
8339 case Common::Assignment::A_PAR_TEMPL_IN
:
8340 case Common::Assignment::A_PAR_TEMPL_OUT
:
8341 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
8342 // the reference points to a value or template-like entity
8343 // checking sub-references
8344 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
8345 if (subrefs
&& t_ass
->get_Type()->get_field_type(subrefs
,
8346 Type::EXPECTED_DYNAMIC_VALUE
)) {
8347 // subrefs seems to be correct
8348 // also checking the presence of referred fields if possible
8349 if (asstype
== Common::Assignment::A_CONST
) {
8350 ReferenceChain
refch(ref
, "While searching referenced value");
8351 t_ass
->get_Value()->get_refd_sub_value(subrefs
, 0, false, &refch
);
8352 } else if (asstype
== Common::Assignment::A_TEMPLATE
) {
8353 ReferenceChain
refch(ref
, "While searching referenced template");
8354 t_ass
->get_Template()
8355 ->get_refd_sub_template(subrefs
, false, &refch
);
8359 case Common::Assignment::A_TIMER
:
8360 case Common::Assignment::A_PORT
: {
8361 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
8362 if (t_dims
) t_dims
->chk_indices(ref
, t_ass
->get_assname(), true,
8363 Type::EXPECTED_DYNAMIC_VALUE
);
8364 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8365 "cannot have field or array sub-references",
8366 t_ass
->get_description().c_str());
8368 case Common::Assignment::A_PAR_TIMER
:
8369 case Common::Assignment::A_PAR_PORT
:
8370 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8371 "field or array sub-references", t_ass
->get_description().c_str());
8373 case Common::Assignment::A_FUNCTION
:
8374 case Common::Assignment::A_EXT_FUNCTION
:
8375 ref
->error("Reference to a value, template, timer or port was expected "
8376 "instead of a call of %s, which does not have return type",
8377 t_ass
->get_description().c_str());
8380 ref
->error("Reference to a value, template, timer or port was expected "
8381 "instead of %s", t_ass
->get_description().c_str());
8385 void LogArgument::chk_val()
8387 // literal enumerated values cannot appear in this context
8388 val
->set_lowerid_to_ref();
8389 switch (val
->get_valuetype()) {
8390 case Value::V_CSTR
: {
8391 string
*t_cstr
= new string(val
->get_val_str());
8396 case Value::V_REFD
: {
8397 Ref_base
*t_ref
= val
->steal_ttcn_ref_base();
8404 if (val
->get_optype() == Value::OPTYPE_MATCH
) logargtype
= L_MATCH
;
8405 else logargtype
= L_VAL
;
8407 case Value::V_MACRO
:
8408 logargtype
= L_MACRO
;
8413 Type
*governor
= val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
8415 val
->set_my_governor(governor
);
8416 (void)governor
->chk_this_value(val
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
8417 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
8418 if (logargtype
== L_VAL
&& val
->get_valuetype() == Value::V_CSTR
8419 && !val
->is_unfoldable()) { // string value known at compile time
8420 string
*t_cstr
= new string(val
->get_val_str());
8426 if (logargtype
== L_MACRO
) {
8427 switch (val
->get_valuetype()) {
8428 case Value::V_CSTR
: {
8429 // the macro was evaluated to a charstring value
8430 string
*t_cstr
= new string(val
->get_val_str());
8435 case Value::V_MACRO
:
8436 // the macro could not be evaluated at compile time
8437 // leave logargtype as is
8440 // the macro was evaluated to other value (e.g. integer)
8445 val
->error("Cannot determine the type of the argument");
8447 logargtype
= L_ERROR
;
8451 void LogArgument::dump(unsigned int level
) const
8453 Node::dump(level
++);
8454 switch (logargtype
) {
8456 DEBUG(level
, "*error*");
8459 DEBUG(level
, "*undef*");
8462 DEBUG(level
, "TemplateInstance");
8468 DEBUG(level
, "Match");
8471 DEBUG(level
, "Macro");
8474 DEBUG(level
, "Reference");
8477 DEBUG(level
, "String=`%s'", cstr
->c_str());
8480 FATAL_ERROR("LogArgument::~LogArgument()");
8484 void LogArgument::set_code_section(
8485 GovernedSimple::code_section_t p_code_section
)
8487 switch (logargtype
) {
8490 ti
->set_code_section(p_code_section
);
8495 val
->set_code_section(p_code_section
);
8498 ref
->set_code_section(p_code_section
);
8504 FATAL_ERROR("LogArgument::set_code_section()");
8508 char *LogArgument::generate_code_log(char *str
)
8510 expression_struct expr
;
8511 Code::init_expr(&expr
);
8512 generate_code_expr(&expr
);
8513 str
= Code::merge_free_expr(str
, &expr
);
8517 void LogArgument::chk_recursions(ReferenceChain
& refch
)
8519 switch (logargtype
) {
8522 ti
->chk_recursions(refch
);
8527 val
->chk_recursions(refch
);
8530 Common::Assignment
*ass
= ref
->get_refd_assignment();
8532 refch
.add(ass
->get_fullname());
8538 FATAL_ERROR("LogArgument::chk_recursions()");
8542 bool LogArgument::has_single_expr()
8544 switch (logargtype
) {
8547 return ti
->has_single_expr();
8551 return ( val
->has_single_expr() && !val
->explicit_cast_needed() );
8553 Common::Assignment
*ass
= ref
->get_refd_assignment();
8554 switch (ass
->get_asstype()) {
8555 case Common::Assignment::A_CONST
:
8556 case Common::Assignment::A_EXT_CONST
:
8557 return ref
->has_single_expr();
8566 FATAL_ERROR("LogArgument::has_single_expr()");
8571 void LogArgument::generate_code_expr(expression_struct
*expr
)
8573 switch(logargtype
) {
8575 if (ti
->is_only_specific_value()) {
8576 // use the embedded specific value for code generation
8577 ti
->get_Template()->get_specific_value()->generate_code_log(expr
);
8579 ti
->generate_code(expr
);
8580 expr
->expr
= mputstr(expr
->expr
, ".log()");
8584 val
->generate_code_log(expr
);
8587 val
->generate_code_log_match(expr
);
8590 if (val
->has_single_expr()) {
8591 expr
->expr
= mputprintf(expr
->expr
, "TTCN_Logger::log_event_str(%s)",
8592 val
->get_single_expr().c_str());
8593 } else val
->generate_code_log(expr
);
8596 ref
->generate_code_const_ref(expr
);
8597 expr
->expr
=mputstr(expr
->expr
, ".log()");
8600 size_t str_len
= cstr
->size();
8601 const char *str_ptr
= cstr
->c_str();
8604 // the string is empty: do not generate any code
8606 // the string has one character: use log_char member
8607 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_char('");
8608 expr
->expr
= Code::translate_character(expr
->expr
, *str_ptr
, false);
8609 expr
->expr
= mputstr(expr
->expr
, "')");
8612 // the string has more characters: use log_event_str member
8613 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_event_str(\"");
8614 expr
->expr
= Code::translate_string(expr
->expr
, str_ptr
);
8615 expr
->expr
= mputstr(expr
->expr
, "\")");
8619 FATAL_ERROR("LogArgument::generate_code_expr()");
8623 // =================================
8624 // ===== LogArguments
8625 // =================================
8627 LogArguments::~LogArguments()
8629 for(size_t i
=0; i
<logargs
.size(); i
++) delete logargs
[i
];
8633 LogArguments
*LogArguments::clone() const
8635 FATAL_ERROR("LogArguments::clone");
8638 void LogArguments::add_logarg(LogArgument
*p_logarg
)
8641 FATAL_ERROR("LogArguments::add_logarg()");
8642 logargs
.add(p_logarg
);
8645 void LogArguments::set_my_scope(Scope
*p_scope
)
8647 for(size_t i
=0; i
<logargs
.size(); i
++)
8648 logargs
[i
]->set_my_scope(p_scope
);
8651 void LogArguments::set_fullname(const string
& p_fullname
)
8653 Node::set_fullname(p_fullname
);
8654 for(size_t i
=0; i
<logargs
.size(); i
++)
8655 logargs
[i
]->set_fullname(p_fullname
+".logargs_"+Int2string(i
+1));
8658 void LogArguments::chk()
8660 for(size_t i
=0; i
<logargs
.size(); i
++)
8664 void LogArguments::join_strings()
8666 // points to the previous string argument otherwise it is NULL
8667 LogArgument
*prev_arg
= 0;
8668 for (size_t i
= 0; i
< logargs
.size(); ) {
8669 LogArgument
*arg
= logargs
[i
];
8670 if (arg
->get_type() == LogArgument::L_STR
) {
8671 const string
& str
= arg
->get_str();
8672 if (str
.size() > 0) {
8673 // the current argument is a non-empty string
8675 // append str to prev_arg and drop arg
8676 prev_arg
->append_str(str
);
8678 logargs
.replace(i
, 1);
8679 // don't increment i
8681 // keep it for the next iteration
8686 // the current argument is an empty string
8687 // simply drop it unless it is the only argument
8688 // note: we must distinguish between log() and log("")
8689 if (i
> 0 || logargs
.size() > 1) {
8691 logargs
.replace(i
, 1);
8692 // don't increment i
8696 // the current argument is not a string
8697 // forget the previous arg
8704 void LogArguments::set_code_section(
8705 GovernedSimple::code_section_t p_code_section
)
8707 for (size_t i
= 0; i
< logargs
.size(); i
++)
8708 logargs
[i
]->set_code_section(p_code_section
);
8711 char *LogArguments::generate_code(char *str
)
8713 for(size_t i
=0; i
<logargs
.size(); i
++)
8714 str
=logargs
[i
]->generate_code_log(str
);
8718 void LogArguments::chk_recursions(ReferenceChain
& refch
)
8720 for (size_t i
=0; i
<logargs
.size(); i
++) {
8722 logargs
[i
]->chk_recursions(refch
);
8727 bool LogArguments::has_single_expr()
8729 bool i_have_single_expr
= true;
8730 for (size_t i
=0; i
<logargs
.size(); i
++)
8731 i_have_single_expr
= i_have_single_expr
&& logargs
[i
]->has_single_expr();
8732 return i_have_single_expr
;
8735 void LogArguments::generate_code_expr(expression_struct
*expr
)
8737 expr
->expr
= mputstr(expr
->expr
, "(TTCN_Logger::begin_event_log2str(),");
8738 for(size_t i
=0; i
<logargs
.size(); i
++) {
8739 logargs
[i
]->generate_code_expr(expr
);
8740 expr
->expr
= mputc(expr
->expr
, ','); // comma operator
8742 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::end_event_log2str())");
8745 // =================================
8747 // =================================
8749 IfClause::IfClause(Value
*p_expr
, StatementBlock
*p_block
)
8750 : expr(p_expr
), block(p_block
)
8753 FATAL_ERROR("IfClause::IfClause()");
8756 IfClause::~IfClause()
8762 IfClause
*IfClause::clone() const
8764 FATAL_ERROR("IfClause::clone");
8767 void IfClause::set_my_scope(Scope
*p_scope
)
8769 expr
->set_my_scope(p_scope
);
8770 block
->set_my_scope(p_scope
);
8773 void IfClause::set_fullname(const string
& p_fullname
)
8775 Node::set_fullname(p_fullname
);
8776 expr
->set_fullname(p_fullname
+".expr");
8777 block
->set_fullname(p_fullname
+".block");
8780 bool IfClause::has_receiving_stmt() const
8782 return block
->has_receiving_stmt();
8785 void IfClause::chk(bool& unreach
)
8787 Error_Context
cntxt(this, "In if statement");
8788 if(unreach
) warning("Control never reaches this code because of"
8789 " previous effective condition(s)");
8790 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
8791 if(!expr
->is_unfoldable()) {
8792 if(expr
->get_val_bool()) unreach
=true;
8793 else block
->warning("Control never reaches this code because the"
8794 " conditional expression evaluates to false");
8799 void IfClause::set_code_section(
8800 GovernedSimple::code_section_t p_code_section
)
8802 expr
->set_code_section(p_code_section
);
8803 block
->set_code_section(p_code_section
);
8806 char* IfClause::generate_code(char *str
, size_t& blockcount
,
8807 bool& unreach
, bool& eachfalse
)
8809 if(unreach
) return str
;
8810 if(!expr
->is_unfoldable()) {
8811 if(expr
->get_val_bool()) unreach
=true;
8814 if (!eachfalse
) str
= mputstr(str
, "else ");
8817 str
= mputstr(str
, "{\n");
8820 str
= expr
->update_location_object(str
);
8821 str
= expr
->generate_code_tmp(str
, "if (", blockcount
);
8822 str
= mputstr(str
, ") ");
8825 str
=mputstr(str
, "{\n");
8826 str
=block
->generate_code(str
);
8827 str
=mputstr(str
, "}\n");
8831 void IfClause::ilt_generate_code(ILT
*ilt
, const char *end_label
,
8835 if(!expr
->is_unfoldable()) {
8836 if(expr
->get_val_bool()) unreach
=true;
8839 char*& str
=ilt
->get_out_branches();
8842 size_t blockcount
=0;
8843 label
=mprintf("%s_l%lu",
8844 ilt
->get_my_tmpid().c_str(),
8845 (unsigned long) ilt
->get_new_label_num());
8846 str
=expr
->update_location_object(str
);
8847 str
=expr
->generate_code_tmp(str
, "if(!", blockcount
);
8848 str
=mputprintf(str
, ") goto %s;\n", label
);
8849 while(blockcount
-->0) str
=mputstr(str
, "}\n");
8851 block
->ilt_generate_code(ilt
);
8853 str
=mputprintf(str
, "goto %s;\n%s:\n",
8859 void IfClause::set_parent_path(WithAttribPath
* p_path
) {
8860 block
->set_parent_path(p_path
);
8863 void IfClause::dump(unsigned int level
) const {
8864 DEBUG(level
, "If clause!");
8865 expr
->dump(level
+ 1);
8866 block
->dump(level
+ 1);
8869 // =================================
8871 // =================================
8873 IfClauses::~IfClauses()
8875 for(size_t i
=0; i
<ics
.size(); i
++) delete ics
[i
];
8879 IfClauses
*IfClauses::clone() const
8881 FATAL_ERROR("IfClauses::clone");
8884 void IfClauses::add_ic(IfClause
*p_ic
)
8887 FATAL_ERROR("IfClauses::add_ic()");
8891 void IfClauses::add_front_ic(IfClause
*p_ic
)
8894 FATAL_ERROR("IfClauses::add_front_ic()");
8895 ics
.add_front(p_ic
);
8898 void IfClauses::set_my_scope(Scope
*p_scope
)
8900 for(size_t i
=0; i
<ics
.size(); i
++)
8901 ics
[i
]->set_my_scope(p_scope
);
8904 void IfClauses::set_fullname(const string
& p_fullname
)
8906 Node::set_fullname(p_fullname
);
8907 for(size_t i
=0; i
<ics
.size(); i
++)
8908 ics
[i
]->set_fullname(p_fullname
+".ic_"+Int2string(i
+1));
8911 void IfClauses::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
8913 for(size_t i
=0; i
<ics
.size(); i
++)
8914 ics
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
8917 void IfClauses::set_my_def(Definition
*p_def
)
8919 for(size_t i
=0; i
<ics
.size(); i
++)
8920 ics
[i
]->get_block()->set_my_def(p_def
);
8923 void IfClauses::set_my_ags(AltGuards
*p_ags
)
8925 for(size_t i
=0; i
<ics
.size(); i
++)
8926 ics
[i
]->get_block()->set_my_ags(p_ags
);
8929 void IfClauses::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
8931 for(size_t i
=0; i
<ics
.size(); i
++)
8932 ics
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
8935 StatementBlock::returnstatus_t
IfClauses::has_return
8936 (StatementBlock
*elseblock
) const
8938 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
8939 for (size_t i
= 0; i
< ics
.size(); i
++) {
8940 switch (ics
[i
]->get_block()->has_return()) {
8941 case StatementBlock::RS_NO
:
8942 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
8943 else ret_val
= StatementBlock::RS_NO
;
8945 case StatementBlock::RS_YES
:
8946 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
8947 else ret_val
= StatementBlock::RS_YES
;
8950 return StatementBlock::RS_MAYBE
;
8953 StatementBlock::returnstatus_t else_status
;
8954 if (elseblock
) else_status
= elseblock
->has_return();
8955 else else_status
= StatementBlock::RS_NO
;
8956 switch (else_status
) {
8957 case StatementBlock::RS_NO
:
8958 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
8959 else ret_val
= StatementBlock::RS_NO
;
8961 case StatementBlock::RS_YES
:
8962 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
8963 else ret_val
= StatementBlock::RS_YES
;
8966 return StatementBlock::RS_MAYBE
;
8971 bool IfClauses::has_receiving_stmt() const
8973 for(size_t i
=0; i
<ics
.size(); i
++)
8974 if(ics
[i
]->has_receiving_stmt()) return true;
8978 void IfClauses::chk(bool& unreach
)
8980 for(size_t i
=0; i
<ics
.size(); i
++)
8981 ics
[i
]->chk(unreach
);
8984 void IfClauses::chk_allowed_interleave()
8986 for (size_t i
= 0; i
< ics
.size(); i
++)
8987 ics
[i
]->get_block()->chk_allowed_interleave();
8990 void IfClauses::set_code_section(
8991 GovernedSimple::code_section_t p_code_section
)
8993 for (size_t i
= 0; i
< ics
.size(); i
++)
8994 ics
[i
]->set_code_section(p_code_section
);
8997 char* IfClauses::generate_code(char *str
, size_t& blockcount
,
8998 bool& unreach
, bool& eachfalse
)
9000 for(size_t i
=0; i
<ics
.size(); i
++) {
9001 if(unreach
) return str
;
9002 str
=ics
[i
]->generate_code(str
, blockcount
, unreach
, eachfalse
);
9007 void IfClauses::ilt_generate_code(ILT
*ilt
, const char *end_label
,
9010 for(size_t i
=0; i
<ics
.size(); i
++) {
9012 ics
[i
]->ilt_generate_code(ilt
, end_label
, unreach
);
9016 void IfClauses::set_parent_path(WithAttribPath
* p_path
) {
9017 for (size_t i
= 0; i
< ics
.size(); i
++)
9018 ics
[i
]->set_parent_path(p_path
);
9021 void IfClauses::dump(unsigned int level
) const {
9022 DEBUG(level
, "%lu if clauses", (unsigned long)ics
.size());
9023 for (size_t i
= 0; i
< ics
.size(); i
++)
9024 ics
[i
]->dump(level
+ 1);
9027 // =================================
9029 // =================================
9031 SelectCase::SelectCase(TemplateInstances
*p_tis
, StatementBlock
*p_block
)
9032 : tis(p_tis
), block(p_block
)
9035 FATAL_ERROR("SelectCase::SelectCase()");
9038 SelectCase::~SelectCase()
9044 SelectCase
*SelectCase::clone() const
9046 FATAL_ERROR("SelectCase::clone");
9049 void SelectCase::set_my_scope(Scope
*p_scope
)
9051 if(tis
) tis
->set_my_scope(p_scope
);
9052 block
->set_my_scope(p_scope
);
9055 void SelectCase::set_fullname(const string
& p_fullname
)
9057 Node::set_fullname(p_fullname
);
9058 if(tis
) tis
->set_fullname(p_fullname
+".tis");
9059 block
->set_fullname(p_fullname
+".block");
9063 void SelectCase::chk(Type
*p_gov
, bool& unreach
)
9065 Error_Context
cntxt(this, "In select case statement");
9066 if(unreach
) warning("Control never reaches this code because of"
9067 " previous effective case(s)");
9069 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++)
9070 tis
->get_ti_byIndex(i
)->chk(p_gov
);
9071 else unreach
=true; // else statement
9075 void SelectCase::set_code_section
9076 (GovernedSimple::code_section_t p_code_section
)
9078 if(tis
) tis
->set_code_section(p_code_section
);
9079 block
->set_code_section(p_code_section
);
9083 char* SelectCase::generate_code_if(char *str
, const char *tmp_prefix
,
9084 const char *expr_name
, size_t idx
,
9087 if(unreach
) return str
;
9089 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++) {
9090 TemplateInstance
*ti
=tis
->get_ti_byIndex(i
);
9091 Template
*tb
=ti
->get_Template();
9092 bool specval
= tb
->is_Value();
9093 expression_struct exprs
;
9094 Code::init_expr(&exprs
);
9095 if (!specval
) ti
->generate_code(&exprs
);
9096 else if (tb
->get_templatetype() == Template::SPECIFIC_VALUE
) {
9097 tb
->get_specific_value()->generate_code_expr_mandatory(&exprs
);
9100 Value
* val
= tb
->get_Value();
9101 val
->generate_code_expr_mandatory(&exprs
);
9104 str
=tb
->update_location_object(str
);
9105 if(!exprs
.preamble
&& !exprs
.postamble
) {
9106 str
=mputstr(str
, "if(");
9108 str
=mputprintf(str
, "%s.match(%s)", exprs
.expr
, expr_name
);
9109 else str
=mputprintf(str
, "%s == %s", expr_name
, exprs
.expr
);
9110 str
=mputprintf(str
, ") goto %s_%lu;\n", tmp_prefix
,
9111 (unsigned long) idx
);
9112 Code::free_expr(&exprs
);
9115 str
=mputprintf(str
, "{\nboolean %s_%lub;\n", tmp_prefix
,
9116 (unsigned long) idx
);
9118 exprs
.expr
=mprintf("%s_%lub = ", tmp_prefix
, (unsigned long) idx
);
9120 exprs
.expr
=mputprintf(exprs
.expr
, "%s.match(%s)", s
, expr_name
);
9121 else exprs
.expr
=mputprintf(exprs
.expr
, "(%s == %s)", expr_name
, s
);
9123 str
=Code::merge_free_expr(str
, &exprs
);
9124 str
=mputprintf(str
, "if(%s_%lub) goto %s_%lu;\n}\n",
9125 tmp_prefix
, (unsigned long) idx
, tmp_prefix
, (unsigned long) idx
);
9130 unreach
=true; // else statement
9131 str
=mputprintf(str
, "goto %s_%lu;\n", tmp_prefix
, (unsigned long) idx
);
9137 char* SelectCase::generate_code_stmt(char *str
, const char *tmp_prefix
,
9138 size_t idx
, bool& unreach
)
9140 if(unreach
) return str
;
9141 if(!tis
) unreach
=true;
9142 str
=mputprintf(str
, "%s_%lu:\n{\n", tmp_prefix
, (unsigned long) idx
);
9143 str
=block
->generate_code(str
);
9144 str
=mputprintf(str
, "goto %s_end;\n}\n", tmp_prefix
);
9148 void SelectCase::ilt_generate_code_stmt(ILT
*ilt
, const char *tmp_prefix
,
9149 size_t idx
, bool& unreach
)
9152 if(!tis
) unreach
=true;
9153 char*& str
=ilt
->get_out_branches();
9154 str
=mputprintf(str
, "%s_%lu:\n", tmp_prefix
, (unsigned long) idx
);
9155 bool has_recv
=block
->has_receiving_stmt();
9157 str
=mputstr(str
, "{\n");
9158 str
=block
->generate_code(str
);
9160 else block
->ilt_generate_code(ilt
);
9161 str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9163 str
=mputstr(str
, "}\n");
9166 void SelectCase::set_parent_path(WithAttribPath
* p_path
) {
9167 block
->set_parent_path(p_path
);
9170 // =================================
9171 // ===== SelectCases
9172 // =================================
9174 SelectCases::~SelectCases()
9176 for(size_t i
=0; i
<scs
.size(); i
++) delete scs
[i
];
9180 SelectCases
*SelectCases::clone() const
9182 FATAL_ERROR("SelectCases::clone");
9185 void SelectCases::add_sc(SelectCase
*p_sc
)
9188 FATAL_ERROR("SelectCases::add_sc()");
9192 void SelectCases::set_my_scope(Scope
*p_scope
)
9194 for(size_t i
=0; i
<scs
.size(); i
++)
9195 scs
[i
]->set_my_scope(p_scope
);
9198 void SelectCases::set_fullname(const string
& p_fullname
)
9200 Node::set_fullname(p_fullname
);
9201 for(size_t i
=0; i
<scs
.size(); i
++)
9202 scs
[i
]->set_fullname(p_fullname
+".sc_"+Int2string(i
+1));
9205 void SelectCases::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9207 for(size_t i
=0; i
<scs
.size(); i
++)
9208 scs
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9211 void SelectCases::set_my_def(Definition
*p_def
)
9213 for(size_t i
=0; i
<scs
.size(); i
++)
9214 scs
[i
]->get_block()->set_my_def(p_def
);
9217 void SelectCases::set_my_ags(AltGuards
*p_ags
)
9219 for(size_t i
=0; i
<scs
.size(); i
++)
9220 scs
[i
]->get_block()->set_my_ags(p_ags
);
9223 void SelectCases::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9225 for(size_t i
=0; i
<scs
.size(); i
++)
9226 scs
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9229 StatementBlock::returnstatus_t
SelectCases::has_return() const
9231 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9232 bool has_else
= false;
9233 for (size_t i
= 0; i
< scs
.size(); i
++) {
9234 SelectCase
*sc
= scs
[i
];
9235 switch (sc
->get_block()->has_return()) {
9236 case StatementBlock::RS_NO
:
9237 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9238 else ret_val
= StatementBlock::RS_NO
;
9240 case StatementBlock::RS_YES
:
9241 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9242 else ret_val
= StatementBlock::RS_YES
;
9245 return StatementBlock::RS_MAYBE
;
9247 if (!sc
->get_tis()) {
9252 if (!has_else
&& ret_val
== StatementBlock::RS_YES
)
9253 return StatementBlock::RS_MAYBE
;
9254 else return ret_val
;
9257 bool SelectCases::has_receiving_stmt() const
9259 for(size_t i
=0; i
<scs
.size(); i
++)
9260 if(scs
[i
]->get_block()->has_receiving_stmt()) return true;
9265 void SelectCases::chk(Type
*p_gov
)
9268 for(size_t i
=0; i
<scs
.size(); i
++)
9269 scs
[i
]->chk(p_gov
, unreach
);
9272 void SelectCases::chk_allowed_interleave()
9274 for (size_t i
= 0; i
< scs
.size(); i
++)
9275 scs
[i
]->get_block()->chk_allowed_interleave();
9278 void SelectCases::set_code_section
9279 (GovernedSimple::code_section_t p_code_section
)
9281 for(size_t i
=0; i
<scs
.size(); i
++)
9282 scs
[i
]->set_code_section(p_code_section
);
9285 char* SelectCases::generate_code(char *str
, const char *tmp_prefix
,
9286 const char *expr_name
)
9289 for(size_t i
=0; i
<scs
.size(); i
++) {
9290 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9293 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9295 for(size_t i
=0; i
<scs
.size(); i
++) {
9296 str
=scs
[i
]->generate_code_stmt(str
, tmp_prefix
, i
, unreach
);
9299 str
=mputprintf(str
, "%s_end: /* empty */;\n", tmp_prefix
);
9303 void SelectCases::ilt_generate_code(ILT
*ilt
, const char *tmp_prefix
,
9304 const char *expr_init
,
9305 const char *expr_name
)
9307 char*& str
=ilt
->get_out_branches();
9308 if(strlen(expr_init
)) {
9309 str
=mputstr(str
, "{\n"); // (1)
9310 str
=mputstr(str
, expr_init
);
9313 for(size_t i
=0; i
<scs
.size(); i
++) {
9315 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9317 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9318 if(strlen(expr_init
)) str
=mputstr(str
, "}\n"); // (1)
9320 for(size_t i
=0; i
<scs
.size(); i
++) {
9322 scs
[i
]->ilt_generate_code_stmt(ilt
, tmp_prefix
, i
, unreach
);
9324 str
=mputprintf(str
, "%s_end:\n", tmp_prefix
);
9327 void SelectCases::set_parent_path(WithAttribPath
* p_path
) {
9328 for (size_t i
= 0; i
< scs
.size(); i
++)
9329 scs
[i
]->set_parent_path(p_path
);
9332 // =================================
9334 // =================================
9336 AltGuard::AltGuard(Value
*p_expr
, Statement
*p_stmt
, StatementBlock
*p_block
)
9337 : altguardtype(AG_OP
), expr(p_expr
), stmt(p_stmt
), block(p_block
)
9339 if (!p_stmt
|| !p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9342 AltGuard::AltGuard(Value
*p_expr
, Ref_pard
*p_ref
, StatementBlock
*p_block
)
9343 : altguardtype(AG_REF
), expr(p_expr
), ref(p_ref
), block(p_block
)
9345 if (!p_ref
) FATAL_ERROR("AltGuard::AltGuard()");
9348 AltGuard::AltGuard(Value
*p_expr
, Value
*p_v
,
9349 Ttcn::TemplateInstances
*p_t_list
, StatementBlock
*p_block
)
9350 : altguardtype(AG_INVOKE
), expr(p_expr
)
9353 if(!p_v
|| !p_t_list
) FATAL_ERROR("AltGuard::AltGuard()");
9355 invoke
.t_list
= p_t_list
;
9359 AltGuard::AltGuard(StatementBlock
*p_block
)
9360 : altguardtype(AG_ELSE
), expr(0), dummy(0), block(p_block
)
9362 if (!p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9365 AltGuard::~AltGuard()
9367 switch(altguardtype
) {
9381 delete invoke
.t_list
;
9382 delete invoke
.ap_list
;
9389 FATAL_ERROR("AltGuard::~AltGuard()");
9393 AltGuard
*AltGuard::clone() const
9395 FATAL_ERROR("AltGuard::clone");
9398 void AltGuard::set_my_scope(Scope
*p_scope
)
9400 switch(altguardtype
) {
9402 if(expr
) expr
->set_my_scope(p_scope
);
9403 stmt
->set_my_scope(p_scope
);
9404 block
->set_my_scope(p_scope
);
9407 if(expr
) expr
->set_my_scope(p_scope
);
9408 ref
->set_my_scope(p_scope
);
9409 if(block
) block
->set_my_scope(p_scope
);
9412 if(expr
) expr
->set_my_scope(p_scope
);
9413 invoke
.v
->set_my_scope(p_scope
);
9414 if(invoke
.t_list
) invoke
.t_list
->set_my_scope(p_scope
);
9415 if(invoke
.ap_list
) invoke
.ap_list
->set_my_scope(p_scope
);
9416 if(block
) block
->set_my_scope(p_scope
);
9419 block
->set_my_scope(p_scope
);
9422 FATAL_ERROR("AltGuard::set_my_scope()");
9426 void AltGuard::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9428 switch(altguardtype
) {
9430 stmt
->set_my_sb(p_sb
, p_index
);
9431 block
->set_my_sb(p_sb
, p_index
);
9434 if(block
) block
->set_my_sb(p_sb
, p_index
);
9437 if(block
) block
->set_my_sb(p_sb
, p_index
);
9440 block
->set_my_sb(p_sb
, p_index
);
9443 FATAL_ERROR("AltGuard::set_my_sb()");
9447 void AltGuard::set_fullname(const string
& p_fullname
)
9449 Node::set_fullname(p_fullname
);
9450 switch(altguardtype
) {
9452 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9453 stmt
->set_fullname(p_fullname
+".stmt");
9454 block
->set_fullname(p_fullname
+".block");
9457 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9458 ref
->set_fullname(p_fullname
+".ref");
9459 if(block
) block
->set_fullname(p_fullname
+".block");
9462 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9463 invoke
.v
->set_fullname(p_fullname
+".function");
9464 if(invoke
.t_list
) invoke
.t_list
->set_fullname(p_fullname
+".argument");
9465 if(invoke
.ap_list
) invoke
.ap_list
->set_fullname(p_fullname
+".argument");
9466 if(block
) block
->set_fullname(p_fullname
+".block");
9469 block
->set_fullname(p_fullname
+".elseblock");
9472 FATAL_ERROR("AltGuard::set_fullname()");
9476 Value
*AltGuard::get_guard_expr() const
9478 if (altguardtype
== AG_ELSE
) FATAL_ERROR("AltGuard::get_guard_expr()");
9482 Ref_pard
*AltGuard::get_guard_ref() const
9484 if (altguardtype
!= AG_REF
) FATAL_ERROR("AltGuard::get_guard_ref()");
9488 Statement
*AltGuard::get_guard_stmt() const
9490 if (altguardtype
!= AG_OP
) FATAL_ERROR("AltGuard::get_guard_stmt()");
9494 void AltGuard::set_my_def(Definition
*p_def
)
9496 switch(altguardtype
) {
9498 stmt
->set_my_def(p_def
);
9499 block
->set_my_def(p_def
);
9502 if(block
) block
->set_my_def(p_def
);
9505 if(block
) block
->set_my_def(p_def
);
9508 block
->set_my_def(p_def
);
9511 FATAL_ERROR("AltGuard::set_my_def()");
9515 void AltGuard::set_my_ags(AltGuards
*p_ags
)
9517 switch (altguardtype
) {
9519 block
->set_my_ags(p_ags
);
9522 if (block
) block
->set_my_ags(p_ags
);
9525 if (block
) block
->set_my_ags(p_ags
);
9528 block
->set_my_ags(p_ags
);
9531 FATAL_ERROR("AltGuard::set_my_ags()");
9535 void AltGuard::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9537 switch (altguardtype
) {
9539 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9542 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9545 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9548 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9551 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9555 void AltGuard::chk()
9557 switch(altguardtype
) {
9560 Error_Context
cntxt(expr
, "In guard expression");
9561 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9564 Error_Context
cntxt(stmt
, "In guard operation");
9571 Error_Context
cntxt(expr
, "In guard expression");
9572 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9575 Error_Context
cntxt(ref
, "In guard statement");
9576 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
9578 if (t_ass
->get_asstype() == Common::Assignment::A_ALTSTEP
) {
9579 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *ref
, "call");
9581 ref
->error("Reference to an altstep was expected instead of %s",
9582 t_ass
->get_description().c_str());
9586 if (block
) block
->chk();
9590 Error_Context
cntxt(expr
, "In guard expression");
9591 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9594 if (!invoke
.t_list
) return; //already_checked
9595 Error_Context
cntxt(ref
, "In guard statement");
9596 switch(invoke
.v
->get_valuetype()){
9597 case Value::V_REFER
:
9599 "A value of an altstep type was expected "
9600 "in the argument instead of a `refers' statement,"
9601 " which does not specify any function type");
9603 case Value::V_TTCN3_NULL
:
9605 "A value of an altstep type was expected "
9606 "in the argument instead of a `null' value,"
9607 " which does not specify any function type");
9612 Type
*t
= invoke
.v
->get_expr_governor_last();
9614 switch (t
->get_typetype()) {
9617 case Type::T_ALTSTEP
:
9620 invoke
.v
->error("A value of type altstep was expected instead of "
9621 "`%s'", t
->get_typename().c_str());
9624 invoke
.v
->get_my_scope()->chk_runs_on_clause(t
, *this, "call");
9625 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
9626 invoke
.ap_list
= new Ttcn::ActualParList
;
9627 bool is_erroneous
= fp_list
->chk_actual_parlist(invoke
.t_list
,
9629 delete invoke
.t_list
;
9632 delete invoke
.ap_list
;
9635 invoke
.ap_list
->set_fullname(get_fullname());
9636 invoke
.ap_list
->set_my_scope(invoke
.v
->get_my_scope());
9639 if (block
) block
->chk();
9643 Error_Context
cntxt(this, "In else branch");
9645 Statement
*first_stmt
= block
->get_first_stmt();
9646 if (first_stmt
&& first_stmt
->get_statementtype() ==
9647 Statement::S_REPEAT
)
9648 first_stmt
->warning("The first statement of the [else] branch is a "
9649 "repeat statement. This will result in busy waiting");
9653 FATAL_ERROR("AltGuard::chk()");
9657 void AltGuard::set_code_section(
9658 GovernedSimple::code_section_t p_code_section
)
9660 switch(altguardtype
) {
9662 if (expr
) expr
->set_code_section(p_code_section
);
9663 stmt
->set_code_section(p_code_section
);
9664 block
->set_code_section(p_code_section
);
9667 if (expr
) expr
->set_code_section(p_code_section
);
9668 ref
->set_code_section(p_code_section
);
9669 if (block
) block
->set_code_section(p_code_section
);
9672 if (expr
) expr
->set_code_section(p_code_section
);
9673 invoke
.v
->set_code_section(p_code_section
);
9674 if(invoke
.t_list
) invoke
.t_list
->set_code_section(p_code_section
);
9676 for(size_t i
= 0; i
< invoke
.ap_list
->get_nof_pars(); i
++)
9677 invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
9678 if (block
) block
->set_code_section(p_code_section
);
9681 block
->set_code_section(p_code_section
);
9684 FATAL_ERROR("AltGuard::set_fullname()");
9688 void AltGuard::generate_code_invoke_instance(expression_struct
*p_expr
)
9690 if (altguardtype
!= AG_INVOKE
)
9691 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9692 Value
*last_v
= invoke
.v
->get_value_refd_last();
9693 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
9694 Common::Assignment
*altstep
= last_v
->get_refd_fat();
9695 p_expr
->expr
= mputprintf(p_expr
->expr
, "%s_instance(",
9696 altstep
->get_genname_from_scope(invoke
.v
->get_my_scope()).c_str());
9697 invoke
.ap_list
->generate_code_alias(p_expr
,
9698 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9700 invoke
.v
->generate_code_expr_mandatory(p_expr
);
9701 p_expr
->expr
= mputstr(p_expr
->expr
, ".invoke(");
9702 Type
* gov_last
= invoke
.v
->get_expr_governor_last();
9703 invoke
.ap_list
->generate_code_alias(p_expr
, 0,
9704 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
9706 p_expr
->expr
= mputc(p_expr
->expr
, ')');
9709 // =================================
9711 // =================================
9713 AltGuards::~AltGuards()
9715 for(size_t i
=0; i
<ags
.size(); i
++) delete ags
[i
];
9718 delete il_label_end
;
9721 AltGuards
*AltGuards::clone() const
9723 FATAL_ERROR("AltGuards::clone");
9726 void AltGuards::add_ag(AltGuard
*p_ag
)
9729 FATAL_ERROR("AltGuards::add_ag()");
9733 void AltGuards::set_my_scope(Scope
*p_scope
)
9736 for(size_t i
=0; i
<ags
.size(); i
++)
9737 ags
[i
]->set_my_scope(p_scope
);
9740 void AltGuards::set_fullname(const string
& p_fullname
)
9742 Node::set_fullname(p_fullname
);
9743 for(size_t i
=0; i
<ags
.size(); i
++)
9744 ags
[i
]->set_fullname(p_fullname
+".ag_"+Int2string(i
+1));
9747 void AltGuards::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9749 for(size_t i
=0; i
<ags
.size(); i
++)
9750 ags
[i
]->set_my_sb(p_sb
, p_index
);
9753 void AltGuards::set_my_def(Definition
*p_def
)
9755 for(size_t i
=0; i
<ags
.size(); i
++)
9756 ags
[i
]->set_my_def(p_def
);
9759 void AltGuards::set_my_ags(AltGuards
*p_ags
)
9761 for(size_t i
=0; i
<ags
.size(); i
++)
9762 ags
[i
]->set_my_ags(p_ags
);
9765 void AltGuards::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9767 for(size_t i
=0; i
<ags
.size(); i
++)
9768 ags
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9771 bool AltGuards::has_else() const
9773 for (size_t i
= 0; i
< ags
.size(); i
++)
9774 if (ags
[i
]->get_type() == AltGuard::AG_ELSE
) return true;
9778 StatementBlock::returnstatus_t
AltGuards::has_return() const
9780 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9781 for (size_t i
= 0; i
< ags
.size(); i
++) {
9782 AltGuard
*ag
= ags
[i
];
9783 StatementBlock
*block
= ag
->get_block();
9784 StatementBlock::returnstatus_t block_status
;
9785 if (block
) block_status
= block
->has_return();
9786 else block_status
= StatementBlock::RS_NO
;
9787 switch (block_status
) {
9788 case StatementBlock::RS_NO
:
9789 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9790 else ret_val
= StatementBlock::RS_NO
;
9792 case StatementBlock::RS_YES
:
9793 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9794 else ret_val
= StatementBlock::RS_YES
;
9797 return StatementBlock::RS_MAYBE
;
9799 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9804 bool AltGuards::has_receiving_stmt() const
9806 for(size_t i
=0; i
<ags
.size(); i
++)
9807 if(ags
[i
]->get_block()->has_receiving_stmt()) return true;
9811 void AltGuards::chk()
9813 bool unreach_found
= false;
9814 size_t nof_ags
= ags
.size();
9815 AltGuard
*prev_ag
= 0;
9816 for (size_t i
= 0; i
< nof_ags
; i
++) {
9817 AltGuard
*ag
= ags
[i
];
9819 if (!unreach_found
&& prev_ag
&&
9820 prev_ag
->get_type() == AltGuard::AG_ELSE
) {
9821 ag
->warning("Control never reaches this branch of alternative "
9822 "because of the previous [else] branch");
9823 unreach_found
= true;
9829 void AltGuards::chk_allowed_interleave()
9831 for (size_t i
= 0; i
< ags
.size(); i
++) {
9832 AltGuard
*ag
= ags
[i
];
9833 switch (ag
->get_type()) {
9834 case AltGuard::AG_OP
:
9836 case AltGuard::AG_REF
:
9837 case AltGuard::AG_INVOKE
:
9838 ag
->error("Invocation of an altstep is not allowed within an "
9839 "interleave statement");
9841 case AltGuard::AG_ELSE
:
9842 ag
->error("Else branch of an alternative is not allowed within an "
9843 "interleave statement");
9846 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
9848 ag
->get_block()->chk_allowed_interleave();
9852 void AltGuards::set_code_section(
9853 GovernedSimple::code_section_t p_code_section
)
9855 for (size_t i
= 0; i
< ags
.size(); i
++)
9856 ags
[i
]->set_code_section(p_code_section
);
9859 char *AltGuards::generate_code_alt(char *str
, const Location
& loc
)
9861 bool label_needed
= has_repeat
, has_else_branch
= false;
9862 for (size_t i
= 0; i
< ags
.size(); i
++) {
9863 AltGuard
*ag
= ags
[i
];
9864 switch (ag
->get_type()) {
9865 case AltGuard::AG_OP
:
9866 // trigger may return ALT_REPEAT
9867 if (ag
->get_guard_stmt()->can_repeat()) label_needed
= true;
9869 case AltGuard::AG_REF
:
9870 case AltGuard::AG_INVOKE
:
9871 // an altstep may return ALT_REPEAT
9872 label_needed
= true;
9874 case AltGuard::AG_ELSE
:
9875 has_else_branch
= true;
9878 FATAL_ERROR("AltGuards::generate_code_alt()");
9880 if (has_else_branch
) break;
9882 // if there is no [else] branch the defaults may return ALT_REPEAT
9883 if (!has_else_branch
) label_needed
= true;
9884 // opening bracket of the statement block
9885 str
= mputstr(str
, "{\n");
9886 // the label name is also used for prefixing local variables
9887 if (!my_scope
|| label
) FATAL_ERROR("AltGuards::generate_code_alt()");
9888 label
= new string(my_scope
->get_scope_mod_gen()->get_temporary_id());
9889 const char *label_str
= label
->c_str();
9890 if (label_needed
) str
= mputprintf(str
, "%s:\n", label_str
);
9891 // temporary variables used for caching of status codes
9892 for (size_t i
= 0; i
< ags
.size(); i
++) {
9893 AltGuard
*ag
= ags
[i
];
9894 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9895 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
9896 label_str
, (unsigned long) i
,
9897 ag
->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
9899 if (!has_else_branch
) {
9900 str
= mputprintf(str
, "alt_status %s_default_flag = ALT_MAYBE;\n",
9903 // the first snapshot is taken in non-blocking mode
9904 // and opening infinite for() loop
9905 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
9907 for (size_t i
= 0; i
< ags
.size(); i
++) {
9908 AltGuard
*ag
= ags
[i
];
9909 AltGuard::altguardtype_t agtype
= ag
->get_type();
9910 if (agtype
== AltGuard::AG_ELSE
) {
9911 // an else branch was found
9912 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
9913 StatementBlock
*block
= ag
->get_block();
9914 if (block
->get_nof_stmts() > 0) {
9915 str
= mputstr(str
, "{\n");
9916 str
= block
->generate_code(str
);
9917 str
= mputstr(str
, "}\n");
9919 // jump out of the infinite for() loop
9920 if (block
->has_return() != StatementBlock::RS_YES
)
9921 str
= mputstr(str
, "break;\n");
9922 // do not generate code for further branches
9925 Value
*guard_expr
= ag
->get_guard_expr();
9927 // the branch has a boolean guard expression
9928 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
9929 label_str
, (unsigned long) i
);
9930 str
= guard_expr
->update_location_object(str
);
9931 expression_struct expr
;
9932 Code::init_expr(&expr
);
9933 guard_expr
->generate_code_expr(&expr
);
9934 str
= mputstr(str
, expr
.preamble
);
9935 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
9936 "else %s_alt_flag_%lu = ALT_NO;\n", expr
.expr
, label_str
,
9937 (unsigned long) i
, label_str
, (unsigned long) i
);
9938 str
= mputstr(str
, expr
.postamble
);
9939 Code::free_expr(&expr
);
9940 str
= mputstr(str
, "}\n");
9942 // evaluation of guard operation or altstep
9943 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
9944 label_str
, (unsigned long) i
);
9945 // indicates whether the guard operation might return ALT_REPEAT
9947 expression_struct expr
;
9948 Code::init_expr(&expr
);
9949 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
9952 case AltGuard::AG_OP
: {
9953 // the guard operation is a receiving statement
9954 Statement
*stmt
= ag
->get_guard_stmt();
9955 str
= stmt
->update_location_object(str
);
9956 stmt
->generate_code_expr(&expr
);
9957 can_repeat
= stmt
->can_repeat();
9959 case AltGuard::AG_REF
: {
9960 // the guard operation is an altstep instance
9961 Ref_pard
*ref
= ag
->get_guard_ref();
9962 str
= ref
->update_location_object(str
);
9963 Common::Assignment
*altstep
= ref
->get_refd_assignment();
9964 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
9965 altstep
->get_genname_from_scope(my_scope
).c_str());
9966 ref
->get_parlist()->generate_code_alias(&expr
,
9967 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9968 expr
.expr
= mputc(expr
.expr
, ')');
9971 case AltGuard::AG_INVOKE
: {
9972 // the guard operation is an altstep invocation
9973 str
= ag
->update_location_object(str
);
9974 ag
->generate_code_invoke_instance(&expr
);
9978 FATAL_ERROR("AltGuards::generate_code_alt()");
9980 str
= Code::merge_free_expr(str
, &expr
);
9982 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
9983 label_str
, (unsigned long) i
, label_str
);
9985 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
9986 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
9987 label_str
, (unsigned long) i
);
9989 // execution of statement block if the guard was successful
9990 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
9992 StatementBlock
*block
= ag
->get_block();
9993 if (block
&& block
->get_nof_stmts() > 0) {
9994 str
= mputstr(str
, "{\n");
9995 str
= block
->generate_code(str
);
9996 if (block
->has_return() != StatementBlock::RS_YES
)
9997 str
= mputstr(str
, "break;\n");
9998 str
= mputstr(str
, "}\n");
9999 } else str
= mputstr(str
, "break;\n");
10000 // closing of if() block
10001 str
= mputstr(str
, "}\n");
10004 if (!has_else_branch
) {
10005 // calling of defaults
10006 str
= mputprintf(str
, "if (%s_default_flag == ALT_MAYBE) {\n"
10007 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10008 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10010 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10012 label_str
, label_str
, label_str
, label_str
, label_str
, label_str
);
10013 str
= loc
.update_location_object(str
);
10014 // error handling and taking the next snapshot in blocking mode
10015 str
= mputstr(str
, "if (");
10016 for (size_t i
= 0; i
< ags
.size(); i
++)
10017 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO && ", label_str
,
10018 (unsigned long) i
);
10019 str
= mputprintf(str
,"%s_default_flag == ALT_NO) "
10020 "TTCN_error(\"None of the branches can be chosen in the alt "
10021 "statement in file ", label_str
);
10022 str
= Code::translate_string(str
, loc
.get_filename());
10023 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10024 if (first_line
< last_line
) str
= mputprintf(str
,
10025 " between lines %d and %d", first_line
, last_line
);
10026 else str
= mputprintf(str
, ", line %d", first_line
);
10027 str
= mputstr(str
, ".\");\n"
10028 "TTCN_Snapshot::take_new(TRUE);\n");
10030 // end of for() statement and the statement block
10031 str
= mputstr(str
, "}\n"
10036 char *AltGuards::generate_code_altstep(char *str
)
10038 if (!my_scope
) FATAL_ERROR("AltGuards::generate_code_altstep()");
10039 Common::Module
*my_mod
= my_scope
->get_scope_mod_gen();
10040 bool has_else_branch
= has_else();
10041 if (!has_else_branch
) {
10042 str
= mputstr(str
, "alt_status ret_val = ALT_NO;\n");
10044 for (size_t i
= 0; i
< ags
.size(); i
++) {
10045 AltGuard
*ag
= ags
[i
];
10046 AltGuard::altguardtype_t agtype
= ag
->get_type();
10047 if (agtype
== AltGuard::AG_ELSE
) {
10048 // an else branch was found
10049 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10050 StatementBlock
*block
= ag
->get_block();
10051 if (block
->get_nof_stmts() > 0) {
10052 str
= mputstr(str
, "{\n");
10053 str
= block
->generate_code(str
);
10054 str
= mputstr(str
, "}\n");
10056 if (block
->has_return() != StatementBlock::RS_YES
)
10057 str
= mputstr(str
, "return ALT_YES;\n");
10058 // do not generate code for further branches
10061 size_t blockcount
= 0;
10062 Value
*guard_expr
= ag
->get_guard_expr();
10064 // the branch has a boolean guard expression
10065 str
= guard_expr
->update_location_object(str
);
10066 str
= guard_expr
->generate_code_tmp(str
, "if (", blockcount
);
10067 str
= mputstr(str
, ") {\n");
10070 // indicates whether the guard operation might return ALT_REPEAT
10072 expression_struct expr
;
10073 Code::init_expr(&expr
);
10075 case AltGuard::AG_OP
: {
10076 // the guard operation is a receiving statement
10077 Statement
*stmt
= ag
->get_guard_stmt();
10078 str
= stmt
->update_location_object(str
);
10079 stmt
->generate_code_expr(&expr
);
10080 can_repeat
= stmt
->can_repeat();
10082 case AltGuard::AG_REF
: {
10083 // the guard operation is an altstep instance
10084 Ref_pard
*ref
= ag
->get_guard_ref();
10085 str
= ref
->update_location_object(str
);
10086 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10087 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10088 altstep
->get_genname_from_scope(my_scope
).c_str());
10089 ref
->get_parlist()->generate_code_alias(&expr
,
10090 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10091 expr
.expr
= mputc(expr
.expr
, ')');
10094 case AltGuard::AG_INVOKE
: {
10095 str
= ag
->update_location_object(str
);
10096 ag
->generate_code_invoke_instance(&expr
);
10100 FATAL_ERROR("AltGuards::generate_code_altstep()");
10102 if (expr
.preamble
|| expr
.postamble
) {
10103 if (blockcount
== 0) {
10104 // open a statement block if it is not done so far
10105 str
= mputstr(str
, "{\n");
10108 const string
& tmp_id
= my_mod
->get_temporary_id();
10109 const char *tmp_id_str
= tmp_id
.c_str();
10110 str
= mputprintf(str
, "alt_status %s;\n"
10111 "{\n", tmp_id_str
);
10112 str
= mputstr(str
, expr
.preamble
);
10113 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, expr
.expr
);
10114 str
= mputstr(str
, expr
.postamble
);
10115 str
= mputprintf(str
, "}\n"
10116 "switch (%s) {\n", tmp_id_str
);
10118 str
= mputprintf(str
, "switch (%s) {\n", expr
.expr
);
10120 Code::free_expr(&expr
);
10121 str
= mputstr(str
, "case ALT_YES:\n");
10122 StatementBlock
*block
= ag
->get_block();
10123 if (block
&& block
->get_nof_stmts() > 0) {
10124 str
= mputstr(str
, "{\n");
10125 str
= block
->generate_code(str
);
10126 str
= mputstr(str
, "}\n");
10128 if (!block
|| block
->has_return() != StatementBlock::RS_YES
)
10129 str
= mputstr(str
, "return ALT_YES;\n");
10131 str
= mputstr(str
, "case ALT_REPEAT:\n"
10132 "return ALT_REPEAT;\n");
10133 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10134 str
= mputprintf(str
, "case ALT_BREAK:\n"
10135 "return ALT_BREAK;\n");
10137 if (!has_else_branch
)
10138 str
= mputstr(str
, "case ALT_MAYBE:\n"
10139 "ret_val = ALT_MAYBE;\n");
10140 str
= mputstr(str
, "default:\n"
10143 // closing statement blocks
10144 for ( ; blockcount
> 0; blockcount
--) str
= mputstr(str
, "}\n");
10147 if (!has_else_branch
) str
= mputstr(str
, "return ret_val;\n");
10151 char* AltGuards::generate_code_call_body(char *str
, const Location
& loc
,
10152 const string
& temp_id
, bool in_interleave
)
10154 if (label
) FATAL_ERROR("AltGuards::generate_code_call_body()");
10155 label
= new string(temp_id
);
10156 const char *label_str
= temp_id
.c_str();
10157 // label is needed only if there is a repeat statement in the branches
10158 if (has_repeat
) str
= mputprintf(str
, "%s:\n", label_str
);
10159 // temporary variables used for caching of status codes
10160 for (size_t i
= 0; i
< ags
.size(); i
++)
10161 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10162 label_str
, (unsigned long) i
,
10163 ags
[i
]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10164 str
= loc
.update_location_object(str
);
10165 // the first snapshot is taken in non-blocking mode
10166 // and opening infinite for() loop
10167 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10168 "for ( ; ; ) {\n"); // (1)
10169 for (size_t i
= 0; i
< ags
.size(); i
++) {
10170 AltGuard
*ag
= ags
[i
];
10171 if (ag
->get_type() != AltGuard::AG_OP
)
10172 FATAL_ERROR("AltGuards::generate_code_call_body()");
10173 Value
*guard_expr
= ag
->get_guard_expr();
10175 // the branch has a boolean guard expression
10176 str
= mputprintf(str
,
10177 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10178 label_str
, (unsigned long) i
);
10179 str
= guard_expr
->update_location_object(str
);
10180 expression_struct expr
;
10181 Code::init_expr(&expr
);
10182 guard_expr
->generate_code_expr(&expr
);
10183 str
= mputstr(str
, expr
.preamble
);
10184 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10185 "else %s_alt_flag_%lu = ALT_NO;\n",
10186 expr
.expr
, label_str
, (unsigned long) i
,
10187 label_str
, (unsigned long) i
);
10188 str
= mputstr(str
, expr
.postamble
);
10189 Code::free_expr(&expr
);
10190 str
= mputstr(str
, "}\n"); // (2)
10192 // evaluation of guard operation
10193 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10194 label_str
, (unsigned long) i
);
10195 expression_struct expr
;
10196 Code::init_expr(&expr
);
10197 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10198 (unsigned long) i
);
10199 Statement
*stmt
= ag
->get_guard_stmt();
10200 str
= stmt
->update_location_object(str
);
10201 stmt
->generate_code_expr(&expr
);
10202 str
= Code::merge_free_expr(str
, &expr
);
10203 // execution of statement block if the guard was successful
10204 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10205 (unsigned long) i
);
10206 StatementBlock
*block
= ag
->get_block();
10207 if(in_interleave
) {
10208 if(block
&& block
->get_nof_stmts() > 0) {
10209 if(block
->has_receiving_stmt()) {
10210 str
= mputprintf(str
, "goto %s_branch%lu;\n",
10211 label_str
, (unsigned long) i
);
10214 str
= mputstr(str
, "{\n"); // (3)
10215 str
= block
->generate_code(str
);
10216 str
= mputprintf(str
, "goto %s_end;\n"
10221 else str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10224 if (block
&& block
->get_nof_stmts() > 0) {
10225 str
= mputstr(str
, "{\n"); // (3)
10226 str
= block
->generate_code(str
);
10227 if (block
->has_return() != StatementBlock::RS_YES
)
10228 str
= mputstr(str
, "break;\n");
10229 str
= mputstr(str
, "}\n"); // (3)
10231 else str
= mputstr(str
, "break;\n");
10233 // closing of if() block
10234 str
= mputstr(str
, "}\n"); // (2)
10236 str
= loc
.update_location_object(str
);
10237 // error handling and taking the next snapshot in blocking mode
10238 str
= mputstr(str
, "if (");
10239 for (size_t i
= 0; i
< ags
.size(); i
++) {
10240 if (i
> 0) str
= mputstr(str
, " && ");
10241 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO", label_str
,
10242 (unsigned long) i
);
10244 str
= mputstr(str
, ") TTCN_error(\"None of the branches can be chosen in "
10245 "the response and exception handling part of call statement in file ");
10246 str
= Code::translate_string(str
, loc
.get_filename());
10247 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10248 if (first_line
< last_line
) str
= mputprintf(str
,
10249 " between lines %d and %d", first_line
, last_line
);
10250 else str
= mputprintf(str
, ", line %d", first_line
);
10251 str
= mputstr(str
, ".\");\n"
10252 "TTCN_Snapshot::take_new(TRUE);\n"
10257 void AltGuards::ilt_generate_code_call_body(ILT
*ilt
, const char *label_str
)
10259 char*& str
=ilt
->get_out_branches();
10260 for(size_t i
=0; i
<ags
.size(); i
++) {
10261 StatementBlock
*block
= ags
[i
]->get_block();
10262 if (block
&& block
->has_receiving_stmt()) {
10263 str
= mputprintf(str
, "%s_branch%lu:\n", label_str
, (unsigned long) i
);
10264 block
->ilt_generate_code(ilt
);
10265 str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10270 } // namespace Ttcn