1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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
)
157 // return NULL outside test cases
158 if (!my_def
|| my_def
->get_asstype() != Common::Assignment::A_TESTCASE
)
161 Def_Testcase
*t_tc
= dynamic_cast<Def_Testcase
*>(my_def
);
162 if (!t_tc
) FATAL_ERROR("StatementBlock::get_mtc_system_comptype()");
163 Type
*system_ct
= t_tc
->get_SystemType();
164 if (system_ct
) return system_ct
;
165 // otherwise (if the testcase has no system clause) the type of 'system'
166 // is the same as the type of 'mtc' (which is given in 'runs on' clause)
168 return my_def
->get_RunsOnType();
171 Ttcn::StatementBlock
*StatementBlock::get_statementblock_scope()
176 void StatementBlock::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
180 for(size_t i
=0; i
<stmts
.size(); i
++)
181 stmts
[i
]->set_my_sb(this, i
);
184 size_t StatementBlock::get_my_sb_index() const
186 if(!my_sb
) FATAL_ERROR("StatementBlock::get_my_sb_index()");
190 void StatementBlock::set_my_def(Definition
*p_def
)
193 for(size_t i
=0; i
<stmts
.size(); i
++)
194 stmts
[i
]->set_my_def(p_def
);
197 void StatementBlock::set_my_ags(AltGuards
*p_ags
)
199 for(size_t i
=0; i
<stmts
.size(); i
++)
200 stmts
[i
]->set_my_ags(p_ags
);
203 void StatementBlock::set_my_laic_stmt(AltGuards
*p_ags
,
204 Statement
*p_loop_stmt
)
206 for(size_t i
=0; i
<stmts
.size(); i
++)
207 stmts
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
210 StatementBlock::returnstatus_t
StatementBlock::has_return() const
212 returnstatus_t ret_val
= RS_NO
;
213 size_t nof_stmts
= stmts
.size();
214 for (size_t i
= 0; i
< nof_stmts
; i
++) {
215 Statement
*stmt
= stmts
[i
];
216 if (stmt
->get_statementtype() == Statement::S_GOTO
) {
217 if (stmt
->goto_jumps_forward()) {
218 // heuristics without deep analysis of the control flow graph:
219 // skip over the next statements until a (used) label is found
220 // the behaviour will be sound (i.e. no false errors will be reported)
221 for (i
++; i
< nof_stmts
; i
++) {
223 if (stmt
->get_statementtype() == Statement::S_LABEL
&&
224 stmt
->label_is_used()) break;
226 } else return RS_YES
;
227 } else if (stmt
->get_statementtype()==Statement::S_BLOCK
&& stmt
->get_block()->exception_handling
!=EH_NONE
) {
228 switch (stmt
->get_block()->exception_handling
) {
229 case EH_TRY
: // the i-th statement is a try{} statement block, the (i+1)-th must be a catch{} block
230 if ((i
+1)<nof_stmts
&& stmts
[i
+1]->get_statementtype()==Statement::S_BLOCK
&& stmts
[i
+1]->get_block()->exception_handling
==EH_CATCH
) {
231 returnstatus_t try_block_rs
= stmt
->has_return();
232 returnstatus_t catch_block_rs
= stmts
[i
+1]->has_return();
233 // 3 x 3 combinations
234 if (try_block_rs
==catch_block_rs
) {
235 switch (try_block_rs
) {
246 } else { // if next statement is not a catch{} block then that error has already been reported
247 ret_val
= RS_MAYBE
; // assume the catch block was an RS_MAYBE
251 // logically this is part of the preceding try{} block, handle it as part of it, see above case EH_TRY
254 FATAL_ERROR("StatementBlock::has_return()");
257 switch (stmt
->has_return()) {
270 bool StatementBlock::has_receiving_stmt(size_t start_i
) const
272 for(size_t i
=start_i
; i
<stmts
.size(); i
++)
273 if(stmts
[i
]->has_receiving_stmt()) return true;
277 bool StatementBlock::has_def_stmt_i(size_t start_i
) const
279 for(size_t i
=start_i
; i
<stmts
.size(); i
++)
280 if(stmts
[i
]->get_statementtype()==Statement::S_DEF
) return true;
284 size_t StatementBlock::last_receiving_stmt_i() const
286 size_t nof_stmts
= stmts
.size();
288 size_t i
= nof_stmts
;
290 if (stmts
[--i
]->has_receiving_stmt()) return i
;
296 StatementBlock
*StatementBlock::get_parent_block() const
298 for (Scope
*s
= get_parent_scope(); s
; s
=s
->get_parent_scope()) {
299 StatementBlock
*sb
= dynamic_cast<StatementBlock
*>(s
);
305 void StatementBlock::chk_trycatch_blocks(Statement
* s1
, Statement
* s2
) {
306 if (s1
&& s1
->get_statementtype()==Statement::S_BLOCK
&& s1
->get_block()->get_exception_handling()==StatementBlock::EH_TRY
) {
307 if (!(s2
&& s2
->get_statementtype()==Statement::S_BLOCK
&& s2
->get_block()->get_exception_handling()==StatementBlock::EH_CATCH
)) {
308 s1
->error("`try' statement block must be followed by a `catch' block");
311 if (s2
&& s2
->get_statementtype()==Statement::S_BLOCK
&& s2
->get_block()->get_exception_handling()==StatementBlock::EH_CATCH
) {
312 if (!(s1
&& s1
->get_statementtype()==Statement::S_BLOCK
&& s1
->get_block()->get_exception_handling()==StatementBlock::EH_TRY
)) {
313 s2
->error("`catch' statement block must be preceded by a `try' block");
318 void StatementBlock::chk()
322 bool unreach_found
= false;
323 size_t nof_stmts
= stmts
.size();
324 Statement
*prev_stmt
= 0;
325 for (size_t i
= 0; i
< nof_stmts
; i
++) {
326 Statement
*stmt
= stmts
[i
];
328 if (!unreach_found
&& stmt
->get_statementtype() != Statement::S_LABEL
&&
329 prev_stmt
&& prev_stmt
->is_terminating()) {
330 // a statement is unreachable if:
331 // - it is not a label (i.e. goto cannot jump to it)
332 // - it is not the first statement of the block
333 // - the previous statement terminates the control flow
334 stmt
->warning("Control never reaches this statement");
335 unreach_found
= true;
337 // check try-catch statement block usage
338 chk_trycatch_blocks(prev_stmt
, stmt
);
342 chk_trycatch_blocks(prev_stmt
, 0);
347 void StatementBlock::chk_allowed_interleave()
349 size_t nof_stmts
= stmts
.size();
350 for (size_t i
= 0; i
< nof_stmts
; i
++)
351 stmts
[i
]->chk_allowed_interleave();
354 void StatementBlock::chk_labels()
356 if(labels_checked
) return;
357 for(size_t i
=0; i
<stmts
.size(); i
++) {
358 Statement
*st
=stmts
[i
];
359 if(st
->get_statementtype()!=Statement::S_LABEL
) continue;
360 const Identifier
& labelid
=st
->get_labelid();
361 if(has_label(labelid
)) {
362 const char *name
=labelid
.get_dispname().c_str();
363 st
->error("Duplicate label `%s'", name
);
364 Statement
*st2
=get_label(labelid
);
365 st2
->note("Previous definition of label `%s' is here", name
);
367 else labels
.add(labelid
, st
);
372 void StatementBlock::chk_unused_labels()
374 size_t nof_stmts
= stmts
.size();
375 for (size_t i
= 0; i
< nof_stmts
; i
++) {
376 Statement
*stmt
= stmts
[i
];
377 if (stmt
->get_statementtype() == Statement::S_LABEL
&&
378 !stmt
->label_is_used())
379 stmt
->warning("Label `%s' is defined, but not used",
380 stmt
->get_labelid().get_dispname().c_str());
384 bool StatementBlock::has_label(const Identifier
& p_id
) const
386 for (const StatementBlock
*sb
= this; sb
; sb
= sb
->get_parent_block())
387 if (sb
->labels
.has_key(p_id
)) return true;
391 Statement
*StatementBlock::get_label(const Identifier
& p_id
) const
393 for (const StatementBlock
*sb
= this; sb
; sb
= sb
->get_parent_block())
394 if (sb
->labels
.has_key(p_id
)) return sb
->labels
[p_id
];
395 FATAL_ERROR("StatementBlock::get_label()");
399 void StatementBlock::set_code_section(
400 GovernedSimple::code_section_t p_code_section
)
402 for(size_t i
= 0; i
< stmts
.size(); i
++)
403 stmts
[i
]->set_code_section(p_code_section
);
406 char* StatementBlock::generate_code(char *str
)
408 if (exception_handling
==EH_TRY
) {
409 str
= mputstr(str
, "TTCN_TryBlock try_block;\n");
411 if (stmts
.size()>0) {
412 Statement
* first_stmt
= stmts
[0];
413 str
= first_stmt
->generate_code(str
);
414 if (exception_handling
==EH_CATCH
) {
415 if (first_stmt
->get_statementtype()!=Statement::S_DEF
) FATAL_ERROR("StatementBlock::generate_code()");
416 Definition
* error_msg_def
= first_stmt
->get_def();
417 string error_msg_name
= error_msg_def
->get_id().get_name();
418 str
= mputprintf(str
, "%s = ttcn_error.get_message();\n", error_msg_name
.c_str());
421 for(size_t i
=1; i
<stmts
.size(); i
++) {
422 str
= stmts
[i
]->generate_code(str
);
427 void StatementBlock::ilt_generate_code(ILT
*ilt
)
429 size_t nof_stmts
= stmts
.size();
430 if (nof_stmts
== 0) return;
431 char*& str
=ilt
->get_out_branches();
432 size_t last_recv_stmt_i
=last_receiving_stmt_i();
433 // has no receiving stmt
434 if (last_recv_stmt_i
== nof_stmts
) {
435 bool has_def
=has_def_stmt_i();
436 if(has_def
) str
=mputstr(str
, "{\n");
437 for(size_t i
=0; i
<nof_stmts
; i
++)
438 str
=stmts
[i
]->generate_code(str
);
439 if(has_def
) str
=mputstr(str
, "}\n");
442 for(size_t i
=0; i
<=last_recv_stmt_i
; i
++)
443 stmts
[i
]->ilt_generate_code(ilt
);
444 // the last part which does not contain receiving stmt
445 if(last_recv_stmt_i
==nof_stmts
-1) return;
446 bool has_def
=has_def_stmt_i(last_recv_stmt_i
+1);
447 if(has_def
) str
=mputstr(str
, "{\n");
448 for(size_t i
=last_recv_stmt_i
+1; i
<nof_stmts
; i
++)
449 str
=stmts
[i
]->generate_code(str
);
450 if(has_def
) str
=mputstr(str
, "}\n");
453 void StatementBlock::set_parent_path(WithAttribPath
* p_path
)
455 for (size_t i
= 0; i
< stmts
.size(); i
++)
456 stmts
[i
]->set_parent_path(p_path
);
459 // =================================
461 // =================================
463 void Statement::clean_up()
465 switch (statementtype
) {
471 case S_START_PROFILER
:
472 case S_STOP_PROFILER
:
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
;
679 delete convert_op
.val
;
680 delete convert_op
.ref
;
683 FATAL_ERROR("Statement::clean_up()");
684 } // switch statementtype
687 Statement::Statement(statementtype_t p_st
)
688 : statementtype(p_st
), my_sb(0)
690 switch(statementtype
) {
695 case S_START_PROFILER
:
696 case S_STOP_PROFILER
:
704 FATAL_ERROR("Statement::Statement()");
705 } // switch statementtype
708 Statement::Statement(statementtype_t p_st
, Ref_base
*p_ref
, Value
*p_val
)
709 : statementtype(p_st
), my_sb(0)
711 switch(statementtype
) {
713 if (!p_ref
) FATAL_ERROR("Statement::Statement()");
714 undefstartstop
.ref
=p_ref
;
715 undefstartstop
.val
=p_val
;
718 if (!p_ref
|| p_val
) FATAL_ERROR("Statement::Statement()");
719 undefstartstop
.ref
=p_ref
;
720 undefstartstop
.val
=0;
723 FATAL_ERROR("Statement::Statement()");
724 } // switch statementtype
727 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
)
728 : statementtype(p_st
), my_sb(0)
730 switch(statementtype
) {
731 case S_UNKNOWN_INSTANCE
:
732 case S_FUNCTION_INSTANCE
:
733 case S_ALTSTEP_INSTANCE
:
736 FATAL_ERROR("Statement::Statement()");
740 FATAL_ERROR("Statement::Statement()");
741 } // switch statementtype
744 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
745 ParsedActualParameters
*p_ap_list
)
746 : statementtype(p_st
), my_sb(0)
748 switch(statementtype
) {
749 case S_ACTIVATE_REFD
:
750 case S_UNKNOWN_INVOKED
:
751 case S_FUNCTION_INVOKED
:
752 case S_ALTSTEP_INVOKED
:
753 if(!p_derefered_value
|| !p_ap_list
)
754 FATAL_ERROR("Statement::Statement()");
755 fau_refd
.value
= p_derefered_value
;
756 fau_refd
.t_list1
= p_ap_list
;
759 FATAL_ERROR("Statement::Statement()");
763 Statement::Statement(statementtype_t p_st
, Definition
*p_def
)
764 : statementtype(p_st
), my_sb(0)
766 switch(statementtype
) {
769 FATAL_ERROR("Statement::Statement()");
773 FATAL_ERROR("Statement::Statement()");
774 } // switch statementtype
777 Statement::Statement(statementtype_t p_st
, Assignment
*p_ass
)
778 : statementtype(p_st
), my_sb(0)
780 switch(statementtype
) {
783 FATAL_ERROR("Statement::Statement()");
787 FATAL_ERROR("Statement::Statement()");
788 } // switch statementtype
791 Statement::Statement(statementtype_t p_st
, StatementBlock
*p_block
)
792 : statementtype(p_st
), my_sb(0)
794 switch (statementtype
) {
796 if (!p_block
) FATAL_ERROR("Statement::Statement()");
800 FATAL_ERROR("Statement::Statement()");
801 } // switch statementtype
804 Statement::Statement(statementtype_t p_st
, LogArguments
*p_logargs
)
805 : statementtype(p_st
), my_sb(0)
807 switch(statementtype
) {
810 case S_STOP_TESTCASE
:
814 FATAL_ERROR("Statement::Statement()");
815 } // switch statementtype
818 Statement::Statement(statementtype_t p_st
, Identifier
*p_id
)
819 : statementtype(p_st
), my_sb(0)
822 FATAL_ERROR("Statement::Statement()");
823 switch (statementtype
) {
834 go_to
.jumps_forward
= false;
837 FATAL_ERROR("Statement::Statement()");
838 } // switch statementtype
841 Statement::Statement(statementtype_t p_st
, IfClauses
*p_ics
,
842 StatementBlock
*p_block
, Location
*p_loc
)
843 : statementtype(p_st
), my_sb(0)
845 switch(statementtype
) {
848 FATAL_ERROR("Statement::Statement()");
851 if (!p_loc
) FATAL_ERROR("Statement::Statement()");
852 if_stmt
.elseblock
= p_block
;
853 if_stmt
.elseblock_location
= p_loc
;
855 if (p_loc
) FATAL_ERROR("Statement::Statement()");
856 if_stmt
.elseblock
= 0;
857 if_stmt
.elseblock_location
= 0;
861 FATAL_ERROR("Statement::Statement()");
862 } // switch statementtype
865 Statement::Statement(statementtype_t p_st
, Value
*p_expr
, SelectCases
*p_scs
)
866 : statementtype(p_st
), my_sb(0)
868 switch(statementtype
) {
870 if(!p_expr
|| !p_scs
)
871 FATAL_ERROR("Statement::Statement()");
876 FATAL_ERROR("Statement::Statement()");
877 } // switch statementtype
880 Statement::Statement(statementtype_t p_st
, Definitions
*p_defs
,
881 Assignment
*p_ass
, Value
*p_final
,
882 Assignment
*p_step
, StatementBlock
*p_block
)
883 : statementtype(p_st
), my_sb(0)
885 switch (statementtype
) {
886 case S_FOR
: // precisely one of p_defs, p_ass allowed
888 // it came from a for loop which looked like this:
889 // for (var integer foo:=1; foo<10; foo:=foo+1) ;
890 if (p_ass
) FATAL_ERROR("Statement::Statement()");
891 loop
.for_stmt
.varinst
= true;
892 loop
.for_stmt
.init_varinst
= p_defs
;
894 // it came from a for loop which looked like this:
895 // for (foo:=1; foo<10; foo:=foo+1) ;
896 if (!p_ass
) FATAL_ERROR("Statement::Statement()");
897 loop
.for_stmt
.varinst
= false;
898 loop
.for_stmt
.init_ass
= p_ass
;
900 if(!p_final
|| !p_step
|| !p_block
)
901 FATAL_ERROR("Statement::Statement()");
902 loop
.for_stmt
.finalexpr
=p_final
;
903 loop
.for_stmt
.step
=p_step
;
909 loop
.has_cnt_in_ags
=false;
910 loop
.iterate_once
=false; // not used by for
914 FATAL_ERROR("Statement::Statement()");
915 } // switch statementtype
918 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
919 StatementBlock
*p_block
)
920 : statementtype(p_st
), my_sb(0)
922 switch(statementtype
) {
925 if(!p_val
|| !p_block
)
926 FATAL_ERROR("Statement::Statement()");
933 loop
.has_cnt_in_ags
=false;
934 loop
.iterate_once
=false; // used only by do-while
938 FATAL_ERROR("Statement::Statement()");
939 } // switch statementtype
942 Statement::Statement(statementtype_t p_st
, AltGuards
*p_ags
)
943 : statementtype(p_st
), my_sb(0)
945 switch(statementtype
) {
949 FATAL_ERROR("Statement::Statement()");
953 FATAL_ERROR("Statement::Statement()");
954 } // switch statementtype
957 Statement::Statement(statementtype_t p_st
, Template
*p_temp
)
958 : statementtype(p_st
), my_sb(0)
960 switch(statementtype
) {
966 FATAL_ERROR("Statement::Statement()");
967 } // switch statementtype
970 Statement::Statement(statementtype_t p_st
, Value
*p_val
)
971 : statementtype(p_st
), my_sb(0)
973 switch (statementtype
) {
976 FATAL_ERROR("Statement::Statement()");
980 comp_op
.compref
=p_val
;
986 FATAL_ERROR("Statement::Statement()");
987 } // switch statementtype
990 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
991 LogArguments
*p_logargs
)
992 : statementtype(p_st
), my_sb(0)
994 if (!p_val
|| statementtype
!= S_SETVERDICT
)
995 FATAL_ERROR("Statement::Statement()");
996 setverdict
.verdictval
= p_val
;
997 setverdict
.logargs
= p_logargs
;
1000 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1001 TemplateInstance
*p_templinst
, Value
*p_val
)
1002 : statementtype(p_st
), my_sb(0)
1004 switch(statementtype
) {
1006 if(!p_ref
|| !p_templinst
)
1007 FATAL_ERROR("Statement::Statement()");
1008 port_op
.portref
=p_ref
;
1009 port_op
.s
.sendpar
=p_templinst
;
1010 port_op
.s
.toclause
=p_val
;
1013 FATAL_ERROR("Statement::Statement()");
1014 } // switch statementtype
1017 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1018 TemplateInstance
*p_templinst
, Value
*p_timerval
,
1019 bool p_nowait
, Value
*p_toclause
, AltGuards
*p_callbody
)
1020 : statementtype(p_st
), my_sb(0)
1022 switch(statementtype
) {
1024 if(!p_ref
|| !p_templinst
|| (p_timerval
&& p_nowait
))
1025 FATAL_ERROR("Statement::Statement()");
1026 port_op
.portref
=p_ref
;
1027 port_op
.s
.sendpar
=p_templinst
;
1028 port_op
.s
.call
.timer
=p_timerval
;
1029 port_op
.s
.call
.nowait
=p_nowait
;
1030 port_op
.s
.toclause
=p_toclause
;
1031 port_op
.s
.call
.body
=p_callbody
;
1034 FATAL_ERROR("Statement::Statement()");
1035 } // switch statementtype
1038 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1039 TemplateInstance
*p_templinst
, Value
*p_replyval
,
1041 : statementtype(p_st
), my_sb(0)
1043 switch(statementtype
) {
1045 if(!p_ref
|| !p_templinst
)
1046 FATAL_ERROR("Statement::Statement()");
1047 port_op
.portref
=p_ref
;
1048 port_op
.s
.sendpar
=p_templinst
;
1049 port_op
.s
.replyval
=p_replyval
;
1050 port_op
.s
.toclause
=p_toclause
;
1053 FATAL_ERROR("Statement::Statement()");
1054 } // switch statementtype
1057 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1058 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1060 : statementtype(p_st
), my_sb(0)
1062 switch(statementtype
) {
1064 if(!p_ref
|| !p_templinst
|| !p_sig
)
1065 FATAL_ERROR("Statement::Statement()");
1066 port_op
.portref
=p_ref
;
1067 port_op
.s
.raise
.signature_ref
=p_sig
;
1068 port_op
.s
.raise
.signature
=0;
1069 port_op
.s
.sendpar
=p_templinst
;
1070 port_op
.s
.toclause
=p_toclause
;
1073 FATAL_ERROR("Statement::Statement()");
1074 } // switch statementtype
1077 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1078 TemplateInstance
*p_templinst
,
1079 TemplateInstance
*p_fromclause
,
1080 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1081 : statementtype(p_st
), my_sb(0)
1083 switch(statementtype
) {
1085 case S_CHECK_RECEIVE
:
1087 port_op
.portref
=p_ref
;
1088 port_op
.r
.rcvpar
=p_templinst
;
1089 port_op
.r
.fromclause
=p_fromclause
;
1090 port_op
.r
.redirect
.value
=p_redirectval
;
1091 port_op
.r
.redirect
.param
=0;
1092 port_op
.r
.redirect
.sender
=p_redirectsender
;
1095 FATAL_ERROR("Statement::Statement()");
1096 } // switch statementtype
1099 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1100 TemplateInstance
*p_templinst
,
1101 TemplateInstance
*p_fromclause
,
1102 ParamRedirect
*p_redirectparam
,
1103 Reference
*p_redirectsender
)
1104 : statementtype(p_st
), my_sb(0)
1106 switch(statementtype
) {
1108 case S_CHECK_GETCALL
:
1109 port_op
.portref
=p_ref
;
1110 port_op
.r
.rcvpar
=p_templinst
;
1111 port_op
.r
.fromclause
=p_fromclause
;
1112 port_op
.r
.redirect
.value
=0;
1113 port_op
.r
.redirect
.param
=p_redirectparam
;
1114 port_op
.r
.redirect
.sender
=p_redirectsender
;
1117 FATAL_ERROR("Statement::Statement()");
1118 } // switch statementtype
1121 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1122 TemplateInstance
*p_templinst
,
1123 TemplateInstance
*p_valuematch
,
1124 TemplateInstance
*p_fromclause
,
1125 Reference
*p_redirectval
, ParamRedirect
*p_redirectparam
,
1126 Reference
*p_redirectsender
)
1127 : statementtype(p_st
), my_sb(0)
1129 switch(statementtype
) {
1131 case S_CHECK_GETREPLY
:
1132 if (!p_templinst
&& p_valuematch
) FATAL_ERROR("Statement::Statement()");
1133 port_op
.portref
=p_ref
;
1134 port_op
.r
.rcvpar
=p_templinst
;
1135 port_op
.r
.getreply_valuematch
=p_valuematch
;
1136 port_op
.r
.fromclause
=p_fromclause
;
1137 port_op
.r
.redirect
.value
=p_redirectval
;
1138 port_op
.r
.redirect
.param
=p_redirectparam
;
1139 port_op
.r
.redirect
.sender
=p_redirectsender
;
1142 FATAL_ERROR("Statement::Statement()");
1143 } // switch statementtype
1146 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1147 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1148 bool p_timeout
, TemplateInstance
*p_fromclause
,
1149 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1150 : statementtype(p_st
), my_sb(0)
1152 switch(statementtype
) {
1155 if (((p_sig
|| p_templinst
) && p_timeout
) ||
1156 (p_sig
&& !p_templinst
) || (!p_sig
&& p_templinst
))
1157 FATAL_ERROR("Statement::Statement()");
1158 port_op
.portref
=p_ref
;
1159 port_op
.r
.ctch
.signature_ref
=p_sig
;
1160 port_op
.r
.ctch
.signature
=0;
1161 port_op
.r
.rcvpar
=p_templinst
;
1162 port_op
.r
.ctch
.timeout
=p_timeout
;
1163 port_op
.r
.ctch
.in_call
=false;
1164 port_op
.r
.ctch
.call_has_timer
=false;
1165 port_op
.r
.fromclause
=p_fromclause
;
1166 port_op
.r
.redirect
.value
=p_redirectval
;
1167 port_op
.r
.redirect
.param
=0;
1168 port_op
.r
.redirect
.sender
=p_redirectsender
;
1171 FATAL_ERROR("Statement::Statement()");
1172 } // switch statementtype
1175 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1176 TemplateInstance
*p_fromclause
,
1177 Reference
*p_redirectsender
)
1178 : statementtype(p_st
), my_sb(0)
1180 switch(statementtype
) {
1182 port_op
.portref
=p_ref
; // may be NULL for "any port.check"
1183 port_op
.r
.fromclause
=p_fromclause
;
1184 port_op
.r
.redirect
.value
=0;
1185 port_op
.r
.redirect
.param
=0;
1186 port_op
.r
.redirect
.sender
=p_redirectsender
;
1189 FATAL_ERROR("Statement::Statement()");
1190 } // switch statementtype
1193 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
)
1194 : statementtype(p_st
), my_sb(0)
1196 switch(statementtype
) {
1201 port_op
.portref
=p_ref
;
1205 timer_op
.timerref
=p_ref
;
1208 FATAL_ERROR("Statement::Statement()");
1209 } // switch statementtype
1212 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1213 Ref_pard
*p_funcinst
)
1214 : statementtype(p_st
), my_sb(0)
1216 switch(statementtype
) {
1218 if(!p_compref
|| !p_funcinst
)
1219 FATAL_ERROR("Statement::Statement()");
1220 comp_op
.compref
= p_compref
;
1221 comp_op
.funcinstref
= p_funcinst
;
1224 FATAL_ERROR("Statement::Statement()");
1225 } // switch statementtype
1228 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1229 Value
*p_derefered_value
, ParsedActualParameters
*p_ap_list
)
1230 : statementtype(p_st
), my_sb(0)
1232 switch(statementtype
) {
1233 case S_START_COMP_REFD
:
1234 if(!p_compref
|| !p_derefered_value
|| !p_ap_list
)
1235 FATAL_ERROR("Statement::Statement()");
1236 comp_op
.compref
= p_compref
;
1237 comp_op
.derefered
.value
= p_derefered_value
;
1238 comp_op
.derefered
.t_list1
= p_ap_list
;
1241 FATAL_ERROR("Statement::Statement()");
1245 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1246 TemplateInstance
*p_donematch
, Reference
*p_redirect
)
1247 : statementtype(p_st
), my_sb(0)
1249 switch (statementtype
) {
1251 if (!p_compref
) FATAL_ERROR("Statement::Statement()");
1252 comp_op
.compref
= p_compref
;
1253 comp_op
.donereturn
.donematch
= p_donematch
;
1254 comp_op
.donereturn
.redirect
= p_redirect
;
1257 FATAL_ERROR("Statement::Statement()");
1258 } // switch statementtype
1261 Statement::Statement(statementtype_t p_st
, component_t p_anyall
)
1262 : statementtype(p_st
), my_sb(0)
1264 switch (statementtype
) {
1267 comp_op
.compref
= 0;
1268 comp_op
.any_or_all
= p_anyall
;
1271 FATAL_ERROR("Statement::Statement()");
1272 } // switch statementtype
1275 Statement::Statement(statementtype_t p_st
,
1276 Value
*p_compref1
, Reference
*p_portref1
,
1277 Value
*p_compref2
, Reference
*p_portref2
)
1278 : statementtype(p_st
), my_sb(0)
1280 switch(statementtype
) {
1285 if(!p_compref1
|| !p_portref1
|| !p_compref2
|| !p_portref2
)
1286 FATAL_ERROR("Statement::Statement()");
1287 config_op
.compref1
=p_compref1
;
1288 config_op
.portref1
=p_portref1
;
1289 config_op
.compref2
=p_compref2
;
1290 config_op
.portref2
=p_portref2
;
1293 FATAL_ERROR("Statement::Statement()");
1294 } // switch statementtype
1297 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
, Value
*p_val
)
1298 : statementtype(p_st
), my_sb(0)
1300 switch(statementtype
) {
1301 case S_TESTCASE_INSTANCE
:
1303 FATAL_ERROR("Statement::Statement()");
1304 testcase_inst
.tcref
=p_ref
;
1305 testcase_inst
.timerval
=p_val
;
1308 FATAL_ERROR("Statement::Statement()");
1309 } // switch statementtype
1312 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
1313 TemplateInstances
*p_ap_list
, Value
*p_val
)
1314 : statementtype(p_st
), my_sb(0)
1316 switch(statementtype
) {
1317 case S_TESTCASE_INSTANCE_REFD
:
1318 if(!p_derefered_value
) FATAL_ERROR("Statement::Statement()");
1319 execute_refd
.value
= p_derefered_value
;
1320 execute_refd
.t_list1
= p_ap_list
;
1321 execute_refd
.timerval
= p_val
;
1324 FATAL_ERROR("Statement::Statement()");
1328 Statement::Statement(statementtype_t p_st
, Value
* p_val
, Reference
* p_ref
)
1329 : statementtype(p_st
), my_sb(0)
1331 switch (statementtype
) {
1334 if (p_val
==NULL
|| p_ref
==NULL
) {
1335 FATAL_ERROR("Statement::Statement()");
1337 convert_op
.val
= p_val
;
1338 convert_op
.ref
= p_ref
;
1341 FATAL_ERROR("Statement::Statement()");
1345 Statement::~Statement()
1350 Statement
*Statement::clone() const
1352 FATAL_ERROR("Statement::clone");
1355 void Statement::dump(unsigned int level
) const
1357 DEBUG(level
, "Statement at %p, a(n) %s", (const void *)this,
1359 switch (statementtype
) {
1360 case S_TESTCASE_INSTANCE
:
1361 case S_TESTCASE_INSTANCE_REFD
: {
1362 Common::Value
*v
= execute_refd
.value
;
1366 def
->dump(level
+ 1);
1369 ass
->dump(level
+ 1);
1372 block
->dump(level
+ 1);
1375 if_stmt
.ics
->dump(level
+ 1);
1376 if (if_stmt
.elseblock
) if_stmt
.elseblock
->dump(level
+ 1);
1383 size_t Statement::get_my_sb_index() const
1385 switch (statementtype
) {
1387 return label
.stmt_idx
;
1389 return go_to
.stmt_idx
;
1391 FATAL_ERROR("Statement::get_my_sb_index()");
1396 const char *Statement::get_stmt_name() const
1398 switch(statementtype
) {
1399 case S_ERROR
: return "<erroneous statement>";
1400 case S_START_UNDEF
: return "start";
1401 case S_STOP_UNDEF
: return "stop";
1402 case S_UNKNOWN_INSTANCE
: return "function or altstep instance";
1403 case S_UNKNOWN_INVOKED
: return "function or altstep type invocation";
1404 case S_DEF
: return "definition";
1405 case S_ASSIGNMENT
: return "assignment";
1406 case S_FUNCTION_INSTANCE
: return "function instance";
1407 case S_FUNCTION_INVOKED
: return "function type invocation";
1408 case S_BLOCK
: return "statement block";
1409 case S_LOG
: return "log";
1410 case S_LABEL
: return "label";
1411 case S_GOTO
: return "goto";
1412 case S_IF
: return "if";
1413 case S_SELECT
: return "select-case";
1414 case S_FOR
: return "for";
1415 case S_WHILE
: return "while";
1416 case S_DOWHILE
: return "do-while";
1417 case S_BREAK
: return "break";
1418 case S_CONTINUE
: return "continue";
1419 case S_STOP_EXEC
: return "stop";
1420 case S_STOP_TESTCASE
: return "testcase.stop";
1421 case S_ALT
: return "alt";
1422 case S_REPEAT
: return "repeat";
1423 case S_INTERLEAVE
: return "interleave";
1424 case S_ALTSTEP_INSTANCE
: return "altstep instance";
1425 case S_ALTSTEP_INVOKED
: return "altstep type invocation";
1426 case S_RETURN
: return "return";
1428 case S_ACTIVATE_REFD
:
1430 case S_DEACTIVATE
: return "deactivate";
1431 case S_SEND
: return "send";
1432 case S_CALL
: return "call";
1433 case S_REPLY
: return "reply";
1434 case S_RAISE
: return "raise";
1435 case S_RECEIVE
: return "receive";
1436 case S_TRIGGER
: return "trigger";
1437 case S_GETCALL
: return "getcall";
1438 case S_GETREPLY
: return "getreply";
1439 case S_CATCH
: return "catch";
1440 case S_CHECK
: return "check";
1441 case S_CHECK_RECEIVE
: return "check-receive";
1442 case S_CHECK_GETCALL
: return "check-getcall";
1443 case S_CHECK_GETREPLY
: return "check-getreply";
1444 case S_CHECK_CATCH
: return "check-catch";
1445 case S_CLEAR
: return "clear";
1446 case S_START_PORT
: return "start port";
1447 case S_STOP_PORT
: return "stop port";
1448 case S_HALT
: return "halt";
1450 case S_START_COMP_REFD
:
1451 return "start test component";
1452 case S_STOP_COMP
: return "stop test component";
1453 case S_DONE
: return "done";
1454 case S_KILL
: return "kill";
1455 case S_KILLED
: return "killed";
1456 case S_CONNECT
: return "connect";
1457 case S_MAP
: return "map";
1458 case S_DISCONNECT
: return "disconnect";
1459 case S_UNMAP
: return "unmap";
1460 case S_START_TIMER
: return "start timer";
1461 case S_STOP_TIMER
: return "stop timer";
1462 case S_TIMEOUT
: return "timeout";
1463 case S_SETVERDICT
: return "setverdict";
1464 case S_ACTION
: return "action";
1465 case S_TESTCASE_INSTANCE
:
1466 case S_TESTCASE_INSTANCE_REFD
:
1468 case S_STRING2TTCN
: return "string2ttcn";
1469 case S_INT2ENUM
: return "int2enum";
1470 case S_START_PROFILER
: return "@profiler.start";
1471 case S_STOP_PROFILER
: return "@profiler.stop";
1473 FATAL_ERROR("Statement::get_stmt_name()");
1475 } // switch statementtype
1478 const Identifier
& Statement::get_labelid() const
1480 switch (statementtype
) {
1486 FATAL_ERROR("Statement::get_labelid()");
1491 bool Statement::label_is_used() const
1493 if (statementtype
!= S_LABEL
) FATAL_ERROR("Statement::label_is_used()");
1497 bool Statement::goto_jumps_forward() const
1499 if (statementtype
!= S_GOTO
) FATAL_ERROR("Statement::goto_jumps_forward()");
1500 return go_to
.jumps_forward
;
1503 const string
& Statement::get_clabel()
1505 if (statementtype
!= S_LABEL
|| !my_sb
)
1506 FATAL_ERROR("Statement::get_clabel()");
1507 if (!label
.clabel
) label
.clabel
=
1508 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
1509 return *label
.clabel
;
1512 Definition
*Statement::get_def() const
1514 if (statementtype
!= S_DEF
) FATAL_ERROR("Statement::get_def()");
1518 AltGuards
*Statement::get_ags() const
1520 if (statementtype
!= S_ALT
&& statementtype
!= S_INTERLEAVE
)
1521 FATAL_ERROR("Statement::get_ags()");
1525 StatementBlock
*Statement::get_block() const
1527 switch (statementtype
) {
1535 FATAL_ERROR("Statement::get_block()");
1540 void Statement::set_my_scope(Scope
*p_scope
)
1542 switch(statementtype
) {
1550 case S_START_PROFILER
:
1551 case S_STOP_PROFILER
:
1555 undefstartstop
.ref
->set_my_scope(p_scope
);
1556 if (undefstartstop
.val
) undefstartstop
.val
->set_my_scope(p_scope
);
1558 case S_UNKNOWN_INSTANCE
:
1559 case S_FUNCTION_INSTANCE
:
1560 case S_ALTSTEP_INSTANCE
:
1562 ref_pard
->set_my_scope(p_scope
);
1565 def
->set_my_scope(p_scope
);
1568 ass
->set_my_scope(p_scope
);
1571 block
->set_my_scope(p_scope
);
1575 case S_STOP_TESTCASE
:
1576 if (logargs
) logargs
->set_my_scope(p_scope
);
1579 if_stmt
.ics
->set_my_scope(p_scope
);
1580 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_scope(p_scope
);
1583 select
.expr
->set_my_scope(p_scope
);
1584 select
.scs
->set_my_scope(p_scope
);
1587 if (loop
.for_stmt
.varinst
) {
1588 loop
.for_stmt
.init_varinst
->set_parent_scope(p_scope
);
1589 loop
.for_stmt
.finalexpr
->set_my_scope(loop
.for_stmt
.init_varinst
);
1590 loop
.for_stmt
.step
->set_my_scope(loop
.for_stmt
.init_varinst
);
1591 loop
.block
->set_my_scope(loop
.for_stmt
.init_varinst
);
1593 loop
.for_stmt
.init_ass
->set_my_scope(p_scope
);
1594 loop
.for_stmt
.finalexpr
->set_my_scope(p_scope
);
1595 loop
.for_stmt
.step
->set_my_scope(p_scope
);
1596 loop
.block
->set_my_scope(p_scope
);
1601 loop
.expr
->set_my_scope(p_scope
);
1602 loop
.block
->set_my_scope(p_scope
);
1606 ags
->set_my_scope(p_scope
);
1609 if (returnexpr
.v
) returnexpr
.v
->set_my_scope(p_scope
);
1610 if (returnexpr
.t
) returnexpr
.t
->set_my_scope(p_scope
);
1613 if (deactivate
) deactivate
->set_my_scope(p_scope
);
1616 port_op
.portref
->set_my_scope(p_scope
);
1617 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1618 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1621 port_op
.portref
->set_my_scope(p_scope
);
1622 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1623 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1624 if(port_op
.s
.call
.timer
) port_op
.s
.call
.timer
->set_my_scope(p_scope
);
1625 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_scope(p_scope
);
1628 port_op
.portref
->set_my_scope(p_scope
);
1629 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1630 if(port_op
.s
.replyval
) port_op
.s
.replyval
->set_my_scope(p_scope
);
1631 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1634 port_op
.portref
->set_my_scope(p_scope
);
1635 port_op
.s
.raise
.signature_ref
->set_my_scope(p_scope
);
1636 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1637 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1640 case S_CHECK_RECEIVE
:
1642 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1643 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1644 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1645 if(port_op
.r
.redirect
.value
)
1646 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1647 if(port_op
.r
.redirect
.sender
)
1648 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1651 case S_CHECK_GETCALL
:
1652 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1653 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1654 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1655 if(port_op
.r
.redirect
.param
)
1656 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1657 if(port_op
.r
.redirect
.sender
)
1658 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1661 case S_CHECK_GETREPLY
:
1662 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1663 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1664 if(port_op
.r
.getreply_valuematch
)
1665 port_op
.r
.getreply_valuematch
->set_my_scope(p_scope
);
1666 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1667 if(port_op
.r
.redirect
.value
)
1668 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1669 if(port_op
.r
.redirect
.param
)
1670 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1671 if(port_op
.r
.redirect
.sender
)
1672 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1676 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1677 if(port_op
.r
.ctch
.signature_ref
)
1678 port_op
.r
.ctch
.signature_ref
->set_my_scope(p_scope
);
1679 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1680 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1681 if(port_op
.r
.redirect
.value
)
1682 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1683 if(port_op
.r
.redirect
.sender
)
1684 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1687 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1688 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1689 if(port_op
.r
.redirect
.sender
)
1690 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1696 if (port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1699 comp_op
.compref
->set_my_scope(p_scope
);
1700 comp_op
.funcinstref
->set_my_scope(p_scope
);
1702 case S_START_COMP_REFD
:
1703 comp_op
.compref
->set_my_scope(p_scope
);
1704 comp_op
.derefered
.value
->set_my_scope(p_scope
);
1705 comp_op
.derefered
.t_list1
->set_my_scope(p_scope
);
1710 if (comp_op
.compref
) comp_op
.compref
->set_my_scope(p_scope
);
1713 if (comp_op
.compref
) {
1714 comp_op
.compref
->set_my_scope(p_scope
);
1715 if (comp_op
.donereturn
.donematch
)
1716 comp_op
.donereturn
.donematch
->set_my_scope(p_scope
);
1717 if (comp_op
.donereturn
.redirect
)
1718 comp_op
.donereturn
.redirect
->set_my_scope(p_scope
);
1725 config_op
.compref1
->set_my_scope(p_scope
);
1726 config_op
.portref1
->set_my_scope(p_scope
);
1727 config_op
.compref2
->set_my_scope(p_scope
);
1728 config_op
.portref2
->set_my_scope(p_scope
);
1731 timer_op
.timerref
->set_my_scope(p_scope
);
1732 if (timer_op
.value
) timer_op
.value
->set_my_scope(p_scope
);
1736 if (timer_op
.timerref
) timer_op
.timerref
->set_my_scope(p_scope
);
1739 setverdict
.verdictval
->set_my_scope(p_scope
);
1740 if (setverdict
.logargs
)
1741 setverdict
.logargs
->set_my_scope(p_scope
);
1743 case S_TESTCASE_INSTANCE
:
1744 testcase_inst
.tcref
->set_my_scope(p_scope
);
1745 if (testcase_inst
.timerval
) testcase_inst
.timerval
->set_my_scope(p_scope
);
1747 case S_TESTCASE_INSTANCE_REFD
:
1748 execute_refd
.value
->set_my_scope(p_scope
);
1749 execute_refd
.t_list1
->set_my_scope(p_scope
);
1750 if(execute_refd
.timerval
) execute_refd
.timerval
->set_my_scope(p_scope
);
1752 case S_ACTIVATE_REFD
:
1753 case S_UNKNOWN_INVOKED
:
1754 case S_FUNCTION_INVOKED
:
1755 case S_ALTSTEP_INVOKED
:
1756 fau_refd
.value
->set_my_scope(p_scope
);
1757 fau_refd
.t_list1
->set_my_scope(p_scope
);
1761 convert_op
.val
->set_my_scope(p_scope
);
1762 convert_op
.ref
->set_my_scope(p_scope
);
1765 FATAL_ERROR("Statement::set_my_scope()");
1766 } // switch statementtype
1769 void Statement::set_fullname(const string
& p_fullname
)
1771 Node::set_fullname(p_fullname
);
1772 switch (statementtype
) {
1780 case S_START_PROFILER
:
1781 case S_STOP_PROFILER
:
1785 undefstartstop
.ref
->set_fullname(p_fullname
+".ref");
1786 if (undefstartstop
.val
)
1787 undefstartstop
.val
->set_fullname(p_fullname
+".val");
1789 case S_UNKNOWN_INSTANCE
:
1790 case S_FUNCTION_INSTANCE
:
1791 case S_ALTSTEP_INSTANCE
:
1793 ref_pard
->set_fullname(p_fullname
+".ref");
1796 def
->set_fullname(p_fullname
+".def");
1799 ass
->set_fullname(p_fullname
+".ass");
1802 block
->set_fullname(p_fullname
+".block");
1806 case S_STOP_TESTCASE
:
1807 if (logargs
) logargs
->set_fullname(p_fullname
+".logargs");
1810 if_stmt
.ics
->set_fullname(p_fullname
+".ifclauses");
1811 if (if_stmt
.elseblock
)
1812 if_stmt
.elseblock
->set_fullname(p_fullname
+".elseblock");
1815 select
.expr
->set_fullname(p_fullname
+".expr");
1816 select
.scs
->set_fullname(p_fullname
+".scs");
1819 if(loop
.for_stmt
.varinst
)
1820 loop
.for_stmt
.init_varinst
->set_fullname(p_fullname
+".init");
1822 loop
.for_stmt
.init_ass
->set_fullname(p_fullname
+".init");
1823 loop
.for_stmt
.finalexpr
->set_fullname(p_fullname
+".final");
1824 loop
.for_stmt
.step
->set_fullname(p_fullname
+".step");
1825 loop
.block
->set_fullname(p_fullname
+".block");
1829 loop
.expr
->set_fullname(p_fullname
+".expr");
1830 loop
.block
->set_fullname(p_fullname
+".block");
1834 ags
->set_fullname(p_fullname
+".ags");
1837 if (returnexpr
.v
) returnexpr
.v
->set_fullname(p_fullname
+".returnexpr");
1838 if (returnexpr
.t
) returnexpr
.t
->set_fullname(p_fullname
+".returnexpr");
1841 if (deactivate
) deactivate
->set_fullname(p_fullname
+".deact");
1844 port_op
.portref
->set_fullname(p_fullname
+".portref");
1845 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1846 if(port_op
.s
.toclause
)
1847 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1850 port_op
.portref
->set_fullname(p_fullname
+".portref");
1851 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1852 if(port_op
.s
.toclause
)
1853 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1854 if(port_op
.s
.call
.timer
)
1855 port_op
.s
.call
.timer
->set_fullname(p_fullname
+".timer");
1856 if(port_op
.s
.call
.body
)
1857 port_op
.s
.call
.body
->set_fullname(p_fullname
+".body");
1860 port_op
.portref
->set_fullname(p_fullname
+".portref");
1861 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1862 if(port_op
.s
.replyval
)
1863 port_op
.s
.replyval
->set_fullname(p_fullname
+".replyval");
1864 if(port_op
.s
.toclause
)
1865 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1868 port_op
.portref
->set_fullname(p_fullname
+".portref");
1869 port_op
.s
.raise
.signature_ref
->set_fullname(p_fullname
+".sign");
1870 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1871 if(port_op
.s
.toclause
)
1872 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1875 case S_CHECK_RECEIVE
:
1877 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1878 if(port_op
.r
.rcvpar
)
1879 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1880 if(port_op
.r
.fromclause
)
1881 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1882 if(port_op
.r
.redirect
.value
)
1883 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1884 if(port_op
.r
.redirect
.sender
)
1885 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1888 case S_CHECK_GETCALL
:
1889 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1890 if(port_op
.r
.rcvpar
)
1891 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1892 if(port_op
.r
.fromclause
)
1893 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1894 if(port_op
.r
.redirect
.param
)
1895 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1896 if(port_op
.r
.redirect
.sender
)
1897 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1900 case S_CHECK_GETREPLY
:
1901 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1902 if(port_op
.r
.rcvpar
)
1903 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1904 if(port_op
.r
.getreply_valuematch
)
1905 port_op
.r
.getreply_valuematch
->set_fullname(p_fullname
+".valmatch");
1906 if(port_op
.r
.fromclause
)
1907 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1908 if(port_op
.r
.redirect
.value
)
1909 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1910 if(port_op
.r
.redirect
.param
)
1911 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1912 if(port_op
.r
.redirect
.sender
)
1913 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1917 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1918 if(port_op
.r
.ctch
.signature_ref
)
1919 port_op
.r
.ctch
.signature_ref
->set_fullname(p_fullname
+".sign");
1920 if(port_op
.r
.rcvpar
)
1921 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1922 if(port_op
.r
.fromclause
)
1923 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1924 if(port_op
.r
.redirect
.value
)
1925 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1926 if(port_op
.r
.redirect
.sender
)
1927 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1930 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1931 if(port_op
.r
.fromclause
)
1932 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1933 if(port_op
.r
.redirect
.sender
)
1934 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1940 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1943 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1944 comp_op
.funcinstref
->set_fullname(p_fullname
+".funcref");
1946 case S_START_COMP_REFD
:
1947 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1948 comp_op
.derefered
.value
->set_fullname(p_fullname
+".funcref");
1949 comp_op
.derefered
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1954 if (comp_op
.compref
) comp_op
.compref
->set_fullname(p_fullname
+".compref");
1957 if(comp_op
.compref
) {
1958 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1959 if(comp_op
.donereturn
.donematch
)
1960 comp_op
.donereturn
.donematch
->set_fullname(p_fullname
+".donematch");
1961 if(comp_op
.donereturn
.redirect
)
1962 comp_op
.donereturn
.redirect
->set_fullname(p_fullname
+".redir");
1969 config_op
.compref1
->set_fullname(p_fullname
+".compref1");
1970 config_op
.portref1
->set_fullname(p_fullname
+".portref1");
1971 config_op
.compref2
->set_fullname(p_fullname
+".compref2");
1972 config_op
.portref2
->set_fullname(p_fullname
+".portref2");
1975 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1976 if(timer_op
.value
) timer_op
.value
->set_fullname(p_fullname
+".timerval");
1980 if (timer_op
.timerref
)
1981 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1984 setverdict
.verdictval
->set_fullname(p_fullname
+".verdictval");
1985 if (setverdict
.logargs
)
1986 setverdict
.logargs
->set_fullname(p_fullname
+".verdictreason");
1988 case S_TESTCASE_INSTANCE
:
1989 testcase_inst
.tcref
->set_fullname(p_fullname
+".tcref");
1990 if (testcase_inst
.timerval
)
1991 testcase_inst
.timerval
->set_fullname(p_fullname
+".timerval");
1993 case S_TESTCASE_INSTANCE_REFD
:
1994 execute_refd
.value
->set_fullname(p_fullname
+".tcref");
1995 execute_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1996 if(execute_refd
.timerval
)
1997 execute_refd
.timerval
->set_fullname(p_fullname
+".timerval");
1999 case S_ACTIVATE_REFD
:
2000 case S_UNKNOWN_INVOKED
:
2001 case S_FUNCTION_INVOKED
:
2002 case S_ALTSTEP_INVOKED
:
2003 fau_refd
.value
->set_fullname(p_fullname
+".ref");
2004 fau_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
2008 convert_op
.val
->set_fullname(p_fullname
+".ti");
2009 convert_op
.ref
->set_fullname(p_fullname
+".ref");
2012 FATAL_ERROR("Statement::set_fullname()");
2013 } // switch statementtype
2016 void Statement::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
2019 switch(statementtype
) {
2021 block
->set_my_sb(p_sb
, p_index
);
2024 label
.stmt_idx
= p_index
;
2027 go_to
.stmt_idx
= p_index
;
2030 if_stmt
.ics
->set_my_sb(p_sb
, p_index
);
2031 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_sb(p_sb
, p_index
);
2034 select
.scs
->set_my_sb(p_sb
, p_index
);
2039 loop
.block
->set_my_sb(p_sb
, p_index
);
2043 ags
->set_my_sb(p_sb
, p_index
);
2046 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_sb(p_sb
, p_index
);
2050 } // switch statementtype
2053 void Statement::set_my_def(Definition
*p_def
)
2055 switch (statementtype
) {
2057 block
->set_my_def(p_def
);
2060 if_stmt
.ics
->set_my_def(p_def
);
2061 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_def(p_def
);
2064 select
.scs
->set_my_def(p_def
);
2069 loop
.block
->set_my_def(p_def
);
2073 ags
->set_my_def(p_def
);
2076 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_def(p_def
);
2080 } // switch statementtype
2083 void Statement::set_my_ags(AltGuards
*p_ags
)
2085 switch (statementtype
) {
2087 block
->set_my_ags(p_ags
);
2090 if_stmt
.ics
->set_my_ags(p_ags
);
2091 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_ags(p_ags
);
2094 select
.scs
->set_my_ags(p_ags
);
2099 loop
.block
->set_my_ags(p_ags
);
2106 } // switch statementtype
2109 void Statement::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
2111 switch (statementtype
) {
2113 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2116 if_stmt
.ics
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2117 if (if_stmt
.elseblock
)
2118 if_stmt
.elseblock
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2121 select
.scs
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2126 ags
->set_my_laic_stmt(0, p_loop_stmt
); // ags is set later
2129 if (p_loop_stmt
&& port_op
.s
.call
.body
)
2130 port_op
.s
.call
.body
->set_my_laic_stmt(0, p_loop_stmt
);
2136 brk_cnt
.loop_stmt
=p_loop_stmt
;
2141 } // switch statementtype
2144 /** \todo handle blocks, loops and conditional statements
2145 * (i.e. investigate their last statements within the block) */
2146 bool Statement::is_terminating() const
2148 switch (statementtype
) {
2153 case S_STOP_TESTCASE
:
2159 // checking for self.stop, self.kill, mtc.stop and mtc.kill
2160 if (comp_op
.compref
) {
2161 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
2162 if (v_last
->get_valuetype() == Value::V_EXPR
) {
2163 switch (v_last
->get_optype()) {
2164 case Value::OPTYPE_COMP_SELF
:
2165 case Value::OPTYPE_COMP_MTC
:
2175 if(!loop
.expr
->is_unfoldable() && loop
.expr
->get_val_bool()) {
2176 return !loop
.has_brk
; // not endless loop if it has a break
2184 StatementBlock::returnstatus_t
Statement::has_return() const
2186 switch (statementtype
) {
2188 return block
->has_return();
2190 return if_stmt
.ics
->has_return(if_stmt
.elseblock
);
2192 return select
.scs
->has_return();
2195 if (loop
.block
->has_return() == StatementBlock::RS_NO
)
2196 return StatementBlock::RS_NO
;
2197 else return StatementBlock::RS_MAYBE
;
2199 return loop
.block
->has_return();
2201 StatementBlock::returnstatus_t ret_val
= ags
->has_return();
2202 if (ret_val
== StatementBlock::RS_YES
&& !ags
->has_else()) {
2203 // the invoked defaults may skip the entire statement
2204 ret_val
= StatementBlock::RS_MAYBE
;
2208 if (port_op
.s
.call
.body
) return port_op
.s
.call
.body
->has_return();
2209 else return StatementBlock::RS_NO
;
2211 if (is_terminating()) return StatementBlock::RS_YES
;
2212 else return StatementBlock::RS_NO
;
2216 bool Statement::is_receiving_stmt() const
2218 switch (statementtype
) {
2221 case S_ALTSTEP_INSTANCE
:
2222 case S_ALTSTEP_INVOKED
:
2224 case S_CHECK_RECEIVE
:
2227 case S_CHECK_GETCALL
:
2229 case S_CHECK_GETREPLY
:
2239 } // switch statementtype
2242 bool Statement::has_receiving_stmt() const
2244 switch (statementtype
) {
2247 case S_FUNCTION_INSTANCE
:
2248 case S_FUNCTION_INVOKED
:
2257 case S_STOP_TESTCASE
:
2261 case S_ACTIVATE_REFD
:
2271 case S_START_COMP_REFD
:
2281 case S_TESTCASE_INSTANCE
:
2282 case S_TESTCASE_INSTANCE_REFD
:
2283 case S_START_PROFILER
:
2284 case S_STOP_PROFILER
:
2289 case S_ALTSTEP_INSTANCE
:
2290 case S_ALTSTEP_INVOKED
:
2292 case S_CHECK_RECEIVE
:
2295 case S_CHECK_GETCALL
:
2297 case S_CHECK_GETREPLY
:
2306 return block
->has_receiving_stmt();
2308 return if_stmt
.ics
->has_receiving_stmt()
2309 || (if_stmt
.elseblock
&& if_stmt
.elseblock
->has_receiving_stmt());
2311 return select
.scs
->has_receiving_stmt();
2315 return loop
.block
->has_receiving_stmt();
2317 return port_op
.s
.call
.body
&& port_op
.s
.call
.body
->has_receiving_stmt();
2321 case S_UNKNOWN_INSTANCE
:
2322 case S_UNKNOWN_INVOKED
:
2324 FATAL_ERROR("Statement::has_receiving_stmt()");
2325 } // switch statementtype
2328 bool Statement::can_repeat() const
2330 switch (statementtype
) {
2336 case S_CHECK_RECEIVE
:
2338 case S_CHECK_GETCALL
:
2340 case S_CHECK_GETREPLY
:
2347 FATAL_ERROR("Statement::can_repeat()");
2348 } // switch statementtype
2351 void Statement::chk()
2353 switch (statementtype
) {
2362 case S_UNKNOWN_INSTANCE
:
2363 chk_unknown_instance();
2365 case S_UNKNOWN_INVOKED
:
2366 case S_FUNCTION_INVOKED
:
2367 case S_ALTSTEP_INVOKED
:
2368 chk_unknown_invoke();
2372 my_sb
->register_def(def
);
2377 case S_FUNCTION_INSTANCE
:
2385 case S_STOP_TESTCASE
:
2386 chk_log_action(logargs
);
2427 case S_ALTSTEP_INSTANCE
:
2436 case S_ACTIVATE_REFD
:
2437 chk_activate_refd();
2455 case S_CHECK_RECEIVE
:
2460 case S_CHECK_GETCALL
:
2464 case S_CHECK_GETREPLY
:
2480 chk_start_stop_port();
2485 case S_START_COMP_REFD
:
2486 chk_start_comp_refd();
2490 chk_stop_kill_comp();
2511 chk_stop_timer_timeout();
2515 chk_log_action(setverdict
.logargs
); // for checking verdictreason
2517 case S_TESTCASE_INSTANCE
:
2520 case S_TESTCASE_INSTANCE_REFD
:
2529 case S_START_PROFILER
:
2530 case S_STOP_PROFILER
:
2534 FATAL_ERROR("Statement::chk()");
2535 } // switch statementtype
2538 void Statement::chk_string2ttcn()
2540 Error_Context
cntxt(this, "In string2ttcn() statement");
2541 convert_op
.val
->chk_expr_type(Type::T_CSTR
, "charstring", Type::EXPECTED_DYNAMIC_VALUE
);
2543 Common::Assignment
* refd_ass
= convert_op
.ref
->get_refd_assignment();
2544 if (refd_ass
==NULL
) {
2545 error("Could not determine the assignment for second parameter");
2548 switch (refd_ass
->get_asstype()) {
2549 case Definition::A_PAR_VAL_IN
:
2550 case Definition::A_PAR_TEMPL_IN
:
2551 refd_ass
->use_as_lvalue(*convert_op
.ref
);
2552 case Definition::A_VAR
:
2553 case Definition::A_VAR_TEMPLATE
:
2554 case Definition::A_PAR_VAL_OUT
:
2555 case Definition::A_PAR_VAL_INOUT
:
2556 case Definition::A_PAR_TEMPL_OUT
:
2557 case Definition::A_PAR_TEMPL_INOUT
:
2558 // valid assignment types
2561 convert_op
.ref
->error("Reference to '%s' cannot be used as the second parameter", refd_ass
->get_assname());
2566 delete convert_op
.val
;
2567 delete convert_op
.ref
;
2568 statementtype
= S_ERROR
;
2571 void Statement::chk_int2enum()
2573 Error_Context
cntxt(this, "In int2enum() statement");
2574 convert_op
.val
->chk_expr_type(Type::T_INT
, "integer", Type::EXPECTED_DYNAMIC_VALUE
);
2576 Common::Assignment
* refd_ass
= convert_op
.ref
->get_refd_assignment();
2577 if (refd_ass
==NULL
) {
2578 error("Could not determine the assignment for second parameter");
2581 if (Type::T_ENUM_T
!= convert_op
.ref
->chk_variable_ref()->get_type_refd_last()->get_typetype_ttcn3()) {
2582 convert_op
.ref
->error("A reference to variable or value parameter of "
2583 "type enumerated was expected");
2588 delete convert_op
.val
;
2589 delete convert_op
.ref
;
2590 statementtype
= S_ERROR
;
2593 void Statement::chk_allowed_interleave()
2595 switch (statementtype
) {
2597 block
->chk_allowed_interleave();
2600 error("Label statement is not allowed within an interleave statement");
2603 error("Goto statement is not allowed within an interleave statement");
2606 if_stmt
.ics
->chk_allowed_interleave();
2607 if (if_stmt
.elseblock
) if_stmt
.elseblock
->chk_allowed_interleave();
2610 select
.scs
->chk_allowed_interleave();
2615 loop
.block
->chk_allowed_interleave();
2618 ags
->chk_allowed_interleave();
2621 error("Repeat statement is not allowed within an interleave statement");
2623 case S_ALTSTEP_INSTANCE
:
2624 error("Invocation of an altstep is not allowed within an interleave "
2627 case S_ALTSTEP_INVOKED
:
2628 error("Invocation of an altstep type is not allowed within an interleave"
2632 error("Return statement is not allowed within an interleave statement");
2635 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->chk_allowed_interleave();
2638 // the other statements are allowed
2643 void Statement::chk_start_undef()
2645 Ref_base
*t_ref
= undefstartstop
.ref
;
2646 Value
*t_val
= undefstartstop
.val
;
2647 Common::Assignment
*t_ass
;
2649 Error_Context
cntxt(this, "In start statement");
2650 t_ass
= t_ref
->get_refd_assignment();
2652 if (!t_ass
) goto error
;
2653 switch (t_ass
->get_asstype()) {
2654 case Definition::A_PORT
:
2655 case Definition::A_PAR_PORT
:
2656 statementtype
= S_START_PORT
;
2657 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2658 if (!port_op
.portref
) goto error
;
2660 t_val
->error("Start port operation cannot have argument");
2663 chk_start_stop_port();
2665 case Definition::A_TIMER
:
2666 case Definition::A_PAR_TIMER
:
2667 statementtype
= S_START_TIMER
;
2668 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2669 if (!timer_op
.timerref
) goto error
;
2670 timer_op
.value
= t_val
;
2673 case Definition::A_CONST
:
2674 case Definition::A_EXT_CONST
:
2675 case Definition::A_MODULEPAR
:
2676 case Definition::A_VAR
:
2677 case Definition::A_FUNCTION_RVAL
:
2678 case Definition::A_EXT_FUNCTION_RVAL
:
2679 case Definition::A_PAR_VAL_IN
:
2680 case Definition::A_PAR_VAL_OUT
:
2681 case Definition::A_PAR_VAL_INOUT
:
2682 statementtype
= S_START_COMP
;
2684 error("The argument of start operation is missing, although it cannot "
2685 "be a start timer or start port operation");
2687 } else if (t_val
->get_valuetype() != Value::V_REFD
) {
2688 t_val
->error("The argument of start operation is not a function, "
2689 "although it cannot be a start timer or start port operation");
2692 comp_op
.funcinstref
= t_val
->steal_ttcn_ref_base();
2695 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2696 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2697 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2698 comp_op
.compref
->set_location(*t_ref
);
2702 t_ref
->error("Port, timer or component reference was expected as the "
2703 "operand of start operation instead of %s",
2704 t_ass
->get_description().c_str());
2711 statementtype
= S_ERROR
;
2714 void Statement::chk_stop_undef()
2716 Ref_base
*t_ref
= undefstartstop
.ref
;
2717 Common::Assignment
*t_ass
;
2719 Error_Context
cntxt(this, "In stop statement");
2720 t_ass
= t_ref
->get_refd_assignment();
2722 if (!t_ass
) goto error
;
2723 // Determine what it is that we are trying to stop; change statementtype
2724 switch (t_ass
->get_asstype()) {
2725 case Definition::A_PORT
:
2726 case Definition::A_PAR_PORT
:
2727 statementtype
= S_STOP_PORT
;
2728 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2729 if (!port_op
.portref
) goto error
;
2730 chk_start_stop_port();
2732 case Definition::A_TIMER
:
2733 case Definition::A_PAR_TIMER
:
2734 statementtype
= S_STOP_TIMER
;
2735 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2736 if (!timer_op
.timerref
) goto error
;
2738 chk_stop_timer_timeout();
2740 case Definition::A_CONST
:
2741 case Definition::A_EXT_CONST
:
2742 case Definition::A_MODULEPAR
:
2743 case Definition::A_VAR
:
2744 case Definition::A_FUNCTION_RVAL
:
2745 case Definition::A_EXT_FUNCTION_RVAL
:
2746 case Definition::A_PAR_VAL_IN
:
2747 case Definition::A_PAR_VAL_OUT
:
2748 case Definition::A_PAR_VAL_INOUT
:
2749 statementtype
= S_STOP_COMP
;
2750 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2751 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2752 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2753 comp_op
.compref
->set_location(*t_ref
);
2754 chk_stop_kill_comp();
2757 t_ref
->error("Port, timer or component reference was expected as the "
2758 "operand of stop operation instead of %s",
2759 t_ass
->get_description().c_str());
2765 statementtype
= S_ERROR
;
2768 void Statement::chk_unknown_instance()
2770 Common::Assignment
*t_ass
;
2772 Error_Context
cntxt(this, "In function or altstep instance");
2773 t_ass
= ref_pard
->get_refd_assignment(false);
2775 if (!t_ass
) goto error
;
2776 switch (t_ass
->get_asstype()) {
2777 case Common::Assignment::A_FUNCTION
:
2778 case Common::Assignment::A_FUNCTION_RVAL
:
2779 case Common::Assignment::A_FUNCTION_RTEMP
:
2780 case Common::Assignment::A_EXT_FUNCTION
:
2781 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2782 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2783 statementtype
= S_FUNCTION_INSTANCE
;
2786 case Common::Assignment::A_ALTSTEP
:
2787 statementtype
= S_ALTSTEP_INSTANCE
;
2791 ref_pard
->error("Reference to a function or altstep was expected "
2792 "instead of %s, which cannot be invoked",
2793 t_ass
->get_description().c_str());
2799 statementtype
= S_ERROR
;
2802 void Statement::chk_unknown_invoke()
2804 Error_Context
cntxt(this, "In apply operation");
2805 Type
*t
= fau_refd
.value
->get_expr_governor_last();
2807 switch (t
->get_typetype()) {
2810 case Type::T_FUNCTION
:
2811 statementtype
= S_FUNCTION_INVOKED
;
2812 if (t
->get_function_return_type()) warning("The value returned by "
2813 "function type `%s' is not used", t
->get_typename().c_str());
2815 case Type::T_ALTSTEP
:
2816 statementtype
= S_ALTSTEP_INVOKED
;
2819 fau_refd
.value
->error("A value of type function or altstep was "
2820 "expected instead of `%s'", t
->get_typename().c_str());
2823 my_sb
->chk_runs_on_clause(t
, *this, "call");
2825 ActualParList
*parlist
= new Ttcn::ActualParList
;
2826 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
2827 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
2829 delete fau_refd
.t_list1
;
2832 fau_refd
.ap_list2
= 0;
2834 parlist
->set_fullname(get_fullname());
2835 parlist
->set_my_scope(my_sb
);
2836 fau_refd
.ap_list2
= parlist
;
2842 statementtype
= S_ERROR
;
2845 void Statement::chk_assignment()
2847 Error_Context
cntxt(this, "In variable assignment");
2851 void Statement::chk_function()
2853 Error_Context
cntxt(this, "In function instance");
2854 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
2855 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
2856 if (t_ass
->get_Type())
2857 ref_pard
->warning("The value returned by %s is not used",
2858 t_ass
->get_description().c_str());
2861 void Statement::chk_block()
2863 Error_Context
cntxt(this, "In statement block");
2867 void Statement::chk_log_action(LogArguments
*lga
)
2869 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
2872 if (!semantic_check_only
) lga
->join_strings();
2876 void Statement::chk_goto()
2878 Error_Context
cntxt(this, "In goto statement");
2879 if (!my_sb
->has_label(*go_to
.id
)) {
2880 error("Label `%s' is used, but not defined",
2881 go_to
.id
->get_dispname().c_str());
2883 go_to
.jumps_forward
= false;
2886 Statement
*label_stmt
= my_sb
->get_label(*go_to
.id
);
2887 label_stmt
->label
.used
= true;
2888 StatementBlock
*label_sb
= label_stmt
->get_my_sb();
2889 // the index of the label in its own statement block
2890 size_t label_idx
= label_stmt
->get_my_sb_index();
2891 // the index of the goto statement (or its parent statement) in the
2892 // statement block of the label
2894 if (my_sb
== label_sb
) goto_idx
= go_to
.stmt_idx
;
2896 // the goto statement is within a nested statement block
2897 StatementBlock
*goto_sb
= my_sb
, *parent_sb
= my_sb
->get_my_sb();
2898 while (parent_sb
!= label_sb
) {
2899 // go up until the block of the label is found
2900 if (!parent_sb
) FATAL_ERROR("Statement::chk_goto()");
2901 goto_sb
= parent_sb
;
2902 parent_sb
= parent_sb
->get_my_sb();
2904 goto_idx
= goto_sb
->get_my_sb_index();
2906 if (label_idx
> goto_idx
) {
2907 bool error_flag
= false;
2908 for (size_t i
= goto_idx
+ 1; i
< label_idx
; i
++) {
2909 Statement
*stmt
= label_sb
->get_stmt_byIndex(i
);
2910 if (stmt
->get_statementtype() != S_DEF
) continue;
2912 error("Jump to label `%s' crosses local definition",
2913 go_to
.id
->get_dispname().c_str());
2916 stmt
->note("Definition of %s is here",
2917 stmt
->get_def()->get_description().c_str());
2920 label_stmt
->note("Label `%s' is here",
2921 go_to
.id
->get_dispname().c_str());
2922 go_to
.jumps_forward
= true;
2923 } else go_to
.jumps_forward
= false;
2924 go_to
.label
= label_stmt
;
2927 void Statement::chk_if()
2930 if_stmt
.ics
->chk(unreach
);
2931 if(if_stmt
.elseblock
) {
2932 Error_Context
cntxt(if_stmt
.elseblock_location
, "In else statement");
2933 if(unreach
) if_stmt
.elseblock_location
->warning
2934 ("Control never reaches this code because of previous effective"
2936 if_stmt
.elseblock
->chk();
2941 void Statement::chk_select()
2943 Error_Context
cntxt(this, "In select case statement");
2945 for(int turn
=0; turn
<2; turn
++) {
2946 if(turn
) select
.expr
->set_lowerid_to_ref();
2947 Type::typetype_t tt
=select
.expr
->get_expr_returntype();
2948 t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2949 if(!t_gov
|| tt
==Type::T_ERROR
) {
2950 SelectCases
*scs
=select
.scs
;
2951 for(size_t i
=0; i
<scs
->get_nof_scs(); i
++) {
2952 TemplateInstances
*tis
=scs
->get_sc_byIndex(i
)->get_tis();
2954 for(size_t j
=0; j
<tis
->get_nof_tis(); j
++) {
2955 TemplateInstance
*ti
=tis
->get_ti_byIndex(j
);
2956 if(turn
) ti
->get_Template()->set_lowerid_to_ref();
2957 t_gov
=ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
2958 tt
=ti
->get_expr_returntype(Type::EXPECTED_TEMPLATE
);
2959 if(t_gov
&& tt
!=Type::T_ERROR
) break;
2964 else t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2967 select
.expr
->error("Cannot determine the type of the expression");
2968 t_gov
=Type::get_pooltype(Type::T_ERROR
);
2970 select
.expr
->set_my_governor(t_gov
);
2971 t_gov
->chk_this_value_ref(select
.expr
);
2972 t_gov
->chk_this_value(select
.expr
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
2973 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2974 select
.scs
->chk(t_gov
);
2977 void Statement::chk_for()
2979 Error_Context
cntxt(this, "In for statement");
2980 if (loop
.for_stmt
.varinst
) loop
.for_stmt
.init_varinst
->chk_for();
2981 else loop
.for_stmt
.init_ass
->chk();
2982 loop
.for_stmt
.finalexpr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2983 if(!loop
.for_stmt
.finalexpr
->is_unfoldable()
2984 && !loop
.for_stmt
.finalexpr
->get_val_bool())
2985 loop
.for_stmt
.finalexpr
->warning
2986 ("Control never reaches this code because the"
2987 " final conditional expression evals to false");
2988 loop
.for_stmt
.step
->chk();
2989 loop
.block
->set_my_laic_stmt(0, this);
2993 void Statement::chk_while()
2995 Error_Context
cntxt(this, "In while statement");
2996 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2997 if(!loop
.expr
->is_unfoldable() && !loop
.expr
->get_val_bool())
2998 loop
.expr
->warning("Control never reaches this code because the"
2999 " conditional expression evals to false");
3000 loop
.block
->set_my_laic_stmt(0, this);
3004 void Statement::chk_do_while()
3006 Error_Context
cntxt(this, "In do-while statement");
3007 loop
.block
->set_my_laic_stmt(0, this);
3009 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
3012 void Statement::chk_break()
3014 Error_Context
cntxt(this, "In break statement");
3015 if (!brk_cnt
.loop_stmt
&& !brk_cnt
.ags
)
3016 error("Break statement cannot be used outside loops, alt or interleave"
3017 " statements, altsteps or response and exception handling part of call"
3019 if (brk_cnt
.loop_stmt
)
3020 brk_cnt
.loop_stmt
->loop
.has_brk
=true;
3023 void Statement::chk_continue()
3025 Error_Context
cntxt(this, "In continue statement");
3026 if (brk_cnt
.loop_stmt
) {
3027 brk_cnt
.loop_stmt
->loop
.has_cnt
=true;
3028 if (brk_cnt
.ags
) brk_cnt
.loop_stmt
->loop
.has_cnt_in_ags
=true;
3030 error("Continue statement cannot be used outside loops");
3033 void Statement::chk_alt()
3035 Error_Context
cntxt(this, "In alt construct");
3036 ags
->set_my_ags(ags
);
3037 ags
->set_my_laic_stmt(ags
, 0);
3041 void Statement::chk_repeat()
3043 Error_Context
cntxt(this, "In repeat statement");
3044 if (ags
) ags
->repeat_found();
3045 else error("Repeat statement cannot be used outside alt statements, "
3046 "altsteps or response and exception handling part of call operations");
3049 void Statement::chk_interleave()
3051 Error_Context
cntxt(this, "In interleave statement");
3052 ags
->set_my_laic_stmt(ags
, 0);
3054 ags
->chk_allowed_interleave();
3057 void Statement::chk_altstep()
3059 Error_Context
cntxt(this, "In altstep instance");
3060 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
3061 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
3064 void Statement::chk_return()
3066 Error_Context
cntxt(this, "In return statement");
3067 Definition
*my_def
= my_sb
->get_my_def();
3069 error("Return statement cannot be used in the control part. "
3070 "It is allowed only in functions and altsteps");
3073 switch (my_def
->get_asstype()) {
3074 case Definition::A_FUNCTION
:
3076 returnexpr
.t
->error("Unexpected return value. The function does not "
3077 "have return type");
3081 case Definition::A_FUNCTION_RVAL
:
3082 if (!returnexpr
.t
) {
3083 error("Missing return value. The function should return a value of "
3084 "type `%s'", my_def
->get_Type()->get_typename().c_str());
3086 } else if (!returnexpr
.t
->is_Value()) {
3087 returnexpr
.t
->error("A specific value without matching symbols was "
3088 "expected as return value");
3091 returnexpr
.v
= returnexpr
.t
->get_Value();
3092 delete returnexpr
.t
;
3094 Type
*return_type
= my_def
->get_Type();
3095 returnexpr
.v
->set_my_governor(return_type
);
3096 return_type
->chk_this_value_ref(returnexpr
.v
);
3097 return_type
->chk_this_value(returnexpr
.v
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
3098 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
3101 case Definition::A_FUNCTION_RTEMP
:
3102 if (!returnexpr
.t
) {
3103 error("Missing return template. The function should return a template "
3104 "of type `%s'", my_def
->get_Type()->get_typename().c_str());
3107 Type
*return_type
= my_def
->get_Type();
3108 returnexpr
.t
->set_my_governor(return_type
);
3109 return_type
->chk_this_template_ref(returnexpr
.t
);
3110 return_type
->chk_this_template_generic(returnexpr
.t
, INCOMPLETE_NOT_ALLOWED
,
3111 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
3112 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
3113 if (!dfb
) FATAL_ERROR("Statement::chk_return()");
3114 returnexpr
.gen_restriction_check
=
3115 returnexpr
.t
->chk_restriction("return template",
3116 dfb
->get_template_restriction(), this);
3119 case Definition::A_ALTSTEP
:
3121 returnexpr
.t
->error("An altstep cannot return a value");
3126 error("Return statement cannot be used in a %s. It is allowed only in "
3127 "functions and altsteps", my_def
->get_assname());
3132 delete returnexpr
.t
;
3136 void Statement::chk_activate()
3138 Error_Context
cntxt(this, "In activate statement");
3139 if (!ref_pard
->chk_activate_argument()) {
3141 statementtype
= S_ERROR
;
3145 void Statement::chk_activate_refd()
3147 Error_Context
cntxt(this, "In activate statement");
3148 Type
*t
= fau_refd
.value
->get_expr_governor_last();
3150 switch (t
->get_typetype()) {
3153 case Type::T_ALTSTEP
:
3156 fau_refd
.value
->error("A value of type altstep was expected in the "
3157 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
3160 if (t
->get_fat_runs_on_self()) {
3161 fau_refd
.value
->error("The argument of `derefers()' cannot be an altstep "
3162 "reference with 'runs on self' clause");
3165 my_sb
->chk_runs_on_clause(t
, *this, "activate");
3167 ActualParList
*parlist
= new ActualParList
;
3168 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
3169 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
3171 delete fau_refd
.t_list1
;
3174 fau_refd
.ap_list2
= 0;
3177 parlist
->set_fullname(get_fullname());
3178 parlist
->set_my_scope(my_sb
);
3179 fau_refd
.ap_list2
= parlist
;
3180 if (!fp_list
->chk_activate_argument(parlist
,get_fullname().c_str()))
3187 statementtype
= S_ERROR
;
3190 void Statement::chk_deactivate()
3193 Error_Context
cntxt(this, "In deactivate statement");
3194 deactivate
->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE
);
3198 void Statement::chk_send()
3200 Error_Context
cntxt(this, "In send statement");
3201 // checking the port reference
3202 Type
*port_type
= chk_port_ref(port_op
.portref
);
3203 // determining the message type
3205 bool msg_type_determined
= false;
3207 Ttcn::PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3208 TypeSet
*out_msgs
= port_type_body
->get_out_msgs();
3210 if (out_msgs
->get_nof_types() == 1) {
3211 // there is only one outgoing message type
3212 msg_type
= out_msgs
->get_type_byIndex(0);
3214 // there are more than one outgoing message types
3215 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3217 size_t nof_comp_types
=
3218 out_msgs
->get_nof_compatible_types(msg_type
);
3219 if (nof_comp_types
== 0) {
3220 port_op
.s
.sendpar
->error("Message type `%s' is not present on "
3221 "the outgoing list of port type `%s'",
3222 msg_type
->get_typename().c_str(),
3223 port_type
->get_typename().c_str());
3224 } else if (nof_comp_types
> 1) {
3225 port_op
.s
.sendpar
->error("Type of the message is ambiguous: "
3226 "`%s' is compatible with more than one outgoing message types "
3227 "of port type `%s'", msg_type
->get_typename().c_str(),
3228 port_type
->get_typename().c_str());
3231 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3232 "outgoing message");
3235 msg_type_determined
= true;
3236 } else if (port_type_body
->get_operation_mode() ==
3237 PortTypeBody::PO_PROCEDURE
) {
3238 port_op
.portref
->error("Message-based operation `send' is not "
3239 "applicable to a procedure-based port of type `%s'",
3240 port_type
->get_typename().c_str());
3242 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3243 "message types", port_type
->get_typename().c_str());
3246 // determining the message type if it is not done so far
3247 if (!msg_type_determined
) {
3248 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3250 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3251 // checking the parameter (template instance)
3252 port_op
.s
.sendpar
->chk(msg_type
);
3253 // checking for invalid message types
3254 msg_type
= msg_type
->get_type_refd_last();
3255 switch (msg_type
->get_typetype()) {
3256 case Type::T_SIGNATURE
:
3257 port_op
.s
.sendpar
->error("The type of send parameter is signature `%s', "
3258 "which cannot be a message type", msg_type
->get_typename().c_str());
3261 port_op
.s
.sendpar
->error("The type of send parameter is port type `%s', "
3262 "which cannot be a message type", msg_type
->get_typename().c_str());
3264 case Type::T_DEFAULT
:
3265 port_op
.s
.sendpar
->error("The type of send parameter is the `default' "
3266 "type, which cannot be a message type");
3270 // checking for presence of wildcards in the template body
3271 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3272 // checking to clause
3273 chk_to_clause(port_type
);
3276 void Statement::chk_call()
3278 Error_Context
cntxt(this, "In call statement");
3279 // checking the port reference
3280 Type
*port_type
= chk_port_ref(port_op
.portref
);
3281 // determining the signature of the argument
3282 Type
*signature
= 0;
3283 bool signature_determined
= false;
3285 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3286 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3288 if (out_sigs
->get_nof_types() == 1) {
3289 // there is only one outgoing signature
3290 signature
= out_sigs
->get_type_byIndex(0);
3292 // there are more than one outgoing signatures
3293 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3295 if (!out_sigs
->has_type(signature
)) {
3296 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3297 "outgoing list of port type `%s'",
3298 signature
->get_typename().c_str(),
3299 port_type
->get_typename().c_str());
3302 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3306 signature_determined
= true;
3307 } else if (port_type_body
->get_operation_mode() ==
3308 PortTypeBody::PO_MESSAGE
) {
3309 port_op
.portref
->error("Procedure-based operation `call' is not "
3310 "applicable to a message-based port of type `%s'",
3311 port_type
->get_typename().c_str());
3313 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3314 "signatures", port_type
->get_typename().c_str());
3317 if (!signature_determined
)
3318 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3319 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3320 // checking the parameter (template instance)
3321 port_op
.s
.sendpar
->chk(signature
);
3322 signature
= signature
->get_type_refd_last();
3323 bool is_noblock_sig
= false;
3324 Type::typetype_t tt
= signature
->get_typetype();
3326 case Type::T_SIGNATURE
:
3327 // the signature is known and correct
3328 is_noblock_sig
= signature
->is_nonblocking_signature();
3332 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not "
3333 "a signature", signature
->get_typename().c_str());
3335 // checking presence/absence of optional parts
3336 if (is_noblock_sig
) {
3337 if (port_op
.s
.call
.timer
) {
3338 port_op
.s
.call
.timer
->error("A call of non-blocking signature `%s' "
3339 "cannot have call timer", signature
->get_typename().c_str());
3340 } else if (port_op
.s
.call
.nowait
) {
3341 error("A call of non-blocking signature `%s' cannot use the "
3342 "`nowait' keyword", signature
->get_typename().c_str());
3344 if (port_op
.s
.call
.body
) {
3345 error("A call of non-blocking signature `%s' cannot have "
3346 "response and exception handling part",
3347 signature
->get_typename().c_str());
3349 } else if (port_op
.s
.call
.nowait
) {
3350 if (port_op
.s
.call
.body
) {
3351 error("A call with `nowait' keyword cannot have response and "
3352 "exception handling part");
3355 // do not issue any error if the signature is erroneous
3356 // because it could have been a non-blocking one
3357 if (tt
== Type::T_SIGNATURE
&& !port_op
.s
.call
.body
) {
3358 error("Response and exception handling part is missing from "
3359 "blocking call operation");
3362 // checking call timer
3363 if (port_op
.s
.call
.timer
) {
3364 Error_Context
cntxt2(port_op
.s
.call
.timer
, "In call timer value");
3365 port_op
.s
.call
.timer
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
3366 Value
*t_val
= port_op
.s
.call
.timer
->get_value_refd_last();
3367 if (t_val
->get_valuetype() == Value::V_REAL
) {
3368 ttcn3float v_real
= t_val
->get_val_Real();
3370 port_op
.s
.call
.timer
->error("The call timer has "
3371 "negative duration: `%s'", Real2string(v_real
).c_str());
3372 } else if (isSpecialFloatValue(v_real
)) {
3373 port_op
.s
.call
.timer
->error("The call timer duration cannot be %s",
3374 Real2string(v_real
).c_str());
3378 // checking to clause
3379 chk_to_clause(port_type
);
3380 // checking response and exception handling part
3381 if (port_op
.s
.call
.body
) chk_call_body(port_type
, signature
);
3384 void Statement::chk_reply()
3386 Error_Context
cntxt(this, "In reply statement");
3387 // checking the port reference
3388 Type
*port_type
= chk_port_ref(port_op
.portref
);
3389 // determining the signature of the argument
3390 Type
*signature
= 0;
3391 bool signature_determined
= false;
3393 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3394 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3396 if (in_sigs
->get_nof_types() == 1) {
3397 // there is only one incoming signature
3398 signature
= in_sigs
->get_type_byIndex(0);
3400 // there are more than one incoming signatures
3401 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3403 if (!in_sigs
->has_type(signature
)) {
3404 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3405 "incoming list of port type `%s'",
3406 signature
->get_typename().c_str(),
3407 port_type
->get_typename().c_str());
3410 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3414 signature_determined
= true;
3415 } else if (port_type_body
->get_operation_mode() ==
3416 PortTypeBody::PO_MESSAGE
) {
3417 port_op
.portref
->error("Procedure-based operation `reply' is not "
3418 "applicable to a message-based port of type `%s'",
3419 port_type
->get_typename().c_str());
3421 port_op
.portref
->error("Port type `%s' does not have any incoming "
3422 "signatures", port_type
->get_typename().c_str());
3425 if (!signature_determined
)
3426 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3427 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3428 // checking the parameter (template instance)
3429 port_op
.s
.sendpar
->chk(signature
);
3430 signature
= signature
->get_type_refd_last();
3431 Type
*return_type
= 0;
3432 switch (signature
->get_typetype()) {
3433 case Type::T_SIGNATURE
:
3434 // the signature is known and correct
3435 if (signature
->is_nonblocking_signature())
3436 error("Operation `reply' is not applicable to non-blocking signature "
3437 "`%s'", signature
->get_typename().c_str());
3438 else return_type
= signature
->get_signature_return_type();
3439 // checking the presence/absence of reply value
3440 if (port_op
.s
.replyval
) {
3442 port_op
.s
.replyval
->error("Unexpected return value. Signature "
3443 "`%s' does not have return type",
3444 signature
->get_typename().c_str());
3446 } else if (return_type
) {
3447 error("Missing return value. Signature `%s' returns type `%s'",
3448 signature
->get_typename().c_str(),
3449 return_type
->get_typename().c_str());
3454 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not a "
3455 "signature", signature
->get_typename().c_str());
3457 // checking the reply value if present
3458 if (port_op
.s
.replyval
) {
3459 Error_Context
cntxt2(port_op
.s
.replyval
, "In return value");
3460 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3461 port_op
.s
.replyval
->set_my_governor(return_type
);
3462 return_type
->chk_this_value_ref(port_op
.s
.replyval
);
3463 return_type
->chk_this_value(port_op
.s
.replyval
, 0,
3464 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
3467 // checking to clause
3468 chk_to_clause(port_type
);
3471 void Statement::chk_raise()
3473 Error_Context
cntxt(this, "In raise statement");
3474 // checking the port reference
3475 Type
*port_type
= chk_port_ref(port_op
.portref
);
3476 // determining the signature of the exception
3477 port_op
.s
.raise
.signature
=
3478 chk_signature_ref(port_op
.s
.raise
.signature_ref
);
3479 // checking whether the signature is present on the incoming list
3480 // of the respective port type
3482 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3483 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3484 if (port_type_body
->get_operation_mode() ==
3485 PortTypeBody::PO_MESSAGE
) {
3486 port_op
.portref
->error("Procedure-based operation `raise' is not "
3487 "applicable to a message-based port of type `%s'",
3488 port_type
->get_typename().c_str());
3489 } else if (in_sigs
) {
3490 if (port_op
.s
.raise
.signature
) {
3491 if (!in_sigs
->has_type(port_op
.s
.raise
.signature
)) {
3492 port_op
.s
.raise
.signature_ref
->error("Signature `%s' is not "
3493 "present on the incoming list of port type `%s'",
3494 port_op
.s
.raise
.signature
->get_typename().c_str(),
3495 port_type
->get_typename().c_str());
3497 } else if (in_sigs
->get_nof_types() == 1) {
3498 // if the signature is unknown and the port type has exactly one
3499 // incoming signature then use that for further checking
3500 port_op
.s
.raise
.signature
=
3501 in_sigs
->get_type_byIndex(0)->get_type_refd_last();
3504 port_op
.portref
->error("Port type `%s' does not have any incoming "
3505 "signatures", port_type
->get_typename().c_str());
3508 // determining the type of exception
3510 bool exc_type_determined
= false;
3511 if (port_op
.s
.raise
.signature
) {
3512 // the signature is known
3513 SignatureExceptions
*exceptions
=
3514 port_op
.s
.raise
.signature
->get_signature_exceptions();
3516 if (exceptions
->get_nof_types() == 1) {
3517 // the signature has exactly one exception type
3518 // use that for checking
3519 exc_type
= exceptions
->get_type_byIndex(0);
3521 // the signature has more than one exception types
3522 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3524 size_t nof_comp_types
=
3525 exceptions
->get_nof_compatible_types(exc_type
);
3526 if (nof_comp_types
== 0) {
3527 port_op
.s
.sendpar
->error("Type `%s' is not present on the "
3528 "exception list of signature `%s'",
3529 exc_type
->get_typename().c_str(),
3530 port_op
.s
.raise
.signature
->get_typename().c_str());
3531 } else if (nof_comp_types
> 1) {
3532 port_op
.s
.sendpar
->error("Type of the exception is ambiguous: "
3533 "`%s' is compatible with more than one exception types of "
3534 "signature `%s'", exc_type
->get_typename().c_str(),
3535 port_op
.s
.raise
.signature
->get_typename().c_str());
3538 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3542 exc_type_determined
= true;
3544 port_op
.s
.raise
.signature_ref
->error("Signature `%s' does not have "
3545 "exceptions", port_op
.s
.raise
.signature
->get_typename().c_str());
3548 // determining the type of exception if it is not done so far
3549 if (!exc_type_determined
) {
3550 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3552 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3553 // checking the exception template
3554 port_op
.s
.sendpar
->chk(exc_type
);
3555 // checking for invalid exception types
3556 exc_type
= exc_type
->get_type_refd_last();
3557 switch (exc_type
->get_typetype()) {
3558 case Type::T_SIGNATURE
:
3559 port_op
.s
.sendpar
->error("The type of raise parameter is signature `%s', "
3560 "which cannot be an exception type",
3561 exc_type
->get_typename().c_str());
3564 port_op
.s
.sendpar
->error("The type of raise parameter is port type `%s', "
3565 "which cannot be an exception type",
3566 exc_type
->get_typename().c_str());
3568 case Type::T_DEFAULT
:
3569 port_op
.s
.sendpar
->error("The type of raise parameter is the `default' "
3570 "type, which cannot be an exception type");
3574 // checking for presence of wildcards in the template body
3575 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3576 // checking to clause
3577 chk_to_clause(port_type
);
3580 void Statement::chk_receive()
3582 // determining statement type
3583 const char *stmt_name
= get_stmt_name();
3584 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3585 // checking the port reference
3586 Type
*port_type
= chk_port_ref(port_op
.portref
);
3587 // checking the parameter and/or value redirect
3588 if (port_op
.r
.rcvpar
) {
3589 // the receive parameter (template instance) is present
3590 // trying to determine type of the incoming message
3592 bool msg_type_determined
= false, value_redirect_checked
= false;
3594 // the port reference is correct and the port type is known
3595 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3596 TypeSet
*in_msgs
= port_type_body
->get_in_msgs();
3598 if (in_msgs
->get_nof_types() == 1) {
3599 // there is only one incoming message type
3600 // use that for checking
3601 msg_type
= in_msgs
->get_type_byIndex(0);
3603 // there are more than one incoming message types
3604 msg_type
= get_incoming_type(port_op
.r
.rcvpar
,
3605 port_op
.r
.redirect
.value
, value_redirect_checked
);
3607 size_t nof_comp_types
=
3608 in_msgs
->get_nof_compatible_types(msg_type
);
3609 if (nof_comp_types
== 0) {
3610 port_op
.r
.rcvpar
->error("Message type `%s' is not present on "
3611 "the incoming list of port of type `%s'",
3612 msg_type
->get_typename().c_str(),
3613 port_type
->get_typename().c_str());
3614 } else if (nof_comp_types
> 1) {
3615 port_op
.r
.rcvpar
->error("Type of the message is ambiguous: "
3616 "`%s' is compatible with more than one incoming message "
3617 "types of port type `%s'", msg_type
->get_typename().c_str(),
3618 port_type
->get_typename().c_str());
3621 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3622 "incoming message");
3625 msg_type_determined
= true;
3626 } else if (port_type_body
->get_operation_mode() ==
3627 PortTypeBody::PO_PROCEDURE
) {
3628 port_op
.portref
->error("Message-based operation `%s' is not "
3629 "applicable to a procedure-based port of type `%s'", stmt_name
,
3630 port_type
->get_typename().c_str());
3632 port_op
.portref
->error("Port type `%s' does not have any incoming "
3633 "message types", port_type
->get_typename().c_str());
3635 } else if (!port_op
.portref
) {
3636 // the statement refers to 'any port'
3637 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3639 if (port_op
.r
.redirect
.value
) {
3640 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3641 "value redirect", stmt_name
);
3644 if (!msg_type_determined
) {
3645 msg_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3646 value_redirect_checked
);
3648 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3649 // check the template instance using the message type
3650 port_op
.r
.rcvpar
->chk(msg_type
);
3651 // check the value redirect if it is not done so far
3652 if (!value_redirect_checked
)
3653 chk_value_redirect(port_op
.r
.redirect
.value
, msg_type
);
3655 // the statement does not have parameter
3657 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3658 if (!port_type_body
->get_in_msgs()) {
3659 // the port type is known and it does not have incoming messages
3660 if (port_type_body
->get_operation_mode() ==
3661 PortTypeBody::PO_PROCEDURE
) {
3662 port_op
.portref
->error("Message-based operation `%s' is not "
3663 "applicable to a procedure-based port of type `%s'", stmt_name
,
3664 port_type
->get_typename().c_str());
3666 port_op
.portref
->error("Port type `%s' does not have any incoming "
3667 "message types", port_type
->get_typename().c_str());
3671 if (port_op
.r
.redirect
.value
) {
3672 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
3673 "receive parameter");
3674 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3677 // checking from clause and sender redirect
3678 chk_from_clause(port_type
);
3681 void Statement::chk_getcall()
3683 // determining statement type
3684 const char *stmt_name
= get_stmt_name();
3685 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3686 // checking the port reference
3687 Type
*port_type
= chk_port_ref(port_op
.portref
);
3688 if (port_op
.r
.rcvpar
) {
3689 // the parameter (signature template) is present
3690 // determining the signature of the argument
3691 Type
*signature
= 0;
3692 bool signature_determined
= false;
3694 // the port reference is correct and the port type is known
3695 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3696 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3698 if (in_sigs
->get_nof_types() == 1) {
3699 // there is only one incoming signature
3700 signature
= in_sigs
->get_type_byIndex(0);
3702 // there are more than one incoming signatures
3703 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3705 if (!in_sigs
->has_type(signature
)) {
3706 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3707 "incoming list of port type `%s'",
3708 signature
->get_typename().c_str(),
3709 port_type
->get_typename().c_str());
3712 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3716 signature_determined
= true;
3717 } else if (port_type_body
->get_operation_mode() ==
3718 PortTypeBody::PO_MESSAGE
) {
3719 port_op
.portref
->error("Procedure-based operation `%s' is not "
3720 "applicable to a message-based port of type `%s'", stmt_name
,
3721 port_type
->get_typename().c_str());
3723 port_op
.portref
->error("Port type `%s' does not have any incoming "
3724 "signatures", port_type
->get_typename().c_str());
3726 } else if (!port_op
.portref
) {
3727 // the statement refers to 'any port'
3728 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3730 if (port_op
.r
.redirect
.param
) {
3731 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3732 "have parameter redirect", stmt_name
);
3735 if (!signature_determined
)
3736 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3737 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3738 // checking the parameter (template instance)
3739 port_op
.r
.rcvpar
->chk(signature
);
3740 // checking whether the argument is a signature template
3741 // and checking the parameter redirect if present
3742 signature
= signature
->get_type_refd_last();
3743 switch (signature
->get_typetype()) {
3744 case Type::T_SIGNATURE
:
3745 if (port_op
.r
.redirect
.param
)
3746 port_op
.r
.redirect
.param
->chk(signature
, false);
3749 if (port_op
.r
.redirect
.param
)
3750 port_op
.r
.redirect
.param
->chk_erroneous();
3753 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3754 "a signature", signature
->get_typename().c_str());
3755 if (port_op
.r
.redirect
.param
)
3756 port_op
.r
.redirect
.param
->chk_erroneous();
3759 // the statement does not have parameter
3761 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3762 if (!port_type_body
->get_in_sigs()) {
3763 // the port type is known and it does not have incoming signatures
3764 if (port_type_body
->get_operation_mode() ==
3765 PortTypeBody::PO_MESSAGE
) {
3766 port_op
.portref
->error("Procedure-based operation `%s' is not "
3767 "applicable to a message-based port of type `%s'", stmt_name
,
3768 port_type
->get_typename().c_str());
3770 port_op
.portref
->error("Port type `%s' does not have any incoming "
3771 "signatures", port_type
->get_typename().c_str());
3775 if (port_op
.r
.redirect
.param
) {
3776 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3777 "without signature template");
3778 port_op
.r
.redirect
.param
->chk_erroneous();
3781 // checking from clause and sender redirect
3782 chk_from_clause(port_type
);
3785 void Statement::chk_getreply()
3787 // determining statement type
3788 const char *stmt_name
= get_stmt_name();
3789 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3790 // checking the port reference
3791 Type
*port_type
= chk_port_ref(port_op
.portref
);
3792 if (port_op
.r
.rcvpar
) {
3793 // the parameter (signature template) is present
3794 // determining the signature of the argument
3795 Type
*signature
= 0;
3796 bool signature_determined
= false;
3798 // the port reference is correct and the port type is known
3799 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3800 if (port_type_body
->getreply_allowed()) {
3801 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3802 if (out_sigs
->get_nof_types() == 1) {
3803 // there is only one outgoing signature
3804 signature
= out_sigs
->get_type_byIndex(0);
3806 // there are more than one outgoing signatures
3807 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3809 if (!out_sigs
->has_type(signature
)) {
3810 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3811 "outgoing list of port type `%s'",
3812 signature
->get_typename().c_str(),
3813 port_type
->get_typename().c_str());
3816 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3820 signature_determined
= true;
3821 } else if (port_type_body
->get_operation_mode() ==
3822 PortTypeBody::PO_MESSAGE
) {
3823 port_op
.portref
->error("Procedure-based operation `%s' is not "
3824 "applicable to a message-based port of type `%s'", stmt_name
,
3825 port_type
->get_typename().c_str());
3827 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3828 "signatures that support reply", port_type
->get_typename().c_str());
3830 } else if (!port_op
.portref
) {
3831 // the statement refers to 'any port'
3832 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3834 if (port_op
.r
.getreply_valuematch
) {
3835 port_op
.r
.getreply_valuematch
->error("Operation `any port.%s' cannot "
3836 "have value match", stmt_name
);
3838 if (port_op
.r
.redirect
.value
) {
3839 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot "
3840 "have value redirect", stmt_name
);
3842 if (port_op
.r
.redirect
.param
) {
3843 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3844 "have parameter redirect", stmt_name
);
3847 if (!signature_determined
)
3848 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3849 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3850 // checking the parameter (template instance)
3851 port_op
.r
.rcvpar
->chk(signature
);
3852 // checking whether the argument is a signature template
3853 // checking the parameter redirect if present
3854 // and determining the return type of the signature
3855 signature
= signature
->get_type_refd_last();
3856 Type
*return_type
= 0;
3857 switch (signature
->get_typetype()) {
3858 case Type::T_SIGNATURE
:
3859 if (signature
->is_nonblocking_signature())
3860 error("Operation `%s' is not applicable to non-blocking signature "
3861 "`%s'", stmt_name
, signature
->get_typename().c_str());
3862 else return_type
= signature
->get_signature_return_type();
3863 if (port_op
.r
.redirect
.param
)
3864 port_op
.r
.redirect
.param
->chk(signature
, true);
3866 if (port_op
.r
.getreply_valuematch
) {
3867 port_op
.r
.getreply_valuematch
->error("Value match cannot be used "
3868 "because signature `%s' does not have return type",
3869 signature
->get_typename().c_str());
3871 if (port_op
.r
.redirect
.value
) {
3872 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3873 "because signature `%s' does not have return type",
3874 signature
->get_typename().c_str());
3879 if (port_op
.r
.redirect
.param
)
3880 port_op
.r
.redirect
.param
->chk_erroneous();
3883 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3884 "a signature", signature
->get_typename().c_str());
3885 if (port_op
.r
.redirect
.param
)
3886 port_op
.r
.redirect
.param
->chk_erroneous();
3888 // checking the value match if present
3889 if (port_op
.r
.getreply_valuematch
) {
3890 Error_Context
cntxt2(port_op
.s
.replyval
, "In value match");
3891 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3892 port_op
.r
.getreply_valuematch
->chk(return_type
);
3894 // checking the value redirect if present
3895 chk_value_redirect(port_op
.r
.redirect
.value
, return_type
);
3897 // the statement does not have parameter (value match is also omitted)
3899 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3900 if (!port_type_body
->getreply_allowed()) {
3901 // the port type is known and it does not have outgoing signatures
3902 if (port_type_body
->get_operation_mode() ==
3903 PortTypeBody::PO_MESSAGE
) {
3904 port_op
.portref
->error("Procedure-based operation `%s' is not "
3905 "applicable to a message-based port of type `%s'", stmt_name
,
3906 port_type
->get_typename().c_str());
3908 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3909 "signatures that support reply",
3910 port_type
->get_typename().c_str());
3914 if (port_op
.r
.redirect
.value
) {
3915 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3916 "without signature template");
3917 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3919 if (port_op
.r
.redirect
.param
) {
3920 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3921 "without signature template");
3922 port_op
.r
.redirect
.param
->chk_erroneous();
3925 // checking from clause and sender redirect
3926 chk_from_clause(port_type
);
3929 void Statement::chk_catch()
3931 // determining statement type
3932 const char *stmt_name
= get_stmt_name();
3933 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3934 // checking the port reference
3935 Type
*port_type
= chk_port_ref(port_op
.portref
);
3936 // checking the signature reference, parameter and/or value redirect
3937 if (port_op
.r
.ctch
.signature_ref
) {
3938 // the signature reference is present
3939 port_op
.r
.ctch
.signature
=
3940 chk_signature_ref(port_op
.r
.ctch
.signature_ref
);
3941 // checking whether the signature is present on the incoming list
3942 // of the respective port type
3944 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3945 if (port_type_body
->catch_allowed()) {
3946 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3947 if (port_op
.r
.ctch
.signature
) {
3948 if (!out_sigs
->has_type(port_op
.r
.ctch
.signature
)) {
3949 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' is not "
3950 "present on the outgoing list of port type `%s'",
3951 port_op
.r
.ctch
.signature
->get_typename().c_str(),
3952 port_type
->get_typename().c_str());
3954 } else if (out_sigs
->get_nof_types() == 1) {
3955 // if the signature is unknown and the port type has exactly one
3956 // outgoing signature then use that for further checking
3957 port_op
.r
.ctch
.signature
=
3958 out_sigs
->get_type_byIndex(0)->get_type_refd_last();
3960 } else if (port_type_body
->get_operation_mode() ==
3961 PortTypeBody::PO_MESSAGE
) {
3962 port_op
.portref
->error("Procedure-based operation `%s' is not "
3963 "applicable to a message-based port of type `%s'", stmt_name
,
3964 port_type
->get_typename().c_str());
3966 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3967 "signatures that support exceptions",
3968 port_type
->get_typename().c_str());
3970 } else if (!port_op
.portref
) {
3971 // the statement refers to 'any port'
3972 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3974 if (port_op
.r
.redirect
.value
) {
3975 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3976 "value redirect", stmt_name
);
3979 // the receive parameter (template instance) must be also present
3980 // trying to determine type of the exception
3982 bool exc_type_determined
= false, value_redirect_checked
= false;
3983 if (port_op
.r
.ctch
.signature
) {
3984 // the signature is known
3985 SignatureExceptions
*exceptions
=
3986 port_op
.r
.ctch
.signature
->get_signature_exceptions();
3988 if (exceptions
->get_nof_types() == 1) {
3989 // the signature has exactly one exception type
3990 // use that for checking
3991 exc_type
= exceptions
->get_type_byIndex(0);
3993 // the signature has more than one exception types
3994 exc_type
= get_incoming_type(port_op
.r
.rcvpar
,
3995 port_op
.r
.redirect
.value
, value_redirect_checked
);
3997 size_t nof_comp_types
=
3998 exceptions
->get_nof_compatible_types(exc_type
);
3999 if (nof_comp_types
== 0) {
4000 port_op
.r
.rcvpar
->error("Type `%s' is not present on the "
4001 "exception list of signature `%s'",
4002 exc_type
->get_typename().c_str(),
4003 port_op
.r
.ctch
.signature
->get_typename().c_str());
4004 } else if (nof_comp_types
> 1) {
4005 port_op
.r
.rcvpar
->error("Type of the exception is ambiguous: "
4006 "`%s' is compatible with more than one exception types of "
4007 "signature `%s'", exc_type
->get_typename().c_str(),
4008 port_op
.r
.ctch
.signature
->get_typename().c_str());
4011 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
4015 exc_type_determined
= true;
4017 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' does not have "
4018 "exceptions", port_op
.r
.ctch
.signature
->get_typename().c_str());
4021 if (!exc_type_determined
) {
4022 exc_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
4023 value_redirect_checked
);
4025 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
4026 // check the template instance using the exception type
4027 port_op
.r
.rcvpar
->chk(exc_type
);
4028 // check the value redirect if it is not done so far
4029 if (!value_redirect_checked
)
4030 chk_value_redirect(port_op
.r
.redirect
.value
, exc_type
);
4031 // checking for invalid exception types
4032 exc_type
= exc_type
->get_type_refd_last();
4033 switch (exc_type
->get_typetype()) {
4034 case Type::T_SIGNATURE
:
4035 port_op
.r
.rcvpar
->error("The type of catch parameter is signature "
4036 "`%s', which cannot be an exception type",
4037 exc_type
->get_typename().c_str());
4040 port_op
.r
.rcvpar
->error("The type of catch parameter is port type "
4041 "`%s', which cannot be an exception type",
4042 exc_type
->get_typename().c_str());
4044 case Type::T_DEFAULT
:
4045 port_op
.r
.rcvpar
->error("The type of catch parameter is the `default' "
4046 "type, which cannot be an exception type");
4051 // the statement does not have signature reference
4052 if (port_op
.r
.ctch
.timeout
) {
4053 // the parameter is timeout
4054 if (port_op
.portref
) {
4055 // the port reference is present
4057 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4058 if (!port_type_body
->getreply_allowed()) {
4059 // the port type is known and it does not allow blocking calls
4060 if (port_type_body
->get_operation_mode() ==
4061 PortTypeBody::PO_MESSAGE
) {
4062 port_op
.portref
->error("Timeout exception cannot be caught on "
4063 "a message-based port of type `%s'",
4064 port_type
->get_typename().c_str());
4066 port_op
.portref
->error("Timeout exception cannot be caught on "
4067 "a port of type `%s', which does not have any outgoing "
4068 "signatures that allow blocking calls",
4069 port_type
->get_typename().c_str());
4073 } else error("Timeout exception cannot be caught on `any port'");
4074 if (!port_op
.r
.ctch
.in_call
)
4075 error("Catching of `timeout' exception is not allowed in this "
4076 "context. It is permitted only in the response and exception "
4077 "handling part of `call' operations");
4078 else if (!port_op
.r
.ctch
.call_has_timer
)
4079 error("Catching of `timeout' exception is not allowed because the "
4080 "previous `call' operation does not have timer");
4081 if (port_op
.r
.fromclause
) port_op
.r
.fromclause
->error(
4082 "Operation `catch(timeout)' cannot have from clause");
4083 if (port_op
.r
.redirect
.sender
) port_op
.r
.redirect
.sender
->error(
4084 "Operation `catch(timeout)' cannot have sender redirect");
4086 // the operation does not have any parameter
4088 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4089 if (!port_type_body
->catch_allowed()) {
4090 // the port type is known and it does not have outgoing signatures
4091 if (port_type_body
->get_operation_mode() ==
4092 PortTypeBody::PO_MESSAGE
) {
4093 port_op
.portref
->error("Procedure-based operation `%s' is not "
4094 "applicable to a message-based port of type `%s'", stmt_name
,
4095 port_type
->get_typename().c_str());
4097 port_op
.portref
->error("Port type `%s' does not have any "
4098 "outgoing signatures that support exceptions",
4099 port_type
->get_typename().c_str());
4104 if (port_op
.r
.redirect
.value
) {
4105 // the statement does not have any parameter,
4106 // but the value redirect is present
4107 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
4108 "signature and parameter");
4109 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
4112 // checking from clause and sender redirect
4113 chk_from_clause(port_type
);
4116 void Statement::chk_check()
4118 Error_Context
cntxt(this, "In check statement");
4119 Type
*port_type
= chk_port_ref(port_op
.portref
);
4120 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4121 // the port type is known and it does not have incoming queue
4122 port_op
.portref
->error("Port type `%s' does not have incoming queue "
4123 "because it has neither incoming messages nor incoming or outgoing "
4124 "signatures", port_type
->get_typename().c_str());
4126 // checking from clause and sender redirect
4127 chk_from_clause(port_type
);
4130 void Statement::chk_clear()
4132 Error_Context
cntxt(this, "In clear port statement");
4133 Type
*port_type
= chk_port_ref(port_op
.portref
);
4134 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4135 // the port type is known and it does not have incoming queue
4136 port_op
.portref
->warning("Port type `%s' does not have incoming queue "
4137 "because it has neither incoming messages nor incoming or outgoing "
4138 "signatures", port_type
->get_typename().c_str());
4142 void Statement::chk_start_stop_port()
4144 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4145 chk_port_ref(port_op
.portref
);
4148 void Statement::chk_start_comp()
4150 Error_Context
cntxt(this, "In start test component statement");
4151 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4152 Common::Assignment
*t_ass
= comp_op
.funcinstref
->get_refd_assignment();
4154 // checking whether the referred definition is a function
4155 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
4157 case Common::Assignment::A_FUNCTION
:
4158 case Common::Assignment::A_FUNCTION_RVAL
:
4159 case Common::Assignment::A_FUNCTION_RTEMP
:
4162 comp_op
.funcinstref
->error("Reference to a function was expected in the "
4163 "argument instead of %s", t_ass
->get_description().c_str());
4166 Def_Function
*t_func
= dynamic_cast<Def_Function
*>(t_ass
);
4167 if (!t_func
) FATAL_ERROR("Statement::chk_start_comp()");
4168 // checking startability
4169 if (!t_func
->chk_startable()) return;
4170 // checking the 'runs on' clause against the type of component reference
4171 Type
*runs_on_type
= t_func
->get_RunsOnType();
4172 if (!comp_type
|| !runs_on_type
) return;
4173 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4174 comp_op
.compref
->error("Component type mismatch: The component reference "
4175 "is of type `%s', but %s runs on `%s'",
4176 comp_type
->get_typename().c_str(), t_func
->get_description().c_str(),
4177 runs_on_type
->get_typename().c_str());
4178 // checking the return type
4180 case Common::Assignment::A_FUNCTION_RTEMP
:
4181 comp_op
.funcinstref
->warning("Function `%s' returns a template of type "
4182 "`%s', which cannot be retrieved when the test component terminates",
4183 t_func
->get_fullname().c_str(),
4184 t_func
->get_Type()->get_typename().c_str());
4186 case Common::Assignment::A_FUNCTION_RVAL
: {
4187 bool return_type_correct
= false;
4188 Type
*return_type
= t_func
->get_Type();
4189 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4190 if (t
->has_done_attribute()) {
4191 return_type_correct
= true;
4193 } else if (!t
->is_ref()) break;
4195 if (!return_type_correct
)
4196 comp_op
.funcinstref
->warning("The return type of %s is `%s', which "
4197 "does not have the `done' extension attribute. When the test "
4198 "component terminates the returned value cannot be retrieved with "
4199 "a `done' operation", t_func
->get_description().c_str(),
4200 return_type
->get_typename().c_str());
4207 void Statement::chk_start_comp_refd()
4209 Error_Context
cntxt(this, "In start test component statement");
4210 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4211 switch(comp_op
.derefered
.value
->get_valuetype()){
4212 case Value::V_REFER
:
4213 comp_op
.derefered
.value
->error("A value of a function type was expected "
4214 "in the argument instead of a `refers' statement,"
4215 " which does not specify any function type");
4217 case Value::V_TTCN3_NULL
:
4218 comp_op
.derefered
.value
->error("A value of a function type was expected "
4219 "in the argument instead of a `null' value,"
4220 " which does not specify any function type");
4225 Type
*f_type
= comp_op
.derefered
.value
->get_expr_governor_last();
4226 if (!f_type
) return;
4227 switch (f_type
->get_typetype()) {
4230 case Type::T_FUNCTION
:
4233 comp_op
.derefered
.value
->error("A value of type function was expected "
4234 "in the argument instead of `%s'", f_type
->get_typename().c_str());
4237 if (f_type
->get_fat_runs_on_self()) {
4238 fau_refd
.value
->error("The argument cannot be a function reference with "
4239 "'runs on self' clause");
4242 if(!f_type
->chk_startability()) return;
4243 Type
*runs_on_type
= f_type
->get_fat_runs_on_type();
4244 if (!comp_type
|| !runs_on_type
) return;
4245 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4246 comp_op
.compref
->error("Component type mismatch: The component reference "
4247 "is of type `%s', but functions of type `%s' run on `%s'",
4248 comp_type
->get_typename().c_str(), f_type
->get_typename().c_str(),
4249 runs_on_type
->get_typename().c_str());
4250 Type
*return_type
= f_type
->get_function_return_type();
4252 if (f_type
->get_returns_template()) {
4253 comp_op
.derefered
.value
->warning("Functions of type `%s' return a "
4254 "template of type `%s', which cannot be retrieved when the test "
4255 "component terminates", f_type
->get_typename().c_str(),
4256 return_type
->get_typename().c_str());
4258 bool return_type_correct
= false;
4259 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4260 if (t
->has_done_attribute()) {
4261 return_type_correct
= true;
4263 } else if (!t
->is_ref()) break;
4265 if (!return_type_correct
)
4266 comp_op
.derefered
.value
->warning("The return type of function type "
4267 "`%s' is `%s', which does not have the `done' extension attribute. "
4268 "When the test component terminates the returned value cannot be "
4269 "retrieved with a `done' operation", f_type
->get_typename().c_str(),
4270 return_type
->get_typename().c_str());
4273 ActualParList
*parlist
= new ActualParList
;
4274 Ttcn::FormalParList
*fp_list
= f_type
->get_fat_parameters();
4275 if(fp_list
->fold_named_and_chk(comp_op
.derefered
.t_list1
, parlist
)) {
4277 delete comp_op
.derefered
.t_list1
;
4278 comp_op
.derefered
.ap_list2
= 0;
4280 delete comp_op
.derefered
.t_list1
;
4281 parlist
->set_fullname(get_fullname());
4282 parlist
->set_my_scope(my_sb
);
4283 comp_op
.derefered
.ap_list2
= parlist
;
4287 void Statement::chk_stop_kill_comp()
4289 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4290 chk_comp_ref(comp_op
.compref
, true, false);
4293 void Statement::chk_done()
4295 Error_Context
cntxt(this, "In done statement");
4296 chk_comp_ref(comp_op
.compref
, false, false);
4297 if (!comp_op
.compref
) return;
4298 // value returning done can be used only when the statement contains a
4299 // specific component reference
4300 if (comp_op
.donereturn
.donematch
) {
4301 bool value_redirect_checked
= false;
4302 // try to determine the type of return value
4303 Type
*return_type
= get_incoming_type(comp_op
.donereturn
.donematch
,
4304 comp_op
.donereturn
.redirect
, value_redirect_checked
);
4306 bool return_type_correct
= false;
4307 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4308 if (t
->has_done_attribute()) {
4309 return_type_correct
= true;
4311 } else if (!t
->is_ref()) break;
4313 if (!return_type_correct
) {
4314 error("Return type `%s' does not have `done' extension attribute",
4315 return_type
->get_typename().c_str());
4316 return_type
= Type::get_pooltype(Type::T_ERROR
);
4319 comp_op
.donereturn
.donematch
->error("Cannot determine the return type "
4320 "for value returning done");
4321 return_type
= Type::get_pooltype(Type::T_ERROR
);
4323 comp_op
.donereturn
.donematch
->chk(return_type
);
4324 if (!value_redirect_checked
)
4325 chk_value_redirect(comp_op
.donereturn
.redirect
, return_type
);
4326 } else if (comp_op
.donereturn
.redirect
) {
4327 comp_op
.donereturn
.redirect
->error("Redirect cannot be used for the "
4328 "return value without a matching template");
4329 chk_value_redirect(comp_op
.donereturn
.redirect
, 0);
4333 void Statement::chk_killed()
4335 Error_Context
cntxt(this, "In killed statement");
4336 chk_comp_ref(comp_op
.compref
, false, false);
4339 void Statement::chk_connect()
4341 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4342 // checking endpoints
4344 PortTypeBody
*ptb1
, *ptb2
;
4346 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4347 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, false);
4348 ptb1
= pt1
? pt1
->get_PortBody() : 0;
4351 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4352 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, false);
4353 ptb2
= pt2
? pt2
->get_PortBody() : 0;
4355 // checking consistency
4356 if (!ptb1
|| !ptb2
) return;
4357 if (!ptb1
->is_connectable(ptb2
) ||
4358 (ptb1
!= ptb2
&& !ptb2
->is_connectable(ptb1
))) {
4359 error("The connection between port types `%s' and `%s' is not consistent",
4360 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4361 ptb1
->report_connection_errors(ptb2
);
4362 if (ptb1
!= ptb2
) ptb2
->report_connection_errors(ptb1
);
4366 void Statement::chk_map()
4368 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4369 // checking endpoints
4371 PortTypeBody
*ptb1
, *ptb2
;
4372 bool cref1_is_tc
= false, cref1_is_system
= false;
4373 bool cref2_is_tc
= false, cref2_is_system
= false;
4375 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4376 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, true);
4378 ptb1
= pt1
->get_PortBody();
4379 if (ptb1
->is_internal()) {
4380 config_op
.portref1
->warning("Port type `%s' was marked as `internal'",
4381 pt1
->get_typename().c_str());
4384 Value
*cref1
= config_op
.compref1
->get_value_refd_last();
4385 if (cref1
->get_valuetype() == Value::V_EXPR
) {
4386 switch (cref1
->get_optype()) {
4387 case Value::OPTYPE_COMP_MTC
:
4388 case Value::OPTYPE_COMP_SELF
:
4389 case Value::OPTYPE_COMP_CREATE
:
4392 case Value::OPTYPE_COMP_SYSTEM
:
4393 cref1_is_system
= true;
4400 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4401 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, true);
4403 ptb2
= pt2
->get_PortBody();
4404 if (ptb2
->is_internal()) {
4405 config_op
.portref2
->warning("Port type `%s' was marked as `internal'",
4406 pt2
->get_typename().c_str());
4409 Value
*cref2
= config_op
.compref2
->get_value_refd_last();
4410 if (cref2
->get_valuetype() == Value::V_EXPR
) {
4411 switch (cref2
->get_optype()) {
4412 case Value::OPTYPE_COMP_MTC
:
4413 case Value::OPTYPE_COMP_SELF
:
4414 case Value::OPTYPE_COMP_CREATE
:
4417 case Value::OPTYPE_COMP_SYSTEM
:
4418 cref2_is_system
= true;
4424 if (cref1_is_tc
&& cref2_is_tc
) {
4425 error("Both endpoints of the mapping are test component ports");
4428 if (cref1_is_system
&& cref2_is_system
) {
4429 error("Both endpoints of the mapping are system ports");
4432 // checking consistency
4433 if (!ptb1
|| !ptb2
) return;
4434 if (cref1_is_tc
|| cref2_is_system
) {
4435 if (!ptb1
->is_mappable(ptb2
)) {
4436 error("The mapping between test component port type `%s' and system "
4437 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4438 pt2
->get_typename().c_str());
4439 ptb1
->report_mapping_errors(ptb2
);
4441 } else if (cref2_is_tc
|| cref1_is_system
) {
4442 if (!ptb2
->is_mappable(ptb1
)) {
4443 error("The mapping between system port type `%s' and test component "
4444 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4445 pt2
->get_typename().c_str());
4446 ptb2
->report_mapping_errors(ptb1
);
4449 // we have no idea which one is the system port
4450 if (!ptb1
->is_mappable(ptb1
) && !ptb2
->is_mappable(ptb1
)) {
4451 error("The mapping between port types `%s' and `%s' is not consistent",
4452 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4457 void Statement::chk_start_timer()
4459 Error_Context
cntxt(this, "In start timer statement");
4460 chk_timer_ref(timer_op
.timerref
);
4461 if (timer_op
.value
) {
4462 // check the actual duration
4463 timer_op
.value
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4464 Value
*t_val
= timer_op
.value
->get_value_refd_last();
4465 if (t_val
->get_valuetype() == Value::V_REAL
) {
4466 ttcn3float v_real
= t_val
->get_val_Real();
4468 timer_op
.value
->error("The timer duration is negative: `%s'",
4469 Real2string(v_real
).c_str());
4470 } else if (isSpecialFloatValue(v_real
)) {
4471 timer_op
.value
->error("The timer duration cannot be %s",
4472 Real2string(v_real
).c_str());
4476 // check whether the timer has default duration
4477 Common::Assignment
*t_ass
= timer_op
.timerref
->get_refd_assignment();
4478 if (t_ass
&& t_ass
->get_asstype() == Common::Assignment::A_TIMER
) {
4479 Def_Timer
*t_def_timer
= dynamic_cast<Def_Timer
*>(t_ass
);
4480 if (!t_def_timer
) FATAL_ERROR("Statement::chk_start_timer()");
4481 if (!t_def_timer
->has_default_duration(
4482 timer_op
.timerref
->get_subrefs()))
4483 error("Missing duration: %s does not have default duration",
4484 t_ass
->get_description().c_str());
4489 void Statement::chk_stop_timer_timeout()
4491 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4492 chk_timer_ref(timer_op
.timerref
);
4495 void Statement::chk_setverdict()
4497 Error_Context
cntxt(this, "In setverdict statement");
4498 if(!my_sb
->get_my_def())
4499 error("Setverdict statement is not allowed in the control part");
4500 setverdict
.verdictval
->chk_expr_verdict(Type::EXPECTED_DYNAMIC_VALUE
);
4501 Value
*t_val
= setverdict
.verdictval
->get_value_refd_last();
4502 if (t_val
->get_valuetype() == Value::V_VERDICT
&&
4503 t_val
->get_val_verdict() == Value::Verdict_ERROR
) {
4504 setverdict
.verdictval
->error("Error verdict cannot be set by the setverdict "
4509 void Statement::chk_execute()
4511 Error_Context
cntxt(this, "In execute statement");
4512 Ref_pard
*ref
=testcase_inst
.tcref
;
4513 Common::Assignment
*t_ass
=ref
->get_refd_assignment();
4514 if(!t_ass
) goto error
;
4515 if(t_ass
->get_asstype()!=Common::Assignment::A_TESTCASE
) {
4516 ref
->error("Reference to a testcase was expected in the argument"
4517 " instead of %s", t_ass
->get_description().c_str());
4520 if(my_sb
->get_scope_runs_on()) {
4521 ref
->error("A definition that has `runs on' clause cannot "
4522 "execute testcases");
4525 if (testcase_inst
.timerval
) {
4526 testcase_inst
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4527 Value
*t_val
= testcase_inst
.timerval
->get_value_refd_last();
4528 if (t_val
->get_valuetype() == Value::V_REAL
) {
4529 ttcn3float v_real
= t_val
->get_val_Real();
4531 testcase_inst
.timerval
->error("The testcase guard "
4532 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4533 } else if (isSpecialFloatValue(v_real
)) {
4534 testcase_inst
.timerval
->error("The testcase guard "
4535 "timer duration cannot be %s", Real2string(v_real
).c_str());
4542 statementtype
=S_ERROR
;
4545 void Statement::chk_execute_refd()
4547 Error_Context
cntxt(this, "In execute statement");
4548 switch(execute_refd
.value
->get_valuetype()){
4549 case Value::V_REFER
:
4550 execute_refd
.value
->error("A value of a testcase type was expected "
4551 "in the argument instead of a `refers' statement,"
4552 " which does not specify any function type");
4554 case Value::V_TTCN3_NULL
:
4555 execute_refd
.value
->error("A value of a testcase type was expected "
4556 "in the argument instead of a `null' value,"
4557 " which does not specify any function type");
4562 Type
*t
= execute_refd
.value
->get_expr_governor_last();
4564 switch (t
->get_typetype()) {
4567 case Type::T_TESTCASE
:
4570 execute_refd
.value
->error("A value of type testcase was expected in the "
4571 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
4574 if (my_sb
->get_scope_runs_on()) {
4575 execute_refd
.value
->error("A definition that has `runs on' clause cannot "
4576 "execute testcases");
4579 ActualParList
*parlist
= new ActualParList
;
4580 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
4581 bool is_erroneous
= fp_list
->chk_actual_parlist(execute_refd
.t_list1
,
4583 delete execute_refd
.t_list1
;
4586 execute_refd
.ap_list2
= 0;
4589 parlist
->set_fullname(get_fullname());
4590 parlist
->set_my_scope(my_sb
);
4591 execute_refd
.ap_list2
= parlist
;
4593 if(execute_refd
.timerval
) {
4594 execute_refd
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4595 Value
*t_val
= execute_refd
.timerval
->get_value_refd_last();
4596 if(t_val
->get_valuetype() == Value::V_REAL
) {
4597 ttcn3float v_real
= t_val
->get_val_Real();
4599 execute_refd
.value
->error("The testcase guard "
4600 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4601 } else if (isSpecialFloatValue(v_real
)) {
4602 execute_refd
.value
->error("The testcase guard "
4603 "timer duration cannot be %s", Real2string(v_real
).c_str());
4611 statementtype
=S_ERROR
;
4614 Type
*Statement::chk_port_ref(Reference
*p_ref
)
4616 if (!my_sb
->get_my_def())
4617 error("Port operation is not allowed in the control part");
4618 if (!p_ref
) return 0;
4619 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4620 if (!t_ass
) return 0;
4621 switch (t_ass
->get_asstype()) {
4622 case Common::Assignment::A_PORT
: {
4623 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4624 if (t_dims
) t_dims
->chk_indices(p_ref
, "port", false,
4625 Type::EXPECTED_DYNAMIC_VALUE
);
4626 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4627 "cannot have field or array sub-references",
4628 t_ass
->get_description().c_str());
4630 case Common::Assignment::A_PAR_PORT
:
4631 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4632 "field or array sub-references", t_ass
->get_description().c_str());
4635 p_ref
->error("Reference to a port or port parameter was expected "
4636 "instead of %s", t_ass
->get_description().c_str());
4639 Type
*ret_val
= t_ass
->get_Type();
4640 if (!ret_val
) return 0;
4641 ret_val
= ret_val
->get_type_refd_last();
4642 if (ret_val
->get_typetype() == Type::T_PORT
) return ret_val
;
4646 void Statement::chk_to_clause(Type
*port_type
)
4648 if (!port_op
.s
.toclause
) return;
4649 // pointer to the address type
4652 // the port type is known
4653 address_type
= port_type
->get_PortBody()->get_address_type();
4655 // the port type is unknown
4656 // address is permitted if it is visible from the current module
4657 address_type
= my_sb
->get_scope_mod()->get_address_type();
4659 Error_Context
cntxt(port_op
.s
.toclause
, "In `to' clause");
4661 // detect possible enumerated values (address may be an enumerated type)
4662 address_type
->chk_this_value_ref(port_op
.s
.toclause
);
4663 // try to figure out whether the argument is a component reference or
4667 port_op
.s
.toclause
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4668 if (t_governor
) is_address
= address_type
->is_compatible(t_governor
, NULL
);
4670 port_op
.s
.toclause
->get_expr_returntype(Type::EXPECTED_DYNAMIC_VALUE
)
4671 != Type::T_COMPONENT
;
4673 // the argument is an address value
4674 port_op
.s
.toclause
->set_my_governor(address_type
);
4675 address_type
->chk_this_value(port_op
.s
.toclause
, 0,
4676 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
4679 // the argument is not an address value, treat as a component reference
4680 chk_comp_ref(port_op
.s
.toclause
, true, true);
4683 // usage of address is not allowed
4684 chk_comp_ref(port_op
.s
.toclause
, true, true);
4688 void Statement::chk_from_clause(Type
*port_type
)
4690 if (!port_op
.r
.fromclause
&& !port_op
.r
.redirect
.sender
) return;
4691 // pointer to the address type
4694 // the port type is known
4695 address_type
= port_type
->get_PortBody()->get_address_type();
4696 } else if (port_op
.portref
) {
4697 // the operation refers to a specific port, but its type is unknown
4698 // address is permitted if it is visible from the current module
4699 address_type
= my_sb
->get_scope_mod()->get_address_type();
4701 // the operation refers to 'any port'
4702 // address is not allowed
4705 bool sender_redirect_checked
= false;
4706 Type
*from_clause_type
= 0;
4707 if (port_op
.r
.fromclause
) {
4708 // the from clause is present
4709 Error_Context
cntxt(port_op
.r
.fromclause
, "In `from' clause");
4711 port_op
.r
.fromclause
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4712 Template
*templ_body
= port_op
.r
.fromclause
->get_Template();
4713 if (!from_clause_type
) {
4714 // try to detect possible enumerated values
4715 if (address_type
) address_type
->chk_this_template_ref(templ_body
);
4716 else templ_body
->set_lowerid_to_ref();
4718 templ_body
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4720 if (!from_clause_type
) {
4721 // trying to determine the type of template in from clause
4722 // based on the sender redirect
4723 from_clause_type
= chk_sender_redirect(address_type
);
4724 sender_redirect_checked
= true;
4726 if (!from_clause_type
) {
4727 // trying to figure out whether the template is a component reference
4728 // or an SUT address
4730 if (templ_body
->get_expr_returntype(Type::EXPECTED_TEMPLATE
)
4731 == Type::T_COMPONENT
) is_compref
= true;
4733 switch (templ_body
->get_templatetype()) {
4734 case Template::SPECIFIC_VALUE
:
4735 // treat 'null' as component reference
4736 if (templ_body
->get_specific_value()->get_valuetype() ==
4737 Value::V_TTCN3_NULL
) is_compref
= true;
4738 else is_compref
= false;
4740 case Template::ANY_VALUE
:
4741 case Template::ANY_OR_OMIT
:
4742 // treat generic wildcards ? and * as component references
4750 // the argument is a component reference: get a pool type
4751 from_clause_type
= Type::get_pooltype(Type::T_COMPONENT
);
4752 } else if (address_type
) {
4753 // the argument is not a component reference: try the address type
4754 from_clause_type
= address_type
;
4757 if (from_clause_type
) {
4758 // the type of from clause is known
4759 port_op
.r
.fromclause
->chk(from_clause_type
);
4761 || !address_type
->is_compatible(from_clause_type
, NULL
)) {
4762 // from_clause_type must be a component type
4763 switch (from_clause_type
->get_type_refd_last()->get_typetype()) {
4765 // to avoid further errors in sender redirect
4766 from_clause_type
= 0;
4767 case Type::T_COMPONENT
:
4768 if (templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
)
4769 chk_comp_ref(templ_body
->get_specific_value(), true, true);
4772 port_op
.r
.fromclause
->error("The type of the template should be a "
4773 "component type %sinstead of `%s'",
4774 address_type
? "or the `address' type " : "",
4775 from_clause_type
->get_typename().c_str());
4776 // to avoid further errors in sender redirect
4777 from_clause_type
= 0;
4781 // the type of from clause is unknown
4782 port_op
.r
.fromclause
->error("Cannot determine the type of the "
4786 if (!sender_redirect_checked
) {
4787 Type
*sender_redirect_type
= chk_sender_redirect(address_type
);
4788 if (from_clause_type
&& sender_redirect_type
&&
4789 !from_clause_type
->is_identical(sender_redirect_type
)) {
4790 error("The types in `from' clause and `sender' redirect are not the "
4791 "same: `%s' was expected instead of `%s'",
4792 from_clause_type
->get_typename().c_str(),
4793 sender_redirect_type
->get_typename().c_str());
4798 void Statement::chk_call_body(Type
*port_type
, Type
*signature
)
4800 bool has_catch_timeout
= false;
4801 // setting the flags whether 'catch(timeout)' statements are allowed
4802 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4803 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4804 if (t_ag
->get_type() != AltGuard::AG_OP
)
4805 FATAL_ERROR("Statement::chk_call_body()");
4806 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4807 if (t_stmt
->statementtype
== S_CATCH
) {
4808 t_stmt
->port_op
.r
.ctch
.in_call
= true;
4809 if (port_op
.s
.call
.timer
)
4810 t_stmt
->port_op
.r
.ctch
.call_has_timer
= true;
4811 if (t_stmt
->port_op
.r
.ctch
.timeout
) has_catch_timeout
= true;
4814 Error_Context
cntxt(this, "In response and exception handling part");
4815 port_op
.s
.call
.body
->set_my_laic_stmt(port_op
.s
.call
.body
, 0);
4816 port_op
.s
.call
.body
->set_my_ags(port_op
.s
.call
.body
);
4817 port_op
.s
.call
.body
->chk();
4819 // checking whether getreply/catch operations refer to the same port
4820 // and same signature as the call operation
4821 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4822 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4823 if (t_ag
->get_type() != AltGuard::AG_OP
)
4824 FATAL_ERROR("Statement::chk_call_body()");
4825 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4826 if (t_stmt
->statementtype
== S_ERROR
) continue;
4827 // checking port reference
4828 if (!t_stmt
->port_op
.portref
) {
4829 t_stmt
->error("The `%s' operation must refer to the same port as "
4830 "the previous `call' statement: `%s' was expected instead of "
4831 "`any port'", t_stmt
->get_stmt_name(),
4832 port_op
.portref
->get_id()->get_dispname().c_str());
4833 } else if (*port_op
.portref
->get_id() !=
4834 *t_stmt
->port_op
.portref
->get_id()) {
4835 t_stmt
->port_op
.portref
->error("The `%s' operation refers to a "
4836 "different port than the previous `call' statement: `%s' was "
4837 "expected instead of `%s'", t_stmt
->get_stmt_name(),
4838 port_op
.portref
->get_id()->get_dispname().c_str(),
4839 t_stmt
->port_op
.portref
->get_id()->get_dispname().c_str());
4841 // checking the signature
4842 switch (t_stmt
->statementtype
) {
4844 if (t_stmt
->port_op
.r
.rcvpar
) {
4845 Type
*t_sig
= t_stmt
->port_op
.r
.rcvpar
4846 ->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4847 if (!signature
->is_compatible(t_sig
, NULL
))
4848 t_stmt
->port_op
.r
.rcvpar
->error("The `getreply' operation refers "
4849 "to a different signature than the previous `call' statement: "
4850 "`%s' was expected instead of `%s'",
4851 signature
->get_typename().c_str(),
4852 t_sig
->get_typename().c_str());
4856 if (t_stmt
->port_op
.r
.ctch
.signature
4857 && !signature
->is_compatible(t_stmt
->port_op
.r
.ctch
.signature
, NULL
))
4858 t_stmt
->port_op
.r
.ctch
.signature_ref
->error("The `catch' "
4859 "operation refers to a different signature than the previous "
4860 "`call' statement: `%s' was expected instead of `%s'",
4861 signature
->get_typename().c_str(),
4862 t_stmt
->port_op
.r
.ctch
.signature
->get_typename().c_str());
4865 FATAL_ERROR("Statement::chk_call_body()");
4869 if (port_op
.s
.call
.timer
&& !has_catch_timeout
)
4870 warning("The call operation has a timer, but the timeout exception is "
4874 Type
*Statement::get_outgoing_type(TemplateInstance
*p_ti
)
4876 // first analyze the template instance as is
4877 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4878 // return if this step was successful
4879 if (ret_val
) return ret_val
;
4880 // try to convert the undef identifier in the template instance to
4881 // a reference because it cannot be an enum value anymore
4882 Template
*t_templ
= p_ti
->get_Template();
4883 t_templ
->set_lowerid_to_ref();
4884 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4887 Type
*Statement::get_incoming_type(TemplateInstance
*p_ti
,
4888 Reference
*p_val_redir
, bool& p_val_redir_checked
)
4890 // first analyze the template instance
4891 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4892 // return if this step was successful
4893 if (ret_val
) return ret_val
;
4894 // use the variable in value redirect in the next step
4895 ret_val
= chk_value_redirect(p_val_redir
, 0);
4896 p_val_redir_checked
= true;
4897 // return if this step was successful
4898 if (ret_val
) return ret_val
;
4899 // finally try to convert the undef identifier in the template instance to
4900 // a reference because it cannot be an enum value anymore
4901 Template
*t_templ
= p_ti
->get_Template();
4902 t_templ
->set_lowerid_to_ref();
4903 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4906 Type
*Statement::chk_value_redirect(Reference
*p_ref
, Type
*p_type
)
4908 if (!p_ref
) return NULL
;
4909 Error_Context
cntxt(p_ref
, "In `value' redirect");
4910 Type
*t_var_type
= p_ref
->chk_variable_ref();
4911 if (p_type
&& t_var_type
) {
4912 TypeCompatInfo
info(my_sb
->get_scope_mod(), p_type
, t_var_type
, true, false);
4913 if (p_ref
->get_subrefs()) info
.set_str2_elem(p_ref
->get_subrefs()->refers_to_string_element());
4916 if (!p_type
->is_compatible(t_var_type
, &info
, &l_chain
, &r_chain
)) {
4917 if (info
.is_subtype_error()) {
4918 p_ref
->error("%s", info
.get_subtype_error().c_str());
4920 if (!info
.is_erroneous()) {
4921 p_ref
->error("Type mismatch in value redirect: "
4922 "A variable of type `%s' was expected instead of `%s'",
4923 p_type
->get_typename().c_str(),
4924 t_var_type
->get_typename().c_str());
4926 p_ref
->error("%s", info
.get_error_str_str().c_str());
4933 Type
*Statement::chk_sender_redirect(Type
*address_type
)
4935 if (!port_op
.r
.redirect
.sender
) return 0;
4936 Error_Context
cntxt(port_op
.r
.redirect
.sender
, "In `sender' redirect");
4937 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
4938 if (!t_var_type
) return 0;
4939 if (!address_type
|| !address_type
->is_identical(t_var_type
)) {
4940 // t_var_type must be a component type
4941 switch (t_var_type
->get_type_refd_last()->get_typetype()) {
4942 case Type::T_COMPONENT
:
4947 port_op
.r
.redirect
.sender
->error("The type of the variable should be "
4948 "a component type %sinstead of `%s'",
4949 address_type
? "or the `address' type " : "",
4950 t_var_type
->get_typename().c_str());
4957 Type
*Statement::chk_signature_ref(Reference
*p_ref
)
4959 if (!p_ref
) FATAL_ERROR("Statement::chk_signature_ref()");
4960 Error_Context(p_ref
, "In signature");
4961 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4962 if (!t_ass
) return 0;
4963 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
) {
4964 p_ref
->error("Reference to a signature was expected instead of %s",
4965 t_ass
->get_description().c_str());
4968 Type
*ret_val
= t_ass
->get_Type();
4969 if (!ret_val
) return 0;
4970 ret_val
= ret_val
->get_field_type(p_ref
->get_subrefs(),
4971 Type::EXPECTED_DYNAMIC_VALUE
);
4972 if (!ret_val
) return 0;
4973 ret_val
= ret_val
->get_type_refd_last();
4974 switch (ret_val
->get_typetype()) {
4975 case Type::T_SIGNATURE
:
4980 p_ref
->error("Reference to a signature was expected instead of port type "
4981 "`%s'", ret_val
->get_typename().c_str());
4984 p_ref
->error("Reference to a signature was expected instead of data type "
4985 "`%s'", ret_val
->get_typename().c_str());
4991 void Statement::chk_timer_ref(Reference
*p_ref
)
4994 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4996 switch (t_ass
->get_asstype()) {
4997 case Common::Assignment::A_TIMER
: {
4998 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4999 if (t_dims
) t_dims
->chk_indices(p_ref
, "timer", false,
5000 Type::EXPECTED_DYNAMIC_VALUE
);
5001 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
5002 "cannot have field or array sub-references",
5003 t_ass
->get_description().c_str());
5005 case Common::Assignment::A_PAR_TIMER
:
5006 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
5007 "field or array sub-references", t_ass
->get_description().c_str());
5010 p_ref
->error("Reference to a timer or timer parameter was expected "
5011 "instead of %s", t_ass
->get_description().c_str());
5015 Type
*Statement::chk_comp_ref(Value
*p_val
, bool allow_mtc
, bool allow_system
)
5017 if (!my_sb
->get_my_def())
5018 error("Component operation is not allowed in the control part");
5019 if (!p_val
) return 0;
5020 Value
*v
= p_val
->get_value_refd_last();
5021 switch (v
->get_valuetype()) {
5022 case Value::V_ERROR
:
5026 case Value::V_INVOKE
:
5027 if(p_val
->get_expr_returntype() != Type::T_COMPONENT
)
5028 p_val
->error("A component reference was expected as return value");
5030 case Value::V_TTCN3_NULL
:
5031 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
5034 switch (v
->get_optype()) {
5035 case Value::OPTYPE_COMP_NULL
:
5036 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
5038 case Value::OPTYPE_COMP_MTC
:
5040 p_val
->error("The `mtc' component reference shall not be used in `%s' operation", get_stmt_name());
5042 case Value::OPTYPE_COMP_SYSTEM
:
5044 p_val
->error("The `system' component reference shall not be used in `%s' operation", get_stmt_name());
5046 case Value::OPTYPE_COMP_SELF
:
5047 case Value::OPTYPE_COMP_CREATE
:
5050 p_val
->error("A component reference was expected as operand");
5055 p_val
->error("A component reference was expected as operand");
5058 Type
*ret_val
= p_val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
5059 if (!ret_val
) return 0;
5060 ret_val
= ret_val
->get_type_refd_last();
5061 switch (ret_val
->get_typetype()) {
5064 case Type::T_COMPONENT
:
5067 p_val
->error("Type mismatch: The type of the operand should be a "
5068 "component type instead of `%s'", ret_val
->get_typename().c_str());
5073 Type
*Statement::chk_conn_endpoint(Value
*p_compref
, Reference
*p_portref
,
5076 Type
*comp_type
= chk_comp_ref(p_compref
, true, allow_system
);
5078 ComponentTypeBody
*comp_body
= comp_type
->get_CompBody();
5079 p_portref
->set_base_scope(comp_body
);
5080 const Identifier
& t_portid
= *p_portref
->get_id();
5081 if (!comp_body
->has_local_ass_withId(t_portid
)) {
5082 p_portref
->error("Component type `%s' does not have port with name "
5083 "`%s'", comp_type
->get_typename().c_str(),
5084 t_portid
.get_dispname().c_str());
5087 Common::Assignment
*t_ass
= comp_body
->get_local_ass_byId(t_portid
);
5088 if (t_ass
->get_asstype() != Common::Assignment::A_PORT
) {
5089 p_portref
->error("Definition `%s' in component type `%s' is a %s and "
5090 "not a port", t_portid
.get_dispname().c_str(),
5091 comp_type
->get_typename().c_str(), t_ass
->get_assname());
5094 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
5095 if (t_dims
) t_dims
->chk_indices(p_portref
, "port", false,
5096 Type::EXPECTED_DYNAMIC_VALUE
);
5097 else if (p_portref
->get_subrefs()) {
5098 p_portref
->error("Port `%s' is not an array. The "
5099 "reference cannot have array indices",
5100 t_portid
.get_dispname().c_str());
5102 Type
*port_type
= t_ass
->get_Type();
5104 // check whether the external interface is provided by another port type
5105 PortTypeBody
*port_body
= port_type
->get_PortBody();
5106 if (port_body
->get_type() == PortTypeBody::PT_USER
) {
5107 Type
*provider_type
= port_body
->get_provider_type();
5108 if (provider_type
) port_type
= provider_type
;
5113 // the component type cannot be determined
5114 FieldOrArrayRefs
*t_subrefs
= p_portref
->get_subrefs();
5116 // check the array indices: they should be integers
5117 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
5118 t_subrefs
->get_ref(i
)->get_val()
5119 ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
5126 void Statement::set_code_section(
5127 GovernedSimple::code_section_t p_code_section
)
5129 switch(statementtype
) {
5138 case S_START_PROFILER
:
5139 case S_STOP_PROFILER
:
5142 ass
->set_code_section(p_code_section
);
5144 case S_FUNCTION_INSTANCE
:
5145 case S_ALTSTEP_INSTANCE
:
5147 ref_pard
->set_code_section(p_code_section
);
5150 block
->set_code_section(p_code_section
);
5154 case S_STOP_TESTCASE
:
5155 if (logargs
) logargs
->set_code_section(p_code_section
);
5158 if_stmt
.ics
->set_code_section(p_code_section
);
5159 if (if_stmt
.elseblock
)
5160 if_stmt
.elseblock
->set_code_section(p_code_section
);
5163 if (!loop
.for_stmt
.varinst
)
5164 loop
.for_stmt
.init_ass
->set_code_section(p_code_section
);
5165 loop
.for_stmt
.finalexpr
->set_code_section(p_code_section
);
5166 loop
.for_stmt
.step
->set_code_section(p_code_section
);
5167 loop
.block
->set_code_section(p_code_section
);
5171 loop
.expr
->set_code_section(p_code_section
);
5172 loop
.block
->set_code_section(p_code_section
);
5175 select
.expr
->set_code_section(p_code_section
);
5176 select
.scs
->set_code_section(p_code_section
);
5180 ags
->set_code_section(p_code_section
);
5183 if (returnexpr
.v
) returnexpr
.v
->set_code_section(p_code_section
);
5184 if (returnexpr
.t
) returnexpr
.t
->set_code_section(p_code_section
);
5187 if (deactivate
) deactivate
->set_code_section(p_code_section
);
5190 port_op
.portref
->set_code_section(p_code_section
);
5191 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5192 if (port_op
.s
.toclause
)
5193 port_op
.s
.toclause
->set_code_section(p_code_section
);
5196 port_op
.portref
->set_code_section(p_code_section
);
5197 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5198 if (port_op
.s
.toclause
)
5199 port_op
.s
.toclause
->set_code_section(p_code_section
);
5200 if (port_op
.s
.call
.timer
)
5201 port_op
.s
.call
.timer
->set_code_section(p_code_section
);
5202 if (port_op
.s
.call
.body
)
5203 port_op
.s
.call
.body
->set_code_section(p_code_section
);
5206 port_op
.portref
->set_code_section(p_code_section
);
5207 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5208 if (port_op
.s
.replyval
)
5209 port_op
.s
.replyval
->set_code_section(p_code_section
);
5210 if (port_op
.s
.toclause
)
5211 port_op
.s
.toclause
->set_code_section(p_code_section
);
5214 port_op
.portref
->set_code_section(p_code_section
);
5215 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5216 if (port_op
.s
.toclause
)
5217 port_op
.s
.toclause
->set_code_section(p_code_section
);
5220 case S_CHECK_RECEIVE
:
5222 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5223 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5224 if (port_op
.r
.fromclause
)
5225 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5226 if (port_op
.r
.redirect
.value
)
5227 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5228 if (port_op
.r
.redirect
.sender
)
5229 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5232 case S_CHECK_GETCALL
:
5233 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5234 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5235 if (port_op
.r
.fromclause
)
5236 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5237 if (port_op
.r
.redirect
.param
)
5238 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5239 if (port_op
.r
.redirect
.sender
)
5240 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5243 case S_CHECK_GETREPLY
:
5244 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5245 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5246 if (port_op
.r
.getreply_valuematch
)
5247 port_op
.r
.getreply_valuematch
->set_code_section(p_code_section
);
5248 if (port_op
.r
.fromclause
)
5249 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5250 if (port_op
.r
.redirect
.value
)
5251 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5252 if (port_op
.r
.redirect
.param
)
5253 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5254 if (port_op
.r
.redirect
.sender
)
5255 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5259 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5260 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5261 if (port_op
.r
.fromclause
)
5262 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5263 if (port_op
.r
.redirect
.value
)
5264 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5265 if (port_op
.r
.redirect
.sender
)
5266 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5269 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5270 if (port_op
.r
.fromclause
)
5271 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5272 if (port_op
.r
.redirect
.sender
)
5273 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5279 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5282 comp_op
.compref
->set_code_section(p_code_section
);
5283 comp_op
.funcinstref
->set_code_section(p_code_section
);
5285 case S_START_COMP_REFD
:
5286 comp_op
.compref
->set_code_section(p_code_section
);
5287 comp_op
.derefered
.value
->set_code_section(p_code_section
);
5292 if (comp_op
.compref
) comp_op
.compref
->set_code_section(p_code_section
);
5295 if (comp_op
.compref
) {
5296 comp_op
.compref
->set_code_section(p_code_section
);
5297 if (comp_op
.donereturn
.donematch
)
5298 comp_op
.donereturn
.donematch
->set_code_section(p_code_section
);
5299 if (comp_op
.donereturn
.redirect
)
5300 comp_op
.donereturn
.redirect
->set_code_section(p_code_section
);
5307 config_op
.compref1
->set_code_section(p_code_section
);
5308 config_op
.portref1
->set_code_section(p_code_section
);
5309 config_op
.compref2
->set_code_section(p_code_section
);
5310 config_op
.portref2
->set_code_section(p_code_section
);
5313 timer_op
.timerref
->set_code_section(p_code_section
);
5314 if (timer_op
.value
) timer_op
.value
->set_code_section(p_code_section
);
5318 if (timer_op
.timerref
)
5319 timer_op
.timerref
->set_code_section(p_code_section
);
5322 setverdict
.verdictval
->set_code_section(p_code_section
);
5323 if (setverdict
.logargs
)
5324 setverdict
.logargs
->set_code_section(p_code_section
);
5326 case S_TESTCASE_INSTANCE
:
5327 testcase_inst
.tcref
->set_code_section(p_code_section
);
5328 if (testcase_inst
.timerval
)
5329 testcase_inst
.timerval
->set_code_section(p_code_section
);
5331 case S_TESTCASE_INSTANCE_REFD
:
5332 execute_refd
.value
->set_code_section(p_code_section
);
5333 if(execute_refd
.timerval
)
5334 execute_refd
.timerval
->set_code_section(p_code_section
);
5336 case S_ACTIVATE_REFD
:
5337 case S_FUNCTION_INVOKED
:
5338 case S_ALTSTEP_INVOKED
:
5339 fau_refd
.value
->set_code_section(p_code_section
);
5340 if(fau_refd
.ap_list2
)
5341 for(size_t i
= 0; i
< fau_refd
.ap_list2
->get_nof_pars(); i
++)
5342 fau_refd
.ap_list2
->get_par(i
)->set_code_section(p_code_section
);
5346 convert_op
.val
->set_code_section(p_code_section
);
5347 convert_op
.ref
->set_code_section(p_code_section
);
5350 FATAL_ERROR("Statement::set_code_section()");
5351 } // switch statementtype
5354 char *Statement::generate_code(char *str
)
5356 switch (statementtype
) {
5363 // conditional and loop statements do not need single location setting
5364 // the embedded expressions, statements have their own locations
5367 str
= update_location_object(str
);
5370 switch(statementtype
) {
5372 str
=def
->generate_code_str(str
);
5375 str
=ass
->generate_code(str
);
5377 case S_FUNCTION_INSTANCE
:
5378 case S_ALTSTEP_INSTANCE
:
5379 str
=generate_code_funcinst(str
);
5381 case S_FUNCTION_INVOKED
:
5382 case S_ALTSTEP_INVOKED
:
5383 str
=generate_code_invoke(str
);
5386 str
=generate_code_block(str
);
5389 str
=generate_code_log(str
);
5392 str
= generate_code_label(str
);
5395 str
= generate_code_goto(str
);
5398 str
=generate_code_if(str
);
5401 str
=generate_code_select(str
);
5404 str
=generate_code_for(str
);
5407 str
=generate_code_while(str
);
5410 str
=generate_code_dowhile(str
);
5413 str
=generate_code_break(str
);
5416 str
=generate_code_continue(str
);
5419 str
=mputstr(str
, "TTCN_Runtime::stop_execution();\n");
5421 case S_STOP_TESTCASE
:
5422 str
=generate_code_testcase_stop(str
);
5425 str
=ags
->generate_code_alt(str
, *this);
5428 str
=generate_code_repeat(str
);
5431 str
=generate_code_interleave(str
);
5434 str
=generate_code_return(str
);
5437 str
=generate_code_activate(str
);
5439 case S_ACTIVATE_REFD
:
5440 str
=generate_code_activate_refd(str
);
5443 str
=generate_code_deactivate(str
);
5446 str
= generate_code_send(str
);
5449 str
= generate_code_call(str
);
5452 str
= generate_code_reply(str
);
5455 str
= generate_code_raise(str
);
5463 case S_CHECK_RECEIVE
:
5464 case S_CHECK_GETCALL
:
5465 case S_CHECK_GETREPLY
:
5470 str
= generate_code_standalone(str
);
5473 str
=generate_code_portop(str
, "clear");
5476 str
=generate_code_portop(str
, "start");
5479 str
=generate_code_portop(str
, "stop");
5482 str
=generate_code_portop(str
, "halt");
5485 str
=generate_code_startcomp(str
);
5487 case S_START_COMP_REFD
:
5488 str
=generate_code_startcomp_refd(str
);
5491 str
= generate_code_compop(str
, "stop");
5494 str
= generate_code_compop(str
, "kill");
5497 str
= generate_code_configop(str
, "connect");
5500 str
= generate_code_configop(str
, "map");
5503 str
= generate_code_configop(str
, "disconnect");
5506 str
= generate_code_configop(str
, "unmap");
5509 str
=generate_code_starttimer(str
);
5512 str
=generate_code_stoptimer(str
);
5515 str
=generate_code_setverdict(str
);
5518 str
=generate_code_action(str
);
5520 case S_TESTCASE_INSTANCE
:
5521 str
=generate_code_testcaseinst(str
);
5523 case S_TESTCASE_INSTANCE_REFD
:
5524 str
=generate_code_execute_refd(str
);
5527 str
=generate_code_string2ttcn(str
);
5530 str
= generate_code_int2enum(str
);
5532 case S_START_PROFILER
:
5533 str
= mputstr(str
, "ttcn3_prof.start();\n");
5535 case S_STOP_PROFILER
:
5536 str
= mputstr(str
, "ttcn3_prof.stop();\n");
5539 FATAL_ERROR("Statement::generate_code()");
5544 char* Statement::generate_code_string2ttcn(char *str
)
5546 expression_struct val_expr
;
5547 Code::init_expr(&val_expr
);
5548 convert_op
.val
->generate_code_expr(&val_expr
);
5550 expression_struct ref_expr
;
5551 Code::init_expr(&ref_expr
);
5552 convert_op
.ref
->generate_code(&ref_expr
);
5554 str
= mputstr(str
, val_expr
.preamble
);
5555 str
= mputstr(str
, ref_expr
.preamble
);
5557 str
= mputprintf(str
, "string_to_ttcn(%s,%s);\n", val_expr
.expr
, ref_expr
.expr
);
5559 str
= mputstr(str
, val_expr
.postamble
);
5560 str
= mputstr(str
, ref_expr
.postamble
);
5562 Code::free_expr(&val_expr
);
5563 Code::free_expr(&ref_expr
);
5568 char* Statement::generate_code_int2enum(char* str
)
5570 expression_struct val_expr
;
5571 Code::init_expr(&val_expr
);
5572 convert_op
.val
->generate_code_expr(&val_expr
);
5574 expression_struct ref_expr
;
5575 Code::init_expr(&ref_expr
);
5576 convert_op
.ref
->generate_code(&ref_expr
);
5578 // check if the reference is an optional field
5579 bool is_optional
= false;
5580 FieldOrArrayRefs
* subrefs
= convert_op
.ref
->get_subrefs();
5581 if (NULL
!= subrefs
) {
5582 Type
* ref_type
= convert_op
.ref
->get_refd_assignment()->get_Type()->get_type_refd_last();
5583 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
5584 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
5585 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
5586 ref_type
= ref_type
->get_ofType()->get_type_refd_last();
5589 CompField
* cf
= ref_type
->get_comp_byName(*subref
->get_id());
5590 if (i
== subrefs
->get_nof_refs() - 1 && cf
->get_is_optional()) {
5593 ref_type
= cf
->get_type()->get_type_refd_last();
5598 str
= mputstr(str
, val_expr
.preamble
);
5599 str
= mputstr(str
, ref_expr
.preamble
);
5601 str
= mputprintf(str
, "%s%s.int2enum(%s);\n", ref_expr
.expr
,
5602 is_optional
? "()" : "", val_expr
.expr
);
5604 str
= mputstr(str
, val_expr
.postamble
);
5605 str
= mputstr(str
, ref_expr
.postamble
);
5607 Code::free_expr(&val_expr
);
5608 Code::free_expr(&ref_expr
);
5613 void Statement::generate_code_expr(expression_struct
*expr
)
5615 switch (statementtype
) {
5617 generate_code_expr_receive(expr
, "receive");
5620 generate_code_expr_receive(expr
, "trigger");
5622 case S_CHECK_RECEIVE
:
5623 generate_code_expr_receive(expr
, "check_receive");
5626 generate_code_expr_getcall(expr
, "getcall");
5628 case S_CHECK_GETCALL
:
5629 generate_code_expr_getcall(expr
, "check_getcall");
5632 generate_code_expr_getreply(expr
, "getreply");
5634 case S_CHECK_GETREPLY
:
5635 generate_code_expr_getreply(expr
, "check_getreply");
5639 generate_code_expr_catch(expr
);
5642 generate_code_expr_check(expr
);
5645 generate_code_expr_done(expr
);
5648 generate_code_expr_killed(expr
);
5651 generate_code_expr_timeout(expr
);
5654 FATAL_ERROR("Statement::generate_code_expr()");
5658 void Statement::ilt_generate_code(ILT
*ilt
)
5660 switch (statementtype
) {
5662 ilt_generate_code_interleave(ilt
);
5665 ilt_generate_code_alt(ilt
);
5668 ilt_generate_code_def(ilt
);
5673 if (is_receiving_stmt()) {
5674 ilt_generate_code_receiving(ilt
);
5677 if (!has_receiving_stmt()) {
5678 char*& str
=ilt
->get_out_branches();
5679 str
=generate_code(str
);
5682 switch (statementtype
) {
5684 block
->ilt_generate_code(ilt
);
5687 ilt_generate_code_if(ilt
);
5690 ilt_generate_code_select(ilt
);
5693 ilt_generate_code_call(ilt
);
5696 ilt_generate_code_for(ilt
);
5699 ilt_generate_code_while(ilt
);
5702 ilt_generate_code_dowhile(ilt
);
5705 FATAL_ERROR("Statement::ilt_generate_code()");
5706 } // switch statementtype
5709 char *Statement::generate_code_standalone(char *str
)
5711 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5712 const char *label_str
= tmplabel
.c_str();
5713 str
= mputprintf(str
, "{\n"
5714 "%s:\n", label_str
);
5715 expression_struct expr
;
5716 Code::init_expr(&expr
);
5717 generate_code_expr(&expr
);
5718 str
= mputstr(str
, expr
.preamble
);
5719 str
= mputprintf(str
, "alt_status alt_flag = ALT_UNCHECKED, "
5720 "default_flag = ALT_UNCHECKED;\n"
5721 "TTCN_Snapshot::take_new(FALSE);\n"
5723 "if (alt_flag != ALT_NO) {\n"
5725 "if (alt_flag == ALT_YES) break;\n", expr
.expr
);
5727 str
= mputprintf(str
, "else if (alt_flag == ALT_REPEAT) goto %s;\n",
5730 str
= mputprintf(str
, "}\n"
5731 "if (default_flag != ALT_NO) {\n"
5732 "default_flag = TTCN_Default::try_altsteps();\n"
5733 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) break;\n"
5734 "else if (default_flag == ALT_REPEAT) goto %s;\n"
5736 str
= update_location_object(str
);
5737 str
= mputprintf(str
, "if (alt_flag == ALT_NO && default_flag == ALT_NO) "
5738 "TTCN_error(\"Stand-alone %s statement failed in file ", get_stmt_name());
5739 str
= Code::translate_string(str
, get_filename());
5740 int first_line
= get_first_line(), last_line
= get_last_line();
5741 if (first_line
< last_line
) str
= mputprintf(str
,
5742 " between lines %d and %d", first_line
, last_line
);
5743 else str
= mputprintf(str
, ", line %d", first_line
);
5744 str
= mputstr(str
, ".\");\n"
5745 "TTCN_Snapshot::take_new(TRUE);\n"
5747 str
= mputstr(str
, expr
.postamble
);
5748 str
= mputstr(str
, "}\n");
5749 Code::free_expr(&expr
);
5753 char *Statement::generate_code_funcinst(char *str
)
5755 expression_struct expr
;
5756 Code::init_expr(&expr
);
5757 ref_pard
->generate_code_const_ref(&expr
);
5758 str
=Code::merge_free_expr(str
, &expr
);
5762 char* Statement::generate_code_invoke(char *str
)
5764 expression_struct expr
;
5765 Code::init_expr(&expr
);
5766 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
5767 switch(last_v
->get_valuetype()) {
5768 case Value::V_FUNCTION
:
5769 case Value::V_ALTSTEP
: {
5770 Common::Assignment
*t_fat
= last_v
->get_refd_fat();
5771 expr
.expr
= mputprintf(expr
.expr
, "%s(",
5772 t_fat
->get_genname_from_scope(my_sb
).c_str());
5773 fau_refd
.ap_list2
->generate_code_alias(&expr
, t_fat
->get_FormalParList(),
5774 t_fat
->get_RunsOnType(), false);
5777 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
5778 Type
*t_governor
= fau_refd
.value
->get_expr_governor_last();
5779 expr
.expr
= mputprintf(expr
.expr
, ".%s(",
5780 t_governor
->get_typetype() == Type::T_ALTSTEP
?
5781 "invoke_standalone" : "invoke");
5782 fau_refd
.ap_list2
->generate_code_alias(&expr
, 0,
5783 t_governor
->get_fat_runs_on_type(),
5784 t_governor
->get_fat_runs_on_self()); }
5786 expr
.expr
= mputc(expr
.expr
, ')');
5787 str
=Code::merge_free_expr(str
, &expr
);
5791 char *Statement::generate_code_block(char *str
)
5793 switch (block
->get_exception_handling()) {
5794 case StatementBlock::EH_NONE
:
5796 case StatementBlock::EH_TRY
:
5797 str
= mputstr(str
, "try ");
5799 case StatementBlock::EH_CATCH
:
5800 str
= mputstr(str
, "catch (const TTCN_Error& ttcn_error) ");
5803 FATAL_ERROR("Statement::generate_code_block()");
5805 if (block
->get_nof_stmts() > 0 || block
->get_exception_handling()!=StatementBlock::EH_NONE
) {
5806 str
= mputstr(str
, "{\n");
5807 str
= block
->generate_code(str
);
5808 str
= mputstr(str
, "}\n");
5809 } else str
= mputstr(str
, "/* empty block */;\n");
5813 char *Statement::generate_code_log(char *str
)
5816 bool buffered_mode
= true;
5817 if (logargs
->get_nof_logargs() == 1) {
5818 LogArgument
*first_logarg
= logargs
->get_logarg_byIndex(0);
5819 switch (first_logarg
->get_type()) {
5820 case LogArgument::L_STR
:
5821 // the argument is a simple string: use non-buffered mode
5822 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, \"");
5823 str
= Code::translate_string(str
, first_logarg
->get_str().c_str());
5824 str
= mputstr(str
, "\");\n");
5825 buffered_mode
= false;
5827 case LogArgument::L_MACRO
: {
5828 Value
*t_val
= first_logarg
->get_val();
5829 if (t_val
->has_single_expr()) {
5830 // the argument is a simple macro call: use non-buffered mode
5831 str
= mputprintf(str
, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5832 t_val
->get_single_expr().c_str());
5833 buffered_mode
= false;
5839 if (buffered_mode
) {
5840 // the argument is a complicated construct: use buffered mode
5841 str
= mputstr(str
, "try {\n"
5842 "TTCN_Logger::begin_event(TTCN_USER);\n");
5843 str
= logargs
->generate_code(str
);
5844 str
= mputstr(str
, "TTCN_Logger::end_event();\n"
5846 "TTCN_Logger::finish_event();\n"
5851 // the argument is missing
5852 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, "
5853 "\"<empty log statement>\");\n");
5858 char *Statement::generate_code_testcase_stop(char *str
)
5860 if (logargs
) str
= generate_code_log(str
);
5861 str
= mputstr(str
, "TTCN_error(\"testcase.stop\");\n");
5865 char *Statement::generate_code_label(char *str
)
5868 return mputprintf(str
, "%s: /* TTCN-3 label: %s */;\n",
5869 get_clabel().c_str(), label
.id
->get_dispname().c_str());
5871 return mputprintf(str
, "/* unused TTCN-3 label: %s */;\n",
5872 label
.id
->get_dispname().c_str());
5876 char *Statement::generate_code_goto(char *str
)
5878 if (!go_to
.label
) FATAL_ERROR("Statement::generate_code_goto()");
5879 return mputprintf(str
, "goto %s; /* TTCN-3 label: %s */\n",
5880 go_to
.label
->get_clabel().c_str(), go_to
.id
->get_dispname().c_str());
5884 char* Statement::generate_code_if(char *str
)
5886 size_t blockcount
=0;
5887 bool unreach
=false, eachfalse
=true;
5888 str
=if_stmt
.ics
->generate_code(str
, blockcount
, unreach
, eachfalse
);
5889 if(if_stmt
.elseblock
&& !unreach
) {
5890 if(!eachfalse
) str
=mputstr(str
, "else ");
5892 str
=mputstr(str
, "{\n");
5894 str
=if_stmt
.elseblock
->generate_code(str
);
5896 while(blockcount
-->0) str
=mputstr(str
, "}\n");
5897 if(eachfalse
) str
=mputstr(str
, "/* never occurs */;\n");
5901 char* Statement::generate_code_select(char *str
)
5903 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5904 char *expr_init
=memptystr();
5905 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
5906 if (expr_init
[0]) { // some init code was generated
5907 str
= update_location_object(str
);
5908 str
= mputstr(str
, "{\n");
5909 str
= mputstr(str
, expr_init
);
5911 str
=select
.scs
->generate_code(str
, tmp_prefix
.c_str(), expr_name
);
5913 if (expr_init
[0]) str
=mputstr(str
, "}\n");
5918 char *Statement::generate_code_for(char *str
)
5920 /** \todo initial does not have its own location */
5921 // statements in initial may have side effects
5922 // generate code for them anyway
5923 if (loop
.for_stmt
.varinst
) {
5924 str
= mputstr(str
, "{\n");
5925 str
= loop
.for_stmt
.init_varinst
->generate_code_str(str
);
5927 str
= loop
.for_stmt
.init_ass
->update_location_object(str
);
5928 str
= loop
.for_stmt
.init_ass
->generate_code(str
);
5930 // check whether the final expression is constant
5931 bool final_is_true
= false, final_is_false
= false;
5932 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
5933 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
5934 else final_is_false
= true;
5936 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
5940 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5941 str
= update_location_object(str
);
5942 str
= mputstr(str
, "for ( ; ; ) {\n");
5943 // do not generate the exit condition for infinite loops
5944 if (!final_is_true
) {
5945 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
5946 size_t blockcount
= 0;
5947 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
5949 str
= mputstr(str
, ") break;\n");
5950 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5952 if (loop
.label_next
) str
= mputstr(str
, "{\n");
5953 str
= loop
.block
->generate_code(str
);
5954 if (loop
.label_next
)
5955 str
= mputprintf(str
, "}\n"
5956 "%s:\n", loop
.label_next
->c_str());
5957 str
= loop
.for_stmt
.step
->update_location_object(str
);
5958 str
= loop
.for_stmt
.step
->generate_code(str
);
5959 str
= mputstr(str
, "}\n");
5961 if (loop
.for_stmt
.varinst
) str
= mputstr(str
, "}\n");
5965 char *Statement::generate_code_while(char *str
)
5967 // check whether the expression is constant
5968 bool condition_always_true
= false, condition_always_false
= false;
5969 if (!loop
.expr
->is_unfoldable()) {
5970 if (loop
.expr
->get_val_bool()) condition_always_true
= true;
5971 else condition_always_false
= true;
5973 if (condition_always_false
) str
= mputstr(str
, "/* never occurs */;\n");
5975 str
= mputstr(str
, "for ( ; ; ) {\n");
5976 if (loop
.has_cnt_in_ags
) {
5978 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5979 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5981 // do not generate the exit condition for infinite loops
5982 if (!condition_always_true
) {
5983 str
= loop
.expr
->update_location_object(str
);
5984 size_t blockcount
= 0;
5985 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5986 str
= mputstr(str
, ") break;\n");
5987 while(blockcount
-- > 0) str
= mputstr(str
, "}\n");
5989 str
= loop
.block
->generate_code(str
);
5990 str
= mputstr(str
, "}\n");
5995 char *Statement::generate_code_dowhile(char *str
)
5997 // check whether the expression is constant
5998 bool expr_is_const
= !loop
.expr
->is_unfoldable();
5999 bool is_infinite_loop
= false;
6000 if (expr_is_const
) {
6001 if (loop
.expr
->get_val_bool()) is_infinite_loop
= true;
6002 else loop
.iterate_once
= true;
6004 if (loop
.iterate_once
&& !loop
.has_brk
&& !loop
.has_cnt
) {
6005 str
= mputstr(str
, "{\n");
6006 str
= loop
.block
->generate_code(str
);
6008 str
= mputstr(str
, "for ( ; ; ) {\n");
6009 if (loop
.has_cnt_in_ags
|| (!expr_is_const
&& loop
.has_cnt
))
6011 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
6012 if (loop
.label_next
&& is_infinite_loop
)
6013 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
6014 if (loop
.label_next
&& !is_infinite_loop
) str
= mputstr(str
, "{\n");
6015 str
= loop
.block
->generate_code(str
);
6016 // do not generate the exit condition for infinite loops
6017 if (!is_infinite_loop
) {
6018 if (loop
.label_next
)
6019 str
= mputprintf(str
, "}\n"
6020 "%s:\n", loop
.label_next
->c_str());
6021 str
= loop
.expr
->update_location_object(str
);
6022 if (loop
.iterate_once
) str
= mputstr(str
, "break;\n");
6024 size_t blockcount
= 0;
6025 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6026 str
= mputstr(str
, ") break;\n");
6027 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6031 str
= mputstr(str
, "}\n");
6035 char *Statement::generate_code_break(char *str
)
6037 // in altstep (2 (=2nd if branch))
6038 // in alt and loops - not inside interleave (4)
6039 // in loops without receiving statement embedded in interleave (4)
6040 // in loops with receiving statement embedded in interleave (1)
6041 // in interleave when not embedded in enclosed loop or alt/interleave (4)
6042 // in alt/interleave embedded in interleave (3)
6043 if (brk_cnt
.loop_stmt
&& brk_cnt
.loop_stmt
->loop
.il_label_end
)
6044 str
=mputprintf(str
, "goto %s;\n",
6045 brk_cnt
.loop_stmt
->loop
.il_label_end
->c_str());
6046 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_is_altstep())
6047 str
=mputstr(str
, "return ALT_BREAK;\n");
6048 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_il_label_end())
6049 str
=mputprintf(str
, "goto %s;\n",
6050 brk_cnt
.ags
->get_il_label_end()->c_str());
6052 str
=mputstr(str
, "break;\n");
6056 char *Statement::generate_code_continue(char *str
)
6058 // not inside interleave when continue is not inside embedded ags (2 or 1)
6059 // continue is inside ags enclosed in the loop (3)
6060 // in interleave (3, 2 or 1)
6061 if (brk_cnt
.loop_stmt
!= 0) {
6062 if (brk_cnt
.loop_stmt
->loop
.iterate_once
&& !brk_cnt
.ags
&&
6063 !brk_cnt
.loop_stmt
->loop
.is_ilt
)
6064 str
=mputstr(str
, "break;\n");
6066 if (!brk_cnt
.loop_stmt
->loop
.label_next
)
6067 str
=mputstr(str
, "continue;\n");
6069 str
=mputprintf(str
, "goto %s;\n",
6070 brk_cnt
.loop_stmt
->loop
.label_next
->c_str());
6073 FATAL_ERROR("Statement::generate_code_continue()");
6077 char *Statement::generate_code_repeat(char *str
)
6079 string
*tmplabel
=ags
->get_label();
6080 if(!tmplabel
) str
=mputstr(str
, "return ALT_REPEAT;\n");
6081 else str
=mputprintf(str
, "goto %s;\n", tmplabel
->c_str());
6085 char* Statement::generate_code_interleave(char *str
)
6088 str
=ilt
.generate_code(str
);
6092 void Statement::ilt_generate_code_interleave(ILT
*ilt
)
6094 const string
& mytmpid
=ilt
->get_my_tmpid();
6095 bool toplevel
=ilt
->is_toplevel();
6096 size_t goto_label_num
=toplevel
?(size_t)-1:ilt
->get_new_label_num();
6097 char*& out_branches
=ilt
->get_out_branches();
6098 out_branches
=update_location_object(out_branches
);
6100 if(toplevel
) state_cond
="";
6102 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6103 (unsigned long) goto_label_num
);
6104 ags
->set_il_label_end (label_end
);
6106 ILT_branch
*branch
=ilt
->get_as_branch();
6107 size_t state_var
=branch
->get_my_state_var();
6108 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6109 state_cond
=branch
->get_state_cond();
6110 if(!state_cond
.empty()) state_cond
+=" && ";
6111 char *s
=mprintf("%s_state[%lu]==%lu", mytmpid
.c_str(),
6112 (unsigned long) state_var
, (unsigned long) state_var_val
);
6115 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6117 (unsigned long) state_var
, (unsigned long) state_var_val
);
6119 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6120 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6121 if(ag
->get_type()!=AltGuard::AG_OP
)
6122 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6123 size_t state_var
=ilt
->get_new_state_var(toplevel
);
6124 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6125 ilt
->add_branch(new ILT_branch(ILT_branch::BT_IL
, ag
, state_cond
,
6126 state_var
, state_var_val
,
6129 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6131 (unsigned long) state_var
, (unsigned long) state_var_val
);
6134 out_branches
=mputprintf(out_branches
, "goto %s;\n"
6137 mytmpid
.c_str(), (unsigned long) goto_label_num
);
6140 void Statement::ilt_generate_code_alt(ILT
*ilt
)
6142 const string
& mytmpid
=ilt
->get_my_tmpid();
6143 size_t goto_label_num
=ilt
->get_new_label_num();
6144 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6145 (unsigned long) goto_label_num
);
6146 ags
->set_il_label_end (label_end
);
6147 ILT_branch
*branch
=ilt
->get_as_branch();
6148 string state_cond
=branch
->get_state_cond();
6149 size_t state_var
=branch
->get_my_state_var();
6150 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6151 char*& out_branches
=ilt
->get_out_branches();
6152 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6153 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6154 if(ag
->get_type()!=AltGuard::AG_OP
)
6155 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6156 ilt
->add_branch(new ILT_branch(ILT_branch::BT_ALT
, ag
, state_cond
,
6157 state_var
, state_var_val
,
6160 out_branches
=update_location_object(out_branches
);
6161 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6164 mytmpid
.c_str(), (unsigned long) state_var
,
6165 (unsigned long) state_var_val
,
6166 mytmpid
.c_str(), label_end
);
6170 void Statement::ilt_generate_code_receiving(ILT
*ilt
)
6172 const string
& mytmpid
=ilt
->get_my_tmpid();
6173 size_t goto_label_num
=ilt
->get_new_label_num();
6174 ILT_branch
*branch
=ilt
->get_as_branch();
6175 string state_cond
=branch
->get_state_cond();
6176 size_t state_var
=branch
->get_my_state_var();
6177 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6178 char*& out_branches
=ilt
->get_out_branches();
6179 ilt
->add_branch(new ILT_branch(ILT_branch::BT_RECV
, this, state_cond
,
6180 state_var
, state_var_val
, goto_label_num
));
6181 out_branches
=update_location_object(out_branches
);
6182 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6185 mytmpid
.c_str(), (unsigned long) state_var
,
6186 (unsigned long) state_var_val
,
6187 mytmpid
.c_str(), mytmpid
.c_str(),
6188 (unsigned long) goto_label_num
);
6191 void Statement::ilt_generate_code_def(ILT
*ilt
)
6193 char*& str
=ilt
->get_out_branches();
6194 str
=update_location_object(str
);
6196 char *genname
=mprintf("%s_d%lu_%s", ilt
->get_my_tmpid().c_str(),
6197 (unsigned long) ilt
->get_new_tmpnum(),
6198 def
->get_id().get_name().c_str());
6199 def
->set_genname(string(genname
));
6202 def
->ilt_generate_code(ilt
);
6205 void Statement::ilt_generate_code_if(ILT
*ilt
)
6207 char *end_label
=mprintf("%s_l%lu",
6208 ilt
->get_my_tmpid().c_str(),
6209 (unsigned long) ilt
->get_new_label_num());
6211 if_stmt
.ics
->ilt_generate_code(ilt
, end_label
, unreach
);
6212 if(if_stmt
.elseblock
&& !unreach
)
6213 if_stmt
.elseblock
->ilt_generate_code(ilt
);
6214 char*& str
=ilt
->get_out_branches();
6215 str
=mputprintf(str
, "%s:\n", end_label
);
6219 void Statement::ilt_generate_code_select(ILT
*ilt
)
6221 char*& str
=ilt
->get_out_branches();
6222 str
=update_location_object(str
);
6223 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6224 char *expr_init
=memptystr();
6225 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
6226 select
.scs
->ilt_generate_code(ilt
, tmp_prefix
.c_str(),
6227 expr_init
, expr_name
);
6232 void Statement::ilt_generate_code_call(ILT
*ilt
)
6234 char*& str
=ilt
->get_out_branches();
6235 str
=update_location_object(str
);
6236 expression_struct expr
;
6237 Code::init_expr(&expr
);
6238 port_op
.portref
->generate_code(&expr
);
6239 expr
.expr
= mputstr(expr
.expr
, ".call(");
6240 port_op
.s
.sendpar
->generate_code(&expr
);
6241 if(port_op
.s
.toclause
) {
6242 expr
.expr
= mputstr(expr
.expr
, ", ");
6243 port_op
.s
.toclause
->generate_code_expr(&expr
);
6245 expr
.expr
= mputc(expr
.expr
, ')');
6246 str
= Code::merge_free_expr(str
, &expr
);
6247 if (port_op
.s
.call
.body
) {
6248 str
= mputstr(str
, "{\n"); // (1)
6249 if (port_op
.s
.call
.timer
) {
6250 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6251 str
= mputstr(str
, "TIMER call_timer;\n");
6252 Code::init_expr(&expr
);
6253 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6254 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6255 expr
.expr
= mputc(expr
.expr
, ')');
6256 str
= Code::merge_free_expr(str
, &expr
);
6258 // the label name is used for prefixing local variables
6259 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6260 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6261 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this, tmplabel
,
6263 const char *label_str
= tmplabel
.c_str();
6264 str
=mputprintf(str
, "goto %s_end;\n"
6267 port_op
.s
.call
.body
->ilt_generate_code_call_body(ilt
, label_str
);
6268 str
=mputprintf(str
, "%s_end:\n", label_str
);
6272 void Statement::ilt_generate_code_for(ILT
*ilt
)
6274 char*& str
= ilt
->get_out_branches();
6275 str
= update_location_object(str
);
6276 // statements in initial may have side effects
6277 // generate code for them anyway
6278 if (loop
.for_stmt
.varinst
) {
6279 char *genname
= mprintf("%s_d%lu_", ilt
->get_my_tmpid().c_str(),
6280 (unsigned long) ilt
->get_new_tmpnum());
6281 loop
.for_stmt
.init_varinst
->set_genname(string(genname
));
6283 loop
.for_stmt
.init_varinst
->ilt_generate_code(ilt
);
6284 } else str
= loop
.for_stmt
.init_ass
->generate_code(str
);
6285 // check whether the final expression is constant
6286 bool final_is_true
= false, final_is_false
= false;
6287 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
6288 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
6289 else final_is_false
= true;
6291 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6293 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6294 (unsigned long) ilt
->get_new_label_num());
6295 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6296 // do not generate the exit condition for infinite loops
6297 if (!final_is_true
) {
6298 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
6299 size_t blockcount
= 0;
6300 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
6302 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6303 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6307 loop
.il_label_end
= new string(label_prefix
);
6308 *loop
.il_label_end
+= "end";
6311 loop
.label_next
= new string(label_prefix
);
6312 *loop
.label_next
+= "next";
6314 loop
.block
->ilt_generate_code(ilt
);
6315 if (loop
.label_next
)
6316 str
= mputprintf(str
, "%snext:\n", label_prefix
);
6317 str
= update_location_object(str
);
6318 str
= loop
.for_stmt
.step
->generate_code(str
);
6319 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6320 if (!final_is_true
|| loop
.has_brk
)
6321 str
= mputprintf(str
, "%send:\n", label_prefix
);
6326 void Statement::ilt_generate_code_while(ILT
*ilt
)
6328 char*& str
= ilt
->get_out_branches();
6329 // Location need not be set here; the location is set for the expression.
6330 // check whether the expression is constant
6331 bool expr_is_true
= false, expr_is_false
= false;
6332 if (!loop
.expr
->is_unfoldable()) {
6333 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6334 else expr_is_false
= true;
6336 if (expr_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6338 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6339 (unsigned long) ilt
->get_new_label_num());
6340 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6343 loop
.il_label_end
= new string(label_prefix
);
6344 *loop
.il_label_end
+= "end";
6347 loop
.label_next
= new string(label_prefix
);
6348 *loop
.label_next
+= "begin";
6350 // do not generate the exit condition for infinite loops
6351 if (!expr_is_true
) {
6352 str
= loop
.expr
->update_location_object(str
);
6353 size_t blockcount
= 0;
6354 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6355 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6356 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6358 loop
.block
->ilt_generate_code(ilt
);
6359 str
= update_location_object(str
);
6360 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6361 if (!expr_is_true
|| loop
.has_brk
)
6362 str
= mputprintf(str
, "%send:\n", label_prefix
);
6367 void Statement::ilt_generate_code_dowhile(ILT
*ilt
)
6369 char*& str
= ilt
->get_out_branches();
6370 // Location need not be set here; there is only a label before the body.
6371 // check whether the expression is constant
6372 bool expr_is_true
= false;
6373 if (!loop
.expr
->is_unfoldable()) {
6374 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6375 else loop
.iterate_once
= true;
6377 char *label_prefix
= 0;
6378 if (!loop
.iterate_once
|| loop
.has_brk
|| loop
.has_cnt
)
6379 label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6380 (unsigned long) ilt
->get_new_label_num());
6383 loop
.il_label_end
= new string(label_prefix
);
6384 *loop
.il_label_end
+= "end";
6387 loop
.label_next
= new string(label_prefix
);
6388 if (loop
.iterate_once
) {
6389 if (loop
.label_next
) *loop
.label_next
+= "end";
6390 loop
.block
->ilt_generate_code(ilt
);
6392 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6393 if (loop
.label_next
)
6394 *loop
.label_next
+= (expr_is_true
? "begin" : "next");
6395 loop
.block
->ilt_generate_code(ilt
);
6396 if (expr_is_true
) str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6398 if (loop
.label_next
) str
= mputprintf(str
, "%snext:\n", label_prefix
);
6399 str
= loop
.expr
->update_location_object(str
);
6400 size_t blockcount
= 0;
6401 str
= loop
.expr
->generate_code_tmp(str
, "if (", blockcount
);
6402 str
= mputprintf(str
, ") goto %sbegin;\n", label_prefix
);
6403 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6406 if (loop
.il_label_end
|| (loop
.iterate_once
&& loop
.label_next
)) {
6407 str
= mputprintf(str
, "%send: ;\n", label_prefix
);
6412 char *Statement::generate_code_return(char *str
)
6414 expression_struct expr
;
6415 Code::init_expr(&expr
);
6416 expr
.expr
= mputstr(expr
.expr
, "return");
6417 Definition
*my_def
= my_sb
->get_my_def();
6419 expr
.expr
= mputc(expr
.expr
, ' ');
6420 returnexpr
.v
->generate_code_expr_mandatory(&expr
);
6421 } else if (returnexpr
.t
) {
6422 expr
.expr
= mputc(expr
.expr
, ' ');
6423 if (!my_def
) FATAL_ERROR("Statement::generate_code_return()");
6424 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
6425 if (!dfb
) FATAL_ERROR("Statement::generate_code_return()");
6426 if (dfb
->get_template_restriction() != TR_NONE
&&
6427 returnexpr
.gen_restriction_check
) {
6428 returnexpr
.t
->generate_code_expr(&expr
,
6429 dfb
->get_template_restriction());
6431 returnexpr
.t
->generate_code_expr(&expr
, TR_NONE
);
6434 if (my_def
&& my_def
->get_asstype() == Definition::A_ALTSTEP
)
6435 expr
.expr
= mputstr(expr
.expr
, " ALT_YES");
6436 // else it's a return with no value: the only case a blank is unneeded
6438 return Code::merge_free_expr(str
, &expr
);
6441 char *Statement::generate_code_activate(char *str
)
6443 expression_struct expr
;
6444 Code::init_expr(&expr
);
6445 expr
.expr
= mputprintf(expr
.expr
, "%s(", ref_pard
->get_refd_assignment()
6446 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6447 ref_pard
->get_parlist()->generate_code_noalias(&expr
, ref_pard
->get_refd_assignment()->get_FormalParList());
6448 expr
.expr
= mputc(expr
.expr
, ')');
6449 return Code::merge_free_expr(str
, &expr
);
6452 char *Statement::generate_code_activate_refd(char *str
)
6454 expression_struct expr
;
6455 Code::init_expr(&expr
);
6456 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6457 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
6458 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6459 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6461 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
6462 expr
.expr
= mputstr(expr
.expr
, ".activate(");
6464 fau_refd
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6465 expr
.expr
= mputc(expr
.expr
, ')');
6466 return Code::merge_free_expr(str
, &expr
);
6469 char *Statement::generate_code_deactivate(char *str
)
6471 if(!deactivate
) str
=mputstr(str
, "TTCN_Default::deactivate_all();\n");
6473 expression_struct expr
;
6474 Code::init_expr(&expr
);
6475 expr
.expr
=mputstr(expr
.expr
, "TTCN_Default::deactivate(");
6476 deactivate
->generate_code_expr(&expr
);
6477 expr
.expr
=mputstr(expr
.expr
, ");\n");
6478 str
=Code::merge_free_expr(str
, &expr
);
6483 char *Statement::generate_code_send(char *str
)
6485 expression_struct expr
;
6486 Code::init_expr(&expr
);
6487 port_op
.portref
->generate_code(&expr
);
6488 expr
.expr
= mputstr(expr
.expr
, ".send(");
6489 generate_code_expr_sendpar(&expr
);
6490 if (port_op
.s
.toclause
) {
6491 expr
.expr
= mputstr(expr
.expr
, ", ");
6492 port_op
.s
.toclause
->generate_code_expr(&expr
);
6494 expr
.expr
= mputc(expr
.expr
, ')');
6495 return Code::merge_free_expr(str
, &expr
);
6498 char *Statement::generate_code_call(char *str
)
6500 expression_struct expr
;
6501 Code::init_expr(&expr
);
6502 port_op
.portref
->generate_code(&expr
);
6503 expr
.expr
= mputstr(expr
.expr
, ".call(");
6504 port_op
.s
.sendpar
->generate_code(&expr
);
6505 if(port_op
.s
.toclause
) {
6506 expr
.expr
= mputstr(expr
.expr
, ", ");
6507 port_op
.s
.toclause
->generate_code_expr(&expr
);
6509 expr
.expr
= mputc(expr
.expr
, ')');
6510 str
= Code::merge_free_expr(str
, &expr
);
6511 if (port_op
.s
.call
.body
) {
6512 str
= mputstr(str
, "{\n");
6513 if (port_op
.s
.call
.timer
) {
6514 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6515 str
= mputstr(str
, "TIMER call_timer;\n");
6516 Code::init_expr(&expr
);
6517 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6518 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6519 expr
.expr
= mputc(expr
.expr
, ')');
6520 str
= Code::merge_free_expr(str
, &expr
);
6522 // the label name is used for prefixing local variables
6523 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6524 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this,
6525 my_sb
->get_scope_mod_gen()->get_temporary_id(), false);
6526 str
=mputstr(str
, "}\n");
6531 char *Statement::generate_code_reply(char *str
)
6533 expression_struct expr
;
6534 Code::init_expr(&expr
);
6535 port_op
.portref
->generate_code(&expr
);
6536 expr
.expr
=mputstr(expr
.expr
, ".reply(");
6537 port_op
.s
.sendpar
->generate_code(&expr
);
6538 if(port_op
.s
.replyval
) {
6539 expr
.expr
=mputstr(expr
.expr
, ".set_value_template(");
6540 port_op
.s
.replyval
->generate_code_expr(&expr
);
6541 expr
.expr
=mputc(expr
.expr
, ')');
6543 if(port_op
.s
.toclause
) {
6544 expr
.expr
=mputstr(expr
.expr
, ", ");
6545 port_op
.s
.toclause
->generate_code_expr(&expr
);
6547 expr
.expr
=mputc(expr
.expr
, ')');
6548 return Code::merge_free_expr(str
, &expr
);
6551 char *Statement::generate_code_raise(char *str
)
6553 expression_struct expr
;
6554 Code::init_expr(&expr
);
6555 port_op
.portref
->generate_code(&expr
);
6556 expr
.expr
=mputstr(expr
.expr
, ".raise(");
6557 port_op
.s
.raise
.signature_ref
->generate_code(&expr
);
6558 expr
.expr
=mputstr(expr
.expr
, "_exception(");
6559 generate_code_expr_sendpar(&expr
);
6560 expr
.expr
=mputc(expr
.expr
, ')');
6561 if(port_op
.s
.toclause
) {
6562 expr
.expr
=mputstr(expr
.expr
, ", ");
6563 port_op
.s
.toclause
->generate_code_expr(&expr
);
6565 expr
.expr
=mputc(expr
.expr
, ')');
6566 return Code::merge_free_expr(str
, &expr
);
6569 char *Statement::generate_code_portop(char *str
, const char *opname
)
6571 if (port_op
.portref
) {
6572 expression_struct expr
;
6573 Code::init_expr(&expr
);
6574 port_op
.portref
->generate_code(&expr
);
6575 expr
.expr
=mputprintf(expr
.expr
, ".%s()", opname
);
6576 str
=Code::merge_free_expr(str
, &expr
);
6578 str
= mputprintf(str
, "PORT::all_%s();\n", opname
);
6583 char *Statement::generate_code_startcomp(char *str
)
6585 expression_struct expr
;
6586 Code::init_expr(&expr
);
6587 Common::Assignment
*func
= comp_op
.funcinstref
->get_refd_assignment();
6588 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6589 func
->get_genname_from_scope(my_sb
, "start_").c_str());
6590 comp_op
.compref
->generate_code_expr(&expr
);
6591 FormalParList
*fplist
= func
->get_FormalParList();
6592 if (fplist
->get_nof_fps() > 0) {
6593 expr
.expr
= mputstr(expr
.expr
, ", ");
6594 comp_op
.funcinstref
->get_parlist()->generate_code_noalias(&expr
, fplist
);
6596 expr
.expr
= mputc(expr
.expr
, ')');
6597 return Code::merge_free_expr(str
, &expr
);
6600 char *Statement::generate_code_startcomp_refd(char *str
)
6602 expression_struct expr
;
6603 Code::init_expr(&expr
);
6604 Value
*last_v
= comp_op
.derefered
.value
->get_value_refd_last();
6605 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
6606 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6607 ->get_genname_from_scope(my_sb
, "start_").c_str());
6609 comp_op
.derefered
.value
->generate_code_expr_mandatory(&expr
);
6610 expr
.expr
= mputstr(expr
.expr
, ".start(");
6612 comp_op
.compref
->generate_code_expr(&expr
);
6613 if (comp_op
.derefered
.ap_list2
->get_nof_pars() > 0) {
6614 expr
.expr
= mputstr(expr
.expr
, ", ");
6615 comp_op
.derefered
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6617 expr
.expr
= mputc(expr
.expr
, ')');
6618 return Code::merge_free_expr(str
, &expr
);
6621 char *Statement::generate_code_compop(char *str
, const char *opname
)
6623 expression_struct expr
;
6624 Code::init_expr(&expr
);
6625 if (comp_op
.compref
) {
6626 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
6627 if (v_last
->get_valuetype() == Value::V_REFD
) {
6628 // the argument is a simple component reference
6629 v_last
->generate_code_expr_mandatory(&expr
);
6630 expr
.expr
= mputprintf(expr
.expr
, ".%s()", opname
);
6632 bool refers_to_self
= false;
6633 if (v_last
->get_valuetype() == Value::V_EXPR
) {
6634 // the argument is a special component reference (mtc, self, etc.)
6635 switch (v_last
->get_optype()) {
6636 case Value::OPTYPE_COMP_MTC
: {
6637 Definition
*my_def
= my_sb
->get_my_def();
6638 if (my_def
&& my_def
->get_asstype() == Definition::A_TESTCASE
)
6639 refers_to_self
= true;
6641 case Value::OPTYPE_COMP_SELF
:
6642 refers_to_self
= true;
6647 if (refers_to_self
) {
6648 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_execution()",
6651 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_component(",
6653 v_last
->generate_code_expr(&expr
);
6654 expr
.expr
= mputc(expr
.expr
, ')');
6658 // the operation refers to all component
6659 expr
.expr
= mputprintf(expr
.expr
,
6660 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname
);
6662 return Code::merge_free_expr(str
, &expr
);
6665 char *Statement::generate_code_configop(char *str
, const char *opname
)
6667 expression_struct expr
;
6668 Code::init_expr(&expr
);
6669 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_port(", opname
);
6670 config_op
.compref1
->generate_code_expr(&expr
);
6671 expr
.expr
= mputstr(expr
.expr
, ", ");
6672 if (config_op
.compref1
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6673 // the component type is known
6674 // the name of the referred port can be used
6675 config_op
.portref1
->generate_code_portref(&expr
, my_sb
);
6676 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6678 // the component type is unknown
6679 // a simple string shall be formed from the port name and array indices
6680 generate_code_portref(&expr
, config_op
.portref1
);
6682 expr
.expr
= mputstr(expr
.expr
, ", ");
6683 config_op
.compref2
->generate_code_expr(&expr
);
6684 expr
.expr
= mputstr(expr
.expr
, ", ");
6685 if (config_op
.compref2
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6686 // the component type is known
6687 // the name of the referred port can be used
6688 config_op
.portref2
->generate_code_portref(&expr
, my_sb
);
6689 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6691 // the component type is unknown
6692 // a simple string shall be formed from the port name and array indices
6693 generate_code_portref(&expr
, config_op
.portref2
);
6695 expr
.expr
= mputc(expr
.expr
, ')');
6696 return Code::merge_free_expr(str
, &expr
);
6699 char *Statement::generate_code_starttimer(char *str
)
6701 expression_struct expr
;
6702 Code::init_expr(&expr
);
6703 timer_op
.timerref
->generate_code(&expr
);
6704 expr
.expr
=mputstr(expr
.expr
, ".start(");
6705 if(timer_op
.value
) timer_op
.value
->generate_code_expr(&expr
);
6706 expr
.expr
=mputc(expr
.expr
, ')');
6707 str
=Code::merge_free_expr(str
, &expr
);
6711 char *Statement::generate_code_stoptimer(char *str
)
6713 if(!timer_op
.timerref
) str
=mputstr(str
, "TIMER::all_stop();\n");
6715 expression_struct expr
;
6716 Code::init_expr(&expr
);
6717 timer_op
.timerref
->generate_code(&expr
);
6718 expr
.expr
=mputstr(expr
.expr
, ".stop()");
6719 str
=Code::merge_free_expr(str
, &expr
);
6724 char *Statement::generate_code_setverdict(char *str
)
6726 expression_struct expr
;
6727 Code::init_expr(&expr
);
6728 expr
.expr
=mputstr(expr
.expr
, "TTCN_Runtime::setverdict(");
6729 setverdict
.verdictval
->generate_code_expr(&expr
);
6730 if (setverdict
.logargs
) {
6731 expr
.expr
=mputc(expr
.expr
, ',');
6732 expression_struct expr_reason
;
6733 Code::init_expr(&expr_reason
);
6734 setverdict
.logargs
->generate_code_expr(&expr_reason
);
6735 if (expr_reason
.preamble
)
6736 expr
.preamble
= mputprintf(expr
.preamble
, "%s;\n",
6737 expr_reason
.preamble
);
6738 if (expr_reason
.postamble
)
6739 expr
.postamble
= mputprintf(expr
.postamble
, "%s;\n",
6740 expr_reason
.postamble
);
6741 expr
.expr
= mputprintf(expr
.expr
, "%s", expr_reason
.expr
);
6742 Code::free_expr(&expr_reason
);
6744 expr
.expr
=mputc(expr
.expr
, ')');
6745 str
=Code::merge_free_expr(str
, &expr
);
6749 char *Statement::generate_code_action(char *str
)
6751 str
=mputstr(str
, "TTCN_Runtime::begin_action();\n");
6752 if(!logargs
) str
=mputstr(str
, "TTCN_Logger::log_event_str"
6753 "(\"<empty action statement>\");\n");
6754 else str
=logargs
->generate_code(str
);
6755 str
=mputstr(str
, "TTCN_Runtime::end_action();\n");
6759 char *Statement::generate_code_testcaseinst(char *str
)
6761 expression_struct expr
;
6762 Code::init_expr(&expr
);
6763 Common::Assignment
*testcase
= testcase_inst
.tcref
->get_refd_assignment();
6764 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6765 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6766 ActualParList
*t_aplist
= testcase_inst
.tcref
->get_parlist();
6767 if (t_aplist
->get_nof_pars() > 0) {
6768 t_aplist
->generate_code_alias(&expr
, testcase
->get_FormalParList(),
6770 expr
.expr
= mputstr(expr
.expr
, ", ");
6772 if (testcase_inst
.timerval
) {
6773 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6774 testcase_inst
.timerval
->generate_code_expr(&expr
);
6775 expr
.expr
= mputc(expr
.expr
, ')');
6776 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6777 return Code::merge_free_expr(str
, &expr
);
6780 char *Statement::generate_code_execute_refd(char *str
)
6782 expression_struct expr
;
6783 Code::init_expr(&expr
);
6784 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6785 if (last_v
->get_valuetype() == Value::V_TESTCASE
) {
6786 Common::Assignment
*testcase
= last_v
->get_refd_fat();
6787 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6788 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6789 execute_refd
.ap_list2
->generate_code_alias(&expr
,
6790 testcase
->get_FormalParList(), 0, false);
6792 execute_refd
.value
->generate_code_expr_mandatory(&expr
);
6793 expr
.expr
= mputstr(expr
.expr
, ".execute(");
6794 execute_refd
.ap_list2
->generate_code_alias(&expr
, 0, 0, false);
6796 if (execute_refd
.ap_list2
->get_nof_pars() > 0)
6797 expr
.expr
= mputstr(expr
.expr
, ", ");
6798 if (execute_refd
.timerval
) {
6799 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6800 execute_refd
.timerval
->generate_code_expr(&expr
);
6801 expr
.expr
= mputc(expr
.expr
, ')');
6802 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6803 return Code::merge_free_expr(str
,&expr
);
6806 void Statement::generate_code_expr_receive(expression_struct
*expr
,
6809 if (port_op
.portref
) {
6810 // The operation refers to a specific port.
6811 port_op
.portref
->generate_code(expr
);
6812 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6813 if (port_op
.r
.rcvpar
) {
6814 // The receive parameter is present.
6815 if (use_runtime_2
&& TypeConv::needs_conv_redir(port_op
.r
.rcvpar
,
6816 port_op
.r
.redirect
.value
)) {
6817 // Don't change the first parameter. Otherwise it won't receive
6818 // anything. The only thing we need is a temporary to save the
6819 // result and a conversion at the end.
6820 TypeConv::gen_conv_code_redir(expr
, port_op
.r
.rcvpar
,
6821 port_op
.r
.redirect
.value
);
6823 port_op
.r
.rcvpar
->generate_code(expr
);
6824 expr
->expr
= mputstr(expr
->expr
, ", ");
6825 if (port_op
.r
.redirect
.value
) {
6826 // Value redirect is also present.
6827 expr
->expr
= mputstr(expr
->expr
, "&(");
6828 port_op
.r
.redirect
.value
->generate_code(expr
);
6829 expr
->expr
= mputc(expr
->expr
, ')');
6830 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6832 expr
->expr
= mputstr(expr
->expr
, ", ");
6835 // the operation refers to any port
6836 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6838 generate_code_expr_fromclause(expr
);
6839 expr
->expr
= mputstr(expr
->expr
, ", ");
6840 generate_code_expr_senderredirect(expr
);
6841 expr
->expr
= mputc(expr
->expr
, ')');
6844 void Statement::generate_code_expr_getcall(expression_struct
*expr
,
6847 if (port_op
.portref
) {
6848 // the operation refers to a specific port
6849 port_op
.portref
->generate_code(expr
);
6850 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6851 if (port_op
.r
.rcvpar
) {
6852 // the signature template is present
6853 port_op
.r
.rcvpar
->generate_code(expr
);
6854 expr
->expr
= mputstr(expr
->expr
, ", ");
6855 generate_code_expr_fromclause(expr
);
6856 // a temporary object is needed for parameter redirect
6857 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6858 expr
->expr
= mputprintf(expr
->expr
, ", %s_call_redirect(",
6859 signature
->get_genname_value(my_sb
).c_str());
6860 if (port_op
.r
.redirect
.param
)
6861 port_op
.r
.redirect
.param
->generate_code(expr
);
6862 expr
->expr
= mputstr(expr
->expr
, "), ");
6863 generate_code_expr_senderredirect(expr
);
6865 // the signature parameter is not present
6866 generate_code_expr_fromclause(expr
);
6867 expr
->expr
= mputstr(expr
->expr
, ", ");
6868 generate_code_expr_senderredirect(expr
);
6871 // the operation refers to any port
6872 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6873 generate_code_expr_fromclause(expr
);
6874 expr
->expr
= mputstr(expr
->expr
, ", ");
6875 generate_code_expr_senderredirect(expr
);
6877 expr
->expr
=mputc(expr
->expr
, ')');
6880 void Statement::generate_code_expr_getreply(expression_struct
*expr
,
6883 if (port_op
.portref
) {
6884 // the operation refers to a specific port
6885 port_op
.portref
->generate_code(expr
);
6886 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6887 if (port_op
.r
.rcvpar
) {
6888 // the signature template is present
6889 port_op
.r
.rcvpar
->generate_code(expr
);
6890 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6892 signature
->get_type_refd_last()->get_signature_return_type();
6894 expr
->expr
= mputstr(expr
->expr
, ".set_value_template(");
6895 if (port_op
.r
.getreply_valuematch
) {
6896 // the value match is also present
6897 port_op
.r
.getreply_valuematch
->generate_code(expr
);
6899 // the value match is not present
6900 // we must substitute it with ? in the signature template
6901 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6902 return_type
->get_genname_template(my_sb
).c_str());
6904 expr
->expr
= mputc(expr
->expr
, ')');
6906 expr
->expr
= mputstr(expr
->expr
, ", ");
6907 generate_code_expr_fromclause(expr
);
6908 // a temporary object is needed for value and parameter redirect
6909 expr
->expr
= mputprintf(expr
->expr
, ", %s_reply_redirect(",
6910 signature
->get_genname_value(my_sb
).c_str());
6912 // the first argument of the constructor must contain
6913 // the value redirect
6914 if (port_op
.r
.redirect
.value
) {
6915 expr
->expr
= mputstr(expr
->expr
, "&(");
6916 port_op
.r
.redirect
.value
->generate_code(expr
);
6917 expr
->expr
= mputc(expr
->expr
, ')');
6918 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6919 if (port_op
.r
.redirect
.param
) expr
->expr
= mputstr(expr
->expr
, ", ");
6921 if (port_op
.r
.redirect
.param
)
6922 port_op
.r
.redirect
.param
->generate_code(expr
);
6923 expr
->expr
= mputstr(expr
->expr
, "), ");
6924 generate_code_expr_senderredirect(expr
);
6926 // the signature template is not present
6927 generate_code_expr_fromclause(expr
);
6928 expr
->expr
= mputstr(expr
->expr
, ", ");
6929 generate_code_expr_senderredirect(expr
);
6932 // the operation refers to any port
6933 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6934 generate_code_expr_fromclause(expr
);
6935 expr
->expr
= mputstr(expr
->expr
, ", ");
6936 generate_code_expr_senderredirect(expr
);
6938 expr
->expr
= mputc(expr
->expr
, ')');
6941 void Statement::generate_code_expr_catch(expression_struct
*expr
)
6943 if (port_op
.portref
) {
6944 // the operation refers to a specific port
6945 if (port_op
.r
.ctch
.timeout
) {
6946 // the operation catches the timeout exception
6947 expr
->expr
= mputstr(expr
->expr
, "call_timer.timeout()");
6950 port_op
.portref
->generate_code(expr
);
6951 expr
->expr
= mputprintf(expr
->expr
, ".%s(",
6952 statementtype
== S_CHECK_CATCH
? "check_catch" : "get_exception");
6953 if (port_op
.r
.ctch
.signature_ref
) {
6954 // the signature reference and the exception template is present
6955 expr
->expr
= mputprintf(expr
->expr
, "%s_exception_template(",
6956 port_op
.r
.ctch
.signature
->get_genname_value(my_sb
).c_str());
6957 port_op
.r
.rcvpar
->generate_code(expr
);
6958 expr
->expr
= mputstr(expr
->expr
, ", ");
6959 if (port_op
.r
.redirect
.value
) {
6960 // value redirect is also present
6961 expr
->expr
= mputstr(expr
->expr
, "&(");
6962 port_op
.r
.redirect
.value
->generate_code(expr
);
6963 expr
->expr
= mputc(expr
->expr
, ')');
6964 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6965 expr
->expr
= mputstr(expr
->expr
, "), ");
6968 // the operation refers to any port
6969 expr
->expr
= mputprintf(expr
->expr
, "PORT::%s(",
6970 statementtype
== S_CHECK_CATCH
? "any_check_catch" : "any_catch");
6972 generate_code_expr_fromclause(expr
);
6973 expr
->expr
= mputstr(expr
->expr
, ", ");
6974 generate_code_expr_senderredirect(expr
);
6975 expr
->expr
= mputc(expr
->expr
, ')');
6978 void Statement::generate_code_expr_check(expression_struct
*expr
)
6980 if (port_op
.portref
) {
6981 // the operation refers to a specific port
6982 port_op
.portref
->generate_code(expr
);
6983 expr
->expr
= mputstr(expr
->expr
, ".check");
6985 // the operation refers to any port
6986 expr
->expr
= mputstr(expr
->expr
, "PORT::any_check");
6988 expr
->expr
= mputc(expr
->expr
, '(');
6989 generate_code_expr_fromclause(expr
);
6990 expr
->expr
= mputstr(expr
->expr
, ", ");
6991 generate_code_expr_senderredirect(expr
);
6992 expr
->expr
= mputc(expr
->expr
, ')');
6995 void Statement::generate_code_expr_done(expression_struct
*expr
)
6997 if (comp_op
.compref
) {
6998 if (comp_op
.donereturn
.donematch
) {
6999 // value returning done
7000 // figure out what type the done() function belongs to
7001 Type
*t
= comp_op
.donereturn
.donematch
7002 ->get_expr_governor(Type::EXPECTED_TEMPLATE
);
7003 if (!t
) FATAL_ERROR("Statement::generate_code_expr_done()");
7004 while (t
->is_ref() && !t
->has_done_attribute())
7005 t
= t
->get_type_refd();
7006 if (!t
->has_done_attribute())
7007 FATAL_ERROR("Statement::generate_code_expr_done()");
7008 // determine whether the done() function is in the same module
7009 Common::Module
*t_mod
= t
->get_my_scope()->get_scope_mod_gen();
7010 if (t_mod
!= my_sb
->get_scope_mod_gen()) {
7011 expr
->expr
= mputprintf(expr
->expr
, "%s::",
7012 t_mod
->get_modid().get_name().c_str());
7014 expr
->expr
= mputstr(expr
->expr
, "done(");
7015 comp_op
.compref
->generate_code_expr(expr
);
7016 expr
->expr
= mputstr(expr
->expr
, ", ");
7017 comp_op
.donereturn
.donematch
->generate_code(expr
);
7018 expr
->expr
= mputstr(expr
->expr
, ", ");
7019 if (comp_op
.donereturn
.redirect
) {
7020 // value redirect is present
7021 expr
->expr
= mputstr(expr
->expr
, "&(");
7022 comp_op
.donereturn
.redirect
->generate_code(expr
);
7023 expr
->expr
= mputc(expr
->expr
, ')');
7025 // value redirect is omitted
7026 expr
->expr
= mputstr(expr
->expr
, "NULL");
7028 expr
->expr
= mputc(expr
->expr
, ')');
7031 comp_op
.compref
->generate_code_expr_mandatory(expr
);
7032 expr
->expr
= mputstr(expr
->expr
, ".done()");
7034 } else if (comp_op
.any_or_all
== C_ANY
) {
7035 // any component.done
7036 expr
->expr
= mputstr(expr
->expr
,
7037 "TTCN_Runtime::component_done(ANY_COMPREF)");
7039 // all component.done
7040 expr
->expr
= mputstr(expr
->expr
,
7041 "TTCN_Runtime::component_done(ALL_COMPREF)");
7045 void Statement::generate_code_expr_killed(expression_struct
*expr
)
7047 if (comp_op
.compref
) {
7049 comp_op
.compref
->generate_code_expr_mandatory(expr
);
7050 expr
->expr
= mputstr(expr
->expr
, ".killed()");
7051 } else if (comp_op
.any_or_all
== C_ANY
) {
7052 // any component.killed
7053 expr
->expr
= mputstr(expr
->expr
,
7054 "TTCN_Runtime::component_killed(ANY_COMPREF)");
7056 // all component.killed
7057 expr
->expr
= mputstr(expr
->expr
,
7058 "TTCN_Runtime::component_killed(ALL_COMPREF)");
7062 void Statement::generate_code_expr_timeout(expression_struct
*expr
)
7064 if (timer_op
.timerref
) {
7065 timer_op
.timerref
->generate_code(expr
);
7066 expr
->expr
=mputstr(expr
->expr
, ".timeout()");
7067 } else expr
->expr
= mputstr(expr
->expr
, "TIMER::any_timeout()");
7070 void Statement::generate_code_expr_sendpar(expression_struct
*expr
)
7072 Template
*templ_body
= port_op
.s
.sendpar
->get_Template();
7073 if (!port_op
.s
.sendpar
->get_DerivedRef() &&
7074 templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
) {
7075 // the send parameter is a value: optimization is possible
7076 Value
*t_val
= templ_body
->get_specific_value();
7077 bool cast_needed
= t_val
->explicit_cast_needed();
7079 // the ambiguous C++ expression is converted to the value class
7080 expr
->expr
= mputprintf(expr
->expr
, "%s(",
7081 t_val
->get_my_governor()->get_genname_value(my_sb
).c_str());
7083 t_val
->generate_code_expr_mandatory(expr
);
7084 if (cast_needed
) expr
->expr
= mputc(expr
->expr
, ')');
7086 // the send parameter is a real template: optimization is not possible
7087 port_op
.s
.sendpar
->generate_code(expr
);
7091 void Statement::generate_code_expr_fromclause(expression_struct
*expr
)
7093 if (port_op
.r
.fromclause
) {
7094 // the from clause is present: trivial case
7095 port_op
.r
.fromclause
->generate_code(expr
);
7096 } else if (port_op
.r
.redirect
.sender
) {
7097 // from clause is omitted, but sender redirect is present
7098 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
7100 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
7101 if (t_var_type
->get_type_refd_last()->get_typetype() ==
7102 Type::T_COMPONENT
) {
7103 // the variable can store a component reference
7104 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7106 // the variable can store an address value
7107 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
7108 t_var_type
->get_genname_template(my_sb
).c_str());
7111 // neither from clause nor sender redirect is present
7112 // the operation cannot refer to address type
7113 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7117 void Statement::generate_code_expr_senderredirect(expression_struct
*expr
)
7119 if (port_op
.r
.redirect
.sender
) {
7120 expr
->expr
= mputstr(expr
->expr
, "&(");
7121 port_op
.r
.redirect
.sender
->generate_code(expr
);
7122 expr
->expr
= mputc(expr
->expr
, ')');
7123 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
7126 void Statement::generate_code_portref(expression_struct
*expr
,
7129 // make a backup of the current expression
7130 char *expr_backup
= expr
->expr
;
7131 // build the equivalent of p_ref in expr->expr
7132 expr
->expr
= mprintf("\"%s\"", p_ref
->get_id()->get_dispname().c_str());
7133 FieldOrArrayRefs
*t_subrefs
= p_ref
->get_subrefs();
7135 // array indices are present
7136 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
7137 FieldOrArrayRef
*t_ref
= t_subrefs
->get_ref(i
);
7138 if (t_ref
->get_type() != FieldOrArrayRef::ARRAY_REF
)
7139 FATAL_ERROR("Statement::generate_code_portref()");
7140 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7141 char *tmp
= expr
->expr
;
7142 expr
->expr
= mcopystr("get_port_name(");
7143 expr
->expr
= mputstr(expr
->expr
, tmp
);
7145 expr
->expr
= mputstr(expr
->expr
, ", ");
7146 t_ref
->get_val()->generate_code_expr(expr
);
7147 expr
->expr
= mputc(expr
->expr
, ')');
7150 // now expr->expr contains the equivalent of p_ref
7151 // append it to the original expression and restore the result
7152 expr_backup
= mputstr(expr_backup
, expr
->expr
);
7154 expr
->expr
= expr_backup
;
7157 void Statement::set_parent_path(WithAttribPath
* p_path
) {
7158 switch (statementtype
) {
7160 def
->set_parent_path(p_path
);
7163 block
->set_parent_path(p_path
);
7166 if_stmt
.ics
->set_parent_path(p_path
);
7167 if (if_stmt
.elseblock
)
7168 if_stmt
.elseblock
->set_parent_path(p_path
);
7171 select
.scs
->set_parent_path(p_path
);
7174 loop
.block
->set_parent_path(p_path
);
7178 loop
.block
->set_parent_path(p_path
);
7189 case S_STOP_TESTCASE
:
7193 case S_UNKNOWN_INSTANCE
:
7194 case S_FUNCTION_INSTANCE
:
7195 case S_ALTSTEP_INSTANCE
:
7206 case S_CHECK_RECEIVE
:
7209 case S_CHECK_GETCALL
:
7211 case S_CHECK_GETREPLY
:
7220 case S_START_COMP_REFD
:
7233 case S_TESTCASE_INSTANCE
:
7234 case S_TESTCASE_INSTANCE_REFD
:
7235 case S_ACTIVATE_REFD
:
7236 case S_UNKNOWN_INVOKED
:
7237 case S_FUNCTION_INVOKED
:
7238 case S_ALTSTEP_INVOKED
:
7240 case S_START_PROFILER
:
7241 case S_STOP_PROFILER
:
7245 FATAL_ERROR("Statement::set_parent_path()");
7249 // =================================
7251 // =================================
7253 Assignment::Assignment(Reference
*p_ref
, Template
*p_templ
)
7254 : asstype(ASS_UNKNOWN
), ref(p_ref
), templ(p_templ
), self_ref(false),
7255 template_restriction(TR_NONE
), gen_restriction_check(false)
7257 if(!ref
|| !templ
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7260 Assignment::Assignment(Reference
*p_ref
, Value
*p_val
)
7261 : asstype(ASS_VAR
), ref(p_ref
), val(p_val
), self_ref(false),
7262 template_restriction(TR_NONE
), gen_restriction_check(false)
7264 if(!ref
|| !val
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7267 Assignment::~Assignment()
7282 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7286 Assignment
*Assignment::clone() const
7288 FATAL_ERROR("Assignment::clone");
7291 void Assignment::set_my_scope(Scope
*p_scope
)
7296 ref
->set_my_scope(p_scope
);
7297 templ
->set_my_scope(p_scope
);
7300 ref
->set_my_scope(p_scope
);
7301 val
->set_my_scope(p_scope
);
7306 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7310 void Assignment::set_fullname(const string
& p_fullname
)
7312 Node::set_fullname(p_fullname
);
7316 ref
->set_fullname(p_fullname
);
7317 templ
->set_fullname(p_fullname
);
7320 ref
->set_fullname(p_fullname
);
7321 val
->set_fullname(p_fullname
);
7326 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7330 void Assignment::dump(unsigned int level
) const
7332 // warning, ref is not always set (e.g. ASS_ERROR)
7340 DEBUG(level
, "*** ERROR ***");
7344 DEBUG(level
, "*** UNKNOWN ***");
7349 templ
->dump(level
+1);
7354 void Assignment::chk_unknown_ass()
7356 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7357 if (!t_ass
) goto error
;
7358 switch (t_ass
->get_asstype()) {
7359 case Common::Assignment::A_ERROR
:
7361 case Common::Assignment::A_PAR_VAL_IN
:
7362 t_ass
->use_as_lvalue(*ref
);
7364 case Common::Assignment::A_VAR
:
7365 case Common::Assignment::A_PAR_VAL_OUT
:
7366 case Common::Assignment::A_PAR_VAL_INOUT
:
7367 if (templ
->is_Value()) {
7368 Value
*t_val
= templ
->get_Value();
7374 templ
->error("A template body with matching symbols cannot be"
7375 " assigned to a variable");
7379 case Common::Assignment::A_PAR_TEMPL_IN
:
7380 t_ass
->use_as_lvalue(*ref
);
7382 case Common::Assignment::A_VAR_TEMPLATE
: {
7383 Type::typetype_t tt
= t_ass
->get_Type()->get_typetype();
7386 case Type::T_BSTR_A
:
7391 case Type::T_UTF8STRING
:
7392 case Type::T_NUMERICSTRING
:
7393 case Type::T_PRINTABLESTRING
:
7394 case Type::T_TELETEXSTRING
:
7395 case Type::T_VIDEOTEXSTRING
:
7396 case Type::T_IA5STRING
:
7397 case Type::T_GRAPHICSTRING
:
7398 case Type::T_VISIBLESTRING
:
7399 case Type::T_GENERALSTRING
:
7400 case Type::T_UNIVERSALSTRING
:
7401 case Type::T_BMPSTRING
:
7402 case Type::T_UTCTIME
:
7403 case Type::T_GENERALIZEDTIME
:
7404 case Type::T_OBJECTDESCRIPTOR
: {
7405 Ttcn::FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7406 if (!subrefs
) break;
7407 size_t nof_subrefs
= subrefs
->get_nof_refs();
7408 if (nof_subrefs
> 0) {
7409 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
7410 ->get_ref(nof_subrefs
- 1);
7411 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
7412 if (!templ
->is_Value()) {
7413 templ
->error("A template body with matching symbols cannot be "
7414 "assigned to an element of a template variable");
7424 case Common::Assignment::A_PAR_TEMPL_OUT
:
7425 case Common::Assignment::A_PAR_TEMPL_INOUT
:
7426 asstype
= ASS_TEMPLATE
;
7430 ref
->error("Reference to a variable or template variable was expected "
7431 "instead of %s", t_ass
->get_description().c_str());
7438 asstype
= ASS_ERROR
;
7442 void Assignment::chk_var_ass()
7444 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7445 Type
*var_type
= lhs
->get_Type();
7446 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7448 var_type
->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7449 if (!type
) goto error
;
7450 val
->set_my_governor(type
);
7451 type
->chk_this_value_ref(val
);
7452 if (val
->get_value_refd_last()->get_valuetype() == Value::V_OMIT
) {
7453 Identifier
*field_id
= 0;
7454 if (subrefs
) field_id
= subrefs
->remove_last_field();
7456 val
->error("Omit value can be assigned to an optional field of "
7457 "a record or set value only");
7460 Type
*base_type
= var_type
7461 ->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7462 // Putting field_id back to subrefs.
7463 subrefs
->add(new FieldOrArrayRef(field_id
));
7464 base_type
= base_type
->get_type_refd_last();
7465 switch (base_type
->get_typetype()) {
7474 val
->error("Omit value can be assigned to an optional field of "
7475 "a record or set value only");
7478 if (!base_type
->get_comp_byName(*field_id
)->get_is_optional()) {
7479 val
->error("Assignment of `omit' to mandatory field `%s' of type "
7480 "`%s'", field_id
->get_dispname().c_str(),
7481 base_type
->get_typename().c_str());
7485 bool is_string_element
= subrefs
&& subrefs
->refers_to_string_element();
7486 self_ref
|= type
->chk_this_value(val
, lhs
, Type::EXPECTED_DYNAMIC_VALUE
,
7487 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
,
7488 (is_string_element
? NO_SUB_CHK
: SUB_CHK
), NOT_IMPLICIT_OMIT
,
7489 (is_string_element
? IS_STR_ELEM
: NOT_STR_ELEM
));
7490 if (is_string_element
) {
7491 // The length of RHS value shall be 1.
7492 Value
*v_last
= val
->get_value_refd_last();
7493 switch (type
->get_type_refd_last()->get_typetype()) {
7495 case Type::T_BSTR_A
:
7496 if (v_last
->get_valuetype() != Value::V_BSTR
) v_last
= 0;
7499 if (v_last
->get_valuetype() != Value::V_HSTR
) v_last
= 0;
7502 if (v_last
->get_valuetype() != Value::V_OSTR
) v_last
= 0;
7505 case Type::T_NUMERICSTRING
:
7506 case Type::T_PRINTABLESTRING
:
7507 case Type::T_IA5STRING
:
7508 case Type::T_VISIBLESTRING
:
7509 case Type::T_UTCTIME
:
7510 case Type::T_GENERALIZEDTIME
:
7511 if (v_last
->get_valuetype() != Value::V_CSTR
) v_last
= 0;
7514 case Type::T_UTF8STRING
:
7515 case Type::T_TELETEXSTRING
:
7516 case Type::T_VIDEOTEXSTRING
:
7517 case Type::T_GRAPHICSTRING
:
7518 case Type::T_GENERALSTRING
:
7519 case Type::T_UNIVERSALSTRING
:
7520 case Type::T_BMPSTRING
:
7521 case Type::T_OBJECTDESCRIPTOR
:
7522 if (v_last
->get_valuetype() != Value::V_USTR
) v_last
= 0;
7528 size_t string_len
= v_last
->get_val_strlen();
7529 if (string_len
!= 1) {
7530 val
->error("The length of the string to be assigned to a string "
7531 "element of type `%s' should be 1 instead of %lu",
7532 type
->get_typename().c_str(),
7533 (unsigned long)string_len
);
7543 asstype
= ASS_ERROR
;
7547 void Assignment::chk_template_ass()
7549 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7550 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7551 if (!lhs
) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7552 Type
*type
= lhs
->get_Type()->
7553 get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7554 if (!type
) goto error
;
7555 if (lhs
->get_asstype() != Common::Assignment::A_VAR_TEMPLATE
&&
7556 subrefs
&& subrefs
->refers_to_string_element()) {
7557 ref
->error("It is not allowed to index template strings");
7560 templ
->set_my_governor(type
);
7562 templ
->flatten(false);
7564 type
->chk_this_template_ref(templ
);
7565 self_ref
|= type
->chk_this_template_generic(templ
, INCOMPLETE_ALLOWED
,
7566 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, lhs
);
7567 chk_template_restriction();
7572 asstype
= ASS_ERROR
;
7576 void Assignment::chk()
7591 FATAL_ERROR("Ttcn::Assignment::chk()");
7595 void Assignment::set_code_section(
7596 GovernedSimple::code_section_t p_code_section
)
7600 ref
->set_code_section(p_code_section
);
7601 val
->set_code_section(p_code_section
);
7604 ref
->set_code_section(p_code_section
);
7605 templ
->set_code_section(p_code_section
);
7611 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7615 void Assignment::chk_template_restriction()
7617 if (asstype
!=ASS_TEMPLATE
)
7618 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7619 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7620 if (!t_ass
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7621 switch (t_ass
->get_asstype()) {
7622 case Common::Assignment::A_VAR_TEMPLATE
: {
7623 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(t_ass
);
7624 if (!dvt
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7625 template_restriction
= dvt
->get_template_restriction();
7627 case Common::Assignment::A_PAR_TEMPL_IN
:
7628 case Common::Assignment::A_PAR_TEMPL_OUT
:
7629 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
7630 FormalPar
* fp
= dynamic_cast<FormalPar
*>(t_ass
);
7631 if (!fp
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7632 template_restriction
= fp
->get_template_restriction();
7635 template_restriction
= TR_NONE
;
7637 // transform the restriction if this is a subfield
7638 template_restriction
= Template::get_sub_restriction(template_restriction
, ref
);
7639 // check the template restriction
7640 gen_restriction_check
=
7641 templ
->chk_restriction("template", template_restriction
, this);
7644 char *Assignment::generate_code(char *str
)
7646 // check if the LHS reference is a parameter, mark it as used if it is
7647 ref
->refd_param_usage_found();
7648 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
7649 const bool rhs_copied
= self_ref
;
7652 const string
& rhs_copy
= val
->get_temporary_id();
7653 string rhs_ref
= rhs_copy
;
7654 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7655 if (val
->get_my_governor()->is_optional_field()) {
7656 str
= mputprintf(str
, "{\nOPTIONAL<%s> %s;\n",
7657 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7660 str
= mputprintf(str
, "{\n%s %s;\n",
7661 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7664 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(val
);
7667 // Most complicated case. The LHS is saved in a temporary reference,
7668 // in case we need to access it more than once, e.g:
7669 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7670 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7671 // This saves having to index x2 more than once.
7672 const string
& tmp_id
= val
->get_temporary_id(); // For "ref".
7673 const char *tmp_id_str
= tmp_id
.c_str();
7674 const string
& type_genname
=
7675 val
->get_my_governor()->get_genname_value(val
->get_my_scope());
7676 const char *type_genname_str
= type_genname
.c_str();
7677 expression_struct expr
;
7678 Code::init_expr(&expr
);
7679 ref
->generate_code(&expr
);
7683 str
= TypeConv::gen_conv_code_refd(str
, rhs_ref
.c_str(), val
);
7684 else str
= val
->generate_code_init(str
, rhs_ref
.c_str());
7687 str
= mputstr(str
, "{\n");
7688 str
= mputstr(str
, expr
.preamble
);
7689 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
7690 // The LHS is a string element.
7691 str
= mputprintf(str
, "%s_ELEMENT %s(%s);\n", type_genname_str
,
7692 tmp_id_str
, expr
.expr
);
7694 // The LHS is a normal value.
7695 str
= mputprintf(str
, "%s& %s = %s; /* 7388 */\n", type_genname_str
,
7696 tmp_id_str
, expr
.expr
);
7698 str
= mputstr(str
, expr
.postamble
);
7699 // We now have a reference to the LHS. Generate the actual assignment
7701 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7705 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, val
);
7706 else str
= val
->generate_code_init(str
, tmp_id_str
);
7708 Code::free_expr(&expr
);
7709 str
= mputstr(str
, "}\n");
7713 if (!val
->has_single_expr()) goto case3
;
7714 // C++ equivalent of RHS is a single expression.
7715 expression_struct expr
;
7716 Code::init_expr(&expr
);
7717 ref
->generate_code(&expr
);// vu.s()
7719 str
= mputprintf(str
, "%s = %s;\n",
7720 rhs_copy
.c_str(), val
->get_single_expr().c_str());
7722 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7725 expr
.expr
= mputprintf(expr
.expr
,
7726 " = %s", val
->get_single_expr().c_str());
7728 str
= Code::merge_free_expr(str
, &expr
);
7731 // The LHS is a single identifier.
7732 const string
& rhs_name
= ref
->get_refd_assignment()
7733 ->get_genname_from_scope(ref
->get_my_scope());
7734 if (val
->can_use_increment(ref
)) {
7735 switch (val
->get_optype()) {
7736 case Value::OPTYPE_ADD
:
7737 str
= mputprintf(str
, "++%s;\n", rhs_name
.c_str());
7739 case Value::OPTYPE_SUBTRACT
:
7740 str
= mputprintf(str
, "--%s;\n", rhs_name
.c_str());
7743 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7746 str
= val
->generate_code_init(str
,
7747 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7750 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7756 str
= mputstr(str
, "}\n");
7759 case ASS_TEMPLATE
: {
7760 const string
& rhs_copy
= templ
->get_temporary_id();
7761 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7762 str
= mputprintf(str
, "{\n%s %s;\n",
7763 templ
->get_my_governor()->get_genname_template(templ
->get_my_scope()).c_str(), rhs_copy
.c_str()//, rhs_copy.c_str()
7766 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(templ
);
7767 if (needs_conv
) { // case 3
7769 // Most complicated case. The LHS is saved in a temporary reference.
7770 const string
& tmp_id
= templ
->get_temporary_id();
7771 const char *tmp_id_str
= tmp_id
.c_str();
7772 expression_struct expr
;
7773 Code::init_expr(&expr
);
7774 ref
->generate_code(&expr
);
7778 str
= TypeConv::gen_conv_code_refd(str
, rhs_copy
.c_str(), templ
);
7779 else str
= templ
->generate_code_init(str
, rhs_copy
.c_str());
7782 str
= mputstr(str
, "{\n");
7783 str
= mputstr(str
, expr
.preamble
);
7784 str
= mputprintf(str
, "%s& %s = %s;\n",
7785 templ
->get_my_governor()->get_genname_template(
7786 templ
->get_my_scope()
7787 ).c_str(), tmp_id_str
, expr
.expr
);
7788 str
= mputstr(str
, expr
.postamble
);
7790 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7794 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, templ
);
7796 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7797 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7798 str
= mputprintf(str
, "%s.remove_all_permutations();\n", tmp_id_str
);
7800 str
= templ
->generate_code_init(str
, tmp_id_str
);
7803 Code::free_expr(&expr
);
7805 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7806 str
= Template::generate_restriction_check_code(str
,
7807 tmp_id_str
, template_restriction
);
7808 str
= mputstr(str
, "}\n");
7810 else { // !needs_conv
7812 if ((template_restriction
== TR_NONE
|| !gen_restriction_check
)
7813 && templ
->has_single_expr()) {
7814 // C++ equivalent of RHS is a single expression and no restriction
7815 // check. Skipped if conversion needed.
7816 expression_struct expr
;
7817 Code::init_expr(&expr
);
7818 ref
->generate_code(&expr
);
7820 str
= mputprintf(str
, "%s = %s;\n",
7821 rhs_copy
.c_str(), templ
->get_single_expr(false).c_str());
7823 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7826 expr
.expr
= mputprintf(expr
.expr
,
7827 " = %s", templ
->get_single_expr(false).c_str());
7829 str
= Code::merge_free_expr(str
, &expr
); // will add a semicolon
7834 // LHS is a single identifier
7835 const string
& rhs_name
= ref
->get_refd_assignment()
7836 ->get_genname_from_scope(ref
->get_my_scope());
7837 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7838 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7839 str
= mputprintf(str
, "%s.remove_all_permutations();\n", (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7841 str
= templ
->generate_code_init(str
,
7842 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7844 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7846 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7847 str
= Template::generate_restriction_check_code(str
,
7848 ref
->get_refd_assignment()->get_genname_from_scope(
7850 ).c_str(), template_restriction
);
7854 str
= mputstr(str
, "}\n");
7858 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7863 // =================================
7864 // ===== ParamAssignment
7865 // =================================
7867 ParamAssignment::ParamAssignment(Identifier
*p_id
, Reference
*p_ref
)
7868 : Node(), Location(), id(p_id
), ref(p_ref
)
7870 if(!id
|| !ref
) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7873 ParamAssignment::~ParamAssignment()
7879 ParamAssignment
*ParamAssignment::clone() const
7881 FATAL_ERROR("ParamAssignment::clone");
7884 void ParamAssignment::set_my_scope(Scope
*p_scope
)
7886 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7887 ref
->set_my_scope(p_scope
);
7890 void ParamAssignment::set_fullname(const string
& p_fullname
)
7892 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7893 ref
->set_fullname(p_fullname
);
7896 Reference
*ParamAssignment::get_ref() const
7898 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7902 Reference
*ParamAssignment::steal_ref()
7904 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7905 Reference
*ret_val
= ref
;
7910 // =================================
7911 // ===== ParamAssignments
7912 // =================================
7914 ParamAssignments::~ParamAssignments()
7916 for(size_t i
=0; i
<parasss
.size(); i
++)
7921 ParamAssignments
*ParamAssignments::clone() const
7923 FATAL_ERROR("ParamAssignments::clone");
7926 void ParamAssignments::set_my_scope(Scope
*p_scope
)
7928 for(size_t i
=0; i
<parasss
.size(); i
++)
7929 parasss
[i
]->set_my_scope(p_scope
);
7932 void ParamAssignments::set_fullname(const string
& p_fullname
)
7934 Node::set_fullname(p_fullname
);
7935 for(size_t i
=0; i
<parasss
.size(); i
++)
7936 parasss
[i
]->set_fullname(p_fullname
+".parass_"+Int2string(i
+1));
7939 void ParamAssignments::add_parass(ParamAssignment
*p_parass
)
7942 FATAL_ERROR("ParamAssignments::add_parass()");
7943 parasss
.add(p_parass
);
7946 // =================================
7947 // ===== VariableEntry
7948 // =================================
7950 VariableEntry::VariableEntry(Reference
*p_ref
)
7951 : Node(), Location(), ref(p_ref
)
7953 if(!ref
) FATAL_ERROR("VariableEntry::VariableEntry()");
7956 VariableEntry::~VariableEntry()
7961 VariableEntry
*VariableEntry::clone() const
7963 FATAL_ERROR("VariableEntry::clone");
7966 void VariableEntry::set_my_scope(Scope
*p_scope
)
7968 if(ref
) ref
->set_my_scope(p_scope
);
7971 void VariableEntry::set_fullname(const string
& p_fullname
)
7973 Node::set_fullname(p_fullname
);
7974 if(ref
) ref
->set_fullname(p_fullname
+".ref");
7977 // =================================
7978 // ===== VariableEntries
7979 // =================================
7981 VariableEntries::~VariableEntries()
7983 for(size_t i
=0; i
<ves
.size(); i
++)
7988 VariableEntries
*VariableEntries::clone() const
7990 FATAL_ERROR("VariableEntries::clone");
7993 void VariableEntries::set_my_scope(Scope
*p_scope
)
7995 for(size_t i
=0; i
<ves
.size(); i
++)
7996 ves
[i
]->set_my_scope(p_scope
);
7999 void VariableEntries::set_fullname(const string
& p_fullname
)
8001 Node::set_fullname(p_fullname
);
8002 for(size_t i
=0; i
<ves
.size(); i
++)
8003 ves
[i
]->set_fullname(p_fullname
+".ve_"+Int2string(i
+1));
8006 void VariableEntries::add_ve(VariableEntry
*p_ve
)
8009 FATAL_ERROR("VariableEntries::add_ve()");
8013 // =================================
8014 // ===== ParamRedirect
8015 // =================================
8017 ParamRedirect::ParamRedirect(ParamAssignments
*p_parasss
)
8018 : Node(), Location(), parredirtype(P_ASS
), parasss(p_parasss
)
8020 if(!parasss
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8023 ParamRedirect::ParamRedirect(VariableEntries
*p_ves
)
8024 : Node(), Location(), parredirtype(P_VAR
), ves(p_ves
)
8026 if(!ves
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8029 ParamRedirect::~ParamRedirect()
8031 switch(parredirtype
) {
8039 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
8043 ParamRedirect
*ParamRedirect::clone() const
8045 FATAL_ERROR("ParamRedirect::clone");
8048 void ParamRedirect::set_my_scope(Scope
*p_scope
)
8050 switch(parredirtype
) {
8052 parasss
->set_my_scope(p_scope
);
8055 ves
->set_my_scope(p_scope
);
8058 FATAL_ERROR("ParamRedirect::set_my_scope()");
8062 void ParamRedirect::set_fullname(const string
& p_fullname
)
8064 Node::set_fullname(p_fullname
);
8065 switch(parredirtype
) {
8067 parasss
->set_fullname(p_fullname
+".parasss");
8070 ves
->set_fullname(p_fullname
+".parvars");
8073 FATAL_ERROR("ParamRedirect::set_fullname()");
8077 void ParamRedirect::chk_erroneous()
8079 Error_Context
cntxt(this, "In parameter redirect");
8080 switch(parredirtype
) {
8082 map
<string
, ParamAssignment
> parass_m
;
8083 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8084 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8085 const Identifier
&t_id
= t_parass
->get_id();
8086 const string
& name
= t_id
.get_name();
8087 const char *dispname_str
= t_id
.get_dispname().c_str();
8088 if (parass_m
.has_key(name
)) {
8089 t_parass
->error("Duplicate redirect for parameter `%s'",
8091 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8092 "already given here", dispname_str
);
8093 } else parass_m
.add(name
, t_parass
);
8094 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8096 chk_variable_ref(t_parass
->get_ref(), 0);
8101 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8102 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8103 Error_Context
cntxt2(t_ve
, "In variable entry #%lu",
8104 (unsigned long) (i
+ 1));
8105 chk_variable_ref(t_ve
->get_ref(), 0);
8109 FATAL_ERROR("ParamRedirect::chk_erroneous()");
8113 void ParamRedirect::chk(Type
*p_sig
, bool is_out
)
8115 SignatureParamList
*t_parlist
= p_sig
->get_signature_parameters();
8117 Error_Context
cntxt(this, "In parameter redirect");
8118 switch (parredirtype
) {
8120 chk_parasss(p_sig
, t_parlist
, is_out
);
8123 chk_ves(p_sig
, t_parlist
, is_out
);
8126 FATAL_ERROR("ParamRedirect::chk()");
8129 error("Parameter redirect cannot be used because signature `%s' "
8130 "does not have parameters", p_sig
->get_typename().c_str());
8135 void ParamRedirect::chk_parasss(Type
*p_sig
, SignatureParamList
*p_parlist
,
8138 map
<string
, ParamAssignment
> parass_m
;
8139 bool error_flag
= false;
8140 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8141 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8142 const Identifier
&t_id
= t_parass
->get_id();
8143 const string
& name
= t_id
.get_name();
8144 const char *dispname_str
= t_id
.get_dispname().c_str();
8145 if (parass_m
.has_key(name
)) {
8146 t_parass
->error("Duplicate redirect for parameter `%s'",
8148 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8149 "already given here", dispname_str
);
8151 } else parass_m
.add(name
, t_parass
);
8152 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8154 if (p_parlist
->has_param_withName(t_id
)) {
8155 const SignatureParam
*t_par
= p_parlist
->get_param_byName(t_id
);
8156 SignatureParam::param_direction_t t_dir
= t_par
->get_direction();
8158 if (t_dir
== SignatureParam::PARAM_IN
) {
8159 t_parass
->error("Parameter `%s' of signature `%s' has `in' "
8160 "direction", dispname_str
, p_sig
->get_typename().c_str());
8164 if (t_dir
== SignatureParam::PARAM_OUT
) {
8165 t_parass
->error("Parameter `%s' of signature `%s' has `out' "
8166 "direction", dispname_str
, p_sig
->get_typename().c_str());
8170 chk_variable_ref(t_parass
->get_ref(), t_par
->get_type());
8172 t_parass
->error("Signature `%s' does not have parameter named `%s'",
8173 p_sig
->get_typename().c_str(), dispname_str
);
8175 chk_variable_ref(t_parass
->get_ref(), 0);
8179 // converting the AssignmentList to VariableList
8180 VariableEntries
*t_ves
= new VariableEntries
;
8181 size_t upper_limit
= is_out
?
8182 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8183 for (size_t i
= 0; i
< upper_limit
; i
++) {
8184 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8185 : p_parlist
->get_in_param_byIndex(i
);
8186 const string
& name
= t_par
->get_id().get_name();
8187 if (parass_m
.has_key(name
))
8188 t_ves
->add_ve(new VariableEntry(parass_m
[name
]->steal_ref()));
8189 else t_ves
->add_ve(new VariableEntry
);
8193 parredirtype
= P_VAR
;
8198 void ParamRedirect::chk_ves(Type
*p_sig
, SignatureParamList
*p_parlist
,
8201 size_t nof_ves
= ves
->get_nof_ves();
8202 size_t nof_pars
= is_out
?
8203 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8204 if (nof_ves
!= nof_pars
) {
8205 error("Too %s variable entries compared to the number of %s/inout "
8206 "parameters in signature `%s': %lu was expected instead of %lu",
8207 nof_ves
> nof_pars
? "many" : "few", is_out
? "out" : "in",
8208 p_sig
->get_typename().c_str(), (unsigned long) nof_pars
,
8209 (unsigned long) nof_ves
);
8211 for (size_t i
= 0; i
< nof_ves
; i
++) {
8212 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8214 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8215 : p_parlist
->get_in_param_byIndex(i
);
8216 Error_Context
cntxt(t_ve
, "In variable entry #%lu (for parameter `%s')",
8217 (unsigned long) (i
+ 1), t_par
->get_id().get_dispname().c_str());
8218 chk_variable_ref(t_ve
->get_ref(), t_par
->get_type());
8220 Error_Context
cntxt(t_ve
, "In variable entry #%lu",
8221 (unsigned long) (i
+ 1));
8222 chk_variable_ref(t_ve
->get_ref(), 0);
8227 void ParamRedirect::chk_variable_ref(Reference
*p_ref
, Type
*p_type
)
8230 Type
*t_var_type
= p_ref
->chk_variable_ref();
8231 if (p_type
&& t_var_type
&& !p_type
->is_identical(t_var_type
)) {
8232 p_ref
->error("Type mismatch in parameter redirect: "
8233 "A variable of type `%s' was expected instead of `%s'",
8234 p_type
->get_typename().c_str(),
8235 t_var_type
->get_typename().c_str());
8239 void ParamRedirect::set_code_section(
8240 GovernedSimple::code_section_t p_code_section
)
8242 // code can be generated from VariableList only
8243 switch (parredirtype
) {
8247 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8248 Reference
*t_ref
= ves
->get_ve_byIndex(i
)->get_ref();
8249 if (t_ref
) t_ref
->set_code_section(p_code_section
);
8253 FATAL_ERROR("ParamRedirect::set_code_section()");
8257 void ParamRedirect::generate_code(expression_struct_t
*expr
)
8259 // AssignmentList is converted to VariableList during checking
8260 if (parredirtype
!= P_VAR
) FATAL_ERROR("ParamRedirect::generate_code()");
8261 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8262 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
8263 Reference
*ref
= ves
->get_ve_byIndex(i
)->get_ref();
8265 // the variable reference is present
8266 expr
->expr
= mputstr(expr
->expr
, "&(");
8267 ref
->generate_code(expr
);
8268 expr
->expr
= mputc(expr
->expr
, ')');
8269 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
8273 // =================================
8274 // ===== LogArgument
8275 // =================================
8277 LogArgument::LogArgument(TemplateInstance
*p_ti
)
8278 : logargtype(L_UNDEF
)
8280 if (!p_ti
) FATAL_ERROR("LogArgument::LogArgument()");
8284 LogArgument::~LogArgument()
8286 switch (logargtype
) {
8305 FATAL_ERROR("LogArgument::~LogArgument()");
8309 LogArgument
*LogArgument::clone() const
8311 FATAL_ERROR("LogArgument::clone");
8314 void LogArgument::set_my_scope(Scope
*p_scope
)
8316 switch (logargtype
) {
8321 ti
->set_my_scope(p_scope
);
8326 val
->set_my_scope(p_scope
);
8329 ref
->set_my_scope(p_scope
);
8334 FATAL_ERROR("LogArgument::set_my_scope()");
8338 void LogArgument::set_fullname(const string
& p_fullname
)
8340 Node::set_fullname(p_fullname
);
8341 switch (logargtype
) {
8346 ti
->set_fullname(p_fullname
);
8351 val
->set_fullname(p_fullname
);
8354 ref
->set_fullname(p_fullname
);
8359 FATAL_ERROR("LogArgument::set_fullname()");
8363 const string
& LogArgument::get_str() const
8365 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::get_str()");
8369 Value
*LogArgument::get_val() const
8371 switch (logargtype
) {
8377 FATAL_ERROR("LogArgument::get_val()");
8382 Ref_base
*LogArgument::get_ref() const
8384 if (logargtype
!= L_REF
) FATAL_ERROR("LogArgument::get_ref()");
8388 TemplateInstance
*LogArgument::get_ti() const
8390 if (logargtype
!= L_TI
) FATAL_ERROR("LogArgument::get_ref()");
8394 void LogArgument::append_str(const string
& p_str
)
8396 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::append_str()");
8400 void LogArgument::chk() // determine the proper type of the log argument
8402 if (logargtype
!= L_UNDEF
) return;
8403 Template
*t_templ
= ti
->get_Template();
8404 t_templ
= t_templ
->get_template_refd_last();
8405 t_templ
->set_lowerid_to_ref();
8406 if (!ti
->get_Type() && !ti
->get_DerivedRef() && t_templ
->is_Value()) {
8407 // drop the template instance and keep only the embedded value
8408 Value
*t_val
= t_templ
->get_Value();
8414 // try to obtain the governor of the template instance
8415 Type
*governor
= ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8417 // the governor is still unknown: an error occurred
8418 // try to interpret possible enum values as references
8419 t_templ
->set_lowerid_to_ref();
8420 governor
= t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8426 t_templ
->error("Cannot determine the type of the argument");
8428 logargtype
= L_ERROR
;
8433 void LogArgument::chk_ref()
8435 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
8437 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
8439 case Common::Assignment::A_FUNCTION_RVAL
:
8440 case Common::Assignment::A_FUNCTION_RTEMP
:
8441 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
8442 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
8443 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *this, "call");
8444 case Common::Assignment::A_CONST
:
8445 case Common::Assignment::A_EXT_CONST
:
8446 case Common::Assignment::A_MODULEPAR
:
8447 case Common::Assignment::A_MODULEPAR_TEMP
:
8448 case Common::Assignment::A_TEMPLATE
:
8449 case Common::Assignment::A_VAR
:
8450 case Common::Assignment::A_VAR_TEMPLATE
:
8451 case Common::Assignment::A_PAR_VAL_IN
:
8452 case Common::Assignment::A_PAR_VAL_OUT
:
8453 case Common::Assignment::A_PAR_VAL_INOUT
:
8454 case Common::Assignment::A_PAR_TEMPL_IN
:
8455 case Common::Assignment::A_PAR_TEMPL_OUT
:
8456 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
8457 // the reference points to a value or template-like entity
8458 // checking sub-references
8459 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
8460 if (subrefs
&& t_ass
->get_Type()->get_field_type(subrefs
,
8461 Type::EXPECTED_DYNAMIC_VALUE
)) {
8462 // subrefs seems to be correct
8463 // also checking the presence of referred fields if possible
8464 if (asstype
== Common::Assignment::A_CONST
) {
8465 ReferenceChain
refch(ref
, "While searching referenced value");
8466 t_ass
->get_Value()->get_refd_sub_value(subrefs
, 0, false, &refch
);
8467 } else if (asstype
== Common::Assignment::A_TEMPLATE
) {
8468 ReferenceChain
refch(ref
, "While searching referenced template");
8469 t_ass
->get_Template()
8470 ->get_refd_sub_template(subrefs
, false, &refch
);
8474 case Common::Assignment::A_TIMER
:
8475 case Common::Assignment::A_PORT
: {
8476 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
8477 if (t_dims
) t_dims
->chk_indices(ref
, t_ass
->get_assname(), true,
8478 Type::EXPECTED_DYNAMIC_VALUE
);
8479 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8480 "cannot have field or array sub-references",
8481 t_ass
->get_description().c_str());
8483 case Common::Assignment::A_PAR_TIMER
:
8484 case Common::Assignment::A_PAR_PORT
:
8485 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8486 "field or array sub-references", t_ass
->get_description().c_str());
8488 case Common::Assignment::A_FUNCTION
:
8489 case Common::Assignment::A_EXT_FUNCTION
:
8490 ref
->error("Reference to a value, template, timer or port was expected "
8491 "instead of a call of %s, which does not have return type",
8492 t_ass
->get_description().c_str());
8495 ref
->error("Reference to a value, template, timer or port was expected "
8496 "instead of %s", t_ass
->get_description().c_str());
8500 void LogArgument::chk_val()
8502 // literal enumerated values cannot appear in this context
8503 val
->set_lowerid_to_ref();
8504 switch (val
->get_valuetype()) {
8505 case Value::V_CSTR
: {
8506 string
*t_cstr
= new string(val
->get_val_str());
8511 case Value::V_REFD
: {
8512 Ref_base
*t_ref
= val
->steal_ttcn_ref_base();
8519 if (val
->get_optype() == Value::OPTYPE_MATCH
) logargtype
= L_MATCH
;
8520 else logargtype
= L_VAL
;
8522 case Value::V_MACRO
:
8523 logargtype
= L_MACRO
;
8528 Type
*governor
= val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
8530 val
->set_my_governor(governor
);
8531 (void)governor
->chk_this_value(val
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
8532 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
8533 if (logargtype
== L_VAL
&& val
->get_valuetype() == Value::V_CSTR
8534 && !val
->is_unfoldable()) { // string value known at compile time
8535 string
*t_cstr
= new string(val
->get_val_str());
8541 if (logargtype
== L_MACRO
) {
8542 switch (val
->get_valuetype()) {
8543 case Value::V_CSTR
: {
8544 // the macro was evaluated to a charstring value
8545 string
*t_cstr
= new string(val
->get_val_str());
8550 case Value::V_MACRO
:
8551 // the macro could not be evaluated at compile time
8552 // leave logargtype as is
8555 // the macro was evaluated to other value (e.g. integer)
8560 val
->error("Cannot determine the type of the argument");
8562 logargtype
= L_ERROR
;
8566 void LogArgument::dump(unsigned int level
) const
8568 Node::dump(level
++);
8569 switch (logargtype
) {
8571 DEBUG(level
, "*error*");
8574 DEBUG(level
, "*undef*");
8577 DEBUG(level
, "TemplateInstance");
8583 DEBUG(level
, "Match");
8586 DEBUG(level
, "Macro");
8589 DEBUG(level
, "Reference");
8592 DEBUG(level
, "String=`%s'", cstr
->c_str());
8595 FATAL_ERROR("LogArgument::~LogArgument()");
8599 void LogArgument::set_code_section(
8600 GovernedSimple::code_section_t p_code_section
)
8602 switch (logargtype
) {
8605 ti
->set_code_section(p_code_section
);
8610 val
->set_code_section(p_code_section
);
8613 ref
->set_code_section(p_code_section
);
8619 FATAL_ERROR("LogArgument::set_code_section()");
8623 char *LogArgument::generate_code_log(char *str
)
8625 expression_struct expr
;
8626 Code::init_expr(&expr
);
8627 generate_code_expr(&expr
);
8628 str
= Code::merge_free_expr(str
, &expr
);
8632 void LogArgument::chk_recursions(ReferenceChain
& refch
)
8634 switch (logargtype
) {
8637 ti
->chk_recursions(refch
);
8642 val
->chk_recursions(refch
);
8645 Common::Assignment
*ass
= ref
->get_refd_assignment();
8647 refch
.add(ass
->get_fullname());
8653 FATAL_ERROR("LogArgument::chk_recursions()");
8657 bool LogArgument::has_single_expr()
8659 switch (logargtype
) {
8662 return ti
->has_single_expr();
8666 return ( val
->has_single_expr() && !val
->explicit_cast_needed() );
8668 Common::Assignment
*ass
= ref
->get_refd_assignment();
8669 switch (ass
->get_asstype()) {
8670 case Common::Assignment::A_CONST
:
8671 case Common::Assignment::A_EXT_CONST
:
8672 return ref
->has_single_expr();
8681 FATAL_ERROR("LogArgument::has_single_expr()");
8686 void LogArgument::generate_code_expr(expression_struct
*expr
)
8688 switch(logargtype
) {
8690 if (ti
->is_only_specific_value()) {
8691 // use the embedded specific value for code generation
8692 ti
->get_Template()->get_specific_value()->generate_code_log(expr
);
8694 ti
->generate_code(expr
);
8695 expr
->expr
= mputstr(expr
->expr
, ".log()");
8699 val
->generate_code_log(expr
);
8702 val
->generate_code_log_match(expr
);
8705 if (val
->has_single_expr()) {
8706 expr
->expr
= mputprintf(expr
->expr
, "TTCN_Logger::log_event_str(%s)",
8707 val
->get_single_expr().c_str());
8708 } else val
->generate_code_log(expr
);
8711 ref
->generate_code_const_ref(expr
);
8712 expr
->expr
=mputstr(expr
->expr
, ".log()");
8715 size_t str_len
= cstr
->size();
8716 const char *str_ptr
= cstr
->c_str();
8719 // the string is empty: do not generate any code
8721 // the string has one character: use log_char member
8722 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_char('");
8723 expr
->expr
= Code::translate_character(expr
->expr
, *str_ptr
, false);
8724 expr
->expr
= mputstr(expr
->expr
, "')");
8727 // the string has more characters: use log_event_str member
8728 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_event_str(\"");
8729 expr
->expr
= Code::translate_string(expr
->expr
, str_ptr
);
8730 expr
->expr
= mputstr(expr
->expr
, "\")");
8734 FATAL_ERROR("LogArgument::generate_code_expr()");
8738 // =================================
8739 // ===== LogArguments
8740 // =================================
8742 LogArguments::~LogArguments()
8744 for(size_t i
=0; i
<logargs
.size(); i
++) delete logargs
[i
];
8748 LogArguments
*LogArguments::clone() const
8750 FATAL_ERROR("LogArguments::clone");
8753 void LogArguments::add_logarg(LogArgument
*p_logarg
)
8756 FATAL_ERROR("LogArguments::add_logarg()");
8757 logargs
.add(p_logarg
);
8760 void LogArguments::set_my_scope(Scope
*p_scope
)
8762 for(size_t i
=0; i
<logargs
.size(); i
++)
8763 logargs
[i
]->set_my_scope(p_scope
);
8766 void LogArguments::set_fullname(const string
& p_fullname
)
8768 Node::set_fullname(p_fullname
);
8769 for(size_t i
=0; i
<logargs
.size(); i
++)
8770 logargs
[i
]->set_fullname(p_fullname
+".logargs_"+Int2string(i
+1));
8773 void LogArguments::chk()
8775 for(size_t i
=0; i
<logargs
.size(); i
++)
8779 void LogArguments::join_strings()
8781 // points to the previous string argument otherwise it is NULL
8782 LogArgument
*prev_arg
= 0;
8783 for (size_t i
= 0; i
< logargs
.size(); ) {
8784 LogArgument
*arg
= logargs
[i
];
8785 if (arg
->get_type() == LogArgument::L_STR
) {
8786 const string
& str
= arg
->get_str();
8787 if (str
.size() > 0) {
8788 // the current argument is a non-empty string
8790 // append str to prev_arg and drop arg
8791 prev_arg
->append_str(str
);
8793 logargs
.replace(i
, 1);
8794 // don't increment i
8796 // keep it for the next iteration
8801 // the current argument is an empty string
8802 // simply drop it unless it is the only argument
8803 // note: we must distinguish between log() and log("")
8804 if (i
> 0 || logargs
.size() > 1) {
8806 logargs
.replace(i
, 1);
8807 // don't increment i
8811 // the current argument is not a string
8812 // forget the previous arg
8819 void LogArguments::set_code_section(
8820 GovernedSimple::code_section_t p_code_section
)
8822 for (size_t i
= 0; i
< logargs
.size(); i
++)
8823 logargs
[i
]->set_code_section(p_code_section
);
8826 char *LogArguments::generate_code(char *str
)
8828 for(size_t i
=0; i
<logargs
.size(); i
++)
8829 str
=logargs
[i
]->generate_code_log(str
);
8833 void LogArguments::chk_recursions(ReferenceChain
& refch
)
8835 for (size_t i
=0; i
<logargs
.size(); i
++) {
8837 logargs
[i
]->chk_recursions(refch
);
8842 bool LogArguments::has_single_expr()
8844 bool i_have_single_expr
= true;
8845 for (size_t i
=0; i
<logargs
.size(); i
++)
8846 i_have_single_expr
= i_have_single_expr
&& logargs
[i
]->has_single_expr();
8847 return i_have_single_expr
;
8850 void LogArguments::generate_code_expr(expression_struct
*expr
)
8852 expr
->expr
= mputstr(expr
->expr
, "(TTCN_Logger::begin_event_log2str(),");
8853 for(size_t i
=0; i
<logargs
.size(); i
++) {
8854 logargs
[i
]->generate_code_expr(expr
);
8855 expr
->expr
= mputc(expr
->expr
, ','); // comma operator
8857 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::end_event_log2str())");
8860 // =================================
8862 // =================================
8864 IfClause::IfClause(Value
*p_expr
, StatementBlock
*p_block
)
8865 : expr(p_expr
), block(p_block
)
8868 FATAL_ERROR("IfClause::IfClause()");
8871 IfClause::~IfClause()
8877 IfClause
*IfClause::clone() const
8879 FATAL_ERROR("IfClause::clone");
8882 void IfClause::set_my_scope(Scope
*p_scope
)
8884 expr
->set_my_scope(p_scope
);
8885 block
->set_my_scope(p_scope
);
8888 void IfClause::set_fullname(const string
& p_fullname
)
8890 Node::set_fullname(p_fullname
);
8891 expr
->set_fullname(p_fullname
+".expr");
8892 block
->set_fullname(p_fullname
+".block");
8895 bool IfClause::has_receiving_stmt() const
8897 return block
->has_receiving_stmt();
8900 void IfClause::chk(bool& unreach
)
8902 Error_Context
cntxt(this, "In if statement");
8903 if(unreach
) warning("Control never reaches this code because of"
8904 " previous effective condition(s)");
8905 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
8906 if(!expr
->is_unfoldable()) {
8907 if(expr
->get_val_bool()) unreach
=true;
8908 else block
->warning("Control never reaches this code because the"
8909 " conditional expression evaluates to false");
8914 void IfClause::set_code_section(
8915 GovernedSimple::code_section_t p_code_section
)
8917 expr
->set_code_section(p_code_section
);
8918 block
->set_code_section(p_code_section
);
8921 char* IfClause::generate_code(char *str
, size_t& blockcount
,
8922 bool& unreach
, bool& eachfalse
)
8924 if(unreach
) return str
;
8925 if(!expr
->is_unfoldable()) {
8926 if(expr
->get_val_bool()) unreach
=true;
8929 if (!eachfalse
) str
= mputstr(str
, "else ");
8932 str
= mputstr(str
, "{\n");
8935 str
= expr
->update_location_object(str
);
8936 str
= expr
->generate_code_tmp(str
, "if (", blockcount
);
8937 str
= mputstr(str
, ") ");
8940 str
=mputstr(str
, "{\n");
8941 str
=block
->generate_code(str
);
8942 str
=mputstr(str
, "}\n");
8946 void IfClause::ilt_generate_code(ILT
*ilt
, const char *end_label
,
8950 if(!expr
->is_unfoldable()) {
8951 if(expr
->get_val_bool()) unreach
=true;
8954 char*& str
=ilt
->get_out_branches();
8957 size_t blockcount
=0;
8958 label
=mprintf("%s_l%lu",
8959 ilt
->get_my_tmpid().c_str(),
8960 (unsigned long) ilt
->get_new_label_num());
8961 str
=expr
->update_location_object(str
);
8962 str
=expr
->generate_code_tmp(str
, "if(!", blockcount
);
8963 str
=mputprintf(str
, ") goto %s;\n", label
);
8964 while(blockcount
-->0) str
=mputstr(str
, "}\n");
8966 block
->ilt_generate_code(ilt
);
8968 str
=mputprintf(str
, "goto %s;\n%s:\n",
8974 void IfClause::set_parent_path(WithAttribPath
* p_path
) {
8975 block
->set_parent_path(p_path
);
8978 void IfClause::dump(unsigned int level
) const {
8979 DEBUG(level
, "If clause!");
8980 expr
->dump(level
+ 1);
8981 block
->dump(level
+ 1);
8984 // =================================
8986 // =================================
8988 IfClauses::~IfClauses()
8990 for(size_t i
=0; i
<ics
.size(); i
++) delete ics
[i
];
8994 IfClauses
*IfClauses::clone() const
8996 FATAL_ERROR("IfClauses::clone");
8999 void IfClauses::add_ic(IfClause
*p_ic
)
9002 FATAL_ERROR("IfClauses::add_ic()");
9006 void IfClauses::add_front_ic(IfClause
*p_ic
)
9009 FATAL_ERROR("IfClauses::add_front_ic()");
9010 ics
.add_front(p_ic
);
9013 void IfClauses::set_my_scope(Scope
*p_scope
)
9015 for(size_t i
=0; i
<ics
.size(); i
++)
9016 ics
[i
]->set_my_scope(p_scope
);
9019 void IfClauses::set_fullname(const string
& p_fullname
)
9021 Node::set_fullname(p_fullname
);
9022 for(size_t i
=0; i
<ics
.size(); i
++)
9023 ics
[i
]->set_fullname(p_fullname
+".ic_"+Int2string(i
+1));
9026 void IfClauses::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9028 for(size_t i
=0; i
<ics
.size(); i
++)
9029 ics
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9032 void IfClauses::set_my_def(Definition
*p_def
)
9034 for(size_t i
=0; i
<ics
.size(); i
++)
9035 ics
[i
]->get_block()->set_my_def(p_def
);
9038 void IfClauses::set_my_ags(AltGuards
*p_ags
)
9040 for(size_t i
=0; i
<ics
.size(); i
++)
9041 ics
[i
]->get_block()->set_my_ags(p_ags
);
9044 void IfClauses::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9046 for(size_t i
=0; i
<ics
.size(); i
++)
9047 ics
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9050 StatementBlock::returnstatus_t
IfClauses::has_return
9051 (StatementBlock
*elseblock
) const
9053 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9054 for (size_t i
= 0; i
< ics
.size(); i
++) {
9055 switch (ics
[i
]->get_block()->has_return()) {
9056 case StatementBlock::RS_NO
:
9057 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9058 else ret_val
= StatementBlock::RS_NO
;
9060 case StatementBlock::RS_YES
:
9061 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9062 else ret_val
= StatementBlock::RS_YES
;
9065 return StatementBlock::RS_MAYBE
;
9068 StatementBlock::returnstatus_t else_status
;
9069 if (elseblock
) else_status
= elseblock
->has_return();
9070 else else_status
= StatementBlock::RS_NO
;
9071 switch (else_status
) {
9072 case StatementBlock::RS_NO
:
9073 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9074 else ret_val
= StatementBlock::RS_NO
;
9076 case StatementBlock::RS_YES
:
9077 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9078 else ret_val
= StatementBlock::RS_YES
;
9081 return StatementBlock::RS_MAYBE
;
9086 bool IfClauses::has_receiving_stmt() const
9088 for(size_t i
=0; i
<ics
.size(); i
++)
9089 if(ics
[i
]->has_receiving_stmt()) return true;
9093 void IfClauses::chk(bool& unreach
)
9095 for(size_t i
=0; i
<ics
.size(); i
++)
9096 ics
[i
]->chk(unreach
);
9099 void IfClauses::chk_allowed_interleave()
9101 for (size_t i
= 0; i
< ics
.size(); i
++)
9102 ics
[i
]->get_block()->chk_allowed_interleave();
9105 void IfClauses::set_code_section(
9106 GovernedSimple::code_section_t p_code_section
)
9108 for (size_t i
= 0; i
< ics
.size(); i
++)
9109 ics
[i
]->set_code_section(p_code_section
);
9112 char* IfClauses::generate_code(char *str
, size_t& blockcount
,
9113 bool& unreach
, bool& eachfalse
)
9115 for(size_t i
=0; i
<ics
.size(); i
++) {
9116 if(unreach
) return str
;
9117 str
=ics
[i
]->generate_code(str
, blockcount
, unreach
, eachfalse
);
9122 void IfClauses::ilt_generate_code(ILT
*ilt
, const char *end_label
,
9125 for(size_t i
=0; i
<ics
.size(); i
++) {
9127 ics
[i
]->ilt_generate_code(ilt
, end_label
, unreach
);
9131 void IfClauses::set_parent_path(WithAttribPath
* p_path
) {
9132 for (size_t i
= 0; i
< ics
.size(); i
++)
9133 ics
[i
]->set_parent_path(p_path
);
9136 void IfClauses::dump(unsigned int level
) const {
9137 DEBUG(level
, "%lu if clauses", (unsigned long)ics
.size());
9138 for (size_t i
= 0; i
< ics
.size(); i
++)
9139 ics
[i
]->dump(level
+ 1);
9142 // =================================
9144 // =================================
9146 SelectCase::SelectCase(TemplateInstances
*p_tis
, StatementBlock
*p_block
)
9147 : tis(p_tis
), block(p_block
)
9150 FATAL_ERROR("SelectCase::SelectCase()");
9153 SelectCase::~SelectCase()
9159 SelectCase
*SelectCase::clone() const
9161 FATAL_ERROR("SelectCase::clone");
9164 void SelectCase::set_my_scope(Scope
*p_scope
)
9166 if(tis
) tis
->set_my_scope(p_scope
);
9167 block
->set_my_scope(p_scope
);
9170 void SelectCase::set_fullname(const string
& p_fullname
)
9172 Node::set_fullname(p_fullname
);
9173 if(tis
) tis
->set_fullname(p_fullname
+".tis");
9174 block
->set_fullname(p_fullname
+".block");
9178 void SelectCase::chk(Type
*p_gov
, bool& unreach
)
9180 Error_Context
cntxt(this, "In select case statement");
9181 if(unreach
) warning("Control never reaches this code because of"
9182 " previous effective case(s)");
9184 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++)
9185 tis
->get_ti_byIndex(i
)->chk(p_gov
);
9186 else unreach
=true; // else statement
9190 void SelectCase::set_code_section
9191 (GovernedSimple::code_section_t p_code_section
)
9193 if(tis
) tis
->set_code_section(p_code_section
);
9194 block
->set_code_section(p_code_section
);
9198 char* SelectCase::generate_code_if(char *str
, const char *tmp_prefix
,
9199 const char *expr_name
, size_t idx
,
9202 if(unreach
) return str
;
9204 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++) {
9205 TemplateInstance
*ti
=tis
->get_ti_byIndex(i
);
9206 Template
*tb
=ti
->get_Template();
9207 bool is_value
= NULL
== ti
->get_DerivedRef() && tb
->is_Value();
9208 expression_struct exprs
;
9209 Code::init_expr(&exprs
);
9211 if (tb
->get_templatetype() == Template::SPECIFIC_VALUE
) {
9212 tb
->get_specific_value()->generate_code_expr_mandatory(&exprs
);
9215 Value
* val
= tb
->get_Value();
9216 if (NULL
== val
->get_my_governor()) {
9217 // the value's governor could not be determined, treat it as a non-value template
9221 val
->generate_code_expr_mandatory(&exprs
);
9227 ti
->generate_code(&exprs
);
9229 str
=tb
->update_location_object(str
);
9230 if(!exprs
.preamble
&& !exprs
.postamble
) {
9231 str
=mputstr(str
, "if(");
9233 str
=mputprintf(str
, "%s.match(%s%s)", exprs
.expr
, expr_name
,
9234 omit_in_value_list
? ", TRUE" : "");
9235 else str
=mputprintf(str
, "%s == %s", expr_name
, exprs
.expr
);
9236 str
=mputprintf(str
, ") goto %s_%lu;\n", tmp_prefix
,
9237 (unsigned long) idx
);
9238 Code::free_expr(&exprs
);
9241 str
=mputprintf(str
, "{\nboolean %s_%lub;\n", tmp_prefix
,
9242 (unsigned long) idx
);
9244 exprs
.expr
=mprintf("%s_%lub = ", tmp_prefix
, (unsigned long) idx
);
9246 exprs
.expr
=mputprintf(exprs
.expr
, "%s.match(%s%s)", s
, expr_name
,
9247 omit_in_value_list
? ", TRUE" : "");
9248 else exprs
.expr
=mputprintf(exprs
.expr
, "(%s == %s)", expr_name
, s
);
9250 str
=Code::merge_free_expr(str
, &exprs
);
9251 str
=mputprintf(str
, "if(%s_%lub) goto %s_%lu;\n}\n",
9252 tmp_prefix
, (unsigned long) idx
, tmp_prefix
, (unsigned long) idx
);
9257 unreach
=true; // else statement
9258 str
=mputprintf(str
, "goto %s_%lu;\n", tmp_prefix
, (unsigned long) idx
);
9264 char* SelectCase::generate_code_stmt(char *str
, const char *tmp_prefix
,
9265 size_t idx
, bool& unreach
)
9267 if(unreach
) return str
;
9268 if(!tis
) unreach
=true;
9269 str
=mputprintf(str
, "%s_%lu:\n{\n", tmp_prefix
, (unsigned long) idx
);
9270 str
=block
->generate_code(str
);
9271 str
=mputprintf(str
, "goto %s_end;\n}\n", tmp_prefix
);
9275 void SelectCase::ilt_generate_code_stmt(ILT
*ilt
, const char *tmp_prefix
,
9276 size_t idx
, bool& unreach
)
9279 if(!tis
) unreach
=true;
9280 char*& str
=ilt
->get_out_branches();
9281 str
=mputprintf(str
, "%s_%lu:\n", tmp_prefix
, (unsigned long) idx
);
9282 bool has_recv
=block
->has_receiving_stmt();
9284 str
=mputstr(str
, "{\n");
9285 str
=block
->generate_code(str
);
9287 else block
->ilt_generate_code(ilt
);
9288 str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9290 str
=mputstr(str
, "}\n");
9293 void SelectCase::set_parent_path(WithAttribPath
* p_path
) {
9294 block
->set_parent_path(p_path
);
9297 // =================================
9298 // ===== SelectCases
9299 // =================================
9301 SelectCases::~SelectCases()
9303 for(size_t i
=0; i
<scs
.size(); i
++) delete scs
[i
];
9307 SelectCases
*SelectCases::clone() const
9309 FATAL_ERROR("SelectCases::clone");
9312 void SelectCases::add_sc(SelectCase
*p_sc
)
9315 FATAL_ERROR("SelectCases::add_sc()");
9319 void SelectCases::set_my_scope(Scope
*p_scope
)
9321 for(size_t i
=0; i
<scs
.size(); i
++)
9322 scs
[i
]->set_my_scope(p_scope
);
9325 void SelectCases::set_fullname(const string
& p_fullname
)
9327 Node::set_fullname(p_fullname
);
9328 for(size_t i
=0; i
<scs
.size(); i
++)
9329 scs
[i
]->set_fullname(p_fullname
+".sc_"+Int2string(i
+1));
9332 void SelectCases::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9334 for(size_t i
=0; i
<scs
.size(); i
++)
9335 scs
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9338 void SelectCases::set_my_def(Definition
*p_def
)
9340 for(size_t i
=0; i
<scs
.size(); i
++)
9341 scs
[i
]->get_block()->set_my_def(p_def
);
9344 void SelectCases::set_my_ags(AltGuards
*p_ags
)
9346 for(size_t i
=0; i
<scs
.size(); i
++)
9347 scs
[i
]->get_block()->set_my_ags(p_ags
);
9350 void SelectCases::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9352 for(size_t i
=0; i
<scs
.size(); i
++)
9353 scs
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9356 StatementBlock::returnstatus_t
SelectCases::has_return() const
9358 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9359 bool has_else
= false;
9360 for (size_t i
= 0; i
< scs
.size(); i
++) {
9361 SelectCase
*sc
= scs
[i
];
9362 switch (sc
->get_block()->has_return()) {
9363 case StatementBlock::RS_NO
:
9364 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9365 else ret_val
= StatementBlock::RS_NO
;
9367 case StatementBlock::RS_YES
:
9368 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9369 else ret_val
= StatementBlock::RS_YES
;
9372 return StatementBlock::RS_MAYBE
;
9374 if (!sc
->get_tis()) {
9379 if (!has_else
&& ret_val
== StatementBlock::RS_YES
)
9380 return StatementBlock::RS_MAYBE
;
9381 else return ret_val
;
9384 bool SelectCases::has_receiving_stmt() const
9386 for(size_t i
=0; i
<scs
.size(); i
++)
9387 if(scs
[i
]->get_block()->has_receiving_stmt()) return true;
9392 void SelectCases::chk(Type
*p_gov
)
9395 for(size_t i
=0; i
<scs
.size(); i
++)
9396 scs
[i
]->chk(p_gov
, unreach
);
9399 void SelectCases::chk_allowed_interleave()
9401 for (size_t i
= 0; i
< scs
.size(); i
++)
9402 scs
[i
]->get_block()->chk_allowed_interleave();
9405 void SelectCases::set_code_section
9406 (GovernedSimple::code_section_t p_code_section
)
9408 for(size_t i
=0; i
<scs
.size(); i
++)
9409 scs
[i
]->set_code_section(p_code_section
);
9412 char* SelectCases::generate_code(char *str
, const char *tmp_prefix
,
9413 const char *expr_name
)
9416 for(size_t i
=0; i
<scs
.size(); i
++) {
9417 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9420 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9422 for(size_t i
=0; i
<scs
.size(); i
++) {
9423 str
=scs
[i
]->generate_code_stmt(str
, tmp_prefix
, i
, unreach
);
9426 str
=mputprintf(str
, "%s_end: /* empty */;\n", tmp_prefix
);
9430 void SelectCases::ilt_generate_code(ILT
*ilt
, const char *tmp_prefix
,
9431 const char *expr_init
,
9432 const char *expr_name
)
9434 char*& str
=ilt
->get_out_branches();
9435 if(strlen(expr_init
)) {
9436 str
=mputstr(str
, "{\n"); // (1)
9437 str
=mputstr(str
, expr_init
);
9440 for(size_t i
=0; i
<scs
.size(); i
++) {
9442 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9444 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9445 if(strlen(expr_init
)) str
=mputstr(str
, "}\n"); // (1)
9447 for(size_t i
=0; i
<scs
.size(); i
++) {
9449 scs
[i
]->ilt_generate_code_stmt(ilt
, tmp_prefix
, i
, unreach
);
9451 str
=mputprintf(str
, "%s_end:\n", tmp_prefix
);
9454 void SelectCases::set_parent_path(WithAttribPath
* p_path
) {
9455 for (size_t i
= 0; i
< scs
.size(); i
++)
9456 scs
[i
]->set_parent_path(p_path
);
9459 // =================================
9461 // =================================
9463 AltGuard::AltGuard(Value
*p_expr
, Statement
*p_stmt
, StatementBlock
*p_block
)
9464 : altguardtype(AG_OP
), expr(p_expr
), stmt(p_stmt
), block(p_block
)
9466 if (!p_stmt
|| !p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9469 AltGuard::AltGuard(Value
*p_expr
, Ref_pard
*p_ref
, StatementBlock
*p_block
)
9470 : altguardtype(AG_REF
), expr(p_expr
), ref(p_ref
), block(p_block
)
9472 if (!p_ref
) FATAL_ERROR("AltGuard::AltGuard()");
9475 AltGuard::AltGuard(Value
*p_expr
, Value
*p_v
,
9476 Ttcn::TemplateInstances
*p_t_list
, StatementBlock
*p_block
)
9477 : altguardtype(AG_INVOKE
), expr(p_expr
)
9480 if(!p_v
|| !p_t_list
) FATAL_ERROR("AltGuard::AltGuard()");
9482 invoke
.t_list
= p_t_list
;
9486 AltGuard::AltGuard(StatementBlock
*p_block
)
9487 : altguardtype(AG_ELSE
), expr(0), dummy(0), block(p_block
)
9489 if (!p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9492 AltGuard::~AltGuard()
9494 switch(altguardtype
) {
9508 delete invoke
.t_list
;
9509 delete invoke
.ap_list
;
9516 FATAL_ERROR("AltGuard::~AltGuard()");
9520 AltGuard
*AltGuard::clone() const
9522 FATAL_ERROR("AltGuard::clone");
9525 void AltGuard::set_my_scope(Scope
*p_scope
)
9527 switch(altguardtype
) {
9529 if(expr
) expr
->set_my_scope(p_scope
);
9530 stmt
->set_my_scope(p_scope
);
9531 block
->set_my_scope(p_scope
);
9534 if(expr
) expr
->set_my_scope(p_scope
);
9535 ref
->set_my_scope(p_scope
);
9536 if(block
) block
->set_my_scope(p_scope
);
9539 if(expr
) expr
->set_my_scope(p_scope
);
9540 invoke
.v
->set_my_scope(p_scope
);
9541 if(invoke
.t_list
) invoke
.t_list
->set_my_scope(p_scope
);
9542 if(invoke
.ap_list
) invoke
.ap_list
->set_my_scope(p_scope
);
9543 if(block
) block
->set_my_scope(p_scope
);
9546 block
->set_my_scope(p_scope
);
9549 FATAL_ERROR("AltGuard::set_my_scope()");
9553 void AltGuard::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9555 switch(altguardtype
) {
9557 stmt
->set_my_sb(p_sb
, p_index
);
9558 block
->set_my_sb(p_sb
, p_index
);
9561 if(block
) block
->set_my_sb(p_sb
, p_index
);
9564 if(block
) block
->set_my_sb(p_sb
, p_index
);
9567 block
->set_my_sb(p_sb
, p_index
);
9570 FATAL_ERROR("AltGuard::set_my_sb()");
9574 void AltGuard::set_fullname(const string
& p_fullname
)
9576 Node::set_fullname(p_fullname
);
9577 switch(altguardtype
) {
9579 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9580 stmt
->set_fullname(p_fullname
+".stmt");
9581 block
->set_fullname(p_fullname
+".block");
9584 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9585 ref
->set_fullname(p_fullname
+".ref");
9586 if(block
) block
->set_fullname(p_fullname
+".block");
9589 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9590 invoke
.v
->set_fullname(p_fullname
+".function");
9591 if(invoke
.t_list
) invoke
.t_list
->set_fullname(p_fullname
+".argument");
9592 if(invoke
.ap_list
) invoke
.ap_list
->set_fullname(p_fullname
+".argument");
9593 if(block
) block
->set_fullname(p_fullname
+".block");
9596 block
->set_fullname(p_fullname
+".elseblock");
9599 FATAL_ERROR("AltGuard::set_fullname()");
9603 Value
*AltGuard::get_guard_expr() const
9605 if (altguardtype
== AG_ELSE
) FATAL_ERROR("AltGuard::get_guard_expr()");
9609 Ref_pard
*AltGuard::get_guard_ref() const
9611 if (altguardtype
!= AG_REF
) FATAL_ERROR("AltGuard::get_guard_ref()");
9615 Statement
*AltGuard::get_guard_stmt() const
9617 if (altguardtype
!= AG_OP
) FATAL_ERROR("AltGuard::get_guard_stmt()");
9621 void AltGuard::set_my_def(Definition
*p_def
)
9623 switch(altguardtype
) {
9625 stmt
->set_my_def(p_def
);
9626 block
->set_my_def(p_def
);
9629 if(block
) block
->set_my_def(p_def
);
9632 if(block
) block
->set_my_def(p_def
);
9635 block
->set_my_def(p_def
);
9638 FATAL_ERROR("AltGuard::set_my_def()");
9642 void AltGuard::set_my_ags(AltGuards
*p_ags
)
9644 switch (altguardtype
) {
9646 block
->set_my_ags(p_ags
);
9649 if (block
) block
->set_my_ags(p_ags
);
9652 if (block
) block
->set_my_ags(p_ags
);
9655 block
->set_my_ags(p_ags
);
9658 FATAL_ERROR("AltGuard::set_my_ags()");
9662 void AltGuard::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9664 switch (altguardtype
) {
9666 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9669 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9672 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9675 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9678 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9682 void AltGuard::chk()
9684 switch(altguardtype
) {
9687 Error_Context
cntxt(expr
, "In guard expression");
9688 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9691 Error_Context
cntxt(stmt
, "In guard operation");
9698 Error_Context
cntxt(expr
, "In guard expression");
9699 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9702 Error_Context
cntxt(ref
, "In guard statement");
9703 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
9705 if (t_ass
->get_asstype() == Common::Assignment::A_ALTSTEP
) {
9706 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *ref
, "call");
9708 ref
->error("Reference to an altstep was expected instead of %s",
9709 t_ass
->get_description().c_str());
9713 if (block
) block
->chk();
9717 Error_Context
cntxt(expr
, "In guard expression");
9718 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9721 if (!invoke
.t_list
) return; //already_checked
9722 Error_Context
cntxt(ref
, "In guard statement");
9723 switch(invoke
.v
->get_valuetype()){
9724 case Value::V_REFER
:
9726 "A value of an altstep type was expected "
9727 "in the argument instead of a `refers' statement,"
9728 " which does not specify any function type");
9730 case Value::V_TTCN3_NULL
:
9732 "A value of an altstep type was expected "
9733 "in the argument instead of a `null' value,"
9734 " which does not specify any function type");
9739 Type
*t
= invoke
.v
->get_expr_governor_last();
9741 switch (t
->get_typetype()) {
9744 case Type::T_ALTSTEP
:
9747 invoke
.v
->error("A value of type altstep was expected instead of "
9748 "`%s'", t
->get_typename().c_str());
9751 invoke
.v
->get_my_scope()->chk_runs_on_clause(t
, *this, "call");
9752 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
9753 invoke
.ap_list
= new Ttcn::ActualParList
;
9754 bool is_erroneous
= fp_list
->chk_actual_parlist(invoke
.t_list
,
9756 delete invoke
.t_list
;
9759 delete invoke
.ap_list
;
9762 invoke
.ap_list
->set_fullname(get_fullname());
9763 invoke
.ap_list
->set_my_scope(invoke
.v
->get_my_scope());
9766 if (block
) block
->chk();
9770 Error_Context
cntxt(this, "In else branch");
9772 Statement
*first_stmt
= block
->get_first_stmt();
9773 if (first_stmt
&& first_stmt
->get_statementtype() ==
9774 Statement::S_REPEAT
)
9775 first_stmt
->warning("The first statement of the [else] branch is a "
9776 "repeat statement. This will result in busy waiting");
9780 FATAL_ERROR("AltGuard::chk()");
9784 void AltGuard::set_code_section(
9785 GovernedSimple::code_section_t p_code_section
)
9787 switch(altguardtype
) {
9789 if (expr
) expr
->set_code_section(p_code_section
);
9790 stmt
->set_code_section(p_code_section
);
9791 block
->set_code_section(p_code_section
);
9794 if (expr
) expr
->set_code_section(p_code_section
);
9795 ref
->set_code_section(p_code_section
);
9796 if (block
) block
->set_code_section(p_code_section
);
9799 if (expr
) expr
->set_code_section(p_code_section
);
9800 invoke
.v
->set_code_section(p_code_section
);
9801 if(invoke
.t_list
) invoke
.t_list
->set_code_section(p_code_section
);
9803 for(size_t i
= 0; i
< invoke
.ap_list
->get_nof_pars(); i
++)
9804 invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
9805 if (block
) block
->set_code_section(p_code_section
);
9808 block
->set_code_section(p_code_section
);
9811 FATAL_ERROR("AltGuard::set_fullname()");
9815 void AltGuard::generate_code_invoke_instance(expression_struct
*p_expr
)
9817 if (altguardtype
!= AG_INVOKE
)
9818 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9819 Value
*last_v
= invoke
.v
->get_value_refd_last();
9820 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
9821 Common::Assignment
*altstep
= last_v
->get_refd_fat();
9822 p_expr
->expr
= mputprintf(p_expr
->expr
, "%s_instance(",
9823 altstep
->get_genname_from_scope(invoke
.v
->get_my_scope()).c_str());
9824 invoke
.ap_list
->generate_code_alias(p_expr
,
9825 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9827 invoke
.v
->generate_code_expr_mandatory(p_expr
);
9828 p_expr
->expr
= mputstr(p_expr
->expr
, ".invoke(");
9829 Type
* gov_last
= invoke
.v
->get_expr_governor_last();
9830 invoke
.ap_list
->generate_code_alias(p_expr
, 0,
9831 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
9833 p_expr
->expr
= mputc(p_expr
->expr
, ')');
9836 // =================================
9838 // =================================
9840 AltGuards::~AltGuards()
9842 for(size_t i
=0; i
<ags
.size(); i
++) delete ags
[i
];
9845 delete il_label_end
;
9848 AltGuards
*AltGuards::clone() const
9850 FATAL_ERROR("AltGuards::clone");
9853 void AltGuards::add_ag(AltGuard
*p_ag
)
9856 FATAL_ERROR("AltGuards::add_ag()");
9860 void AltGuards::set_my_scope(Scope
*p_scope
)
9863 for(size_t i
=0; i
<ags
.size(); i
++)
9864 ags
[i
]->set_my_scope(p_scope
);
9867 void AltGuards::set_fullname(const string
& p_fullname
)
9869 Node::set_fullname(p_fullname
);
9870 for(size_t i
=0; i
<ags
.size(); i
++)
9871 ags
[i
]->set_fullname(p_fullname
+".ag_"+Int2string(i
+1));
9874 void AltGuards::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9876 for(size_t i
=0; i
<ags
.size(); i
++)
9877 ags
[i
]->set_my_sb(p_sb
, p_index
);
9880 void AltGuards::set_my_def(Definition
*p_def
)
9882 for(size_t i
=0; i
<ags
.size(); i
++)
9883 ags
[i
]->set_my_def(p_def
);
9886 void AltGuards::set_my_ags(AltGuards
*p_ags
)
9888 for(size_t i
=0; i
<ags
.size(); i
++)
9889 ags
[i
]->set_my_ags(p_ags
);
9892 void AltGuards::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9894 for(size_t i
=0; i
<ags
.size(); i
++)
9895 ags
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9898 bool AltGuards::has_else() const
9900 for (size_t i
= 0; i
< ags
.size(); i
++)
9901 if (ags
[i
]->get_type() == AltGuard::AG_ELSE
) return true;
9905 StatementBlock::returnstatus_t
AltGuards::has_return() const
9907 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9908 for (size_t i
= 0; i
< ags
.size(); i
++) {
9909 AltGuard
*ag
= ags
[i
];
9910 StatementBlock
*block
= ag
->get_block();
9911 StatementBlock::returnstatus_t block_status
;
9912 if (block
) block_status
= block
->has_return();
9913 else block_status
= StatementBlock::RS_NO
;
9914 switch (block_status
) {
9915 case StatementBlock::RS_NO
:
9916 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9917 else ret_val
= StatementBlock::RS_NO
;
9919 case StatementBlock::RS_YES
:
9920 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9921 else ret_val
= StatementBlock::RS_YES
;
9924 return StatementBlock::RS_MAYBE
;
9926 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9931 bool AltGuards::has_receiving_stmt() const
9933 for(size_t i
=0; i
<ags
.size(); i
++)
9934 if(ags
[i
]->get_block()->has_receiving_stmt()) return true;
9938 void AltGuards::chk()
9940 bool unreach_found
= false;
9941 size_t nof_ags
= ags
.size();
9942 AltGuard
*prev_ag
= 0;
9943 for (size_t i
= 0; i
< nof_ags
; i
++) {
9944 AltGuard
*ag
= ags
[i
];
9946 if (!unreach_found
&& prev_ag
&&
9947 prev_ag
->get_type() == AltGuard::AG_ELSE
) {
9948 ag
->warning("Control never reaches this branch of alternative "
9949 "because of the previous [else] branch");
9950 unreach_found
= true;
9956 void AltGuards::chk_allowed_interleave()
9958 for (size_t i
= 0; i
< ags
.size(); i
++) {
9959 AltGuard
*ag
= ags
[i
];
9960 switch (ag
->get_type()) {
9961 case AltGuard::AG_OP
:
9963 case AltGuard::AG_REF
:
9964 case AltGuard::AG_INVOKE
:
9965 ag
->error("Invocation of an altstep is not allowed within an "
9966 "interleave statement");
9968 case AltGuard::AG_ELSE
:
9969 ag
->error("Else branch of an alternative is not allowed within an "
9970 "interleave statement");
9973 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
9975 ag
->get_block()->chk_allowed_interleave();
9979 void AltGuards::set_code_section(
9980 GovernedSimple::code_section_t p_code_section
)
9982 for (size_t i
= 0; i
< ags
.size(); i
++)
9983 ags
[i
]->set_code_section(p_code_section
);
9986 char *AltGuards::generate_code_alt(char *str
, const Location
& loc
)
9988 bool label_needed
= has_repeat
, has_else_branch
= false;
9989 for (size_t i
= 0; i
< ags
.size(); i
++) {
9990 AltGuard
*ag
= ags
[i
];
9991 switch (ag
->get_type()) {
9992 case AltGuard::AG_OP
:
9993 // trigger may return ALT_REPEAT
9994 if (ag
->get_guard_stmt()->can_repeat()) label_needed
= true;
9996 case AltGuard::AG_REF
:
9997 case AltGuard::AG_INVOKE
:
9998 // an altstep may return ALT_REPEAT
9999 label_needed
= true;
10001 case AltGuard::AG_ELSE
:
10002 has_else_branch
= true;
10005 FATAL_ERROR("AltGuards::generate_code_alt()");
10007 if (has_else_branch
) break;
10009 // if there is no [else] branch the defaults may return ALT_REPEAT
10010 if (!has_else_branch
) label_needed
= true;
10011 // opening bracket of the statement block
10012 str
= mputstr(str
, "{\n");
10013 // the label name is also used for prefixing local variables
10014 if (!my_scope
|| label
) FATAL_ERROR("AltGuards::generate_code_alt()");
10015 label
= new string(my_scope
->get_scope_mod_gen()->get_temporary_id());
10016 const char *label_str
= label
->c_str();
10017 if (label_needed
) str
= mputprintf(str
, "%s:\n", label_str
);
10018 // temporary variables used for caching of status codes
10019 for (size_t i
= 0; i
< ags
.size(); i
++) {
10020 AltGuard
*ag
= ags
[i
];
10021 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
10022 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10023 label_str
, (unsigned long) i
,
10024 ag
->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
10026 if (!has_else_branch
) {
10027 str
= mputprintf(str
, "alt_status %s_default_flag = ALT_MAYBE;\n",
10030 // the first snapshot is taken in non-blocking mode
10031 // and opening infinite for() loop
10032 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10033 "for ( ; ; ) {\n");
10034 for (size_t i
= 0; i
< ags
.size(); i
++) {
10035 AltGuard
*ag
= ags
[i
];
10036 AltGuard::altguardtype_t agtype
= ag
->get_type();
10037 if (agtype
== AltGuard::AG_ELSE
) {
10038 // an else branch was found
10039 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10040 StatementBlock
*block
= ag
->get_block();
10041 if (block
->get_nof_stmts() > 0) {
10042 str
= mputstr(str
, "{\n");
10043 str
= block
->generate_code(str
);
10044 str
= mputstr(str
, "}\n");
10046 // jump out of the infinite for() loop
10047 if (block
->has_return() != StatementBlock::RS_YES
)
10048 str
= mputstr(str
, "break;\n");
10049 // do not generate code for further branches
10052 Value
*guard_expr
= ag
->get_guard_expr();
10054 // the branch has a boolean guard expression
10055 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
10056 label_str
, (unsigned long) i
);
10057 str
= guard_expr
->update_location_object(str
);
10058 expression_struct expr
;
10059 Code::init_expr(&expr
);
10060 guard_expr
->generate_code_expr(&expr
);
10061 str
= mputstr(str
, expr
.preamble
);
10062 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10063 "else %s_alt_flag_%lu = ALT_NO;\n", expr
.expr
, label_str
,
10064 (unsigned long) i
, label_str
, (unsigned long) i
);
10065 str
= mputstr(str
, expr
.postamble
);
10066 Code::free_expr(&expr
);
10067 str
= mputstr(str
, "}\n");
10069 // evaluation of guard operation or altstep
10070 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
10071 label_str
, (unsigned long) i
);
10072 // indicates whether the guard operation might return ALT_REPEAT
10074 expression_struct expr
;
10075 Code::init_expr(&expr
);
10076 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10077 (unsigned long) i
);
10079 case AltGuard::AG_OP
: {
10080 // the guard operation is a receiving statement
10081 Statement
*stmt
= ag
->get_guard_stmt();
10082 str
= stmt
->update_location_object(str
);
10083 stmt
->generate_code_expr(&expr
);
10084 can_repeat
= stmt
->can_repeat();
10086 case AltGuard::AG_REF
: {
10087 // the guard operation is an altstep instance
10088 Ref_pard
*ref
= ag
->get_guard_ref();
10089 str
= ref
->update_location_object(str
);
10090 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10091 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10092 altstep
->get_genname_from_scope(my_scope
).c_str());
10093 ref
->get_parlist()->generate_code_alias(&expr
,
10094 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10095 expr
.expr
= mputc(expr
.expr
, ')');
10098 case AltGuard::AG_INVOKE
: {
10099 // the guard operation is an altstep invocation
10100 str
= ag
->update_location_object(str
);
10101 ag
->generate_code_invoke_instance(&expr
);
10105 FATAL_ERROR("AltGuards::generate_code_alt()");
10107 str
= Code::merge_free_expr(str
, &expr
);
10109 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
10110 label_str
, (unsigned long) i
, label_str
);
10112 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10113 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
10114 label_str
, (unsigned long) i
);
10116 // execution of statement block if the guard was successful
10117 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10118 (unsigned long) i
);
10119 StatementBlock
*block
= ag
->get_block();
10120 if (block
&& block
->get_nof_stmts() > 0) {
10121 str
= mputstr(str
, "{\n");
10122 str
= block
->generate_code(str
);
10123 if (block
->has_return() != StatementBlock::RS_YES
)
10124 str
= mputstr(str
, "break;\n");
10125 str
= mputstr(str
, "}\n");
10126 } else str
= mputstr(str
, "break;\n");
10127 // closing of if() block
10128 str
= mputstr(str
, "}\n");
10131 if (!has_else_branch
) {
10132 // calling of defaults
10133 str
= mputprintf(str
, "if (%s_default_flag == ALT_MAYBE) {\n"
10134 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10135 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10137 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10139 label_str
, label_str
, label_str
, label_str
, label_str
, label_str
);
10140 str
= loc
.update_location_object(str
);
10141 // error handling and taking the next snapshot in blocking mode
10142 str
= mputstr(str
, "if (");
10143 for (size_t i
= 0; i
< ags
.size(); i
++)
10144 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO && ", label_str
,
10145 (unsigned long) i
);
10146 str
= mputprintf(str
,"%s_default_flag == ALT_NO) "
10147 "TTCN_error(\"None of the branches can be chosen in the alt "
10148 "statement in file ", label_str
);
10149 str
= Code::translate_string(str
, loc
.get_filename());
10150 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10151 if (first_line
< last_line
) str
= mputprintf(str
,
10152 " between lines %d and %d", first_line
, last_line
);
10153 else str
= mputprintf(str
, ", line %d", first_line
);
10154 str
= mputstr(str
, ".\");\n"
10155 "TTCN_Snapshot::take_new(TRUE);\n");
10157 // end of for() statement and the statement block
10158 str
= mputstr(str
, "}\n"
10163 char *AltGuards::generate_code_altstep(char *str
)
10165 if (!my_scope
) FATAL_ERROR("AltGuards::generate_code_altstep()");
10166 Common::Module
*my_mod
= my_scope
->get_scope_mod_gen();
10167 bool has_else_branch
= has_else();
10168 if (!has_else_branch
) {
10169 str
= mputstr(str
, "alt_status ret_val = ALT_NO;\n");
10171 for (size_t i
= 0; i
< ags
.size(); i
++) {
10172 AltGuard
*ag
= ags
[i
];
10173 AltGuard::altguardtype_t agtype
= ag
->get_type();
10174 if (agtype
== AltGuard::AG_ELSE
) {
10175 // an else branch was found
10176 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10177 StatementBlock
*block
= ag
->get_block();
10178 if (block
->get_nof_stmts() > 0) {
10179 str
= mputstr(str
, "{\n");
10180 str
= block
->generate_code(str
);
10181 str
= mputstr(str
, "}\n");
10183 if (block
->has_return() != StatementBlock::RS_YES
)
10184 str
= mputstr(str
, "return ALT_YES;\n");
10185 // do not generate code for further branches
10188 size_t blockcount
= 0;
10189 Value
*guard_expr
= ag
->get_guard_expr();
10191 // the branch has a boolean guard expression
10192 str
= guard_expr
->update_location_object(str
);
10193 str
= guard_expr
->generate_code_tmp(str
, "if (", blockcount
);
10194 str
= mputstr(str
, ") {\n");
10197 // indicates whether the guard operation might return ALT_REPEAT
10199 expression_struct expr
;
10200 Code::init_expr(&expr
);
10202 case AltGuard::AG_OP
: {
10203 // the guard operation is a receiving statement
10204 Statement
*stmt
= ag
->get_guard_stmt();
10205 str
= stmt
->update_location_object(str
);
10206 stmt
->generate_code_expr(&expr
);
10207 can_repeat
= stmt
->can_repeat();
10209 case AltGuard::AG_REF
: {
10210 // the guard operation is an altstep instance
10211 Ref_pard
*ref
= ag
->get_guard_ref();
10212 str
= ref
->update_location_object(str
);
10213 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10214 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10215 altstep
->get_genname_from_scope(my_scope
).c_str());
10216 ref
->get_parlist()->generate_code_alias(&expr
,
10217 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10218 expr
.expr
= mputc(expr
.expr
, ')');
10221 case AltGuard::AG_INVOKE
: {
10222 str
= ag
->update_location_object(str
);
10223 ag
->generate_code_invoke_instance(&expr
);
10227 FATAL_ERROR("AltGuards::generate_code_altstep()");
10229 if (expr
.preamble
|| expr
.postamble
) {
10230 if (blockcount
== 0) {
10231 // open a statement block if it is not done so far
10232 str
= mputstr(str
, "{\n");
10235 const string
& tmp_id
= my_mod
->get_temporary_id();
10236 const char *tmp_id_str
= tmp_id
.c_str();
10237 str
= mputprintf(str
, "alt_status %s;\n"
10238 "{\n", tmp_id_str
);
10239 str
= mputstr(str
, expr
.preamble
);
10240 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, expr
.expr
);
10241 str
= mputstr(str
, expr
.postamble
);
10242 str
= mputprintf(str
, "}\n"
10243 "switch (%s) {\n", tmp_id_str
);
10245 str
= mputprintf(str
, "switch (%s) {\n", expr
.expr
);
10247 Code::free_expr(&expr
);
10248 str
= mputstr(str
, "case ALT_YES:\n");
10249 StatementBlock
*block
= ag
->get_block();
10250 if (block
&& block
->get_nof_stmts() > 0) {
10251 str
= mputstr(str
, "{\n");
10252 str
= block
->generate_code(str
);
10253 str
= mputstr(str
, "}\n");
10255 if (!block
|| block
->has_return() != StatementBlock::RS_YES
)
10256 str
= mputstr(str
, "return ALT_YES;\n");
10258 str
= mputstr(str
, "case ALT_REPEAT:\n"
10259 "return ALT_REPEAT;\n");
10260 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10261 str
= mputprintf(str
, "case ALT_BREAK:\n"
10262 "return ALT_BREAK;\n");
10264 if (!has_else_branch
)
10265 str
= mputstr(str
, "case ALT_MAYBE:\n"
10266 "ret_val = ALT_MAYBE;\n");
10267 str
= mputstr(str
, "default:\n"
10270 // closing statement blocks
10271 for ( ; blockcount
> 0; blockcount
--) str
= mputstr(str
, "}\n");
10274 if (!has_else_branch
) str
= mputstr(str
, "return ret_val;\n");
10278 char* AltGuards::generate_code_call_body(char *str
, const Location
& loc
,
10279 const string
& temp_id
, bool in_interleave
)
10281 if (label
) FATAL_ERROR("AltGuards::generate_code_call_body()");
10282 label
= new string(temp_id
);
10283 const char *label_str
= temp_id
.c_str();
10284 // label is needed only if there is a repeat statement in the branches
10285 if (has_repeat
) str
= mputprintf(str
, "%s:\n", label_str
);
10286 // temporary variables used for caching of status codes
10287 for (size_t i
= 0; i
< ags
.size(); i
++)
10288 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10289 label_str
, (unsigned long) i
,
10290 ags
[i
]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10291 str
= loc
.update_location_object(str
);
10292 // the first snapshot is taken in non-blocking mode
10293 // and opening infinite for() loop
10294 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10295 "for ( ; ; ) {\n"); // (1)
10296 for (size_t i
= 0; i
< ags
.size(); i
++) {
10297 AltGuard
*ag
= ags
[i
];
10298 if (ag
->get_type() != AltGuard::AG_OP
)
10299 FATAL_ERROR("AltGuards::generate_code_call_body()");
10300 Value
*guard_expr
= ag
->get_guard_expr();
10302 // the branch has a boolean guard expression
10303 str
= mputprintf(str
,
10304 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10305 label_str
, (unsigned long) i
);
10306 str
= guard_expr
->update_location_object(str
);
10307 expression_struct expr
;
10308 Code::init_expr(&expr
);
10309 guard_expr
->generate_code_expr(&expr
);
10310 str
= mputstr(str
, expr
.preamble
);
10311 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10312 "else %s_alt_flag_%lu = ALT_NO;\n",
10313 expr
.expr
, label_str
, (unsigned long) i
,
10314 label_str
, (unsigned long) i
);
10315 str
= mputstr(str
, expr
.postamble
);
10316 Code::free_expr(&expr
);
10317 str
= mputstr(str
, "}\n"); // (2)
10319 // evaluation of guard operation
10320 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10321 label_str
, (unsigned long) i
);
10322 expression_struct expr
;
10323 Code::init_expr(&expr
);
10324 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10325 (unsigned long) i
);
10326 Statement
*stmt
= ag
->get_guard_stmt();
10327 str
= stmt
->update_location_object(str
);
10328 stmt
->generate_code_expr(&expr
);
10329 str
= Code::merge_free_expr(str
, &expr
);
10330 // execution of statement block if the guard was successful
10331 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10332 (unsigned long) i
);
10333 StatementBlock
*block
= ag
->get_block();
10334 if(in_interleave
) {
10335 if(block
&& block
->get_nof_stmts() > 0) {
10336 if(block
->has_receiving_stmt()) {
10337 str
= mputprintf(str
, "goto %s_branch%lu;\n",
10338 label_str
, (unsigned long) i
);
10341 str
= mputstr(str
, "{\n"); // (3)
10342 str
= block
->generate_code(str
);
10343 str
= mputprintf(str
, "goto %s_end;\n"
10348 else str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10351 if (block
&& block
->get_nof_stmts() > 0) {
10352 str
= mputstr(str
, "{\n"); // (3)
10353 str
= block
->generate_code(str
);
10354 if (block
->has_return() != StatementBlock::RS_YES
)
10355 str
= mputstr(str
, "break;\n");
10356 str
= mputstr(str
, "}\n"); // (3)
10358 else str
= mputstr(str
, "break;\n");
10360 // closing of if() block
10361 str
= mputstr(str
, "}\n"); // (2)
10363 str
= loc
.update_location_object(str
);
10364 // error handling and taking the next snapshot in blocking mode
10365 str
= mputstr(str
, "if (");
10366 for (size_t i
= 0; i
< ags
.size(); i
++) {
10367 if (i
> 0) str
= mputstr(str
, " && ");
10368 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO", label_str
,
10369 (unsigned long) i
);
10371 str
= mputstr(str
, ") TTCN_error(\"None of the branches can be chosen in "
10372 "the response and exception handling part of call statement in file ");
10373 str
= Code::translate_string(str
, loc
.get_filename());
10374 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10375 if (first_line
< last_line
) str
= mputprintf(str
,
10376 " between lines %d and %d", first_line
, last_line
);
10377 else str
= mputprintf(str
, ", line %d", first_line
);
10378 str
= mputstr(str
, ".\");\n"
10379 "TTCN_Snapshot::take_new(TRUE);\n"
10384 void AltGuards::ilt_generate_code_call_body(ILT
*ilt
, const char *label_str
)
10386 char*& str
=ilt
->get_out_branches();
10387 for(size_t i
=0; i
<ags
.size(); i
++) {
10388 StatementBlock
*block
= ags
[i
]->get_block();
10389 if (block
&& block
->has_receiving_stmt()) {
10390 str
= mputprintf(str
, "%s_branch%lu:\n", label_str
, (unsigned long) i
);
10391 block
->ilt_generate_code(ilt
);
10392 str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10397 } // namespace Ttcn