1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../../common/dbgnew.hh"
9 #include "Statement.hh"
10 #include "Ttcnstuff.hh"
11 #include "../TypeCompat.hh"
12 #include "../CompType.hh"
13 #include "../CompField.hh"
14 #include "../SigParam.hh"
15 #include "TtcnTemplate.hh"
17 #include "ArrayDimensions.hh"
20 #include "Attributes.hh"
24 // =================================
25 // ===== StatementBlock
26 // =================================
28 StatementBlock::StatementBlock()
29 : Scope(), checked(false), labels_checked(false), my_sb(0), my_def(0), exception_handling(EH_NONE
)
33 StatementBlock::~StatementBlock()
35 for(size_t i
=0; i
<stmts
.size(); i
++)
42 StatementBlock
*StatementBlock::clone() const
44 FATAL_ERROR("StatementBlock::clone");
47 void StatementBlock::dump(unsigned int level
) const
49 size_t n
= stmts
.size();
50 DEBUG(level
, "StatementBlock at %p with %lu", (const void*)this,
52 for (size_t i
= 0; i
< n
; ++i
) {
53 stmts
[i
]->dump(level
+1);
57 void StatementBlock::add_stmt(Statement
*p_stmt
, bool to_front
)
60 FATAL_ERROR("StatementBlock::add_stmt()");
62 stmts
.add_front(p_stmt
);
66 p_stmt
->set_my_scope(this);
67 p_stmt
->set_my_sb(this, stmts
.size()-1);
70 void StatementBlock::set_my_scope(Scope
*p_scope
)
72 set_parent_scope(p_scope
);
73 for(size_t i
=0; i
<stmts
.size(); i
++)
74 stmts
[i
]->set_my_scope(this);
77 void StatementBlock::set_fullname(const string
& p_fullname
)
79 Node::set_fullname(p_fullname
);
80 for(size_t i
=0; i
<stmts
.size(); i
++)
81 stmts
[i
]->set_fullname(p_fullname
+".stmt_"+Int2string(i
+1));
84 /** \todo handle loops and conditional statements */
85 Statement
*StatementBlock::get_first_stmt() const
87 size_t nof_stmts
= stmts
.size();
88 for (size_t i
= 0; i
< nof_stmts
; i
++) {
89 Statement
*stmt
= stmts
[i
];
90 switch (stmt
->get_statementtype()) {
91 case Statement::S_LABEL
:
92 // ignore and go to the next statement
94 case Statement::S_BLOCK
: {
95 // if the block is not empty return its first statement
96 // otherwise go to the next statement
97 Statement
*first_stmt
= stmt
->get_block()->get_first_stmt();
98 if (first_stmt
) return first_stmt
;
100 case Statement::S_DOWHILE
: {
101 // if the block is not empty return its first statement
102 // otherwise return the whole do-while statement
103 Statement
*first_stmt
= stmt
->get_block()->get_first_stmt();
104 if (first_stmt
) return first_stmt
;
113 void StatementBlock::register_def(Definition
*p_def
)
115 if(!p_def
) FATAL_ERROR("StatementBlock::register_def()");
116 const Identifier
& id
=p_def
->get_id();
117 if (defs
.has_key(id
)) {
118 const char *dispname
= id
.get_dispname().c_str();
119 p_def
->error("Duplicate definition with identifier `%s'", dispname
);
120 defs
[id
]->note("Previous definition with identifier `%s' is here",
125 if (parent_scope
->has_ass_withId(id
)) {
126 const char *dispname
= id
.get_dispname().c_str();
127 p_def
->error("Definition with identifier `%s' is not unique"
128 " in the scope hierarchy", dispname
);
129 Reference
ref(0, id
.clone());
130 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
131 if (!ass
) FATAL_ERROR("StatementBlock::register_def()");
132 ass
->note("Previous definition with identifier `%s' in higher "
133 "scope unit is here", dispname
);
134 } else if (parent_scope
->is_valid_moduleid(id
)) {
135 p_def
->warning("Definition with name `%s' hides a module identifier",
136 id
.get_dispname().c_str());
142 bool StatementBlock::has_ass_withId(const Identifier
& p_id
)
144 return defs
.has_key(p_id
) || get_parent_scope()->has_ass_withId(p_id
);
147 Common::Assignment
* StatementBlock::get_ass_bySRef(Ref_simple
*p_ref
)
149 if(p_ref
->get_modid()) return get_parent_scope()->get_ass_bySRef(p_ref
);
150 const Identifier
& id
=*p_ref
->get_id();
151 if(defs
.has_key(id
)) return defs
[id
];
152 else return get_parent_scope()->get_ass_bySRef(p_ref
);
155 Type
*StatementBlock::get_mtc_system_comptype(bool is_system
)
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
;
682 FATAL_ERROR("Statement::clean_up()");
683 } // switch statementtype
686 Statement::Statement(statementtype_t p_st
)
687 : statementtype(p_st
), my_sb(0)
689 switch(statementtype
) {
694 case S_START_PROFILER
:
695 case S_STOP_PROFILER
:
703 FATAL_ERROR("Statement::Statement()");
704 } // switch statementtype
707 Statement::Statement(statementtype_t p_st
, Ref_base
*p_ref
, Value
*p_val
)
708 : statementtype(p_st
), my_sb(0)
710 switch(statementtype
) {
712 if (!p_ref
) FATAL_ERROR("Statement::Statement()");
713 undefstartstop
.ref
=p_ref
;
714 undefstartstop
.val
=p_val
;
717 if (!p_ref
|| p_val
) FATAL_ERROR("Statement::Statement()");
718 undefstartstop
.ref
=p_ref
;
719 undefstartstop
.val
=0;
722 FATAL_ERROR("Statement::Statement()");
723 } // switch statementtype
726 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
)
727 : statementtype(p_st
), my_sb(0)
729 switch(statementtype
) {
730 case S_UNKNOWN_INSTANCE
:
731 case S_FUNCTION_INSTANCE
:
732 case S_ALTSTEP_INSTANCE
:
735 FATAL_ERROR("Statement::Statement()");
739 FATAL_ERROR("Statement::Statement()");
740 } // switch statementtype
743 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
744 ParsedActualParameters
*p_ap_list
)
745 : statementtype(p_st
), my_sb(0)
747 switch(statementtype
) {
748 case S_ACTIVATE_REFD
:
749 case S_UNKNOWN_INVOKED
:
750 case S_FUNCTION_INVOKED
:
751 case S_ALTSTEP_INVOKED
:
752 if(!p_derefered_value
|| !p_ap_list
)
753 FATAL_ERROR("Statement::Statement()");
754 fau_refd
.value
= p_derefered_value
;
755 fau_refd
.t_list1
= p_ap_list
;
758 FATAL_ERROR("Statement::Statement()");
762 Statement::Statement(statementtype_t p_st
, Definition
*p_def
)
763 : statementtype(p_st
), my_sb(0)
765 switch(statementtype
) {
768 FATAL_ERROR("Statement::Statement()");
772 FATAL_ERROR("Statement::Statement()");
773 } // switch statementtype
776 Statement::Statement(statementtype_t p_st
, Assignment
*p_ass
)
777 : statementtype(p_st
), my_sb(0)
779 switch(statementtype
) {
782 FATAL_ERROR("Statement::Statement()");
786 FATAL_ERROR("Statement::Statement()");
787 } // switch statementtype
790 Statement::Statement(statementtype_t p_st
, StatementBlock
*p_block
)
791 : statementtype(p_st
), my_sb(0)
793 switch (statementtype
) {
795 if (!p_block
) FATAL_ERROR("Statement::Statement()");
799 FATAL_ERROR("Statement::Statement()");
800 } // switch statementtype
803 Statement::Statement(statementtype_t p_st
, LogArguments
*p_logargs
)
804 : statementtype(p_st
), my_sb(0)
806 switch(statementtype
) {
809 case S_STOP_TESTCASE
:
813 FATAL_ERROR("Statement::Statement()");
814 } // switch statementtype
817 Statement::Statement(statementtype_t p_st
, Identifier
*p_id
)
818 : statementtype(p_st
), my_sb(0)
821 FATAL_ERROR("Statement::Statement()");
822 switch (statementtype
) {
833 go_to
.jumps_forward
= false;
836 FATAL_ERROR("Statement::Statement()");
837 } // switch statementtype
840 Statement::Statement(statementtype_t p_st
, IfClauses
*p_ics
,
841 StatementBlock
*p_block
, Location
*p_loc
)
842 : statementtype(p_st
), my_sb(0)
844 switch(statementtype
) {
847 FATAL_ERROR("Statement::Statement()");
850 if (!p_loc
) FATAL_ERROR("Statement::Statement()");
851 if_stmt
.elseblock
= p_block
;
852 if_stmt
.elseblock_location
= p_loc
;
854 if (p_loc
) FATAL_ERROR("Statement::Statement()");
855 if_stmt
.elseblock
= 0;
856 if_stmt
.elseblock_location
= 0;
860 FATAL_ERROR("Statement::Statement()");
861 } // switch statementtype
864 Statement::Statement(statementtype_t p_st
, Value
*p_expr
, SelectCases
*p_scs
)
865 : statementtype(p_st
), my_sb(0)
867 switch(statementtype
) {
869 if(!p_expr
|| !p_scs
)
870 FATAL_ERROR("Statement::Statement()");
875 FATAL_ERROR("Statement::Statement()");
876 } // switch statementtype
879 Statement::Statement(statementtype_t p_st
, Definitions
*p_defs
,
880 Assignment
*p_ass
, Value
*p_final
,
881 Assignment
*p_step
, StatementBlock
*p_block
)
882 : statementtype(p_st
), my_sb(0)
884 switch (statementtype
) {
885 case S_FOR
: // precisely one of p_defs, p_ass allowed
887 // it came from a for loop which looked like this:
888 // for (var integer foo:=1; foo<10; foo:=foo+1) ;
889 if (p_ass
) FATAL_ERROR("Statement::Statement()");
890 loop
.for_stmt
.varinst
= true;
891 loop
.for_stmt
.init_varinst
= p_defs
;
893 // it came from a for loop which looked like this:
894 // for (foo:=1; foo<10; foo:=foo+1) ;
895 if (!p_ass
) FATAL_ERROR("Statement::Statement()");
896 loop
.for_stmt
.varinst
= false;
897 loop
.for_stmt
.init_ass
= p_ass
;
899 if(!p_final
|| !p_step
|| !p_block
)
900 FATAL_ERROR("Statement::Statement()");
901 loop
.for_stmt
.finalexpr
=p_final
;
902 loop
.for_stmt
.step
=p_step
;
908 loop
.has_cnt_in_ags
=false;
909 loop
.iterate_once
=false; // not used by for
913 FATAL_ERROR("Statement::Statement()");
914 } // switch statementtype
917 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
918 StatementBlock
*p_block
)
919 : statementtype(p_st
), my_sb(0)
921 switch(statementtype
) {
924 if(!p_val
|| !p_block
)
925 FATAL_ERROR("Statement::Statement()");
932 loop
.has_cnt_in_ags
=false;
933 loop
.iterate_once
=false; // used only by do-while
937 FATAL_ERROR("Statement::Statement()");
938 } // switch statementtype
941 Statement::Statement(statementtype_t p_st
, AltGuards
*p_ags
)
942 : statementtype(p_st
), my_sb(0)
944 switch(statementtype
) {
948 FATAL_ERROR("Statement::Statement()");
952 FATAL_ERROR("Statement::Statement()");
953 } // switch statementtype
956 Statement::Statement(statementtype_t p_st
, Template
*p_temp
)
957 : statementtype(p_st
), my_sb(0)
959 switch(statementtype
) {
965 FATAL_ERROR("Statement::Statement()");
966 } // switch statementtype
969 Statement::Statement(statementtype_t p_st
, Value
*p_val
)
970 : statementtype(p_st
), my_sb(0)
972 switch (statementtype
) {
975 FATAL_ERROR("Statement::Statement()");
979 comp_op
.compref
=p_val
;
985 FATAL_ERROR("Statement::Statement()");
986 } // switch statementtype
989 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
990 LogArguments
*p_logargs
)
991 : statementtype(p_st
), my_sb(0)
993 if (!p_val
|| statementtype
!= S_SETVERDICT
)
994 FATAL_ERROR("Statement::Statement()");
995 setverdict
.verdictval
= p_val
;
996 setverdict
.logargs
= p_logargs
;
999 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1000 TemplateInstance
*p_templinst
, Value
*p_val
)
1001 : statementtype(p_st
), my_sb(0)
1003 switch(statementtype
) {
1005 if(!p_ref
|| !p_templinst
)
1006 FATAL_ERROR("Statement::Statement()");
1007 port_op
.portref
=p_ref
;
1008 port_op
.s
.sendpar
=p_templinst
;
1009 port_op
.s
.toclause
=p_val
;
1012 FATAL_ERROR("Statement::Statement()");
1013 } // switch statementtype
1016 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1017 TemplateInstance
*p_templinst
, Value
*p_timerval
,
1018 bool p_nowait
, Value
*p_toclause
, AltGuards
*p_callbody
)
1019 : statementtype(p_st
), my_sb(0)
1021 switch(statementtype
) {
1023 if(!p_ref
|| !p_templinst
|| (p_timerval
&& p_nowait
))
1024 FATAL_ERROR("Statement::Statement()");
1025 port_op
.portref
=p_ref
;
1026 port_op
.s
.sendpar
=p_templinst
;
1027 port_op
.s
.call
.timer
=p_timerval
;
1028 port_op
.s
.call
.nowait
=p_nowait
;
1029 port_op
.s
.toclause
=p_toclause
;
1030 port_op
.s
.call
.body
=p_callbody
;
1033 FATAL_ERROR("Statement::Statement()");
1034 } // switch statementtype
1037 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1038 TemplateInstance
*p_templinst
, Value
*p_replyval
,
1040 : statementtype(p_st
), my_sb(0)
1042 switch(statementtype
) {
1044 if(!p_ref
|| !p_templinst
)
1045 FATAL_ERROR("Statement::Statement()");
1046 port_op
.portref
=p_ref
;
1047 port_op
.s
.sendpar
=p_templinst
;
1048 port_op
.s
.replyval
=p_replyval
;
1049 port_op
.s
.toclause
=p_toclause
;
1052 FATAL_ERROR("Statement::Statement()");
1053 } // switch statementtype
1056 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1057 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1059 : statementtype(p_st
), my_sb(0)
1061 switch(statementtype
) {
1063 if(!p_ref
|| !p_templinst
|| !p_sig
)
1064 FATAL_ERROR("Statement::Statement()");
1065 port_op
.portref
=p_ref
;
1066 port_op
.s
.raise
.signature_ref
=p_sig
;
1067 port_op
.s
.raise
.signature
=0;
1068 port_op
.s
.sendpar
=p_templinst
;
1069 port_op
.s
.toclause
=p_toclause
;
1072 FATAL_ERROR("Statement::Statement()");
1073 } // switch statementtype
1076 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1077 TemplateInstance
*p_templinst
,
1078 TemplateInstance
*p_fromclause
,
1079 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1080 : statementtype(p_st
), my_sb(0)
1082 switch(statementtype
) {
1084 case S_CHECK_RECEIVE
:
1086 port_op
.portref
=p_ref
;
1087 port_op
.r
.rcvpar
=p_templinst
;
1088 port_op
.r
.fromclause
=p_fromclause
;
1089 port_op
.r
.redirect
.value
=p_redirectval
;
1090 port_op
.r
.redirect
.param
=0;
1091 port_op
.r
.redirect
.sender
=p_redirectsender
;
1094 FATAL_ERROR("Statement::Statement()");
1095 } // switch statementtype
1098 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1099 TemplateInstance
*p_templinst
,
1100 TemplateInstance
*p_fromclause
,
1101 ParamRedirect
*p_redirectparam
,
1102 Reference
*p_redirectsender
)
1103 : statementtype(p_st
), my_sb(0)
1105 switch(statementtype
) {
1107 case S_CHECK_GETCALL
:
1108 port_op
.portref
=p_ref
;
1109 port_op
.r
.rcvpar
=p_templinst
;
1110 port_op
.r
.fromclause
=p_fromclause
;
1111 port_op
.r
.redirect
.value
=0;
1112 port_op
.r
.redirect
.param
=p_redirectparam
;
1113 port_op
.r
.redirect
.sender
=p_redirectsender
;
1116 FATAL_ERROR("Statement::Statement()");
1117 } // switch statementtype
1120 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1121 TemplateInstance
*p_templinst
,
1122 TemplateInstance
*p_valuematch
,
1123 TemplateInstance
*p_fromclause
,
1124 Reference
*p_redirectval
, ParamRedirect
*p_redirectparam
,
1125 Reference
*p_redirectsender
)
1126 : statementtype(p_st
), my_sb(0)
1128 switch(statementtype
) {
1130 case S_CHECK_GETREPLY
:
1131 if (!p_templinst
&& p_valuematch
) FATAL_ERROR("Statement::Statement()");
1132 port_op
.portref
=p_ref
;
1133 port_op
.r
.rcvpar
=p_templinst
;
1134 port_op
.r
.getreply_valuematch
=p_valuematch
;
1135 port_op
.r
.fromclause
=p_fromclause
;
1136 port_op
.r
.redirect
.value
=p_redirectval
;
1137 port_op
.r
.redirect
.param
=p_redirectparam
;
1138 port_op
.r
.redirect
.sender
=p_redirectsender
;
1141 FATAL_ERROR("Statement::Statement()");
1142 } // switch statementtype
1145 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1146 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1147 bool p_timeout
, TemplateInstance
*p_fromclause
,
1148 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1149 : statementtype(p_st
), my_sb(0)
1151 switch(statementtype
) {
1154 if (((p_sig
|| p_templinst
) && p_timeout
) ||
1155 (p_sig
&& !p_templinst
) || (!p_sig
&& p_templinst
))
1156 FATAL_ERROR("Statement::Statement()");
1157 port_op
.portref
=p_ref
;
1158 port_op
.r
.ctch
.signature_ref
=p_sig
;
1159 port_op
.r
.ctch
.signature
=0;
1160 port_op
.r
.rcvpar
=p_templinst
;
1161 port_op
.r
.ctch
.timeout
=p_timeout
;
1162 port_op
.r
.ctch
.in_call
=false;
1163 port_op
.r
.ctch
.call_has_timer
=false;
1164 port_op
.r
.fromclause
=p_fromclause
;
1165 port_op
.r
.redirect
.value
=p_redirectval
;
1166 port_op
.r
.redirect
.param
=0;
1167 port_op
.r
.redirect
.sender
=p_redirectsender
;
1170 FATAL_ERROR("Statement::Statement()");
1171 } // switch statementtype
1174 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1175 TemplateInstance
*p_fromclause
,
1176 Reference
*p_redirectsender
)
1177 : statementtype(p_st
), my_sb(0)
1179 switch(statementtype
) {
1181 port_op
.portref
=p_ref
; // may be NULL for "any port.check"
1182 port_op
.r
.fromclause
=p_fromclause
;
1183 port_op
.r
.redirect
.value
=0;
1184 port_op
.r
.redirect
.param
=0;
1185 port_op
.r
.redirect
.sender
=p_redirectsender
;
1188 FATAL_ERROR("Statement::Statement()");
1189 } // switch statementtype
1192 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
)
1193 : statementtype(p_st
), my_sb(0)
1195 switch(statementtype
) {
1200 port_op
.portref
=p_ref
;
1204 timer_op
.timerref
=p_ref
;
1207 FATAL_ERROR("Statement::Statement()");
1208 } // switch statementtype
1211 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1212 Ref_pard
*p_funcinst
)
1213 : statementtype(p_st
), my_sb(0)
1215 switch(statementtype
) {
1217 if(!p_compref
|| !p_funcinst
)
1218 FATAL_ERROR("Statement::Statement()");
1219 comp_op
.compref
= p_compref
;
1220 comp_op
.funcinstref
= p_funcinst
;
1223 FATAL_ERROR("Statement::Statement()");
1224 } // switch statementtype
1227 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1228 Value
*p_derefered_value
, ParsedActualParameters
*p_ap_list
)
1229 : statementtype(p_st
), my_sb(0)
1231 switch(statementtype
) {
1232 case S_START_COMP_REFD
:
1233 if(!p_compref
|| !p_derefered_value
|| !p_ap_list
)
1234 FATAL_ERROR("Statement::Statement()");
1235 comp_op
.compref
= p_compref
;
1236 comp_op
.derefered
.value
= p_derefered_value
;
1237 comp_op
.derefered
.t_list1
= p_ap_list
;
1240 FATAL_ERROR("Statement::Statement()");
1244 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1245 TemplateInstance
*p_donematch
, Reference
*p_redirect
)
1246 : statementtype(p_st
), my_sb(0)
1248 switch (statementtype
) {
1250 if (!p_compref
) FATAL_ERROR("Statement::Statement()");
1251 comp_op
.compref
= p_compref
;
1252 comp_op
.donereturn
.donematch
= p_donematch
;
1253 comp_op
.donereturn
.redirect
= p_redirect
;
1256 FATAL_ERROR("Statement::Statement()");
1257 } // switch statementtype
1260 Statement::Statement(statementtype_t p_st
, component_t p_anyall
)
1261 : statementtype(p_st
), my_sb(0)
1263 switch (statementtype
) {
1266 comp_op
.compref
= 0;
1267 comp_op
.any_or_all
= p_anyall
;
1270 FATAL_ERROR("Statement::Statement()");
1271 } // switch statementtype
1274 Statement::Statement(statementtype_t p_st
,
1275 Value
*p_compref1
, Reference
*p_portref1
,
1276 Value
*p_compref2
, Reference
*p_portref2
)
1277 : statementtype(p_st
), my_sb(0)
1279 switch(statementtype
) {
1284 if(!p_compref1
|| !p_portref1
|| !p_compref2
|| !p_portref2
)
1285 FATAL_ERROR("Statement::Statement()");
1286 config_op
.compref1
=p_compref1
;
1287 config_op
.portref1
=p_portref1
;
1288 config_op
.compref2
=p_compref2
;
1289 config_op
.portref2
=p_portref2
;
1292 FATAL_ERROR("Statement::Statement()");
1293 } // switch statementtype
1296 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
, Value
*p_val
)
1297 : statementtype(p_st
), my_sb(0)
1299 switch(statementtype
) {
1300 case S_TESTCASE_INSTANCE
:
1302 FATAL_ERROR("Statement::Statement()");
1303 testcase_inst
.tcref
=p_ref
;
1304 testcase_inst
.timerval
=p_val
;
1307 FATAL_ERROR("Statement::Statement()");
1308 } // switch statementtype
1311 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
1312 TemplateInstances
*p_ap_list
, Value
*p_val
)
1313 : statementtype(p_st
), my_sb(0)
1315 switch(statementtype
) {
1316 case S_TESTCASE_INSTANCE_REFD
:
1317 if(!p_derefered_value
) FATAL_ERROR("Statement::Statement()");
1318 execute_refd
.value
= p_derefered_value
;
1319 execute_refd
.t_list1
= p_ap_list
;
1320 execute_refd
.timerval
= p_val
;
1323 FATAL_ERROR("Statement::Statement()");
1327 Statement::Statement(statementtype_t p_st
, Value
* p_val
, Reference
* p_ref
): statementtype(p_st
), my_sb(0)
1329 if (p_st
!=S_STRING2TTCN
|| p_val
==NULL
|| p_ref
==NULL
) FATAL_ERROR("Statement::Statement()");
1330 str2ttcn
.val
= p_val
;
1331 str2ttcn
.ref
= p_ref
;
1334 Statement::~Statement()
1339 Statement
*Statement::clone() const
1341 FATAL_ERROR("Statement::clone");
1344 void Statement::dump(unsigned int level
) const
1346 DEBUG(level
, "Statement at %p, a(n) %s", (const void *)this,
1348 switch (statementtype
) {
1349 case S_TESTCASE_INSTANCE
:
1350 case S_TESTCASE_INSTANCE_REFD
: {
1351 Common::Value
*v
= execute_refd
.value
;
1355 def
->dump(level
+ 1);
1358 ass
->dump(level
+ 1);
1361 block
->dump(level
+ 1);
1364 if_stmt
.ics
->dump(level
+ 1);
1365 if (if_stmt
.elseblock
) if_stmt
.elseblock
->dump(level
+ 1);
1372 size_t Statement::get_my_sb_index() const
1374 switch (statementtype
) {
1376 return label
.stmt_idx
;
1378 return go_to
.stmt_idx
;
1380 FATAL_ERROR("Statement::get_my_sb_index()");
1385 const char *Statement::get_stmt_name() const
1387 switch(statementtype
) {
1388 case S_ERROR
: return "<erroneous statement>";
1389 case S_START_UNDEF
: return "start";
1390 case S_STOP_UNDEF
: return "stop";
1391 case S_UNKNOWN_INSTANCE
: return "function or altstep instance";
1392 case S_UNKNOWN_INVOKED
: return "function or altstep type invocation";
1393 case S_DEF
: return "definition";
1394 case S_ASSIGNMENT
: return "assignment";
1395 case S_FUNCTION_INSTANCE
: return "function instance";
1396 case S_FUNCTION_INVOKED
: return "function type invocation";
1397 case S_BLOCK
: return "statement block";
1398 case S_LOG
: return "log";
1399 case S_LABEL
: return "label";
1400 case S_GOTO
: return "goto";
1401 case S_IF
: return "if";
1402 case S_SELECT
: return "select-case";
1403 case S_FOR
: return "for";
1404 case S_WHILE
: return "while";
1405 case S_DOWHILE
: return "do-while";
1406 case S_BREAK
: return "break";
1407 case S_CONTINUE
: return "continue";
1408 case S_STOP_EXEC
: return "stop";
1409 case S_STOP_TESTCASE
: return "testcase.stop";
1410 case S_ALT
: return "alt";
1411 case S_REPEAT
: return "repeat";
1412 case S_INTERLEAVE
: return "interleave";
1413 case S_ALTSTEP_INSTANCE
: return "altstep instance";
1414 case S_ALTSTEP_INVOKED
: return "altstep type invocation";
1415 case S_RETURN
: return "return";
1417 case S_ACTIVATE_REFD
:
1419 case S_DEACTIVATE
: return "deactivate";
1420 case S_SEND
: return "send";
1421 case S_CALL
: return "call";
1422 case S_REPLY
: return "reply";
1423 case S_RAISE
: return "raise";
1424 case S_RECEIVE
: return "receive";
1425 case S_TRIGGER
: return "trigger";
1426 case S_GETCALL
: return "getcall";
1427 case S_GETREPLY
: return "getreply";
1428 case S_CATCH
: return "catch";
1429 case S_CHECK
: return "check";
1430 case S_CHECK_RECEIVE
: return "check-receive";
1431 case S_CHECK_GETCALL
: return "check-getcall";
1432 case S_CHECK_GETREPLY
: return "check-getreply";
1433 case S_CHECK_CATCH
: return "check-catch";
1434 case S_CLEAR
: return "clear";
1435 case S_START_PORT
: return "start port";
1436 case S_STOP_PORT
: return "stop port";
1437 case S_HALT
: return "halt";
1439 case S_START_COMP_REFD
:
1440 return "start test component";
1441 case S_STOP_COMP
: return "stop test component";
1442 case S_DONE
: return "done";
1443 case S_KILL
: return "kill";
1444 case S_KILLED
: return "killed";
1445 case S_CONNECT
: return "connect";
1446 case S_MAP
: return "map";
1447 case S_DISCONNECT
: return "disconnect";
1448 case S_UNMAP
: return "unmap";
1449 case S_START_TIMER
: return "start timer";
1450 case S_STOP_TIMER
: return "stop timer";
1451 case S_TIMEOUT
: return "timeout";
1452 case S_SETVERDICT
: return "setverdict";
1453 case S_ACTION
: return "action";
1454 case S_TESTCASE_INSTANCE
:
1455 case S_TESTCASE_INSTANCE_REFD
:
1457 case S_STRING2TTCN
: return "string2ttcn";
1458 case S_START_PROFILER
: return "@profiler.start";
1459 case S_STOP_PROFILER
: return "@profiler.stop";
1461 FATAL_ERROR("Statement::get_stmt_name()");
1463 } // switch statementtype
1466 const Identifier
& Statement::get_labelid() const
1468 switch (statementtype
) {
1474 FATAL_ERROR("Statement::get_labelid()");
1479 bool Statement::label_is_used() const
1481 if (statementtype
!= S_LABEL
) FATAL_ERROR("Statement::label_is_used()");
1485 bool Statement::goto_jumps_forward() const
1487 if (statementtype
!= S_GOTO
) FATAL_ERROR("Statement::goto_jumps_forward()");
1488 return go_to
.jumps_forward
;
1491 const string
& Statement::get_clabel()
1493 if (statementtype
!= S_LABEL
|| !my_sb
)
1494 FATAL_ERROR("Statement::get_clabel()");
1495 if (!label
.clabel
) label
.clabel
=
1496 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
1497 return *label
.clabel
;
1500 Definition
*Statement::get_def() const
1502 if (statementtype
!= S_DEF
) FATAL_ERROR("Statement::get_def()");
1506 AltGuards
*Statement::get_ags() const
1508 if (statementtype
!= S_ALT
&& statementtype
!= S_INTERLEAVE
)
1509 FATAL_ERROR("Statement::get_ags()");
1513 StatementBlock
*Statement::get_block() const
1515 switch (statementtype
) {
1523 FATAL_ERROR("Statement::get_block()");
1528 void Statement::set_my_scope(Scope
*p_scope
)
1530 switch(statementtype
) {
1538 case S_START_PROFILER
:
1539 case S_STOP_PROFILER
:
1543 undefstartstop
.ref
->set_my_scope(p_scope
);
1544 if (undefstartstop
.val
) undefstartstop
.val
->set_my_scope(p_scope
);
1546 case S_UNKNOWN_INSTANCE
:
1547 case S_FUNCTION_INSTANCE
:
1548 case S_ALTSTEP_INSTANCE
:
1550 ref_pard
->set_my_scope(p_scope
);
1553 def
->set_my_scope(p_scope
);
1556 ass
->set_my_scope(p_scope
);
1559 block
->set_my_scope(p_scope
);
1563 case S_STOP_TESTCASE
:
1564 if (logargs
) logargs
->set_my_scope(p_scope
);
1567 if_stmt
.ics
->set_my_scope(p_scope
);
1568 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_scope(p_scope
);
1571 select
.expr
->set_my_scope(p_scope
);
1572 select
.scs
->set_my_scope(p_scope
);
1575 if (loop
.for_stmt
.varinst
) {
1576 loop
.for_stmt
.init_varinst
->set_parent_scope(p_scope
);
1577 loop
.for_stmt
.finalexpr
->set_my_scope(loop
.for_stmt
.init_varinst
);
1578 loop
.for_stmt
.step
->set_my_scope(loop
.for_stmt
.init_varinst
);
1579 loop
.block
->set_my_scope(loop
.for_stmt
.init_varinst
);
1581 loop
.for_stmt
.init_ass
->set_my_scope(p_scope
);
1582 loop
.for_stmt
.finalexpr
->set_my_scope(p_scope
);
1583 loop
.for_stmt
.step
->set_my_scope(p_scope
);
1584 loop
.block
->set_my_scope(p_scope
);
1589 loop
.expr
->set_my_scope(p_scope
);
1590 loop
.block
->set_my_scope(p_scope
);
1594 ags
->set_my_scope(p_scope
);
1597 if (returnexpr
.v
) returnexpr
.v
->set_my_scope(p_scope
);
1598 if (returnexpr
.t
) returnexpr
.t
->set_my_scope(p_scope
);
1601 if (deactivate
) deactivate
->set_my_scope(p_scope
);
1604 port_op
.portref
->set_my_scope(p_scope
);
1605 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1606 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1609 port_op
.portref
->set_my_scope(p_scope
);
1610 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1611 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1612 if(port_op
.s
.call
.timer
) port_op
.s
.call
.timer
->set_my_scope(p_scope
);
1613 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->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
.replyval
) port_op
.s
.replyval
->set_my_scope(p_scope
);
1619 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1622 port_op
.portref
->set_my_scope(p_scope
);
1623 port_op
.s
.raise
.signature_ref
->set_my_scope(p_scope
);
1624 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1625 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1628 case S_CHECK_RECEIVE
:
1630 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1631 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1632 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1633 if(port_op
.r
.redirect
.value
)
1634 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1635 if(port_op
.r
.redirect
.sender
)
1636 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1639 case S_CHECK_GETCALL
:
1640 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1641 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1642 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1643 if(port_op
.r
.redirect
.param
)
1644 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1645 if(port_op
.r
.redirect
.sender
)
1646 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1649 case S_CHECK_GETREPLY
:
1650 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1651 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1652 if(port_op
.r
.getreply_valuematch
)
1653 port_op
.r
.getreply_valuematch
->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
.value
)
1656 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1657 if(port_op
.r
.redirect
.param
)
1658 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1659 if(port_op
.r
.redirect
.sender
)
1660 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1664 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1665 if(port_op
.r
.ctch
.signature_ref
)
1666 port_op
.r
.ctch
.signature_ref
->set_my_scope(p_scope
);
1667 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1668 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1669 if(port_op
.r
.redirect
.value
)
1670 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1671 if(port_op
.r
.redirect
.sender
)
1672 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1675 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1676 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1677 if(port_op
.r
.redirect
.sender
)
1678 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1684 if (port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1687 comp_op
.compref
->set_my_scope(p_scope
);
1688 comp_op
.funcinstref
->set_my_scope(p_scope
);
1690 case S_START_COMP_REFD
:
1691 comp_op
.compref
->set_my_scope(p_scope
);
1692 comp_op
.derefered
.value
->set_my_scope(p_scope
);
1693 comp_op
.derefered
.t_list1
->set_my_scope(p_scope
);
1698 if (comp_op
.compref
) comp_op
.compref
->set_my_scope(p_scope
);
1701 if (comp_op
.compref
) {
1702 comp_op
.compref
->set_my_scope(p_scope
);
1703 if (comp_op
.donereturn
.donematch
)
1704 comp_op
.donereturn
.donematch
->set_my_scope(p_scope
);
1705 if (comp_op
.donereturn
.redirect
)
1706 comp_op
.donereturn
.redirect
->set_my_scope(p_scope
);
1713 config_op
.compref1
->set_my_scope(p_scope
);
1714 config_op
.portref1
->set_my_scope(p_scope
);
1715 config_op
.compref2
->set_my_scope(p_scope
);
1716 config_op
.portref2
->set_my_scope(p_scope
);
1719 timer_op
.timerref
->set_my_scope(p_scope
);
1720 if (timer_op
.value
) timer_op
.value
->set_my_scope(p_scope
);
1724 if (timer_op
.timerref
) timer_op
.timerref
->set_my_scope(p_scope
);
1727 setverdict
.verdictval
->set_my_scope(p_scope
);
1728 if (setverdict
.logargs
)
1729 setverdict
.logargs
->set_my_scope(p_scope
);
1731 case S_TESTCASE_INSTANCE
:
1732 testcase_inst
.tcref
->set_my_scope(p_scope
);
1733 if (testcase_inst
.timerval
) testcase_inst
.timerval
->set_my_scope(p_scope
);
1735 case S_TESTCASE_INSTANCE_REFD
:
1736 execute_refd
.value
->set_my_scope(p_scope
);
1737 execute_refd
.t_list1
->set_my_scope(p_scope
);
1738 if(execute_refd
.timerval
) execute_refd
.timerval
->set_my_scope(p_scope
);
1740 case S_ACTIVATE_REFD
:
1741 case S_UNKNOWN_INVOKED
:
1742 case S_FUNCTION_INVOKED
:
1743 case S_ALTSTEP_INVOKED
:
1744 fau_refd
.value
->set_my_scope(p_scope
);
1745 fau_refd
.t_list1
->set_my_scope(p_scope
);
1748 str2ttcn
.val
->set_my_scope(p_scope
);
1749 str2ttcn
.ref
->set_my_scope(p_scope
);
1752 FATAL_ERROR("Statement::set_my_scope()");
1753 } // switch statementtype
1756 void Statement::set_fullname(const string
& p_fullname
)
1758 Node::set_fullname(p_fullname
);
1759 switch (statementtype
) {
1767 case S_START_PROFILER
:
1768 case S_STOP_PROFILER
:
1772 undefstartstop
.ref
->set_fullname(p_fullname
+".ref");
1773 if (undefstartstop
.val
)
1774 undefstartstop
.val
->set_fullname(p_fullname
+".val");
1776 case S_UNKNOWN_INSTANCE
:
1777 case S_FUNCTION_INSTANCE
:
1778 case S_ALTSTEP_INSTANCE
:
1780 ref_pard
->set_fullname(p_fullname
+".ref");
1783 def
->set_fullname(p_fullname
+".def");
1786 ass
->set_fullname(p_fullname
+".ass");
1789 block
->set_fullname(p_fullname
+".block");
1793 case S_STOP_TESTCASE
:
1794 if (logargs
) logargs
->set_fullname(p_fullname
+".logargs");
1797 if_stmt
.ics
->set_fullname(p_fullname
+".ifclauses");
1798 if (if_stmt
.elseblock
)
1799 if_stmt
.elseblock
->set_fullname(p_fullname
+".elseblock");
1802 select
.expr
->set_fullname(p_fullname
+".expr");
1803 select
.scs
->set_fullname(p_fullname
+".scs");
1806 if(loop
.for_stmt
.varinst
)
1807 loop
.for_stmt
.init_varinst
->set_fullname(p_fullname
+".init");
1809 loop
.for_stmt
.init_ass
->set_fullname(p_fullname
+".init");
1810 loop
.for_stmt
.finalexpr
->set_fullname(p_fullname
+".final");
1811 loop
.for_stmt
.step
->set_fullname(p_fullname
+".step");
1812 loop
.block
->set_fullname(p_fullname
+".block");
1816 loop
.expr
->set_fullname(p_fullname
+".expr");
1817 loop
.block
->set_fullname(p_fullname
+".block");
1821 ags
->set_fullname(p_fullname
+".ags");
1824 if (returnexpr
.v
) returnexpr
.v
->set_fullname(p_fullname
+".returnexpr");
1825 if (returnexpr
.t
) returnexpr
.t
->set_fullname(p_fullname
+".returnexpr");
1828 if (deactivate
) deactivate
->set_fullname(p_fullname
+".deact");
1831 port_op
.portref
->set_fullname(p_fullname
+".portref");
1832 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1833 if(port_op
.s
.toclause
)
1834 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1837 port_op
.portref
->set_fullname(p_fullname
+".portref");
1838 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1839 if(port_op
.s
.toclause
)
1840 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1841 if(port_op
.s
.call
.timer
)
1842 port_op
.s
.call
.timer
->set_fullname(p_fullname
+".timer");
1843 if(port_op
.s
.call
.body
)
1844 port_op
.s
.call
.body
->set_fullname(p_fullname
+".body");
1847 port_op
.portref
->set_fullname(p_fullname
+".portref");
1848 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1849 if(port_op
.s
.replyval
)
1850 port_op
.s
.replyval
->set_fullname(p_fullname
+".replyval");
1851 if(port_op
.s
.toclause
)
1852 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1855 port_op
.portref
->set_fullname(p_fullname
+".portref");
1856 port_op
.s
.raise
.signature_ref
->set_fullname(p_fullname
+".sign");
1857 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1858 if(port_op
.s
.toclause
)
1859 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1862 case S_CHECK_RECEIVE
:
1864 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1865 if(port_op
.r
.rcvpar
)
1866 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1867 if(port_op
.r
.fromclause
)
1868 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1869 if(port_op
.r
.redirect
.value
)
1870 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1871 if(port_op
.r
.redirect
.sender
)
1872 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1875 case S_CHECK_GETCALL
:
1876 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1877 if(port_op
.r
.rcvpar
)
1878 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1879 if(port_op
.r
.fromclause
)
1880 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1881 if(port_op
.r
.redirect
.param
)
1882 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1883 if(port_op
.r
.redirect
.sender
)
1884 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1887 case S_CHECK_GETREPLY
:
1888 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1889 if(port_op
.r
.rcvpar
)
1890 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1891 if(port_op
.r
.getreply_valuematch
)
1892 port_op
.r
.getreply_valuematch
->set_fullname(p_fullname
+".valmatch");
1893 if(port_op
.r
.fromclause
)
1894 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1895 if(port_op
.r
.redirect
.value
)
1896 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1897 if(port_op
.r
.redirect
.param
)
1898 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1899 if(port_op
.r
.redirect
.sender
)
1900 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1904 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1905 if(port_op
.r
.ctch
.signature_ref
)
1906 port_op
.r
.ctch
.signature_ref
->set_fullname(p_fullname
+".sign");
1907 if(port_op
.r
.rcvpar
)
1908 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1909 if(port_op
.r
.fromclause
)
1910 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1911 if(port_op
.r
.redirect
.value
)
1912 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1913 if(port_op
.r
.redirect
.sender
)
1914 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
.fromclause
)
1919 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1920 if(port_op
.r
.redirect
.sender
)
1921 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1927 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1930 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1931 comp_op
.funcinstref
->set_fullname(p_fullname
+".funcref");
1933 case S_START_COMP_REFD
:
1934 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1935 comp_op
.derefered
.value
->set_fullname(p_fullname
+".funcref");
1936 comp_op
.derefered
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1941 if (comp_op
.compref
) comp_op
.compref
->set_fullname(p_fullname
+".compref");
1944 if(comp_op
.compref
) {
1945 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1946 if(comp_op
.donereturn
.donematch
)
1947 comp_op
.donereturn
.donematch
->set_fullname(p_fullname
+".donematch");
1948 if(comp_op
.donereturn
.redirect
)
1949 comp_op
.donereturn
.redirect
->set_fullname(p_fullname
+".redir");
1956 config_op
.compref1
->set_fullname(p_fullname
+".compref1");
1957 config_op
.portref1
->set_fullname(p_fullname
+".portref1");
1958 config_op
.compref2
->set_fullname(p_fullname
+".compref2");
1959 config_op
.portref2
->set_fullname(p_fullname
+".portref2");
1962 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1963 if(timer_op
.value
) timer_op
.value
->set_fullname(p_fullname
+".timerval");
1967 if (timer_op
.timerref
)
1968 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1971 setverdict
.verdictval
->set_fullname(p_fullname
+".verdictval");
1972 if (setverdict
.logargs
)
1973 setverdict
.logargs
->set_fullname(p_fullname
+".verdictreason");
1975 case S_TESTCASE_INSTANCE
:
1976 testcase_inst
.tcref
->set_fullname(p_fullname
+".tcref");
1977 if (testcase_inst
.timerval
)
1978 testcase_inst
.timerval
->set_fullname(p_fullname
+".timerval");
1980 case S_TESTCASE_INSTANCE_REFD
:
1981 execute_refd
.value
->set_fullname(p_fullname
+".tcref");
1982 execute_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1983 if(execute_refd
.timerval
)
1984 execute_refd
.timerval
->set_fullname(p_fullname
+".timerval");
1986 case S_ACTIVATE_REFD
:
1987 case S_UNKNOWN_INVOKED
:
1988 case S_FUNCTION_INVOKED
:
1989 case S_ALTSTEP_INVOKED
:
1990 fau_refd
.value
->set_fullname(p_fullname
+".ref");
1991 fau_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1994 str2ttcn
.val
->set_fullname(p_fullname
+".ti");
1995 str2ttcn
.ref
->set_fullname(p_fullname
+".ref");
1998 FATAL_ERROR("Statement::set_fullname()");
1999 } // switch statementtype
2002 void Statement::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
2005 switch(statementtype
) {
2007 block
->set_my_sb(p_sb
, p_index
);
2010 label
.stmt_idx
= p_index
;
2013 go_to
.stmt_idx
= p_index
;
2016 if_stmt
.ics
->set_my_sb(p_sb
, p_index
);
2017 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_sb(p_sb
, p_index
);
2020 select
.scs
->set_my_sb(p_sb
, p_index
);
2025 loop
.block
->set_my_sb(p_sb
, p_index
);
2029 ags
->set_my_sb(p_sb
, p_index
);
2032 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_sb(p_sb
, p_index
);
2036 } // switch statementtype
2039 void Statement::set_my_def(Definition
*p_def
)
2041 switch (statementtype
) {
2043 block
->set_my_def(p_def
);
2046 if_stmt
.ics
->set_my_def(p_def
);
2047 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_def(p_def
);
2050 select
.scs
->set_my_def(p_def
);
2055 loop
.block
->set_my_def(p_def
);
2059 ags
->set_my_def(p_def
);
2062 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_def(p_def
);
2066 } // switch statementtype
2069 void Statement::set_my_ags(AltGuards
*p_ags
)
2071 switch (statementtype
) {
2073 block
->set_my_ags(p_ags
);
2076 if_stmt
.ics
->set_my_ags(p_ags
);
2077 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_ags(p_ags
);
2080 select
.scs
->set_my_ags(p_ags
);
2085 loop
.block
->set_my_ags(p_ags
);
2092 } // switch statementtype
2095 void Statement::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
2097 switch (statementtype
) {
2099 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2102 if_stmt
.ics
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2103 if (if_stmt
.elseblock
)
2104 if_stmt
.elseblock
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2107 select
.scs
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2112 ags
->set_my_laic_stmt(0, p_loop_stmt
); // ags is set later
2115 if (p_loop_stmt
&& port_op
.s
.call
.body
)
2116 port_op
.s
.call
.body
->set_my_laic_stmt(0, p_loop_stmt
);
2122 brk_cnt
.loop_stmt
=p_loop_stmt
;
2127 } // switch statementtype
2130 /** \todo handle blocks, loops and conditional statements
2131 * (i.e. investigate their last statements within the block) */
2132 bool Statement::is_terminating() const
2134 switch (statementtype
) {
2139 case S_STOP_TESTCASE
:
2145 // checking for self.stop, self.kill, mtc.stop and mtc.kill
2146 if (comp_op
.compref
) {
2147 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
2148 if (v_last
->get_valuetype() == Value::V_EXPR
) {
2149 switch (v_last
->get_optype()) {
2150 case Value::OPTYPE_COMP_SELF
:
2151 case Value::OPTYPE_COMP_MTC
:
2161 if(!loop
.expr
->is_unfoldable() && loop
.expr
->get_val_bool()) {
2162 return !loop
.has_brk
; // not endless loop if it has a break
2170 StatementBlock::returnstatus_t
Statement::has_return() const
2172 switch (statementtype
) {
2174 return block
->has_return();
2176 return if_stmt
.ics
->has_return(if_stmt
.elseblock
);
2178 return select
.scs
->has_return();
2181 if (loop
.block
->has_return() == StatementBlock::RS_NO
)
2182 return StatementBlock::RS_NO
;
2183 else return StatementBlock::RS_MAYBE
;
2185 return loop
.block
->has_return();
2187 StatementBlock::returnstatus_t ret_val
= ags
->has_return();
2188 if (ret_val
== StatementBlock::RS_YES
&& !ags
->has_else()) {
2189 // the invoked defaults may skip the entire statement
2190 ret_val
= StatementBlock::RS_MAYBE
;
2194 if (port_op
.s
.call
.body
) return port_op
.s
.call
.body
->has_return();
2195 else return StatementBlock::RS_NO
;
2197 if (is_terminating()) return StatementBlock::RS_YES
;
2198 else return StatementBlock::RS_NO
;
2202 bool Statement::is_receiving_stmt() const
2204 switch (statementtype
) {
2207 case S_ALTSTEP_INSTANCE
:
2208 case S_ALTSTEP_INVOKED
:
2210 case S_CHECK_RECEIVE
:
2213 case S_CHECK_GETCALL
:
2215 case S_CHECK_GETREPLY
:
2225 } // switch statementtype
2228 bool Statement::has_receiving_stmt() const
2230 switch (statementtype
) {
2233 case S_FUNCTION_INSTANCE
:
2234 case S_FUNCTION_INVOKED
:
2243 case S_STOP_TESTCASE
:
2247 case S_ACTIVATE_REFD
:
2257 case S_START_COMP_REFD
:
2267 case S_TESTCASE_INSTANCE
:
2268 case S_TESTCASE_INSTANCE_REFD
:
2269 case S_START_PROFILER
:
2270 case S_STOP_PROFILER
:
2274 case S_ALTSTEP_INSTANCE
:
2275 case S_ALTSTEP_INVOKED
:
2277 case S_CHECK_RECEIVE
:
2280 case S_CHECK_GETCALL
:
2282 case S_CHECK_GETREPLY
:
2291 return block
->has_receiving_stmt();
2293 return if_stmt
.ics
->has_receiving_stmt()
2294 || (if_stmt
.elseblock
&& if_stmt
.elseblock
->has_receiving_stmt());
2296 return select
.scs
->has_receiving_stmt();
2300 return loop
.block
->has_receiving_stmt();
2302 return port_op
.s
.call
.body
&& port_op
.s
.call
.body
->has_receiving_stmt();
2306 case S_UNKNOWN_INSTANCE
:
2307 case S_UNKNOWN_INVOKED
:
2309 FATAL_ERROR("Statement::has_receiving_stmt()");
2310 } // switch statementtype
2313 bool Statement::can_repeat() const
2315 switch (statementtype
) {
2321 case S_CHECK_RECEIVE
:
2323 case S_CHECK_GETCALL
:
2325 case S_CHECK_GETREPLY
:
2332 FATAL_ERROR("Statement::can_repeat()");
2333 } // switch statementtype
2336 void Statement::chk()
2338 switch (statementtype
) {
2347 case S_UNKNOWN_INSTANCE
:
2348 chk_unknown_instance();
2350 case S_UNKNOWN_INVOKED
:
2351 case S_FUNCTION_INVOKED
:
2352 case S_ALTSTEP_INVOKED
:
2353 chk_unknown_invoke();
2357 my_sb
->register_def(def
);
2362 case S_FUNCTION_INSTANCE
:
2370 case S_STOP_TESTCASE
:
2371 chk_log_action(logargs
);
2412 case S_ALTSTEP_INSTANCE
:
2421 case S_ACTIVATE_REFD
:
2422 chk_activate_refd();
2440 case S_CHECK_RECEIVE
:
2445 case S_CHECK_GETCALL
:
2449 case S_CHECK_GETREPLY
:
2465 chk_start_stop_port();
2470 case S_START_COMP_REFD
:
2471 chk_start_comp_refd();
2475 chk_stop_kill_comp();
2496 chk_stop_timer_timeout();
2500 chk_log_action(setverdict
.logargs
); // for checking verdictreason
2502 case S_TESTCASE_INSTANCE
:
2505 case S_TESTCASE_INSTANCE_REFD
:
2511 case S_START_PROFILER
:
2512 case S_STOP_PROFILER
:
2516 FATAL_ERROR("Statement::chk()");
2517 } // switch statementtype
2520 void Statement::chk_string2ttcn()
2522 Error_Context
cntxt(this, "In string2ttcn() statement");
2523 str2ttcn
.val
->chk_expr_type(Type::T_CSTR
, "charstring", Type::EXPECTED_DYNAMIC_VALUE
);
2525 Common::Assignment
* refd_ass
= str2ttcn
.ref
->get_refd_assignment();
2526 if (refd_ass
==NULL
) {
2527 error("Could not determine the assignment for second parameter");
2530 switch (refd_ass
->get_asstype()) {
2531 case Definition::A_PAR_VAL_IN
:
2532 case Definition::A_PAR_TEMPL_IN
:
2533 refd_ass
->use_as_lvalue(*str2ttcn
.ref
);
2534 case Definition::A_VAR
:
2535 case Definition::A_VAR_TEMPLATE
:
2536 case Definition::A_PAR_VAL_OUT
:
2537 case Definition::A_PAR_VAL_INOUT
:
2538 case Definition::A_PAR_TEMPL_OUT
:
2539 case Definition::A_PAR_TEMPL_INOUT
:
2540 // valid assignment types
2543 str2ttcn
.ref
->error("Reference to '%s' cannot be used as the second parameter", refd_ass
->get_assname());
2548 delete str2ttcn
.val
;
2549 delete str2ttcn
.ref
;
2550 statementtype
= S_ERROR
;
2553 void Statement::chk_allowed_interleave()
2555 switch (statementtype
) {
2557 block
->chk_allowed_interleave();
2560 error("Label statement is not allowed within an interleave statement");
2563 error("Goto statement is not allowed within an interleave statement");
2566 if_stmt
.ics
->chk_allowed_interleave();
2567 if (if_stmt
.elseblock
) if_stmt
.elseblock
->chk_allowed_interleave();
2570 select
.scs
->chk_allowed_interleave();
2575 loop
.block
->chk_allowed_interleave();
2578 ags
->chk_allowed_interleave();
2581 error("Repeat statement is not allowed within an interleave statement");
2583 case S_ALTSTEP_INSTANCE
:
2584 error("Invocation of an altstep is not allowed within an interleave "
2587 case S_ALTSTEP_INVOKED
:
2588 error("Invocation of an altstep type is not allowed within an interleave"
2592 error("Return statement is not allowed within an interleave statement");
2595 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->chk_allowed_interleave();
2598 // the other statements are allowed
2603 void Statement::chk_start_undef()
2605 Ref_base
*t_ref
= undefstartstop
.ref
;
2606 Value
*t_val
= undefstartstop
.val
;
2607 Common::Assignment
*t_ass
;
2609 Error_Context
cntxt(this, "In start statement");
2610 t_ass
= t_ref
->get_refd_assignment();
2612 if (!t_ass
) goto error
;
2613 switch (t_ass
->get_asstype()) {
2614 case Definition::A_PORT
:
2615 case Definition::A_PAR_PORT
:
2616 statementtype
= S_START_PORT
;
2617 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2618 if (!port_op
.portref
) goto error
;
2620 t_val
->error("Start port operation cannot have argument");
2623 chk_start_stop_port();
2625 case Definition::A_TIMER
:
2626 case Definition::A_PAR_TIMER
:
2627 statementtype
= S_START_TIMER
;
2628 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2629 if (!timer_op
.timerref
) goto error
;
2630 timer_op
.value
= t_val
;
2633 case Definition::A_CONST
:
2634 case Definition::A_EXT_CONST
:
2635 case Definition::A_MODULEPAR
:
2636 case Definition::A_VAR
:
2637 case Definition::A_FUNCTION_RVAL
:
2638 case Definition::A_EXT_FUNCTION_RVAL
:
2639 case Definition::A_PAR_VAL_IN
:
2640 case Definition::A_PAR_VAL_OUT
:
2641 case Definition::A_PAR_VAL_INOUT
:
2642 statementtype
= S_START_COMP
;
2644 error("The argument of start operation is missing, although it cannot "
2645 "be a start timer or start port operation");
2647 } else if (t_val
->get_valuetype() != Value::V_REFD
) {
2648 t_val
->error("The argument of start operation is not a function, "
2649 "although it cannot be a start timer or start port operation");
2652 comp_op
.funcinstref
= t_val
->steal_ttcn_ref_base();
2655 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2656 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2657 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2658 comp_op
.compref
->set_location(*t_ref
);
2662 t_ref
->error("Port, timer or component reference was expected as the "
2663 "operand of start operation instead of %s",
2664 t_ass
->get_description().c_str());
2671 statementtype
= S_ERROR
;
2674 void Statement::chk_stop_undef()
2676 Ref_base
*t_ref
= undefstartstop
.ref
;
2677 Common::Assignment
*t_ass
;
2679 Error_Context
cntxt(this, "In stop statement");
2680 t_ass
= t_ref
->get_refd_assignment();
2682 if (!t_ass
) goto error
;
2683 // Determine what it is that we are trying to stop; change statementtype
2684 switch (t_ass
->get_asstype()) {
2685 case Definition::A_PORT
:
2686 case Definition::A_PAR_PORT
:
2687 statementtype
= S_STOP_PORT
;
2688 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2689 if (!port_op
.portref
) goto error
;
2690 chk_start_stop_port();
2692 case Definition::A_TIMER
:
2693 case Definition::A_PAR_TIMER
:
2694 statementtype
= S_STOP_TIMER
;
2695 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2696 if (!timer_op
.timerref
) goto error
;
2698 chk_stop_timer_timeout();
2700 case Definition::A_CONST
:
2701 case Definition::A_EXT_CONST
:
2702 case Definition::A_MODULEPAR
:
2703 case Definition::A_VAR
:
2704 case Definition::A_FUNCTION_RVAL
:
2705 case Definition::A_EXT_FUNCTION_RVAL
:
2706 case Definition::A_PAR_VAL_IN
:
2707 case Definition::A_PAR_VAL_OUT
:
2708 case Definition::A_PAR_VAL_INOUT
:
2709 statementtype
= S_STOP_COMP
;
2710 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2711 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2712 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2713 comp_op
.compref
->set_location(*t_ref
);
2714 chk_stop_kill_comp();
2717 t_ref
->error("Port, timer or component reference was expected as the "
2718 "operand of stop operation instead of %s",
2719 t_ass
->get_description().c_str());
2725 statementtype
= S_ERROR
;
2728 void Statement::chk_unknown_instance()
2730 Common::Assignment
*t_ass
;
2732 Error_Context
cntxt(this, "In function or altstep instance");
2733 t_ass
= ref_pard
->get_refd_assignment(false);
2735 if (!t_ass
) goto error
;
2736 switch (t_ass
->get_asstype()) {
2737 case Common::Assignment::A_FUNCTION
:
2738 case Common::Assignment::A_FUNCTION_RVAL
:
2739 case Common::Assignment::A_FUNCTION_RTEMP
:
2740 case Common::Assignment::A_EXT_FUNCTION
:
2741 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2742 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2743 statementtype
= S_FUNCTION_INSTANCE
;
2746 case Common::Assignment::A_ALTSTEP
:
2747 statementtype
= S_ALTSTEP_INSTANCE
;
2751 ref_pard
->error("Reference to a function or altstep was expected "
2752 "instead of %s, which cannot be invoked",
2753 t_ass
->get_description().c_str());
2759 statementtype
= S_ERROR
;
2762 void Statement::chk_unknown_invoke()
2764 Error_Context
cntxt(this, "In apply operation");
2765 Type
*t
= fau_refd
.value
->get_expr_governor_last();
2767 switch (t
->get_typetype()) {
2770 case Type::T_FUNCTION
:
2771 statementtype
= S_FUNCTION_INVOKED
;
2772 if (t
->get_function_return_type()) warning("The value returned by "
2773 "function type `%s' is not used", t
->get_typename().c_str());
2775 case Type::T_ALTSTEP
:
2776 statementtype
= S_ALTSTEP_INVOKED
;
2779 fau_refd
.value
->error("A value of type function or altstep was "
2780 "expected instead of `%s'", t
->get_typename().c_str());
2783 my_sb
->chk_runs_on_clause(t
, *this, "call");
2785 ActualParList
*parlist
= new Ttcn::ActualParList
;
2786 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
2787 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
2789 delete fau_refd
.t_list1
;
2792 fau_refd
.ap_list2
= 0;
2794 parlist
->set_fullname(get_fullname());
2795 parlist
->set_my_scope(my_sb
);
2796 fau_refd
.ap_list2
= parlist
;
2802 statementtype
= S_ERROR
;
2805 void Statement::chk_assignment()
2807 Error_Context
cntxt(this, "In variable assignment");
2811 void Statement::chk_function()
2813 Error_Context
cntxt(this, "In function instance");
2814 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
2815 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
2816 if (t_ass
->get_Type())
2817 ref_pard
->warning("The value returned by %s is not used",
2818 t_ass
->get_description().c_str());
2821 void Statement::chk_block()
2823 Error_Context
cntxt(this, "In statement block");
2827 void Statement::chk_log_action(LogArguments
*lga
)
2829 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
2832 if (!semantic_check_only
) lga
->join_strings();
2836 void Statement::chk_goto()
2838 Error_Context
cntxt(this, "In goto statement");
2839 if (!my_sb
->has_label(*go_to
.id
)) {
2840 error("Label `%s' is used, but not defined",
2841 go_to
.id
->get_dispname().c_str());
2843 go_to
.jumps_forward
= false;
2846 Statement
*label_stmt
= my_sb
->get_label(*go_to
.id
);
2847 label_stmt
->label
.used
= true;
2848 StatementBlock
*label_sb
= label_stmt
->get_my_sb();
2849 // the index of the label in its own statement block
2850 size_t label_idx
= label_stmt
->get_my_sb_index();
2851 // the index of the goto statement (or its parent statement) in the
2852 // statement block of the label
2854 if (my_sb
== label_sb
) goto_idx
= go_to
.stmt_idx
;
2856 // the goto statement is within a nested statement block
2857 StatementBlock
*goto_sb
= my_sb
, *parent_sb
= my_sb
->get_my_sb();
2858 while (parent_sb
!= label_sb
) {
2859 // go up until the block of the label is found
2860 if (!parent_sb
) FATAL_ERROR("Statement::chk_goto()");
2861 goto_sb
= parent_sb
;
2862 parent_sb
= parent_sb
->get_my_sb();
2864 goto_idx
= goto_sb
->get_my_sb_index();
2866 if (label_idx
> goto_idx
) {
2867 bool error_flag
= false;
2868 for (size_t i
= goto_idx
+ 1; i
< label_idx
; i
++) {
2869 Statement
*stmt
= label_sb
->get_stmt_byIndex(i
);
2870 if (stmt
->get_statementtype() != S_DEF
) continue;
2872 error("Jump to label `%s' crosses local definition",
2873 go_to
.id
->get_dispname().c_str());
2876 stmt
->note("Definition of %s is here",
2877 stmt
->get_def()->get_description().c_str());
2880 label_stmt
->note("Label `%s' is here",
2881 go_to
.id
->get_dispname().c_str());
2882 go_to
.jumps_forward
= true;
2883 } else go_to
.jumps_forward
= false;
2884 go_to
.label
= label_stmt
;
2887 void Statement::chk_if()
2890 if_stmt
.ics
->chk(unreach
);
2891 if(if_stmt
.elseblock
) {
2892 Error_Context
cntxt(if_stmt
.elseblock_location
, "In else statement");
2893 if(unreach
) if_stmt
.elseblock_location
->warning
2894 ("Control never reaches this code because of previous effective"
2896 if_stmt
.elseblock
->chk();
2901 void Statement::chk_select()
2903 Error_Context
cntxt(this, "In select case statement");
2905 for(int turn
=0; turn
<2; turn
++) {
2906 if(turn
) select
.expr
->set_lowerid_to_ref();
2907 Type::typetype_t tt
=select
.expr
->get_expr_returntype();
2908 t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2909 if(!t_gov
|| tt
==Type::T_ERROR
) {
2910 SelectCases
*scs
=select
.scs
;
2911 for(size_t i
=0; i
<scs
->get_nof_scs(); i
++) {
2912 TemplateInstances
*tis
=scs
->get_sc_byIndex(i
)->get_tis();
2914 for(size_t j
=0; j
<tis
->get_nof_tis(); j
++) {
2915 TemplateInstance
*ti
=tis
->get_ti_byIndex(j
);
2916 if(turn
) ti
->get_Template()->set_lowerid_to_ref();
2917 t_gov
=ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
2918 tt
=ti
->get_expr_returntype(Type::EXPECTED_TEMPLATE
);
2919 if(t_gov
&& tt
!=Type::T_ERROR
) break;
2924 else t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2927 select
.expr
->error("Cannot determine the type of the expression");
2928 t_gov
=Type::get_pooltype(Type::T_ERROR
);
2930 select
.expr
->set_my_governor(t_gov
);
2931 t_gov
->chk_this_value_ref(select
.expr
);
2932 t_gov
->chk_this_value(select
.expr
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
2933 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2934 select
.scs
->chk(t_gov
);
2937 void Statement::chk_for()
2939 Error_Context
cntxt(this, "In for statement");
2940 if (loop
.for_stmt
.varinst
) loop
.for_stmt
.init_varinst
->chk_for();
2941 else loop
.for_stmt
.init_ass
->chk();
2942 loop
.for_stmt
.finalexpr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2943 if(!loop
.for_stmt
.finalexpr
->is_unfoldable()
2944 && !loop
.for_stmt
.finalexpr
->get_val_bool())
2945 loop
.for_stmt
.finalexpr
->warning
2946 ("Control never reaches this code because the"
2947 " final conditional expression evals to false");
2948 loop
.for_stmt
.step
->chk();
2949 loop
.block
->set_my_laic_stmt(0, this);
2953 void Statement::chk_while()
2955 Error_Context
cntxt(this, "In while statement");
2956 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2957 if(!loop
.expr
->is_unfoldable() && !loop
.expr
->get_val_bool())
2958 loop
.expr
->warning("Control never reaches this code because the"
2959 " conditional expression evals to false");
2960 loop
.block
->set_my_laic_stmt(0, this);
2964 void Statement::chk_do_while()
2966 Error_Context
cntxt(this, "In do-while statement");
2967 loop
.block
->set_my_laic_stmt(0, this);
2969 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2972 void Statement::chk_break()
2974 Error_Context
cntxt(this, "In break statement");
2975 if (!brk_cnt
.loop_stmt
&& !brk_cnt
.ags
)
2976 error("Break statement cannot be used outside loops, alt or interleave"
2977 " statements, altsteps or response and exception handling part of call"
2979 if (brk_cnt
.loop_stmt
)
2980 brk_cnt
.loop_stmt
->loop
.has_brk
=true;
2983 void Statement::chk_continue()
2985 Error_Context
cntxt(this, "In continue statement");
2986 if (brk_cnt
.loop_stmt
) {
2987 brk_cnt
.loop_stmt
->loop
.has_cnt
=true;
2988 if (brk_cnt
.ags
) brk_cnt
.loop_stmt
->loop
.has_cnt_in_ags
=true;
2990 error("Continue statement cannot be used outside loops");
2993 void Statement::chk_alt()
2995 Error_Context
cntxt(this, "In alt construct");
2996 ags
->set_my_ags(ags
);
2997 ags
->set_my_laic_stmt(ags
, 0);
3001 void Statement::chk_repeat()
3003 Error_Context
cntxt(this, "In repeat statement");
3004 if (ags
) ags
->repeat_found();
3005 else error("Repeat statement cannot be used outside alt statements, "
3006 "altsteps or response and exception handling part of call operations");
3009 void Statement::chk_interleave()
3011 Error_Context
cntxt(this, "In interleave statement");
3012 ags
->set_my_laic_stmt(ags
, 0);
3014 ags
->chk_allowed_interleave();
3017 void Statement::chk_altstep()
3019 Error_Context
cntxt(this, "In altstep instance");
3020 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
3021 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
3024 void Statement::chk_return()
3026 Error_Context
cntxt(this, "In return statement");
3027 Definition
*my_def
= my_sb
->get_my_def();
3029 error("Return statement cannot be used in the control part. "
3030 "It is allowed only in functions and altsteps");
3033 switch (my_def
->get_asstype()) {
3034 case Definition::A_FUNCTION
:
3036 returnexpr
.t
->error("Unexpected return value. The function does not "
3037 "have return type");
3041 case Definition::A_FUNCTION_RVAL
:
3042 if (!returnexpr
.t
) {
3043 error("Missing return value. The function should return a value of "
3044 "type `%s'", my_def
->get_Type()->get_typename().c_str());
3046 } else if (!returnexpr
.t
->is_Value()) {
3047 returnexpr
.t
->error("A specific value without matching symbols was "
3048 "expected as return value");
3051 returnexpr
.v
= returnexpr
.t
->get_Value();
3052 delete returnexpr
.t
;
3054 Type
*return_type
= my_def
->get_Type();
3055 returnexpr
.v
->set_my_governor(return_type
);
3056 return_type
->chk_this_value_ref(returnexpr
.v
);
3057 return_type
->chk_this_value(returnexpr
.v
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
3058 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
3061 case Definition::A_FUNCTION_RTEMP
:
3062 if (!returnexpr
.t
) {
3063 error("Missing return template. The function should return a template "
3064 "of type `%s'", my_def
->get_Type()->get_typename().c_str());
3067 Type
*return_type
= my_def
->get_Type();
3068 returnexpr
.t
->set_my_governor(return_type
);
3069 return_type
->chk_this_template_ref(returnexpr
.t
);
3070 return_type
->chk_this_template_generic(returnexpr
.t
, INCOMPLETE_NOT_ALLOWED
,
3071 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
3072 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
3073 if (!dfb
) FATAL_ERROR("Statement::chk_return()");
3074 returnexpr
.gen_restriction_check
=
3075 returnexpr
.t
->chk_restriction("return template",
3076 dfb
->get_template_restriction());
3079 case Definition::A_ALTSTEP
:
3081 returnexpr
.t
->error("An altstep cannot return a value");
3086 error("Return statement cannot be used in a %s. It is allowed only in "
3087 "functions and altsteps", my_def
->get_assname());
3092 delete returnexpr
.t
;
3096 void Statement::chk_activate()
3098 Error_Context
cntxt(this, "In activate statement");
3099 if (!ref_pard
->chk_activate_argument()) {
3101 statementtype
= S_ERROR
;
3105 void Statement::chk_activate_refd()
3107 Error_Context
cntxt(this, "In activate statement");
3108 Type
*t
= fau_refd
.value
->get_expr_governor_last();
3110 switch (t
->get_typetype()) {
3113 case Type::T_ALTSTEP
:
3116 fau_refd
.value
->error("A value of type altstep was expected in the "
3117 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
3120 if (t
->get_fat_runs_on_self()) {
3121 fau_refd
.value
->error("The argument of `derefers()' cannot be an altstep "
3122 "reference with 'runs on self' clause");
3125 my_sb
->chk_runs_on_clause(t
, *this, "activate");
3127 ActualParList
*parlist
= new ActualParList
;
3128 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
3129 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
3131 delete fau_refd
.t_list1
;
3134 fau_refd
.ap_list2
= 0;
3137 parlist
->set_fullname(get_fullname());
3138 parlist
->set_my_scope(my_sb
);
3139 fau_refd
.ap_list2
= parlist
;
3140 if (!fp_list
->chk_activate_argument(parlist
,get_fullname().c_str()))
3147 statementtype
= S_ERROR
;
3150 void Statement::chk_deactivate()
3153 Error_Context
cntxt(this, "In deactivate statement");
3154 deactivate
->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE
);
3158 void Statement::chk_send()
3160 Error_Context
cntxt(this, "In send statement");
3161 // checking the port reference
3162 Type
*port_type
= chk_port_ref(port_op
.portref
);
3163 // determining the message type
3165 bool msg_type_determined
= false;
3167 Ttcn::PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3168 TypeSet
*out_msgs
= port_type_body
->get_out_msgs();
3170 if (out_msgs
->get_nof_types() == 1) {
3171 // there is only one outgoing message type
3172 msg_type
= out_msgs
->get_type_byIndex(0);
3174 // there are more than one outgoing message types
3175 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3177 size_t nof_comp_types
=
3178 out_msgs
->get_nof_compatible_types(msg_type
);
3179 if (nof_comp_types
== 0) {
3180 port_op
.s
.sendpar
->error("Message type `%s' is not present on "
3181 "the outgoing list of port type `%s'",
3182 msg_type
->get_typename().c_str(),
3183 port_type
->get_typename().c_str());
3184 } else if (nof_comp_types
> 1) {
3185 port_op
.s
.sendpar
->error("Type of the message is ambiguous: "
3186 "`%s' is compatible with more than one outgoing message types "
3187 "of port type `%s'", msg_type
->get_typename().c_str(),
3188 port_type
->get_typename().c_str());
3191 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3192 "outgoing message");
3195 msg_type_determined
= true;
3196 } else if (port_type_body
->get_operation_mode() ==
3197 PortTypeBody::PO_PROCEDURE
) {
3198 port_op
.portref
->error("Message-based operation `send' is not "
3199 "applicable to a procedure-based port of type `%s'",
3200 port_type
->get_typename().c_str());
3202 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3203 "message types", port_type
->get_typename().c_str());
3206 // determining the message type if it is not done so far
3207 if (!msg_type_determined
) {
3208 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3210 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3211 // checking the parameter (template instance)
3212 port_op
.s
.sendpar
->chk(msg_type
);
3213 // checking for invalid message types
3214 msg_type
= msg_type
->get_type_refd_last();
3215 switch (msg_type
->get_typetype()) {
3216 case Type::T_SIGNATURE
:
3217 port_op
.s
.sendpar
->error("The type of send parameter is signature `%s', "
3218 "which cannot be a message type", msg_type
->get_typename().c_str());
3221 port_op
.s
.sendpar
->error("The type of send parameter is port type `%s', "
3222 "which cannot be a message type", msg_type
->get_typename().c_str());
3224 case Type::T_DEFAULT
:
3225 port_op
.s
.sendpar
->error("The type of send parameter is the `default' "
3226 "type, which cannot be a message type");
3230 // checking for presence of wildcards in the template body
3231 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3232 // checking to clause
3233 chk_to_clause(port_type
);
3236 void Statement::chk_call()
3238 Error_Context
cntxt(this, "In call statement");
3239 // checking the port reference
3240 Type
*port_type
= chk_port_ref(port_op
.portref
);
3241 // determining the signature of the argument
3242 Type
*signature
= 0;
3243 bool signature_determined
= false;
3245 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3246 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3248 if (out_sigs
->get_nof_types() == 1) {
3249 // there is only one outgoing signature
3250 signature
= out_sigs
->get_type_byIndex(0);
3252 // there are more than one outgoing signatures
3253 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3255 if (!out_sigs
->has_type(signature
)) {
3256 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3257 "outgoing list of port type `%s'",
3258 signature
->get_typename().c_str(),
3259 port_type
->get_typename().c_str());
3262 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3266 signature_determined
= true;
3267 } else if (port_type_body
->get_operation_mode() ==
3268 PortTypeBody::PO_MESSAGE
) {
3269 port_op
.portref
->error("Procedure-based operation `call' is not "
3270 "applicable to a message-based port of type `%s'",
3271 port_type
->get_typename().c_str());
3273 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3274 "signatures", port_type
->get_typename().c_str());
3277 if (!signature_determined
)
3278 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3279 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3280 // checking the parameter (template instance)
3281 port_op
.s
.sendpar
->chk(signature
);
3282 signature
= signature
->get_type_refd_last();
3283 bool is_noblock_sig
= false;
3284 Type::typetype_t tt
= signature
->get_typetype();
3286 case Type::T_SIGNATURE
:
3287 // the signature is known and correct
3288 is_noblock_sig
= signature
->is_nonblocking_signature();
3292 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not "
3293 "a signature", signature
->get_typename().c_str());
3295 // checking presence/absence of optional parts
3296 if (is_noblock_sig
) {
3297 if (port_op
.s
.call
.timer
) {
3298 port_op
.s
.call
.timer
->error("A call of non-blocking signature `%s' "
3299 "cannot have call timer", signature
->get_typename().c_str());
3300 } else if (port_op
.s
.call
.nowait
) {
3301 error("A call of non-blocking signature `%s' cannot use the "
3302 "`nowait' keyword", signature
->get_typename().c_str());
3304 if (port_op
.s
.call
.body
) {
3305 error("A call of non-blocking signature `%s' cannot have "
3306 "response and exception handling part",
3307 signature
->get_typename().c_str());
3309 } else if (port_op
.s
.call
.nowait
) {
3310 if (port_op
.s
.call
.body
) {
3311 error("A call with `nowait' keyword cannot have response and "
3312 "exception handling part");
3315 // do not issue any error if the signature is erroneous
3316 // because it could have been a non-blocking one
3317 if (tt
== Type::T_SIGNATURE
&& !port_op
.s
.call
.body
) {
3318 error("Response and exception handling part is missing from "
3319 "blocking call operation");
3322 // checking call timer
3323 if (port_op
.s
.call
.timer
) {
3324 Error_Context
cntxt2(port_op
.s
.call
.timer
, "In call timer value");
3325 port_op
.s
.call
.timer
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
3326 Value
*t_val
= port_op
.s
.call
.timer
->get_value_refd_last();
3327 if (t_val
->get_valuetype() == Value::V_REAL
) {
3328 ttcn3float v_real
= t_val
->get_val_Real();
3330 port_op
.s
.call
.timer
->error("The call timer has "
3331 "negative duration: `%s'", Real2string(v_real
).c_str());
3332 } else if (isSpecialFloatValue(v_real
)) {
3333 port_op
.s
.call
.timer
->error("The call timer duration cannot be %s",
3334 Real2string(v_real
).c_str());
3338 // checking to clause
3339 chk_to_clause(port_type
);
3340 // checking response and exception handling part
3341 if (port_op
.s
.call
.body
) chk_call_body(port_type
, signature
);
3344 void Statement::chk_reply()
3346 Error_Context
cntxt(this, "In reply statement");
3347 // checking the port reference
3348 Type
*port_type
= chk_port_ref(port_op
.portref
);
3349 // determining the signature of the argument
3350 Type
*signature
= 0;
3351 bool signature_determined
= false;
3353 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3354 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3356 if (in_sigs
->get_nof_types() == 1) {
3357 // there is only one incoming signature
3358 signature
= in_sigs
->get_type_byIndex(0);
3360 // there are more than one incoming signatures
3361 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3363 if (!in_sigs
->has_type(signature
)) {
3364 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3365 "incoming list of port type `%s'",
3366 signature
->get_typename().c_str(),
3367 port_type
->get_typename().c_str());
3370 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3374 signature_determined
= true;
3375 } else if (port_type_body
->get_operation_mode() ==
3376 PortTypeBody::PO_MESSAGE
) {
3377 port_op
.portref
->error("Procedure-based operation `reply' is not "
3378 "applicable to a message-based port of type `%s'",
3379 port_type
->get_typename().c_str());
3381 port_op
.portref
->error("Port type `%s' does not have any incoming "
3382 "signatures", port_type
->get_typename().c_str());
3385 if (!signature_determined
)
3386 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3387 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3388 // checking the parameter (template instance)
3389 port_op
.s
.sendpar
->chk(signature
);
3390 signature
= signature
->get_type_refd_last();
3391 Type
*return_type
= 0;
3392 switch (signature
->get_typetype()) {
3393 case Type::T_SIGNATURE
:
3394 // the signature is known and correct
3395 if (signature
->is_nonblocking_signature())
3396 error("Operation `reply' is not applicable to non-blocking signature "
3397 "`%s'", signature
->get_typename().c_str());
3398 else return_type
= signature
->get_signature_return_type();
3399 // checking the presence/absence of reply value
3400 if (port_op
.s
.replyval
) {
3402 port_op
.s
.replyval
->error("Unexpected return value. Signature "
3403 "`%s' does not have return type",
3404 signature
->get_typename().c_str());
3406 } else if (return_type
) {
3407 error("Missing return value. Signature `%s' returns type `%s'",
3408 signature
->get_typename().c_str(),
3409 return_type
->get_typename().c_str());
3414 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not a "
3415 "signature", signature
->get_typename().c_str());
3417 // checking the reply value if present
3418 if (port_op
.s
.replyval
) {
3419 Error_Context
cntxt2(port_op
.s
.replyval
, "In return value");
3420 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3421 port_op
.s
.replyval
->set_my_governor(return_type
);
3422 return_type
->chk_this_value_ref(port_op
.s
.replyval
);
3423 return_type
->chk_this_value(port_op
.s
.replyval
, 0,
3424 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
3427 // checking to clause
3428 chk_to_clause(port_type
);
3431 void Statement::chk_raise()
3433 Error_Context
cntxt(this, "In raise statement");
3434 // checking the port reference
3435 Type
*port_type
= chk_port_ref(port_op
.portref
);
3436 // determining the signature of the exception
3437 port_op
.s
.raise
.signature
=
3438 chk_signature_ref(port_op
.s
.raise
.signature_ref
);
3439 // checking whether the signature is present on the incoming list
3440 // of the respective port type
3442 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3443 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3444 if (port_type_body
->get_operation_mode() ==
3445 PortTypeBody::PO_MESSAGE
) {
3446 port_op
.portref
->error("Procedure-based operation `raise' is not "
3447 "applicable to a message-based port of type `%s'",
3448 port_type
->get_typename().c_str());
3449 } else if (in_sigs
) {
3450 if (port_op
.s
.raise
.signature
) {
3451 if (!in_sigs
->has_type(port_op
.s
.raise
.signature
)) {
3452 port_op
.s
.raise
.signature_ref
->error("Signature `%s' is not "
3453 "present on the incoming list of port type `%s'",
3454 port_op
.s
.raise
.signature
->get_typename().c_str(),
3455 port_type
->get_typename().c_str());
3457 } else if (in_sigs
->get_nof_types() == 1) {
3458 // if the signature is unknown and the port type has exactly one
3459 // incoming signature then use that for further checking
3460 port_op
.s
.raise
.signature
=
3461 in_sigs
->get_type_byIndex(0)->get_type_refd_last();
3464 port_op
.portref
->error("Port type `%s' does not have any incoming "
3465 "signatures", port_type
->get_typename().c_str());
3468 // determining the type of exception
3470 bool exc_type_determined
= false;
3471 if (port_op
.s
.raise
.signature
) {
3472 // the signature is known
3473 SignatureExceptions
*exceptions
=
3474 port_op
.s
.raise
.signature
->get_signature_exceptions();
3476 if (exceptions
->get_nof_types() == 1) {
3477 // the signature has exactly one exception type
3478 // use that for checking
3479 exc_type
= exceptions
->get_type_byIndex(0);
3481 // the signature has more than one exception types
3482 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3484 size_t nof_comp_types
=
3485 exceptions
->get_nof_compatible_types(exc_type
);
3486 if (nof_comp_types
== 0) {
3487 port_op
.s
.sendpar
->error("Type `%s' is not present on the "
3488 "exception list of signature `%s'",
3489 exc_type
->get_typename().c_str(),
3490 port_op
.s
.raise
.signature
->get_typename().c_str());
3491 } else if (nof_comp_types
> 1) {
3492 port_op
.s
.sendpar
->error("Type of the exception is ambiguous: "
3493 "`%s' is compatible with more than one exception types of "
3494 "signature `%s'", exc_type
->get_typename().c_str(),
3495 port_op
.s
.raise
.signature
->get_typename().c_str());
3498 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3502 exc_type_determined
= true;
3504 port_op
.s
.raise
.signature_ref
->error("Signature `%s' does not have "
3505 "exceptions", port_op
.s
.raise
.signature
->get_typename().c_str());
3508 // determining the type of exception if it is not done so far
3509 if (!exc_type_determined
) {
3510 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3512 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3513 // checking the exception template
3514 port_op
.s
.sendpar
->chk(exc_type
);
3515 // checking for invalid exception types
3516 exc_type
= exc_type
->get_type_refd_last();
3517 switch (exc_type
->get_typetype()) {
3518 case Type::T_SIGNATURE
:
3519 port_op
.s
.sendpar
->error("The type of raise parameter is signature `%s', "
3520 "which cannot be an exception type",
3521 exc_type
->get_typename().c_str());
3524 port_op
.s
.sendpar
->error("The type of raise parameter is port type `%s', "
3525 "which cannot be an exception type",
3526 exc_type
->get_typename().c_str());
3528 case Type::T_DEFAULT
:
3529 port_op
.s
.sendpar
->error("The type of raise parameter is the `default' "
3530 "type, which cannot be an exception type");
3534 // checking for presence of wildcards in the template body
3535 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3536 // checking to clause
3537 chk_to_clause(port_type
);
3540 void Statement::chk_receive()
3542 // determining statement type
3543 const char *stmt_name
= get_stmt_name();
3544 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3545 // checking the port reference
3546 Type
*port_type
= chk_port_ref(port_op
.portref
);
3547 // checking the parameter and/or value redirect
3548 if (port_op
.r
.rcvpar
) {
3549 // the receive parameter (template instance) is present
3550 // trying to determine type of the incoming message
3552 bool msg_type_determined
= false, value_redirect_checked
= false;
3554 // the port reference is correct and the port type is known
3555 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3556 TypeSet
*in_msgs
= port_type_body
->get_in_msgs();
3558 if (in_msgs
->get_nof_types() == 1) {
3559 // there is only one incoming message type
3560 // use that for checking
3561 msg_type
= in_msgs
->get_type_byIndex(0);
3563 // there are more than one incoming message types
3564 msg_type
= get_incoming_type(port_op
.r
.rcvpar
,
3565 port_op
.r
.redirect
.value
, value_redirect_checked
);
3567 size_t nof_comp_types
=
3568 in_msgs
->get_nof_compatible_types(msg_type
);
3569 if (nof_comp_types
== 0) {
3570 port_op
.r
.rcvpar
->error("Message type `%s' is not present on "
3571 "the incoming list of port of type `%s'",
3572 msg_type
->get_typename().c_str(),
3573 port_type
->get_typename().c_str());
3574 } else if (nof_comp_types
> 1) {
3575 port_op
.r
.rcvpar
->error("Type of the message is ambiguous: "
3576 "`%s' is compatible with more than one incoming message "
3577 "types of port type `%s'", msg_type
->get_typename().c_str(),
3578 port_type
->get_typename().c_str());
3581 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3582 "incoming message");
3585 msg_type_determined
= true;
3586 } else if (port_type_body
->get_operation_mode() ==
3587 PortTypeBody::PO_PROCEDURE
) {
3588 port_op
.portref
->error("Message-based operation `%s' is not "
3589 "applicable to a procedure-based port of type `%s'", stmt_name
,
3590 port_type
->get_typename().c_str());
3592 port_op
.portref
->error("Port type `%s' does not have any incoming "
3593 "message types", port_type
->get_typename().c_str());
3595 } else if (!port_op
.portref
) {
3596 // the statement refers to 'any port'
3597 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3599 if (port_op
.r
.redirect
.value
) {
3600 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3601 "value redirect", stmt_name
);
3604 if (!msg_type_determined
) {
3605 msg_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3606 value_redirect_checked
);
3608 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3609 // check the template instance using the message type
3610 port_op
.r
.rcvpar
->chk(msg_type
);
3611 // check the value redirect if it is not done so far
3612 if (!value_redirect_checked
)
3613 chk_value_redirect(port_op
.r
.redirect
.value
, msg_type
);
3615 // the statement does not have parameter
3617 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3618 if (!port_type_body
->get_in_msgs()) {
3619 // the port type is known and it does not have incoming messages
3620 if (port_type_body
->get_operation_mode() ==
3621 PortTypeBody::PO_PROCEDURE
) {
3622 port_op
.portref
->error("Message-based operation `%s' is not "
3623 "applicable to a procedure-based port of type `%s'", stmt_name
,
3624 port_type
->get_typename().c_str());
3626 port_op
.portref
->error("Port type `%s' does not have any incoming "
3627 "message types", port_type
->get_typename().c_str());
3631 if (port_op
.r
.redirect
.value
) {
3632 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
3633 "receive parameter");
3634 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3637 // checking from clause and sender redirect
3638 chk_from_clause(port_type
);
3641 void Statement::chk_getcall()
3643 // determining statement type
3644 const char *stmt_name
= get_stmt_name();
3645 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3646 // checking the port reference
3647 Type
*port_type
= chk_port_ref(port_op
.portref
);
3648 if (port_op
.r
.rcvpar
) {
3649 // the parameter (signature template) is present
3650 // determining the signature of the argument
3651 Type
*signature
= 0;
3652 bool signature_determined
= false;
3654 // the port reference is correct and the port type is known
3655 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3656 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3658 if (in_sigs
->get_nof_types() == 1) {
3659 // there is only one incoming signature
3660 signature
= in_sigs
->get_type_byIndex(0);
3662 // there are more than one incoming signatures
3663 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3665 if (!in_sigs
->has_type(signature
)) {
3666 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3667 "incoming list of port type `%s'",
3668 signature
->get_typename().c_str(),
3669 port_type
->get_typename().c_str());
3672 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3676 signature_determined
= true;
3677 } else if (port_type_body
->get_operation_mode() ==
3678 PortTypeBody::PO_MESSAGE
) {
3679 port_op
.portref
->error("Procedure-based operation `%s' is not "
3680 "applicable to a message-based port of type `%s'", stmt_name
,
3681 port_type
->get_typename().c_str());
3683 port_op
.portref
->error("Port type `%s' does not have any incoming "
3684 "signatures", port_type
->get_typename().c_str());
3686 } else if (!port_op
.portref
) {
3687 // the statement refers to 'any port'
3688 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3690 if (port_op
.r
.redirect
.param
) {
3691 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3692 "have parameter redirect", stmt_name
);
3695 if (!signature_determined
)
3696 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3697 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3698 // checking the parameter (template instance)
3699 port_op
.r
.rcvpar
->chk(signature
);
3700 // checking whether the argument is a signature template
3701 // and checking the parameter redirect if present
3702 signature
= signature
->get_type_refd_last();
3703 switch (signature
->get_typetype()) {
3704 case Type::T_SIGNATURE
:
3705 if (port_op
.r
.redirect
.param
)
3706 port_op
.r
.redirect
.param
->chk(signature
, false);
3709 if (port_op
.r
.redirect
.param
)
3710 port_op
.r
.redirect
.param
->chk_erroneous();
3713 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3714 "a signature", signature
->get_typename().c_str());
3715 if (port_op
.r
.redirect
.param
)
3716 port_op
.r
.redirect
.param
->chk_erroneous();
3719 // the statement does not have parameter
3721 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3722 if (!port_type_body
->get_in_sigs()) {
3723 // the port type is known and it does not have incoming signatures
3724 if (port_type_body
->get_operation_mode() ==
3725 PortTypeBody::PO_MESSAGE
) {
3726 port_op
.portref
->error("Procedure-based operation `%s' is not "
3727 "applicable to a message-based port of type `%s'", stmt_name
,
3728 port_type
->get_typename().c_str());
3730 port_op
.portref
->error("Port type `%s' does not have any incoming "
3731 "signatures", port_type
->get_typename().c_str());
3735 if (port_op
.r
.redirect
.param
) {
3736 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3737 "without signature template");
3738 port_op
.r
.redirect
.param
->chk_erroneous();
3741 // checking from clause and sender redirect
3742 chk_from_clause(port_type
);
3745 void Statement::chk_getreply()
3747 // determining statement type
3748 const char *stmt_name
= get_stmt_name();
3749 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3750 // checking the port reference
3751 Type
*port_type
= chk_port_ref(port_op
.portref
);
3752 if (port_op
.r
.rcvpar
) {
3753 // the parameter (signature template) is present
3754 // determining the signature of the argument
3755 Type
*signature
= 0;
3756 bool signature_determined
= false;
3758 // the port reference is correct and the port type is known
3759 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3760 if (port_type_body
->getreply_allowed()) {
3761 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3762 if (out_sigs
->get_nof_types() == 1) {
3763 // there is only one outgoing signature
3764 signature
= out_sigs
->get_type_byIndex(0);
3766 // there are more than one outgoing signatures
3767 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3769 if (!out_sigs
->has_type(signature
)) {
3770 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3771 "outgoing list of port type `%s'",
3772 signature
->get_typename().c_str(),
3773 port_type
->get_typename().c_str());
3776 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3780 signature_determined
= true;
3781 } else if (port_type_body
->get_operation_mode() ==
3782 PortTypeBody::PO_MESSAGE
) {
3783 port_op
.portref
->error("Procedure-based operation `%s' is not "
3784 "applicable to a message-based port of type `%s'", stmt_name
,
3785 port_type
->get_typename().c_str());
3787 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3788 "signatures that support reply", port_type
->get_typename().c_str());
3790 } else if (!port_op
.portref
) {
3791 // the statement refers to 'any port'
3792 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3794 if (port_op
.r
.getreply_valuematch
) {
3795 port_op
.r
.getreply_valuematch
->error("Operation `any port.%s' cannot "
3796 "have value match", stmt_name
);
3798 if (port_op
.r
.redirect
.value
) {
3799 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot "
3800 "have value redirect", stmt_name
);
3802 if (port_op
.r
.redirect
.param
) {
3803 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3804 "have parameter redirect", stmt_name
);
3807 if (!signature_determined
)
3808 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3809 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3810 // checking the parameter (template instance)
3811 port_op
.r
.rcvpar
->chk(signature
);
3812 // checking whether the argument is a signature template
3813 // checking the parameter redirect if present
3814 // and determining the return type of the signature
3815 signature
= signature
->get_type_refd_last();
3816 Type
*return_type
= 0;
3817 switch (signature
->get_typetype()) {
3818 case Type::T_SIGNATURE
:
3819 if (signature
->is_nonblocking_signature())
3820 error("Operation `%s' is not applicable to non-blocking signature "
3821 "`%s'", stmt_name
, signature
->get_typename().c_str());
3822 else return_type
= signature
->get_signature_return_type();
3823 if (port_op
.r
.redirect
.param
)
3824 port_op
.r
.redirect
.param
->chk(signature
, true);
3826 if (port_op
.r
.getreply_valuematch
) {
3827 port_op
.r
.getreply_valuematch
->error("Value match cannot be used "
3828 "because signature `%s' does not have return type",
3829 signature
->get_typename().c_str());
3831 if (port_op
.r
.redirect
.value
) {
3832 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3833 "because signature `%s' does not have return type",
3834 signature
->get_typename().c_str());
3839 if (port_op
.r
.redirect
.param
)
3840 port_op
.r
.redirect
.param
->chk_erroneous();
3843 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3844 "a signature", signature
->get_typename().c_str());
3845 if (port_op
.r
.redirect
.param
)
3846 port_op
.r
.redirect
.param
->chk_erroneous();
3848 // checking the value match if present
3849 if (port_op
.r
.getreply_valuematch
) {
3850 Error_Context
cntxt2(port_op
.s
.replyval
, "In value match");
3851 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3852 port_op
.r
.getreply_valuematch
->chk(return_type
);
3854 // checking the value redirect if present
3855 chk_value_redirect(port_op
.r
.redirect
.value
, return_type
);
3857 // the statement does not have parameter (value match is also omitted)
3859 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3860 if (!port_type_body
->getreply_allowed()) {
3861 // the port type is known and it does not have outgoing signatures
3862 if (port_type_body
->get_operation_mode() ==
3863 PortTypeBody::PO_MESSAGE
) {
3864 port_op
.portref
->error("Procedure-based operation `%s' is not "
3865 "applicable to a message-based port of type `%s'", stmt_name
,
3866 port_type
->get_typename().c_str());
3868 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3869 "signatures that support reply",
3870 port_type
->get_typename().c_str());
3874 if (port_op
.r
.redirect
.value
) {
3875 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3876 "without signature template");
3877 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3879 if (port_op
.r
.redirect
.param
) {
3880 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3881 "without signature template");
3882 port_op
.r
.redirect
.param
->chk_erroneous();
3885 // checking from clause and sender redirect
3886 chk_from_clause(port_type
);
3889 void Statement::chk_catch()
3891 // determining statement type
3892 const char *stmt_name
= get_stmt_name();
3893 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3894 // checking the port reference
3895 Type
*port_type
= chk_port_ref(port_op
.portref
);
3896 // checking the signature reference, parameter and/or value redirect
3897 if (port_op
.r
.ctch
.signature_ref
) {
3898 // the signature reference is present
3899 port_op
.r
.ctch
.signature
=
3900 chk_signature_ref(port_op
.r
.ctch
.signature_ref
);
3901 // checking whether the signature is present on the incoming list
3902 // of the respective port type
3904 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3905 if (port_type_body
->catch_allowed()) {
3906 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3907 if (port_op
.r
.ctch
.signature
) {
3908 if (!out_sigs
->has_type(port_op
.r
.ctch
.signature
)) {
3909 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' is not "
3910 "present on the outgoing list of port type `%s'",
3911 port_op
.r
.ctch
.signature
->get_typename().c_str(),
3912 port_type
->get_typename().c_str());
3914 } else if (out_sigs
->get_nof_types() == 1) {
3915 // if the signature is unknown and the port type has exactly one
3916 // outgoing signature then use that for further checking
3917 port_op
.r
.ctch
.signature
=
3918 out_sigs
->get_type_byIndex(0)->get_type_refd_last();
3920 } else if (port_type_body
->get_operation_mode() ==
3921 PortTypeBody::PO_MESSAGE
) {
3922 port_op
.portref
->error("Procedure-based operation `%s' is not "
3923 "applicable to a message-based port of type `%s'", stmt_name
,
3924 port_type
->get_typename().c_str());
3926 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3927 "signatures that support exceptions",
3928 port_type
->get_typename().c_str());
3930 } else if (!port_op
.portref
) {
3931 // the statement refers to 'any port'
3932 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3934 if (port_op
.r
.redirect
.value
) {
3935 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3936 "value redirect", stmt_name
);
3939 // the receive parameter (template instance) must be also present
3940 // trying to determine type of the exception
3942 bool exc_type_determined
= false, value_redirect_checked
= false;
3943 if (port_op
.r
.ctch
.signature
) {
3944 // the signature is known
3945 SignatureExceptions
*exceptions
=
3946 port_op
.r
.ctch
.signature
->get_signature_exceptions();
3948 if (exceptions
->get_nof_types() == 1) {
3949 // the signature has exactly one exception type
3950 // use that for checking
3951 exc_type
= exceptions
->get_type_byIndex(0);
3953 // the signature has more than one exception types
3954 exc_type
= get_incoming_type(port_op
.r
.rcvpar
,
3955 port_op
.r
.redirect
.value
, value_redirect_checked
);
3957 size_t nof_comp_types
=
3958 exceptions
->get_nof_compatible_types(exc_type
);
3959 if (nof_comp_types
== 0) {
3960 port_op
.r
.rcvpar
->error("Type `%s' is not present on the "
3961 "exception list of signature `%s'",
3962 exc_type
->get_typename().c_str(),
3963 port_op
.r
.ctch
.signature
->get_typename().c_str());
3964 } else if (nof_comp_types
> 1) {
3965 port_op
.r
.rcvpar
->error("Type of the exception is ambiguous: "
3966 "`%s' is compatible with more than one exception types of "
3967 "signature `%s'", exc_type
->get_typename().c_str(),
3968 port_op
.r
.ctch
.signature
->get_typename().c_str());
3971 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3975 exc_type_determined
= true;
3977 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' does not have "
3978 "exceptions", port_op
.r
.ctch
.signature
->get_typename().c_str());
3981 if (!exc_type_determined
) {
3982 exc_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3983 value_redirect_checked
);
3985 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3986 // check the template instance using the exception type
3987 port_op
.r
.rcvpar
->chk(exc_type
);
3988 // check the value redirect if it is not done so far
3989 if (!value_redirect_checked
)
3990 chk_value_redirect(port_op
.r
.redirect
.value
, exc_type
);
3991 // checking for invalid exception types
3992 exc_type
= exc_type
->get_type_refd_last();
3993 switch (exc_type
->get_typetype()) {
3994 case Type::T_SIGNATURE
:
3995 port_op
.r
.rcvpar
->error("The type of catch parameter is signature "
3996 "`%s', which cannot be an exception type",
3997 exc_type
->get_typename().c_str());
4000 port_op
.r
.rcvpar
->error("The type of catch parameter is port type "
4001 "`%s', which cannot be an exception type",
4002 exc_type
->get_typename().c_str());
4004 case Type::T_DEFAULT
:
4005 port_op
.r
.rcvpar
->error("The type of catch parameter is the `default' "
4006 "type, which cannot be an exception type");
4011 // the statement does not have signature reference
4012 if (port_op
.r
.ctch
.timeout
) {
4013 // the parameter is timeout
4014 if (port_op
.portref
) {
4015 // the port reference is present
4017 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4018 if (!port_type_body
->getreply_allowed()) {
4019 // the port type is known and it does not allow blocking calls
4020 if (port_type_body
->get_operation_mode() ==
4021 PortTypeBody::PO_MESSAGE
) {
4022 port_op
.portref
->error("Timeout exception cannot be caught on "
4023 "a message-based port of type `%s'",
4024 port_type
->get_typename().c_str());
4026 port_op
.portref
->error("Timeout exception cannot be caught on "
4027 "a port of type `%s', which does not have any outgoing "
4028 "signatures that allow blocking calls",
4029 port_type
->get_typename().c_str());
4033 } else error("Timeout exception cannot be caught on `any port'");
4034 if (!port_op
.r
.ctch
.in_call
)
4035 error("Catching of `timeout' exception is not allowed in this "
4036 "context. It is permitted only in the response and exception "
4037 "handling part of `call' operations");
4038 else if (!port_op
.r
.ctch
.call_has_timer
)
4039 error("Catching of `timeout' exception is not allowed because the "
4040 "previous `call' operation does not have timer");
4041 if (port_op
.r
.fromclause
) port_op
.r
.fromclause
->error(
4042 "Operation `catch(timeout)' cannot have from clause");
4043 if (port_op
.r
.redirect
.sender
) port_op
.r
.redirect
.sender
->error(
4044 "Operation `catch(timeout)' cannot have sender redirect");
4046 // the operation does not have any parameter
4048 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4049 if (!port_type_body
->catch_allowed()) {
4050 // the port type is known and it does not have outgoing signatures
4051 if (port_type_body
->get_operation_mode() ==
4052 PortTypeBody::PO_MESSAGE
) {
4053 port_op
.portref
->error("Procedure-based operation `%s' is not "
4054 "applicable to a message-based port of type `%s'", stmt_name
,
4055 port_type
->get_typename().c_str());
4057 port_op
.portref
->error("Port type `%s' does not have any "
4058 "outgoing signatures that support exceptions",
4059 port_type
->get_typename().c_str());
4064 if (port_op
.r
.redirect
.value
) {
4065 // the statement does not have any parameter,
4066 // but the value redirect is present
4067 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
4068 "signature and parameter");
4069 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
4072 // checking from clause and sender redirect
4073 chk_from_clause(port_type
);
4076 void Statement::chk_check()
4078 Error_Context
cntxt(this, "In check statement");
4079 Type
*port_type
= chk_port_ref(port_op
.portref
);
4080 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4081 // the port type is known and it does not have incoming queue
4082 port_op
.portref
->error("Port type `%s' does not have incoming queue "
4083 "because it has neither incoming messages nor incoming or outgoing "
4084 "signatures", port_type
->get_typename().c_str());
4086 // checking from clause and sender redirect
4087 chk_from_clause(port_type
);
4090 void Statement::chk_clear()
4092 Error_Context
cntxt(this, "In clear port statement");
4093 Type
*port_type
= chk_port_ref(port_op
.portref
);
4094 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4095 // the port type is known and it does not have incoming queue
4096 port_op
.portref
->warning("Port type `%s' does not have incoming queue "
4097 "because it has neither incoming messages nor incoming or outgoing "
4098 "signatures", port_type
->get_typename().c_str());
4102 void Statement::chk_start_stop_port()
4104 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4105 chk_port_ref(port_op
.portref
);
4108 void Statement::chk_start_comp()
4110 Error_Context
cntxt(this, "In start test component statement");
4111 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4112 Common::Assignment
*t_ass
= comp_op
.funcinstref
->get_refd_assignment();
4114 // checking whether the referred definition is a function
4115 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
4117 case Common::Assignment::A_FUNCTION
:
4118 case Common::Assignment::A_FUNCTION_RVAL
:
4119 case Common::Assignment::A_FUNCTION_RTEMP
:
4122 comp_op
.funcinstref
->error("Reference to a function was expected in the "
4123 "argument instead of %s", t_ass
->get_description().c_str());
4126 Def_Function
*t_func
= dynamic_cast<Def_Function
*>(t_ass
);
4127 if (!t_func
) FATAL_ERROR("Statement::chk_start_comp()");
4128 // checking startability
4129 if (!t_func
->chk_startable()) return;
4130 // checking the 'runs on' clause against the type of component reference
4131 Type
*runs_on_type
= t_func
->get_RunsOnType();
4132 if (!comp_type
|| !runs_on_type
) return;
4133 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4134 comp_op
.compref
->error("Component type mismatch: The component reference "
4135 "is of type `%s', but %s runs on `%s'",
4136 comp_type
->get_typename().c_str(), t_func
->get_description().c_str(),
4137 runs_on_type
->get_typename().c_str());
4138 // checking the return type
4140 case Common::Assignment::A_FUNCTION_RTEMP
:
4141 comp_op
.funcinstref
->warning("Function `%s' returns a template of type "
4142 "`%s', which cannot be retrieved when the test component terminates",
4143 t_func
->get_fullname().c_str(),
4144 t_func
->get_Type()->get_typename().c_str());
4146 case Common::Assignment::A_FUNCTION_RVAL
: {
4147 bool return_type_correct
= false;
4148 Type
*return_type
= t_func
->get_Type();
4149 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4150 if (t
->has_done_attribute()) {
4151 return_type_correct
= true;
4153 } else if (!t
->is_ref()) break;
4155 if (!return_type_correct
)
4156 comp_op
.funcinstref
->warning("The return type of %s is `%s', which "
4157 "does not have the `done' extension attribute. When the test "
4158 "component terminates the returned value cannot be retrieved with "
4159 "a `done' operation", t_func
->get_description().c_str(),
4160 return_type
->get_typename().c_str());
4167 void Statement::chk_start_comp_refd()
4169 Error_Context
cntxt(this, "In start test component statement");
4170 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4171 switch(comp_op
.derefered
.value
->get_valuetype()){
4172 case Value::V_REFER
:
4173 comp_op
.derefered
.value
->error("A value of a function type was expected "
4174 "in the argument instead of a `refers' statement,"
4175 " which does not specify any function type");
4177 case Value::V_TTCN3_NULL
:
4178 comp_op
.derefered
.value
->error("A value of a function type was expected "
4179 "in the argument instead of a `null' value,"
4180 " which does not specify any function type");
4185 Type
*f_type
= comp_op
.derefered
.value
->get_expr_governor_last();
4186 if (!f_type
) return;
4187 switch (f_type
->get_typetype()) {
4190 case Type::T_FUNCTION
:
4193 comp_op
.derefered
.value
->error("A value of type function was expected "
4194 "in the argument instead of `%s'", f_type
->get_typename().c_str());
4197 if (f_type
->get_fat_runs_on_self()) {
4198 fau_refd
.value
->error("The argument cannot be a function reference with "
4199 "'runs on self' clause");
4202 if(!f_type
->chk_startability()) return;
4203 Type
*runs_on_type
= f_type
->get_fat_runs_on_type();
4204 if (!comp_type
|| !runs_on_type
) return;
4205 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4206 comp_op
.compref
->error("Component type mismatch: The component reference "
4207 "is of type `%s', but functions of type `%s' run on `%s'",
4208 comp_type
->get_typename().c_str(), f_type
->get_typename().c_str(),
4209 runs_on_type
->get_typename().c_str());
4210 Type
*return_type
= f_type
->get_function_return_type();
4212 if (f_type
->get_returns_template()) {
4213 comp_op
.derefered
.value
->warning("Functions of type `%s' return a "
4214 "template of type `%s', which cannot be retrieved when the test "
4215 "component terminates", f_type
->get_typename().c_str(),
4216 return_type
->get_typename().c_str());
4218 bool return_type_correct
= false;
4219 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4220 if (t
->has_done_attribute()) {
4221 return_type_correct
= true;
4223 } else if (!t
->is_ref()) break;
4225 if (!return_type_correct
)
4226 comp_op
.derefered
.value
->warning("The return type of function type "
4227 "`%s' is `%s', which does not have the `done' extension attribute. "
4228 "When the test component terminates the returned value cannot be "
4229 "retrieved with a `done' operation", f_type
->get_typename().c_str(),
4230 return_type
->get_typename().c_str());
4233 ActualParList
*parlist
= new ActualParList
;
4234 Ttcn::FormalParList
*fp_list
= f_type
->get_fat_parameters();
4235 if(fp_list
->fold_named_and_chk(comp_op
.derefered
.t_list1
, parlist
)) {
4237 delete comp_op
.derefered
.t_list1
;
4238 comp_op
.derefered
.ap_list2
= 0;
4240 delete comp_op
.derefered
.t_list1
;
4241 parlist
->set_fullname(get_fullname());
4242 parlist
->set_my_scope(my_sb
);
4243 comp_op
.derefered
.ap_list2
= parlist
;
4247 void Statement::chk_stop_kill_comp()
4249 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4250 chk_comp_ref(comp_op
.compref
, true, false);
4253 void Statement::chk_done()
4255 Error_Context
cntxt(this, "In done statement");
4256 chk_comp_ref(comp_op
.compref
, false, false);
4257 if (!comp_op
.compref
) return;
4258 // value returning done can be used only when the statement contains a
4259 // specific component reference
4260 if (comp_op
.donereturn
.donematch
) {
4261 bool value_redirect_checked
= false;
4262 // try to determine the type of return value
4263 Type
*return_type
= get_incoming_type(comp_op
.donereturn
.donematch
,
4264 comp_op
.donereturn
.redirect
, value_redirect_checked
);
4266 bool return_type_correct
= false;
4267 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4268 if (t
->has_done_attribute()) {
4269 return_type_correct
= true;
4271 } else if (!t
->is_ref()) break;
4273 if (!return_type_correct
) {
4274 error("Return type `%s' does not have `done' extension attribute",
4275 return_type
->get_typename().c_str());
4276 return_type
= Type::get_pooltype(Type::T_ERROR
);
4279 comp_op
.donereturn
.donematch
->error("Cannot determine the return type "
4280 "for value returning done");
4281 return_type
= Type::get_pooltype(Type::T_ERROR
);
4283 comp_op
.donereturn
.donematch
->chk(return_type
);
4284 if (!value_redirect_checked
)
4285 chk_value_redirect(comp_op
.donereturn
.redirect
, return_type
);
4286 } else if (comp_op
.donereturn
.redirect
) {
4287 comp_op
.donereturn
.redirect
->error("Redirect cannot be used for the "
4288 "return value without a matching template");
4289 chk_value_redirect(comp_op
.donereturn
.redirect
, 0);
4293 void Statement::chk_killed()
4295 Error_Context
cntxt(this, "In killed statement");
4296 chk_comp_ref(comp_op
.compref
, false, false);
4299 void Statement::chk_connect()
4301 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4302 // checking endpoints
4304 PortTypeBody
*ptb1
, *ptb2
;
4306 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4307 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, false);
4308 ptb1
= pt1
? pt1
->get_PortBody() : 0;
4311 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4312 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, false);
4313 ptb2
= pt2
? pt2
->get_PortBody() : 0;
4315 // checking consistency
4316 if (!ptb1
|| !ptb2
) return;
4317 if (!ptb1
->is_connectable(ptb2
) ||
4318 (ptb1
!= ptb2
&& !ptb2
->is_connectable(ptb1
))) {
4319 error("The connection between port types `%s' and `%s' is not consistent",
4320 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4321 ptb1
->report_connection_errors(ptb2
);
4322 if (ptb1
!= ptb2
) ptb2
->report_connection_errors(ptb1
);
4326 void Statement::chk_map()
4328 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4329 // checking endpoints
4331 PortTypeBody
*ptb1
, *ptb2
;
4332 bool cref1_is_tc
= false, cref1_is_system
= false;
4333 bool cref2_is_tc
= false, cref2_is_system
= false;
4335 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4336 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, true);
4338 ptb1
= pt1
->get_PortBody();
4339 if (ptb1
->is_internal()) {
4340 config_op
.portref1
->warning("Port type `%s' was marked as `internal'",
4341 pt1
->get_typename().c_str());
4344 Value
*cref1
= config_op
.compref1
->get_value_refd_last();
4345 if (cref1
->get_valuetype() == Value::V_EXPR
) {
4346 switch (cref1
->get_optype()) {
4347 case Value::OPTYPE_COMP_MTC
:
4348 case Value::OPTYPE_COMP_SELF
:
4349 case Value::OPTYPE_COMP_CREATE
:
4352 case Value::OPTYPE_COMP_SYSTEM
:
4353 cref1_is_system
= true;
4360 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4361 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, true);
4363 ptb2
= pt2
->get_PortBody();
4364 if (ptb2
->is_internal()) {
4365 config_op
.portref2
->warning("Port type `%s' was marked as `internal'",
4366 pt2
->get_typename().c_str());
4369 Value
*cref2
= config_op
.compref2
->get_value_refd_last();
4370 if (cref2
->get_valuetype() == Value::V_EXPR
) {
4371 switch (cref2
->get_optype()) {
4372 case Value::OPTYPE_COMP_MTC
:
4373 case Value::OPTYPE_COMP_SELF
:
4374 case Value::OPTYPE_COMP_CREATE
:
4377 case Value::OPTYPE_COMP_SYSTEM
:
4378 cref2_is_system
= true;
4384 if (cref1_is_tc
&& cref2_is_tc
) {
4385 error("Both endpoints of the mapping are test component ports");
4388 if (cref1_is_system
&& cref2_is_system
) {
4389 error("Both endpoints of the mapping are system ports");
4392 // checking consistency
4393 if (!ptb1
|| !ptb2
) return;
4394 if (cref1_is_tc
|| cref2_is_system
) {
4395 if (!ptb1
->is_mappable(ptb2
)) {
4396 error("The mapping between test component port type `%s' and system "
4397 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4398 pt2
->get_typename().c_str());
4399 ptb1
->report_mapping_errors(ptb2
);
4401 } else if (cref2_is_tc
|| cref1_is_system
) {
4402 if (!ptb2
->is_mappable(ptb1
)) {
4403 error("The mapping between system port type `%s' and test component "
4404 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4405 pt2
->get_typename().c_str());
4406 ptb2
->report_mapping_errors(ptb1
);
4409 // we have no idea which one is the system port
4410 if (!ptb1
->is_mappable(ptb1
) && !ptb2
->is_mappable(ptb1
)) {
4411 error("The mapping between port types `%s' and `%s' is not consistent",
4412 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4417 void Statement::chk_start_timer()
4419 Error_Context
cntxt(this, "In start timer statement");
4420 chk_timer_ref(timer_op
.timerref
);
4421 if (timer_op
.value
) {
4422 // check the actual duration
4423 timer_op
.value
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4424 Value
*t_val
= timer_op
.value
->get_value_refd_last();
4425 if (t_val
->get_valuetype() == Value::V_REAL
) {
4426 ttcn3float v_real
= t_val
->get_val_Real();
4428 timer_op
.value
->error("The timer duration is negative: `%s'",
4429 Real2string(v_real
).c_str());
4430 } else if (isSpecialFloatValue(v_real
)) {
4431 timer_op
.value
->error("The timer duration cannot be %s",
4432 Real2string(v_real
).c_str());
4436 // check whether the timer has default duration
4437 Common::Assignment
*t_ass
= timer_op
.timerref
->get_refd_assignment();
4438 if (t_ass
&& t_ass
->get_asstype() == Common::Assignment::A_TIMER
) {
4439 Def_Timer
*t_def_timer
= dynamic_cast<Def_Timer
*>(t_ass
);
4440 if (!t_def_timer
) FATAL_ERROR("Statement::chk_start_timer()");
4441 if (!t_def_timer
->has_default_duration(
4442 timer_op
.timerref
->get_subrefs()))
4443 error("Missing duration: %s does not have default duration",
4444 t_ass
->get_description().c_str());
4449 void Statement::chk_stop_timer_timeout()
4451 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4452 chk_timer_ref(timer_op
.timerref
);
4455 void Statement::chk_setverdict()
4457 Error_Context
cntxt(this, "In setverdict statement");
4458 if(!my_sb
->get_my_def())
4459 error("Setverdict statement is not allowed in the control part");
4460 setverdict
.verdictval
->chk_expr_verdict(Type::EXPECTED_DYNAMIC_VALUE
);
4461 Value
*t_val
= setverdict
.verdictval
->get_value_refd_last();
4462 if (t_val
->get_valuetype() == Value::V_VERDICT
&&
4463 t_val
->get_val_verdict() == Value::Verdict_ERROR
) {
4464 setverdict
.verdictval
->error("Error verdict cannot be set by the setverdict "
4469 void Statement::chk_execute()
4471 Error_Context
cntxt(this, "In execute statement");
4472 Ref_pard
*ref
=testcase_inst
.tcref
;
4473 Common::Assignment
*t_ass
=ref
->get_refd_assignment();
4474 if(!t_ass
) goto error
;
4475 if(t_ass
->get_asstype()!=Common::Assignment::A_TESTCASE
) {
4476 ref
->error("Reference to a testcase was expected in the argument"
4477 " instead of %s", t_ass
->get_description().c_str());
4480 if(my_sb
->get_scope_runs_on()) {
4481 ref
->error("A definition that has `runs on' clause cannot "
4482 "execute testcases");
4485 if (testcase_inst
.timerval
) {
4486 testcase_inst
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4487 Value
*t_val
= testcase_inst
.timerval
->get_value_refd_last();
4488 if (t_val
->get_valuetype() == Value::V_REAL
) {
4489 ttcn3float v_real
= t_val
->get_val_Real();
4491 testcase_inst
.timerval
->error("The testcase guard "
4492 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4493 } else if (isSpecialFloatValue(v_real
)) {
4494 testcase_inst
.timerval
->error("The testcase guard "
4495 "timer duration cannot be %s", Real2string(v_real
).c_str());
4502 statementtype
=S_ERROR
;
4505 void Statement::chk_execute_refd()
4507 Error_Context
cntxt(this, "In execute statement");
4508 switch(execute_refd
.value
->get_valuetype()){
4509 case Value::V_REFER
:
4510 execute_refd
.value
->error("A value of a testcase type was expected "
4511 "in the argument instead of a `refers' statement,"
4512 " which does not specify any function type");
4514 case Value::V_TTCN3_NULL
:
4515 execute_refd
.value
->error("A value of a testcase type was expected "
4516 "in the argument instead of a `null' value,"
4517 " which does not specify any function type");
4522 Type
*t
= execute_refd
.value
->get_expr_governor_last();
4524 switch (t
->get_typetype()) {
4527 case Type::T_TESTCASE
:
4530 execute_refd
.value
->error("A value of type testcase was expected in the "
4531 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
4534 if (my_sb
->get_scope_runs_on()) {
4535 execute_refd
.value
->error("A definition that has `runs on' clause cannot "
4536 "execute testcases");
4539 ActualParList
*parlist
= new ActualParList
;
4540 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
4541 bool is_erroneous
= fp_list
->chk_actual_parlist(execute_refd
.t_list1
,
4543 delete execute_refd
.t_list1
;
4546 execute_refd
.ap_list2
= 0;
4549 parlist
->set_fullname(get_fullname());
4550 parlist
->set_my_scope(my_sb
);
4551 execute_refd
.ap_list2
= parlist
;
4553 if(execute_refd
.timerval
) {
4554 execute_refd
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4555 Value
*t_val
= execute_refd
.timerval
->get_value_refd_last();
4556 if(t_val
->get_valuetype() == Value::V_REAL
) {
4557 ttcn3float v_real
= t_val
->get_val_Real();
4559 execute_refd
.value
->error("The testcase guard "
4560 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4561 } else if (isSpecialFloatValue(v_real
)) {
4562 execute_refd
.value
->error("The testcase guard "
4563 "timer duration cannot be %s", Real2string(v_real
).c_str());
4571 statementtype
=S_ERROR
;
4574 Type
*Statement::chk_port_ref(Reference
*p_ref
)
4576 if (!my_sb
->get_my_def())
4577 error("Port operation is not allowed in the control part");
4578 if (!p_ref
) return 0;
4579 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4580 if (!t_ass
) return 0;
4581 switch (t_ass
->get_asstype()) {
4582 case Common::Assignment::A_PORT
: {
4583 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4584 if (t_dims
) t_dims
->chk_indices(p_ref
, "port", false,
4585 Type::EXPECTED_DYNAMIC_VALUE
);
4586 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4587 "cannot have field or array sub-references",
4588 t_ass
->get_description().c_str());
4590 case Common::Assignment::A_PAR_PORT
:
4591 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4592 "field or array sub-references", t_ass
->get_description().c_str());
4595 p_ref
->error("Reference to a port or port parameter was expected "
4596 "instead of %s", t_ass
->get_description().c_str());
4599 Type
*ret_val
= t_ass
->get_Type();
4600 if (!ret_val
) return 0;
4601 ret_val
= ret_val
->get_type_refd_last();
4602 if (ret_val
->get_typetype() == Type::T_PORT
) return ret_val
;
4606 void Statement::chk_to_clause(Type
*port_type
)
4608 if (!port_op
.s
.toclause
) return;
4609 // pointer to the address type
4612 // the port type is known
4613 address_type
= port_type
->get_PortBody()->get_address_type();
4615 // the port type is unknown
4616 // address is permitted if it is visible from the current module
4617 address_type
= my_sb
->get_scope_mod()->get_address_type();
4619 Error_Context
cntxt(port_op
.s
.toclause
, "In `to' clause");
4621 // detect possible enumerated values (address may be an enumerated type)
4622 address_type
->chk_this_value_ref(port_op
.s
.toclause
);
4623 // try to figure out whether the argument is a component reference or
4627 port_op
.s
.toclause
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4628 if (t_governor
) is_address
= address_type
->is_compatible(t_governor
, NULL
);
4630 port_op
.s
.toclause
->get_expr_returntype(Type::EXPECTED_DYNAMIC_VALUE
)
4631 != Type::T_COMPONENT
;
4633 // the argument is an address value
4634 port_op
.s
.toclause
->set_my_governor(address_type
);
4635 address_type
->chk_this_value(port_op
.s
.toclause
, 0,
4636 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
4639 // the argument is not an address value, treat as a component reference
4640 chk_comp_ref(port_op
.s
.toclause
, true, true);
4643 // usage of address is not allowed
4644 chk_comp_ref(port_op
.s
.toclause
, true, true);
4648 void Statement::chk_from_clause(Type
*port_type
)
4650 if (!port_op
.r
.fromclause
&& !port_op
.r
.redirect
.sender
) return;
4651 // pointer to the address type
4654 // the port type is known
4655 address_type
= port_type
->get_PortBody()->get_address_type();
4656 } else if (port_op
.portref
) {
4657 // the operation refers to a specific port, but its type is unknown
4658 // address is permitted if it is visible from the current module
4659 address_type
= my_sb
->get_scope_mod()->get_address_type();
4661 // the operation refers to 'any port'
4662 // address is not allowed
4665 bool sender_redirect_checked
= false;
4666 Type
*from_clause_type
= 0;
4667 if (port_op
.r
.fromclause
) {
4668 // the from clause is present
4669 Error_Context
cntxt(port_op
.r
.fromclause
, "In `from' clause");
4671 port_op
.r
.fromclause
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4672 Template
*templ_body
= port_op
.r
.fromclause
->get_Template();
4673 if (!from_clause_type
) {
4674 // try to detect possible enumerated values
4675 if (address_type
) address_type
->chk_this_template_ref(templ_body
);
4676 else templ_body
->set_lowerid_to_ref();
4678 templ_body
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4680 if (!from_clause_type
) {
4681 // trying to determine the type of template in from clause
4682 // based on the sender redirect
4683 from_clause_type
= chk_sender_redirect(address_type
);
4684 sender_redirect_checked
= true;
4686 if (!from_clause_type
) {
4687 // trying to figure out whether the template is a component reference
4688 // or an SUT address
4690 if (templ_body
->get_expr_returntype(Type::EXPECTED_TEMPLATE
)
4691 == Type::T_COMPONENT
) is_compref
= true;
4693 switch (templ_body
->get_templatetype()) {
4694 case Template::SPECIFIC_VALUE
:
4695 // treat 'null' as component reference
4696 if (templ_body
->get_specific_value()->get_valuetype() ==
4697 Value::V_TTCN3_NULL
) is_compref
= true;
4698 else is_compref
= false;
4700 case Template::ANY_VALUE
:
4701 case Template::ANY_OR_OMIT
:
4702 // treat generic wildcards ? and * as component references
4710 // the argument is a component reference: get a pool type
4711 from_clause_type
= Type::get_pooltype(Type::T_COMPONENT
);
4712 } else if (address_type
) {
4713 // the argument is not a component reference: try the address type
4714 from_clause_type
= address_type
;
4717 if (from_clause_type
) {
4718 // the type of from clause is known
4719 port_op
.r
.fromclause
->chk(from_clause_type
);
4721 || !address_type
->is_compatible(from_clause_type
, NULL
)) {
4722 // from_clause_type must be a component type
4723 switch (from_clause_type
->get_type_refd_last()->get_typetype()) {
4725 // to avoid further errors in sender redirect
4726 from_clause_type
= 0;
4727 case Type::T_COMPONENT
:
4728 if (templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
)
4729 chk_comp_ref(templ_body
->get_specific_value(), true, true);
4732 port_op
.r
.fromclause
->error("The type of the template should be a "
4733 "component type %sinstead of `%s'",
4734 address_type
? "or the `address' type " : "",
4735 from_clause_type
->get_typename().c_str());
4736 // to avoid further errors in sender redirect
4737 from_clause_type
= 0;
4741 // the type of from clause is unknown
4742 port_op
.r
.fromclause
->error("Cannot determine the type of the "
4746 if (!sender_redirect_checked
) {
4747 Type
*sender_redirect_type
= chk_sender_redirect(address_type
);
4748 if (from_clause_type
&& sender_redirect_type
&&
4749 !from_clause_type
->is_identical(sender_redirect_type
)) {
4750 error("The types in `from' clause and `sender' redirect are not the "
4751 "same: `%s' was expected instead of `%s'",
4752 from_clause_type
->get_typename().c_str(),
4753 sender_redirect_type
->get_typename().c_str());
4758 void Statement::chk_call_body(Type
*port_type
, Type
*signature
)
4760 bool has_catch_timeout
= false;
4761 // setting the flags whether 'catch(timeout)' statements are allowed
4762 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4763 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4764 if (t_ag
->get_type() != AltGuard::AG_OP
)
4765 FATAL_ERROR("Statement::chk_call_body()");
4766 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4767 if (t_stmt
->statementtype
== S_CATCH
) {
4768 t_stmt
->port_op
.r
.ctch
.in_call
= true;
4769 if (port_op
.s
.call
.timer
)
4770 t_stmt
->port_op
.r
.ctch
.call_has_timer
= true;
4771 if (t_stmt
->port_op
.r
.ctch
.timeout
) has_catch_timeout
= true;
4774 Error_Context
cntxt(this, "In response and exception handling part");
4775 port_op
.s
.call
.body
->set_my_laic_stmt(port_op
.s
.call
.body
, 0);
4776 port_op
.s
.call
.body
->set_my_ags(port_op
.s
.call
.body
);
4777 port_op
.s
.call
.body
->chk();
4779 // checking whether getreply/catch operations refer to the same port
4780 // and same signature as the call operation
4781 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4782 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4783 if (t_ag
->get_type() != AltGuard::AG_OP
)
4784 FATAL_ERROR("Statement::chk_call_body()");
4785 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4786 if (t_stmt
->statementtype
== S_ERROR
) continue;
4787 // checking port reference
4788 if (!t_stmt
->port_op
.portref
) {
4789 t_stmt
->error("The `%s' operation must refer to the same port as "
4790 "the previous `call' statement: `%s' was expected instead of "
4791 "`any port'", t_stmt
->get_stmt_name(),
4792 port_op
.portref
->get_id()->get_dispname().c_str());
4793 } else if (*port_op
.portref
->get_id() !=
4794 *t_stmt
->port_op
.portref
->get_id()) {
4795 t_stmt
->port_op
.portref
->error("The `%s' operation refers to a "
4796 "different port than the previous `call' statement: `%s' was "
4797 "expected instead of `%s'", t_stmt
->get_stmt_name(),
4798 port_op
.portref
->get_id()->get_dispname().c_str(),
4799 t_stmt
->port_op
.portref
->get_id()->get_dispname().c_str());
4801 // checking the signature
4802 switch (t_stmt
->statementtype
) {
4804 if (t_stmt
->port_op
.r
.rcvpar
) {
4805 Type
*t_sig
= t_stmt
->port_op
.r
.rcvpar
4806 ->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4807 if (!signature
->is_compatible(t_sig
, NULL
))
4808 t_stmt
->port_op
.r
.rcvpar
->error("The `getreply' operation refers "
4809 "to a different signature than the previous `call' statement: "
4810 "`%s' was expected instead of `%s'",
4811 signature
->get_typename().c_str(),
4812 t_sig
->get_typename().c_str());
4816 if (t_stmt
->port_op
.r
.ctch
.signature
4817 && !signature
->is_compatible(t_stmt
->port_op
.r
.ctch
.signature
, NULL
))
4818 t_stmt
->port_op
.r
.ctch
.signature_ref
->error("The `catch' "
4819 "operation refers to a different signature than the previous "
4820 "`call' statement: `%s' was expected instead of `%s'",
4821 signature
->get_typename().c_str(),
4822 t_stmt
->port_op
.r
.ctch
.signature
->get_typename().c_str());
4825 FATAL_ERROR("Statement::chk_call_body()");
4829 if (port_op
.s
.call
.timer
&& !has_catch_timeout
)
4830 warning("The call operation has a timer, but the timeout exception is "
4834 Type
*Statement::get_outgoing_type(TemplateInstance
*p_ti
)
4836 // first analyze the template instance as is
4837 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4838 // return if this step was successful
4839 if (ret_val
) return ret_val
;
4840 // try to convert the undef identifier in the template instance to
4841 // a reference because it cannot be an enum value anymore
4842 Template
*t_templ
= p_ti
->get_Template();
4843 t_templ
->set_lowerid_to_ref();
4844 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4847 Type
*Statement::get_incoming_type(TemplateInstance
*p_ti
,
4848 Reference
*p_val_redir
, bool& p_val_redir_checked
)
4850 // first analyze the template instance
4851 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4852 // return if this step was successful
4853 if (ret_val
) return ret_val
;
4854 // use the variable in value redirect in the next step
4855 ret_val
= chk_value_redirect(p_val_redir
, 0);
4856 p_val_redir_checked
= true;
4857 // return if this step was successful
4858 if (ret_val
) return ret_val
;
4859 // finally try to convert the undef identifier in the template instance to
4860 // a reference because it cannot be an enum value anymore
4861 Template
*t_templ
= p_ti
->get_Template();
4862 t_templ
->set_lowerid_to_ref();
4863 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4866 Type
*Statement::chk_value_redirect(Reference
*p_ref
, Type
*p_type
)
4868 if (!p_ref
) return NULL
;
4869 Error_Context
cntxt(p_ref
, "In `value' redirect");
4870 Type
*t_var_type
= p_ref
->chk_variable_ref();
4871 if (p_type
&& t_var_type
) {
4872 TypeCompatInfo
info(my_sb
->get_scope_mod(), p_type
, t_var_type
, true, false);
4873 if (p_ref
->get_subrefs()) info
.set_str2_elem(p_ref
->get_subrefs()->refers_to_string_element());
4876 if (!p_type
->is_compatible(t_var_type
, &info
, &l_chain
, &r_chain
)) {
4877 if (info
.is_subtype_error()) {
4878 p_ref
->error("%s", info
.get_subtype_error().c_str());
4880 if (!info
.is_erroneous()) {
4881 p_ref
->error("Type mismatch in value redirect: "
4882 "A variable of type `%s' was expected instead of `%s'",
4883 p_type
->get_typename().c_str(),
4884 t_var_type
->get_typename().c_str());
4886 p_ref
->error("%s", info
.get_error_str_str().c_str());
4893 Type
*Statement::chk_sender_redirect(Type
*address_type
)
4895 if (!port_op
.r
.redirect
.sender
) return 0;
4896 Error_Context
cntxt(port_op
.r
.redirect
.sender
, "In `sender' redirect");
4897 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
4898 if (!t_var_type
) return 0;
4899 if (!address_type
|| !address_type
->is_identical(t_var_type
)) {
4900 // t_var_type must be a component type
4901 switch (t_var_type
->get_type_refd_last()->get_typetype()) {
4902 case Type::T_COMPONENT
:
4907 port_op
.r
.redirect
.sender
->error("The type of the variable should be "
4908 "a component type %sinstead of `%s'",
4909 address_type
? "or the `address' type " : "",
4910 t_var_type
->get_typename().c_str());
4917 Type
*Statement::chk_signature_ref(Reference
*p_ref
)
4919 if (!p_ref
) FATAL_ERROR("Statement::chk_signature_ref()");
4920 Error_Context(p_ref
, "In signature");
4921 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4922 if (!t_ass
) return 0;
4923 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
) {
4924 p_ref
->error("Reference to a signature was expected instead of %s",
4925 t_ass
->get_description().c_str());
4928 Type
*ret_val
= t_ass
->get_Type();
4929 if (!ret_val
) return 0;
4930 ret_val
= ret_val
->get_field_type(p_ref
->get_subrefs(),
4931 Type::EXPECTED_DYNAMIC_VALUE
);
4932 if (!ret_val
) return 0;
4933 ret_val
= ret_val
->get_type_refd_last();
4934 switch (ret_val
->get_typetype()) {
4935 case Type::T_SIGNATURE
:
4940 p_ref
->error("Reference to a signature was expected instead of port type "
4941 "`%s'", ret_val
->get_typename().c_str());
4944 p_ref
->error("Reference to a signature was expected instead of data type "
4945 "`%s'", ret_val
->get_typename().c_str());
4951 void Statement::chk_timer_ref(Reference
*p_ref
)
4954 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4956 switch (t_ass
->get_asstype()) {
4957 case Common::Assignment::A_TIMER
: {
4958 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4959 if (t_dims
) t_dims
->chk_indices(p_ref
, "timer", false,
4960 Type::EXPECTED_DYNAMIC_VALUE
);
4961 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4962 "cannot have field or array sub-references",
4963 t_ass
->get_description().c_str());
4965 case Common::Assignment::A_PAR_TIMER
:
4966 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4967 "field or array sub-references", t_ass
->get_description().c_str());
4970 p_ref
->error("Reference to a timer or timer parameter was expected "
4971 "instead of %s", t_ass
->get_description().c_str());
4975 Type
*Statement::chk_comp_ref(Value
*p_val
, bool allow_mtc
, bool allow_system
)
4977 if (!my_sb
->get_my_def())
4978 error("Component operation is not allowed in the control part");
4979 if (!p_val
) return 0;
4980 Value
*v
= p_val
->get_value_refd_last();
4981 switch (v
->get_valuetype()) {
4982 case Value::V_ERROR
:
4986 case Value::V_INVOKE
:
4987 if(p_val
->get_expr_returntype() != Type::T_COMPONENT
)
4988 p_val
->error("A component reference was expected as return value");
4990 case Value::V_TTCN3_NULL
:
4991 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
4994 switch (v
->get_optype()) {
4995 case Value::OPTYPE_COMP_NULL
:
4996 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
4998 case Value::OPTYPE_COMP_MTC
:
5000 p_val
->error("The `mtc' component reference shall not be used in `%s' operation", get_stmt_name());
5002 case Value::OPTYPE_COMP_SYSTEM
:
5004 p_val
->error("The `system' component reference shall not be used in `%s' operation", get_stmt_name());
5006 case Value::OPTYPE_COMP_SELF
:
5007 case Value::OPTYPE_COMP_CREATE
:
5010 p_val
->error("A component reference was expected as operand");
5015 p_val
->error("A component reference was expected as operand");
5018 Type
*ret_val
= p_val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
5019 if (!ret_val
) return 0;
5020 ret_val
= ret_val
->get_type_refd_last();
5021 switch (ret_val
->get_typetype()) {
5024 case Type::T_COMPONENT
:
5027 p_val
->error("Type mismatch: The type of the operand should be a "
5028 "component type instead of `%s'", ret_val
->get_typename().c_str());
5033 Type
*Statement::chk_conn_endpoint(Value
*p_compref
, Reference
*p_portref
,
5036 Type
*comp_type
= chk_comp_ref(p_compref
, true, allow_system
);
5038 ComponentTypeBody
*comp_body
= comp_type
->get_CompBody();
5039 p_portref
->set_base_scope(comp_body
);
5040 const Identifier
& t_portid
= *p_portref
->get_id();
5041 if (!comp_body
->has_local_ass_withId(t_portid
)) {
5042 p_portref
->error("Component type `%s' does not have port with name "
5043 "`%s'", comp_type
->get_typename().c_str(),
5044 t_portid
.get_dispname().c_str());
5047 Common::Assignment
*t_ass
= comp_body
->get_local_ass_byId(t_portid
);
5048 if (t_ass
->get_asstype() != Common::Assignment::A_PORT
) {
5049 p_portref
->error("Definition `%s' in component type `%s' is a %s and "
5050 "not a port", t_portid
.get_dispname().c_str(),
5051 comp_type
->get_typename().c_str(), t_ass
->get_assname());
5054 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
5055 if (t_dims
) t_dims
->chk_indices(p_portref
, "port", false,
5056 Type::EXPECTED_DYNAMIC_VALUE
);
5057 else if (p_portref
->get_subrefs()) {
5058 p_portref
->error("Port `%s' is not an array. The "
5059 "reference cannot have array indices",
5060 t_portid
.get_dispname().c_str());
5062 Type
*port_type
= t_ass
->get_Type();
5064 // check whether the external interface is provided by another port type
5065 PortTypeBody
*port_body
= port_type
->get_PortBody();
5066 if (port_body
->get_type() == PortTypeBody::PT_USER
) {
5067 Type
*provider_type
= port_body
->get_provider_type();
5068 if (provider_type
) port_type
= provider_type
;
5073 // the component type cannot be determined
5074 FieldOrArrayRefs
*t_subrefs
= p_portref
->get_subrefs();
5076 // check the array indices: they should be integers
5077 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
5078 t_subrefs
->get_ref(i
)->get_val()
5079 ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
5086 void Statement::set_code_section(
5087 GovernedSimple::code_section_t p_code_section
)
5089 switch(statementtype
) {
5098 case S_START_PROFILER
:
5099 case S_STOP_PROFILER
:
5102 ass
->set_code_section(p_code_section
);
5104 case S_FUNCTION_INSTANCE
:
5105 case S_ALTSTEP_INSTANCE
:
5107 ref_pard
->set_code_section(p_code_section
);
5110 block
->set_code_section(p_code_section
);
5114 case S_STOP_TESTCASE
:
5115 if (logargs
) logargs
->set_code_section(p_code_section
);
5118 if_stmt
.ics
->set_code_section(p_code_section
);
5119 if (if_stmt
.elseblock
)
5120 if_stmt
.elseblock
->set_code_section(p_code_section
);
5123 if (!loop
.for_stmt
.varinst
)
5124 loop
.for_stmt
.init_ass
->set_code_section(p_code_section
);
5125 loop
.for_stmt
.finalexpr
->set_code_section(p_code_section
);
5126 loop
.for_stmt
.step
->set_code_section(p_code_section
);
5127 loop
.block
->set_code_section(p_code_section
);
5131 loop
.expr
->set_code_section(p_code_section
);
5132 loop
.block
->set_code_section(p_code_section
);
5135 select
.expr
->set_code_section(p_code_section
);
5136 select
.scs
->set_code_section(p_code_section
);
5140 ags
->set_code_section(p_code_section
);
5143 if (returnexpr
.v
) returnexpr
.v
->set_code_section(p_code_section
);
5144 if (returnexpr
.t
) returnexpr
.t
->set_code_section(p_code_section
);
5147 if (deactivate
) deactivate
->set_code_section(p_code_section
);
5150 port_op
.portref
->set_code_section(p_code_section
);
5151 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5152 if (port_op
.s
.toclause
)
5153 port_op
.s
.toclause
->set_code_section(p_code_section
);
5156 port_op
.portref
->set_code_section(p_code_section
);
5157 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5158 if (port_op
.s
.toclause
)
5159 port_op
.s
.toclause
->set_code_section(p_code_section
);
5160 if (port_op
.s
.call
.timer
)
5161 port_op
.s
.call
.timer
->set_code_section(p_code_section
);
5162 if (port_op
.s
.call
.body
)
5163 port_op
.s
.call
.body
->set_code_section(p_code_section
);
5166 port_op
.portref
->set_code_section(p_code_section
);
5167 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5168 if (port_op
.s
.replyval
)
5169 port_op
.s
.replyval
->set_code_section(p_code_section
);
5170 if (port_op
.s
.toclause
)
5171 port_op
.s
.toclause
->set_code_section(p_code_section
);
5174 port_op
.portref
->set_code_section(p_code_section
);
5175 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5176 if (port_op
.s
.toclause
)
5177 port_op
.s
.toclause
->set_code_section(p_code_section
);
5180 case S_CHECK_RECEIVE
:
5182 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5183 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5184 if (port_op
.r
.fromclause
)
5185 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5186 if (port_op
.r
.redirect
.value
)
5187 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5188 if (port_op
.r
.redirect
.sender
)
5189 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5192 case S_CHECK_GETCALL
:
5193 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5194 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5195 if (port_op
.r
.fromclause
)
5196 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5197 if (port_op
.r
.redirect
.param
)
5198 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5199 if (port_op
.r
.redirect
.sender
)
5200 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5203 case S_CHECK_GETREPLY
:
5204 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5205 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5206 if (port_op
.r
.getreply_valuematch
)
5207 port_op
.r
.getreply_valuematch
->set_code_section(p_code_section
);
5208 if (port_op
.r
.fromclause
)
5209 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5210 if (port_op
.r
.redirect
.value
)
5211 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5212 if (port_op
.r
.redirect
.param
)
5213 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5214 if (port_op
.r
.redirect
.sender
)
5215 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5219 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5220 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5221 if (port_op
.r
.fromclause
)
5222 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5223 if (port_op
.r
.redirect
.value
)
5224 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5225 if (port_op
.r
.redirect
.sender
)
5226 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5229 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5230 if (port_op
.r
.fromclause
)
5231 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5232 if (port_op
.r
.redirect
.sender
)
5233 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5239 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5242 comp_op
.compref
->set_code_section(p_code_section
);
5243 comp_op
.funcinstref
->set_code_section(p_code_section
);
5245 case S_START_COMP_REFD
:
5246 comp_op
.compref
->set_code_section(p_code_section
);
5247 comp_op
.derefered
.value
->set_code_section(p_code_section
);
5252 if (comp_op
.compref
) comp_op
.compref
->set_code_section(p_code_section
);
5255 if (comp_op
.compref
) {
5256 comp_op
.compref
->set_code_section(p_code_section
);
5257 if (comp_op
.donereturn
.donematch
)
5258 comp_op
.donereturn
.donematch
->set_code_section(p_code_section
);
5259 if (comp_op
.donereturn
.redirect
)
5260 comp_op
.donereturn
.redirect
->set_code_section(p_code_section
);
5267 config_op
.compref1
->set_code_section(p_code_section
);
5268 config_op
.portref1
->set_code_section(p_code_section
);
5269 config_op
.compref2
->set_code_section(p_code_section
);
5270 config_op
.portref2
->set_code_section(p_code_section
);
5273 timer_op
.timerref
->set_code_section(p_code_section
);
5274 if (timer_op
.value
) timer_op
.value
->set_code_section(p_code_section
);
5278 if (timer_op
.timerref
)
5279 timer_op
.timerref
->set_code_section(p_code_section
);
5282 setverdict
.verdictval
->set_code_section(p_code_section
);
5283 if (setverdict
.logargs
)
5284 setverdict
.logargs
->set_code_section(p_code_section
);
5286 case S_TESTCASE_INSTANCE
:
5287 testcase_inst
.tcref
->set_code_section(p_code_section
);
5288 if (testcase_inst
.timerval
)
5289 testcase_inst
.timerval
->set_code_section(p_code_section
);
5291 case S_TESTCASE_INSTANCE_REFD
:
5292 execute_refd
.value
->set_code_section(p_code_section
);
5293 if(execute_refd
.timerval
)
5294 execute_refd
.timerval
->set_code_section(p_code_section
);
5296 case S_ACTIVATE_REFD
:
5297 case S_FUNCTION_INVOKED
:
5298 case S_ALTSTEP_INVOKED
:
5299 fau_refd
.value
->set_code_section(p_code_section
);
5300 if(fau_refd
.ap_list2
)
5301 for(size_t i
= 0; i
< fau_refd
.ap_list2
->get_nof_pars(); i
++)
5302 fau_refd
.ap_list2
->get_par(i
)->set_code_section(p_code_section
);
5305 str2ttcn
.val
->set_code_section(p_code_section
);
5306 str2ttcn
.ref
->set_code_section(p_code_section
);
5309 FATAL_ERROR("Statement::set_code_section()");
5310 } // switch statementtype
5313 char *Statement::generate_code(char *str
)
5315 switch (statementtype
) {
5322 // conditional and loop statements do not need single location setting
5323 // the embedded expressions, statements have their own locations
5326 str
= update_location_object(str
);
5329 switch(statementtype
) {
5331 str
=def
->generate_code_str(str
);
5334 str
=ass
->generate_code(str
);
5336 case S_FUNCTION_INSTANCE
:
5337 case S_ALTSTEP_INSTANCE
:
5338 str
=generate_code_funcinst(str
);
5340 case S_FUNCTION_INVOKED
:
5341 case S_ALTSTEP_INVOKED
:
5342 str
=generate_code_invoke(str
);
5345 str
=generate_code_block(str
);
5348 str
=generate_code_log(str
);
5351 str
= generate_code_label(str
);
5354 str
= generate_code_goto(str
);
5357 str
=generate_code_if(str
);
5360 str
=generate_code_select(str
);
5363 str
=generate_code_for(str
);
5366 str
=generate_code_while(str
);
5369 str
=generate_code_dowhile(str
);
5372 str
=generate_code_break(str
);
5375 str
=generate_code_continue(str
);
5378 str
=mputstr(str
, "TTCN_Runtime::stop_execution();\n");
5380 case S_STOP_TESTCASE
:
5381 str
=generate_code_testcase_stop(str
);
5384 str
=ags
->generate_code_alt(str
, *this);
5387 str
=generate_code_repeat(str
);
5390 str
=generate_code_interleave(str
);
5393 str
=generate_code_return(str
);
5396 str
=generate_code_activate(str
);
5398 case S_ACTIVATE_REFD
:
5399 str
=generate_code_activate_refd(str
);
5402 str
=generate_code_deactivate(str
);
5405 str
= generate_code_send(str
);
5408 str
= generate_code_call(str
);
5411 str
= generate_code_reply(str
);
5414 str
= generate_code_raise(str
);
5422 case S_CHECK_RECEIVE
:
5423 case S_CHECK_GETCALL
:
5424 case S_CHECK_GETREPLY
:
5429 str
= generate_code_standalone(str
);
5432 str
=generate_code_portop(str
, "clear");
5435 str
=generate_code_portop(str
, "start");
5438 str
=generate_code_portop(str
, "stop");
5441 str
=generate_code_portop(str
, "halt");
5444 str
=generate_code_startcomp(str
);
5446 case S_START_COMP_REFD
:
5447 str
=generate_code_startcomp_refd(str
);
5450 str
= generate_code_compop(str
, "stop");
5453 str
= generate_code_compop(str
, "kill");
5456 str
= generate_code_configop(str
, "connect");
5459 str
= generate_code_configop(str
, "map");
5462 str
= generate_code_configop(str
, "disconnect");
5465 str
= generate_code_configop(str
, "unmap");
5468 str
=generate_code_starttimer(str
);
5471 str
=generate_code_stoptimer(str
);
5474 str
=generate_code_setverdict(str
);
5477 str
=generate_code_action(str
);
5479 case S_TESTCASE_INSTANCE
:
5480 str
=generate_code_testcaseinst(str
);
5482 case S_TESTCASE_INSTANCE_REFD
:
5483 str
=generate_code_execute_refd(str
);
5486 str
=generate_code_string2ttcn(str
);
5488 case S_START_PROFILER
:
5489 str
= mputstr(str
, "ttcn3_prof.start();\n");
5491 case S_STOP_PROFILER
:
5492 str
= mputstr(str
, "ttcn3_prof.stop();\n");
5495 FATAL_ERROR("Statement::generate_code()");
5500 char* Statement::generate_code_string2ttcn(char *str
)
5502 expression_struct val_expr
;
5503 Code::init_expr(&val_expr
);
5504 str2ttcn
.val
->generate_code_expr(&val_expr
);
5506 expression_struct ref_expr
;
5507 Code::init_expr(&ref_expr
);
5508 str2ttcn
.ref
->generate_code(&ref_expr
);
5510 str
= mputstr(str
, val_expr
.preamble
);
5511 str
= mputstr(str
, ref_expr
.preamble
);
5513 str
= mputprintf(str
, "string_to_ttcn(%s,%s);\n", val_expr
.expr
, ref_expr
.expr
);
5515 str
= mputstr(str
, val_expr
.postamble
);
5516 str
= mputstr(str
, ref_expr
.postamble
);
5518 Code::free_expr(&val_expr
);
5519 Code::free_expr(&ref_expr
);
5524 void Statement::generate_code_expr(expression_struct
*expr
)
5526 switch (statementtype
) {
5528 generate_code_expr_receive(expr
, "receive");
5531 generate_code_expr_receive(expr
, "trigger");
5533 case S_CHECK_RECEIVE
:
5534 generate_code_expr_receive(expr
, "check_receive");
5537 generate_code_expr_getcall(expr
, "getcall");
5539 case S_CHECK_GETCALL
:
5540 generate_code_expr_getcall(expr
, "check_getcall");
5543 generate_code_expr_getreply(expr
, "getreply");
5545 case S_CHECK_GETREPLY
:
5546 generate_code_expr_getreply(expr
, "check_getreply");
5550 generate_code_expr_catch(expr
);
5553 generate_code_expr_check(expr
);
5556 generate_code_expr_done(expr
);
5559 generate_code_expr_killed(expr
);
5562 generate_code_expr_timeout(expr
);
5565 FATAL_ERROR("Statement::generate_code_expr()");
5569 void Statement::ilt_generate_code(ILT
*ilt
)
5571 switch (statementtype
) {
5573 ilt_generate_code_interleave(ilt
);
5576 ilt_generate_code_alt(ilt
);
5579 ilt_generate_code_def(ilt
);
5584 if (is_receiving_stmt()) {
5585 ilt_generate_code_receiving(ilt
);
5588 if (!has_receiving_stmt()) {
5589 char*& str
=ilt
->get_out_branches();
5590 str
=generate_code(str
);
5593 switch (statementtype
) {
5595 block
->ilt_generate_code(ilt
);
5598 ilt_generate_code_if(ilt
);
5601 ilt_generate_code_select(ilt
);
5604 ilt_generate_code_call(ilt
);
5607 ilt_generate_code_for(ilt
);
5610 ilt_generate_code_while(ilt
);
5613 ilt_generate_code_dowhile(ilt
);
5616 FATAL_ERROR("Statement::ilt_generate_code()");
5617 } // switch statementtype
5620 char *Statement::generate_code_standalone(char *str
)
5622 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5623 const char *label_str
= tmplabel
.c_str();
5624 str
= mputprintf(str
, "{\n"
5625 "%s:\n", label_str
);
5626 expression_struct expr
;
5627 Code::init_expr(&expr
);
5628 generate_code_expr(&expr
);
5629 str
= mputstr(str
, expr
.preamble
);
5630 str
= mputprintf(str
, "alt_status alt_flag = ALT_UNCHECKED, "
5631 "default_flag = ALT_UNCHECKED;\n"
5632 "TTCN_Snapshot::take_new(FALSE);\n"
5634 "if (alt_flag != ALT_NO) {\n"
5636 "if (alt_flag == ALT_YES) break;\n", expr
.expr
);
5638 str
= mputprintf(str
, "else if (alt_flag == ALT_REPEAT) goto %s;\n",
5641 str
= mputprintf(str
, "}\n"
5642 "if (default_flag != ALT_NO) {\n"
5643 "default_flag = TTCN_Default::try_altsteps();\n"
5644 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) break;\n"
5645 "else if (default_flag == ALT_REPEAT) goto %s;\n"
5647 str
= update_location_object(str
);
5648 str
= mputprintf(str
, "if (alt_flag == ALT_NO && default_flag == ALT_NO) "
5649 "TTCN_error(\"Stand-alone %s statement failed in file ", get_stmt_name());
5650 str
= Code::translate_string(str
, get_filename());
5651 int first_line
= get_first_line(), last_line
= get_last_line();
5652 if (first_line
< last_line
) str
= mputprintf(str
,
5653 " between lines %d and %d", first_line
, last_line
);
5654 else str
= mputprintf(str
, ", line %d", first_line
);
5655 str
= mputstr(str
, ".\");\n"
5656 "TTCN_Snapshot::take_new(TRUE);\n"
5658 str
= mputstr(str
, expr
.postamble
);
5659 str
= mputstr(str
, "}\n");
5660 Code::free_expr(&expr
);
5664 char *Statement::generate_code_funcinst(char *str
)
5666 expression_struct expr
;
5667 Code::init_expr(&expr
);
5668 ref_pard
->generate_code_const_ref(&expr
);
5669 str
=Code::merge_free_expr(str
, &expr
);
5673 char* Statement::generate_code_invoke(char *str
)
5675 expression_struct expr
;
5676 Code::init_expr(&expr
);
5677 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
5678 switch(last_v
->get_valuetype()) {
5679 case Value::V_FUNCTION
:
5680 case Value::V_ALTSTEP
: {
5681 Common::Assignment
*t_fat
= last_v
->get_refd_fat();
5682 expr
.expr
= mputprintf(expr
.expr
, "%s(",
5683 t_fat
->get_genname_from_scope(my_sb
).c_str());
5684 fau_refd
.ap_list2
->generate_code_alias(&expr
, t_fat
->get_FormalParList(),
5685 t_fat
->get_RunsOnType(), false);
5688 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
5689 Type
*t_governor
= fau_refd
.value
->get_expr_governor_last();
5690 expr
.expr
= mputprintf(expr
.expr
, ".%s(",
5691 t_governor
->get_typetype() == Type::T_ALTSTEP
?
5692 "invoke_standalone" : "invoke");
5693 fau_refd
.ap_list2
->generate_code_alias(&expr
, 0,
5694 t_governor
->get_fat_runs_on_type(),
5695 t_governor
->get_fat_runs_on_self()); }
5697 expr
.expr
= mputc(expr
.expr
, ')');
5698 str
=Code::merge_free_expr(str
, &expr
);
5702 char *Statement::generate_code_block(char *str
)
5704 switch (block
->get_exception_handling()) {
5705 case StatementBlock::EH_NONE
:
5707 case StatementBlock::EH_TRY
:
5708 str
= mputstr(str
, "try ");
5710 case StatementBlock::EH_CATCH
:
5711 str
= mputstr(str
, "catch (const TTCN_Error& ttcn_error) ");
5714 FATAL_ERROR("Statement::generate_code_block()");
5716 if (block
->get_nof_stmts() > 0 || block
->get_exception_handling()!=StatementBlock::EH_NONE
) {
5717 str
= mputstr(str
, "{\n");
5718 str
= block
->generate_code(str
);
5719 str
= mputstr(str
, "}\n");
5720 } else str
= mputstr(str
, "/* empty block */;\n");
5724 char *Statement::generate_code_log(char *str
)
5727 bool buffered_mode
= true;
5728 if (logargs
->get_nof_logargs() == 1) {
5729 LogArgument
*first_logarg
= logargs
->get_logarg_byIndex(0);
5730 switch (first_logarg
->get_type()) {
5731 case LogArgument::L_STR
:
5732 // the argument is a simple string: use non-buffered mode
5733 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, \"");
5734 str
= Code::translate_string(str
, first_logarg
->get_str().c_str());
5735 str
= mputstr(str
, "\");\n");
5736 buffered_mode
= false;
5738 case LogArgument::L_MACRO
: {
5739 Value
*t_val
= first_logarg
->get_val();
5740 if (t_val
->has_single_expr()) {
5741 // the argument is a simple macro call: use non-buffered mode
5742 str
= mputprintf(str
, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5743 t_val
->get_single_expr().c_str());
5744 buffered_mode
= false;
5750 if (buffered_mode
) {
5751 // the argument is a complicated construct: use buffered mode
5752 str
= mputstr(str
, "try {\n"
5753 "TTCN_Logger::begin_event(TTCN_USER);\n");
5754 str
= logargs
->generate_code(str
);
5755 str
= mputstr(str
, "TTCN_Logger::end_event();\n"
5757 "TTCN_Logger::finish_event();\n"
5762 // the argument is missing
5763 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, "
5764 "\"<empty log statement>\");\n");
5769 char *Statement::generate_code_testcase_stop(char *str
)
5771 if (logargs
) str
= generate_code_log(str
);
5772 str
= mputstr(str
, "TTCN_error(\"testcase.stop\");\n");
5776 char *Statement::generate_code_label(char *str
)
5779 return mputprintf(str
, "%s: /* TTCN-3 label: %s */;\n",
5780 get_clabel().c_str(), label
.id
->get_dispname().c_str());
5782 return mputprintf(str
, "/* unused TTCN-3 label: %s */;\n",
5783 label
.id
->get_dispname().c_str());
5787 char *Statement::generate_code_goto(char *str
)
5789 if (!go_to
.label
) FATAL_ERROR("Statement::generate_code_goto()");
5790 return mputprintf(str
, "goto %s; /* TTCN-3 label: %s */\n",
5791 go_to
.label
->get_clabel().c_str(), go_to
.id
->get_dispname().c_str());
5795 char* Statement::generate_code_if(char *str
)
5797 size_t blockcount
=0;
5798 bool unreach
=false, eachfalse
=true;
5799 str
=if_stmt
.ics
->generate_code(str
, blockcount
, unreach
, eachfalse
);
5800 if(if_stmt
.elseblock
&& !unreach
) {
5801 if(!eachfalse
) str
=mputstr(str
, "else ");
5803 str
=mputstr(str
, "{\n");
5805 str
=if_stmt
.elseblock
->generate_code(str
);
5807 while(blockcount
-->0) str
=mputstr(str
, "}\n");
5808 if(eachfalse
) str
=mputstr(str
, "/* never occurs */;\n");
5812 char* Statement::generate_code_select(char *str
)
5814 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5815 char *expr_init
=memptystr();
5816 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
5817 if (expr_init
[0]) { // some init code was generated
5818 str
= update_location_object(str
);
5819 str
= mputstr(str
, "{\n");
5820 str
= mputstr(str
, expr_init
);
5822 str
=select
.scs
->generate_code(str
, tmp_prefix
.c_str(), expr_name
);
5824 if (expr_init
[0]) str
=mputstr(str
, "}\n");
5829 char *Statement::generate_code_for(char *str
)
5831 /** \todo initial does not have its own location */
5832 // statements in initial may have side effects
5833 // generate code for them anyway
5834 if (loop
.for_stmt
.varinst
) {
5835 str
= mputstr(str
, "{\n");
5836 str
= loop
.for_stmt
.init_varinst
->generate_code_str(str
);
5838 str
= loop
.for_stmt
.init_ass
->update_location_object(str
);
5839 str
= loop
.for_stmt
.init_ass
->generate_code(str
);
5841 // check whether the final expression is constant
5842 bool final_is_true
= false, final_is_false
= false;
5843 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
5844 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
5845 else final_is_false
= true;
5847 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
5851 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5852 str
= update_location_object(str
);
5853 str
= mputstr(str
, "for ( ; ; ) {\n");
5854 // do not generate the exit condition for infinite loops
5855 if (!final_is_true
) {
5856 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
5857 size_t blockcount
= 0;
5858 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
5860 str
= mputstr(str
, ") break;\n");
5861 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5863 if (loop
.label_next
) str
= mputstr(str
, "{\n");
5864 str
= loop
.block
->generate_code(str
);
5865 if (loop
.label_next
)
5866 str
= mputprintf(str
, "}\n"
5867 "%s:\n", loop
.label_next
->c_str());
5868 str
= loop
.for_stmt
.step
->update_location_object(str
);
5869 str
= loop
.for_stmt
.step
->generate_code(str
);
5870 str
= mputstr(str
, "}\n");
5872 if (loop
.for_stmt
.varinst
) str
= mputstr(str
, "}\n");
5876 char *Statement::generate_code_while(char *str
)
5878 // check whether the expression is constant
5879 bool condition_always_true
= false, condition_always_false
= false;
5880 if (!loop
.expr
->is_unfoldable()) {
5881 if (loop
.expr
->get_val_bool()) condition_always_true
= true;
5882 else condition_always_false
= true;
5884 if (condition_always_false
) str
= mputstr(str
, "/* never occurs */;\n");
5886 str
= mputstr(str
, "for ( ; ; ) {\n");
5887 if (loop
.has_cnt_in_ags
) {
5889 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5890 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5892 // do not generate the exit condition for infinite loops
5893 if (!condition_always_true
) {
5894 str
= loop
.expr
->update_location_object(str
);
5895 size_t blockcount
= 0;
5896 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5897 str
= mputstr(str
, ") break;\n");
5898 while(blockcount
-- > 0) str
= mputstr(str
, "}\n");
5900 str
= loop
.block
->generate_code(str
);
5901 str
= mputstr(str
, "}\n");
5906 char *Statement::generate_code_dowhile(char *str
)
5908 // check whether the expression is constant
5909 bool expr_is_const
= !loop
.expr
->is_unfoldable();
5910 bool is_infinite_loop
= false;
5911 if (expr_is_const
) {
5912 if (loop
.expr
->get_val_bool()) is_infinite_loop
= true;
5913 else loop
.iterate_once
= true;
5915 if (loop
.iterate_once
&& !loop
.has_brk
&& !loop
.has_cnt
) {
5916 str
= mputstr(str
, "{\n");
5917 str
= loop
.block
->generate_code(str
);
5919 str
= mputstr(str
, "for ( ; ; ) {\n");
5920 if (loop
.has_cnt_in_ags
|| (!expr_is_const
&& loop
.has_cnt
))
5922 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5923 if (loop
.label_next
&& is_infinite_loop
)
5924 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5925 if (loop
.label_next
&& !is_infinite_loop
) str
= mputstr(str
, "{\n");
5926 str
= loop
.block
->generate_code(str
);
5927 // do not generate the exit condition for infinite loops
5928 if (!is_infinite_loop
) {
5929 if (loop
.label_next
)
5930 str
= mputprintf(str
, "}\n"
5931 "%s:\n", loop
.label_next
->c_str());
5932 str
= loop
.expr
->update_location_object(str
);
5933 if (loop
.iterate_once
) str
= mputstr(str
, "break;\n");
5935 size_t blockcount
= 0;
5936 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5937 str
= mputstr(str
, ") break;\n");
5938 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5942 str
= mputstr(str
, "}\n");
5946 char *Statement::generate_code_break(char *str
)
5948 // in altstep (2 (=2nd if branch))
5949 // in alt and loops - not inside interleave (4)
5950 // in loops without receiving statement embedded in interleave (4)
5951 // in loops with receiving statement embedded in interleave (1)
5952 // in interleave when not embedded in enclosed loop or alt/interleave (4)
5953 // in alt/interleave embedded in interleave (3)
5954 if (brk_cnt
.loop_stmt
&& brk_cnt
.loop_stmt
->loop
.il_label_end
)
5955 str
=mputprintf(str
, "goto %s;\n",
5956 brk_cnt
.loop_stmt
->loop
.il_label_end
->c_str());
5957 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_is_altstep())
5958 str
=mputstr(str
, "return ALT_BREAK;\n");
5959 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_il_label_end())
5960 str
=mputprintf(str
, "goto %s;\n",
5961 brk_cnt
.ags
->get_il_label_end()->c_str());
5963 str
=mputstr(str
, "break;\n");
5967 char *Statement::generate_code_continue(char *str
)
5969 // not inside interleave when continue is not inside embedded ags (2 or 1)
5970 // continue is inside ags enclosed in the loop (3)
5971 // in interleave (3, 2 or 1)
5972 if (brk_cnt
.loop_stmt
!= 0) {
5973 if (brk_cnt
.loop_stmt
->loop
.iterate_once
&& !brk_cnt
.ags
&&
5974 !brk_cnt
.loop_stmt
->loop
.is_ilt
)
5975 str
=mputstr(str
, "break;\n");
5977 if (!brk_cnt
.loop_stmt
->loop
.label_next
)
5978 str
=mputstr(str
, "continue;\n");
5980 str
=mputprintf(str
, "goto %s;\n",
5981 brk_cnt
.loop_stmt
->loop
.label_next
->c_str());
5984 FATAL_ERROR("Statement::generate_code_continue()");
5988 char *Statement::generate_code_repeat(char *str
)
5990 string
*tmplabel
=ags
->get_label();
5991 if(!tmplabel
) str
=mputstr(str
, "return ALT_REPEAT;\n");
5992 else str
=mputprintf(str
, "goto %s;\n", tmplabel
->c_str());
5996 char* Statement::generate_code_interleave(char *str
)
5999 str
=ilt
.generate_code(str
);
6003 void Statement::ilt_generate_code_interleave(ILT
*ilt
)
6005 const string
& mytmpid
=ilt
->get_my_tmpid();
6006 bool toplevel
=ilt
->is_toplevel();
6007 size_t goto_label_num
=toplevel
?(size_t)-1:ilt
->get_new_label_num();
6008 char*& out_branches
=ilt
->get_out_branches();
6009 out_branches
=update_location_object(out_branches
);
6011 if(toplevel
) state_cond
="";
6013 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6014 (unsigned long) goto_label_num
);
6015 ags
->set_il_label_end (label_end
);
6017 ILT_branch
*branch
=ilt
->get_as_branch();
6018 size_t state_var
=branch
->get_my_state_var();
6019 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6020 state_cond
=branch
->get_state_cond();
6021 if(!state_cond
.empty()) state_cond
+=" && ";
6022 char *s
=mprintf("%s_state[%lu]==%lu", mytmpid
.c_str(),
6023 (unsigned long) state_var
, (unsigned long) state_var_val
);
6026 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6028 (unsigned long) state_var
, (unsigned long) state_var_val
);
6030 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6031 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6032 if(ag
->get_type()!=AltGuard::AG_OP
)
6033 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6034 size_t state_var
=ilt
->get_new_state_var(toplevel
);
6035 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6036 ilt
->add_branch(new ILT_branch(ILT_branch::BT_IL
, ag
, state_cond
,
6037 state_var
, state_var_val
,
6040 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6042 (unsigned long) state_var
, (unsigned long) state_var_val
);
6045 out_branches
=mputprintf(out_branches
, "goto %s;\n"
6048 mytmpid
.c_str(), (unsigned long) goto_label_num
);
6051 void Statement::ilt_generate_code_alt(ILT
*ilt
)
6053 const string
& mytmpid
=ilt
->get_my_tmpid();
6054 size_t goto_label_num
=ilt
->get_new_label_num();
6055 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6056 (unsigned long) goto_label_num
);
6057 ags
->set_il_label_end (label_end
);
6058 ILT_branch
*branch
=ilt
->get_as_branch();
6059 string state_cond
=branch
->get_state_cond();
6060 size_t state_var
=branch
->get_my_state_var();
6061 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6062 char*& out_branches
=ilt
->get_out_branches();
6063 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6064 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6065 if(ag
->get_type()!=AltGuard::AG_OP
)
6066 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6067 ilt
->add_branch(new ILT_branch(ILT_branch::BT_ALT
, ag
, state_cond
,
6068 state_var
, state_var_val
,
6071 out_branches
=update_location_object(out_branches
);
6072 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6075 mytmpid
.c_str(), (unsigned long) state_var
,
6076 (unsigned long) state_var_val
,
6077 mytmpid
.c_str(), label_end
);
6081 void Statement::ilt_generate_code_receiving(ILT
*ilt
)
6083 const string
& mytmpid
=ilt
->get_my_tmpid();
6084 size_t goto_label_num
=ilt
->get_new_label_num();
6085 ILT_branch
*branch
=ilt
->get_as_branch();
6086 string state_cond
=branch
->get_state_cond();
6087 size_t state_var
=branch
->get_my_state_var();
6088 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6089 char*& out_branches
=ilt
->get_out_branches();
6090 ilt
->add_branch(new ILT_branch(ILT_branch::BT_RECV
, this, state_cond
,
6091 state_var
, state_var_val
, goto_label_num
));
6092 out_branches
=update_location_object(out_branches
);
6093 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6096 mytmpid
.c_str(), (unsigned long) state_var
,
6097 (unsigned long) state_var_val
,
6098 mytmpid
.c_str(), mytmpid
.c_str(),
6099 (unsigned long) goto_label_num
);
6102 void Statement::ilt_generate_code_def(ILT
*ilt
)
6104 char*& str
=ilt
->get_out_branches();
6105 str
=update_location_object(str
);
6107 char *genname
=mprintf("%s_d%lu_%s", ilt
->get_my_tmpid().c_str(),
6108 (unsigned long) ilt
->get_new_tmpnum(),
6109 def
->get_id().get_name().c_str());
6110 def
->set_genname(string(genname
));
6113 def
->ilt_generate_code(ilt
);
6116 void Statement::ilt_generate_code_if(ILT
*ilt
)
6118 char *end_label
=mprintf("%s_l%lu",
6119 ilt
->get_my_tmpid().c_str(),
6120 (unsigned long) ilt
->get_new_label_num());
6122 if_stmt
.ics
->ilt_generate_code(ilt
, end_label
, unreach
);
6123 if(if_stmt
.elseblock
&& !unreach
)
6124 if_stmt
.elseblock
->ilt_generate_code(ilt
);
6125 char*& str
=ilt
->get_out_branches();
6126 str
=mputprintf(str
, "%s:\n", end_label
);
6130 void Statement::ilt_generate_code_select(ILT
*ilt
)
6132 char*& str
=ilt
->get_out_branches();
6133 str
=update_location_object(str
);
6134 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6135 char *expr_init
=memptystr();
6136 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
6137 select
.scs
->ilt_generate_code(ilt
, tmp_prefix
.c_str(),
6138 expr_init
, expr_name
);
6143 void Statement::ilt_generate_code_call(ILT
*ilt
)
6145 char*& str
=ilt
->get_out_branches();
6146 str
=update_location_object(str
);
6147 expression_struct expr
;
6148 Code::init_expr(&expr
);
6149 port_op
.portref
->generate_code(&expr
);
6150 expr
.expr
= mputstr(expr
.expr
, ".call(");
6151 port_op
.s
.sendpar
->generate_code(&expr
);
6152 if(port_op
.s
.toclause
) {
6153 expr
.expr
= mputstr(expr
.expr
, ", ");
6154 port_op
.s
.toclause
->generate_code_expr(&expr
);
6156 expr
.expr
= mputc(expr
.expr
, ')');
6157 str
= Code::merge_free_expr(str
, &expr
);
6158 if (port_op
.s
.call
.body
) {
6159 str
= mputstr(str
, "{\n"); // (1)
6160 if (port_op
.s
.call
.timer
) {
6161 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6162 str
= mputstr(str
, "TIMER call_timer;\n");
6163 Code::init_expr(&expr
);
6164 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6165 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6166 expr
.expr
= mputc(expr
.expr
, ')');
6167 str
= Code::merge_free_expr(str
, &expr
);
6169 // the label name is used for prefixing local variables
6170 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6171 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6172 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this, tmplabel
,
6174 const char *label_str
= tmplabel
.c_str();
6175 str
=mputprintf(str
, "goto %s_end;\n"
6178 port_op
.s
.call
.body
->ilt_generate_code_call_body(ilt
, label_str
);
6179 str
=mputprintf(str
, "%s_end:\n", label_str
);
6183 void Statement::ilt_generate_code_for(ILT
*ilt
)
6185 char*& str
= ilt
->get_out_branches();
6186 str
= update_location_object(str
);
6187 // statements in initial may have side effects
6188 // generate code for them anyway
6189 if (loop
.for_stmt
.varinst
) {
6190 char *genname
= mprintf("%s_d%lu_", ilt
->get_my_tmpid().c_str(),
6191 (unsigned long) ilt
->get_new_tmpnum());
6192 loop
.for_stmt
.init_varinst
->set_genname(string(genname
));
6194 loop
.for_stmt
.init_varinst
->ilt_generate_code(ilt
);
6195 } else str
= loop
.for_stmt
.init_ass
->generate_code(str
);
6196 // check whether the final expression is constant
6197 bool final_is_true
= false, final_is_false
= false;
6198 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
6199 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
6200 else final_is_false
= true;
6202 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6204 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6205 (unsigned long) ilt
->get_new_label_num());
6206 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6207 // do not generate the exit condition for infinite loops
6208 if (!final_is_true
) {
6209 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
6210 size_t blockcount
= 0;
6211 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
6213 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6214 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6218 loop
.il_label_end
= new string(label_prefix
);
6219 *loop
.il_label_end
+= "end";
6222 loop
.label_next
= new string(label_prefix
);
6223 *loop
.label_next
+= "next";
6225 loop
.block
->ilt_generate_code(ilt
);
6226 if (loop
.label_next
)
6227 str
= mputprintf(str
, "%snext:\n", label_prefix
);
6228 str
= update_location_object(str
);
6229 str
= loop
.for_stmt
.step
->generate_code(str
);
6230 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6231 if (!final_is_true
|| loop
.has_brk
)
6232 str
= mputprintf(str
, "%send:\n", label_prefix
);
6237 void Statement::ilt_generate_code_while(ILT
*ilt
)
6239 char*& str
= ilt
->get_out_branches();
6240 // Location need not be set here; the location is set for the expression.
6241 // check whether the expression is constant
6242 bool expr_is_true
= false, expr_is_false
= false;
6243 if (!loop
.expr
->is_unfoldable()) {
6244 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6245 else expr_is_false
= true;
6247 if (expr_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6249 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6250 (unsigned long) ilt
->get_new_label_num());
6251 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6254 loop
.il_label_end
= new string(label_prefix
);
6255 *loop
.il_label_end
+= "end";
6258 loop
.label_next
= new string(label_prefix
);
6259 *loop
.label_next
+= "begin";
6261 // do not generate the exit condition for infinite loops
6262 if (!expr_is_true
) {
6263 str
= loop
.expr
->update_location_object(str
);
6264 size_t blockcount
= 0;
6265 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6266 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6267 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6269 loop
.block
->ilt_generate_code(ilt
);
6270 str
= update_location_object(str
);
6271 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6272 if (!expr_is_true
|| loop
.has_brk
)
6273 str
= mputprintf(str
, "%send:\n", label_prefix
);
6278 void Statement::ilt_generate_code_dowhile(ILT
*ilt
)
6280 char*& str
= ilt
->get_out_branches();
6281 // Location need not be set here; there is only a label before the body.
6282 // check whether the expression is constant
6283 bool expr_is_true
= false;
6284 if (!loop
.expr
->is_unfoldable()) {
6285 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6286 else loop
.iterate_once
= true;
6288 char *label_prefix
= 0;
6289 if (!loop
.iterate_once
|| loop
.has_brk
|| loop
.has_cnt
)
6290 label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6291 (unsigned long) ilt
->get_new_label_num());
6294 loop
.il_label_end
= new string(label_prefix
);
6295 *loop
.il_label_end
+= "end";
6298 loop
.label_next
= new string(label_prefix
);
6299 if (loop
.iterate_once
) {
6300 if (loop
.label_next
) *loop
.label_next
+= "end";
6301 loop
.block
->ilt_generate_code(ilt
);
6303 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6304 if (loop
.label_next
)
6305 *loop
.label_next
+= (expr_is_true
? "begin" : "next");
6306 loop
.block
->ilt_generate_code(ilt
);
6307 if (expr_is_true
) str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6309 if (loop
.label_next
) str
= mputprintf(str
, "%snext:\n", label_prefix
);
6310 str
= loop
.expr
->update_location_object(str
);
6311 size_t blockcount
= 0;
6312 str
= loop
.expr
->generate_code_tmp(str
, "if (", blockcount
);
6313 str
= mputprintf(str
, ") goto %sbegin;\n", label_prefix
);
6314 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6317 if (loop
.il_label_end
|| (loop
.iterate_once
&& loop
.label_next
)) {
6318 str
= mputprintf(str
, "%send: ;\n", label_prefix
);
6323 char *Statement::generate_code_return(char *str
)
6325 expression_struct expr
;
6326 Code::init_expr(&expr
);
6327 expr
.expr
= mputstr(expr
.expr
, "return");
6328 Definition
*my_def
= my_sb
->get_my_def();
6330 expr
.expr
= mputc(expr
.expr
, ' ');
6331 returnexpr
.v
->generate_code_expr_mandatory(&expr
);
6332 } else if (returnexpr
.t
) {
6333 expr
.expr
= mputc(expr
.expr
, ' ');
6334 if (!my_def
) FATAL_ERROR("Statement::generate_code_return()");
6335 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
6336 if (!dfb
) FATAL_ERROR("Statement::generate_code_return()");
6337 if (dfb
->get_template_restriction() != TR_NONE
&&
6338 returnexpr
.gen_restriction_check
) {
6339 returnexpr
.t
->generate_code_expr(&expr
,
6340 dfb
->get_template_restriction());
6342 returnexpr
.t
->generate_code_expr(&expr
, TR_NONE
);
6345 if (my_def
&& my_def
->get_asstype() == Definition::A_ALTSTEP
)
6346 expr
.expr
= mputstr(expr
.expr
, " ALT_YES");
6347 // else it's a return with no value: the only case a blank is unneeded
6349 return Code::merge_free_expr(str
, &expr
);
6352 char *Statement::generate_code_activate(char *str
)
6354 expression_struct expr
;
6355 Code::init_expr(&expr
);
6356 expr
.expr
= mputprintf(expr
.expr
, "%s(", ref_pard
->get_refd_assignment()
6357 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6358 ref_pard
->get_parlist()->generate_code_noalias(&expr
, ref_pard
->get_refd_assignment()->get_FormalParList());
6359 expr
.expr
= mputc(expr
.expr
, ')');
6360 return Code::merge_free_expr(str
, &expr
);
6363 char *Statement::generate_code_activate_refd(char *str
)
6365 expression_struct expr
;
6366 Code::init_expr(&expr
);
6367 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6368 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
6369 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6370 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6372 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
6373 expr
.expr
= mputstr(expr
.expr
, ".activate(");
6375 fau_refd
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6376 expr
.expr
= mputc(expr
.expr
, ')');
6377 return Code::merge_free_expr(str
, &expr
);
6380 char *Statement::generate_code_deactivate(char *str
)
6382 if(!deactivate
) str
=mputstr(str
, "TTCN_Default::deactivate_all();\n");
6384 expression_struct expr
;
6385 Code::init_expr(&expr
);
6386 expr
.expr
=mputstr(expr
.expr
, "TTCN_Default::deactivate(");
6387 deactivate
->generate_code_expr(&expr
);
6388 expr
.expr
=mputstr(expr
.expr
, ");\n");
6389 str
=Code::merge_free_expr(str
, &expr
);
6394 char *Statement::generate_code_send(char *str
)
6396 expression_struct expr
;
6397 Code::init_expr(&expr
);
6398 port_op
.portref
->generate_code(&expr
);
6399 expr
.expr
= mputstr(expr
.expr
, ".send(");
6400 generate_code_expr_sendpar(&expr
);
6401 if (port_op
.s
.toclause
) {
6402 expr
.expr
= mputstr(expr
.expr
, ", ");
6403 port_op
.s
.toclause
->generate_code_expr(&expr
);
6405 expr
.expr
= mputc(expr
.expr
, ')');
6406 return Code::merge_free_expr(str
, &expr
);
6409 char *Statement::generate_code_call(char *str
)
6411 expression_struct expr
;
6412 Code::init_expr(&expr
);
6413 port_op
.portref
->generate_code(&expr
);
6414 expr
.expr
= mputstr(expr
.expr
, ".call(");
6415 port_op
.s
.sendpar
->generate_code(&expr
);
6416 if(port_op
.s
.toclause
) {
6417 expr
.expr
= mputstr(expr
.expr
, ", ");
6418 port_op
.s
.toclause
->generate_code_expr(&expr
);
6420 expr
.expr
= mputc(expr
.expr
, ')');
6421 str
= Code::merge_free_expr(str
, &expr
);
6422 if (port_op
.s
.call
.body
) {
6423 str
= mputstr(str
, "{\n");
6424 if (port_op
.s
.call
.timer
) {
6425 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6426 str
= mputstr(str
, "TIMER call_timer;\n");
6427 Code::init_expr(&expr
);
6428 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6429 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6430 expr
.expr
= mputc(expr
.expr
, ')');
6431 str
= Code::merge_free_expr(str
, &expr
);
6433 // the label name is used for prefixing local variables
6434 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6435 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this,
6436 my_sb
->get_scope_mod_gen()->get_temporary_id(), false);
6437 str
=mputstr(str
, "}\n");
6442 char *Statement::generate_code_reply(char *str
)
6444 expression_struct expr
;
6445 Code::init_expr(&expr
);
6446 port_op
.portref
->generate_code(&expr
);
6447 expr
.expr
=mputstr(expr
.expr
, ".reply(");
6448 port_op
.s
.sendpar
->generate_code(&expr
);
6449 if(port_op
.s
.replyval
) {
6450 expr
.expr
=mputstr(expr
.expr
, ".set_value_template(");
6451 port_op
.s
.replyval
->generate_code_expr(&expr
);
6452 expr
.expr
=mputc(expr
.expr
, ')');
6454 if(port_op
.s
.toclause
) {
6455 expr
.expr
=mputstr(expr
.expr
, ", ");
6456 port_op
.s
.toclause
->generate_code_expr(&expr
);
6458 expr
.expr
=mputc(expr
.expr
, ')');
6459 return Code::merge_free_expr(str
, &expr
);
6462 char *Statement::generate_code_raise(char *str
)
6464 expression_struct expr
;
6465 Code::init_expr(&expr
);
6466 port_op
.portref
->generate_code(&expr
);
6467 expr
.expr
=mputstr(expr
.expr
, ".raise(");
6468 port_op
.s
.raise
.signature_ref
->generate_code(&expr
);
6469 expr
.expr
=mputstr(expr
.expr
, "_exception(");
6470 generate_code_expr_sendpar(&expr
);
6471 expr
.expr
=mputc(expr
.expr
, ')');
6472 if(port_op
.s
.toclause
) {
6473 expr
.expr
=mputstr(expr
.expr
, ", ");
6474 port_op
.s
.toclause
->generate_code_expr(&expr
);
6476 expr
.expr
=mputc(expr
.expr
, ')');
6477 return Code::merge_free_expr(str
, &expr
);
6480 char *Statement::generate_code_portop(char *str
, const char *opname
)
6482 if (port_op
.portref
) {
6483 expression_struct expr
;
6484 Code::init_expr(&expr
);
6485 port_op
.portref
->generate_code(&expr
);
6486 expr
.expr
=mputprintf(expr
.expr
, ".%s()", opname
);
6487 str
=Code::merge_free_expr(str
, &expr
);
6489 str
= mputprintf(str
, "PORT::all_%s();\n", opname
);
6494 char *Statement::generate_code_startcomp(char *str
)
6496 expression_struct expr
;
6497 Code::init_expr(&expr
);
6498 Common::Assignment
*func
= comp_op
.funcinstref
->get_refd_assignment();
6499 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6500 func
->get_genname_from_scope(my_sb
, "start_").c_str());
6501 comp_op
.compref
->generate_code_expr(&expr
);
6502 FormalParList
*fplist
= func
->get_FormalParList();
6503 if (fplist
->get_nof_fps() > 0) {
6504 expr
.expr
= mputstr(expr
.expr
, ", ");
6505 comp_op
.funcinstref
->get_parlist()->generate_code_noalias(&expr
, fplist
);
6507 expr
.expr
= mputc(expr
.expr
, ')');
6508 return Code::merge_free_expr(str
, &expr
);
6511 char *Statement::generate_code_startcomp_refd(char *str
)
6513 expression_struct expr
;
6514 Code::init_expr(&expr
);
6515 Value
*last_v
= comp_op
.derefered
.value
->get_value_refd_last();
6516 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
6517 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6518 ->get_genname_from_scope(my_sb
, "start_").c_str());
6520 comp_op
.derefered
.value
->generate_code_expr_mandatory(&expr
);
6521 expr
.expr
= mputstr(expr
.expr
, ".start(");
6523 comp_op
.compref
->generate_code_expr(&expr
);
6524 if (comp_op
.derefered
.ap_list2
->get_nof_pars() > 0) {
6525 expr
.expr
= mputstr(expr
.expr
, ", ");
6526 comp_op
.derefered
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6528 expr
.expr
= mputc(expr
.expr
, ')');
6529 return Code::merge_free_expr(str
, &expr
);
6532 char *Statement::generate_code_compop(char *str
, const char *opname
)
6534 expression_struct expr
;
6535 Code::init_expr(&expr
);
6536 if (comp_op
.compref
) {
6537 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
6538 if (v_last
->get_valuetype() == Value::V_REFD
) {
6539 // the argument is a simple component reference
6540 v_last
->generate_code_expr_mandatory(&expr
);
6541 expr
.expr
= mputprintf(expr
.expr
, ".%s()", opname
);
6543 bool refers_to_self
= false;
6544 if (v_last
->get_valuetype() == Value::V_EXPR
) {
6545 // the argument is a special component reference (mtc, self, etc.)
6546 switch (v_last
->get_optype()) {
6547 case Value::OPTYPE_COMP_MTC
: {
6548 Definition
*my_def
= my_sb
->get_my_def();
6549 if (my_def
&& my_def
->get_asstype() == Definition::A_TESTCASE
)
6550 refers_to_self
= true;
6552 case Value::OPTYPE_COMP_SELF
:
6553 refers_to_self
= true;
6558 if (refers_to_self
) {
6559 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_execution()",
6562 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_component(",
6564 v_last
->generate_code_expr(&expr
);
6565 expr
.expr
= mputc(expr
.expr
, ')');
6569 // the operation refers to all component
6570 expr
.expr
= mputprintf(expr
.expr
,
6571 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname
);
6573 return Code::merge_free_expr(str
, &expr
);
6576 char *Statement::generate_code_configop(char *str
, const char *opname
)
6578 expression_struct expr
;
6579 Code::init_expr(&expr
);
6580 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_port(", opname
);
6581 config_op
.compref1
->generate_code_expr(&expr
);
6582 expr
.expr
= mputstr(expr
.expr
, ", ");
6583 if (config_op
.compref1
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6584 // the component type is known
6585 // the name of the referred port can be used
6586 config_op
.portref1
->generate_code_portref(&expr
, my_sb
);
6587 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6589 // the component type is unknown
6590 // a simple string shall be formed from the port name and array indices
6591 generate_code_portref(&expr
, config_op
.portref1
);
6593 expr
.expr
= mputstr(expr
.expr
, ", ");
6594 config_op
.compref2
->generate_code_expr(&expr
);
6595 expr
.expr
= mputstr(expr
.expr
, ", ");
6596 if (config_op
.compref2
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6597 // the component type is known
6598 // the name of the referred port can be used
6599 config_op
.portref2
->generate_code_portref(&expr
, my_sb
);
6600 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6602 // the component type is unknown
6603 // a simple string shall be formed from the port name and array indices
6604 generate_code_portref(&expr
, config_op
.portref2
);
6606 expr
.expr
= mputc(expr
.expr
, ')');
6607 return Code::merge_free_expr(str
, &expr
);
6610 char *Statement::generate_code_starttimer(char *str
)
6612 expression_struct expr
;
6613 Code::init_expr(&expr
);
6614 timer_op
.timerref
->generate_code(&expr
);
6615 expr
.expr
=mputstr(expr
.expr
, ".start(");
6616 if(timer_op
.value
) timer_op
.value
->generate_code_expr(&expr
);
6617 expr
.expr
=mputc(expr
.expr
, ')');
6618 str
=Code::merge_free_expr(str
, &expr
);
6622 char *Statement::generate_code_stoptimer(char *str
)
6624 if(!timer_op
.timerref
) str
=mputstr(str
, "TIMER::all_stop();\n");
6626 expression_struct expr
;
6627 Code::init_expr(&expr
);
6628 timer_op
.timerref
->generate_code(&expr
);
6629 expr
.expr
=mputstr(expr
.expr
, ".stop()");
6630 str
=Code::merge_free_expr(str
, &expr
);
6635 char *Statement::generate_code_setverdict(char *str
)
6637 expression_struct expr
;
6638 Code::init_expr(&expr
);
6639 expr
.expr
=mputstr(expr
.expr
, "TTCN_Runtime::setverdict(");
6640 setverdict
.verdictval
->generate_code_expr(&expr
);
6641 if (setverdict
.logargs
) {
6642 expr
.expr
=mputc(expr
.expr
, ',');
6643 expression_struct expr_reason
;
6644 Code::init_expr(&expr_reason
);
6645 setverdict
.logargs
->generate_code_expr(&expr_reason
);
6646 if (expr_reason
.preamble
)
6647 expr
.preamble
= mputprintf(expr
.preamble
, "%s;\n",
6648 expr_reason
.preamble
);
6649 if (expr_reason
.postamble
)
6650 expr
.postamble
= mputprintf(expr
.postamble
, "%s;\n",
6651 expr_reason
.postamble
);
6652 expr
.expr
= mputprintf(expr
.expr
, "%s", expr_reason
.expr
);
6653 Code::free_expr(&expr_reason
);
6655 expr
.expr
=mputc(expr
.expr
, ')');
6656 str
=Code::merge_free_expr(str
, &expr
);
6660 char *Statement::generate_code_action(char *str
)
6662 str
=mputstr(str
, "TTCN_Runtime::begin_action();\n");
6663 if(!logargs
) str
=mputstr(str
, "TTCN_Logger::log_event_str"
6664 "(\"<empty action statement>\");\n");
6665 else str
=logargs
->generate_code(str
);
6666 str
=mputstr(str
, "TTCN_Runtime::end_action();\n");
6670 char *Statement::generate_code_testcaseinst(char *str
)
6672 expression_struct expr
;
6673 Code::init_expr(&expr
);
6674 Common::Assignment
*testcase
= testcase_inst
.tcref
->get_refd_assignment();
6675 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6676 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6677 ActualParList
*t_aplist
= testcase_inst
.tcref
->get_parlist();
6678 if (t_aplist
->get_nof_pars() > 0) {
6679 t_aplist
->generate_code_alias(&expr
, testcase
->get_FormalParList(),
6681 expr
.expr
= mputstr(expr
.expr
, ", ");
6683 if (testcase_inst
.timerval
) {
6684 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6685 testcase_inst
.timerval
->generate_code_expr(&expr
);
6686 expr
.expr
= mputc(expr
.expr
, ')');
6687 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6688 return Code::merge_free_expr(str
, &expr
);
6691 char *Statement::generate_code_execute_refd(char *str
)
6693 expression_struct expr
;
6694 Code::init_expr(&expr
);
6695 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6696 if (last_v
->get_valuetype() == Value::V_TESTCASE
) {
6697 Common::Assignment
*testcase
= last_v
->get_refd_fat();
6698 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6699 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6700 execute_refd
.ap_list2
->generate_code_alias(&expr
,
6701 testcase
->get_FormalParList(), 0, false);
6703 execute_refd
.value
->generate_code_expr_mandatory(&expr
);
6704 expr
.expr
= mputstr(expr
.expr
, ".execute(");
6705 execute_refd
.ap_list2
->generate_code_alias(&expr
, 0, 0, false);
6707 if (execute_refd
.ap_list2
->get_nof_pars() > 0)
6708 expr
.expr
= mputstr(expr
.expr
, ", ");
6709 if (execute_refd
.timerval
) {
6710 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6711 execute_refd
.timerval
->generate_code_expr(&expr
);
6712 expr
.expr
= mputc(expr
.expr
, ')');
6713 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6714 return Code::merge_free_expr(str
,&expr
);
6717 void Statement::generate_code_expr_receive(expression_struct
*expr
,
6720 if (port_op
.portref
) {
6721 // The operation refers to a specific port.
6722 port_op
.portref
->generate_code(expr
);
6723 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6724 if (port_op
.r
.rcvpar
) {
6725 // The receive parameter is present.
6726 if (use_runtime_2
&& TypeConv::needs_conv_redir(port_op
.r
.rcvpar
,
6727 port_op
.r
.redirect
.value
)) {
6728 // Don't change the first parameter. Otherwise it won't receive
6729 // anything. The only thing we need is a temporary to save the
6730 // result and a conversion at the end.
6731 TypeConv::gen_conv_code_redir(expr
, port_op
.r
.rcvpar
,
6732 port_op
.r
.redirect
.value
);
6734 port_op
.r
.rcvpar
->generate_code(expr
);
6735 expr
->expr
= mputstr(expr
->expr
, ", ");
6736 if (port_op
.r
.redirect
.value
) {
6737 // Value redirect is also present.
6738 expr
->expr
= mputstr(expr
->expr
, "&(");
6739 port_op
.r
.redirect
.value
->generate_code(expr
);
6740 expr
->expr
= mputc(expr
->expr
, ')');
6741 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6743 expr
->expr
= mputstr(expr
->expr
, ", ");
6746 // the operation refers to any port
6747 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6749 generate_code_expr_fromclause(expr
);
6750 expr
->expr
= mputstr(expr
->expr
, ", ");
6751 generate_code_expr_senderredirect(expr
);
6752 expr
->expr
= mputc(expr
->expr
, ')');
6755 void Statement::generate_code_expr_getcall(expression_struct
*expr
,
6758 if (port_op
.portref
) {
6759 // the operation refers to a specific port
6760 port_op
.portref
->generate_code(expr
);
6761 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6762 if (port_op
.r
.rcvpar
) {
6763 // the signature template is present
6764 port_op
.r
.rcvpar
->generate_code(expr
);
6765 expr
->expr
= mputstr(expr
->expr
, ", ");
6766 generate_code_expr_fromclause(expr
);
6767 // a temporary object is needed for parameter redirect
6768 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6769 expr
->expr
= mputprintf(expr
->expr
, ", %s_call_redirect(",
6770 signature
->get_genname_value(my_sb
).c_str());
6771 if (port_op
.r
.redirect
.param
)
6772 port_op
.r
.redirect
.param
->generate_code(expr
);
6773 expr
->expr
= mputstr(expr
->expr
, "), ");
6774 generate_code_expr_senderredirect(expr
);
6776 // the signature parameter is not present
6777 generate_code_expr_fromclause(expr
);
6778 expr
->expr
= mputstr(expr
->expr
, ", ");
6779 generate_code_expr_senderredirect(expr
);
6782 // the operation refers to any port
6783 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6784 generate_code_expr_fromclause(expr
);
6785 expr
->expr
= mputstr(expr
->expr
, ", ");
6786 generate_code_expr_senderredirect(expr
);
6788 expr
->expr
=mputc(expr
->expr
, ')');
6791 void Statement::generate_code_expr_getreply(expression_struct
*expr
,
6794 if (port_op
.portref
) {
6795 // the operation refers to a specific port
6796 port_op
.portref
->generate_code(expr
);
6797 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6798 if (port_op
.r
.rcvpar
) {
6799 // the signature template is present
6800 port_op
.r
.rcvpar
->generate_code(expr
);
6801 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6803 signature
->get_type_refd_last()->get_signature_return_type();
6805 expr
->expr
= mputstr(expr
->expr
, ".set_value_template(");
6806 if (port_op
.r
.getreply_valuematch
) {
6807 // the value match is also present
6808 port_op
.r
.getreply_valuematch
->generate_code(expr
);
6810 // the value match is not present
6811 // we must substitute it with ? in the signature template
6812 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6813 return_type
->get_genname_template(my_sb
).c_str());
6815 expr
->expr
= mputc(expr
->expr
, ')');
6817 expr
->expr
= mputstr(expr
->expr
, ", ");
6818 generate_code_expr_fromclause(expr
);
6819 // a temporary object is needed for value and parameter redirect
6820 expr
->expr
= mputprintf(expr
->expr
, ", %s_reply_redirect(",
6821 signature
->get_genname_value(my_sb
).c_str());
6823 // the first argument of the constructor must contain
6824 // the value redirect
6825 if (port_op
.r
.redirect
.value
) {
6826 expr
->expr
= mputstr(expr
->expr
, "&(");
6827 port_op
.r
.redirect
.value
->generate_code(expr
);
6828 expr
->expr
= mputc(expr
->expr
, ')');
6829 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6830 if (port_op
.r
.redirect
.param
) expr
->expr
= mputstr(expr
->expr
, ", ");
6832 if (port_op
.r
.redirect
.param
)
6833 port_op
.r
.redirect
.param
->generate_code(expr
);
6834 expr
->expr
= mputstr(expr
->expr
, "), ");
6835 generate_code_expr_senderredirect(expr
);
6837 // the signature template is not present
6838 generate_code_expr_fromclause(expr
);
6839 expr
->expr
= mputstr(expr
->expr
, ", ");
6840 generate_code_expr_senderredirect(expr
);
6843 // the operation refers to any port
6844 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6845 generate_code_expr_fromclause(expr
);
6846 expr
->expr
= mputstr(expr
->expr
, ", ");
6847 generate_code_expr_senderredirect(expr
);
6849 expr
->expr
= mputc(expr
->expr
, ')');
6852 void Statement::generate_code_expr_catch(expression_struct
*expr
)
6854 if (port_op
.portref
) {
6855 // the operation refers to a specific port
6856 if (port_op
.r
.ctch
.timeout
) {
6857 // the operation catches the timeout exception
6858 expr
->expr
= mputstr(expr
->expr
, "call_timer.timeout()");
6861 port_op
.portref
->generate_code(expr
);
6862 expr
->expr
= mputprintf(expr
->expr
, ".%s(",
6863 statementtype
== S_CHECK_CATCH
? "check_catch" : "get_exception");
6864 if (port_op
.r
.ctch
.signature_ref
) {
6865 // the signature reference and the exception template is present
6866 expr
->expr
= mputprintf(expr
->expr
, "%s_exception_template(",
6867 port_op
.r
.ctch
.signature
->get_genname_value(my_sb
).c_str());
6868 port_op
.r
.rcvpar
->generate_code(expr
);
6869 expr
->expr
= mputstr(expr
->expr
, ", ");
6870 if (port_op
.r
.redirect
.value
) {
6871 // value redirect is also present
6872 expr
->expr
= mputstr(expr
->expr
, "&(");
6873 port_op
.r
.redirect
.value
->generate_code(expr
);
6874 expr
->expr
= mputc(expr
->expr
, ')');
6875 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6876 expr
->expr
= mputstr(expr
->expr
, "), ");
6879 // the operation refers to any port
6880 expr
->expr
= mputprintf(expr
->expr
, "PORT::%s(",
6881 statementtype
== S_CHECK_CATCH
? "any_check_catch" : "any_catch");
6883 generate_code_expr_fromclause(expr
);
6884 expr
->expr
= mputstr(expr
->expr
, ", ");
6885 generate_code_expr_senderredirect(expr
);
6886 expr
->expr
= mputc(expr
->expr
, ')');
6889 void Statement::generate_code_expr_check(expression_struct
*expr
)
6891 if (port_op
.portref
) {
6892 // the operation refers to a specific port
6893 port_op
.portref
->generate_code(expr
);
6894 expr
->expr
= mputstr(expr
->expr
, ".check");
6896 // the operation refers to any port
6897 expr
->expr
= mputstr(expr
->expr
, "PORT::any_check");
6899 expr
->expr
= mputc(expr
->expr
, '(');
6900 generate_code_expr_fromclause(expr
);
6901 expr
->expr
= mputstr(expr
->expr
, ", ");
6902 generate_code_expr_senderredirect(expr
);
6903 expr
->expr
= mputc(expr
->expr
, ')');
6906 void Statement::generate_code_expr_done(expression_struct
*expr
)
6908 if (comp_op
.compref
) {
6909 if (comp_op
.donereturn
.donematch
) {
6910 // value returning done
6911 // figure out what type the done() function belongs to
6912 Type
*t
= comp_op
.donereturn
.donematch
6913 ->get_expr_governor(Type::EXPECTED_TEMPLATE
);
6914 if (!t
) FATAL_ERROR("Statement::generate_code_expr_done()");
6915 while (t
->is_ref() && !t
->has_done_attribute())
6916 t
= t
->get_type_refd();
6917 if (!t
->has_done_attribute())
6918 FATAL_ERROR("Statement::generate_code_expr_done()");
6919 // determine whether the done() function is in the same module
6920 Common::Module
*t_mod
= t
->get_my_scope()->get_scope_mod_gen();
6921 if (t_mod
!= my_sb
->get_scope_mod_gen()) {
6922 expr
->expr
= mputprintf(expr
->expr
, "%s::",
6923 t_mod
->get_modid().get_name().c_str());
6925 expr
->expr
= mputstr(expr
->expr
, "done(");
6926 comp_op
.compref
->generate_code_expr(expr
);
6927 expr
->expr
= mputstr(expr
->expr
, ", ");
6928 comp_op
.donereturn
.donematch
->generate_code(expr
);
6929 expr
->expr
= mputstr(expr
->expr
, ", ");
6930 if (comp_op
.donereturn
.redirect
) {
6931 // value redirect is present
6932 expr
->expr
= mputstr(expr
->expr
, "&(");
6933 comp_op
.donereturn
.redirect
->generate_code(expr
);
6934 expr
->expr
= mputc(expr
->expr
, ')');
6936 // value redirect is omitted
6937 expr
->expr
= mputstr(expr
->expr
, "NULL");
6939 expr
->expr
= mputc(expr
->expr
, ')');
6942 comp_op
.compref
->generate_code_expr_mandatory(expr
);
6943 expr
->expr
= mputstr(expr
->expr
, ".done()");
6945 } else if (comp_op
.any_or_all
== C_ANY
) {
6946 // any component.done
6947 expr
->expr
= mputstr(expr
->expr
,
6948 "TTCN_Runtime::component_done(ANY_COMPREF)");
6950 // all component.done
6951 expr
->expr
= mputstr(expr
->expr
,
6952 "TTCN_Runtime::component_done(ALL_COMPREF)");
6956 void Statement::generate_code_expr_killed(expression_struct
*expr
)
6958 if (comp_op
.compref
) {
6960 comp_op
.compref
->generate_code_expr_mandatory(expr
);
6961 expr
->expr
= mputstr(expr
->expr
, ".killed()");
6962 } else if (comp_op
.any_or_all
== C_ANY
) {
6963 // any component.killed
6964 expr
->expr
= mputstr(expr
->expr
,
6965 "TTCN_Runtime::component_killed(ANY_COMPREF)");
6967 // all component.killed
6968 expr
->expr
= mputstr(expr
->expr
,
6969 "TTCN_Runtime::component_killed(ALL_COMPREF)");
6973 void Statement::generate_code_expr_timeout(expression_struct
*expr
)
6975 if (timer_op
.timerref
) {
6976 timer_op
.timerref
->generate_code(expr
);
6977 expr
->expr
=mputstr(expr
->expr
, ".timeout()");
6978 } else expr
->expr
= mputstr(expr
->expr
, "TIMER::any_timeout()");
6981 void Statement::generate_code_expr_sendpar(expression_struct
*expr
)
6983 Template
*templ_body
= port_op
.s
.sendpar
->get_Template();
6984 if (!port_op
.s
.sendpar
->get_DerivedRef() &&
6985 templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
) {
6986 // the send parameter is a value: optimization is possible
6987 Value
*t_val
= templ_body
->get_specific_value();
6988 bool cast_needed
= t_val
->explicit_cast_needed();
6990 // the ambiguous C++ expression is converted to the value class
6991 expr
->expr
= mputprintf(expr
->expr
, "%s(",
6992 t_val
->get_my_governor()->get_genname_value(my_sb
).c_str());
6994 t_val
->generate_code_expr_mandatory(expr
);
6995 if (cast_needed
) expr
->expr
= mputc(expr
->expr
, ')');
6997 // the send parameter is a real template: optimization is not possible
6998 port_op
.s
.sendpar
->generate_code(expr
);
7002 void Statement::generate_code_expr_fromclause(expression_struct
*expr
)
7004 if (port_op
.r
.fromclause
) {
7005 // the from clause is present: trivial case
7006 port_op
.r
.fromclause
->generate_code(expr
);
7007 } else if (port_op
.r
.redirect
.sender
) {
7008 // from clause is omitted, but sender redirect is present
7009 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
7011 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
7012 if (t_var_type
->get_type_refd_last()->get_typetype() ==
7013 Type::T_COMPONENT
) {
7014 // the variable can store a component reference
7015 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7017 // the variable can store an address value
7018 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
7019 t_var_type
->get_genname_template(my_sb
).c_str());
7022 // neither from clause nor sender redirect is present
7023 // the operation cannot refer to address type
7024 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7028 void Statement::generate_code_expr_senderredirect(expression_struct
*expr
)
7030 if (port_op
.r
.redirect
.sender
) {
7031 expr
->expr
= mputstr(expr
->expr
, "&(");
7032 port_op
.r
.redirect
.sender
->generate_code(expr
);
7033 expr
->expr
= mputc(expr
->expr
, ')');
7034 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
7037 void Statement::generate_code_portref(expression_struct
*expr
,
7040 // make a backup of the current expression
7041 char *expr_backup
= expr
->expr
;
7042 // build the equivalent of p_ref in expr->expr
7043 expr
->expr
= mprintf("\"%s\"", p_ref
->get_id()->get_dispname().c_str());
7044 FieldOrArrayRefs
*t_subrefs
= p_ref
->get_subrefs();
7046 // array indices are present
7047 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
7048 FieldOrArrayRef
*t_ref
= t_subrefs
->get_ref(i
);
7049 if (t_ref
->get_type() != FieldOrArrayRef::ARRAY_REF
)
7050 FATAL_ERROR("Statement::generate_code_portref()");
7051 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7052 char *tmp
= expr
->expr
;
7053 expr
->expr
= mcopystr("get_port_name(");
7054 expr
->expr
= mputstr(expr
->expr
, tmp
);
7056 expr
->expr
= mputstr(expr
->expr
, ", ");
7057 t_ref
->get_val()->generate_code_expr(expr
);
7058 expr
->expr
= mputc(expr
->expr
, ')');
7061 // now expr->expr contains the equivalent of p_ref
7062 // append it to the original expression and restore the result
7063 expr_backup
= mputstr(expr_backup
, expr
->expr
);
7065 expr
->expr
= expr_backup
;
7068 void Statement::set_parent_path(WithAttribPath
* p_path
) {
7069 switch (statementtype
) {
7071 def
->set_parent_path(p_path
);
7074 block
->set_parent_path(p_path
);
7077 if_stmt
.ics
->set_parent_path(p_path
);
7078 if (if_stmt
.elseblock
)
7079 if_stmt
.elseblock
->set_parent_path(p_path
);
7082 select
.scs
->set_parent_path(p_path
);
7085 loop
.block
->set_parent_path(p_path
);
7089 loop
.block
->set_parent_path(p_path
);
7100 case S_STOP_TESTCASE
:
7104 case S_UNKNOWN_INSTANCE
:
7105 case S_FUNCTION_INSTANCE
:
7106 case S_ALTSTEP_INSTANCE
:
7117 case S_CHECK_RECEIVE
:
7120 case S_CHECK_GETCALL
:
7122 case S_CHECK_GETREPLY
:
7131 case S_START_COMP_REFD
:
7144 case S_TESTCASE_INSTANCE
:
7145 case S_TESTCASE_INSTANCE_REFD
:
7146 case S_ACTIVATE_REFD
:
7147 case S_UNKNOWN_INVOKED
:
7148 case S_FUNCTION_INVOKED
:
7149 case S_ALTSTEP_INVOKED
:
7151 case S_START_PROFILER
:
7152 case S_STOP_PROFILER
:
7155 FATAL_ERROR("Statement::set_parent_path()");
7159 // =================================
7161 // =================================
7163 Assignment::Assignment(Reference
*p_ref
, Template
*p_templ
)
7164 : asstype(ASS_UNKNOWN
), ref(p_ref
), templ(p_templ
), self_ref(false),
7165 template_restriction(TR_NONE
), gen_restriction_check(false)
7167 if(!ref
|| !templ
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7170 Assignment::Assignment(Reference
*p_ref
, Value
*p_val
)
7171 : asstype(ASS_VAR
), ref(p_ref
), val(p_val
), self_ref(false),
7172 template_restriction(TR_NONE
), gen_restriction_check(false)
7174 if(!ref
|| !val
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7177 Assignment::~Assignment()
7192 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7196 Assignment
*Assignment::clone() const
7198 FATAL_ERROR("Assignment::clone");
7201 void Assignment::set_my_scope(Scope
*p_scope
)
7206 ref
->set_my_scope(p_scope
);
7207 templ
->set_my_scope(p_scope
);
7210 ref
->set_my_scope(p_scope
);
7211 val
->set_my_scope(p_scope
);
7216 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7220 void Assignment::set_fullname(const string
& p_fullname
)
7222 Node::set_fullname(p_fullname
);
7226 ref
->set_fullname(p_fullname
);
7227 templ
->set_fullname(p_fullname
);
7230 ref
->set_fullname(p_fullname
);
7231 val
->set_fullname(p_fullname
);
7236 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7240 void Assignment::dump(unsigned int level
) const
7242 // warning, ref is not always set (e.g. ASS_ERROR)
7250 DEBUG(level
, "*** ERROR ***");
7254 DEBUG(level
, "*** UNKNOWN ***");
7259 templ
->dump(level
+1);
7264 void Assignment::chk_unknown_ass()
7266 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7267 if (!t_ass
) goto error
;
7268 switch (t_ass
->get_asstype()) {
7269 case Common::Assignment::A_ERROR
:
7271 case Common::Assignment::A_PAR_VAL_IN
:
7272 t_ass
->use_as_lvalue(*ref
);
7274 case Common::Assignment::A_VAR
:
7275 case Common::Assignment::A_PAR_VAL_OUT
:
7276 case Common::Assignment::A_PAR_VAL_INOUT
:
7277 if (templ
->is_Value()) {
7278 Value
*t_val
= templ
->get_Value();
7284 templ
->error("A template body with matching symbols cannot be"
7285 " assigned to a variable");
7289 case Common::Assignment::A_PAR_TEMPL_IN
:
7290 t_ass
->use_as_lvalue(*ref
);
7292 case Common::Assignment::A_VAR_TEMPLATE
: {
7293 Type::typetype_t tt
= t_ass
->get_Type()->get_typetype();
7296 case Type::T_BSTR_A
:
7301 case Type::T_UTF8STRING
:
7302 case Type::T_NUMERICSTRING
:
7303 case Type::T_PRINTABLESTRING
:
7304 case Type::T_TELETEXSTRING
:
7305 case Type::T_VIDEOTEXSTRING
:
7306 case Type::T_IA5STRING
:
7307 case Type::T_GRAPHICSTRING
:
7308 case Type::T_VISIBLESTRING
:
7309 case Type::T_GENERALSTRING
:
7310 case Type::T_UNIVERSALSTRING
:
7311 case Type::T_BMPSTRING
:
7312 case Type::T_UTCTIME
:
7313 case Type::T_GENERALIZEDTIME
:
7314 case Type::T_OBJECTDESCRIPTOR
: {
7315 Ttcn::FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7316 if (!subrefs
) break;
7317 size_t nof_subrefs
= subrefs
->get_nof_refs();
7318 if (nof_subrefs
> 0) {
7319 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
7320 ->get_ref(nof_subrefs
- 1);
7321 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
7322 if (!templ
->is_Value()) {
7323 templ
->error("A template body with matching symbols cannot be "
7324 "assigned to an element of a template variable");
7334 case Common::Assignment::A_PAR_TEMPL_OUT
:
7335 case Common::Assignment::A_PAR_TEMPL_INOUT
:
7336 asstype
= ASS_TEMPLATE
;
7340 ref
->error("Reference to a variable or template variable was expected "
7341 "instead of %s", t_ass
->get_description().c_str());
7348 asstype
= ASS_ERROR
;
7352 void Assignment::chk_var_ass()
7354 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7355 Type
*var_type
= lhs
->get_Type();
7356 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7358 var_type
->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7359 if (!type
) goto error
;
7360 val
->set_my_governor(type
);
7361 type
->chk_this_value_ref(val
);
7362 if (val
->get_value_refd_last()->get_valuetype() == Value::V_OMIT
) {
7363 Identifier
*field_id
= 0;
7364 if (subrefs
) field_id
= subrefs
->remove_last_field();
7366 val
->error("Omit value can be assigned to an optional field of "
7367 "a record or set value only");
7370 Type
*base_type
= var_type
7371 ->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7372 // Putting field_id back to subrefs.
7373 subrefs
->add(new FieldOrArrayRef(field_id
));
7374 base_type
= base_type
->get_type_refd_last();
7375 switch (base_type
->get_typetype()) {
7384 val
->error("Omit value can be assigned to an optional field of "
7385 "a record or set value only");
7388 if (!base_type
->get_comp_byName(*field_id
)->get_is_optional()) {
7389 val
->error("Assignment of `omit' to mandatory field `%s' of type "
7390 "`%s'", field_id
->get_dispname().c_str(),
7391 base_type
->get_typename().c_str());
7395 bool is_string_element
= subrefs
&& subrefs
->refers_to_string_element();
7396 self_ref
|= type
->chk_this_value(val
, lhs
, Type::EXPECTED_DYNAMIC_VALUE
,
7397 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
,
7398 (is_string_element
? NO_SUB_CHK
: SUB_CHK
), NOT_IMPLICIT_OMIT
,
7399 (is_string_element
? IS_STR_ELEM
: NOT_STR_ELEM
));
7400 if (is_string_element
) {
7401 // The length of RHS value shall be 1.
7402 Value
*v_last
= val
->get_value_refd_last();
7403 switch (type
->get_type_refd_last()->get_typetype()) {
7405 case Type::T_BSTR_A
:
7406 if (v_last
->get_valuetype() != Value::V_BSTR
) v_last
= 0;
7409 if (v_last
->get_valuetype() != Value::V_HSTR
) v_last
= 0;
7412 if (v_last
->get_valuetype() != Value::V_OSTR
) v_last
= 0;
7415 case Type::T_NUMERICSTRING
:
7416 case Type::T_PRINTABLESTRING
:
7417 case Type::T_IA5STRING
:
7418 case Type::T_VISIBLESTRING
:
7419 case Type::T_UTCTIME
:
7420 case Type::T_GENERALIZEDTIME
:
7421 if (v_last
->get_valuetype() != Value::V_CSTR
) v_last
= 0;
7424 case Type::T_UTF8STRING
:
7425 case Type::T_TELETEXSTRING
:
7426 case Type::T_VIDEOTEXSTRING
:
7427 case Type::T_GRAPHICSTRING
:
7428 case Type::T_GENERALSTRING
:
7429 case Type::T_UNIVERSALSTRING
:
7430 case Type::T_BMPSTRING
:
7431 case Type::T_OBJECTDESCRIPTOR
:
7432 if (v_last
->get_valuetype() != Value::V_USTR
) v_last
= 0;
7438 size_t string_len
= v_last
->get_val_strlen();
7439 if (string_len
!= 1) {
7440 val
->error("The length of the string to be assigned to a string "
7441 "element of type `%s' should be 1 instead of %lu",
7442 type
->get_typename().c_str(),
7443 (unsigned long)string_len
);
7453 asstype
= ASS_ERROR
;
7457 void Assignment::chk_template_ass()
7459 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7460 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7461 if (!lhs
) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7462 Type
*type
= lhs
->get_Type()->
7463 get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7464 if (!type
) goto error
;
7465 if (lhs
->get_asstype() != Common::Assignment::A_VAR_TEMPLATE
&&
7466 subrefs
&& subrefs
->refers_to_string_element()) {
7467 ref
->error("It is not allowed to index template strings");
7470 templ
->set_my_governor(type
);
7472 templ
->flatten(false);
7474 type
->chk_this_template_ref(templ
);
7475 self_ref
|= type
->chk_this_template_generic(templ
, INCOMPLETE_ALLOWED
,
7476 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, lhs
);
7477 chk_template_restriction();
7482 asstype
= ASS_ERROR
;
7486 void Assignment::chk()
7501 FATAL_ERROR("Ttcn::Assignment::chk()");
7505 void Assignment::set_code_section(
7506 GovernedSimple::code_section_t p_code_section
)
7510 ref
->set_code_section(p_code_section
);
7511 val
->set_code_section(p_code_section
);
7514 ref
->set_code_section(p_code_section
);
7515 templ
->set_code_section(p_code_section
);
7521 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7525 void Assignment::chk_template_restriction()
7527 if (asstype
!=ASS_TEMPLATE
)
7528 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7529 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7530 if (!t_ass
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7531 switch (t_ass
->get_asstype()) {
7532 case Common::Assignment::A_VAR_TEMPLATE
: {
7533 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(t_ass
);
7534 if (!dvt
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7535 template_restriction
= dvt
->get_template_restriction();
7537 case Common::Assignment::A_PAR_TEMPL_IN
:
7538 case Common::Assignment::A_PAR_TEMPL_OUT
:
7539 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
7540 FormalPar
* fp
= dynamic_cast<FormalPar
*>(t_ass
);
7541 if (!fp
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7542 template_restriction
= fp
->get_template_restriction();
7545 template_restriction
= TR_NONE
;
7547 // transform the restriction if this is a subfield
7548 template_restriction
= Template::get_sub_restriction(template_restriction
, ref
);
7549 // check the template restriction
7550 gen_restriction_check
=
7551 templ
->chk_restriction("template", template_restriction
);
7554 char *Assignment::generate_code(char *str
)
7556 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
7557 const bool rhs_copied
= self_ref
;
7560 const string
& rhs_copy
= val
->get_temporary_id();
7561 string rhs_ref
= rhs_copy
;
7562 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7563 if (val
->get_my_governor()->is_optional_field()) {
7564 str
= mputprintf(str
, "{\nOPTIONAL<%s> %s;\n",
7565 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7568 str
= mputprintf(str
, "{\n%s %s;\n",
7569 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7572 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(val
);
7575 // Most complicated case. The LHS is saved in a temporary reference,
7576 // in case we need to access it more than once, e.g:
7577 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7578 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7579 // This saves having to index x2 more than once.
7580 const string
& tmp_id
= val
->get_temporary_id(); // For "ref".
7581 const char *tmp_id_str
= tmp_id
.c_str();
7582 const string
& type_genname
=
7583 val
->get_my_governor()->get_genname_value(val
->get_my_scope());
7584 const char *type_genname_str
= type_genname
.c_str();
7585 expression_struct expr
;
7586 Code::init_expr(&expr
);
7587 ref
->generate_code(&expr
);
7591 str
= TypeConv::gen_conv_code_refd(str
, rhs_ref
.c_str(), val
);
7592 else str
= val
->generate_code_init(str
, rhs_ref
.c_str());
7595 str
= mputstr(str
, "{\n");
7596 str
= mputstr(str
, expr
.preamble
);
7597 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
7598 // The LHS is a string element.
7599 str
= mputprintf(str
, "%s_ELEMENT %s(%s);\n", type_genname_str
,
7600 tmp_id_str
, expr
.expr
);
7602 // The LHS is a normal value.
7603 str
= mputprintf(str
, "%s& %s = %s; /* 7388 */\n", type_genname_str
,
7604 tmp_id_str
, expr
.expr
);
7606 str
= mputstr(str
, expr
.postamble
);
7607 // We now have a reference to the LHS. Generate the actual assignment
7609 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7613 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, val
);
7614 else str
= val
->generate_code_init(str
, tmp_id_str
);
7616 Code::free_expr(&expr
);
7617 str
= mputstr(str
, "}\n");
7621 if (!val
->has_single_expr()) goto case3
;
7622 // C++ equivalent of RHS is a single expression.
7623 expression_struct expr
;
7624 Code::init_expr(&expr
);
7625 ref
->generate_code(&expr
);// vu.s()
7627 str
= mputprintf(str
, "%s = %s;\n",
7628 rhs_copy
.c_str(), val
->get_single_expr().c_str());
7630 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7633 expr
.expr
= mputprintf(expr
.expr
,
7634 " = %s", val
->get_single_expr().c_str());
7636 str
= Code::merge_free_expr(str
, &expr
);
7639 // The LHS is a single identifier.
7640 const string
& rhs_name
= ref
->get_refd_assignment()
7641 ->get_genname_from_scope(ref
->get_my_scope());
7642 if (val
->can_use_increment(ref
)) {
7643 switch (val
->get_optype()) {
7644 case Value::OPTYPE_ADD
:
7645 str
= mputprintf(str
, "++%s;\n", rhs_name
.c_str());
7647 case Value::OPTYPE_SUBTRACT
:
7648 str
= mputprintf(str
, "--%s;\n", rhs_name
.c_str());
7651 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7654 str
= val
->generate_code_init(str
,
7655 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7658 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7664 str
= mputstr(str
, "}\n");
7667 case ASS_TEMPLATE
: {
7668 const string
& rhs_copy
= templ
->get_temporary_id();
7669 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7670 str
= mputprintf(str
, "{\n%s %s;\n",
7671 templ
->get_my_governor()->get_genname_template(templ
->get_my_scope()).c_str(), rhs_copy
.c_str()//, rhs_copy.c_str()
7674 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(templ
);
7675 if (needs_conv
) { // case 3
7677 // Most complicated case. The LHS is saved in a temporary reference.
7678 const string
& tmp_id
= templ
->get_temporary_id();
7679 const char *tmp_id_str
= tmp_id
.c_str();
7680 expression_struct expr
;
7681 Code::init_expr(&expr
);
7682 ref
->generate_code(&expr
);
7686 str
= TypeConv::gen_conv_code_refd(str
, rhs_copy
.c_str(), templ
);
7687 else str
= templ
->generate_code_init(str
, rhs_copy
.c_str());
7690 str
= mputstr(str
, "{\n");
7691 str
= mputstr(str
, expr
.preamble
);
7692 str
= mputprintf(str
, "%s& %s = %s;\n",
7693 templ
->get_my_governor()->get_genname_template(
7694 templ
->get_my_scope()
7695 ).c_str(), tmp_id_str
, expr
.expr
);
7696 str
= mputstr(str
, expr
.postamble
);
7698 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7702 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, templ
);
7704 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7705 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7706 str
= mputprintf(str
, "%s.remove_all_permutations();\n", tmp_id_str
);
7708 str
= templ
->generate_code_init(str
, tmp_id_str
);
7711 Code::free_expr(&expr
);
7713 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7714 str
= Template::generate_restriction_check_code(str
,
7715 tmp_id_str
, template_restriction
);
7716 str
= mputstr(str
, "}\n");
7718 else { // !needs_conv
7720 if ((template_restriction
== TR_NONE
|| !gen_restriction_check
)
7721 && templ
->has_single_expr()) {
7722 // C++ equivalent of RHS is a single expression and no restriction
7723 // check. Skipped if conversion needed.
7724 expression_struct expr
;
7725 Code::init_expr(&expr
);
7726 ref
->generate_code(&expr
);
7728 str
= mputprintf(str
, "%s = %s;\n",
7729 rhs_copy
.c_str(), templ
->get_single_expr(false).c_str());
7731 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7734 expr
.expr
= mputprintf(expr
.expr
,
7735 " = %s", templ
->get_single_expr(false).c_str());
7737 str
= Code::merge_free_expr(str
, &expr
); // will add a semicolon
7742 // LHS is a single identifier
7743 const string
& rhs_name
= ref
->get_refd_assignment()
7744 ->get_genname_from_scope(ref
->get_my_scope());
7745 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7746 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7747 str
= mputprintf(str
, "%s.remove_all_permutations();\n", (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7749 str
= templ
->generate_code_init(str
,
7750 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7752 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7754 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7755 str
= Template::generate_restriction_check_code(str
,
7756 ref
->get_refd_assignment()->get_genname_from_scope(
7758 ).c_str(), template_restriction
);
7762 str
= mputstr(str
, "}\n");
7766 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7771 // =================================
7772 // ===== ParamAssignment
7773 // =================================
7775 ParamAssignment::ParamAssignment(Identifier
*p_id
, Reference
*p_ref
)
7776 : Node(), Location(), id(p_id
), ref(p_ref
)
7778 if(!id
|| !ref
) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7781 ParamAssignment::~ParamAssignment()
7787 ParamAssignment
*ParamAssignment::clone() const
7789 FATAL_ERROR("ParamAssignment::clone");
7792 void ParamAssignment::set_my_scope(Scope
*p_scope
)
7794 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7795 ref
->set_my_scope(p_scope
);
7798 void ParamAssignment::set_fullname(const string
& p_fullname
)
7800 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7801 ref
->set_fullname(p_fullname
);
7804 Reference
*ParamAssignment::get_ref() const
7806 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7810 Reference
*ParamAssignment::steal_ref()
7812 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7813 Reference
*ret_val
= ref
;
7818 // =================================
7819 // ===== ParamAssignments
7820 // =================================
7822 ParamAssignments::~ParamAssignments()
7824 for(size_t i
=0; i
<parasss
.size(); i
++)
7829 ParamAssignments
*ParamAssignments::clone() const
7831 FATAL_ERROR("ParamAssignments::clone");
7834 void ParamAssignments::set_my_scope(Scope
*p_scope
)
7836 for(size_t i
=0; i
<parasss
.size(); i
++)
7837 parasss
[i
]->set_my_scope(p_scope
);
7840 void ParamAssignments::set_fullname(const string
& p_fullname
)
7842 Node::set_fullname(p_fullname
);
7843 for(size_t i
=0; i
<parasss
.size(); i
++)
7844 parasss
[i
]->set_fullname(p_fullname
+".parass_"+Int2string(i
+1));
7847 void ParamAssignments::add_parass(ParamAssignment
*p_parass
)
7850 FATAL_ERROR("ParamAssignments::add_parass()");
7851 parasss
.add(p_parass
);
7854 // =================================
7855 // ===== VariableEntry
7856 // =================================
7858 VariableEntry::VariableEntry(Reference
*p_ref
)
7859 : Node(), Location(), ref(p_ref
)
7861 if(!ref
) FATAL_ERROR("VariableEntry::VariableEntry()");
7864 VariableEntry::~VariableEntry()
7869 VariableEntry
*VariableEntry::clone() const
7871 FATAL_ERROR("VariableEntry::clone");
7874 void VariableEntry::set_my_scope(Scope
*p_scope
)
7876 if(ref
) ref
->set_my_scope(p_scope
);
7879 void VariableEntry::set_fullname(const string
& p_fullname
)
7881 Node::set_fullname(p_fullname
);
7882 if(ref
) ref
->set_fullname(p_fullname
+".ref");
7885 // =================================
7886 // ===== VariableEntries
7887 // =================================
7889 VariableEntries::~VariableEntries()
7891 for(size_t i
=0; i
<ves
.size(); i
++)
7896 VariableEntries
*VariableEntries::clone() const
7898 FATAL_ERROR("VariableEntries::clone");
7901 void VariableEntries::set_my_scope(Scope
*p_scope
)
7903 for(size_t i
=0; i
<ves
.size(); i
++)
7904 ves
[i
]->set_my_scope(p_scope
);
7907 void VariableEntries::set_fullname(const string
& p_fullname
)
7909 Node::set_fullname(p_fullname
);
7910 for(size_t i
=0; i
<ves
.size(); i
++)
7911 ves
[i
]->set_fullname(p_fullname
+".ve_"+Int2string(i
+1));
7914 void VariableEntries::add_ve(VariableEntry
*p_ve
)
7917 FATAL_ERROR("VariableEntries::add_ve()");
7921 // =================================
7922 // ===== ParamRedirect
7923 // =================================
7925 ParamRedirect::ParamRedirect(ParamAssignments
*p_parasss
)
7926 : Node(), Location(), parredirtype(P_ASS
), parasss(p_parasss
)
7928 if(!parasss
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
7931 ParamRedirect::ParamRedirect(VariableEntries
*p_ves
)
7932 : Node(), Location(), parredirtype(P_VAR
), ves(p_ves
)
7934 if(!ves
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
7937 ParamRedirect::~ParamRedirect()
7939 switch(parredirtype
) {
7947 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
7951 ParamRedirect
*ParamRedirect::clone() const
7953 FATAL_ERROR("ParamRedirect::clone");
7956 void ParamRedirect::set_my_scope(Scope
*p_scope
)
7958 switch(parredirtype
) {
7960 parasss
->set_my_scope(p_scope
);
7963 ves
->set_my_scope(p_scope
);
7966 FATAL_ERROR("ParamRedirect::set_my_scope()");
7970 void ParamRedirect::set_fullname(const string
& p_fullname
)
7972 Node::set_fullname(p_fullname
);
7973 switch(parredirtype
) {
7975 parasss
->set_fullname(p_fullname
+".parasss");
7978 ves
->set_fullname(p_fullname
+".parvars");
7981 FATAL_ERROR("ParamRedirect::set_fullname()");
7985 void ParamRedirect::chk_erroneous()
7987 Error_Context
cntxt(this, "In parameter redirect");
7988 switch(parredirtype
) {
7990 map
<string
, ParamAssignment
> parass_m
;
7991 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
7992 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
7993 const Identifier
&t_id
= t_parass
->get_id();
7994 const string
& name
= t_id
.get_name();
7995 const char *dispname_str
= t_id
.get_dispname().c_str();
7996 if (parass_m
.has_key(name
)) {
7997 t_parass
->error("Duplicate redirect for parameter `%s'",
7999 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8000 "already given here", dispname_str
);
8001 } else parass_m
.add(name
, t_parass
);
8002 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8004 chk_variable_ref(t_parass
->get_ref(), 0);
8009 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8010 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8011 Error_Context
cntxt2(t_ve
, "In variable entry #%lu",
8012 (unsigned long) (i
+ 1));
8013 chk_variable_ref(t_ve
->get_ref(), 0);
8017 FATAL_ERROR("ParamRedirect::chk_erroneous()");
8021 void ParamRedirect::chk(Type
*p_sig
, bool is_out
)
8023 SignatureParamList
*t_parlist
= p_sig
->get_signature_parameters();
8025 Error_Context
cntxt(this, "In parameter redirect");
8026 switch (parredirtype
) {
8028 chk_parasss(p_sig
, t_parlist
, is_out
);
8031 chk_ves(p_sig
, t_parlist
, is_out
);
8034 FATAL_ERROR("ParamRedirect::chk()");
8037 error("Parameter redirect cannot be used because signature `%s' "
8038 "does not have parameters", p_sig
->get_typename().c_str());
8043 void ParamRedirect::chk_parasss(Type
*p_sig
, SignatureParamList
*p_parlist
,
8046 map
<string
, ParamAssignment
> parass_m
;
8047 bool error_flag
= false;
8048 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8049 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8050 const Identifier
&t_id
= t_parass
->get_id();
8051 const string
& name
= t_id
.get_name();
8052 const char *dispname_str
= t_id
.get_dispname().c_str();
8053 if (parass_m
.has_key(name
)) {
8054 t_parass
->error("Duplicate redirect for parameter `%s'",
8056 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8057 "already given here", dispname_str
);
8059 } else parass_m
.add(name
, t_parass
);
8060 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8062 if (p_parlist
->has_param_withName(t_id
)) {
8063 const SignatureParam
*t_par
= p_parlist
->get_param_byName(t_id
);
8064 SignatureParam::param_direction_t t_dir
= t_par
->get_direction();
8066 if (t_dir
== SignatureParam::PARAM_IN
) {
8067 t_parass
->error("Parameter `%s' of signature `%s' has `in' "
8068 "direction", dispname_str
, p_sig
->get_typename().c_str());
8072 if (t_dir
== SignatureParam::PARAM_OUT
) {
8073 t_parass
->error("Parameter `%s' of signature `%s' has `out' "
8074 "direction", dispname_str
, p_sig
->get_typename().c_str());
8078 chk_variable_ref(t_parass
->get_ref(), t_par
->get_type());
8080 t_parass
->error("Signature `%s' does not have parameter named `%s'",
8081 p_sig
->get_typename().c_str(), dispname_str
);
8083 chk_variable_ref(t_parass
->get_ref(), 0);
8087 // converting the AssignmentList to VariableList
8088 VariableEntries
*t_ves
= new VariableEntries
;
8089 size_t upper_limit
= is_out
?
8090 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8091 for (size_t i
= 0; i
< upper_limit
; i
++) {
8092 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8093 : p_parlist
->get_in_param_byIndex(i
);
8094 const string
& name
= t_par
->get_id().get_name();
8095 if (parass_m
.has_key(name
))
8096 t_ves
->add_ve(new VariableEntry(parass_m
[name
]->steal_ref()));
8097 else t_ves
->add_ve(new VariableEntry
);
8101 parredirtype
= P_VAR
;
8106 void ParamRedirect::chk_ves(Type
*p_sig
, SignatureParamList
*p_parlist
,
8109 size_t nof_ves
= ves
->get_nof_ves();
8110 size_t nof_pars
= is_out
?
8111 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8112 if (nof_ves
!= nof_pars
) {
8113 error("Too %s variable entries compared to the number of %s/inout "
8114 "parameters in signature `%s': %lu was expected instead of %lu",
8115 nof_ves
> nof_pars
? "many" : "few", is_out
? "out" : "in",
8116 p_sig
->get_typename().c_str(), (unsigned long) nof_pars
,
8117 (unsigned long) nof_ves
);
8119 for (size_t i
= 0; i
< nof_ves
; i
++) {
8120 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8122 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8123 : p_parlist
->get_in_param_byIndex(i
);
8124 Error_Context
cntxt(t_ve
, "In variable entry #%lu (for parameter `%s')",
8125 (unsigned long) (i
+ 1), t_par
->get_id().get_dispname().c_str());
8126 chk_variable_ref(t_ve
->get_ref(), t_par
->get_type());
8128 Error_Context
cntxt(t_ve
, "In variable entry #%lu",
8129 (unsigned long) (i
+ 1));
8130 chk_variable_ref(t_ve
->get_ref(), 0);
8135 void ParamRedirect::chk_variable_ref(Reference
*p_ref
, Type
*p_type
)
8138 Type
*t_var_type
= p_ref
->chk_variable_ref();
8139 if (p_type
&& t_var_type
&& !p_type
->is_identical(t_var_type
)) {
8140 p_ref
->error("Type mismatch in parameter redirect: "
8141 "A variable of type `%s' was expected instead of `%s'",
8142 p_type
->get_typename().c_str(),
8143 t_var_type
->get_typename().c_str());
8147 void ParamRedirect::set_code_section(
8148 GovernedSimple::code_section_t p_code_section
)
8150 // code can be generated from VariableList only
8151 switch (parredirtype
) {
8155 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8156 Reference
*t_ref
= ves
->get_ve_byIndex(i
)->get_ref();
8157 if (t_ref
) t_ref
->set_code_section(p_code_section
);
8161 FATAL_ERROR("ParamRedirect::set_code_section()");
8165 void ParamRedirect::generate_code(expression_struct_t
*expr
)
8167 // AssignmentList is converted to VariableList during checking
8168 if (parredirtype
!= P_VAR
) FATAL_ERROR("ParamRedirect::generate_code()");
8169 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8170 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
8171 Reference
*ref
= ves
->get_ve_byIndex(i
)->get_ref();
8173 // the variable reference is present
8174 expr
->expr
= mputstr(expr
->expr
, "&(");
8175 ref
->generate_code(expr
);
8176 expr
->expr
= mputc(expr
->expr
, ')');
8177 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
8181 // =================================
8182 // ===== LogArgument
8183 // =================================
8185 LogArgument::LogArgument(TemplateInstance
*p_ti
)
8186 : logargtype(L_UNDEF
)
8188 if (!p_ti
) FATAL_ERROR("LogArgument::LogArgument()");
8192 LogArgument::~LogArgument()
8194 switch (logargtype
) {
8213 FATAL_ERROR("LogArgument::~LogArgument()");
8217 LogArgument
*LogArgument::clone() const
8219 FATAL_ERROR("LogArgument::clone");
8222 void LogArgument::set_my_scope(Scope
*p_scope
)
8224 switch (logargtype
) {
8229 ti
->set_my_scope(p_scope
);
8234 val
->set_my_scope(p_scope
);
8237 ref
->set_my_scope(p_scope
);
8242 FATAL_ERROR("LogArgument::set_my_scope()");
8246 void LogArgument::set_fullname(const string
& p_fullname
)
8248 Node::set_fullname(p_fullname
);
8249 switch (logargtype
) {
8254 ti
->set_fullname(p_fullname
);
8259 val
->set_fullname(p_fullname
);
8262 ref
->set_fullname(p_fullname
);
8267 FATAL_ERROR("LogArgument::set_fullname()");
8271 const string
& LogArgument::get_str() const
8273 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::get_str()");
8277 Value
*LogArgument::get_val() const
8279 switch (logargtype
) {
8285 FATAL_ERROR("LogArgument::get_val()");
8290 Ref_base
*LogArgument::get_ref() const
8292 if (logargtype
!= L_REF
) FATAL_ERROR("LogArgument::get_ref()");
8296 TemplateInstance
*LogArgument::get_ti() const
8298 if (logargtype
!= L_TI
) FATAL_ERROR("LogArgument::get_ref()");
8302 void LogArgument::append_str(const string
& p_str
)
8304 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::append_str()");
8308 void LogArgument::chk() // determine the proper type of the log argument
8310 if (logargtype
!= L_UNDEF
) return;
8311 Template
*t_templ
= ti
->get_Template();
8312 t_templ
= t_templ
->get_template_refd_last();
8313 t_templ
->set_lowerid_to_ref();
8314 if (!ti
->get_Type() && !ti
->get_DerivedRef() && t_templ
->is_Value()) {
8315 // drop the template instance and keep only the embedded value
8316 Value
*t_val
= t_templ
->get_Value();
8322 // try to obtain the governor of the template instance
8323 Type
*governor
= ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8325 // the governor is still unknown: an error occurred
8326 // try to interpret possible enum values as references
8327 t_templ
->set_lowerid_to_ref();
8328 governor
= t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8334 t_templ
->error("Cannot determine the type of the argument");
8336 logargtype
= L_ERROR
;
8341 void LogArgument::chk_ref()
8343 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
8345 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
8347 case Common::Assignment::A_FUNCTION_RVAL
:
8348 case Common::Assignment::A_FUNCTION_RTEMP
:
8349 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
8350 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
8351 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *this, "call");
8352 case Common::Assignment::A_CONST
:
8353 case Common::Assignment::A_EXT_CONST
:
8354 case Common::Assignment::A_MODULEPAR
:
8355 case Common::Assignment::A_MODULEPAR_TEMP
:
8356 case Common::Assignment::A_TEMPLATE
:
8357 case Common::Assignment::A_VAR
:
8358 case Common::Assignment::A_VAR_TEMPLATE
:
8359 case Common::Assignment::A_PAR_VAL_IN
:
8360 case Common::Assignment::A_PAR_VAL_OUT
:
8361 case Common::Assignment::A_PAR_VAL_INOUT
:
8362 case Common::Assignment::A_PAR_TEMPL_IN
:
8363 case Common::Assignment::A_PAR_TEMPL_OUT
:
8364 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
8365 // the reference points to a value or template-like entity
8366 // checking sub-references
8367 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
8368 if (subrefs
&& t_ass
->get_Type()->get_field_type(subrefs
,
8369 Type::EXPECTED_DYNAMIC_VALUE
)) {
8370 // subrefs seems to be correct
8371 // also checking the presence of referred fields if possible
8372 if (asstype
== Common::Assignment::A_CONST
) {
8373 ReferenceChain
refch(ref
, "While searching referenced value");
8374 t_ass
->get_Value()->get_refd_sub_value(subrefs
, 0, false, &refch
);
8375 } else if (asstype
== Common::Assignment::A_TEMPLATE
) {
8376 ReferenceChain
refch(ref
, "While searching referenced template");
8377 t_ass
->get_Template()
8378 ->get_refd_sub_template(subrefs
, false, &refch
);
8382 case Common::Assignment::A_TIMER
:
8383 case Common::Assignment::A_PORT
: {
8384 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
8385 if (t_dims
) t_dims
->chk_indices(ref
, t_ass
->get_assname(), true,
8386 Type::EXPECTED_DYNAMIC_VALUE
);
8387 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8388 "cannot have field or array sub-references",
8389 t_ass
->get_description().c_str());
8391 case Common::Assignment::A_PAR_TIMER
:
8392 case Common::Assignment::A_PAR_PORT
:
8393 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8394 "field or array sub-references", t_ass
->get_description().c_str());
8396 case Common::Assignment::A_FUNCTION
:
8397 case Common::Assignment::A_EXT_FUNCTION
:
8398 ref
->error("Reference to a value, template, timer or port was expected "
8399 "instead of a call of %s, which does not have return type",
8400 t_ass
->get_description().c_str());
8403 ref
->error("Reference to a value, template, timer or port was expected "
8404 "instead of %s", t_ass
->get_description().c_str());
8408 void LogArgument::chk_val()
8410 // literal enumerated values cannot appear in this context
8411 val
->set_lowerid_to_ref();
8412 switch (val
->get_valuetype()) {
8413 case Value::V_CSTR
: {
8414 string
*t_cstr
= new string(val
->get_val_str());
8419 case Value::V_REFD
: {
8420 Ref_base
*t_ref
= val
->steal_ttcn_ref_base();
8427 if (val
->get_optype() == Value::OPTYPE_MATCH
) logargtype
= L_MATCH
;
8428 else logargtype
= L_VAL
;
8430 case Value::V_MACRO
:
8431 logargtype
= L_MACRO
;
8436 Type
*governor
= val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
8438 val
->set_my_governor(governor
);
8439 (void)governor
->chk_this_value(val
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
8440 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
8441 if (logargtype
== L_VAL
&& val
->get_valuetype() == Value::V_CSTR
8442 && !val
->is_unfoldable()) { // string value known at compile time
8443 string
*t_cstr
= new string(val
->get_val_str());
8449 if (logargtype
== L_MACRO
) {
8450 switch (val
->get_valuetype()) {
8451 case Value::V_CSTR
: {
8452 // the macro was evaluated to a charstring value
8453 string
*t_cstr
= new string(val
->get_val_str());
8458 case Value::V_MACRO
:
8459 // the macro could not be evaluated at compile time
8460 // leave logargtype as is
8463 // the macro was evaluated to other value (e.g. integer)
8468 val
->error("Cannot determine the type of the argument");
8470 logargtype
= L_ERROR
;
8474 void LogArgument::dump(unsigned int level
) const
8476 Node::dump(level
++);
8477 switch (logargtype
) {
8479 DEBUG(level
, "*error*");
8482 DEBUG(level
, "*undef*");
8485 DEBUG(level
, "TemplateInstance");
8491 DEBUG(level
, "Match");
8494 DEBUG(level
, "Macro");
8497 DEBUG(level
, "Reference");
8500 DEBUG(level
, "String=`%s'", cstr
->c_str());
8503 FATAL_ERROR("LogArgument::~LogArgument()");
8507 void LogArgument::set_code_section(
8508 GovernedSimple::code_section_t p_code_section
)
8510 switch (logargtype
) {
8513 ti
->set_code_section(p_code_section
);
8518 val
->set_code_section(p_code_section
);
8521 ref
->set_code_section(p_code_section
);
8527 FATAL_ERROR("LogArgument::set_code_section()");
8531 char *LogArgument::generate_code_log(char *str
)
8533 expression_struct expr
;
8534 Code::init_expr(&expr
);
8535 generate_code_expr(&expr
);
8536 str
= Code::merge_free_expr(str
, &expr
);
8540 void LogArgument::chk_recursions(ReferenceChain
& refch
)
8542 switch (logargtype
) {
8545 ti
->chk_recursions(refch
);
8550 val
->chk_recursions(refch
);
8553 Common::Assignment
*ass
= ref
->get_refd_assignment();
8555 refch
.add(ass
->get_fullname());
8561 FATAL_ERROR("LogArgument::chk_recursions()");
8565 bool LogArgument::has_single_expr()
8567 switch (logargtype
) {
8570 return ti
->has_single_expr();
8574 return ( val
->has_single_expr() && !val
->explicit_cast_needed() );
8576 Common::Assignment
*ass
= ref
->get_refd_assignment();
8577 switch (ass
->get_asstype()) {
8578 case Common::Assignment::A_CONST
:
8579 case Common::Assignment::A_EXT_CONST
:
8580 return ref
->has_single_expr();
8589 FATAL_ERROR("LogArgument::has_single_expr()");
8594 void LogArgument::generate_code_expr(expression_struct
*expr
)
8596 switch(logargtype
) {
8598 if (ti
->is_only_specific_value()) {
8599 // use the embedded specific value for code generation
8600 ti
->get_Template()->get_specific_value()->generate_code_log(expr
);
8602 ti
->generate_code(expr
);
8603 expr
->expr
= mputstr(expr
->expr
, ".log()");
8607 val
->generate_code_log(expr
);
8610 val
->generate_code_log_match(expr
);
8613 if (val
->has_single_expr()) {
8614 expr
->expr
= mputprintf(expr
->expr
, "TTCN_Logger::log_event_str(%s)",
8615 val
->get_single_expr().c_str());
8616 } else val
->generate_code_log(expr
);
8619 ref
->generate_code_const_ref(expr
);
8620 expr
->expr
=mputstr(expr
->expr
, ".log()");
8623 size_t str_len
= cstr
->size();
8624 const char *str_ptr
= cstr
->c_str();
8627 // the string is empty: do not generate any code
8629 // the string has one character: use log_char member
8630 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_char('");
8631 expr
->expr
= Code::translate_character(expr
->expr
, *str_ptr
, false);
8632 expr
->expr
= mputstr(expr
->expr
, "')");
8635 // the string has more characters: use log_event_str member
8636 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_event_str(\"");
8637 expr
->expr
= Code::translate_string(expr
->expr
, str_ptr
);
8638 expr
->expr
= mputstr(expr
->expr
, "\")");
8642 FATAL_ERROR("LogArgument::generate_code_expr()");
8646 // =================================
8647 // ===== LogArguments
8648 // =================================
8650 LogArguments::~LogArguments()
8652 for(size_t i
=0; i
<logargs
.size(); i
++) delete logargs
[i
];
8656 LogArguments
*LogArguments::clone() const
8658 FATAL_ERROR("LogArguments::clone");
8661 void LogArguments::add_logarg(LogArgument
*p_logarg
)
8664 FATAL_ERROR("LogArguments::add_logarg()");
8665 logargs
.add(p_logarg
);
8668 void LogArguments::set_my_scope(Scope
*p_scope
)
8670 for(size_t i
=0; i
<logargs
.size(); i
++)
8671 logargs
[i
]->set_my_scope(p_scope
);
8674 void LogArguments::set_fullname(const string
& p_fullname
)
8676 Node::set_fullname(p_fullname
);
8677 for(size_t i
=0; i
<logargs
.size(); i
++)
8678 logargs
[i
]->set_fullname(p_fullname
+".logargs_"+Int2string(i
+1));
8681 void LogArguments::chk()
8683 for(size_t i
=0; i
<logargs
.size(); i
++)
8687 void LogArguments::join_strings()
8689 // points to the previous string argument otherwise it is NULL
8690 LogArgument
*prev_arg
= 0;
8691 for (size_t i
= 0; i
< logargs
.size(); ) {
8692 LogArgument
*arg
= logargs
[i
];
8693 if (arg
->get_type() == LogArgument::L_STR
) {
8694 const string
& str
= arg
->get_str();
8695 if (str
.size() > 0) {
8696 // the current argument is a non-empty string
8698 // append str to prev_arg and drop arg
8699 prev_arg
->append_str(str
);
8701 logargs
.replace(i
, 1);
8702 // don't increment i
8704 // keep it for the next iteration
8709 // the current argument is an empty string
8710 // simply drop it unless it is the only argument
8711 // note: we must distinguish between log() and log("")
8712 if (i
> 0 || logargs
.size() > 1) {
8714 logargs
.replace(i
, 1);
8715 // don't increment i
8719 // the current argument is not a string
8720 // forget the previous arg
8727 void LogArguments::set_code_section(
8728 GovernedSimple::code_section_t p_code_section
)
8730 for (size_t i
= 0; i
< logargs
.size(); i
++)
8731 logargs
[i
]->set_code_section(p_code_section
);
8734 char *LogArguments::generate_code(char *str
)
8736 for(size_t i
=0; i
<logargs
.size(); i
++)
8737 str
=logargs
[i
]->generate_code_log(str
);
8741 void LogArguments::chk_recursions(ReferenceChain
& refch
)
8743 for (size_t i
=0; i
<logargs
.size(); i
++) {
8745 logargs
[i
]->chk_recursions(refch
);
8750 bool LogArguments::has_single_expr()
8752 bool i_have_single_expr
= true;
8753 for (size_t i
=0; i
<logargs
.size(); i
++)
8754 i_have_single_expr
= i_have_single_expr
&& logargs
[i
]->has_single_expr();
8755 return i_have_single_expr
;
8758 void LogArguments::generate_code_expr(expression_struct
*expr
)
8760 expr
->expr
= mputstr(expr
->expr
, "(TTCN_Logger::begin_event_log2str(),");
8761 for(size_t i
=0; i
<logargs
.size(); i
++) {
8762 logargs
[i
]->generate_code_expr(expr
);
8763 expr
->expr
= mputc(expr
->expr
, ','); // comma operator
8765 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::end_event_log2str())");
8768 // =================================
8770 // =================================
8772 IfClause::IfClause(Value
*p_expr
, StatementBlock
*p_block
)
8773 : expr(p_expr
), block(p_block
)
8776 FATAL_ERROR("IfClause::IfClause()");
8779 IfClause::~IfClause()
8785 IfClause
*IfClause::clone() const
8787 FATAL_ERROR("IfClause::clone");
8790 void IfClause::set_my_scope(Scope
*p_scope
)
8792 expr
->set_my_scope(p_scope
);
8793 block
->set_my_scope(p_scope
);
8796 void IfClause::set_fullname(const string
& p_fullname
)
8798 Node::set_fullname(p_fullname
);
8799 expr
->set_fullname(p_fullname
+".expr");
8800 block
->set_fullname(p_fullname
+".block");
8803 bool IfClause::has_receiving_stmt() const
8805 return block
->has_receiving_stmt();
8808 void IfClause::chk(bool& unreach
)
8810 Error_Context
cntxt(this, "In if statement");
8811 if(unreach
) warning("Control never reaches this code because of"
8812 " previous effective condition(s)");
8813 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
8814 if(!expr
->is_unfoldable()) {
8815 if(expr
->get_val_bool()) unreach
=true;
8816 else block
->warning("Control never reaches this code because the"
8817 " conditional expression evaluates to false");
8822 void IfClause::set_code_section(
8823 GovernedSimple::code_section_t p_code_section
)
8825 expr
->set_code_section(p_code_section
);
8826 block
->set_code_section(p_code_section
);
8829 char* IfClause::generate_code(char *str
, size_t& blockcount
,
8830 bool& unreach
, bool& eachfalse
)
8832 if(unreach
) return str
;
8833 if(!expr
->is_unfoldable()) {
8834 if(expr
->get_val_bool()) unreach
=true;
8837 if (!eachfalse
) str
= mputstr(str
, "else ");
8840 str
= mputstr(str
, "{\n");
8843 str
= expr
->update_location_object(str
);
8844 str
= expr
->generate_code_tmp(str
, "if (", blockcount
);
8845 str
= mputstr(str
, ") ");
8848 str
=mputstr(str
, "{\n");
8849 str
=block
->generate_code(str
);
8850 str
=mputstr(str
, "}\n");
8854 void IfClause::ilt_generate_code(ILT
*ilt
, const char *end_label
,
8858 if(!expr
->is_unfoldable()) {
8859 if(expr
->get_val_bool()) unreach
=true;
8862 char*& str
=ilt
->get_out_branches();
8865 size_t blockcount
=0;
8866 label
=mprintf("%s_l%lu",
8867 ilt
->get_my_tmpid().c_str(),
8868 (unsigned long) ilt
->get_new_label_num());
8869 str
=expr
->update_location_object(str
);
8870 str
=expr
->generate_code_tmp(str
, "if(!", blockcount
);
8871 str
=mputprintf(str
, ") goto %s;\n", label
);
8872 while(blockcount
-->0) str
=mputstr(str
, "}\n");
8874 block
->ilt_generate_code(ilt
);
8876 str
=mputprintf(str
, "goto %s;\n%s:\n",
8882 void IfClause::set_parent_path(WithAttribPath
* p_path
) {
8883 block
->set_parent_path(p_path
);
8886 void IfClause::dump(unsigned int level
) const {
8887 DEBUG(level
, "If clause!");
8888 expr
->dump(level
+ 1);
8889 block
->dump(level
+ 1);
8892 // =================================
8894 // =================================
8896 IfClauses::~IfClauses()
8898 for(size_t i
=0; i
<ics
.size(); i
++) delete ics
[i
];
8902 IfClauses
*IfClauses::clone() const
8904 FATAL_ERROR("IfClauses::clone");
8907 void IfClauses::add_ic(IfClause
*p_ic
)
8910 FATAL_ERROR("IfClauses::add_ic()");
8914 void IfClauses::add_front_ic(IfClause
*p_ic
)
8917 FATAL_ERROR("IfClauses::add_front_ic()");
8918 ics
.add_front(p_ic
);
8921 void IfClauses::set_my_scope(Scope
*p_scope
)
8923 for(size_t i
=0; i
<ics
.size(); i
++)
8924 ics
[i
]->set_my_scope(p_scope
);
8927 void IfClauses::set_fullname(const string
& p_fullname
)
8929 Node::set_fullname(p_fullname
);
8930 for(size_t i
=0; i
<ics
.size(); i
++)
8931 ics
[i
]->set_fullname(p_fullname
+".ic_"+Int2string(i
+1));
8934 void IfClauses::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
8936 for(size_t i
=0; i
<ics
.size(); i
++)
8937 ics
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
8940 void IfClauses::set_my_def(Definition
*p_def
)
8942 for(size_t i
=0; i
<ics
.size(); i
++)
8943 ics
[i
]->get_block()->set_my_def(p_def
);
8946 void IfClauses::set_my_ags(AltGuards
*p_ags
)
8948 for(size_t i
=0; i
<ics
.size(); i
++)
8949 ics
[i
]->get_block()->set_my_ags(p_ags
);
8952 void IfClauses::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
8954 for(size_t i
=0; i
<ics
.size(); i
++)
8955 ics
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
8958 StatementBlock::returnstatus_t
IfClauses::has_return
8959 (StatementBlock
*elseblock
) const
8961 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
8962 for (size_t i
= 0; i
< ics
.size(); i
++) {
8963 switch (ics
[i
]->get_block()->has_return()) {
8964 case StatementBlock::RS_NO
:
8965 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
8966 else ret_val
= StatementBlock::RS_NO
;
8968 case StatementBlock::RS_YES
:
8969 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
8970 else ret_val
= StatementBlock::RS_YES
;
8973 return StatementBlock::RS_MAYBE
;
8976 StatementBlock::returnstatus_t else_status
;
8977 if (elseblock
) else_status
= elseblock
->has_return();
8978 else else_status
= StatementBlock::RS_NO
;
8979 switch (else_status
) {
8980 case StatementBlock::RS_NO
:
8981 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
8982 else ret_val
= StatementBlock::RS_NO
;
8984 case StatementBlock::RS_YES
:
8985 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
8986 else ret_val
= StatementBlock::RS_YES
;
8989 return StatementBlock::RS_MAYBE
;
8994 bool IfClauses::has_receiving_stmt() const
8996 for(size_t i
=0; i
<ics
.size(); i
++)
8997 if(ics
[i
]->has_receiving_stmt()) return true;
9001 void IfClauses::chk(bool& unreach
)
9003 for(size_t i
=0; i
<ics
.size(); i
++)
9004 ics
[i
]->chk(unreach
);
9007 void IfClauses::chk_allowed_interleave()
9009 for (size_t i
= 0; i
< ics
.size(); i
++)
9010 ics
[i
]->get_block()->chk_allowed_interleave();
9013 void IfClauses::set_code_section(
9014 GovernedSimple::code_section_t p_code_section
)
9016 for (size_t i
= 0; i
< ics
.size(); i
++)
9017 ics
[i
]->set_code_section(p_code_section
);
9020 char* IfClauses::generate_code(char *str
, size_t& blockcount
,
9021 bool& unreach
, bool& eachfalse
)
9023 for(size_t i
=0; i
<ics
.size(); i
++) {
9024 if(unreach
) return str
;
9025 str
=ics
[i
]->generate_code(str
, blockcount
, unreach
, eachfalse
);
9030 void IfClauses::ilt_generate_code(ILT
*ilt
, const char *end_label
,
9033 for(size_t i
=0; i
<ics
.size(); i
++) {
9035 ics
[i
]->ilt_generate_code(ilt
, end_label
, unreach
);
9039 void IfClauses::set_parent_path(WithAttribPath
* p_path
) {
9040 for (size_t i
= 0; i
< ics
.size(); i
++)
9041 ics
[i
]->set_parent_path(p_path
);
9044 void IfClauses::dump(unsigned int level
) const {
9045 DEBUG(level
, "%lu if clauses", (unsigned long)ics
.size());
9046 for (size_t i
= 0; i
< ics
.size(); i
++)
9047 ics
[i
]->dump(level
+ 1);
9050 // =================================
9052 // =================================
9054 SelectCase::SelectCase(TemplateInstances
*p_tis
, StatementBlock
*p_block
)
9055 : tis(p_tis
), block(p_block
)
9058 FATAL_ERROR("SelectCase::SelectCase()");
9061 SelectCase::~SelectCase()
9067 SelectCase
*SelectCase::clone() const
9069 FATAL_ERROR("SelectCase::clone");
9072 void SelectCase::set_my_scope(Scope
*p_scope
)
9074 if(tis
) tis
->set_my_scope(p_scope
);
9075 block
->set_my_scope(p_scope
);
9078 void SelectCase::set_fullname(const string
& p_fullname
)
9080 Node::set_fullname(p_fullname
);
9081 if(tis
) tis
->set_fullname(p_fullname
+".tis");
9082 block
->set_fullname(p_fullname
+".block");
9086 void SelectCase::chk(Type
*p_gov
, bool& unreach
)
9088 Error_Context
cntxt(this, "In select case statement");
9089 if(unreach
) warning("Control never reaches this code because of"
9090 " previous effective case(s)");
9092 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++)
9093 tis
->get_ti_byIndex(i
)->chk(p_gov
);
9094 else unreach
=true; // else statement
9098 void SelectCase::set_code_section
9099 (GovernedSimple::code_section_t p_code_section
)
9101 if(tis
) tis
->set_code_section(p_code_section
);
9102 block
->set_code_section(p_code_section
);
9106 char* SelectCase::generate_code_if(char *str
, const char *tmp_prefix
,
9107 const char *expr_name
, size_t idx
,
9110 if(unreach
) return str
;
9112 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++) {
9113 TemplateInstance
*ti
=tis
->get_ti_byIndex(i
);
9114 Template
*tb
=ti
->get_Template();
9115 bool is_value
= NULL
== ti
->get_DerivedRef() && tb
->is_Value();
9116 expression_struct exprs
;
9117 Code::init_expr(&exprs
);
9119 if (tb
->get_templatetype() == Template::SPECIFIC_VALUE
) {
9120 tb
->get_specific_value()->generate_code_expr_mandatory(&exprs
);
9123 Value
* val
= tb
->get_Value();
9124 if (NULL
== val
->get_my_governor()) {
9125 // the value's governor could not be determined, treat it as a non-value template
9129 val
->generate_code_expr_mandatory(&exprs
);
9135 ti
->generate_code(&exprs
);
9137 str
=tb
->update_location_object(str
);
9138 if(!exprs
.preamble
&& !exprs
.postamble
) {
9139 str
=mputstr(str
, "if(");
9141 str
=mputprintf(str
, "%s.match(%s)", exprs
.expr
, expr_name
);
9142 else str
=mputprintf(str
, "%s == %s", expr_name
, exprs
.expr
);
9143 str
=mputprintf(str
, ") goto %s_%lu;\n", tmp_prefix
,
9144 (unsigned long) idx
);
9145 Code::free_expr(&exprs
);
9148 str
=mputprintf(str
, "{\nboolean %s_%lub;\n", tmp_prefix
,
9149 (unsigned long) idx
);
9151 exprs
.expr
=mprintf("%s_%lub = ", tmp_prefix
, (unsigned long) idx
);
9153 exprs
.expr
=mputprintf(exprs
.expr
, "%s.match(%s)", s
, expr_name
);
9154 else exprs
.expr
=mputprintf(exprs
.expr
, "(%s == %s)", expr_name
, s
);
9156 str
=Code::merge_free_expr(str
, &exprs
);
9157 str
=mputprintf(str
, "if(%s_%lub) goto %s_%lu;\n}\n",
9158 tmp_prefix
, (unsigned long) idx
, tmp_prefix
, (unsigned long) idx
);
9163 unreach
=true; // else statement
9164 str
=mputprintf(str
, "goto %s_%lu;\n", tmp_prefix
, (unsigned long) idx
);
9170 char* SelectCase::generate_code_stmt(char *str
, const char *tmp_prefix
,
9171 size_t idx
, bool& unreach
)
9173 if(unreach
) return str
;
9174 if(!tis
) unreach
=true;
9175 str
=mputprintf(str
, "%s_%lu:\n{\n", tmp_prefix
, (unsigned long) idx
);
9176 str
=block
->generate_code(str
);
9177 str
=mputprintf(str
, "goto %s_end;\n}\n", tmp_prefix
);
9181 void SelectCase::ilt_generate_code_stmt(ILT
*ilt
, const char *tmp_prefix
,
9182 size_t idx
, bool& unreach
)
9185 if(!tis
) unreach
=true;
9186 char*& str
=ilt
->get_out_branches();
9187 str
=mputprintf(str
, "%s_%lu:\n", tmp_prefix
, (unsigned long) idx
);
9188 bool has_recv
=block
->has_receiving_stmt();
9190 str
=mputstr(str
, "{\n");
9191 str
=block
->generate_code(str
);
9193 else block
->ilt_generate_code(ilt
);
9194 str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9196 str
=mputstr(str
, "}\n");
9199 void SelectCase::set_parent_path(WithAttribPath
* p_path
) {
9200 block
->set_parent_path(p_path
);
9203 // =================================
9204 // ===== SelectCases
9205 // =================================
9207 SelectCases::~SelectCases()
9209 for(size_t i
=0; i
<scs
.size(); i
++) delete scs
[i
];
9213 SelectCases
*SelectCases::clone() const
9215 FATAL_ERROR("SelectCases::clone");
9218 void SelectCases::add_sc(SelectCase
*p_sc
)
9221 FATAL_ERROR("SelectCases::add_sc()");
9225 void SelectCases::set_my_scope(Scope
*p_scope
)
9227 for(size_t i
=0; i
<scs
.size(); i
++)
9228 scs
[i
]->set_my_scope(p_scope
);
9231 void SelectCases::set_fullname(const string
& p_fullname
)
9233 Node::set_fullname(p_fullname
);
9234 for(size_t i
=0; i
<scs
.size(); i
++)
9235 scs
[i
]->set_fullname(p_fullname
+".sc_"+Int2string(i
+1));
9238 void SelectCases::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9240 for(size_t i
=0; i
<scs
.size(); i
++)
9241 scs
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9244 void SelectCases::set_my_def(Definition
*p_def
)
9246 for(size_t i
=0; i
<scs
.size(); i
++)
9247 scs
[i
]->get_block()->set_my_def(p_def
);
9250 void SelectCases::set_my_ags(AltGuards
*p_ags
)
9252 for(size_t i
=0; i
<scs
.size(); i
++)
9253 scs
[i
]->get_block()->set_my_ags(p_ags
);
9256 void SelectCases::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9258 for(size_t i
=0; i
<scs
.size(); i
++)
9259 scs
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9262 StatementBlock::returnstatus_t
SelectCases::has_return() const
9264 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9265 bool has_else
= false;
9266 for (size_t i
= 0; i
< scs
.size(); i
++) {
9267 SelectCase
*sc
= scs
[i
];
9268 switch (sc
->get_block()->has_return()) {
9269 case StatementBlock::RS_NO
:
9270 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9271 else ret_val
= StatementBlock::RS_NO
;
9273 case StatementBlock::RS_YES
:
9274 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9275 else ret_val
= StatementBlock::RS_YES
;
9278 return StatementBlock::RS_MAYBE
;
9280 if (!sc
->get_tis()) {
9285 if (!has_else
&& ret_val
== StatementBlock::RS_YES
)
9286 return StatementBlock::RS_MAYBE
;
9287 else return ret_val
;
9290 bool SelectCases::has_receiving_stmt() const
9292 for(size_t i
=0; i
<scs
.size(); i
++)
9293 if(scs
[i
]->get_block()->has_receiving_stmt()) return true;
9298 void SelectCases::chk(Type
*p_gov
)
9301 for(size_t i
=0; i
<scs
.size(); i
++)
9302 scs
[i
]->chk(p_gov
, unreach
);
9305 void SelectCases::chk_allowed_interleave()
9307 for (size_t i
= 0; i
< scs
.size(); i
++)
9308 scs
[i
]->get_block()->chk_allowed_interleave();
9311 void SelectCases::set_code_section
9312 (GovernedSimple::code_section_t p_code_section
)
9314 for(size_t i
=0; i
<scs
.size(); i
++)
9315 scs
[i
]->set_code_section(p_code_section
);
9318 char* SelectCases::generate_code(char *str
, const char *tmp_prefix
,
9319 const char *expr_name
)
9322 for(size_t i
=0; i
<scs
.size(); i
++) {
9323 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9326 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9328 for(size_t i
=0; i
<scs
.size(); i
++) {
9329 str
=scs
[i
]->generate_code_stmt(str
, tmp_prefix
, i
, unreach
);
9332 str
=mputprintf(str
, "%s_end: /* empty */;\n", tmp_prefix
);
9336 void SelectCases::ilt_generate_code(ILT
*ilt
, const char *tmp_prefix
,
9337 const char *expr_init
,
9338 const char *expr_name
)
9340 char*& str
=ilt
->get_out_branches();
9341 if(strlen(expr_init
)) {
9342 str
=mputstr(str
, "{\n"); // (1)
9343 str
=mputstr(str
, expr_init
);
9346 for(size_t i
=0; i
<scs
.size(); i
++) {
9348 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9350 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9351 if(strlen(expr_init
)) str
=mputstr(str
, "}\n"); // (1)
9353 for(size_t i
=0; i
<scs
.size(); i
++) {
9355 scs
[i
]->ilt_generate_code_stmt(ilt
, tmp_prefix
, i
, unreach
);
9357 str
=mputprintf(str
, "%s_end:\n", tmp_prefix
);
9360 void SelectCases::set_parent_path(WithAttribPath
* p_path
) {
9361 for (size_t i
= 0; i
< scs
.size(); i
++)
9362 scs
[i
]->set_parent_path(p_path
);
9365 // =================================
9367 // =================================
9369 AltGuard::AltGuard(Value
*p_expr
, Statement
*p_stmt
, StatementBlock
*p_block
)
9370 : altguardtype(AG_OP
), expr(p_expr
), stmt(p_stmt
), block(p_block
)
9372 if (!p_stmt
|| !p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9375 AltGuard::AltGuard(Value
*p_expr
, Ref_pard
*p_ref
, StatementBlock
*p_block
)
9376 : altguardtype(AG_REF
), expr(p_expr
), ref(p_ref
), block(p_block
)
9378 if (!p_ref
) FATAL_ERROR("AltGuard::AltGuard()");
9381 AltGuard::AltGuard(Value
*p_expr
, Value
*p_v
,
9382 Ttcn::TemplateInstances
*p_t_list
, StatementBlock
*p_block
)
9383 : altguardtype(AG_INVOKE
), expr(p_expr
)
9386 if(!p_v
|| !p_t_list
) FATAL_ERROR("AltGuard::AltGuard()");
9388 invoke
.t_list
= p_t_list
;
9392 AltGuard::AltGuard(StatementBlock
*p_block
)
9393 : altguardtype(AG_ELSE
), expr(0), dummy(0), block(p_block
)
9395 if (!p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9398 AltGuard::~AltGuard()
9400 switch(altguardtype
) {
9414 delete invoke
.t_list
;
9415 delete invoke
.ap_list
;
9422 FATAL_ERROR("AltGuard::~AltGuard()");
9426 AltGuard
*AltGuard::clone() const
9428 FATAL_ERROR("AltGuard::clone");
9431 void AltGuard::set_my_scope(Scope
*p_scope
)
9433 switch(altguardtype
) {
9435 if(expr
) expr
->set_my_scope(p_scope
);
9436 stmt
->set_my_scope(p_scope
);
9437 block
->set_my_scope(p_scope
);
9440 if(expr
) expr
->set_my_scope(p_scope
);
9441 ref
->set_my_scope(p_scope
);
9442 if(block
) block
->set_my_scope(p_scope
);
9445 if(expr
) expr
->set_my_scope(p_scope
);
9446 invoke
.v
->set_my_scope(p_scope
);
9447 if(invoke
.t_list
) invoke
.t_list
->set_my_scope(p_scope
);
9448 if(invoke
.ap_list
) invoke
.ap_list
->set_my_scope(p_scope
);
9449 if(block
) block
->set_my_scope(p_scope
);
9452 block
->set_my_scope(p_scope
);
9455 FATAL_ERROR("AltGuard::set_my_scope()");
9459 void AltGuard::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9461 switch(altguardtype
) {
9463 stmt
->set_my_sb(p_sb
, p_index
);
9464 block
->set_my_sb(p_sb
, p_index
);
9467 if(block
) block
->set_my_sb(p_sb
, p_index
);
9470 if(block
) block
->set_my_sb(p_sb
, p_index
);
9473 block
->set_my_sb(p_sb
, p_index
);
9476 FATAL_ERROR("AltGuard::set_my_sb()");
9480 void AltGuard::set_fullname(const string
& p_fullname
)
9482 Node::set_fullname(p_fullname
);
9483 switch(altguardtype
) {
9485 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9486 stmt
->set_fullname(p_fullname
+".stmt");
9487 block
->set_fullname(p_fullname
+".block");
9490 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9491 ref
->set_fullname(p_fullname
+".ref");
9492 if(block
) block
->set_fullname(p_fullname
+".block");
9495 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9496 invoke
.v
->set_fullname(p_fullname
+".function");
9497 if(invoke
.t_list
) invoke
.t_list
->set_fullname(p_fullname
+".argument");
9498 if(invoke
.ap_list
) invoke
.ap_list
->set_fullname(p_fullname
+".argument");
9499 if(block
) block
->set_fullname(p_fullname
+".block");
9502 block
->set_fullname(p_fullname
+".elseblock");
9505 FATAL_ERROR("AltGuard::set_fullname()");
9509 Value
*AltGuard::get_guard_expr() const
9511 if (altguardtype
== AG_ELSE
) FATAL_ERROR("AltGuard::get_guard_expr()");
9515 Ref_pard
*AltGuard::get_guard_ref() const
9517 if (altguardtype
!= AG_REF
) FATAL_ERROR("AltGuard::get_guard_ref()");
9521 Statement
*AltGuard::get_guard_stmt() const
9523 if (altguardtype
!= AG_OP
) FATAL_ERROR("AltGuard::get_guard_stmt()");
9527 void AltGuard::set_my_def(Definition
*p_def
)
9529 switch(altguardtype
) {
9531 stmt
->set_my_def(p_def
);
9532 block
->set_my_def(p_def
);
9535 if(block
) block
->set_my_def(p_def
);
9538 if(block
) block
->set_my_def(p_def
);
9541 block
->set_my_def(p_def
);
9544 FATAL_ERROR("AltGuard::set_my_def()");
9548 void AltGuard::set_my_ags(AltGuards
*p_ags
)
9550 switch (altguardtype
) {
9552 block
->set_my_ags(p_ags
);
9555 if (block
) block
->set_my_ags(p_ags
);
9558 if (block
) block
->set_my_ags(p_ags
);
9561 block
->set_my_ags(p_ags
);
9564 FATAL_ERROR("AltGuard::set_my_ags()");
9568 void AltGuard::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9570 switch (altguardtype
) {
9572 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9575 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9578 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9581 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9584 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9588 void AltGuard::chk()
9590 switch(altguardtype
) {
9593 Error_Context
cntxt(expr
, "In guard expression");
9594 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9597 Error_Context
cntxt(stmt
, "In guard operation");
9604 Error_Context
cntxt(expr
, "In guard expression");
9605 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9608 Error_Context
cntxt(ref
, "In guard statement");
9609 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
9611 if (t_ass
->get_asstype() == Common::Assignment::A_ALTSTEP
) {
9612 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *ref
, "call");
9614 ref
->error("Reference to an altstep was expected instead of %s",
9615 t_ass
->get_description().c_str());
9619 if (block
) block
->chk();
9623 Error_Context
cntxt(expr
, "In guard expression");
9624 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9627 if (!invoke
.t_list
) return; //already_checked
9628 Error_Context
cntxt(ref
, "In guard statement");
9629 switch(invoke
.v
->get_valuetype()){
9630 case Value::V_REFER
:
9632 "A value of an altstep type was expected "
9633 "in the argument instead of a `refers' statement,"
9634 " which does not specify any function type");
9636 case Value::V_TTCN3_NULL
:
9638 "A value of an altstep type was expected "
9639 "in the argument instead of a `null' value,"
9640 " which does not specify any function type");
9645 Type
*t
= invoke
.v
->get_expr_governor_last();
9647 switch (t
->get_typetype()) {
9650 case Type::T_ALTSTEP
:
9653 invoke
.v
->error("A value of type altstep was expected instead of "
9654 "`%s'", t
->get_typename().c_str());
9657 invoke
.v
->get_my_scope()->chk_runs_on_clause(t
, *this, "call");
9658 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
9659 invoke
.ap_list
= new Ttcn::ActualParList
;
9660 bool is_erroneous
= fp_list
->chk_actual_parlist(invoke
.t_list
,
9662 delete invoke
.t_list
;
9665 delete invoke
.ap_list
;
9668 invoke
.ap_list
->set_fullname(get_fullname());
9669 invoke
.ap_list
->set_my_scope(invoke
.v
->get_my_scope());
9672 if (block
) block
->chk();
9676 Error_Context
cntxt(this, "In else branch");
9678 Statement
*first_stmt
= block
->get_first_stmt();
9679 if (first_stmt
&& first_stmt
->get_statementtype() ==
9680 Statement::S_REPEAT
)
9681 first_stmt
->warning("The first statement of the [else] branch is a "
9682 "repeat statement. This will result in busy waiting");
9686 FATAL_ERROR("AltGuard::chk()");
9690 void AltGuard::set_code_section(
9691 GovernedSimple::code_section_t p_code_section
)
9693 switch(altguardtype
) {
9695 if (expr
) expr
->set_code_section(p_code_section
);
9696 stmt
->set_code_section(p_code_section
);
9697 block
->set_code_section(p_code_section
);
9700 if (expr
) expr
->set_code_section(p_code_section
);
9701 ref
->set_code_section(p_code_section
);
9702 if (block
) block
->set_code_section(p_code_section
);
9705 if (expr
) expr
->set_code_section(p_code_section
);
9706 invoke
.v
->set_code_section(p_code_section
);
9707 if(invoke
.t_list
) invoke
.t_list
->set_code_section(p_code_section
);
9709 for(size_t i
= 0; i
< invoke
.ap_list
->get_nof_pars(); i
++)
9710 invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
9711 if (block
) block
->set_code_section(p_code_section
);
9714 block
->set_code_section(p_code_section
);
9717 FATAL_ERROR("AltGuard::set_fullname()");
9721 void AltGuard::generate_code_invoke_instance(expression_struct
*p_expr
)
9723 if (altguardtype
!= AG_INVOKE
)
9724 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9725 Value
*last_v
= invoke
.v
->get_value_refd_last();
9726 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
9727 Common::Assignment
*altstep
= last_v
->get_refd_fat();
9728 p_expr
->expr
= mputprintf(p_expr
->expr
, "%s_instance(",
9729 altstep
->get_genname_from_scope(invoke
.v
->get_my_scope()).c_str());
9730 invoke
.ap_list
->generate_code_alias(p_expr
,
9731 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9733 invoke
.v
->generate_code_expr_mandatory(p_expr
);
9734 p_expr
->expr
= mputstr(p_expr
->expr
, ".invoke(");
9735 Type
* gov_last
= invoke
.v
->get_expr_governor_last();
9736 invoke
.ap_list
->generate_code_alias(p_expr
, 0,
9737 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
9739 p_expr
->expr
= mputc(p_expr
->expr
, ')');
9742 // =================================
9744 // =================================
9746 AltGuards::~AltGuards()
9748 for(size_t i
=0; i
<ags
.size(); i
++) delete ags
[i
];
9751 delete il_label_end
;
9754 AltGuards
*AltGuards::clone() const
9756 FATAL_ERROR("AltGuards::clone");
9759 void AltGuards::add_ag(AltGuard
*p_ag
)
9762 FATAL_ERROR("AltGuards::add_ag()");
9766 void AltGuards::set_my_scope(Scope
*p_scope
)
9769 for(size_t i
=0; i
<ags
.size(); i
++)
9770 ags
[i
]->set_my_scope(p_scope
);
9773 void AltGuards::set_fullname(const string
& p_fullname
)
9775 Node::set_fullname(p_fullname
);
9776 for(size_t i
=0; i
<ags
.size(); i
++)
9777 ags
[i
]->set_fullname(p_fullname
+".ag_"+Int2string(i
+1));
9780 void AltGuards::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9782 for(size_t i
=0; i
<ags
.size(); i
++)
9783 ags
[i
]->set_my_sb(p_sb
, p_index
);
9786 void AltGuards::set_my_def(Definition
*p_def
)
9788 for(size_t i
=0; i
<ags
.size(); i
++)
9789 ags
[i
]->set_my_def(p_def
);
9792 void AltGuards::set_my_ags(AltGuards
*p_ags
)
9794 for(size_t i
=0; i
<ags
.size(); i
++)
9795 ags
[i
]->set_my_ags(p_ags
);
9798 void AltGuards::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9800 for(size_t i
=0; i
<ags
.size(); i
++)
9801 ags
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9804 bool AltGuards::has_else() const
9806 for (size_t i
= 0; i
< ags
.size(); i
++)
9807 if (ags
[i
]->get_type() == AltGuard::AG_ELSE
) return true;
9811 StatementBlock::returnstatus_t
AltGuards::has_return() const
9813 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9814 for (size_t i
= 0; i
< ags
.size(); i
++) {
9815 AltGuard
*ag
= ags
[i
];
9816 StatementBlock
*block
= ag
->get_block();
9817 StatementBlock::returnstatus_t block_status
;
9818 if (block
) block_status
= block
->has_return();
9819 else block_status
= StatementBlock::RS_NO
;
9820 switch (block_status
) {
9821 case StatementBlock::RS_NO
:
9822 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9823 else ret_val
= StatementBlock::RS_NO
;
9825 case StatementBlock::RS_YES
:
9826 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9827 else ret_val
= StatementBlock::RS_YES
;
9830 return StatementBlock::RS_MAYBE
;
9832 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9837 bool AltGuards::has_receiving_stmt() const
9839 for(size_t i
=0; i
<ags
.size(); i
++)
9840 if(ags
[i
]->get_block()->has_receiving_stmt()) return true;
9844 void AltGuards::chk()
9846 bool unreach_found
= false;
9847 size_t nof_ags
= ags
.size();
9848 AltGuard
*prev_ag
= 0;
9849 for (size_t i
= 0; i
< nof_ags
; i
++) {
9850 AltGuard
*ag
= ags
[i
];
9852 if (!unreach_found
&& prev_ag
&&
9853 prev_ag
->get_type() == AltGuard::AG_ELSE
) {
9854 ag
->warning("Control never reaches this branch of alternative "
9855 "because of the previous [else] branch");
9856 unreach_found
= true;
9862 void AltGuards::chk_allowed_interleave()
9864 for (size_t i
= 0; i
< ags
.size(); i
++) {
9865 AltGuard
*ag
= ags
[i
];
9866 switch (ag
->get_type()) {
9867 case AltGuard::AG_OP
:
9869 case AltGuard::AG_REF
:
9870 case AltGuard::AG_INVOKE
:
9871 ag
->error("Invocation of an altstep is not allowed within an "
9872 "interleave statement");
9874 case AltGuard::AG_ELSE
:
9875 ag
->error("Else branch of an alternative is not allowed within an "
9876 "interleave statement");
9879 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
9881 ag
->get_block()->chk_allowed_interleave();
9885 void AltGuards::set_code_section(
9886 GovernedSimple::code_section_t p_code_section
)
9888 for (size_t i
= 0; i
< ags
.size(); i
++)
9889 ags
[i
]->set_code_section(p_code_section
);
9892 char *AltGuards::generate_code_alt(char *str
, const Location
& loc
)
9894 bool label_needed
= has_repeat
, has_else_branch
= false;
9895 for (size_t i
= 0; i
< ags
.size(); i
++) {
9896 AltGuard
*ag
= ags
[i
];
9897 switch (ag
->get_type()) {
9898 case AltGuard::AG_OP
:
9899 // trigger may return ALT_REPEAT
9900 if (ag
->get_guard_stmt()->can_repeat()) label_needed
= true;
9902 case AltGuard::AG_REF
:
9903 case AltGuard::AG_INVOKE
:
9904 // an altstep may return ALT_REPEAT
9905 label_needed
= true;
9907 case AltGuard::AG_ELSE
:
9908 has_else_branch
= true;
9911 FATAL_ERROR("AltGuards::generate_code_alt()");
9913 if (has_else_branch
) break;
9915 // if there is no [else] branch the defaults may return ALT_REPEAT
9916 if (!has_else_branch
) label_needed
= true;
9917 // opening bracket of the statement block
9918 str
= mputstr(str
, "{\n");
9919 // the label name is also used for prefixing local variables
9920 if (!my_scope
|| label
) FATAL_ERROR("AltGuards::generate_code_alt()");
9921 label
= new string(my_scope
->get_scope_mod_gen()->get_temporary_id());
9922 const char *label_str
= label
->c_str();
9923 if (label_needed
) str
= mputprintf(str
, "%s:\n", label_str
);
9924 // temporary variables used for caching of status codes
9925 for (size_t i
= 0; i
< ags
.size(); i
++) {
9926 AltGuard
*ag
= ags
[i
];
9927 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9928 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
9929 label_str
, (unsigned long) i
,
9930 ag
->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
9932 if (!has_else_branch
) {
9933 str
= mputprintf(str
, "alt_status %s_default_flag = ALT_MAYBE;\n",
9936 // the first snapshot is taken in non-blocking mode
9937 // and opening infinite for() loop
9938 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
9940 for (size_t i
= 0; i
< ags
.size(); i
++) {
9941 AltGuard
*ag
= ags
[i
];
9942 AltGuard::altguardtype_t agtype
= ag
->get_type();
9943 if (agtype
== AltGuard::AG_ELSE
) {
9944 // an else branch was found
9945 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
9946 StatementBlock
*block
= ag
->get_block();
9947 if (block
->get_nof_stmts() > 0) {
9948 str
= mputstr(str
, "{\n");
9949 str
= block
->generate_code(str
);
9950 str
= mputstr(str
, "}\n");
9952 // jump out of the infinite for() loop
9953 if (block
->has_return() != StatementBlock::RS_YES
)
9954 str
= mputstr(str
, "break;\n");
9955 // do not generate code for further branches
9958 Value
*guard_expr
= ag
->get_guard_expr();
9960 // the branch has a boolean guard expression
9961 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
9962 label_str
, (unsigned long) i
);
9963 str
= guard_expr
->update_location_object(str
);
9964 expression_struct expr
;
9965 Code::init_expr(&expr
);
9966 guard_expr
->generate_code_expr(&expr
);
9967 str
= mputstr(str
, expr
.preamble
);
9968 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
9969 "else %s_alt_flag_%lu = ALT_NO;\n", expr
.expr
, label_str
,
9970 (unsigned long) i
, label_str
, (unsigned long) i
);
9971 str
= mputstr(str
, expr
.postamble
);
9972 Code::free_expr(&expr
);
9973 str
= mputstr(str
, "}\n");
9975 // evaluation of guard operation or altstep
9976 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
9977 label_str
, (unsigned long) i
);
9978 // indicates whether the guard operation might return ALT_REPEAT
9980 expression_struct expr
;
9981 Code::init_expr(&expr
);
9982 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
9985 case AltGuard::AG_OP
: {
9986 // the guard operation is a receiving statement
9987 Statement
*stmt
= ag
->get_guard_stmt();
9988 str
= stmt
->update_location_object(str
);
9989 stmt
->generate_code_expr(&expr
);
9990 can_repeat
= stmt
->can_repeat();
9992 case AltGuard::AG_REF
: {
9993 // the guard operation is an altstep instance
9994 Ref_pard
*ref
= ag
->get_guard_ref();
9995 str
= ref
->update_location_object(str
);
9996 Common::Assignment
*altstep
= ref
->get_refd_assignment();
9997 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
9998 altstep
->get_genname_from_scope(my_scope
).c_str());
9999 ref
->get_parlist()->generate_code_alias(&expr
,
10000 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10001 expr
.expr
= mputc(expr
.expr
, ')');
10004 case AltGuard::AG_INVOKE
: {
10005 // the guard operation is an altstep invocation
10006 str
= ag
->update_location_object(str
);
10007 ag
->generate_code_invoke_instance(&expr
);
10011 FATAL_ERROR("AltGuards::generate_code_alt()");
10013 str
= Code::merge_free_expr(str
, &expr
);
10015 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
10016 label_str
, (unsigned long) i
, label_str
);
10018 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10019 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
10020 label_str
, (unsigned long) i
);
10022 // execution of statement block if the guard was successful
10023 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10024 (unsigned long) i
);
10025 StatementBlock
*block
= ag
->get_block();
10026 if (block
&& block
->get_nof_stmts() > 0) {
10027 str
= mputstr(str
, "{\n");
10028 str
= block
->generate_code(str
);
10029 if (block
->has_return() != StatementBlock::RS_YES
)
10030 str
= mputstr(str
, "break;\n");
10031 str
= mputstr(str
, "}\n");
10032 } else str
= mputstr(str
, "break;\n");
10033 // closing of if() block
10034 str
= mputstr(str
, "}\n");
10037 if (!has_else_branch
) {
10038 // calling of defaults
10039 str
= mputprintf(str
, "if (%s_default_flag == ALT_MAYBE) {\n"
10040 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10041 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10043 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10045 label_str
, label_str
, label_str
, label_str
, label_str
, label_str
);
10046 str
= loc
.update_location_object(str
);
10047 // error handling and taking the next snapshot in blocking mode
10048 str
= mputstr(str
, "if (");
10049 for (size_t i
= 0; i
< ags
.size(); i
++)
10050 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO && ", label_str
,
10051 (unsigned long) i
);
10052 str
= mputprintf(str
,"%s_default_flag == ALT_NO) "
10053 "TTCN_error(\"None of the branches can be chosen in the alt "
10054 "statement in file ", label_str
);
10055 str
= Code::translate_string(str
, loc
.get_filename());
10056 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10057 if (first_line
< last_line
) str
= mputprintf(str
,
10058 " between lines %d and %d", first_line
, last_line
);
10059 else str
= mputprintf(str
, ", line %d", first_line
);
10060 str
= mputstr(str
, ".\");\n"
10061 "TTCN_Snapshot::take_new(TRUE);\n");
10063 // end of for() statement and the statement block
10064 str
= mputstr(str
, "}\n"
10069 char *AltGuards::generate_code_altstep(char *str
)
10071 if (!my_scope
) FATAL_ERROR("AltGuards::generate_code_altstep()");
10072 Common::Module
*my_mod
= my_scope
->get_scope_mod_gen();
10073 bool has_else_branch
= has_else();
10074 if (!has_else_branch
) {
10075 str
= mputstr(str
, "alt_status ret_val = ALT_NO;\n");
10077 for (size_t i
= 0; i
< ags
.size(); i
++) {
10078 AltGuard
*ag
= ags
[i
];
10079 AltGuard::altguardtype_t agtype
= ag
->get_type();
10080 if (agtype
== AltGuard::AG_ELSE
) {
10081 // an else branch was found
10082 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10083 StatementBlock
*block
= ag
->get_block();
10084 if (block
->get_nof_stmts() > 0) {
10085 str
= mputstr(str
, "{\n");
10086 str
= block
->generate_code(str
);
10087 str
= mputstr(str
, "}\n");
10089 if (block
->has_return() != StatementBlock::RS_YES
)
10090 str
= mputstr(str
, "return ALT_YES;\n");
10091 // do not generate code for further branches
10094 size_t blockcount
= 0;
10095 Value
*guard_expr
= ag
->get_guard_expr();
10097 // the branch has a boolean guard expression
10098 str
= guard_expr
->update_location_object(str
);
10099 str
= guard_expr
->generate_code_tmp(str
, "if (", blockcount
);
10100 str
= mputstr(str
, ") {\n");
10103 // indicates whether the guard operation might return ALT_REPEAT
10105 expression_struct expr
;
10106 Code::init_expr(&expr
);
10108 case AltGuard::AG_OP
: {
10109 // the guard operation is a receiving statement
10110 Statement
*stmt
= ag
->get_guard_stmt();
10111 str
= stmt
->update_location_object(str
);
10112 stmt
->generate_code_expr(&expr
);
10113 can_repeat
= stmt
->can_repeat();
10115 case AltGuard::AG_REF
: {
10116 // the guard operation is an altstep instance
10117 Ref_pard
*ref
= ag
->get_guard_ref();
10118 str
= ref
->update_location_object(str
);
10119 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10120 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10121 altstep
->get_genname_from_scope(my_scope
).c_str());
10122 ref
->get_parlist()->generate_code_alias(&expr
,
10123 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10124 expr
.expr
= mputc(expr
.expr
, ')');
10127 case AltGuard::AG_INVOKE
: {
10128 str
= ag
->update_location_object(str
);
10129 ag
->generate_code_invoke_instance(&expr
);
10133 FATAL_ERROR("AltGuards::generate_code_altstep()");
10135 if (expr
.preamble
|| expr
.postamble
) {
10136 if (blockcount
== 0) {
10137 // open a statement block if it is not done so far
10138 str
= mputstr(str
, "{\n");
10141 const string
& tmp_id
= my_mod
->get_temporary_id();
10142 const char *tmp_id_str
= tmp_id
.c_str();
10143 str
= mputprintf(str
, "alt_status %s;\n"
10144 "{\n", tmp_id_str
);
10145 str
= mputstr(str
, expr
.preamble
);
10146 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, expr
.expr
);
10147 str
= mputstr(str
, expr
.postamble
);
10148 str
= mputprintf(str
, "}\n"
10149 "switch (%s) {\n", tmp_id_str
);
10151 str
= mputprintf(str
, "switch (%s) {\n", expr
.expr
);
10153 Code::free_expr(&expr
);
10154 str
= mputstr(str
, "case ALT_YES:\n");
10155 StatementBlock
*block
= ag
->get_block();
10156 if (block
&& block
->get_nof_stmts() > 0) {
10157 str
= mputstr(str
, "{\n");
10158 str
= block
->generate_code(str
);
10159 str
= mputstr(str
, "}\n");
10161 if (!block
|| block
->has_return() != StatementBlock::RS_YES
)
10162 str
= mputstr(str
, "return ALT_YES;\n");
10164 str
= mputstr(str
, "case ALT_REPEAT:\n"
10165 "return ALT_REPEAT;\n");
10166 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10167 str
= mputprintf(str
, "case ALT_BREAK:\n"
10168 "return ALT_BREAK;\n");
10170 if (!has_else_branch
)
10171 str
= mputstr(str
, "case ALT_MAYBE:\n"
10172 "ret_val = ALT_MAYBE;\n");
10173 str
= mputstr(str
, "default:\n"
10176 // closing statement blocks
10177 for ( ; blockcount
> 0; blockcount
--) str
= mputstr(str
, "}\n");
10180 if (!has_else_branch
) str
= mputstr(str
, "return ret_val;\n");
10184 char* AltGuards::generate_code_call_body(char *str
, const Location
& loc
,
10185 const string
& temp_id
, bool in_interleave
)
10187 if (label
) FATAL_ERROR("AltGuards::generate_code_call_body()");
10188 label
= new string(temp_id
);
10189 const char *label_str
= temp_id
.c_str();
10190 // label is needed only if there is a repeat statement in the branches
10191 if (has_repeat
) str
= mputprintf(str
, "%s:\n", label_str
);
10192 // temporary variables used for caching of status codes
10193 for (size_t i
= 0; i
< ags
.size(); i
++)
10194 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10195 label_str
, (unsigned long) i
,
10196 ags
[i
]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10197 str
= loc
.update_location_object(str
);
10198 // the first snapshot is taken in non-blocking mode
10199 // and opening infinite for() loop
10200 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10201 "for ( ; ; ) {\n"); // (1)
10202 for (size_t i
= 0; i
< ags
.size(); i
++) {
10203 AltGuard
*ag
= ags
[i
];
10204 if (ag
->get_type() != AltGuard::AG_OP
)
10205 FATAL_ERROR("AltGuards::generate_code_call_body()");
10206 Value
*guard_expr
= ag
->get_guard_expr();
10208 // the branch has a boolean guard expression
10209 str
= mputprintf(str
,
10210 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10211 label_str
, (unsigned long) i
);
10212 str
= guard_expr
->update_location_object(str
);
10213 expression_struct expr
;
10214 Code::init_expr(&expr
);
10215 guard_expr
->generate_code_expr(&expr
);
10216 str
= mputstr(str
, expr
.preamble
);
10217 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10218 "else %s_alt_flag_%lu = ALT_NO;\n",
10219 expr
.expr
, label_str
, (unsigned long) i
,
10220 label_str
, (unsigned long) i
);
10221 str
= mputstr(str
, expr
.postamble
);
10222 Code::free_expr(&expr
);
10223 str
= mputstr(str
, "}\n"); // (2)
10225 // evaluation of guard operation
10226 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10227 label_str
, (unsigned long) i
);
10228 expression_struct expr
;
10229 Code::init_expr(&expr
);
10230 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10231 (unsigned long) i
);
10232 Statement
*stmt
= ag
->get_guard_stmt();
10233 str
= stmt
->update_location_object(str
);
10234 stmt
->generate_code_expr(&expr
);
10235 str
= Code::merge_free_expr(str
, &expr
);
10236 // execution of statement block if the guard was successful
10237 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10238 (unsigned long) i
);
10239 StatementBlock
*block
= ag
->get_block();
10240 if(in_interleave
) {
10241 if(block
&& block
->get_nof_stmts() > 0) {
10242 if(block
->has_receiving_stmt()) {
10243 str
= mputprintf(str
, "goto %s_branch%lu;\n",
10244 label_str
, (unsigned long) i
);
10247 str
= mputstr(str
, "{\n"); // (3)
10248 str
= block
->generate_code(str
);
10249 str
= mputprintf(str
, "goto %s_end;\n"
10254 else str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10257 if (block
&& block
->get_nof_stmts() > 0) {
10258 str
= mputstr(str
, "{\n"); // (3)
10259 str
= block
->generate_code(str
);
10260 if (block
->has_return() != StatementBlock::RS_YES
)
10261 str
= mputstr(str
, "break;\n");
10262 str
= mputstr(str
, "}\n"); // (3)
10264 else str
= mputstr(str
, "break;\n");
10266 // closing of if() block
10267 str
= mputstr(str
, "}\n"); // (2)
10269 str
= loc
.update_location_object(str
);
10270 // error handling and taking the next snapshot in blocking mode
10271 str
= mputstr(str
, "if (");
10272 for (size_t i
= 0; i
< ags
.size(); i
++) {
10273 if (i
> 0) str
= mputstr(str
, " && ");
10274 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO", label_str
,
10275 (unsigned long) i
);
10277 str
= mputstr(str
, ") TTCN_error(\"None of the branches can be chosen in "
10278 "the response and exception handling part of call statement in file ");
10279 str
= Code::translate_string(str
, loc
.get_filename());
10280 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10281 if (first_line
< last_line
) str
= mputprintf(str
,
10282 " between lines %d and %d", first_line
, last_line
);
10283 else str
= mputprintf(str
, ", line %d", first_line
);
10284 str
= mputstr(str
, ".\");\n"
10285 "TTCN_Snapshot::take_new(TRUE);\n"
10290 void AltGuards::ilt_generate_code_call_body(ILT
*ilt
, const char *label_str
)
10292 char*& str
=ilt
->get_out_branches();
10293 for(size_t i
=0; i
<ags
.size(); i
++) {
10294 StatementBlock
*block
= ags
[i
]->get_block();
10295 if (block
&& block
->has_receiving_stmt()) {
10296 str
= mputprintf(str
, "%s_branch%lu:\n", label_str
, (unsigned long) i
);
10297 block
->ilt_generate_code(ilt
);
10298 str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10303 } // namespace Ttcn