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
) {
474 delete undefstartstop
.ref
;
475 delete undefstartstop
.val
;
477 case S_UNKNOWN_INSTANCE
:
478 case S_FUNCTION_INSTANCE
:
479 case S_ALTSTEP_INSTANCE
:
494 case S_STOP_TESTCASE
:
506 delete if_stmt
.elseblock
;
507 delete if_stmt
.elseblock_location
;
514 if(loop
.for_stmt
.varinst
)
515 delete loop
.for_stmt
.init_varinst
;
517 delete loop
.for_stmt
.init_ass
;
518 delete loop
.for_stmt
.finalexpr
;
519 delete loop
.for_stmt
.step
;
522 delete loop
.label_next
;
523 if (loop
.il_label_end
)
524 delete loop
.il_label_end
;
531 delete loop
.label_next
;
532 if (loop
.il_label_end
)
533 delete loop
.il_label_end
;
547 delete port_op
.portref
;
548 delete port_op
.s
.sendpar
;
549 delete port_op
.s
.toclause
;
552 delete port_op
.portref
;
553 delete port_op
.s
.sendpar
;
554 delete port_op
.s
.call
.timer
;
555 delete port_op
.s
.toclause
;
556 delete port_op
.s
.call
.body
;
559 delete port_op
.portref
;
560 delete port_op
.s
.sendpar
;
561 delete port_op
.s
.replyval
;
562 delete port_op
.s
.toclause
;
565 delete port_op
.portref
;
566 delete port_op
.s
.raise
.signature_ref
;
567 delete port_op
.s
.sendpar
;
568 delete port_op
.s
.toclause
;
571 case S_CHECK_RECEIVE
:
573 delete port_op
.portref
;
574 delete port_op
.r
.rcvpar
;
575 delete port_op
.r
.fromclause
;
576 delete port_op
.r
.redirect
.value
;
577 delete port_op
.r
.redirect
.sender
;
580 case S_CHECK_GETCALL
:
581 delete port_op
.portref
;
582 delete port_op
.r
.rcvpar
;
583 delete port_op
.r
.fromclause
;
584 delete port_op
.r
.redirect
.param
;
585 delete port_op
.r
.redirect
.sender
;
588 case S_CHECK_GETREPLY
:
589 delete port_op
.portref
;
590 delete port_op
.r
.rcvpar
;
591 delete port_op
.r
.getreply_valuematch
;
592 delete port_op
.r
.fromclause
;
593 delete port_op
.r
.redirect
.value
;
594 delete port_op
.r
.redirect
.param
;
595 delete port_op
.r
.redirect
.sender
;
599 delete port_op
.portref
;
600 delete port_op
.r
.ctch
.signature_ref
;
601 delete port_op
.r
.rcvpar
;
602 delete port_op
.r
.fromclause
;
603 delete port_op
.r
.redirect
.value
;
604 delete port_op
.r
.redirect
.sender
;
607 delete port_op
.portref
;
608 delete port_op
.r
.fromclause
;
609 delete port_op
.r
.redirect
.sender
;
615 delete port_op
.portref
;
618 delete comp_op
.compref
;
619 delete comp_op
.funcinstref
;
621 case S_START_COMP_REFD
:
622 delete comp_op
.compref
;
623 delete comp_op
.derefered
.value
;
624 delete comp_op
.derefered
.ap_list2
;
629 delete comp_op
.compref
;
632 if (comp_op
.compref
) {
633 delete comp_op
.compref
;
634 delete comp_op
.donereturn
.donematch
;
635 delete comp_op
.donereturn
.redirect
;
642 delete config_op
.compref1
;
643 delete config_op
.portref1
;
644 delete config_op
.compref2
;
645 delete config_op
.portref2
;
648 delete timer_op
.timerref
;
649 delete timer_op
.value
;
653 delete timer_op
.timerref
;
656 delete setverdict
.verdictval
;
657 delete setverdict
.logargs
;
659 case S_TESTCASE_INSTANCE
:
660 delete testcase_inst
.tcref
;
661 delete testcase_inst
.timerval
;
663 case S_TESTCASE_INSTANCE_REFD
:
664 delete execute_refd
.value
;
665 delete execute_refd
.ap_list2
;
666 delete execute_refd
.timerval
;
668 case S_ACTIVATE_REFD
:
669 case S_UNKNOWN_INVOKED
:
670 case S_FUNCTION_INVOKED
:
671 case S_ALTSTEP_INVOKED
:
672 delete fau_refd
.value
;
673 delete fau_refd
.ap_list2
;
680 FATAL_ERROR("Statement::clean_up()");
681 } // switch statementtype
684 Statement::Statement(statementtype_t p_st
)
685 : statementtype(p_st
), my_sb(0)
687 switch(statementtype
) {
699 FATAL_ERROR("Statement::Statement()");
700 } // switch statementtype
703 Statement::Statement(statementtype_t p_st
, Ref_base
*p_ref
, Value
*p_val
)
704 : statementtype(p_st
), my_sb(0)
706 switch(statementtype
) {
708 if (!p_ref
) FATAL_ERROR("Statement::Statement()");
709 undefstartstop
.ref
=p_ref
;
710 undefstartstop
.val
=p_val
;
713 if (!p_ref
|| p_val
) FATAL_ERROR("Statement::Statement()");
714 undefstartstop
.ref
=p_ref
;
715 undefstartstop
.val
=0;
718 FATAL_ERROR("Statement::Statement()");
719 } // switch statementtype
722 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
)
723 : statementtype(p_st
), my_sb(0)
725 switch(statementtype
) {
726 case S_UNKNOWN_INSTANCE
:
727 case S_FUNCTION_INSTANCE
:
728 case S_ALTSTEP_INSTANCE
:
731 FATAL_ERROR("Statement::Statement()");
735 FATAL_ERROR("Statement::Statement()");
736 } // switch statementtype
739 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
740 ParsedActualParameters
*p_ap_list
)
741 : statementtype(p_st
), my_sb(0)
743 switch(statementtype
) {
744 case S_ACTIVATE_REFD
:
745 case S_UNKNOWN_INVOKED
:
746 case S_FUNCTION_INVOKED
:
747 case S_ALTSTEP_INVOKED
:
748 if(!p_derefered_value
|| !p_ap_list
)
749 FATAL_ERROR("Statement::Statement()");
750 fau_refd
.value
= p_derefered_value
;
751 fau_refd
.t_list1
= p_ap_list
;
754 FATAL_ERROR("Statement::Statement()");
758 Statement::Statement(statementtype_t p_st
, Definition
*p_def
)
759 : statementtype(p_st
), my_sb(0)
761 switch(statementtype
) {
764 FATAL_ERROR("Statement::Statement()");
768 FATAL_ERROR("Statement::Statement()");
769 } // switch statementtype
772 Statement::Statement(statementtype_t p_st
, Assignment
*p_ass
)
773 : statementtype(p_st
), my_sb(0)
775 switch(statementtype
) {
778 FATAL_ERROR("Statement::Statement()");
782 FATAL_ERROR("Statement::Statement()");
783 } // switch statementtype
786 Statement::Statement(statementtype_t p_st
, StatementBlock
*p_block
)
787 : statementtype(p_st
), my_sb(0)
789 switch (statementtype
) {
791 if (!p_block
) FATAL_ERROR("Statement::Statement()");
795 FATAL_ERROR("Statement::Statement()");
796 } // switch statementtype
799 Statement::Statement(statementtype_t p_st
, LogArguments
*p_logargs
)
800 : statementtype(p_st
), my_sb(0)
802 switch(statementtype
) {
805 case S_STOP_TESTCASE
:
809 FATAL_ERROR("Statement::Statement()");
810 } // switch statementtype
813 Statement::Statement(statementtype_t p_st
, Identifier
*p_id
)
814 : statementtype(p_st
), my_sb(0)
817 FATAL_ERROR("Statement::Statement()");
818 switch (statementtype
) {
829 go_to
.jumps_forward
= false;
832 FATAL_ERROR("Statement::Statement()");
833 } // switch statementtype
836 Statement::Statement(statementtype_t p_st
, IfClauses
*p_ics
,
837 StatementBlock
*p_block
, Location
*p_loc
)
838 : statementtype(p_st
), my_sb(0)
840 switch(statementtype
) {
843 FATAL_ERROR("Statement::Statement()");
846 if (!p_loc
) FATAL_ERROR("Statement::Statement()");
847 if_stmt
.elseblock
= p_block
;
848 if_stmt
.elseblock_location
= p_loc
;
850 if (p_loc
) FATAL_ERROR("Statement::Statement()");
851 if_stmt
.elseblock
= 0;
852 if_stmt
.elseblock_location
= 0;
856 FATAL_ERROR("Statement::Statement()");
857 } // switch statementtype
860 Statement::Statement(statementtype_t p_st
, Value
*p_expr
, SelectCases
*p_scs
)
861 : statementtype(p_st
), my_sb(0)
863 switch(statementtype
) {
865 if(!p_expr
|| !p_scs
)
866 FATAL_ERROR("Statement::Statement()");
871 FATAL_ERROR("Statement::Statement()");
872 } // switch statementtype
875 Statement::Statement(statementtype_t p_st
, Definitions
*p_defs
,
876 Assignment
*p_ass
, Value
*p_final
,
877 Assignment
*p_step
, StatementBlock
*p_block
)
878 : statementtype(p_st
), my_sb(0)
880 switch (statementtype
) {
881 case S_FOR
: // precisely one of p_defs, p_ass allowed
883 // it came from a for loop which looked like this:
884 // for (var integer foo:=1; foo<10; foo:=foo+1) ;
885 if (p_ass
) FATAL_ERROR("Statement::Statement()");
886 loop
.for_stmt
.varinst
= true;
887 loop
.for_stmt
.init_varinst
= p_defs
;
889 // it came from a for loop which looked like this:
890 // for (foo:=1; foo<10; foo:=foo+1) ;
891 if (!p_ass
) FATAL_ERROR("Statement::Statement()");
892 loop
.for_stmt
.varinst
= false;
893 loop
.for_stmt
.init_ass
= p_ass
;
895 if(!p_final
|| !p_step
|| !p_block
)
896 FATAL_ERROR("Statement::Statement()");
897 loop
.for_stmt
.finalexpr
=p_final
;
898 loop
.for_stmt
.step
=p_step
;
904 loop
.has_cnt_in_ags
=false;
905 loop
.iterate_once
=false; // not used by for
909 FATAL_ERROR("Statement::Statement()");
910 } // switch statementtype
913 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
914 StatementBlock
*p_block
)
915 : statementtype(p_st
), my_sb(0)
917 switch(statementtype
) {
920 if(!p_val
|| !p_block
)
921 FATAL_ERROR("Statement::Statement()");
928 loop
.has_cnt_in_ags
=false;
929 loop
.iterate_once
=false; // used only by do-while
933 FATAL_ERROR("Statement::Statement()");
934 } // switch statementtype
937 Statement::Statement(statementtype_t p_st
, AltGuards
*p_ags
)
938 : statementtype(p_st
), my_sb(0)
940 switch(statementtype
) {
944 FATAL_ERROR("Statement::Statement()");
948 FATAL_ERROR("Statement::Statement()");
949 } // switch statementtype
952 Statement::Statement(statementtype_t p_st
, Template
*p_temp
)
953 : statementtype(p_st
), my_sb(0)
955 switch(statementtype
) {
961 FATAL_ERROR("Statement::Statement()");
962 } // switch statementtype
965 Statement::Statement(statementtype_t p_st
, Value
*p_val
)
966 : statementtype(p_st
), my_sb(0)
968 switch (statementtype
) {
971 FATAL_ERROR("Statement::Statement()");
975 comp_op
.compref
=p_val
;
981 FATAL_ERROR("Statement::Statement()");
982 } // switch statementtype
985 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
986 LogArguments
*p_logargs
)
987 : statementtype(p_st
), my_sb(0)
989 if (!p_val
|| statementtype
!= S_SETVERDICT
)
990 FATAL_ERROR("Statement::Statement()");
991 setverdict
.verdictval
= p_val
;
992 setverdict
.logargs
= p_logargs
;
995 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
996 TemplateInstance
*p_templinst
, Value
*p_val
)
997 : statementtype(p_st
), my_sb(0)
999 switch(statementtype
) {
1001 if(!p_ref
|| !p_templinst
)
1002 FATAL_ERROR("Statement::Statement()");
1003 port_op
.portref
=p_ref
;
1004 port_op
.s
.sendpar
=p_templinst
;
1005 port_op
.s
.toclause
=p_val
;
1008 FATAL_ERROR("Statement::Statement()");
1009 } // switch statementtype
1012 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1013 TemplateInstance
*p_templinst
, Value
*p_timerval
,
1014 bool p_nowait
, Value
*p_toclause
, AltGuards
*p_callbody
)
1015 : statementtype(p_st
), my_sb(0)
1017 switch(statementtype
) {
1019 if(!p_ref
|| !p_templinst
|| (p_timerval
&& p_nowait
))
1020 FATAL_ERROR("Statement::Statement()");
1021 port_op
.portref
=p_ref
;
1022 port_op
.s
.sendpar
=p_templinst
;
1023 port_op
.s
.call
.timer
=p_timerval
;
1024 port_op
.s
.call
.nowait
=p_nowait
;
1025 port_op
.s
.toclause
=p_toclause
;
1026 port_op
.s
.call
.body
=p_callbody
;
1029 FATAL_ERROR("Statement::Statement()");
1030 } // switch statementtype
1033 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1034 TemplateInstance
*p_templinst
, Value
*p_replyval
,
1036 : statementtype(p_st
), my_sb(0)
1038 switch(statementtype
) {
1040 if(!p_ref
|| !p_templinst
)
1041 FATAL_ERROR("Statement::Statement()");
1042 port_op
.portref
=p_ref
;
1043 port_op
.s
.sendpar
=p_templinst
;
1044 port_op
.s
.replyval
=p_replyval
;
1045 port_op
.s
.toclause
=p_toclause
;
1048 FATAL_ERROR("Statement::Statement()");
1049 } // switch statementtype
1052 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1053 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1055 : statementtype(p_st
), my_sb(0)
1057 switch(statementtype
) {
1059 if(!p_ref
|| !p_templinst
|| !p_sig
)
1060 FATAL_ERROR("Statement::Statement()");
1061 port_op
.portref
=p_ref
;
1062 port_op
.s
.raise
.signature_ref
=p_sig
;
1063 port_op
.s
.raise
.signature
=0;
1064 port_op
.s
.sendpar
=p_templinst
;
1065 port_op
.s
.toclause
=p_toclause
;
1068 FATAL_ERROR("Statement::Statement()");
1069 } // switch statementtype
1072 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1073 TemplateInstance
*p_templinst
,
1074 TemplateInstance
*p_fromclause
,
1075 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1076 : statementtype(p_st
), my_sb(0)
1078 switch(statementtype
) {
1080 case S_CHECK_RECEIVE
:
1082 port_op
.portref
=p_ref
;
1083 port_op
.r
.rcvpar
=p_templinst
;
1084 port_op
.r
.fromclause
=p_fromclause
;
1085 port_op
.r
.redirect
.value
=p_redirectval
;
1086 port_op
.r
.redirect
.param
=0;
1087 port_op
.r
.redirect
.sender
=p_redirectsender
;
1090 FATAL_ERROR("Statement::Statement()");
1091 } // switch statementtype
1094 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1095 TemplateInstance
*p_templinst
,
1096 TemplateInstance
*p_fromclause
,
1097 ParamRedirect
*p_redirectparam
,
1098 Reference
*p_redirectsender
)
1099 : statementtype(p_st
), my_sb(0)
1101 switch(statementtype
) {
1103 case S_CHECK_GETCALL
:
1104 port_op
.portref
=p_ref
;
1105 port_op
.r
.rcvpar
=p_templinst
;
1106 port_op
.r
.fromclause
=p_fromclause
;
1107 port_op
.r
.redirect
.value
=0;
1108 port_op
.r
.redirect
.param
=p_redirectparam
;
1109 port_op
.r
.redirect
.sender
=p_redirectsender
;
1112 FATAL_ERROR("Statement::Statement()");
1113 } // switch statementtype
1116 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1117 TemplateInstance
*p_templinst
,
1118 TemplateInstance
*p_valuematch
,
1119 TemplateInstance
*p_fromclause
,
1120 Reference
*p_redirectval
, ParamRedirect
*p_redirectparam
,
1121 Reference
*p_redirectsender
)
1122 : statementtype(p_st
), my_sb(0)
1124 switch(statementtype
) {
1126 case S_CHECK_GETREPLY
:
1127 if (!p_templinst
&& p_valuematch
) FATAL_ERROR("Statement::Statement()");
1128 port_op
.portref
=p_ref
;
1129 port_op
.r
.rcvpar
=p_templinst
;
1130 port_op
.r
.getreply_valuematch
=p_valuematch
;
1131 port_op
.r
.fromclause
=p_fromclause
;
1132 port_op
.r
.redirect
.value
=p_redirectval
;
1133 port_op
.r
.redirect
.param
=p_redirectparam
;
1134 port_op
.r
.redirect
.sender
=p_redirectsender
;
1137 FATAL_ERROR("Statement::Statement()");
1138 } // switch statementtype
1141 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1142 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1143 bool p_timeout
, TemplateInstance
*p_fromclause
,
1144 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1145 : statementtype(p_st
), my_sb(0)
1147 switch(statementtype
) {
1150 if (((p_sig
|| p_templinst
) && p_timeout
) ||
1151 (p_sig
&& !p_templinst
) || (!p_sig
&& p_templinst
))
1152 FATAL_ERROR("Statement::Statement()");
1153 port_op
.portref
=p_ref
;
1154 port_op
.r
.ctch
.signature_ref
=p_sig
;
1155 port_op
.r
.ctch
.signature
=0;
1156 port_op
.r
.rcvpar
=p_templinst
;
1157 port_op
.r
.ctch
.timeout
=p_timeout
;
1158 port_op
.r
.ctch
.in_call
=false;
1159 port_op
.r
.ctch
.call_has_timer
=false;
1160 port_op
.r
.fromclause
=p_fromclause
;
1161 port_op
.r
.redirect
.value
=p_redirectval
;
1162 port_op
.r
.redirect
.param
=0;
1163 port_op
.r
.redirect
.sender
=p_redirectsender
;
1166 FATAL_ERROR("Statement::Statement()");
1167 } // switch statementtype
1170 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1171 TemplateInstance
*p_fromclause
,
1172 Reference
*p_redirectsender
)
1173 : statementtype(p_st
), my_sb(0)
1175 switch(statementtype
) {
1177 port_op
.portref
=p_ref
; // may be NULL for "any port.check"
1178 port_op
.r
.fromclause
=p_fromclause
;
1179 port_op
.r
.redirect
.value
=0;
1180 port_op
.r
.redirect
.param
=0;
1181 port_op
.r
.redirect
.sender
=p_redirectsender
;
1184 FATAL_ERROR("Statement::Statement()");
1185 } // switch statementtype
1188 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
)
1189 : statementtype(p_st
), my_sb(0)
1191 switch(statementtype
) {
1196 port_op
.portref
=p_ref
;
1200 timer_op
.timerref
=p_ref
;
1203 FATAL_ERROR("Statement::Statement()");
1204 } // switch statementtype
1207 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1208 Ref_pard
*p_funcinst
)
1209 : statementtype(p_st
), my_sb(0)
1211 switch(statementtype
) {
1213 if(!p_compref
|| !p_funcinst
)
1214 FATAL_ERROR("Statement::Statement()");
1215 comp_op
.compref
= p_compref
;
1216 comp_op
.funcinstref
= p_funcinst
;
1219 FATAL_ERROR("Statement::Statement()");
1220 } // switch statementtype
1223 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1224 Value
*p_derefered_value
, ParsedActualParameters
*p_ap_list
)
1225 : statementtype(p_st
), my_sb(0)
1227 switch(statementtype
) {
1228 case S_START_COMP_REFD
:
1229 if(!p_compref
|| !p_derefered_value
|| !p_ap_list
)
1230 FATAL_ERROR("Statement::Statement()");
1231 comp_op
.compref
= p_compref
;
1232 comp_op
.derefered
.value
= p_derefered_value
;
1233 comp_op
.derefered
.t_list1
= p_ap_list
;
1236 FATAL_ERROR("Statement::Statement()");
1240 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1241 TemplateInstance
*p_donematch
, Reference
*p_redirect
)
1242 : statementtype(p_st
), my_sb(0)
1244 switch (statementtype
) {
1246 if (!p_compref
) FATAL_ERROR("Statement::Statement()");
1247 comp_op
.compref
= p_compref
;
1248 comp_op
.donereturn
.donematch
= p_donematch
;
1249 comp_op
.donereturn
.redirect
= p_redirect
;
1252 FATAL_ERROR("Statement::Statement()");
1253 } // switch statementtype
1256 Statement::Statement(statementtype_t p_st
, component_t p_anyall
)
1257 : statementtype(p_st
), my_sb(0)
1259 switch (statementtype
) {
1262 comp_op
.compref
= 0;
1263 comp_op
.any_or_all
= p_anyall
;
1266 FATAL_ERROR("Statement::Statement()");
1267 } // switch statementtype
1270 Statement::Statement(statementtype_t p_st
,
1271 Value
*p_compref1
, Reference
*p_portref1
,
1272 Value
*p_compref2
, Reference
*p_portref2
)
1273 : statementtype(p_st
), my_sb(0)
1275 switch(statementtype
) {
1280 if(!p_compref1
|| !p_portref1
|| !p_compref2
|| !p_portref2
)
1281 FATAL_ERROR("Statement::Statement()");
1282 config_op
.compref1
=p_compref1
;
1283 config_op
.portref1
=p_portref1
;
1284 config_op
.compref2
=p_compref2
;
1285 config_op
.portref2
=p_portref2
;
1288 FATAL_ERROR("Statement::Statement()");
1289 } // switch statementtype
1292 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
, Value
*p_val
)
1293 : statementtype(p_st
), my_sb(0)
1295 switch(statementtype
) {
1296 case S_TESTCASE_INSTANCE
:
1298 FATAL_ERROR("Statement::Statement()");
1299 testcase_inst
.tcref
=p_ref
;
1300 testcase_inst
.timerval
=p_val
;
1303 FATAL_ERROR("Statement::Statement()");
1304 } // switch statementtype
1307 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
1308 TemplateInstances
*p_ap_list
, Value
*p_val
)
1309 : statementtype(p_st
), my_sb(0)
1311 switch(statementtype
) {
1312 case S_TESTCASE_INSTANCE_REFD
:
1313 if(!p_derefered_value
) FATAL_ERROR("Statement::Statement()");
1314 execute_refd
.value
= p_derefered_value
;
1315 execute_refd
.t_list1
= p_ap_list
;
1316 execute_refd
.timerval
= p_val
;
1319 FATAL_ERROR("Statement::Statement()");
1323 Statement::Statement(statementtype_t p_st
, Value
* p_val
, Reference
* p_ref
): statementtype(p_st
), my_sb(0)
1325 if (p_st
!=S_STRING2TTCN
|| p_val
==NULL
|| p_ref
==NULL
) FATAL_ERROR("Statement::Statement()");
1326 str2ttcn
.val
= p_val
;
1327 str2ttcn
.ref
= p_ref
;
1330 Statement::~Statement()
1335 Statement
*Statement::clone() const
1337 FATAL_ERROR("Statement::clone");
1340 void Statement::dump(unsigned int level
) const
1342 DEBUG(level
, "Statement at %p, a(n) %s", (const void *)this,
1344 switch (statementtype
) {
1345 case S_TESTCASE_INSTANCE
:
1346 case S_TESTCASE_INSTANCE_REFD
: {
1347 Common::Value
*v
= execute_refd
.value
;
1351 def
->dump(level
+ 1);
1354 ass
->dump(level
+ 1);
1357 block
->dump(level
+ 1);
1360 if_stmt
.ics
->dump(level
+ 1);
1361 if (if_stmt
.elseblock
) if_stmt
.elseblock
->dump(level
+ 1);
1368 size_t Statement::get_my_sb_index() const
1370 switch (statementtype
) {
1372 return label
.stmt_idx
;
1374 return go_to
.stmt_idx
;
1376 FATAL_ERROR("Statement::get_my_sb_index()");
1381 const char *Statement::get_stmt_name() const
1383 switch(statementtype
) {
1384 case S_ERROR
: return "<erroneous statement>";
1385 case S_START_UNDEF
: return "start";
1386 case S_STOP_UNDEF
: return "stop";
1387 case S_UNKNOWN_INSTANCE
: return "function or altstep instance";
1388 case S_UNKNOWN_INVOKED
: return "function or altstep type invocation";
1389 case S_DEF
: return "definition";
1390 case S_ASSIGNMENT
: return "assignment";
1391 case S_FUNCTION_INSTANCE
: return "function instance";
1392 case S_FUNCTION_INVOKED
: return "function type invocation";
1393 case S_BLOCK
: return "statement block";
1394 case S_LOG
: return "log";
1395 case S_LABEL
: return "label";
1396 case S_GOTO
: return "goto";
1397 case S_IF
: return "if";
1398 case S_SELECT
: return "select-case";
1399 case S_FOR
: return "for";
1400 case S_WHILE
: return "while";
1401 case S_DOWHILE
: return "do-while";
1402 case S_BREAK
: return "break";
1403 case S_CONTINUE
: return "continue";
1404 case S_STOP_EXEC
: return "stop";
1405 case S_STOP_TESTCASE
: return "testcase.stop";
1406 case S_ALT
: return "alt";
1407 case S_REPEAT
: return "repeat";
1408 case S_INTERLEAVE
: return "interleave";
1409 case S_ALTSTEP_INSTANCE
: return "altstep instance";
1410 case S_ALTSTEP_INVOKED
: return "altstep type invocation";
1411 case S_RETURN
: return "return";
1413 case S_ACTIVATE_REFD
:
1415 case S_DEACTIVATE
: return "deactivate";
1416 case S_SEND
: return "send";
1417 case S_CALL
: return "call";
1418 case S_REPLY
: return "reply";
1419 case S_RAISE
: return "raise";
1420 case S_RECEIVE
: return "receive";
1421 case S_TRIGGER
: return "trigger";
1422 case S_GETCALL
: return "getcall";
1423 case S_GETREPLY
: return "getreply";
1424 case S_CATCH
: return "catch";
1425 case S_CHECK
: return "check";
1426 case S_CHECK_RECEIVE
: return "check-receive";
1427 case S_CHECK_GETCALL
: return "check-getcall";
1428 case S_CHECK_GETREPLY
: return "check-getreply";
1429 case S_CHECK_CATCH
: return "check-catch";
1430 case S_CLEAR
: return "clear";
1431 case S_START_PORT
: return "start port";
1432 case S_STOP_PORT
: return "stop port";
1433 case S_HALT
: return "halt";
1435 case S_START_COMP_REFD
:
1436 return "start test component";
1437 case S_STOP_COMP
: return "stop test component";
1438 case S_DONE
: return "done";
1439 case S_KILL
: return "kill";
1440 case S_KILLED
: return "killed";
1441 case S_CONNECT
: return "connect";
1442 case S_MAP
: return "map";
1443 case S_DISCONNECT
: return "disconnect";
1444 case S_UNMAP
: return "unmap";
1445 case S_START_TIMER
: return "start timer";
1446 case S_STOP_TIMER
: return "stop timer";
1447 case S_TIMEOUT
: return "timeout";
1448 case S_SETVERDICT
: return "setverdict";
1449 case S_ACTION
: return "action";
1450 case S_TESTCASE_INSTANCE
:
1451 case S_TESTCASE_INSTANCE_REFD
:
1453 case S_STRING2TTCN
: return "string2ttcn";
1455 FATAL_ERROR("Statement::get_stmt_name()");
1457 } // switch statementtype
1460 const Identifier
& Statement::get_labelid() const
1462 switch (statementtype
) {
1468 FATAL_ERROR("Statement::get_labelid()");
1473 bool Statement::label_is_used() const
1475 if (statementtype
!= S_LABEL
) FATAL_ERROR("Statement::label_is_used()");
1479 bool Statement::goto_jumps_forward() const
1481 if (statementtype
!= S_GOTO
) FATAL_ERROR("Statement::goto_jumps_forward()");
1482 return go_to
.jumps_forward
;
1485 const string
& Statement::get_clabel()
1487 if (statementtype
!= S_LABEL
|| !my_sb
)
1488 FATAL_ERROR("Statement::get_clabel()");
1489 if (!label
.clabel
) label
.clabel
=
1490 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
1491 return *label
.clabel
;
1494 Definition
*Statement::get_def() const
1496 if (statementtype
!= S_DEF
) FATAL_ERROR("Statement::get_def()");
1500 AltGuards
*Statement::get_ags() const
1502 if (statementtype
!= S_ALT
&& statementtype
!= S_INTERLEAVE
)
1503 FATAL_ERROR("Statement::get_ags()");
1507 StatementBlock
*Statement::get_block() const
1509 switch (statementtype
) {
1517 FATAL_ERROR("Statement::get_block()");
1522 void Statement::set_my_scope(Scope
*p_scope
)
1524 switch(statementtype
) {
1535 undefstartstop
.ref
->set_my_scope(p_scope
);
1536 if (undefstartstop
.val
) undefstartstop
.val
->set_my_scope(p_scope
);
1538 case S_UNKNOWN_INSTANCE
:
1539 case S_FUNCTION_INSTANCE
:
1540 case S_ALTSTEP_INSTANCE
:
1542 ref_pard
->set_my_scope(p_scope
);
1545 def
->set_my_scope(p_scope
);
1548 ass
->set_my_scope(p_scope
);
1551 block
->set_my_scope(p_scope
);
1555 case S_STOP_TESTCASE
:
1556 if (logargs
) logargs
->set_my_scope(p_scope
);
1559 if_stmt
.ics
->set_my_scope(p_scope
);
1560 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_scope(p_scope
);
1563 select
.expr
->set_my_scope(p_scope
);
1564 select
.scs
->set_my_scope(p_scope
);
1567 if (loop
.for_stmt
.varinst
) {
1568 loop
.for_stmt
.init_varinst
->set_parent_scope(p_scope
);
1569 loop
.for_stmt
.finalexpr
->set_my_scope(loop
.for_stmt
.init_varinst
);
1570 loop
.for_stmt
.step
->set_my_scope(loop
.for_stmt
.init_varinst
);
1571 loop
.block
->set_my_scope(loop
.for_stmt
.init_varinst
);
1573 loop
.for_stmt
.init_ass
->set_my_scope(p_scope
);
1574 loop
.for_stmt
.finalexpr
->set_my_scope(p_scope
);
1575 loop
.for_stmt
.step
->set_my_scope(p_scope
);
1576 loop
.block
->set_my_scope(p_scope
);
1581 loop
.expr
->set_my_scope(p_scope
);
1582 loop
.block
->set_my_scope(p_scope
);
1586 ags
->set_my_scope(p_scope
);
1589 if (returnexpr
.v
) returnexpr
.v
->set_my_scope(p_scope
);
1590 if (returnexpr
.t
) returnexpr
.t
->set_my_scope(p_scope
);
1593 if (deactivate
) deactivate
->set_my_scope(p_scope
);
1596 port_op
.portref
->set_my_scope(p_scope
);
1597 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1598 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1601 port_op
.portref
->set_my_scope(p_scope
);
1602 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1603 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1604 if(port_op
.s
.call
.timer
) port_op
.s
.call
.timer
->set_my_scope(p_scope
);
1605 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_scope(p_scope
);
1608 port_op
.portref
->set_my_scope(p_scope
);
1609 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1610 if(port_op
.s
.replyval
) port_op
.s
.replyval
->set_my_scope(p_scope
);
1611 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1614 port_op
.portref
->set_my_scope(p_scope
);
1615 port_op
.s
.raise
.signature_ref
->set_my_scope(p_scope
);
1616 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1617 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1620 case S_CHECK_RECEIVE
:
1622 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1623 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1624 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1625 if(port_op
.r
.redirect
.value
)
1626 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1627 if(port_op
.r
.redirect
.sender
)
1628 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1631 case S_CHECK_GETCALL
:
1632 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1633 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1634 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1635 if(port_op
.r
.redirect
.param
)
1636 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1637 if(port_op
.r
.redirect
.sender
)
1638 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1641 case S_CHECK_GETREPLY
:
1642 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1643 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1644 if(port_op
.r
.getreply_valuematch
)
1645 port_op
.r
.getreply_valuematch
->set_my_scope(p_scope
);
1646 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1647 if(port_op
.r
.redirect
.value
)
1648 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1649 if(port_op
.r
.redirect
.param
)
1650 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1651 if(port_op
.r
.redirect
.sender
)
1652 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1656 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1657 if(port_op
.r
.ctch
.signature_ref
)
1658 port_op
.r
.ctch
.signature_ref
->set_my_scope(p_scope
);
1659 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1660 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1661 if(port_op
.r
.redirect
.value
)
1662 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1663 if(port_op
.r
.redirect
.sender
)
1664 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1667 if(port_op
.portref
) port_op
.portref
->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
.sender
)
1670 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1676 if (port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1679 comp_op
.compref
->set_my_scope(p_scope
);
1680 comp_op
.funcinstref
->set_my_scope(p_scope
);
1682 case S_START_COMP_REFD
:
1683 comp_op
.compref
->set_my_scope(p_scope
);
1684 comp_op
.derefered
.value
->set_my_scope(p_scope
);
1685 comp_op
.derefered
.t_list1
->set_my_scope(p_scope
);
1690 if (comp_op
.compref
) comp_op
.compref
->set_my_scope(p_scope
);
1693 if (comp_op
.compref
) {
1694 comp_op
.compref
->set_my_scope(p_scope
);
1695 if (comp_op
.donereturn
.donematch
)
1696 comp_op
.donereturn
.donematch
->set_my_scope(p_scope
);
1697 if (comp_op
.donereturn
.redirect
)
1698 comp_op
.donereturn
.redirect
->set_my_scope(p_scope
);
1705 config_op
.compref1
->set_my_scope(p_scope
);
1706 config_op
.portref1
->set_my_scope(p_scope
);
1707 config_op
.compref2
->set_my_scope(p_scope
);
1708 config_op
.portref2
->set_my_scope(p_scope
);
1711 timer_op
.timerref
->set_my_scope(p_scope
);
1712 if (timer_op
.value
) timer_op
.value
->set_my_scope(p_scope
);
1716 if (timer_op
.timerref
) timer_op
.timerref
->set_my_scope(p_scope
);
1719 setverdict
.verdictval
->set_my_scope(p_scope
);
1720 if (setverdict
.logargs
)
1721 setverdict
.logargs
->set_my_scope(p_scope
);
1723 case S_TESTCASE_INSTANCE
:
1724 testcase_inst
.tcref
->set_my_scope(p_scope
);
1725 if (testcase_inst
.timerval
) testcase_inst
.timerval
->set_my_scope(p_scope
);
1727 case S_TESTCASE_INSTANCE_REFD
:
1728 execute_refd
.value
->set_my_scope(p_scope
);
1729 execute_refd
.t_list1
->set_my_scope(p_scope
);
1730 if(execute_refd
.timerval
) execute_refd
.timerval
->set_my_scope(p_scope
);
1732 case S_ACTIVATE_REFD
:
1733 case S_UNKNOWN_INVOKED
:
1734 case S_FUNCTION_INVOKED
:
1735 case S_ALTSTEP_INVOKED
:
1736 fau_refd
.value
->set_my_scope(p_scope
);
1737 fau_refd
.t_list1
->set_my_scope(p_scope
);
1740 str2ttcn
.val
->set_my_scope(p_scope
);
1741 str2ttcn
.ref
->set_my_scope(p_scope
);
1744 FATAL_ERROR("Statement::set_my_scope()");
1745 } // switch statementtype
1748 void Statement::set_fullname(const string
& p_fullname
)
1750 Node::set_fullname(p_fullname
);
1751 switch (statementtype
) {
1762 undefstartstop
.ref
->set_fullname(p_fullname
+".ref");
1763 if (undefstartstop
.val
)
1764 undefstartstop
.val
->set_fullname(p_fullname
+".val");
1766 case S_UNKNOWN_INSTANCE
:
1767 case S_FUNCTION_INSTANCE
:
1768 case S_ALTSTEP_INSTANCE
:
1770 ref_pard
->set_fullname(p_fullname
+".ref");
1773 def
->set_fullname(p_fullname
+".def");
1776 ass
->set_fullname(p_fullname
+".ass");
1779 block
->set_fullname(p_fullname
+".block");
1783 case S_STOP_TESTCASE
:
1784 if (logargs
) logargs
->set_fullname(p_fullname
+".logargs");
1787 if_stmt
.ics
->set_fullname(p_fullname
+".ifclauses");
1788 if (if_stmt
.elseblock
)
1789 if_stmt
.elseblock
->set_fullname(p_fullname
+".elseblock");
1792 select
.expr
->set_fullname(p_fullname
+".expr");
1793 select
.scs
->set_fullname(p_fullname
+".scs");
1796 if(loop
.for_stmt
.varinst
)
1797 loop
.for_stmt
.init_varinst
->set_fullname(p_fullname
+".init");
1799 loop
.for_stmt
.init_ass
->set_fullname(p_fullname
+".init");
1800 loop
.for_stmt
.finalexpr
->set_fullname(p_fullname
+".final");
1801 loop
.for_stmt
.step
->set_fullname(p_fullname
+".step");
1802 loop
.block
->set_fullname(p_fullname
+".block");
1806 loop
.expr
->set_fullname(p_fullname
+".expr");
1807 loop
.block
->set_fullname(p_fullname
+".block");
1811 ags
->set_fullname(p_fullname
+".ags");
1814 if (returnexpr
.v
) returnexpr
.v
->set_fullname(p_fullname
+".returnexpr");
1815 if (returnexpr
.t
) returnexpr
.t
->set_fullname(p_fullname
+".returnexpr");
1818 if (deactivate
) deactivate
->set_fullname(p_fullname
+".deact");
1821 port_op
.portref
->set_fullname(p_fullname
+".portref");
1822 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1823 if(port_op
.s
.toclause
)
1824 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1827 port_op
.portref
->set_fullname(p_fullname
+".portref");
1828 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1829 if(port_op
.s
.toclause
)
1830 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1831 if(port_op
.s
.call
.timer
)
1832 port_op
.s
.call
.timer
->set_fullname(p_fullname
+".timer");
1833 if(port_op
.s
.call
.body
)
1834 port_op
.s
.call
.body
->set_fullname(p_fullname
+".body");
1837 port_op
.portref
->set_fullname(p_fullname
+".portref");
1838 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1839 if(port_op
.s
.replyval
)
1840 port_op
.s
.replyval
->set_fullname(p_fullname
+".replyval");
1841 if(port_op
.s
.toclause
)
1842 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1845 port_op
.portref
->set_fullname(p_fullname
+".portref");
1846 port_op
.s
.raise
.signature_ref
->set_fullname(p_fullname
+".sign");
1847 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1848 if(port_op
.s
.toclause
)
1849 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1852 case S_CHECK_RECEIVE
:
1854 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1855 if(port_op
.r
.rcvpar
)
1856 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1857 if(port_op
.r
.fromclause
)
1858 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1859 if(port_op
.r
.redirect
.value
)
1860 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1861 if(port_op
.r
.redirect
.sender
)
1862 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1865 case S_CHECK_GETCALL
:
1866 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1867 if(port_op
.r
.rcvpar
)
1868 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1869 if(port_op
.r
.fromclause
)
1870 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1871 if(port_op
.r
.redirect
.param
)
1872 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1873 if(port_op
.r
.redirect
.sender
)
1874 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1877 case S_CHECK_GETREPLY
:
1878 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1879 if(port_op
.r
.rcvpar
)
1880 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1881 if(port_op
.r
.getreply_valuematch
)
1882 port_op
.r
.getreply_valuematch
->set_fullname(p_fullname
+".valmatch");
1883 if(port_op
.r
.fromclause
)
1884 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1885 if(port_op
.r
.redirect
.value
)
1886 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1887 if(port_op
.r
.redirect
.param
)
1888 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1889 if(port_op
.r
.redirect
.sender
)
1890 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1894 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1895 if(port_op
.r
.ctch
.signature_ref
)
1896 port_op
.r
.ctch
.signature_ref
->set_fullname(p_fullname
+".sign");
1897 if(port_op
.r
.rcvpar
)
1898 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1899 if(port_op
.r
.fromclause
)
1900 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1901 if(port_op
.r
.redirect
.value
)
1902 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1903 if(port_op
.r
.redirect
.sender
)
1904 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1907 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1908 if(port_op
.r
.fromclause
)
1909 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1910 if(port_op
.r
.redirect
.sender
)
1911 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1917 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1920 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1921 comp_op
.funcinstref
->set_fullname(p_fullname
+".funcref");
1923 case S_START_COMP_REFD
:
1924 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1925 comp_op
.derefered
.value
->set_fullname(p_fullname
+".funcref");
1926 comp_op
.derefered
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1931 if (comp_op
.compref
) comp_op
.compref
->set_fullname(p_fullname
+".compref");
1934 if(comp_op
.compref
) {
1935 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1936 if(comp_op
.donereturn
.donematch
)
1937 comp_op
.donereturn
.donematch
->set_fullname(p_fullname
+".donematch");
1938 if(comp_op
.donereturn
.redirect
)
1939 comp_op
.donereturn
.redirect
->set_fullname(p_fullname
+".redir");
1946 config_op
.compref1
->set_fullname(p_fullname
+".compref1");
1947 config_op
.portref1
->set_fullname(p_fullname
+".portref1");
1948 config_op
.compref2
->set_fullname(p_fullname
+".compref2");
1949 config_op
.portref2
->set_fullname(p_fullname
+".portref2");
1952 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1953 if(timer_op
.value
) timer_op
.value
->set_fullname(p_fullname
+".timerval");
1957 if (timer_op
.timerref
)
1958 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1961 setverdict
.verdictval
->set_fullname(p_fullname
+".verdictval");
1962 if (setverdict
.logargs
)
1963 setverdict
.logargs
->set_fullname(p_fullname
+".verdictreason");
1965 case S_TESTCASE_INSTANCE
:
1966 testcase_inst
.tcref
->set_fullname(p_fullname
+".tcref");
1967 if (testcase_inst
.timerval
)
1968 testcase_inst
.timerval
->set_fullname(p_fullname
+".timerval");
1970 case S_TESTCASE_INSTANCE_REFD
:
1971 execute_refd
.value
->set_fullname(p_fullname
+".tcref");
1972 execute_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1973 if(execute_refd
.timerval
)
1974 execute_refd
.timerval
->set_fullname(p_fullname
+".timerval");
1976 case S_ACTIVATE_REFD
:
1977 case S_UNKNOWN_INVOKED
:
1978 case S_FUNCTION_INVOKED
:
1979 case S_ALTSTEP_INVOKED
:
1980 fau_refd
.value
->set_fullname(p_fullname
+".ref");
1981 fau_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1984 str2ttcn
.val
->set_fullname(p_fullname
+".ti");
1985 str2ttcn
.ref
->set_fullname(p_fullname
+".ref");
1988 FATAL_ERROR("Statement::set_fullname()");
1989 } // switch statementtype
1992 void Statement::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
1995 switch(statementtype
) {
1997 block
->set_my_sb(p_sb
, p_index
);
2000 label
.stmt_idx
= p_index
;
2003 go_to
.stmt_idx
= p_index
;
2006 if_stmt
.ics
->set_my_sb(p_sb
, p_index
);
2007 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_sb(p_sb
, p_index
);
2010 select
.scs
->set_my_sb(p_sb
, p_index
);
2015 loop
.block
->set_my_sb(p_sb
, p_index
);
2019 ags
->set_my_sb(p_sb
, p_index
);
2022 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_sb(p_sb
, p_index
);
2026 } // switch statementtype
2029 void Statement::set_my_def(Definition
*p_def
)
2031 switch (statementtype
) {
2033 block
->set_my_def(p_def
);
2036 if_stmt
.ics
->set_my_def(p_def
);
2037 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_def(p_def
);
2040 select
.scs
->set_my_def(p_def
);
2045 loop
.block
->set_my_def(p_def
);
2049 ags
->set_my_def(p_def
);
2052 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_def(p_def
);
2056 } // switch statementtype
2059 void Statement::set_my_ags(AltGuards
*p_ags
)
2061 switch (statementtype
) {
2063 block
->set_my_ags(p_ags
);
2066 if_stmt
.ics
->set_my_ags(p_ags
);
2067 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_ags(p_ags
);
2070 select
.scs
->set_my_ags(p_ags
);
2075 loop
.block
->set_my_ags(p_ags
);
2082 } // switch statementtype
2085 void Statement::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
2087 switch (statementtype
) {
2089 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2092 if_stmt
.ics
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2093 if (if_stmt
.elseblock
)
2094 if_stmt
.elseblock
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2097 select
.scs
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2102 ags
->set_my_laic_stmt(0, p_loop_stmt
); // ags is set later
2105 if (p_loop_stmt
&& port_op
.s
.call
.body
)
2106 port_op
.s
.call
.body
->set_my_laic_stmt(0, p_loop_stmt
);
2112 brk_cnt
.loop_stmt
=p_loop_stmt
;
2117 } // switch statementtype
2120 /** \todo handle blocks, loops and conditional statements
2121 * (i.e. investigate their last statements within the block) */
2122 bool Statement::is_terminating() const
2124 switch (statementtype
) {
2129 case S_STOP_TESTCASE
:
2135 // checking for self.stop, self.kill, mtc.stop and mtc.kill
2136 if (comp_op
.compref
) {
2137 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
2138 if (v_last
->get_valuetype() == Value::V_EXPR
) {
2139 switch (v_last
->get_optype()) {
2140 case Value::OPTYPE_COMP_SELF
:
2141 case Value::OPTYPE_COMP_MTC
:
2151 if(!loop
.expr
->is_unfoldable() && loop
.expr
->get_val_bool()) {
2152 return !loop
.has_brk
; // not endless loop if it has a break
2160 StatementBlock::returnstatus_t
Statement::has_return() const
2162 switch (statementtype
) {
2164 return block
->has_return();
2166 return if_stmt
.ics
->has_return(if_stmt
.elseblock
);
2168 return select
.scs
->has_return();
2171 if (loop
.block
->has_return() == StatementBlock::RS_NO
)
2172 return StatementBlock::RS_NO
;
2173 else return StatementBlock::RS_MAYBE
;
2175 return loop
.block
->has_return();
2177 StatementBlock::returnstatus_t ret_val
= ags
->has_return();
2178 if (ret_val
== StatementBlock::RS_YES
&& !ags
->has_else()) {
2179 // the invoked defaults may skip the entire statement
2180 ret_val
= StatementBlock::RS_MAYBE
;
2184 if (port_op
.s
.call
.body
) return port_op
.s
.call
.body
->has_return();
2185 else return StatementBlock::RS_NO
;
2187 if (is_terminating()) return StatementBlock::RS_YES
;
2188 else return StatementBlock::RS_NO
;
2192 bool Statement::is_receiving_stmt() const
2194 switch (statementtype
) {
2197 case S_ALTSTEP_INSTANCE
:
2198 case S_ALTSTEP_INVOKED
:
2200 case S_CHECK_RECEIVE
:
2203 case S_CHECK_GETCALL
:
2205 case S_CHECK_GETREPLY
:
2215 } // switch statementtype
2218 bool Statement::has_receiving_stmt() const
2220 switch (statementtype
) {
2223 case S_FUNCTION_INSTANCE
:
2224 case S_FUNCTION_INVOKED
:
2233 case S_STOP_TESTCASE
:
2237 case S_ACTIVATE_REFD
:
2247 case S_START_COMP_REFD
:
2257 case S_TESTCASE_INSTANCE
:
2258 case S_TESTCASE_INSTANCE_REFD
:
2262 case S_ALTSTEP_INSTANCE
:
2263 case S_ALTSTEP_INVOKED
:
2265 case S_CHECK_RECEIVE
:
2268 case S_CHECK_GETCALL
:
2270 case S_CHECK_GETREPLY
:
2279 return block
->has_receiving_stmt();
2281 return if_stmt
.ics
->has_receiving_stmt()
2282 || (if_stmt
.elseblock
&& if_stmt
.elseblock
->has_receiving_stmt());
2284 return select
.scs
->has_receiving_stmt();
2288 return loop
.block
->has_receiving_stmt();
2290 return port_op
.s
.call
.body
&& port_op
.s
.call
.body
->has_receiving_stmt();
2294 case S_UNKNOWN_INSTANCE
:
2295 case S_UNKNOWN_INVOKED
:
2297 FATAL_ERROR("Statement::has_receiving_stmt()");
2298 } // switch statementtype
2301 bool Statement::can_repeat() const
2303 switch (statementtype
) {
2309 case S_CHECK_RECEIVE
:
2311 case S_CHECK_GETCALL
:
2313 case S_CHECK_GETREPLY
:
2320 FATAL_ERROR("Statement::can_repeat()");
2321 } // switch statementtype
2324 void Statement::chk()
2326 switch (statementtype
) {
2335 case S_UNKNOWN_INSTANCE
:
2336 chk_unknown_instance();
2338 case S_UNKNOWN_INVOKED
:
2339 case S_FUNCTION_INVOKED
:
2340 case S_ALTSTEP_INVOKED
:
2341 chk_unknown_invoke();
2345 my_sb
->register_def(def
);
2350 case S_FUNCTION_INSTANCE
:
2358 case S_STOP_TESTCASE
:
2359 chk_log_action(logargs
);
2400 case S_ALTSTEP_INSTANCE
:
2409 case S_ACTIVATE_REFD
:
2410 chk_activate_refd();
2428 case S_CHECK_RECEIVE
:
2433 case S_CHECK_GETCALL
:
2437 case S_CHECK_GETREPLY
:
2453 chk_start_stop_port();
2458 case S_START_COMP_REFD
:
2459 chk_start_comp_refd();
2463 chk_stop_kill_comp();
2484 chk_stop_timer_timeout();
2488 chk_log_action(setverdict
.logargs
); // for checking verdictreason
2490 case S_TESTCASE_INSTANCE
:
2493 case S_TESTCASE_INSTANCE_REFD
:
2500 FATAL_ERROR("Statement::chk()");
2501 } // switch statementtype
2504 void Statement::chk_string2ttcn()
2506 Error_Context
cntxt(this, "In string2ttcn() statement");
2507 str2ttcn
.val
->chk_expr_type(Type::T_CSTR
, "charstring", Type::EXPECTED_DYNAMIC_VALUE
);
2509 Common::Assignment
* refd_ass
= str2ttcn
.ref
->get_refd_assignment();
2510 if (refd_ass
==NULL
) {
2511 error("Could not determine the assignment for second parameter");
2514 switch (refd_ass
->get_asstype()) {
2515 case Definition::A_PAR_VAL_IN
:
2516 case Definition::A_PAR_TEMPL_IN
:
2517 refd_ass
->use_as_lvalue(*str2ttcn
.ref
);
2518 case Definition::A_VAR
:
2519 case Definition::A_VAR_TEMPLATE
:
2520 case Definition::A_PAR_VAL_OUT
:
2521 case Definition::A_PAR_VAL_INOUT
:
2522 case Definition::A_PAR_TEMPL_OUT
:
2523 case Definition::A_PAR_TEMPL_INOUT
:
2524 // valid assignment types
2527 str2ttcn
.ref
->error("Reference to '%s' cannot be used as the second parameter", refd_ass
->get_assname());
2532 delete str2ttcn
.val
;
2533 delete str2ttcn
.ref
;
2534 statementtype
= S_ERROR
;
2537 void Statement::chk_allowed_interleave()
2539 switch (statementtype
) {
2541 block
->chk_allowed_interleave();
2544 error("Label statement is not allowed within an interleave statement");
2547 error("Goto statement is not allowed within an interleave statement");
2550 if_stmt
.ics
->chk_allowed_interleave();
2551 if (if_stmt
.elseblock
) if_stmt
.elseblock
->chk_allowed_interleave();
2554 select
.scs
->chk_allowed_interleave();
2559 loop
.block
->chk_allowed_interleave();
2562 ags
->chk_allowed_interleave();
2565 error("Repeat statement is not allowed within an interleave statement");
2567 case S_ALTSTEP_INSTANCE
:
2568 error("Invocation of an altstep is not allowed within an interleave "
2571 case S_ALTSTEP_INVOKED
:
2572 error("Invocation of an altstep type is not allowed within an interleave"
2576 error("Return statement is not allowed within an interleave statement");
2579 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->chk_allowed_interleave();
2582 // the other statements are allowed
2587 void Statement::chk_start_undef()
2589 Ref_base
*t_ref
= undefstartstop
.ref
;
2590 Value
*t_val
= undefstartstop
.val
;
2591 Common::Assignment
*t_ass
;
2593 Error_Context
cntxt(this, "In start statement");
2594 t_ass
= t_ref
->get_refd_assignment();
2596 if (!t_ass
) goto error
;
2597 switch (t_ass
->get_asstype()) {
2598 case Definition::A_PORT
:
2599 case Definition::A_PAR_PORT
:
2600 statementtype
= S_START_PORT
;
2601 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2602 if (!port_op
.portref
) goto error
;
2604 t_val
->error("Start port operation cannot have argument");
2607 chk_start_stop_port();
2609 case Definition::A_TIMER
:
2610 case Definition::A_PAR_TIMER
:
2611 statementtype
= S_START_TIMER
;
2612 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2613 if (!timer_op
.timerref
) goto error
;
2614 timer_op
.value
= t_val
;
2617 case Definition::A_CONST
:
2618 case Definition::A_EXT_CONST
:
2619 case Definition::A_MODULEPAR
:
2620 case Definition::A_VAR
:
2621 case Definition::A_FUNCTION_RVAL
:
2622 case Definition::A_EXT_FUNCTION_RVAL
:
2623 case Definition::A_PAR_VAL_IN
:
2624 case Definition::A_PAR_VAL_OUT
:
2625 case Definition::A_PAR_VAL_INOUT
:
2626 statementtype
= S_START_COMP
;
2628 error("The argument of start operation is missing, although it cannot "
2629 "be a start timer or start port operation");
2631 } else if (t_val
->get_valuetype() != Value::V_REFD
) {
2632 t_val
->error("The argument of start operation is not a function, "
2633 "although it cannot be a start timer or start port operation");
2636 comp_op
.funcinstref
= t_val
->steal_ttcn_ref_base();
2639 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2640 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2641 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2642 comp_op
.compref
->set_location(*t_ref
);
2646 t_ref
->error("Port, timer or component reference was expected as the "
2647 "operand of start operation instead of %s",
2648 t_ass
->get_description().c_str());
2655 statementtype
= S_ERROR
;
2658 void Statement::chk_stop_undef()
2660 Ref_base
*t_ref
= undefstartstop
.ref
;
2661 Common::Assignment
*t_ass
;
2663 Error_Context
cntxt(this, "In stop statement");
2664 t_ass
= t_ref
->get_refd_assignment();
2666 if (!t_ass
) goto error
;
2667 // Determine what it is that we are trying to stop; change statementtype
2668 switch (t_ass
->get_asstype()) {
2669 case Definition::A_PORT
:
2670 case Definition::A_PAR_PORT
:
2671 statementtype
= S_STOP_PORT
;
2672 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2673 if (!port_op
.portref
) goto error
;
2674 chk_start_stop_port();
2676 case Definition::A_TIMER
:
2677 case Definition::A_PAR_TIMER
:
2678 statementtype
= S_STOP_TIMER
;
2679 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2680 if (!timer_op
.timerref
) goto error
;
2682 chk_stop_timer_timeout();
2684 case Definition::A_CONST
:
2685 case Definition::A_EXT_CONST
:
2686 case Definition::A_MODULEPAR
:
2687 case Definition::A_VAR
:
2688 case Definition::A_FUNCTION_RVAL
:
2689 case Definition::A_EXT_FUNCTION_RVAL
:
2690 case Definition::A_PAR_VAL_IN
:
2691 case Definition::A_PAR_VAL_OUT
:
2692 case Definition::A_PAR_VAL_INOUT
:
2693 statementtype
= S_STOP_COMP
;
2694 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2695 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2696 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2697 comp_op
.compref
->set_location(*t_ref
);
2698 chk_stop_kill_comp();
2701 t_ref
->error("Port, timer or component reference was expected as the "
2702 "operand of stop operation instead of %s",
2703 t_ass
->get_description().c_str());
2709 statementtype
= S_ERROR
;
2712 void Statement::chk_unknown_instance()
2714 Common::Assignment
*t_ass
;
2716 Error_Context
cntxt(this, "In function or altstep instance");
2717 t_ass
= ref_pard
->get_refd_assignment(false);
2719 if (!t_ass
) goto error
;
2720 switch (t_ass
->get_asstype()) {
2721 case Common::Assignment::A_FUNCTION
:
2722 case Common::Assignment::A_FUNCTION_RVAL
:
2723 case Common::Assignment::A_FUNCTION_RTEMP
:
2724 case Common::Assignment::A_EXT_FUNCTION
:
2725 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2726 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2727 statementtype
= S_FUNCTION_INSTANCE
;
2730 case Common::Assignment::A_ALTSTEP
:
2731 statementtype
= S_ALTSTEP_INSTANCE
;
2735 ref_pard
->error("Reference to a function or altstep was expected "
2736 "instead of %s, which cannot be invoked",
2737 t_ass
->get_description().c_str());
2743 statementtype
= S_ERROR
;
2746 void Statement::chk_unknown_invoke()
2748 Error_Context
cntxt(this, "In apply operation");
2749 Type
*t
= fau_refd
.value
->get_expr_governor_last();
2751 switch (t
->get_typetype()) {
2754 case Type::T_FUNCTION
:
2755 statementtype
= S_FUNCTION_INVOKED
;
2756 if (t
->get_function_return_type()) warning("The value returned by "
2757 "function type `%s' is not used", t
->get_typename().c_str());
2759 case Type::T_ALTSTEP
:
2760 statementtype
= S_ALTSTEP_INVOKED
;
2763 fau_refd
.value
->error("A value of type function or altstep was "
2764 "expected instead of `%s'", t
->get_typename().c_str());
2767 my_sb
->chk_runs_on_clause(t
, *this, "call");
2769 ActualParList
*parlist
= new Ttcn::ActualParList
;
2770 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
2771 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
2773 delete fau_refd
.t_list1
;
2776 fau_refd
.ap_list2
= 0;
2778 parlist
->set_fullname(get_fullname());
2779 parlist
->set_my_scope(my_sb
);
2780 fau_refd
.ap_list2
= parlist
;
2786 statementtype
= S_ERROR
;
2789 void Statement::chk_assignment()
2791 Error_Context
cntxt(this, "In variable assignment");
2795 void Statement::chk_function()
2797 Error_Context
cntxt(this, "In function instance");
2798 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
2799 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
2800 if (t_ass
->get_Type())
2801 ref_pard
->warning("The value returned by %s is not used",
2802 t_ass
->get_description().c_str());
2805 void Statement::chk_block()
2807 Error_Context
cntxt(this, "In statement block");
2811 void Statement::chk_log_action(LogArguments
*lga
)
2813 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
2816 if (!semantic_check_only
) lga
->join_strings();
2820 void Statement::chk_goto()
2822 Error_Context
cntxt(this, "In goto statement");
2823 if (!my_sb
->has_label(*go_to
.id
)) {
2824 error("Label `%s' is used, but not defined",
2825 go_to
.id
->get_dispname().c_str());
2827 go_to
.jumps_forward
= false;
2830 Statement
*label_stmt
= my_sb
->get_label(*go_to
.id
);
2831 label_stmt
->label
.used
= true;
2832 StatementBlock
*label_sb
= label_stmt
->get_my_sb();
2833 // the index of the label in its own statement block
2834 size_t label_idx
= label_stmt
->get_my_sb_index();
2835 // the index of the goto statement (or its parent statement) in the
2836 // statement block of the label
2838 if (my_sb
== label_sb
) goto_idx
= go_to
.stmt_idx
;
2840 // the goto statement is within a nested statement block
2841 StatementBlock
*goto_sb
= my_sb
, *parent_sb
= my_sb
->get_my_sb();
2842 while (parent_sb
!= label_sb
) {
2843 // go up until the block of the label is found
2844 if (!parent_sb
) FATAL_ERROR("Statement::chk_goto()");
2845 goto_sb
= parent_sb
;
2846 parent_sb
= parent_sb
->get_my_sb();
2848 goto_idx
= goto_sb
->get_my_sb_index();
2850 if (label_idx
> goto_idx
) {
2851 bool error_flag
= false;
2852 for (size_t i
= goto_idx
+ 1; i
< label_idx
; i
++) {
2853 Statement
*stmt
= label_sb
->get_stmt_byIndex(i
);
2854 if (stmt
->get_statementtype() != S_DEF
) continue;
2856 error("Jump to label `%s' crosses local definition",
2857 go_to
.id
->get_dispname().c_str());
2860 stmt
->note("Definition of %s is here",
2861 stmt
->get_def()->get_description().c_str());
2864 label_stmt
->note("Label `%s' is here",
2865 go_to
.id
->get_dispname().c_str());
2866 go_to
.jumps_forward
= true;
2867 } else go_to
.jumps_forward
= false;
2868 go_to
.label
= label_stmt
;
2871 void Statement::chk_if()
2874 if_stmt
.ics
->chk(unreach
);
2875 if(if_stmt
.elseblock
) {
2876 Error_Context
cntxt(if_stmt
.elseblock_location
, "In else statement");
2877 if(unreach
) if_stmt
.elseblock_location
->warning
2878 ("Control never reaches this code because of previous effective"
2880 if_stmt
.elseblock
->chk();
2885 void Statement::chk_select()
2887 Error_Context
cntxt(this, "In select case statement");
2889 for(int turn
=0; turn
<2; turn
++) {
2890 if(turn
) select
.expr
->set_lowerid_to_ref();
2891 Type::typetype_t tt
=select
.expr
->get_expr_returntype();
2892 t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2893 if(!t_gov
|| tt
==Type::T_ERROR
) {
2894 SelectCases
*scs
=select
.scs
;
2895 for(size_t i
=0; i
<scs
->get_nof_scs(); i
++) {
2896 TemplateInstances
*tis
=scs
->get_sc_byIndex(i
)->get_tis();
2898 for(size_t j
=0; j
<tis
->get_nof_tis(); j
++) {
2899 TemplateInstance
*ti
=tis
->get_ti_byIndex(j
);
2900 if(turn
) ti
->get_Template()->set_lowerid_to_ref();
2901 t_gov
=ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
2902 tt
=ti
->get_expr_returntype(Type::EXPECTED_TEMPLATE
);
2903 if(t_gov
&& tt
!=Type::T_ERROR
) break;
2908 else t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2911 select
.expr
->error("Cannot determine the type of the expression");
2912 t_gov
=Type::get_pooltype(Type::T_ERROR
);
2914 select
.expr
->set_my_governor(t_gov
);
2915 t_gov
->chk_this_value_ref(select
.expr
);
2916 t_gov
->chk_this_value(select
.expr
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
2917 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2918 select
.scs
->chk(t_gov
);
2921 void Statement::chk_for()
2923 Error_Context
cntxt(this, "In for statement");
2924 if (loop
.for_stmt
.varinst
) loop
.for_stmt
.init_varinst
->chk_for();
2925 else loop
.for_stmt
.init_ass
->chk();
2926 loop
.for_stmt
.finalexpr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2927 if(!loop
.for_stmt
.finalexpr
->is_unfoldable()
2928 && !loop
.for_stmt
.finalexpr
->get_val_bool())
2929 loop
.for_stmt
.finalexpr
->warning
2930 ("Control never reaches this code because the"
2931 " final conditional expression evals to false");
2932 loop
.for_stmt
.step
->chk();
2933 loop
.block
->set_my_laic_stmt(0, this);
2937 void Statement::chk_while()
2939 Error_Context
cntxt(this, "In while statement");
2940 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2941 if(!loop
.expr
->is_unfoldable() && !loop
.expr
->get_val_bool())
2942 loop
.expr
->warning("Control never reaches this code because the"
2943 " conditional expression evals to false");
2944 loop
.block
->set_my_laic_stmt(0, this);
2948 void Statement::chk_do_while()
2950 Error_Context
cntxt(this, "In do-while statement");
2951 loop
.block
->set_my_laic_stmt(0, this);
2953 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2956 void Statement::chk_break()
2958 Error_Context
cntxt(this, "In break statement");
2959 if (!brk_cnt
.loop_stmt
&& !brk_cnt
.ags
)
2960 error("Break statement cannot be used outside loops, alt or interleave"
2961 " statements, altsteps or response and exception handling part of call"
2963 if (brk_cnt
.loop_stmt
)
2964 brk_cnt
.loop_stmt
->loop
.has_brk
=true;
2967 void Statement::chk_continue()
2969 Error_Context
cntxt(this, "In continue statement");
2970 if (brk_cnt
.loop_stmt
) {
2971 brk_cnt
.loop_stmt
->loop
.has_cnt
=true;
2972 if (brk_cnt
.ags
) brk_cnt
.loop_stmt
->loop
.has_cnt_in_ags
=true;
2974 error("Continue statement cannot be used outside loops");
2977 void Statement::chk_alt()
2979 Error_Context
cntxt(this, "In alt construct");
2980 ags
->set_my_ags(ags
);
2981 ags
->set_my_laic_stmt(ags
, 0);
2985 void Statement::chk_repeat()
2987 Error_Context
cntxt(this, "In repeat statement");
2988 if (ags
) ags
->repeat_found();
2989 else error("Repeat statement cannot be used outside alt statements, "
2990 "altsteps or response and exception handling part of call operations");
2993 void Statement::chk_interleave()
2995 Error_Context
cntxt(this, "In interleave statement");
2996 ags
->set_my_laic_stmt(ags
, 0);
2998 ags
->chk_allowed_interleave();
3001 void Statement::chk_altstep()
3003 Error_Context
cntxt(this, "In altstep instance");
3004 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
3005 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
3008 void Statement::chk_return()
3010 Error_Context
cntxt(this, "In return statement");
3011 Definition
*my_def
= my_sb
->get_my_def();
3013 error("Return statement cannot be used in the control part. "
3014 "It is allowed only in functions and altsteps");
3017 switch (my_def
->get_asstype()) {
3018 case Definition::A_FUNCTION
:
3020 returnexpr
.t
->error("Unexpected return value. The function does not "
3021 "have return type");
3025 case Definition::A_FUNCTION_RVAL
:
3026 if (!returnexpr
.t
) {
3027 error("Missing return value. The function should return a value of "
3028 "type `%s'", my_def
->get_Type()->get_typename().c_str());
3030 } else if (!returnexpr
.t
->is_Value()) {
3031 returnexpr
.t
->error("A specific value without matching symbols was "
3032 "expected as return value");
3035 returnexpr
.v
= returnexpr
.t
->get_Value();
3036 delete returnexpr
.t
;
3038 Type
*return_type
= my_def
->get_Type();
3039 returnexpr
.v
->set_my_governor(return_type
);
3040 return_type
->chk_this_value_ref(returnexpr
.v
);
3041 return_type
->chk_this_value(returnexpr
.v
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
3042 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
3045 case Definition::A_FUNCTION_RTEMP
:
3046 if (!returnexpr
.t
) {
3047 error("Missing return template. The function should return a template "
3048 "of type `%s'", my_def
->get_Type()->get_typename().c_str());
3051 Type
*return_type
= my_def
->get_Type();
3052 returnexpr
.t
->set_my_governor(return_type
);
3053 return_type
->chk_this_template_ref(returnexpr
.t
);
3054 return_type
->chk_this_template_generic(returnexpr
.t
, INCOMPLETE_NOT_ALLOWED
,
3055 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
3056 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
3057 if (!dfb
) FATAL_ERROR("Statement::chk_return()");
3058 returnexpr
.gen_restriction_check
=
3059 returnexpr
.t
->chk_restriction("return template",
3060 dfb
->get_template_restriction());
3063 case Definition::A_ALTSTEP
:
3065 returnexpr
.t
->error("An altstep cannot return a value");
3070 error("Return statement cannot be used in a %s. It is allowed only in "
3071 "functions and altsteps", my_def
->get_assname());
3076 delete returnexpr
.t
;
3080 void Statement::chk_activate()
3082 Error_Context
cntxt(this, "In activate statement");
3083 if (!ref_pard
->chk_activate_argument()) {
3085 statementtype
= S_ERROR
;
3089 void Statement::chk_activate_refd()
3091 Error_Context
cntxt(this, "In activate statement");
3092 Type
*t
= fau_refd
.value
->get_expr_governor_last();
3094 switch (t
->get_typetype()) {
3097 case Type::T_ALTSTEP
:
3100 fau_refd
.value
->error("A value of type altstep was expected in the "
3101 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
3104 if (t
->get_fat_runs_on_self()) {
3105 fau_refd
.value
->error("The argument of `derefers()' cannot be an altstep "
3106 "reference with 'runs on self' clause");
3109 my_sb
->chk_runs_on_clause(t
, *this, "activate");
3111 ActualParList
*parlist
= new ActualParList
;
3112 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
3113 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
3115 delete fau_refd
.t_list1
;
3118 fau_refd
.ap_list2
= 0;
3121 parlist
->set_fullname(get_fullname());
3122 parlist
->set_my_scope(my_sb
);
3123 fau_refd
.ap_list2
= parlist
;
3124 if (!fp_list
->chk_activate_argument(parlist
,get_fullname().c_str()))
3131 statementtype
= S_ERROR
;
3134 void Statement::chk_deactivate()
3137 Error_Context
cntxt(this, "In deactivate statement");
3138 deactivate
->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE
);
3142 void Statement::chk_send()
3144 Error_Context
cntxt(this, "In send statement");
3145 // checking the port reference
3146 Type
*port_type
= chk_port_ref(port_op
.portref
);
3147 // determining the message type
3149 bool msg_type_determined
= false;
3151 Ttcn::PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3152 TypeSet
*out_msgs
= port_type_body
->get_out_msgs();
3154 if (out_msgs
->get_nof_types() == 1) {
3155 // there is only one outgoing message type
3156 msg_type
= out_msgs
->get_type_byIndex(0);
3158 // there are more than one outgoing message types
3159 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3161 size_t nof_comp_types
=
3162 out_msgs
->get_nof_compatible_types(msg_type
);
3163 if (nof_comp_types
== 0) {
3164 port_op
.s
.sendpar
->error("Message type `%s' is not present on "
3165 "the outgoing list of port type `%s'",
3166 msg_type
->get_typename().c_str(),
3167 port_type
->get_typename().c_str());
3168 } else if (nof_comp_types
> 1) {
3169 port_op
.s
.sendpar
->error("Type of the message is ambiguous: "
3170 "`%s' is compatible with more than one outgoing message types "
3171 "of port type `%s'", msg_type
->get_typename().c_str(),
3172 port_type
->get_typename().c_str());
3175 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3176 "outgoing message");
3179 msg_type_determined
= true;
3180 } else if (port_type_body
->get_operation_mode() ==
3181 PortTypeBody::PO_PROCEDURE
) {
3182 port_op
.portref
->error("Message-based operation `send' is not "
3183 "applicable to a procedure-based port of type `%s'",
3184 port_type
->get_typename().c_str());
3186 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3187 "message types", port_type
->get_typename().c_str());
3190 // determining the message type if it is not done so far
3191 if (!msg_type_determined
) {
3192 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3194 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3195 // checking the parameter (template instance)
3196 port_op
.s
.sendpar
->chk(msg_type
);
3197 // checking for invalid message types
3198 msg_type
= msg_type
->get_type_refd_last();
3199 switch (msg_type
->get_typetype()) {
3200 case Type::T_SIGNATURE
:
3201 port_op
.s
.sendpar
->error("The type of send parameter is signature `%s', "
3202 "which cannot be a message type", msg_type
->get_typename().c_str());
3205 port_op
.s
.sendpar
->error("The type of send parameter is port type `%s', "
3206 "which cannot be a message type", msg_type
->get_typename().c_str());
3208 case Type::T_DEFAULT
:
3209 port_op
.s
.sendpar
->error("The type of send parameter is the `default' "
3210 "type, which cannot be a message type");
3214 // checking for presence of wildcards in the template body
3215 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3216 // checking to clause
3217 chk_to_clause(port_type
);
3220 void Statement::chk_call()
3222 Error_Context
cntxt(this, "In call statement");
3223 // checking the port reference
3224 Type
*port_type
= chk_port_ref(port_op
.portref
);
3225 // determining the signature of the argument
3226 Type
*signature
= 0;
3227 bool signature_determined
= false;
3229 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3230 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3232 if (out_sigs
->get_nof_types() == 1) {
3233 // there is only one outgoing signature
3234 signature
= out_sigs
->get_type_byIndex(0);
3236 // there are more than one outgoing signatures
3237 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3239 if (!out_sigs
->has_type(signature
)) {
3240 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3241 "outgoing list of port type `%s'",
3242 signature
->get_typename().c_str(),
3243 port_type
->get_typename().c_str());
3246 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3250 signature_determined
= true;
3251 } else if (port_type_body
->get_operation_mode() ==
3252 PortTypeBody::PO_MESSAGE
) {
3253 port_op
.portref
->error("Procedure-based operation `call' is not "
3254 "applicable to a message-based port of type `%s'",
3255 port_type
->get_typename().c_str());
3257 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3258 "signatures", port_type
->get_typename().c_str());
3261 if (!signature_determined
)
3262 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3263 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3264 // checking the parameter (template instance)
3265 port_op
.s
.sendpar
->chk(signature
);
3266 signature
= signature
->get_type_refd_last();
3267 bool is_noblock_sig
= false;
3268 Type::typetype_t tt
= signature
->get_typetype();
3270 case Type::T_SIGNATURE
:
3271 // the signature is known and correct
3272 is_noblock_sig
= signature
->is_nonblocking_signature();
3276 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not "
3277 "a signature", signature
->get_typename().c_str());
3279 // checking presence/absence of optional parts
3280 if (is_noblock_sig
) {
3281 if (port_op
.s
.call
.timer
) {
3282 port_op
.s
.call
.timer
->error("A call of non-blocking signature `%s' "
3283 "cannot have call timer", signature
->get_typename().c_str());
3284 } else if (port_op
.s
.call
.nowait
) {
3285 error("A call of non-blocking signature `%s' cannot use the "
3286 "`nowait' keyword", signature
->get_typename().c_str());
3288 if (port_op
.s
.call
.body
) {
3289 error("A call of non-blocking signature `%s' cannot have "
3290 "response and exception handling part",
3291 signature
->get_typename().c_str());
3293 } else if (port_op
.s
.call
.nowait
) {
3294 if (port_op
.s
.call
.body
) {
3295 error("A call with `nowait' keyword cannot have response and "
3296 "exception handling part");
3299 // do not issue any error if the signature is erroneous
3300 // because it could have been a non-blocking one
3301 if (tt
== Type::T_SIGNATURE
&& !port_op
.s
.call
.body
) {
3302 error("Response and exception handling part is missing from "
3303 "blocking call operation");
3306 // checking call timer
3307 if (port_op
.s
.call
.timer
) {
3308 Error_Context
cntxt2(port_op
.s
.call
.timer
, "In call timer value");
3309 port_op
.s
.call
.timer
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
3310 Value
*t_val
= port_op
.s
.call
.timer
->get_value_refd_last();
3311 if (t_val
->get_valuetype() == Value::V_REAL
) {
3312 ttcn3float v_real
= t_val
->get_val_Real();
3314 port_op
.s
.call
.timer
->error("The call timer has "
3315 "negative duration: `%s'", Real2string(v_real
).c_str());
3316 } else if (isSpecialFloatValue(v_real
)) {
3317 port_op
.s
.call
.timer
->error("The call timer duration cannot be %s",
3318 Real2string(v_real
).c_str());
3322 // checking to clause
3323 chk_to_clause(port_type
);
3324 // checking response and exception handling part
3325 if (port_op
.s
.call
.body
) chk_call_body(port_type
, signature
);
3328 void Statement::chk_reply()
3330 Error_Context
cntxt(this, "In reply statement");
3331 // checking the port reference
3332 Type
*port_type
= chk_port_ref(port_op
.portref
);
3333 // determining the signature of the argument
3334 Type
*signature
= 0;
3335 bool signature_determined
= false;
3337 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3338 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3340 if (in_sigs
->get_nof_types() == 1) {
3341 // there is only one incoming signature
3342 signature
= in_sigs
->get_type_byIndex(0);
3344 // there are more than one incoming signatures
3345 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3347 if (!in_sigs
->has_type(signature
)) {
3348 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3349 "incoming list of port type `%s'",
3350 signature
->get_typename().c_str(),
3351 port_type
->get_typename().c_str());
3354 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3358 signature_determined
= true;
3359 } else if (port_type_body
->get_operation_mode() ==
3360 PortTypeBody::PO_MESSAGE
) {
3361 port_op
.portref
->error("Procedure-based operation `reply' is not "
3362 "applicable to a message-based port of type `%s'",
3363 port_type
->get_typename().c_str());
3365 port_op
.portref
->error("Port type `%s' does not have any incoming "
3366 "signatures", port_type
->get_typename().c_str());
3369 if (!signature_determined
)
3370 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3371 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3372 // checking the parameter (template instance)
3373 port_op
.s
.sendpar
->chk(signature
);
3374 signature
= signature
->get_type_refd_last();
3375 Type
*return_type
= 0;
3376 switch (signature
->get_typetype()) {
3377 case Type::T_SIGNATURE
:
3378 // the signature is known and correct
3379 if (signature
->is_nonblocking_signature())
3380 error("Operation `reply' is not applicable to non-blocking signature "
3381 "`%s'", signature
->get_typename().c_str());
3382 else return_type
= signature
->get_signature_return_type();
3383 // checking the presence/absence of reply value
3384 if (port_op
.s
.replyval
) {
3386 port_op
.s
.replyval
->error("Unexpected return value. Signature "
3387 "`%s' does not have return type",
3388 signature
->get_typename().c_str());
3390 } else if (return_type
) {
3391 error("Missing return value. Signature `%s' returns type `%s'",
3392 signature
->get_typename().c_str(),
3393 return_type
->get_typename().c_str());
3398 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not a "
3399 "signature", signature
->get_typename().c_str());
3401 // checking the reply value if present
3402 if (port_op
.s
.replyval
) {
3403 Error_Context
cntxt2(port_op
.s
.replyval
, "In return value");
3404 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3405 port_op
.s
.replyval
->set_my_governor(return_type
);
3406 return_type
->chk_this_value_ref(port_op
.s
.replyval
);
3407 return_type
->chk_this_value(port_op
.s
.replyval
, 0,
3408 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
3411 // checking to clause
3412 chk_to_clause(port_type
);
3415 void Statement::chk_raise()
3417 Error_Context
cntxt(this, "In raise statement");
3418 // checking the port reference
3419 Type
*port_type
= chk_port_ref(port_op
.portref
);
3420 // determining the signature of the exception
3421 port_op
.s
.raise
.signature
=
3422 chk_signature_ref(port_op
.s
.raise
.signature_ref
);
3423 // checking whether the signature is present on the incoming list
3424 // of the respective port type
3426 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3427 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3428 if (port_type_body
->get_operation_mode() ==
3429 PortTypeBody::PO_MESSAGE
) {
3430 port_op
.portref
->error("Procedure-based operation `raise' is not "
3431 "applicable to a message-based port of type `%s'",
3432 port_type
->get_typename().c_str());
3433 } else if (in_sigs
) {
3434 if (port_op
.s
.raise
.signature
) {
3435 if (!in_sigs
->has_type(port_op
.s
.raise
.signature
)) {
3436 port_op
.s
.raise
.signature_ref
->error("Signature `%s' is not "
3437 "present on the incoming list of port type `%s'",
3438 port_op
.s
.raise
.signature
->get_typename().c_str(),
3439 port_type
->get_typename().c_str());
3441 } else if (in_sigs
->get_nof_types() == 1) {
3442 // if the signature is unknown and the port type has exactly one
3443 // incoming signature then use that for further checking
3444 port_op
.s
.raise
.signature
=
3445 in_sigs
->get_type_byIndex(0)->get_type_refd_last();
3448 port_op
.portref
->error("Port type `%s' does not have any incoming "
3449 "signatures", port_type
->get_typename().c_str());
3452 // determining the type of exception
3454 bool exc_type_determined
= false;
3455 if (port_op
.s
.raise
.signature
) {
3456 // the signature is known
3457 SignatureExceptions
*exceptions
=
3458 port_op
.s
.raise
.signature
->get_signature_exceptions();
3460 if (exceptions
->get_nof_types() == 1) {
3461 // the signature has exactly one exception type
3462 // use that for checking
3463 exc_type
= exceptions
->get_type_byIndex(0);
3465 // the signature has more than one exception types
3466 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3468 size_t nof_comp_types
=
3469 exceptions
->get_nof_compatible_types(exc_type
);
3470 if (nof_comp_types
== 0) {
3471 port_op
.s
.sendpar
->error("Type `%s' is not present on the "
3472 "exception list of signature `%s'",
3473 exc_type
->get_typename().c_str(),
3474 port_op
.s
.raise
.signature
->get_typename().c_str());
3475 } else if (nof_comp_types
> 1) {
3476 port_op
.s
.sendpar
->error("Type of the exception is ambiguous: "
3477 "`%s' is compatible with more than one exception types of "
3478 "signature `%s'", exc_type
->get_typename().c_str(),
3479 port_op
.s
.raise
.signature
->get_typename().c_str());
3482 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3486 exc_type_determined
= true;
3488 port_op
.s
.raise
.signature_ref
->error("Signature `%s' does not have "
3489 "exceptions", port_op
.s
.raise
.signature
->get_typename().c_str());
3492 // determining the type of exception if it is not done so far
3493 if (!exc_type_determined
) {
3494 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3496 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3497 // checking the exception template
3498 port_op
.s
.sendpar
->chk(exc_type
);
3499 // checking for invalid exception types
3500 exc_type
= exc_type
->get_type_refd_last();
3501 switch (exc_type
->get_typetype()) {
3502 case Type::T_SIGNATURE
:
3503 port_op
.s
.sendpar
->error("The type of raise parameter is signature `%s', "
3504 "which cannot be an exception type",
3505 exc_type
->get_typename().c_str());
3508 port_op
.s
.sendpar
->error("The type of raise parameter is port type `%s', "
3509 "which cannot be an exception type",
3510 exc_type
->get_typename().c_str());
3512 case Type::T_DEFAULT
:
3513 port_op
.s
.sendpar
->error("The type of raise parameter is the `default' "
3514 "type, which cannot be an exception type");
3518 // checking for presence of wildcards in the template body
3519 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3520 // checking to clause
3521 chk_to_clause(port_type
);
3524 void Statement::chk_receive()
3526 // determining statement type
3527 const char *stmt_name
= get_stmt_name();
3528 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3529 // checking the port reference
3530 Type
*port_type
= chk_port_ref(port_op
.portref
);
3531 // checking the parameter and/or value redirect
3532 if (port_op
.r
.rcvpar
) {
3533 // the receive parameter (template instance) is present
3534 // trying to determine type of the incoming message
3536 bool msg_type_determined
= false, value_redirect_checked
= false;
3538 // the port reference is correct and the port type is known
3539 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3540 TypeSet
*in_msgs
= port_type_body
->get_in_msgs();
3542 if (in_msgs
->get_nof_types() == 1) {
3543 // there is only one incoming message type
3544 // use that for checking
3545 msg_type
= in_msgs
->get_type_byIndex(0);
3547 // there are more than one incoming message types
3548 msg_type
= get_incoming_type(port_op
.r
.rcvpar
,
3549 port_op
.r
.redirect
.value
, value_redirect_checked
);
3551 size_t nof_comp_types
=
3552 in_msgs
->get_nof_compatible_types(msg_type
);
3553 if (nof_comp_types
== 0) {
3554 port_op
.r
.rcvpar
->error("Message type `%s' is not present on "
3555 "the incoming list of port of type `%s'",
3556 msg_type
->get_typename().c_str(),
3557 port_type
->get_typename().c_str());
3558 } else if (nof_comp_types
> 1) {
3559 port_op
.r
.rcvpar
->error("Type of the message is ambiguous: "
3560 "`%s' is compatible with more than one incoming message "
3561 "types of port type `%s'", msg_type
->get_typename().c_str(),
3562 port_type
->get_typename().c_str());
3565 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3566 "incoming message");
3569 msg_type_determined
= true;
3570 } else if (port_type_body
->get_operation_mode() ==
3571 PortTypeBody::PO_PROCEDURE
) {
3572 port_op
.portref
->error("Message-based operation `%s' is not "
3573 "applicable to a procedure-based port of type `%s'", stmt_name
,
3574 port_type
->get_typename().c_str());
3576 port_op
.portref
->error("Port type `%s' does not have any incoming "
3577 "message types", port_type
->get_typename().c_str());
3579 } else if (!port_op
.portref
) {
3580 // the statement refers to 'any port'
3581 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3583 if (port_op
.r
.redirect
.value
) {
3584 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3585 "value redirect", stmt_name
);
3588 if (!msg_type_determined
) {
3589 msg_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3590 value_redirect_checked
);
3592 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3593 // check the template instance using the message type
3594 port_op
.r
.rcvpar
->chk(msg_type
);
3595 // check the value redirect if it is not done so far
3596 if (!value_redirect_checked
)
3597 chk_value_redirect(port_op
.r
.redirect
.value
, msg_type
);
3599 // the statement does not have parameter
3601 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3602 if (!port_type_body
->get_in_msgs()) {
3603 // the port type is known and it does not have incoming messages
3604 if (port_type_body
->get_operation_mode() ==
3605 PortTypeBody::PO_PROCEDURE
) {
3606 port_op
.portref
->error("Message-based operation `%s' is not "
3607 "applicable to a procedure-based port of type `%s'", stmt_name
,
3608 port_type
->get_typename().c_str());
3610 port_op
.portref
->error("Port type `%s' does not have any incoming "
3611 "message types", port_type
->get_typename().c_str());
3615 if (port_op
.r
.redirect
.value
) {
3616 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
3617 "receive parameter");
3618 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3621 // checking from clause and sender redirect
3622 chk_from_clause(port_type
);
3625 void Statement::chk_getcall()
3627 // determining statement type
3628 const char *stmt_name
= get_stmt_name();
3629 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3630 // checking the port reference
3631 Type
*port_type
= chk_port_ref(port_op
.portref
);
3632 if (port_op
.r
.rcvpar
) {
3633 // the parameter (signature template) is present
3634 // determining the signature of the argument
3635 Type
*signature
= 0;
3636 bool signature_determined
= false;
3638 // the port reference is correct and the port type is known
3639 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3640 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3642 if (in_sigs
->get_nof_types() == 1) {
3643 // there is only one incoming signature
3644 signature
= in_sigs
->get_type_byIndex(0);
3646 // there are more than one incoming signatures
3647 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3649 if (!in_sigs
->has_type(signature
)) {
3650 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3651 "incoming list of port type `%s'",
3652 signature
->get_typename().c_str(),
3653 port_type
->get_typename().c_str());
3656 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3660 signature_determined
= true;
3661 } else if (port_type_body
->get_operation_mode() ==
3662 PortTypeBody::PO_MESSAGE
) {
3663 port_op
.portref
->error("Procedure-based operation `%s' is not "
3664 "applicable to a message-based port of type `%s'", stmt_name
,
3665 port_type
->get_typename().c_str());
3667 port_op
.portref
->error("Port type `%s' does not have any incoming "
3668 "signatures", port_type
->get_typename().c_str());
3670 } else if (!port_op
.portref
) {
3671 // the statement refers to 'any port'
3672 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3674 if (port_op
.r
.redirect
.param
) {
3675 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3676 "have parameter redirect", stmt_name
);
3679 if (!signature_determined
)
3680 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3681 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3682 // checking the parameter (template instance)
3683 port_op
.r
.rcvpar
->chk(signature
);
3684 // checking whether the argument is a signature template
3685 // and checking the parameter redirect if present
3686 signature
= signature
->get_type_refd_last();
3687 switch (signature
->get_typetype()) {
3688 case Type::T_SIGNATURE
:
3689 if (port_op
.r
.redirect
.param
)
3690 port_op
.r
.redirect
.param
->chk(signature
, false);
3693 if (port_op
.r
.redirect
.param
)
3694 port_op
.r
.redirect
.param
->chk_erroneous();
3697 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3698 "a signature", signature
->get_typename().c_str());
3699 if (port_op
.r
.redirect
.param
)
3700 port_op
.r
.redirect
.param
->chk_erroneous();
3703 // the statement does not have parameter
3705 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3706 if (!port_type_body
->get_in_sigs()) {
3707 // the port type is known and it does not have incoming signatures
3708 if (port_type_body
->get_operation_mode() ==
3709 PortTypeBody::PO_MESSAGE
) {
3710 port_op
.portref
->error("Procedure-based operation `%s' is not "
3711 "applicable to a message-based port of type `%s'", stmt_name
,
3712 port_type
->get_typename().c_str());
3714 port_op
.portref
->error("Port type `%s' does not have any incoming "
3715 "signatures", port_type
->get_typename().c_str());
3719 if (port_op
.r
.redirect
.param
) {
3720 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3721 "without signature template");
3722 port_op
.r
.redirect
.param
->chk_erroneous();
3725 // checking from clause and sender redirect
3726 chk_from_clause(port_type
);
3729 void Statement::chk_getreply()
3731 // determining statement type
3732 const char *stmt_name
= get_stmt_name();
3733 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3734 // checking the port reference
3735 Type
*port_type
= chk_port_ref(port_op
.portref
);
3736 if (port_op
.r
.rcvpar
) {
3737 // the parameter (signature template) is present
3738 // determining the signature of the argument
3739 Type
*signature
= 0;
3740 bool signature_determined
= false;
3742 // the port reference is correct and the port type is known
3743 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3744 if (port_type_body
->getreply_allowed()) {
3745 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3746 if (out_sigs
->get_nof_types() == 1) {
3747 // there is only one outgoing signature
3748 signature
= out_sigs
->get_type_byIndex(0);
3750 // there are more than one outgoing signatures
3751 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3753 if (!out_sigs
->has_type(signature
)) {
3754 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3755 "outgoing list of port type `%s'",
3756 signature
->get_typename().c_str(),
3757 port_type
->get_typename().c_str());
3760 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3764 signature_determined
= true;
3765 } else if (port_type_body
->get_operation_mode() ==
3766 PortTypeBody::PO_MESSAGE
) {
3767 port_op
.portref
->error("Procedure-based operation `%s' is not "
3768 "applicable to a message-based port of type `%s'", stmt_name
,
3769 port_type
->get_typename().c_str());
3771 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3772 "signatures that support reply", port_type
->get_typename().c_str());
3774 } else if (!port_op
.portref
) {
3775 // the statement refers to 'any port'
3776 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3778 if (port_op
.r
.getreply_valuematch
) {
3779 port_op
.r
.getreply_valuematch
->error("Operation `any port.%s' cannot "
3780 "have value match", stmt_name
);
3782 if (port_op
.r
.redirect
.value
) {
3783 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot "
3784 "have value redirect", stmt_name
);
3786 if (port_op
.r
.redirect
.param
) {
3787 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3788 "have parameter redirect", stmt_name
);
3791 if (!signature_determined
)
3792 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3793 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3794 // checking the parameter (template instance)
3795 port_op
.r
.rcvpar
->chk(signature
);
3796 // checking whether the argument is a signature template
3797 // checking the parameter redirect if present
3798 // and determining the return type of the signature
3799 signature
= signature
->get_type_refd_last();
3800 Type
*return_type
= 0;
3801 switch (signature
->get_typetype()) {
3802 case Type::T_SIGNATURE
:
3803 if (signature
->is_nonblocking_signature())
3804 error("Operation `%s' is not applicable to non-blocking signature "
3805 "`%s'", stmt_name
, signature
->get_typename().c_str());
3806 else return_type
= signature
->get_signature_return_type();
3807 if (port_op
.r
.redirect
.param
)
3808 port_op
.r
.redirect
.param
->chk(signature
, true);
3810 if (port_op
.r
.getreply_valuematch
) {
3811 port_op
.r
.getreply_valuematch
->error("Value match cannot be used "
3812 "because signature `%s' does not have return type",
3813 signature
->get_typename().c_str());
3815 if (port_op
.r
.redirect
.value
) {
3816 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3817 "because signature `%s' does not have return type",
3818 signature
->get_typename().c_str());
3823 if (port_op
.r
.redirect
.param
)
3824 port_op
.r
.redirect
.param
->chk_erroneous();
3827 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3828 "a signature", signature
->get_typename().c_str());
3829 if (port_op
.r
.redirect
.param
)
3830 port_op
.r
.redirect
.param
->chk_erroneous();
3832 // checking the value match if present
3833 if (port_op
.r
.getreply_valuematch
) {
3834 Error_Context
cntxt2(port_op
.s
.replyval
, "In value match");
3835 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3836 port_op
.r
.getreply_valuematch
->chk(return_type
);
3838 // checking the value redirect if present
3839 chk_value_redirect(port_op
.r
.redirect
.value
, return_type
);
3841 // the statement does not have parameter (value match is also omitted)
3843 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3844 if (!port_type_body
->getreply_allowed()) {
3845 // the port type is known and it does not have outgoing signatures
3846 if (port_type_body
->get_operation_mode() ==
3847 PortTypeBody::PO_MESSAGE
) {
3848 port_op
.portref
->error("Procedure-based operation `%s' is not "
3849 "applicable to a message-based port of type `%s'", stmt_name
,
3850 port_type
->get_typename().c_str());
3852 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3853 "signatures that support reply",
3854 port_type
->get_typename().c_str());
3858 if (port_op
.r
.redirect
.value
) {
3859 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3860 "without signature template");
3861 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3863 if (port_op
.r
.redirect
.param
) {
3864 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3865 "without signature template");
3866 port_op
.r
.redirect
.param
->chk_erroneous();
3869 // checking from clause and sender redirect
3870 chk_from_clause(port_type
);
3873 void Statement::chk_catch()
3875 // determining statement type
3876 const char *stmt_name
= get_stmt_name();
3877 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3878 // checking the port reference
3879 Type
*port_type
= chk_port_ref(port_op
.portref
);
3880 // checking the signature reference, parameter and/or value redirect
3881 if (port_op
.r
.ctch
.signature_ref
) {
3882 // the signature reference is present
3883 port_op
.r
.ctch
.signature
=
3884 chk_signature_ref(port_op
.r
.ctch
.signature_ref
);
3885 // checking whether the signature is present on the incoming list
3886 // of the respective port type
3888 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3889 if (port_type_body
->catch_allowed()) {
3890 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3891 if (port_op
.r
.ctch
.signature
) {
3892 if (!out_sigs
->has_type(port_op
.r
.ctch
.signature
)) {
3893 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' is not "
3894 "present on the outgoing list of port type `%s'",
3895 port_op
.r
.ctch
.signature
->get_typename().c_str(),
3896 port_type
->get_typename().c_str());
3898 } else if (out_sigs
->get_nof_types() == 1) {
3899 // if the signature is unknown and the port type has exactly one
3900 // outgoing signature then use that for further checking
3901 port_op
.r
.ctch
.signature
=
3902 out_sigs
->get_type_byIndex(0)->get_type_refd_last();
3904 } else if (port_type_body
->get_operation_mode() ==
3905 PortTypeBody::PO_MESSAGE
) {
3906 port_op
.portref
->error("Procedure-based operation `%s' is not "
3907 "applicable to a message-based port of type `%s'", stmt_name
,
3908 port_type
->get_typename().c_str());
3910 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3911 "signatures that support exceptions",
3912 port_type
->get_typename().c_str());
3914 } else if (!port_op
.portref
) {
3915 // the statement refers to 'any port'
3916 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3918 if (port_op
.r
.redirect
.value
) {
3919 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3920 "value redirect", stmt_name
);
3923 // the receive parameter (template instance) must be also present
3924 // trying to determine type of the exception
3926 bool exc_type_determined
= false, value_redirect_checked
= false;
3927 if (port_op
.r
.ctch
.signature
) {
3928 // the signature is known
3929 SignatureExceptions
*exceptions
=
3930 port_op
.r
.ctch
.signature
->get_signature_exceptions();
3932 if (exceptions
->get_nof_types() == 1) {
3933 // the signature has exactly one exception type
3934 // use that for checking
3935 exc_type
= exceptions
->get_type_byIndex(0);
3937 // the signature has more than one exception types
3938 exc_type
= get_incoming_type(port_op
.r
.rcvpar
,
3939 port_op
.r
.redirect
.value
, value_redirect_checked
);
3941 size_t nof_comp_types
=
3942 exceptions
->get_nof_compatible_types(exc_type
);
3943 if (nof_comp_types
== 0) {
3944 port_op
.r
.rcvpar
->error("Type `%s' is not present on the "
3945 "exception list of signature `%s'",
3946 exc_type
->get_typename().c_str(),
3947 port_op
.r
.ctch
.signature
->get_typename().c_str());
3948 } else if (nof_comp_types
> 1) {
3949 port_op
.r
.rcvpar
->error("Type of the exception is ambiguous: "
3950 "`%s' is compatible with more than one exception types of "
3951 "signature `%s'", exc_type
->get_typename().c_str(),
3952 port_op
.r
.ctch
.signature
->get_typename().c_str());
3955 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3959 exc_type_determined
= true;
3961 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' does not have "
3962 "exceptions", port_op
.r
.ctch
.signature
->get_typename().c_str());
3965 if (!exc_type_determined
) {
3966 exc_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3967 value_redirect_checked
);
3969 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3970 // check the template instance using the exception type
3971 port_op
.r
.rcvpar
->chk(exc_type
);
3972 // check the value redirect if it is not done so far
3973 if (!value_redirect_checked
)
3974 chk_value_redirect(port_op
.r
.redirect
.value
, exc_type
);
3975 // checking for invalid exception types
3976 exc_type
= exc_type
->get_type_refd_last();
3977 switch (exc_type
->get_typetype()) {
3978 case Type::T_SIGNATURE
:
3979 port_op
.r
.rcvpar
->error("The type of catch parameter is signature "
3980 "`%s', which cannot be an exception type",
3981 exc_type
->get_typename().c_str());
3984 port_op
.r
.rcvpar
->error("The type of catch parameter is port type "
3985 "`%s', which cannot be an exception type",
3986 exc_type
->get_typename().c_str());
3988 case Type::T_DEFAULT
:
3989 port_op
.r
.rcvpar
->error("The type of catch parameter is the `default' "
3990 "type, which cannot be an exception type");
3995 // the statement does not have signature reference
3996 if (port_op
.r
.ctch
.timeout
) {
3997 // the parameter is timeout
3998 if (port_op
.portref
) {
3999 // the port reference is present
4001 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4002 if (!port_type_body
->getreply_allowed()) {
4003 // the port type is known and it does not allow blocking calls
4004 if (port_type_body
->get_operation_mode() ==
4005 PortTypeBody::PO_MESSAGE
) {
4006 port_op
.portref
->error("Timeout exception cannot be caught on "
4007 "a message-based port of type `%s'",
4008 port_type
->get_typename().c_str());
4010 port_op
.portref
->error("Timeout exception cannot be caught on "
4011 "a port of type `%s', which does not have any outgoing "
4012 "signatures that allow blocking calls",
4013 port_type
->get_typename().c_str());
4017 } else error("Timeout exception cannot be caught on `any port'");
4018 if (!port_op
.r
.ctch
.in_call
)
4019 error("Catching of `timeout' exception is not allowed in this "
4020 "context. It is permitted only in the response and exception "
4021 "handling part of `call' operations");
4022 else if (!port_op
.r
.ctch
.call_has_timer
)
4023 error("Catching of `timeout' exception is not allowed because the "
4024 "previous `call' operation does not have timer");
4025 if (port_op
.r
.fromclause
) port_op
.r
.fromclause
->error(
4026 "Operation `catch(timeout)' cannot have from clause");
4027 if (port_op
.r
.redirect
.sender
) port_op
.r
.redirect
.sender
->error(
4028 "Operation `catch(timeout)' cannot have sender redirect");
4030 // the operation does not have any parameter
4032 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4033 if (!port_type_body
->catch_allowed()) {
4034 // the port type is known and it does not have outgoing signatures
4035 if (port_type_body
->get_operation_mode() ==
4036 PortTypeBody::PO_MESSAGE
) {
4037 port_op
.portref
->error("Procedure-based operation `%s' is not "
4038 "applicable to a message-based port of type `%s'", stmt_name
,
4039 port_type
->get_typename().c_str());
4041 port_op
.portref
->error("Port type `%s' does not have any "
4042 "outgoing signatures that support exceptions",
4043 port_type
->get_typename().c_str());
4048 if (port_op
.r
.redirect
.value
) {
4049 // the statement does not have any parameter,
4050 // but the value redirect is present
4051 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
4052 "signature and parameter");
4053 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
4056 // checking from clause and sender redirect
4057 chk_from_clause(port_type
);
4060 void Statement::chk_check()
4062 Error_Context
cntxt(this, "In check statement");
4063 Type
*port_type
= chk_port_ref(port_op
.portref
);
4064 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4065 // the port type is known and it does not have incoming queue
4066 port_op
.portref
->error("Port type `%s' does not have incoming queue "
4067 "because it has neither incoming messages nor incoming or outgoing "
4068 "signatures", port_type
->get_typename().c_str());
4070 // checking from clause and sender redirect
4071 chk_from_clause(port_type
);
4074 void Statement::chk_clear()
4076 Error_Context
cntxt(this, "In clear port statement");
4077 Type
*port_type
= chk_port_ref(port_op
.portref
);
4078 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4079 // the port type is known and it does not have incoming queue
4080 port_op
.portref
->warning("Port type `%s' does not have incoming queue "
4081 "because it has neither incoming messages nor incoming or outgoing "
4082 "signatures", port_type
->get_typename().c_str());
4086 void Statement::chk_start_stop_port()
4088 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4089 chk_port_ref(port_op
.portref
);
4092 void Statement::chk_start_comp()
4094 Error_Context
cntxt(this, "In start test component statement");
4095 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4096 Common::Assignment
*t_ass
= comp_op
.funcinstref
->get_refd_assignment();
4098 // checking whether the referred definition is a function
4099 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
4101 case Common::Assignment::A_FUNCTION
:
4102 case Common::Assignment::A_FUNCTION_RVAL
:
4103 case Common::Assignment::A_FUNCTION_RTEMP
:
4106 comp_op
.funcinstref
->error("Reference to a function was expected in the "
4107 "argument instead of %s", t_ass
->get_description().c_str());
4110 Def_Function
*t_func
= dynamic_cast<Def_Function
*>(t_ass
);
4111 if (!t_func
) FATAL_ERROR("Statement::chk_start_comp()");
4112 // checking startability
4113 if (!t_func
->chk_startable()) return;
4114 // checking the 'runs on' clause against the type of component reference
4115 Type
*runs_on_type
= t_func
->get_RunsOnType();
4116 if (!comp_type
|| !runs_on_type
) return;
4117 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4118 comp_op
.compref
->error("Component type mismatch: The component reference "
4119 "is of type `%s', but %s runs on `%s'",
4120 comp_type
->get_typename().c_str(), t_func
->get_description().c_str(),
4121 runs_on_type
->get_typename().c_str());
4122 // checking the return type
4124 case Common::Assignment::A_FUNCTION_RTEMP
:
4125 comp_op
.funcinstref
->warning("Function `%s' returns a template of type "
4126 "`%s', which cannot be retrieved when the test component terminates",
4127 t_func
->get_fullname().c_str(),
4128 t_func
->get_Type()->get_typename().c_str());
4130 case Common::Assignment::A_FUNCTION_RVAL
: {
4131 bool return_type_correct
= false;
4132 Type
*return_type
= t_func
->get_Type();
4133 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4134 if (t
->has_done_attribute()) {
4135 return_type_correct
= true;
4137 } else if (!t
->is_ref()) break;
4139 if (!return_type_correct
)
4140 comp_op
.funcinstref
->warning("The return type of %s is `%s', which "
4141 "does not have the `done' extension attribute. When the test "
4142 "component terminates the returned value cannot be retrieved with "
4143 "a `done' operation", t_func
->get_description().c_str(),
4144 return_type
->get_typename().c_str());
4151 void Statement::chk_start_comp_refd()
4153 Error_Context
cntxt(this, "In start test component statement");
4154 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4155 switch(comp_op
.derefered
.value
->get_valuetype()){
4156 case Value::V_REFER
:
4157 comp_op
.derefered
.value
->error("A value of a function type was expected "
4158 "in the argument instead of a `refers' statement,"
4159 " which does not specify any function type");
4161 case Value::V_TTCN3_NULL
:
4162 comp_op
.derefered
.value
->error("A value of a function type was expected "
4163 "in the argument instead of a `null' value,"
4164 " which does not specify any function type");
4169 Type
*f_type
= comp_op
.derefered
.value
->get_expr_governor_last();
4170 if (!f_type
) return;
4171 switch (f_type
->get_typetype()) {
4174 case Type::T_FUNCTION
:
4177 comp_op
.derefered
.value
->error("A value of type function was expected "
4178 "in the argument instead of `%s'", f_type
->get_typename().c_str());
4181 if (f_type
->get_fat_runs_on_self()) {
4182 fau_refd
.value
->error("The argument cannot be a function reference with "
4183 "'runs on self' clause");
4186 if(!f_type
->chk_startability()) return;
4187 Type
*runs_on_type
= f_type
->get_fat_runs_on_type();
4188 if (!comp_type
|| !runs_on_type
) return;
4189 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4190 comp_op
.compref
->error("Component type mismatch: The component reference "
4191 "is of type `%s', but functions of type `%s' run on `%s'",
4192 comp_type
->get_typename().c_str(), f_type
->get_typename().c_str(),
4193 runs_on_type
->get_typename().c_str());
4194 Type
*return_type
= f_type
->get_function_return_type();
4196 if (f_type
->get_returns_template()) {
4197 comp_op
.derefered
.value
->warning("Functions of type `%s' return a "
4198 "template of type `%s', which cannot be retrieved when the test "
4199 "component terminates", f_type
->get_typename().c_str(),
4200 return_type
->get_typename().c_str());
4202 bool return_type_correct
= false;
4203 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4204 if (t
->has_done_attribute()) {
4205 return_type_correct
= true;
4207 } else if (!t
->is_ref()) break;
4209 if (!return_type_correct
)
4210 comp_op
.derefered
.value
->warning("The return type of function type "
4211 "`%s' is `%s', which does not have the `done' extension attribute. "
4212 "When the test component terminates the returned value cannot be "
4213 "retrieved with a `done' operation", f_type
->get_typename().c_str(),
4214 return_type
->get_typename().c_str());
4217 ActualParList
*parlist
= new ActualParList
;
4218 Ttcn::FormalParList
*fp_list
= f_type
->get_fat_parameters();
4219 if(fp_list
->fold_named_and_chk(comp_op
.derefered
.t_list1
, parlist
)) {
4221 delete comp_op
.derefered
.t_list1
;
4222 comp_op
.derefered
.ap_list2
= 0;
4224 delete comp_op
.derefered
.t_list1
;
4225 parlist
->set_fullname(get_fullname());
4226 parlist
->set_my_scope(my_sb
);
4227 comp_op
.derefered
.ap_list2
= parlist
;
4231 void Statement::chk_stop_kill_comp()
4233 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4234 chk_comp_ref(comp_op
.compref
, true, false);
4237 void Statement::chk_done()
4239 Error_Context
cntxt(this, "In done statement");
4240 chk_comp_ref(comp_op
.compref
, false, false);
4241 if (!comp_op
.compref
) return;
4242 // value returning done can be used only when the statement contains a
4243 // specific component reference
4244 if (comp_op
.donereturn
.donematch
) {
4245 bool value_redirect_checked
= false;
4246 // try to determine the type of return value
4247 Type
*return_type
= get_incoming_type(comp_op
.donereturn
.donematch
,
4248 comp_op
.donereturn
.redirect
, value_redirect_checked
);
4250 bool return_type_correct
= false;
4251 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4252 if (t
->has_done_attribute()) {
4253 return_type_correct
= true;
4255 } else if (!t
->is_ref()) break;
4257 if (!return_type_correct
) {
4258 error("Return type `%s' does not have `done' extension attribute",
4259 return_type
->get_typename().c_str());
4260 return_type
= Type::get_pooltype(Type::T_ERROR
);
4263 comp_op
.donereturn
.donematch
->error("Cannot determine the return type "
4264 "for value returning done");
4265 return_type
= Type::get_pooltype(Type::T_ERROR
);
4267 comp_op
.donereturn
.donematch
->chk(return_type
);
4268 if (!value_redirect_checked
)
4269 chk_value_redirect(comp_op
.donereturn
.redirect
, return_type
);
4270 } else if (comp_op
.donereturn
.redirect
) {
4271 comp_op
.donereturn
.redirect
->error("Redirect cannot be used for the "
4272 "return value without a matching template");
4273 chk_value_redirect(comp_op
.donereturn
.redirect
, 0);
4277 void Statement::chk_killed()
4279 Error_Context
cntxt(this, "In killed statement");
4280 chk_comp_ref(comp_op
.compref
, false, false);
4283 void Statement::chk_connect()
4285 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4286 // checking endpoints
4288 PortTypeBody
*ptb1
, *ptb2
;
4290 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4291 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, false);
4292 ptb1
= pt1
? pt1
->get_PortBody() : 0;
4295 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4296 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, false);
4297 ptb2
= pt2
? pt2
->get_PortBody() : 0;
4299 // checking consistency
4300 if (!ptb1
|| !ptb2
) return;
4301 if (!ptb1
->is_connectable(ptb2
) ||
4302 (ptb1
!= ptb2
&& !ptb2
->is_connectable(ptb1
))) {
4303 error("The connection between port types `%s' and `%s' is not consistent",
4304 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4305 ptb1
->report_connection_errors(ptb2
);
4306 if (ptb1
!= ptb2
) ptb2
->report_connection_errors(ptb1
);
4310 void Statement::chk_map()
4312 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4313 // checking endpoints
4315 PortTypeBody
*ptb1
, *ptb2
;
4316 bool cref1_is_tc
= false, cref1_is_system
= false;
4317 bool cref2_is_tc
= false, cref2_is_system
= false;
4319 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4320 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, true);
4322 ptb1
= pt1
->get_PortBody();
4323 if (ptb1
->is_internal()) {
4324 config_op
.portref1
->warning("Port type `%s' was marked as `internal'",
4325 pt1
->get_typename().c_str());
4328 Value
*cref1
= config_op
.compref1
->get_value_refd_last();
4329 if (cref1
->get_valuetype() == Value::V_EXPR
) {
4330 switch (cref1
->get_optype()) {
4331 case Value::OPTYPE_COMP_MTC
:
4332 case Value::OPTYPE_COMP_SELF
:
4333 case Value::OPTYPE_COMP_CREATE
:
4336 case Value::OPTYPE_COMP_SYSTEM
:
4337 cref1_is_system
= true;
4344 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4345 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, true);
4347 ptb2
= pt2
->get_PortBody();
4348 if (ptb2
->is_internal()) {
4349 config_op
.portref2
->warning("Port type `%s' was marked as `internal'",
4350 pt2
->get_typename().c_str());
4353 Value
*cref2
= config_op
.compref2
->get_value_refd_last();
4354 if (cref2
->get_valuetype() == Value::V_EXPR
) {
4355 switch (cref2
->get_optype()) {
4356 case Value::OPTYPE_COMP_MTC
:
4357 case Value::OPTYPE_COMP_SELF
:
4358 case Value::OPTYPE_COMP_CREATE
:
4361 case Value::OPTYPE_COMP_SYSTEM
:
4362 cref2_is_system
= true;
4368 if (cref1_is_tc
&& cref2_is_tc
) {
4369 error("Both endpoints of the mapping are test component ports");
4372 if (cref1_is_system
&& cref2_is_system
) {
4373 error("Both endpoints of the mapping are system ports");
4376 // checking consistency
4377 if (!ptb1
|| !ptb2
) return;
4378 if (cref1_is_tc
|| cref2_is_system
) {
4379 if (!ptb1
->is_mappable(ptb2
)) {
4380 error("The mapping between test component port type `%s' and system "
4381 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4382 pt2
->get_typename().c_str());
4383 ptb1
->report_mapping_errors(ptb2
);
4385 } else if (cref2_is_tc
|| cref1_is_system
) {
4386 if (!ptb2
->is_mappable(ptb1
)) {
4387 error("The mapping between system port type `%s' and test component "
4388 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4389 pt2
->get_typename().c_str());
4390 ptb2
->report_mapping_errors(ptb1
);
4393 // we have no idea which one is the system port
4394 if (!ptb1
->is_mappable(ptb1
) && !ptb2
->is_mappable(ptb1
)) {
4395 error("The mapping between port types `%s' and `%s' is not consistent",
4396 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4401 void Statement::chk_start_timer()
4403 Error_Context
cntxt(this, "In start timer statement");
4404 chk_timer_ref(timer_op
.timerref
);
4405 if (timer_op
.value
) {
4406 // check the actual duration
4407 timer_op
.value
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4408 Value
*t_val
= timer_op
.value
->get_value_refd_last();
4409 if (t_val
->get_valuetype() == Value::V_REAL
) {
4410 ttcn3float v_real
= t_val
->get_val_Real();
4412 timer_op
.value
->error("The timer duration is negative: `%s'",
4413 Real2string(v_real
).c_str());
4414 } else if (isSpecialFloatValue(v_real
)) {
4415 timer_op
.value
->error("The timer duration cannot be %s",
4416 Real2string(v_real
).c_str());
4420 // check whether the timer has default duration
4421 Common::Assignment
*t_ass
= timer_op
.timerref
->get_refd_assignment();
4422 if (t_ass
&& t_ass
->get_asstype() == Common::Assignment::A_TIMER
) {
4423 Def_Timer
*t_def_timer
= dynamic_cast<Def_Timer
*>(t_ass
);
4424 if (!t_def_timer
) FATAL_ERROR("Statement::chk_start_timer()");
4425 if (!t_def_timer
->has_default_duration(
4426 timer_op
.timerref
->get_subrefs()))
4427 error("Missing duration: %s does not have default duration",
4428 t_ass
->get_description().c_str());
4433 void Statement::chk_stop_timer_timeout()
4435 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4436 chk_timer_ref(timer_op
.timerref
);
4439 void Statement::chk_setverdict()
4441 Error_Context
cntxt(this, "In setverdict statement");
4442 if(!my_sb
->get_my_def())
4443 error("Setverdict statement is not allowed in the control part");
4444 setverdict
.verdictval
->chk_expr_verdict(Type::EXPECTED_DYNAMIC_VALUE
);
4445 Value
*t_val
= setverdict
.verdictval
->get_value_refd_last();
4446 if (t_val
->get_valuetype() == Value::V_VERDICT
&&
4447 t_val
->get_val_verdict() == Value::Verdict_ERROR
) {
4448 setverdict
.verdictval
->error("Error verdict cannot be set by the setverdict "
4453 void Statement::chk_execute()
4455 Error_Context
cntxt(this, "In execute statement");
4456 Ref_pard
*ref
=testcase_inst
.tcref
;
4457 Common::Assignment
*t_ass
=ref
->get_refd_assignment();
4458 if(!t_ass
) goto error
;
4459 if(t_ass
->get_asstype()!=Common::Assignment::A_TESTCASE
) {
4460 ref
->error("Reference to a testcase was expected in the argument"
4461 " instead of %s", t_ass
->get_description().c_str());
4464 if(my_sb
->get_scope_runs_on()) {
4465 ref
->error("A definition that has `runs on' clause cannot "
4466 "execute testcases");
4469 if (testcase_inst
.timerval
) {
4470 testcase_inst
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4471 Value
*t_val
= testcase_inst
.timerval
->get_value_refd_last();
4472 if (t_val
->get_valuetype() == Value::V_REAL
) {
4473 ttcn3float v_real
= t_val
->get_val_Real();
4475 testcase_inst
.timerval
->error("The testcase guard "
4476 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4477 } else if (isSpecialFloatValue(v_real
)) {
4478 testcase_inst
.timerval
->error("The testcase guard "
4479 "timer duration cannot be %s", Real2string(v_real
).c_str());
4486 statementtype
=S_ERROR
;
4489 void Statement::chk_execute_refd()
4491 Error_Context
cntxt(this, "In execute statement");
4492 switch(execute_refd
.value
->get_valuetype()){
4493 case Value::V_REFER
:
4494 execute_refd
.value
->error("A value of a testcase type was expected "
4495 "in the argument instead of a `refers' statement,"
4496 " which does not specify any function type");
4498 case Value::V_TTCN3_NULL
:
4499 execute_refd
.value
->error("A value of a testcase type was expected "
4500 "in the argument instead of a `null' value,"
4501 " which does not specify any function type");
4506 Type
*t
= execute_refd
.value
->get_expr_governor_last();
4508 switch (t
->get_typetype()) {
4511 case Type::T_TESTCASE
:
4514 execute_refd
.value
->error("A value of type testcase was expected in the "
4515 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
4518 if (my_sb
->get_scope_runs_on()) {
4519 execute_refd
.value
->error("A definition that has `runs on' clause cannot "
4520 "execute testcases");
4523 ActualParList
*parlist
= new ActualParList
;
4524 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
4525 bool is_erroneous
= fp_list
->chk_actual_parlist(execute_refd
.t_list1
,
4527 delete execute_refd
.t_list1
;
4530 execute_refd
.ap_list2
= 0;
4533 parlist
->set_fullname(get_fullname());
4534 parlist
->set_my_scope(my_sb
);
4535 execute_refd
.ap_list2
= parlist
;
4537 if(execute_refd
.timerval
) {
4538 execute_refd
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4539 Value
*t_val
= execute_refd
.timerval
->get_value_refd_last();
4540 if(t_val
->get_valuetype() == Value::V_REAL
) {
4541 ttcn3float v_real
= t_val
->get_val_Real();
4543 execute_refd
.value
->error("The testcase guard "
4544 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4545 } else if (isSpecialFloatValue(v_real
)) {
4546 execute_refd
.value
->error("The testcase guard "
4547 "timer duration cannot be %s", Real2string(v_real
).c_str());
4555 statementtype
=S_ERROR
;
4558 Type
*Statement::chk_port_ref(Reference
*p_ref
)
4560 if (!my_sb
->get_my_def())
4561 error("Port operation is not allowed in the control part");
4562 if (!p_ref
) return 0;
4563 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4564 if (!t_ass
) return 0;
4565 switch (t_ass
->get_asstype()) {
4566 case Common::Assignment::A_PORT
: {
4567 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4568 if (t_dims
) t_dims
->chk_indices(p_ref
, "port", false,
4569 Type::EXPECTED_DYNAMIC_VALUE
);
4570 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4571 "cannot have field or array sub-references",
4572 t_ass
->get_description().c_str());
4574 case Common::Assignment::A_PAR_PORT
:
4575 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4576 "field or array sub-references", t_ass
->get_description().c_str());
4579 p_ref
->error("Reference to a port or port parameter was expected "
4580 "instead of %s", t_ass
->get_description().c_str());
4583 Type
*ret_val
= t_ass
->get_Type();
4584 if (!ret_val
) return 0;
4585 ret_val
= ret_val
->get_type_refd_last();
4586 if (ret_val
->get_typetype() == Type::T_PORT
) return ret_val
;
4590 void Statement::chk_to_clause(Type
*port_type
)
4592 if (!port_op
.s
.toclause
) return;
4593 // pointer to the address type
4596 // the port type is known
4597 address_type
= port_type
->get_PortBody()->get_address_type();
4599 // the port type is unknown
4600 // address is permitted if it is visible from the current module
4601 address_type
= my_sb
->get_scope_mod()->get_address_type();
4603 Error_Context
cntxt(port_op
.s
.toclause
, "In `to' clause");
4605 // detect possible enumerated values (address may be an enumerated type)
4606 address_type
->chk_this_value_ref(port_op
.s
.toclause
);
4607 // try to figure out whether the argument is a component reference or
4611 port_op
.s
.toclause
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4612 if (t_governor
) is_address
= address_type
->is_compatible(t_governor
, NULL
);
4614 port_op
.s
.toclause
->get_expr_returntype(Type::EXPECTED_DYNAMIC_VALUE
)
4615 != Type::T_COMPONENT
;
4617 // the argument is an address value
4618 port_op
.s
.toclause
->set_my_governor(address_type
);
4619 address_type
->chk_this_value(port_op
.s
.toclause
, 0,
4620 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
4623 // the argument is not an address value, treat as a component reference
4624 chk_comp_ref(port_op
.s
.toclause
, true, true);
4627 // usage of address is not allowed
4628 chk_comp_ref(port_op
.s
.toclause
, true, true);
4632 void Statement::chk_from_clause(Type
*port_type
)
4634 if (!port_op
.r
.fromclause
&& !port_op
.r
.redirect
.sender
) return;
4635 // pointer to the address type
4638 // the port type is known
4639 address_type
= port_type
->get_PortBody()->get_address_type();
4640 } else if (port_op
.portref
) {
4641 // the operation refers to a specific port, but its type is unknown
4642 // address is permitted if it is visible from the current module
4643 address_type
= my_sb
->get_scope_mod()->get_address_type();
4645 // the operation refers to 'any port'
4646 // address is not allowed
4649 bool sender_redirect_checked
= false;
4650 Type
*from_clause_type
= 0;
4651 if (port_op
.r
.fromclause
) {
4652 // the from clause is present
4653 Error_Context
cntxt(port_op
.r
.fromclause
, "In `from' clause");
4655 port_op
.r
.fromclause
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4656 Template
*templ_body
= port_op
.r
.fromclause
->get_Template();
4657 if (!from_clause_type
) {
4658 // try to detect possible enumerated values
4659 if (address_type
) address_type
->chk_this_template_ref(templ_body
);
4660 else templ_body
->set_lowerid_to_ref();
4662 templ_body
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4664 if (!from_clause_type
) {
4665 // trying to determine the type of template in from clause
4666 // based on the sender redirect
4667 from_clause_type
= chk_sender_redirect(address_type
);
4668 sender_redirect_checked
= true;
4670 if (!from_clause_type
) {
4671 // trying to figure out whether the template is a component reference
4672 // or an SUT address
4674 if (templ_body
->get_expr_returntype(Type::EXPECTED_TEMPLATE
)
4675 == Type::T_COMPONENT
) is_compref
= true;
4677 switch (templ_body
->get_templatetype()) {
4678 case Template::SPECIFIC_VALUE
:
4679 // treat 'null' as component reference
4680 if (templ_body
->get_specific_value()->get_valuetype() ==
4681 Value::V_TTCN3_NULL
) is_compref
= true;
4682 else is_compref
= false;
4684 case Template::ANY_VALUE
:
4685 case Template::ANY_OR_OMIT
:
4686 // treat generic wildcards ? and * as component references
4694 // the argument is a component reference: get a pool type
4695 from_clause_type
= Type::get_pooltype(Type::T_COMPONENT
);
4696 } else if (address_type
) {
4697 // the argument is not a component reference: try the address type
4698 from_clause_type
= address_type
;
4701 if (from_clause_type
) {
4702 // the type of from clause is known
4703 port_op
.r
.fromclause
->chk(from_clause_type
);
4705 || !address_type
->is_compatible(from_clause_type
, NULL
)) {
4706 // from_clause_type must be a component type
4707 switch (from_clause_type
->get_type_refd_last()->get_typetype()) {
4709 // to avoid further errors in sender redirect
4710 from_clause_type
= 0;
4711 case Type::T_COMPONENT
:
4712 if (templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
)
4713 chk_comp_ref(templ_body
->get_specific_value(), true, true);
4716 port_op
.r
.fromclause
->error("The type of the template should be a "
4717 "component type %sinstead of `%s'",
4718 address_type
? "or the `address' type " : "",
4719 from_clause_type
->get_typename().c_str());
4720 // to avoid further errors in sender redirect
4721 from_clause_type
= 0;
4725 // the type of from clause is unknown
4726 port_op
.r
.fromclause
->error("Cannot determine the type of the "
4730 if (!sender_redirect_checked
) {
4731 Type
*sender_redirect_type
= chk_sender_redirect(address_type
);
4732 if (from_clause_type
&& sender_redirect_type
&&
4733 !from_clause_type
->is_identical(sender_redirect_type
)) {
4734 error("The types in `from' clause and `sender' redirect are not the "
4735 "same: `%s' was expected instead of `%s'",
4736 from_clause_type
->get_typename().c_str(),
4737 sender_redirect_type
->get_typename().c_str());
4742 void Statement::chk_call_body(Type
*port_type
, Type
*signature
)
4744 bool has_catch_timeout
= false;
4745 // setting the flags whether 'catch(timeout)' statements are allowed
4746 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4747 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4748 if (t_ag
->get_type() != AltGuard::AG_OP
)
4749 FATAL_ERROR("Statement::chk_call_body()");
4750 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4751 if (t_stmt
->statementtype
== S_CATCH
) {
4752 t_stmt
->port_op
.r
.ctch
.in_call
= true;
4753 if (port_op
.s
.call
.timer
)
4754 t_stmt
->port_op
.r
.ctch
.call_has_timer
= true;
4755 if (t_stmt
->port_op
.r
.ctch
.timeout
) has_catch_timeout
= true;
4758 Error_Context
cntxt(this, "In response and exception handling part");
4759 port_op
.s
.call
.body
->set_my_laic_stmt(port_op
.s
.call
.body
, 0);
4760 port_op
.s
.call
.body
->set_my_ags(port_op
.s
.call
.body
);
4761 port_op
.s
.call
.body
->chk();
4763 // checking whether getreply/catch operations refer to the same port
4764 // and same signature as the call operation
4765 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4766 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4767 if (t_ag
->get_type() != AltGuard::AG_OP
)
4768 FATAL_ERROR("Statement::chk_call_body()");
4769 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4770 if (t_stmt
->statementtype
== S_ERROR
) continue;
4771 // checking port reference
4772 if (!t_stmt
->port_op
.portref
) {
4773 t_stmt
->error("The `%s' operation must refer to the same port as "
4774 "the previous `call' statement: `%s' was expected instead of "
4775 "`any port'", t_stmt
->get_stmt_name(),
4776 port_op
.portref
->get_id()->get_dispname().c_str());
4777 } else if (*port_op
.portref
->get_id() !=
4778 *t_stmt
->port_op
.portref
->get_id()) {
4779 t_stmt
->port_op
.portref
->error("The `%s' operation refers to a "
4780 "different port than the previous `call' statement: `%s' was "
4781 "expected instead of `%s'", t_stmt
->get_stmt_name(),
4782 port_op
.portref
->get_id()->get_dispname().c_str(),
4783 t_stmt
->port_op
.portref
->get_id()->get_dispname().c_str());
4785 // checking the signature
4786 switch (t_stmt
->statementtype
) {
4788 if (t_stmt
->port_op
.r
.rcvpar
) {
4789 Type
*t_sig
= t_stmt
->port_op
.r
.rcvpar
4790 ->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4791 if (!signature
->is_compatible(t_sig
, NULL
))
4792 t_stmt
->port_op
.r
.rcvpar
->error("The `getreply' operation refers "
4793 "to a different signature than the previous `call' statement: "
4794 "`%s' was expected instead of `%s'",
4795 signature
->get_typename().c_str(),
4796 t_sig
->get_typename().c_str());
4800 if (t_stmt
->port_op
.r
.ctch
.signature
4801 && !signature
->is_compatible(t_stmt
->port_op
.r
.ctch
.signature
, NULL
))
4802 t_stmt
->port_op
.r
.ctch
.signature_ref
->error("The `catch' "
4803 "operation refers to a different signature than the previous "
4804 "`call' statement: `%s' was expected instead of `%s'",
4805 signature
->get_typename().c_str(),
4806 t_stmt
->port_op
.r
.ctch
.signature
->get_typename().c_str());
4809 FATAL_ERROR("Statement::chk_call_body()");
4813 if (port_op
.s
.call
.timer
&& !has_catch_timeout
)
4814 warning("The call operation has a timer, but the timeout exception is "
4818 Type
*Statement::get_outgoing_type(TemplateInstance
*p_ti
)
4820 // first analyze the template instance as is
4821 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4822 // return if this step was successful
4823 if (ret_val
) return ret_val
;
4824 // try to convert the undef identifier in the template instance to
4825 // a reference because it cannot be an enum value anymore
4826 Template
*t_templ
= p_ti
->get_Template();
4827 t_templ
->set_lowerid_to_ref();
4828 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4831 Type
*Statement::get_incoming_type(TemplateInstance
*p_ti
,
4832 Reference
*p_val_redir
, bool& p_val_redir_checked
)
4834 // first analyze the template instance
4835 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4836 // return if this step was successful
4837 if (ret_val
) return ret_val
;
4838 // use the variable in value redirect in the next step
4839 ret_val
= chk_value_redirect(p_val_redir
, 0);
4840 p_val_redir_checked
= true;
4841 // return if this step was successful
4842 if (ret_val
) return ret_val
;
4843 // finally try to convert the undef identifier in the template instance to
4844 // a reference because it cannot be an enum value anymore
4845 Template
*t_templ
= p_ti
->get_Template();
4846 t_templ
->set_lowerid_to_ref();
4847 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4850 Type
*Statement::chk_value_redirect(Reference
*p_ref
, Type
*p_type
)
4852 if (!p_ref
) return NULL
;
4853 Error_Context
cntxt(p_ref
, "In `value' redirect");
4854 Type
*t_var_type
= p_ref
->chk_variable_ref();
4855 if (p_type
&& t_var_type
) {
4856 TypeCompatInfo
info(my_sb
->get_scope_mod(), p_type
, t_var_type
, true, false);
4857 if (p_ref
->get_subrefs()) info
.set_str2_elem(p_ref
->get_subrefs()->refers_to_string_element());
4860 if (!p_type
->is_compatible(t_var_type
, &info
, &l_chain
, &r_chain
)) {
4861 if (info
.is_subtype_error()) {
4862 p_ref
->error("%s", info
.get_subtype_error().c_str());
4864 if (!info
.is_erroneous()) {
4865 p_ref
->error("Type mismatch in value redirect: "
4866 "A variable of type `%s' was expected instead of `%s'",
4867 p_type
->get_typename().c_str(),
4868 t_var_type
->get_typename().c_str());
4870 p_ref
->error("%s", info
.get_error_str_str().c_str());
4877 Type
*Statement::chk_sender_redirect(Type
*address_type
)
4879 if (!port_op
.r
.redirect
.sender
) return 0;
4880 Error_Context
cntxt(port_op
.r
.redirect
.sender
, "In `sender' redirect");
4881 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
4882 if (!t_var_type
) return 0;
4883 if (!address_type
|| !address_type
->is_identical(t_var_type
)) {
4884 // t_var_type must be a component type
4885 switch (t_var_type
->get_type_refd_last()->get_typetype()) {
4886 case Type::T_COMPONENT
:
4891 port_op
.r
.redirect
.sender
->error("The type of the variable should be "
4892 "a component type %sinstead of `%s'",
4893 address_type
? "or the `address' type " : "",
4894 t_var_type
->get_typename().c_str());
4901 Type
*Statement::chk_signature_ref(Reference
*p_ref
)
4903 if (!p_ref
) FATAL_ERROR("Statement::chk_signature_ref()");
4904 Error_Context(p_ref
, "In signature");
4905 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4906 if (!t_ass
) return 0;
4907 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
) {
4908 p_ref
->error("Reference to a signature was expected instead of %s",
4909 t_ass
->get_description().c_str());
4912 Type
*ret_val
= t_ass
->get_Type();
4913 if (!ret_val
) return 0;
4914 ret_val
= ret_val
->get_field_type(p_ref
->get_subrefs(),
4915 Type::EXPECTED_DYNAMIC_VALUE
);
4916 if (!ret_val
) return 0;
4917 ret_val
= ret_val
->get_type_refd_last();
4918 switch (ret_val
->get_typetype()) {
4919 case Type::T_SIGNATURE
:
4924 p_ref
->error("Reference to a signature was expected instead of port type "
4925 "`%s'", ret_val
->get_typename().c_str());
4928 p_ref
->error("Reference to a signature was expected instead of data type "
4929 "`%s'", ret_val
->get_typename().c_str());
4935 void Statement::chk_timer_ref(Reference
*p_ref
)
4938 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4940 switch (t_ass
->get_asstype()) {
4941 case Common::Assignment::A_TIMER
: {
4942 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4943 if (t_dims
) t_dims
->chk_indices(p_ref
, "timer", false,
4944 Type::EXPECTED_DYNAMIC_VALUE
);
4945 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4946 "cannot have field or array sub-references",
4947 t_ass
->get_description().c_str());
4949 case Common::Assignment::A_PAR_TIMER
:
4950 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4951 "field or array sub-references", t_ass
->get_description().c_str());
4954 p_ref
->error("Reference to a timer or timer parameter was expected "
4955 "instead of %s", t_ass
->get_description().c_str());
4959 Type
*Statement::chk_comp_ref(Value
*p_val
, bool allow_mtc
, bool allow_system
)
4961 if (!my_sb
->get_my_def())
4962 error("Component operation is not allowed in the control part");
4963 if (!p_val
) return 0;
4964 Value
*v
= p_val
->get_value_refd_last();
4965 switch (v
->get_valuetype()) {
4966 case Value::V_ERROR
:
4970 case Value::V_INVOKE
:
4971 if(p_val
->get_expr_returntype() != Type::T_COMPONENT
)
4972 p_val
->error("A component reference was expected as return value");
4974 case Value::V_TTCN3_NULL
:
4975 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
4978 switch (v
->get_optype()) {
4979 case Value::OPTYPE_COMP_NULL
:
4980 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
4982 case Value::OPTYPE_COMP_MTC
:
4984 p_val
->error("The `mtc' component reference shall not be used in `%s' operation", get_stmt_name());
4986 case Value::OPTYPE_COMP_SYSTEM
:
4988 p_val
->error("The `system' component reference shall not be used in `%s' operation", get_stmt_name());
4990 case Value::OPTYPE_COMP_SELF
:
4991 case Value::OPTYPE_COMP_CREATE
:
4994 p_val
->error("A component reference was expected as operand");
4999 p_val
->error("A component reference was expected as operand");
5002 Type
*ret_val
= p_val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
5003 if (!ret_val
) return 0;
5004 ret_val
= ret_val
->get_type_refd_last();
5005 switch (ret_val
->get_typetype()) {
5008 case Type::T_COMPONENT
:
5011 p_val
->error("Type mismatch: The type of the operand should be a "
5012 "component type instead of `%s'", ret_val
->get_typename().c_str());
5017 Type
*Statement::chk_conn_endpoint(Value
*p_compref
, Reference
*p_portref
,
5020 Type
*comp_type
= chk_comp_ref(p_compref
, true, allow_system
);
5022 ComponentTypeBody
*comp_body
= comp_type
->get_CompBody();
5023 p_portref
->set_base_scope(comp_body
);
5024 const Identifier
& t_portid
= *p_portref
->get_id();
5025 if (!comp_body
->has_local_ass_withId(t_portid
)) {
5026 p_portref
->error("Component type `%s' does not have port with name "
5027 "`%s'", comp_type
->get_typename().c_str(),
5028 t_portid
.get_dispname().c_str());
5031 Common::Assignment
*t_ass
= comp_body
->get_local_ass_byId(t_portid
);
5032 if (t_ass
->get_asstype() != Common::Assignment::A_PORT
) {
5033 p_portref
->error("Definition `%s' in component type `%s' is a %s and "
5034 "not a port", t_portid
.get_dispname().c_str(),
5035 comp_type
->get_typename().c_str(), t_ass
->get_assname());
5038 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
5039 if (t_dims
) t_dims
->chk_indices(p_portref
, "port", false,
5040 Type::EXPECTED_DYNAMIC_VALUE
);
5041 else if (p_portref
->get_subrefs()) {
5042 p_portref
->error("Port `%s' is not an array. The "
5043 "reference cannot have array indices",
5044 t_portid
.get_dispname().c_str());
5046 Type
*port_type
= t_ass
->get_Type();
5048 // check whether the external interface is provided by another port type
5049 PortTypeBody
*port_body
= port_type
->get_PortBody();
5050 if (port_body
->get_type() == PortTypeBody::PT_USER
) {
5051 Type
*provider_type
= port_body
->get_provider_type();
5052 if (provider_type
) port_type
= provider_type
;
5057 // the component type cannot be determined
5058 FieldOrArrayRefs
*t_subrefs
= p_portref
->get_subrefs();
5060 // check the array indices: they should be integers
5061 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
5062 t_subrefs
->get_ref(i
)->get_val()
5063 ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
5070 void Statement::set_code_section(
5071 GovernedSimple::code_section_t p_code_section
)
5073 switch(statementtype
) {
5084 ass
->set_code_section(p_code_section
);
5086 case S_FUNCTION_INSTANCE
:
5087 case S_ALTSTEP_INSTANCE
:
5089 ref_pard
->set_code_section(p_code_section
);
5092 block
->set_code_section(p_code_section
);
5096 case S_STOP_TESTCASE
:
5097 if (logargs
) logargs
->set_code_section(p_code_section
);
5100 if_stmt
.ics
->set_code_section(p_code_section
);
5101 if (if_stmt
.elseblock
)
5102 if_stmt
.elseblock
->set_code_section(p_code_section
);
5105 if (!loop
.for_stmt
.varinst
)
5106 loop
.for_stmt
.init_ass
->set_code_section(p_code_section
);
5107 loop
.for_stmt
.finalexpr
->set_code_section(p_code_section
);
5108 loop
.for_stmt
.step
->set_code_section(p_code_section
);
5109 loop
.block
->set_code_section(p_code_section
);
5113 loop
.expr
->set_code_section(p_code_section
);
5114 loop
.block
->set_code_section(p_code_section
);
5117 select
.expr
->set_code_section(p_code_section
);
5118 select
.scs
->set_code_section(p_code_section
);
5122 ags
->set_code_section(p_code_section
);
5125 if (returnexpr
.v
) returnexpr
.v
->set_code_section(p_code_section
);
5126 if (returnexpr
.t
) returnexpr
.t
->set_code_section(p_code_section
);
5129 if (deactivate
) deactivate
->set_code_section(p_code_section
);
5132 port_op
.portref
->set_code_section(p_code_section
);
5133 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5134 if (port_op
.s
.toclause
)
5135 port_op
.s
.toclause
->set_code_section(p_code_section
);
5138 port_op
.portref
->set_code_section(p_code_section
);
5139 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5140 if (port_op
.s
.toclause
)
5141 port_op
.s
.toclause
->set_code_section(p_code_section
);
5142 if (port_op
.s
.call
.timer
)
5143 port_op
.s
.call
.timer
->set_code_section(p_code_section
);
5144 if (port_op
.s
.call
.body
)
5145 port_op
.s
.call
.body
->set_code_section(p_code_section
);
5148 port_op
.portref
->set_code_section(p_code_section
);
5149 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5150 if (port_op
.s
.replyval
)
5151 port_op
.s
.replyval
->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
);
5162 case S_CHECK_RECEIVE
:
5164 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5165 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5166 if (port_op
.r
.fromclause
)
5167 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5168 if (port_op
.r
.redirect
.value
)
5169 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5170 if (port_op
.r
.redirect
.sender
)
5171 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5174 case S_CHECK_GETCALL
:
5175 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5176 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5177 if (port_op
.r
.fromclause
)
5178 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5179 if (port_op
.r
.redirect
.param
)
5180 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5181 if (port_op
.r
.redirect
.sender
)
5182 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5185 case S_CHECK_GETREPLY
:
5186 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5187 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5188 if (port_op
.r
.getreply_valuematch
)
5189 port_op
.r
.getreply_valuematch
->set_code_section(p_code_section
);
5190 if (port_op
.r
.fromclause
)
5191 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5192 if (port_op
.r
.redirect
.value
)
5193 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5194 if (port_op
.r
.redirect
.param
)
5195 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5196 if (port_op
.r
.redirect
.sender
)
5197 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5201 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5202 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5203 if (port_op
.r
.fromclause
)
5204 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5205 if (port_op
.r
.redirect
.value
)
5206 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5207 if (port_op
.r
.redirect
.sender
)
5208 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5211 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5212 if (port_op
.r
.fromclause
)
5213 port_op
.r
.fromclause
->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
);
5221 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5224 comp_op
.compref
->set_code_section(p_code_section
);
5225 comp_op
.funcinstref
->set_code_section(p_code_section
);
5227 case S_START_COMP_REFD
:
5228 comp_op
.compref
->set_code_section(p_code_section
);
5229 comp_op
.derefered
.value
->set_code_section(p_code_section
);
5234 if (comp_op
.compref
) comp_op
.compref
->set_code_section(p_code_section
);
5237 if (comp_op
.compref
) {
5238 comp_op
.compref
->set_code_section(p_code_section
);
5239 if (comp_op
.donereturn
.donematch
)
5240 comp_op
.donereturn
.donematch
->set_code_section(p_code_section
);
5241 if (comp_op
.donereturn
.redirect
)
5242 comp_op
.donereturn
.redirect
->set_code_section(p_code_section
);
5249 config_op
.compref1
->set_code_section(p_code_section
);
5250 config_op
.portref1
->set_code_section(p_code_section
);
5251 config_op
.compref2
->set_code_section(p_code_section
);
5252 config_op
.portref2
->set_code_section(p_code_section
);
5255 timer_op
.timerref
->set_code_section(p_code_section
);
5256 if (timer_op
.value
) timer_op
.value
->set_code_section(p_code_section
);
5260 if (timer_op
.timerref
)
5261 timer_op
.timerref
->set_code_section(p_code_section
);
5264 setverdict
.verdictval
->set_code_section(p_code_section
);
5265 if (setverdict
.logargs
)
5266 setverdict
.logargs
->set_code_section(p_code_section
);
5268 case S_TESTCASE_INSTANCE
:
5269 testcase_inst
.tcref
->set_code_section(p_code_section
);
5270 if (testcase_inst
.timerval
)
5271 testcase_inst
.timerval
->set_code_section(p_code_section
);
5273 case S_TESTCASE_INSTANCE_REFD
:
5274 execute_refd
.value
->set_code_section(p_code_section
);
5275 if(execute_refd
.timerval
)
5276 execute_refd
.timerval
->set_code_section(p_code_section
);
5278 case S_ACTIVATE_REFD
:
5279 case S_FUNCTION_INVOKED
:
5280 case S_ALTSTEP_INVOKED
:
5281 fau_refd
.value
->set_code_section(p_code_section
);
5282 if(fau_refd
.ap_list2
)
5283 for(size_t i
= 0; i
< fau_refd
.ap_list2
->get_nof_pars(); i
++)
5284 fau_refd
.ap_list2
->get_par(i
)->set_code_section(p_code_section
);
5287 str2ttcn
.val
->set_code_section(p_code_section
);
5288 str2ttcn
.ref
->set_code_section(p_code_section
);
5291 FATAL_ERROR("Statement::set_code_section()");
5292 } // switch statementtype
5295 char *Statement::generate_code(char *str
)
5297 switch (statementtype
) {
5304 // conditional and loop statements do not need single location setting
5305 // the embedded expressions, statements have their own locations
5308 str
= update_location_object(str
);
5311 switch(statementtype
) {
5313 str
=def
->generate_code_str(str
);
5316 str
=ass
->generate_code(str
);
5318 case S_FUNCTION_INSTANCE
:
5319 case S_ALTSTEP_INSTANCE
:
5320 str
=generate_code_funcinst(str
);
5322 case S_FUNCTION_INVOKED
:
5323 case S_ALTSTEP_INVOKED
:
5324 str
=generate_code_invoke(str
);
5327 str
=generate_code_block(str
);
5330 str
=generate_code_log(str
);
5333 str
= generate_code_label(str
);
5336 str
= generate_code_goto(str
);
5339 str
=generate_code_if(str
);
5342 str
=generate_code_select(str
);
5345 str
=generate_code_for(str
);
5348 str
=generate_code_while(str
);
5351 str
=generate_code_dowhile(str
);
5354 str
=generate_code_break(str
);
5357 str
=generate_code_continue(str
);
5360 str
=mputstr(str
, "TTCN_Runtime::stop_execution();\n");
5362 case S_STOP_TESTCASE
:
5363 str
=generate_code_testcase_stop(str
);
5366 str
=ags
->generate_code_alt(str
, *this);
5369 str
=generate_code_repeat(str
);
5372 str
=generate_code_interleave(str
);
5375 str
=generate_code_return(str
);
5378 str
=generate_code_activate(str
);
5380 case S_ACTIVATE_REFD
:
5381 str
=generate_code_activate_refd(str
);
5384 str
=generate_code_deactivate(str
);
5387 str
= generate_code_send(str
);
5390 str
= generate_code_call(str
);
5393 str
= generate_code_reply(str
);
5396 str
= generate_code_raise(str
);
5404 case S_CHECK_RECEIVE
:
5405 case S_CHECK_GETCALL
:
5406 case S_CHECK_GETREPLY
:
5411 str
= generate_code_standalone(str
);
5414 str
=generate_code_portop(str
, "clear");
5417 str
=generate_code_portop(str
, "start");
5420 str
=generate_code_portop(str
, "stop");
5423 str
=generate_code_portop(str
, "halt");
5426 str
=generate_code_startcomp(str
);
5428 case S_START_COMP_REFD
:
5429 str
=generate_code_startcomp_refd(str
);
5432 str
= generate_code_compop(str
, "stop");
5435 str
= generate_code_compop(str
, "kill");
5438 str
= generate_code_configop(str
, "connect");
5441 str
= generate_code_configop(str
, "map");
5444 str
= generate_code_configop(str
, "disconnect");
5447 str
= generate_code_configop(str
, "unmap");
5450 str
=generate_code_starttimer(str
);
5453 str
=generate_code_stoptimer(str
);
5456 str
=generate_code_setverdict(str
);
5459 str
=generate_code_action(str
);
5461 case S_TESTCASE_INSTANCE
:
5462 str
=generate_code_testcaseinst(str
);
5464 case S_TESTCASE_INSTANCE_REFD
:
5465 str
=generate_code_execute_refd(str
);
5468 str
=generate_code_string2ttcn(str
);
5471 FATAL_ERROR("Statement::generate_code()");
5476 char* Statement::generate_code_string2ttcn(char *str
)
5478 expression_struct val_expr
;
5479 Code::init_expr(&val_expr
);
5480 str2ttcn
.val
->generate_code_expr(&val_expr
);
5482 expression_struct ref_expr
;
5483 Code::init_expr(&ref_expr
);
5484 str2ttcn
.ref
->generate_code(&ref_expr
);
5486 str
= mputstr(str
, val_expr
.preamble
);
5487 str
= mputstr(str
, ref_expr
.preamble
);
5489 str
= mputprintf(str
, "string_to_ttcn(%s,%s);\n", val_expr
.expr
, ref_expr
.expr
);
5491 str
= mputstr(str
, val_expr
.postamble
);
5492 str
= mputstr(str
, ref_expr
.postamble
);
5494 Code::free_expr(&val_expr
);
5495 Code::free_expr(&ref_expr
);
5500 void Statement::generate_code_expr(expression_struct
*expr
)
5502 switch (statementtype
) {
5504 generate_code_expr_receive(expr
, "receive");
5507 generate_code_expr_receive(expr
, "trigger");
5509 case S_CHECK_RECEIVE
:
5510 generate_code_expr_receive(expr
, "check_receive");
5513 generate_code_expr_getcall(expr
, "getcall");
5515 case S_CHECK_GETCALL
:
5516 generate_code_expr_getcall(expr
, "check_getcall");
5519 generate_code_expr_getreply(expr
, "getreply");
5521 case S_CHECK_GETREPLY
:
5522 generate_code_expr_getreply(expr
, "check_getreply");
5526 generate_code_expr_catch(expr
);
5529 generate_code_expr_check(expr
);
5532 generate_code_expr_done(expr
);
5535 generate_code_expr_killed(expr
);
5538 generate_code_expr_timeout(expr
);
5541 FATAL_ERROR("Statement::generate_code_expr()");
5545 void Statement::ilt_generate_code(ILT
*ilt
)
5547 switch (statementtype
) {
5549 ilt_generate_code_interleave(ilt
);
5552 ilt_generate_code_alt(ilt
);
5555 ilt_generate_code_def(ilt
);
5560 if (is_receiving_stmt()) {
5561 ilt_generate_code_receiving(ilt
);
5564 if (!has_receiving_stmt()) {
5565 char*& str
=ilt
->get_out_branches();
5566 str
=generate_code(str
);
5569 switch (statementtype
) {
5571 block
->ilt_generate_code(ilt
);
5574 ilt_generate_code_if(ilt
);
5577 ilt_generate_code_select(ilt
);
5580 ilt_generate_code_call(ilt
);
5583 ilt_generate_code_for(ilt
);
5586 ilt_generate_code_while(ilt
);
5589 ilt_generate_code_dowhile(ilt
);
5592 FATAL_ERROR("Statement::ilt_generate_code()");
5593 } // switch statementtype
5596 char *Statement::generate_code_standalone(char *str
)
5598 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5599 const char *label_str
= tmplabel
.c_str();
5600 str
= mputprintf(str
, "{\n"
5601 "%s:\n", label_str
);
5602 expression_struct expr
;
5603 Code::init_expr(&expr
);
5604 generate_code_expr(&expr
);
5605 str
= mputstr(str
, expr
.preamble
);
5606 str
= mputprintf(str
, "alt_status alt_flag = ALT_UNCHECKED, "
5607 "default_flag = ALT_UNCHECKED;\n"
5608 "TTCN_Snapshot::take_new(FALSE);\n"
5610 "if (alt_flag != ALT_NO) {\n"
5612 "if (alt_flag == ALT_YES) break;\n", expr
.expr
);
5614 str
= mputprintf(str
, "else if (alt_flag == ALT_REPEAT) goto %s;\n",
5617 str
= mputprintf(str
, "}\n"
5618 "if (default_flag != ALT_NO) {\n"
5619 "default_flag = TTCN_Default::try_altsteps();\n"
5620 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) break;\n"
5621 "else if (default_flag == ALT_REPEAT) goto %s;\n"
5623 str
= update_location_object(str
);
5624 str
= mputprintf(str
, "if (alt_flag == ALT_NO && default_flag == ALT_NO) "
5625 "TTCN_error(\"Stand-alone %s statement failed in file ", get_stmt_name());
5626 str
= Code::translate_string(str
, get_filename());
5627 int first_line
= get_first_line(), last_line
= get_last_line();
5628 if (first_line
< last_line
) str
= mputprintf(str
,
5629 " between lines %d and %d", first_line
, last_line
);
5630 else str
= mputprintf(str
, ", line %d", first_line
);
5631 str
= mputstr(str
, ".\");\n"
5632 "TTCN_Snapshot::take_new(TRUE);\n"
5634 str
= mputstr(str
, expr
.postamble
);
5635 str
= mputstr(str
, "}\n");
5636 Code::free_expr(&expr
);
5640 char *Statement::generate_code_funcinst(char *str
)
5642 expression_struct expr
;
5643 Code::init_expr(&expr
);
5644 ref_pard
->generate_code_const_ref(&expr
);
5645 str
=Code::merge_free_expr(str
, &expr
);
5649 char* Statement::generate_code_invoke(char *str
)
5651 expression_struct expr
;
5652 Code::init_expr(&expr
);
5653 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
5654 switch(last_v
->get_valuetype()) {
5655 case Value::V_FUNCTION
:
5656 case Value::V_ALTSTEP
: {
5657 Common::Assignment
*t_fat
= last_v
->get_refd_fat();
5658 expr
.expr
= mputprintf(expr
.expr
, "%s(",
5659 t_fat
->get_genname_from_scope(my_sb
).c_str());
5660 fau_refd
.ap_list2
->generate_code_alias(&expr
, t_fat
->get_FormalParList(),
5661 t_fat
->get_RunsOnType(), false);
5664 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
5665 Type
*t_governor
= fau_refd
.value
->get_expr_governor_last();
5666 expr
.expr
= mputprintf(expr
.expr
, ".%s(",
5667 t_governor
->get_typetype() == Type::T_ALTSTEP
?
5668 "invoke_standalone" : "invoke");
5669 fau_refd
.ap_list2
->generate_code_alias(&expr
, 0,
5670 t_governor
->get_fat_runs_on_type(),
5671 t_governor
->get_fat_runs_on_self()); }
5673 expr
.expr
= mputc(expr
.expr
, ')');
5674 str
=Code::merge_free_expr(str
, &expr
);
5678 char *Statement::generate_code_block(char *str
)
5680 switch (block
->get_exception_handling()) {
5681 case StatementBlock::EH_NONE
:
5683 case StatementBlock::EH_TRY
:
5684 str
= mputstr(str
, "try ");
5686 case StatementBlock::EH_CATCH
:
5687 str
= mputstr(str
, "catch (const TTCN_Error& ttcn_error) ");
5690 FATAL_ERROR("Statement::generate_code_block()");
5692 if (block
->get_nof_stmts() > 0 || block
->get_exception_handling()!=StatementBlock::EH_NONE
) {
5693 str
= mputstr(str
, "{\n");
5694 str
= block
->generate_code(str
);
5695 str
= mputstr(str
, "}\n");
5696 } else str
= mputstr(str
, "/* empty block */;\n");
5700 char *Statement::generate_code_log(char *str
)
5703 bool buffered_mode
= true;
5704 if (logargs
->get_nof_logargs() == 1) {
5705 LogArgument
*first_logarg
= logargs
->get_logarg_byIndex(0);
5706 switch (first_logarg
->get_type()) {
5707 case LogArgument::L_STR
:
5708 // the argument is a simple string: use non-buffered mode
5709 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, \"");
5710 str
= Code::translate_string(str
, first_logarg
->get_str().c_str());
5711 str
= mputstr(str
, "\");\n");
5712 buffered_mode
= false;
5714 case LogArgument::L_MACRO
: {
5715 Value
*t_val
= first_logarg
->get_val();
5716 if (t_val
->has_single_expr()) {
5717 // the argument is a simple macro call: use non-buffered mode
5718 str
= mputprintf(str
, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5719 t_val
->get_single_expr().c_str());
5720 buffered_mode
= false;
5726 if (buffered_mode
) {
5727 // the argument is a complicated construct: use buffered mode
5728 str
= mputstr(str
, "try {\n"
5729 "TTCN_Logger::begin_event(TTCN_USER);\n");
5730 str
= logargs
->generate_code(str
);
5731 str
= mputstr(str
, "TTCN_Logger::end_event();\n"
5733 "TTCN_Logger::finish_event();\n"
5738 // the argument is missing
5739 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, "
5740 "\"<empty log statement>\");\n");
5745 char *Statement::generate_code_testcase_stop(char *str
)
5747 if (logargs
) str
= generate_code_log(str
);
5748 str
= mputstr(str
, "TTCN_error(\"testcase.stop\");\n");
5752 char *Statement::generate_code_label(char *str
)
5755 return mputprintf(str
, "%s: /* TTCN-3 label: %s */;\n",
5756 get_clabel().c_str(), label
.id
->get_dispname().c_str());
5758 return mputprintf(str
, "/* unused TTCN-3 label: %s */;\n",
5759 label
.id
->get_dispname().c_str());
5763 char *Statement::generate_code_goto(char *str
)
5765 if (!go_to
.label
) FATAL_ERROR("Statement::generate_code_goto()");
5766 return mputprintf(str
, "goto %s; /* TTCN-3 label: %s */\n",
5767 go_to
.label
->get_clabel().c_str(), go_to
.id
->get_dispname().c_str());
5771 char* Statement::generate_code_if(char *str
)
5773 size_t blockcount
=0;
5774 bool unreach
=false, eachfalse
=true;
5775 str
=if_stmt
.ics
->generate_code(str
, blockcount
, unreach
, eachfalse
);
5776 if(if_stmt
.elseblock
&& !unreach
) {
5777 if(!eachfalse
) str
=mputstr(str
, "else ");
5779 str
=mputstr(str
, "{\n");
5781 str
=if_stmt
.elseblock
->generate_code(str
);
5783 while(blockcount
-->0) str
=mputstr(str
, "}\n");
5784 if(eachfalse
) str
=mputstr(str
, "/* never occurs */;\n");
5788 char* Statement::generate_code_select(char *str
)
5790 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5791 char *expr_init
=memptystr();
5792 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
5793 if (expr_init
[0]) { // some init code was generated
5794 str
= update_location_object(str
);
5795 str
= mputstr(str
, "{\n");
5796 str
= mputstr(str
, expr_init
);
5798 str
=select
.scs
->generate_code(str
, tmp_prefix
.c_str(), expr_name
);
5800 if (expr_init
[0]) str
=mputstr(str
, "}\n");
5805 char *Statement::generate_code_for(char *str
)
5807 /** \todo initial does not have its own location */
5808 // statements in initial may have side effects
5809 // generate code for them anyway
5810 if (loop
.for_stmt
.varinst
) {
5811 str
= mputstr(str
, "{\n");
5812 str
= loop
.for_stmt
.init_varinst
->generate_code_str(str
);
5814 str
= loop
.for_stmt
.init_ass
->update_location_object(str
);
5815 str
= loop
.for_stmt
.init_ass
->generate_code(str
);
5817 // check whether the final expression is constant
5818 bool final_is_true
= false, final_is_false
= false;
5819 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
5820 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
5821 else final_is_false
= true;
5823 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
5827 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5828 str
= update_location_object(str
);
5829 str
= mputstr(str
, "for ( ; ; ) {\n");
5830 // do not generate the exit condition for infinite loops
5831 if (!final_is_true
) {
5832 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
5833 size_t blockcount
= 0;
5834 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
5836 str
= mputstr(str
, ") break;\n");
5837 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5839 if (loop
.label_next
) str
= mputstr(str
, "{\n");
5840 str
= loop
.block
->generate_code(str
);
5841 if (loop
.label_next
)
5842 str
= mputprintf(str
, "}\n"
5843 "%s:\n", loop
.label_next
->c_str());
5844 str
= loop
.for_stmt
.step
->update_location_object(str
);
5845 str
= loop
.for_stmt
.step
->generate_code(str
);
5846 str
= mputstr(str
, "}\n");
5848 if (loop
.for_stmt
.varinst
) str
= mputstr(str
, "}\n");
5852 char *Statement::generate_code_while(char *str
)
5854 // check whether the expression is constant
5855 bool condition_always_true
= false, condition_always_false
= false;
5856 if (!loop
.expr
->is_unfoldable()) {
5857 if (loop
.expr
->get_val_bool()) condition_always_true
= true;
5858 else condition_always_false
= true;
5860 if (condition_always_false
) str
= mputstr(str
, "/* never occurs */;\n");
5862 str
= mputstr(str
, "for ( ; ; ) {\n");
5863 if (loop
.has_cnt_in_ags
) {
5865 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5866 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5868 // do not generate the exit condition for infinite loops
5869 if (!condition_always_true
) {
5870 str
= loop
.expr
->update_location_object(str
);
5871 size_t blockcount
= 0;
5872 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5873 str
= mputstr(str
, ") break;\n");
5874 while(blockcount
-- > 0) str
= mputstr(str
, "}\n");
5876 str
= loop
.block
->generate_code(str
);
5877 str
= mputstr(str
, "}\n");
5882 char *Statement::generate_code_dowhile(char *str
)
5884 // check whether the expression is constant
5885 bool expr_is_const
= !loop
.expr
->is_unfoldable();
5886 bool is_infinite_loop
= false;
5887 if (expr_is_const
) {
5888 if (loop
.expr
->get_val_bool()) is_infinite_loop
= true;
5889 else loop
.iterate_once
= true;
5891 if (loop
.iterate_once
&& !loop
.has_brk
&& !loop
.has_cnt
) {
5892 str
= mputstr(str
, "{\n");
5893 str
= loop
.block
->generate_code(str
);
5895 str
= mputstr(str
, "for ( ; ; ) {\n");
5896 if (loop
.has_cnt_in_ags
|| (!expr_is_const
&& loop
.has_cnt
))
5898 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5899 if (loop
.label_next
&& is_infinite_loop
)
5900 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
5901 if (loop
.label_next
&& !is_infinite_loop
) str
= mputstr(str
, "{\n");
5902 str
= loop
.block
->generate_code(str
);
5903 // do not generate the exit condition for infinite loops
5904 if (!is_infinite_loop
) {
5905 if (loop
.label_next
)
5906 str
= mputprintf(str
, "}\n"
5907 "%s:\n", loop
.label_next
->c_str());
5908 str
= loop
.expr
->update_location_object(str
);
5909 if (loop
.iterate_once
) str
= mputstr(str
, "break;\n");
5911 size_t blockcount
= 0;
5912 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
5913 str
= mputstr(str
, ") break;\n");
5914 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5918 str
= mputstr(str
, "}\n");
5922 char *Statement::generate_code_break(char *str
)
5924 // in altstep (2 (=2nd if branch))
5925 // in alt and loops - not inside interleave (4)
5926 // in loops without receiving statement embedded in interleave (4)
5927 // in loops with receiving statement embedded in interleave (1)
5928 // in interleave when not embedded in enclosed loop or alt/interleave (4)
5929 // in alt/interleave embedded in interleave (3)
5930 if (brk_cnt
.loop_stmt
&& brk_cnt
.loop_stmt
->loop
.il_label_end
)
5931 str
=mputprintf(str
, "goto %s;\n",
5932 brk_cnt
.loop_stmt
->loop
.il_label_end
->c_str());
5933 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_is_altstep())
5934 str
=mputstr(str
, "return ALT_BREAK;\n");
5935 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_il_label_end())
5936 str
=mputprintf(str
, "goto %s;\n",
5937 brk_cnt
.ags
->get_il_label_end()->c_str());
5939 str
=mputstr(str
, "break;\n");
5943 char *Statement::generate_code_continue(char *str
)
5945 // not inside interleave when continue is not inside embedded ags (2 or 1)
5946 // continue is inside ags enclosed in the loop (3)
5947 // in interleave (3, 2 or 1)
5948 if (brk_cnt
.loop_stmt
!= 0) {
5949 if (brk_cnt
.loop_stmt
->loop
.iterate_once
&& !brk_cnt
.ags
&&
5950 !brk_cnt
.loop_stmt
->loop
.is_ilt
)
5951 str
=mputstr(str
, "break;\n");
5953 if (!brk_cnt
.loop_stmt
->loop
.label_next
)
5954 str
=mputstr(str
, "continue;\n");
5956 str
=mputprintf(str
, "goto %s;\n",
5957 brk_cnt
.loop_stmt
->loop
.label_next
->c_str());
5960 FATAL_ERROR("Statement::generate_code_continue()");
5964 char *Statement::generate_code_repeat(char *str
)
5966 string
*tmplabel
=ags
->get_label();
5967 if(!tmplabel
) str
=mputstr(str
, "return ALT_REPEAT;\n");
5968 else str
=mputprintf(str
, "goto %s;\n", tmplabel
->c_str());
5972 char* Statement::generate_code_interleave(char *str
)
5975 str
=ilt
.generate_code(str
);
5979 void Statement::ilt_generate_code_interleave(ILT
*ilt
)
5981 const string
& mytmpid
=ilt
->get_my_tmpid();
5982 bool toplevel
=ilt
->is_toplevel();
5983 size_t goto_label_num
=toplevel
?(size_t)-1:ilt
->get_new_label_num();
5984 char*& out_branches
=ilt
->get_out_branches();
5985 out_branches
=update_location_object(out_branches
);
5987 if(toplevel
) state_cond
="";
5989 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
5990 (unsigned long) goto_label_num
);
5991 ags
->set_il_label_end (label_end
);
5993 ILT_branch
*branch
=ilt
->get_as_branch();
5994 size_t state_var
=branch
->get_my_state_var();
5995 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
5996 state_cond
=branch
->get_state_cond();
5997 if(!state_cond
.empty()) state_cond
+=" && ";
5998 char *s
=mprintf("%s_state[%lu]==%lu", mytmpid
.c_str(),
5999 (unsigned long) state_var
, (unsigned long) state_var_val
);
6002 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6004 (unsigned long) state_var
, (unsigned long) state_var_val
);
6006 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6007 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6008 if(ag
->get_type()!=AltGuard::AG_OP
)
6009 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6010 size_t state_var
=ilt
->get_new_state_var(toplevel
);
6011 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6012 ilt
->add_branch(new ILT_branch(ILT_branch::BT_IL
, ag
, state_cond
,
6013 state_var
, state_var_val
,
6016 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6018 (unsigned long) state_var
, (unsigned long) state_var_val
);
6021 out_branches
=mputprintf(out_branches
, "goto %s;\n"
6024 mytmpid
.c_str(), (unsigned long) goto_label_num
);
6027 void Statement::ilt_generate_code_alt(ILT
*ilt
)
6029 const string
& mytmpid
=ilt
->get_my_tmpid();
6030 size_t goto_label_num
=ilt
->get_new_label_num();
6031 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6032 (unsigned long) goto_label_num
);
6033 ags
->set_il_label_end (label_end
);
6034 ILT_branch
*branch
=ilt
->get_as_branch();
6035 string state_cond
=branch
->get_state_cond();
6036 size_t state_var
=branch
->get_my_state_var();
6037 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6038 char*& out_branches
=ilt
->get_out_branches();
6039 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6040 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6041 if(ag
->get_type()!=AltGuard::AG_OP
)
6042 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6043 ilt
->add_branch(new ILT_branch(ILT_branch::BT_ALT
, ag
, state_cond
,
6044 state_var
, state_var_val
,
6047 out_branches
=update_location_object(out_branches
);
6048 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6051 mytmpid
.c_str(), (unsigned long) state_var
,
6052 (unsigned long) state_var_val
,
6053 mytmpid
.c_str(), label_end
);
6057 void Statement::ilt_generate_code_receiving(ILT
*ilt
)
6059 const string
& mytmpid
=ilt
->get_my_tmpid();
6060 size_t goto_label_num
=ilt
->get_new_label_num();
6061 ILT_branch
*branch
=ilt
->get_as_branch();
6062 string state_cond
=branch
->get_state_cond();
6063 size_t state_var
=branch
->get_my_state_var();
6064 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6065 char*& out_branches
=ilt
->get_out_branches();
6066 ilt
->add_branch(new ILT_branch(ILT_branch::BT_RECV
, this, state_cond
,
6067 state_var
, state_var_val
, goto_label_num
));
6068 out_branches
=update_location_object(out_branches
);
6069 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6072 mytmpid
.c_str(), (unsigned long) state_var
,
6073 (unsigned long) state_var_val
,
6074 mytmpid
.c_str(), mytmpid
.c_str(),
6075 (unsigned long) goto_label_num
);
6078 void Statement::ilt_generate_code_def(ILT
*ilt
)
6080 char*& str
=ilt
->get_out_branches();
6081 str
=update_location_object(str
);
6083 char *genname
=mprintf("%s_d%lu_%s", ilt
->get_my_tmpid().c_str(),
6084 (unsigned long) ilt
->get_new_tmpnum(),
6085 def
->get_id().get_name().c_str());
6086 def
->set_genname(string(genname
));
6089 def
->ilt_generate_code(ilt
);
6092 void Statement::ilt_generate_code_if(ILT
*ilt
)
6094 char *end_label
=mprintf("%s_l%lu",
6095 ilt
->get_my_tmpid().c_str(),
6096 (unsigned long) ilt
->get_new_label_num());
6098 if_stmt
.ics
->ilt_generate_code(ilt
, end_label
, unreach
);
6099 if(if_stmt
.elseblock
&& !unreach
)
6100 if_stmt
.elseblock
->ilt_generate_code(ilt
);
6101 char*& str
=ilt
->get_out_branches();
6102 str
=mputprintf(str
, "%s:\n", end_label
);
6106 void Statement::ilt_generate_code_select(ILT
*ilt
)
6108 char*& str
=ilt
->get_out_branches();
6109 str
=update_location_object(str
);
6110 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6111 char *expr_init
=memptystr();
6112 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
6113 select
.scs
->ilt_generate_code(ilt
, tmp_prefix
.c_str(),
6114 expr_init
, expr_name
);
6119 void Statement::ilt_generate_code_call(ILT
*ilt
)
6121 char*& str
=ilt
->get_out_branches();
6122 str
=update_location_object(str
);
6123 expression_struct expr
;
6124 Code::init_expr(&expr
);
6125 port_op
.portref
->generate_code(&expr
);
6126 expr
.expr
= mputstr(expr
.expr
, ".call(");
6127 port_op
.s
.sendpar
->generate_code(&expr
);
6128 if(port_op
.s
.toclause
) {
6129 expr
.expr
= mputstr(expr
.expr
, ", ");
6130 port_op
.s
.toclause
->generate_code_expr(&expr
);
6132 expr
.expr
= mputc(expr
.expr
, ')');
6133 str
= Code::merge_free_expr(str
, &expr
);
6134 if (port_op
.s
.call
.body
) {
6135 str
= mputstr(str
, "{\n"); // (1)
6136 if (port_op
.s
.call
.timer
) {
6137 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6138 str
= mputstr(str
, "TIMER call_timer;\n");
6139 Code::init_expr(&expr
);
6140 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6141 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6142 expr
.expr
= mputc(expr
.expr
, ')');
6143 str
= Code::merge_free_expr(str
, &expr
);
6145 // the label name is used for prefixing local variables
6146 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6147 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6148 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this, tmplabel
,
6150 const char *label_str
= tmplabel
.c_str();
6151 str
=mputprintf(str
, "goto %s_end;\n"
6154 port_op
.s
.call
.body
->ilt_generate_code_call_body(ilt
, label_str
);
6155 str
=mputprintf(str
, "%s_end:\n", label_str
);
6159 void Statement::ilt_generate_code_for(ILT
*ilt
)
6161 char*& str
= ilt
->get_out_branches();
6162 str
= update_location_object(str
);
6163 // statements in initial may have side effects
6164 // generate code for them anyway
6165 if (loop
.for_stmt
.varinst
) {
6166 char *genname
= mprintf("%s_d%lu_", ilt
->get_my_tmpid().c_str(),
6167 (unsigned long) ilt
->get_new_tmpnum());
6168 loop
.for_stmt
.init_varinst
->set_genname(string(genname
));
6170 loop
.for_stmt
.init_varinst
->ilt_generate_code(ilt
);
6171 } else str
= loop
.for_stmt
.init_ass
->generate_code(str
);
6172 // check whether the final expression is constant
6173 bool final_is_true
= false, final_is_false
= false;
6174 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
6175 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
6176 else final_is_false
= true;
6178 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6180 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6181 (unsigned long) ilt
->get_new_label_num());
6182 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6183 // do not generate the exit condition for infinite loops
6184 if (!final_is_true
) {
6185 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
6186 size_t blockcount
= 0;
6187 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
6189 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6190 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6194 loop
.il_label_end
= new string(label_prefix
);
6195 *loop
.il_label_end
+= "end";
6198 loop
.label_next
= new string(label_prefix
);
6199 *loop
.label_next
+= "next";
6201 loop
.block
->ilt_generate_code(ilt
);
6202 if (loop
.label_next
)
6203 str
= mputprintf(str
, "%snext:\n", label_prefix
);
6204 str
= update_location_object(str
);
6205 str
= loop
.for_stmt
.step
->generate_code(str
);
6206 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6207 if (!final_is_true
|| loop
.has_brk
)
6208 str
= mputprintf(str
, "%send:\n", label_prefix
);
6213 void Statement::ilt_generate_code_while(ILT
*ilt
)
6215 char*& str
= ilt
->get_out_branches();
6216 // Location need not be set here; the location is set for the expression.
6217 // check whether the expression is constant
6218 bool expr_is_true
= false, expr_is_false
= false;
6219 if (!loop
.expr
->is_unfoldable()) {
6220 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6221 else expr_is_false
= true;
6223 if (expr_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6225 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6226 (unsigned long) ilt
->get_new_label_num());
6227 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6230 loop
.il_label_end
= new string(label_prefix
);
6231 *loop
.il_label_end
+= "end";
6234 loop
.label_next
= new string(label_prefix
);
6235 *loop
.label_next
+= "begin";
6237 // do not generate the exit condition for infinite loops
6238 if (!expr_is_true
) {
6239 str
= loop
.expr
->update_location_object(str
);
6240 size_t blockcount
= 0;
6241 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6242 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6243 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6245 loop
.block
->ilt_generate_code(ilt
);
6246 str
= update_location_object(str
);
6247 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6248 if (!expr_is_true
|| loop
.has_brk
)
6249 str
= mputprintf(str
, "%send:\n", label_prefix
);
6254 void Statement::ilt_generate_code_dowhile(ILT
*ilt
)
6256 char*& str
= ilt
->get_out_branches();
6257 // Location need not be set here; there is only a label before the body.
6258 // check whether the expression is constant
6259 bool expr_is_true
= false;
6260 if (!loop
.expr
->is_unfoldable()) {
6261 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6262 else loop
.iterate_once
= true;
6264 char *label_prefix
= 0;
6265 if (!loop
.iterate_once
|| loop
.has_brk
|| loop
.has_cnt
)
6266 label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6267 (unsigned long) ilt
->get_new_label_num());
6270 loop
.il_label_end
= new string(label_prefix
);
6271 *loop
.il_label_end
+= "end";
6274 loop
.label_next
= new string(label_prefix
);
6275 if (loop
.iterate_once
) {
6276 if (loop
.label_next
) *loop
.label_next
+= "end";
6277 loop
.block
->ilt_generate_code(ilt
);
6279 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6280 if (loop
.label_next
)
6281 *loop
.label_next
+= (expr_is_true
? "begin" : "next");
6282 loop
.block
->ilt_generate_code(ilt
);
6283 if (expr_is_true
) str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6285 if (loop
.label_next
) str
= mputprintf(str
, "%snext:\n", label_prefix
);
6286 str
= loop
.expr
->update_location_object(str
);
6287 size_t blockcount
= 0;
6288 str
= loop
.expr
->generate_code_tmp(str
, "if (", blockcount
);
6289 str
= mputprintf(str
, ") goto %sbegin;\n", label_prefix
);
6290 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6293 if (loop
.il_label_end
|| (loop
.iterate_once
&& loop
.label_next
)) {
6294 str
= mputprintf(str
, "%send: ;\n", label_prefix
);
6299 char *Statement::generate_code_return(char *str
)
6301 expression_struct expr
;
6302 Code::init_expr(&expr
);
6303 expr
.expr
= mputstr(expr
.expr
, "return");
6304 Definition
*my_def
= my_sb
->get_my_def();
6306 expr
.expr
= mputc(expr
.expr
, ' ');
6307 returnexpr
.v
->generate_code_expr_mandatory(&expr
);
6308 } else if (returnexpr
.t
) {
6309 expr
.expr
= mputc(expr
.expr
, ' ');
6310 if (!my_def
) FATAL_ERROR("Statement::generate_code_return()");
6311 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
6312 if (!dfb
) FATAL_ERROR("Statement::generate_code_return()");
6313 if (dfb
->get_template_restriction() != TR_NONE
&&
6314 returnexpr
.gen_restriction_check
) {
6315 returnexpr
.t
->generate_code_expr(&expr
,
6316 dfb
->get_template_restriction());
6318 returnexpr
.t
->generate_code_expr(&expr
, TR_NONE
);
6321 if (my_def
&& my_def
->get_asstype() == Definition::A_ALTSTEP
)
6322 expr
.expr
= mputstr(expr
.expr
, " ALT_YES");
6323 // else it's a return with no value: the only case a blank is unneeded
6325 return Code::merge_free_expr(str
, &expr
);
6328 char *Statement::generate_code_activate(char *str
)
6330 expression_struct expr
;
6331 Code::init_expr(&expr
);
6332 expr
.expr
= mputprintf(expr
.expr
, "%s(", ref_pard
->get_refd_assignment()
6333 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6334 ref_pard
->get_parlist()->generate_code_noalias(&expr
, ref_pard
->get_refd_assignment()->get_FormalParList());
6335 expr
.expr
= mputc(expr
.expr
, ')');
6336 return Code::merge_free_expr(str
, &expr
);
6339 char *Statement::generate_code_activate_refd(char *str
)
6341 expression_struct expr
;
6342 Code::init_expr(&expr
);
6343 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6344 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
6345 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6346 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6348 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
6349 expr
.expr
= mputstr(expr
.expr
, ".activate(");
6351 fau_refd
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6352 expr
.expr
= mputc(expr
.expr
, ')');
6353 return Code::merge_free_expr(str
, &expr
);
6356 char *Statement::generate_code_deactivate(char *str
)
6358 if(!deactivate
) str
=mputstr(str
, "TTCN_Default::deactivate_all();\n");
6360 expression_struct expr
;
6361 Code::init_expr(&expr
);
6362 expr
.expr
=mputstr(expr
.expr
, "TTCN_Default::deactivate(");
6363 deactivate
->generate_code_expr(&expr
);
6364 expr
.expr
=mputstr(expr
.expr
, ");\n");
6365 str
=Code::merge_free_expr(str
, &expr
);
6370 char *Statement::generate_code_send(char *str
)
6372 expression_struct expr
;
6373 Code::init_expr(&expr
);
6374 port_op
.portref
->generate_code(&expr
);
6375 expr
.expr
= mputstr(expr
.expr
, ".send(");
6376 generate_code_expr_sendpar(&expr
);
6377 if (port_op
.s
.toclause
) {
6378 expr
.expr
= mputstr(expr
.expr
, ", ");
6379 port_op
.s
.toclause
->generate_code_expr(&expr
);
6381 expr
.expr
= mputc(expr
.expr
, ')');
6382 return Code::merge_free_expr(str
, &expr
);
6385 char *Statement::generate_code_call(char *str
)
6387 expression_struct expr
;
6388 Code::init_expr(&expr
);
6389 port_op
.portref
->generate_code(&expr
);
6390 expr
.expr
= mputstr(expr
.expr
, ".call(");
6391 port_op
.s
.sendpar
->generate_code(&expr
);
6392 if(port_op
.s
.toclause
) {
6393 expr
.expr
= mputstr(expr
.expr
, ", ");
6394 port_op
.s
.toclause
->generate_code_expr(&expr
);
6396 expr
.expr
= mputc(expr
.expr
, ')');
6397 str
= Code::merge_free_expr(str
, &expr
);
6398 if (port_op
.s
.call
.body
) {
6399 str
= mputstr(str
, "{\n");
6400 if (port_op
.s
.call
.timer
) {
6401 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6402 str
= mputstr(str
, "TIMER call_timer;\n");
6403 Code::init_expr(&expr
);
6404 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6405 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6406 expr
.expr
= mputc(expr
.expr
, ')');
6407 str
= Code::merge_free_expr(str
, &expr
);
6409 // the label name is used for prefixing local variables
6410 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6411 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this,
6412 my_sb
->get_scope_mod_gen()->get_temporary_id(), false);
6413 str
=mputstr(str
, "}\n");
6418 char *Statement::generate_code_reply(char *str
)
6420 expression_struct expr
;
6421 Code::init_expr(&expr
);
6422 port_op
.portref
->generate_code(&expr
);
6423 expr
.expr
=mputstr(expr
.expr
, ".reply(");
6424 port_op
.s
.sendpar
->generate_code(&expr
);
6425 if(port_op
.s
.replyval
) {
6426 expr
.expr
=mputstr(expr
.expr
, ".set_value_template(");
6427 port_op
.s
.replyval
->generate_code_expr(&expr
);
6428 expr
.expr
=mputc(expr
.expr
, ')');
6430 if(port_op
.s
.toclause
) {
6431 expr
.expr
=mputstr(expr
.expr
, ", ");
6432 port_op
.s
.toclause
->generate_code_expr(&expr
);
6434 expr
.expr
=mputc(expr
.expr
, ')');
6435 return Code::merge_free_expr(str
, &expr
);
6438 char *Statement::generate_code_raise(char *str
)
6440 expression_struct expr
;
6441 Code::init_expr(&expr
);
6442 port_op
.portref
->generate_code(&expr
);
6443 expr
.expr
=mputstr(expr
.expr
, ".raise(");
6444 port_op
.s
.raise
.signature_ref
->generate_code(&expr
);
6445 expr
.expr
=mputstr(expr
.expr
, "_exception(");
6446 generate_code_expr_sendpar(&expr
);
6447 expr
.expr
=mputc(expr
.expr
, ')');
6448 if(port_op
.s
.toclause
) {
6449 expr
.expr
=mputstr(expr
.expr
, ", ");
6450 port_op
.s
.toclause
->generate_code_expr(&expr
);
6452 expr
.expr
=mputc(expr
.expr
, ')');
6453 return Code::merge_free_expr(str
, &expr
);
6456 char *Statement::generate_code_portop(char *str
, const char *opname
)
6458 if (port_op
.portref
) {
6459 expression_struct expr
;
6460 Code::init_expr(&expr
);
6461 port_op
.portref
->generate_code(&expr
);
6462 expr
.expr
=mputprintf(expr
.expr
, ".%s()", opname
);
6463 str
=Code::merge_free_expr(str
, &expr
);
6465 str
= mputprintf(str
, "PORT::all_%s();\n", opname
);
6470 char *Statement::generate_code_startcomp(char *str
)
6472 expression_struct expr
;
6473 Code::init_expr(&expr
);
6474 Common::Assignment
*func
= comp_op
.funcinstref
->get_refd_assignment();
6475 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6476 func
->get_genname_from_scope(my_sb
, "start_").c_str());
6477 comp_op
.compref
->generate_code_expr(&expr
);
6478 FormalParList
*fplist
= func
->get_FormalParList();
6479 if (fplist
->get_nof_fps() > 0) {
6480 expr
.expr
= mputstr(expr
.expr
, ", ");
6481 comp_op
.funcinstref
->get_parlist()->generate_code_noalias(&expr
, fplist
);
6483 expr
.expr
= mputc(expr
.expr
, ')');
6484 return Code::merge_free_expr(str
, &expr
);
6487 char *Statement::generate_code_startcomp_refd(char *str
)
6489 expression_struct expr
;
6490 Code::init_expr(&expr
);
6491 Value
*last_v
= comp_op
.derefered
.value
->get_value_refd_last();
6492 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
6493 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6494 ->get_genname_from_scope(my_sb
, "start_").c_str());
6496 comp_op
.derefered
.value
->generate_code_expr_mandatory(&expr
);
6497 expr
.expr
= mputstr(expr
.expr
, ".start(");
6499 comp_op
.compref
->generate_code_expr(&expr
);
6500 if (comp_op
.derefered
.ap_list2
->get_nof_pars() > 0) {
6501 expr
.expr
= mputstr(expr
.expr
, ", ");
6502 comp_op
.derefered
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6504 expr
.expr
= mputc(expr
.expr
, ')');
6505 return Code::merge_free_expr(str
, &expr
);
6508 char *Statement::generate_code_compop(char *str
, const char *opname
)
6510 expression_struct expr
;
6511 Code::init_expr(&expr
);
6512 if (comp_op
.compref
) {
6513 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
6514 if (v_last
->get_valuetype() == Value::V_REFD
) {
6515 // the argument is a simple component reference
6516 v_last
->generate_code_expr_mandatory(&expr
);
6517 expr
.expr
= mputprintf(expr
.expr
, ".%s()", opname
);
6519 bool refers_to_self
= false;
6520 if (v_last
->get_valuetype() == Value::V_EXPR
) {
6521 // the argument is a special component reference (mtc, self, etc.)
6522 switch (v_last
->get_optype()) {
6523 case Value::OPTYPE_COMP_MTC
: {
6524 Definition
*my_def
= my_sb
->get_my_def();
6525 if (my_def
&& my_def
->get_asstype() == Definition::A_TESTCASE
)
6526 refers_to_self
= true;
6528 case Value::OPTYPE_COMP_SELF
:
6529 refers_to_self
= true;
6534 if (refers_to_self
) {
6535 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_execution()",
6538 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_component(",
6540 v_last
->generate_code_expr(&expr
);
6541 expr
.expr
= mputc(expr
.expr
, ')');
6545 // the operation refers to all component
6546 expr
.expr
= mputprintf(expr
.expr
,
6547 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname
);
6549 return Code::merge_free_expr(str
, &expr
);
6552 char *Statement::generate_code_configop(char *str
, const char *opname
)
6554 expression_struct expr
;
6555 Code::init_expr(&expr
);
6556 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_port(", opname
);
6557 config_op
.compref1
->generate_code_expr(&expr
);
6558 expr
.expr
= mputstr(expr
.expr
, ", ");
6559 if (config_op
.compref1
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6560 // the component type is known
6561 // the name of the referred port can be used
6562 config_op
.portref1
->generate_code_portref(&expr
, my_sb
);
6563 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6565 // the component type is unknown
6566 // a simple string shall be formed from the port name and array indices
6567 generate_code_portref(&expr
, config_op
.portref1
);
6569 expr
.expr
= mputstr(expr
.expr
, ", ");
6570 config_op
.compref2
->generate_code_expr(&expr
);
6571 expr
.expr
= mputstr(expr
.expr
, ", ");
6572 if (config_op
.compref2
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6573 // the component type is known
6574 // the name of the referred port can be used
6575 config_op
.portref2
->generate_code_portref(&expr
, my_sb
);
6576 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6578 // the component type is unknown
6579 // a simple string shall be formed from the port name and array indices
6580 generate_code_portref(&expr
, config_op
.portref2
);
6582 expr
.expr
= mputc(expr
.expr
, ')');
6583 return Code::merge_free_expr(str
, &expr
);
6586 char *Statement::generate_code_starttimer(char *str
)
6588 expression_struct expr
;
6589 Code::init_expr(&expr
);
6590 timer_op
.timerref
->generate_code(&expr
);
6591 expr
.expr
=mputstr(expr
.expr
, ".start(");
6592 if(timer_op
.value
) timer_op
.value
->generate_code_expr(&expr
);
6593 expr
.expr
=mputc(expr
.expr
, ')');
6594 str
=Code::merge_free_expr(str
, &expr
);
6598 char *Statement::generate_code_stoptimer(char *str
)
6600 if(!timer_op
.timerref
) str
=mputstr(str
, "TIMER::all_stop();\n");
6602 expression_struct expr
;
6603 Code::init_expr(&expr
);
6604 timer_op
.timerref
->generate_code(&expr
);
6605 expr
.expr
=mputstr(expr
.expr
, ".stop()");
6606 str
=Code::merge_free_expr(str
, &expr
);
6611 char *Statement::generate_code_setverdict(char *str
)
6613 expression_struct expr
;
6614 Code::init_expr(&expr
);
6615 expr
.expr
=mputstr(expr
.expr
, "TTCN_Runtime::setverdict(");
6616 setverdict
.verdictval
->generate_code_expr(&expr
);
6617 if (setverdict
.logargs
) {
6618 expr
.expr
=mputc(expr
.expr
, ',');
6619 expression_struct expr_reason
;
6620 Code::init_expr(&expr_reason
);
6621 setverdict
.logargs
->generate_code_expr(&expr_reason
);
6622 if (expr_reason
.preamble
)
6623 expr
.preamble
= mputprintf(expr
.preamble
, "%s;\n",
6624 expr_reason
.preamble
);
6625 if (expr_reason
.postamble
)
6626 expr
.postamble
= mputprintf(expr
.postamble
, "%s;\n",
6627 expr_reason
.postamble
);
6628 expr
.expr
= mputprintf(expr
.expr
, "%s", expr_reason
.expr
);
6629 Code::free_expr(&expr_reason
);
6631 expr
.expr
=mputc(expr
.expr
, ')');
6632 str
=Code::merge_free_expr(str
, &expr
);
6636 char *Statement::generate_code_action(char *str
)
6638 str
=mputstr(str
, "TTCN_Runtime::begin_action();\n");
6639 if(!logargs
) str
=mputstr(str
, "TTCN_Logger::log_event_str"
6640 "(\"<empty action statement>\");\n");
6641 else str
=logargs
->generate_code(str
);
6642 str
=mputstr(str
, "TTCN_Runtime::end_action();\n");
6646 char *Statement::generate_code_testcaseinst(char *str
)
6648 expression_struct expr
;
6649 Code::init_expr(&expr
);
6650 Common::Assignment
*testcase
= testcase_inst
.tcref
->get_refd_assignment();
6651 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6652 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6653 ActualParList
*t_aplist
= testcase_inst
.tcref
->get_parlist();
6654 if (t_aplist
->get_nof_pars() > 0) {
6655 t_aplist
->generate_code_alias(&expr
, testcase
->get_FormalParList(),
6657 expr
.expr
= mputstr(expr
.expr
, ", ");
6659 if (testcase_inst
.timerval
) {
6660 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6661 testcase_inst
.timerval
->generate_code_expr(&expr
);
6662 expr
.expr
= mputc(expr
.expr
, ')');
6663 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6664 return Code::merge_free_expr(str
, &expr
);
6667 char *Statement::generate_code_execute_refd(char *str
)
6669 expression_struct expr
;
6670 Code::init_expr(&expr
);
6671 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6672 if (last_v
->get_valuetype() == Value::V_TESTCASE
) {
6673 Common::Assignment
*testcase
= last_v
->get_refd_fat();
6674 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6675 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6676 execute_refd
.ap_list2
->generate_code_alias(&expr
,
6677 testcase
->get_FormalParList(), 0, false);
6679 execute_refd
.value
->generate_code_expr_mandatory(&expr
);
6680 expr
.expr
= mputstr(expr
.expr
, ".execute(");
6681 execute_refd
.ap_list2
->generate_code_alias(&expr
, 0, 0, false);
6683 if (execute_refd
.ap_list2
->get_nof_pars() > 0)
6684 expr
.expr
= mputstr(expr
.expr
, ", ");
6685 if (execute_refd
.timerval
) {
6686 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6687 execute_refd
.timerval
->generate_code_expr(&expr
);
6688 expr
.expr
= mputc(expr
.expr
, ')');
6689 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6690 return Code::merge_free_expr(str
,&expr
);
6693 void Statement::generate_code_expr_receive(expression_struct
*expr
,
6696 if (port_op
.portref
) {
6697 // The operation refers to a specific port.
6698 port_op
.portref
->generate_code(expr
);
6699 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6700 if (port_op
.r
.rcvpar
) {
6701 // The receive parameter is present.
6702 if (use_runtime_2
&& TypeConv::needs_conv_redir(port_op
.r
.rcvpar
,
6703 port_op
.r
.redirect
.value
)) {
6704 // Don't change the first parameter. Otherwise it won't receive
6705 // anything. The only thing we need is a temporary to save the
6706 // result and a conversion at the end.
6707 TypeConv::gen_conv_code_redir(expr
, port_op
.r
.rcvpar
,
6708 port_op
.r
.redirect
.value
);
6710 port_op
.r
.rcvpar
->generate_code(expr
);
6711 expr
->expr
= mputstr(expr
->expr
, ", ");
6712 if (port_op
.r
.redirect
.value
) {
6713 // Value redirect is also present.
6714 expr
->expr
= mputstr(expr
->expr
, "&(");
6715 port_op
.r
.redirect
.value
->generate_code(expr
);
6716 expr
->expr
= mputc(expr
->expr
, ')');
6717 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6719 expr
->expr
= mputstr(expr
->expr
, ", ");
6722 // the operation refers to any port
6723 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6725 generate_code_expr_fromclause(expr
);
6726 expr
->expr
= mputstr(expr
->expr
, ", ");
6727 generate_code_expr_senderredirect(expr
);
6728 expr
->expr
= mputc(expr
->expr
, ')');
6731 void Statement::generate_code_expr_getcall(expression_struct
*expr
,
6734 if (port_op
.portref
) {
6735 // the operation refers to a specific port
6736 port_op
.portref
->generate_code(expr
);
6737 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6738 if (port_op
.r
.rcvpar
) {
6739 // the signature template is present
6740 port_op
.r
.rcvpar
->generate_code(expr
);
6741 expr
->expr
= mputstr(expr
->expr
, ", ");
6742 generate_code_expr_fromclause(expr
);
6743 // a temporary object is needed for parameter redirect
6744 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6745 expr
->expr
= mputprintf(expr
->expr
, ", %s_call_redirect(",
6746 signature
->get_genname_value(my_sb
).c_str());
6747 if (port_op
.r
.redirect
.param
)
6748 port_op
.r
.redirect
.param
->generate_code(expr
);
6749 expr
->expr
= mputstr(expr
->expr
, "), ");
6750 generate_code_expr_senderredirect(expr
);
6752 // the signature parameter is not present
6753 generate_code_expr_fromclause(expr
);
6754 expr
->expr
= mputstr(expr
->expr
, ", ");
6755 generate_code_expr_senderredirect(expr
);
6758 // the operation refers to any port
6759 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6760 generate_code_expr_fromclause(expr
);
6761 expr
->expr
= mputstr(expr
->expr
, ", ");
6762 generate_code_expr_senderredirect(expr
);
6764 expr
->expr
=mputc(expr
->expr
, ')');
6767 void Statement::generate_code_expr_getreply(expression_struct
*expr
,
6770 if (port_op
.portref
) {
6771 // the operation refers to a specific port
6772 port_op
.portref
->generate_code(expr
);
6773 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6774 if (port_op
.r
.rcvpar
) {
6775 // the signature template is present
6776 port_op
.r
.rcvpar
->generate_code(expr
);
6777 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6779 signature
->get_type_refd_last()->get_signature_return_type();
6781 expr
->expr
= mputstr(expr
->expr
, ".set_value_template(");
6782 if (port_op
.r
.getreply_valuematch
) {
6783 // the value match is also present
6784 port_op
.r
.getreply_valuematch
->generate_code(expr
);
6786 // the value match is not present
6787 // we must substitute it with ? in the signature template
6788 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6789 return_type
->get_genname_template(my_sb
).c_str());
6791 expr
->expr
= mputc(expr
->expr
, ')');
6793 expr
->expr
= mputstr(expr
->expr
, ", ");
6794 generate_code_expr_fromclause(expr
);
6795 // a temporary object is needed for value and parameter redirect
6796 expr
->expr
= mputprintf(expr
->expr
, ", %s_reply_redirect(",
6797 signature
->get_genname_value(my_sb
).c_str());
6799 // the first argument of the constructor must contain
6800 // the value redirect
6801 if (port_op
.r
.redirect
.value
) {
6802 expr
->expr
= mputstr(expr
->expr
, "&(");
6803 port_op
.r
.redirect
.value
->generate_code(expr
);
6804 expr
->expr
= mputc(expr
->expr
, ')');
6805 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6806 if (port_op
.r
.redirect
.param
) expr
->expr
= mputstr(expr
->expr
, ", ");
6808 if (port_op
.r
.redirect
.param
)
6809 port_op
.r
.redirect
.param
->generate_code(expr
);
6810 expr
->expr
= mputstr(expr
->expr
, "), ");
6811 generate_code_expr_senderredirect(expr
);
6813 // the signature template is not present
6814 generate_code_expr_fromclause(expr
);
6815 expr
->expr
= mputstr(expr
->expr
, ", ");
6816 generate_code_expr_senderredirect(expr
);
6819 // the operation refers to any port
6820 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6821 generate_code_expr_fromclause(expr
);
6822 expr
->expr
= mputstr(expr
->expr
, ", ");
6823 generate_code_expr_senderredirect(expr
);
6825 expr
->expr
= mputc(expr
->expr
, ')');
6828 void Statement::generate_code_expr_catch(expression_struct
*expr
)
6830 if (port_op
.portref
) {
6831 // the operation refers to a specific port
6832 if (port_op
.r
.ctch
.timeout
) {
6833 // the operation catches the timeout exception
6834 expr
->expr
= mputstr(expr
->expr
, "call_timer.timeout()");
6837 port_op
.portref
->generate_code(expr
);
6838 expr
->expr
= mputprintf(expr
->expr
, ".%s(",
6839 statementtype
== S_CHECK_CATCH
? "check_catch" : "get_exception");
6840 if (port_op
.r
.ctch
.signature_ref
) {
6841 // the signature reference and the exception template is present
6842 expr
->expr
= mputprintf(expr
->expr
, "%s_exception_template(",
6843 port_op
.r
.ctch
.signature
->get_genname_value(my_sb
).c_str());
6844 port_op
.r
.rcvpar
->generate_code(expr
);
6845 expr
->expr
= mputstr(expr
->expr
, ", ");
6846 if (port_op
.r
.redirect
.value
) {
6847 // value redirect is also present
6848 expr
->expr
= mputstr(expr
->expr
, "&(");
6849 port_op
.r
.redirect
.value
->generate_code(expr
);
6850 expr
->expr
= mputc(expr
->expr
, ')');
6851 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6852 expr
->expr
= mputstr(expr
->expr
, "), ");
6855 // the operation refers to any port
6856 expr
->expr
= mputprintf(expr
->expr
, "PORT::%s(",
6857 statementtype
== S_CHECK_CATCH
? "any_check_catch" : "any_catch");
6859 generate_code_expr_fromclause(expr
);
6860 expr
->expr
= mputstr(expr
->expr
, ", ");
6861 generate_code_expr_senderredirect(expr
);
6862 expr
->expr
= mputc(expr
->expr
, ')');
6865 void Statement::generate_code_expr_check(expression_struct
*expr
)
6867 if (port_op
.portref
) {
6868 // the operation refers to a specific port
6869 port_op
.portref
->generate_code(expr
);
6870 expr
->expr
= mputstr(expr
->expr
, ".check");
6872 // the operation refers to any port
6873 expr
->expr
= mputstr(expr
->expr
, "PORT::any_check");
6875 expr
->expr
= mputc(expr
->expr
, '(');
6876 generate_code_expr_fromclause(expr
);
6877 expr
->expr
= mputstr(expr
->expr
, ", ");
6878 generate_code_expr_senderredirect(expr
);
6879 expr
->expr
= mputc(expr
->expr
, ')');
6882 void Statement::generate_code_expr_done(expression_struct
*expr
)
6884 if (comp_op
.compref
) {
6885 if (comp_op
.donereturn
.donematch
) {
6886 // value returning done
6887 // figure out what type the done() function belongs to
6888 Type
*t
= comp_op
.donereturn
.donematch
6889 ->get_expr_governor(Type::EXPECTED_TEMPLATE
);
6890 if (!t
) FATAL_ERROR("Statement::generate_code_expr_done()");
6891 while (t
->is_ref() && !t
->has_done_attribute())
6892 t
= t
->get_type_refd();
6893 if (!t
->has_done_attribute())
6894 FATAL_ERROR("Statement::generate_code_expr_done()");
6895 // determine whether the done() function is in the same module
6896 Common::Module
*t_mod
= t
->get_my_scope()->get_scope_mod_gen();
6897 if (t_mod
!= my_sb
->get_scope_mod_gen()) {
6898 expr
->expr
= mputprintf(expr
->expr
, "%s::",
6899 t_mod
->get_modid().get_name().c_str());
6901 expr
->expr
= mputstr(expr
->expr
, "done(");
6902 comp_op
.compref
->generate_code_expr(expr
);
6903 expr
->expr
= mputstr(expr
->expr
, ", ");
6904 comp_op
.donereturn
.donematch
->generate_code(expr
);
6905 expr
->expr
= mputstr(expr
->expr
, ", ");
6906 if (comp_op
.donereturn
.redirect
) {
6907 // value redirect is present
6908 expr
->expr
= mputstr(expr
->expr
, "&(");
6909 comp_op
.donereturn
.redirect
->generate_code(expr
);
6910 expr
->expr
= mputc(expr
->expr
, ')');
6912 // value redirect is omitted
6913 expr
->expr
= mputstr(expr
->expr
, "NULL");
6915 expr
->expr
= mputc(expr
->expr
, ')');
6918 comp_op
.compref
->generate_code_expr_mandatory(expr
);
6919 expr
->expr
= mputstr(expr
->expr
, ".done()");
6921 } else if (comp_op
.any_or_all
== C_ANY
) {
6922 // any component.done
6923 expr
->expr
= mputstr(expr
->expr
,
6924 "TTCN_Runtime::component_done(ANY_COMPREF)");
6926 // all component.done
6927 expr
->expr
= mputstr(expr
->expr
,
6928 "TTCN_Runtime::component_done(ALL_COMPREF)");
6932 void Statement::generate_code_expr_killed(expression_struct
*expr
)
6934 if (comp_op
.compref
) {
6936 comp_op
.compref
->generate_code_expr_mandatory(expr
);
6937 expr
->expr
= mputstr(expr
->expr
, ".killed()");
6938 } else if (comp_op
.any_or_all
== C_ANY
) {
6939 // any component.killed
6940 expr
->expr
= mputstr(expr
->expr
,
6941 "TTCN_Runtime::component_killed(ANY_COMPREF)");
6943 // all component.killed
6944 expr
->expr
= mputstr(expr
->expr
,
6945 "TTCN_Runtime::component_killed(ALL_COMPREF)");
6949 void Statement::generate_code_expr_timeout(expression_struct
*expr
)
6951 if (timer_op
.timerref
) {
6952 timer_op
.timerref
->generate_code(expr
);
6953 expr
->expr
=mputstr(expr
->expr
, ".timeout()");
6954 } else expr
->expr
= mputstr(expr
->expr
, "TIMER::any_timeout()");
6957 void Statement::generate_code_expr_sendpar(expression_struct
*expr
)
6959 Template
*templ_body
= port_op
.s
.sendpar
->get_Template();
6960 if (!port_op
.s
.sendpar
->get_DerivedRef() &&
6961 templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
) {
6962 // the send parameter is a value: optimization is possible
6963 Value
*t_val
= templ_body
->get_specific_value();
6964 bool cast_needed
= t_val
->explicit_cast_needed();
6966 // the ambiguous C++ expression is converted to the value class
6967 expr
->expr
= mputprintf(expr
->expr
, "%s(",
6968 t_val
->get_my_governor()->get_genname_value(my_sb
).c_str());
6970 t_val
->generate_code_expr_mandatory(expr
);
6971 if (cast_needed
) expr
->expr
= mputc(expr
->expr
, ')');
6973 // the send parameter is a real template: optimization is not possible
6974 port_op
.s
.sendpar
->generate_code(expr
);
6978 void Statement::generate_code_expr_fromclause(expression_struct
*expr
)
6980 if (port_op
.r
.fromclause
) {
6981 // the from clause is present: trivial case
6982 port_op
.r
.fromclause
->generate_code(expr
);
6983 } else if (port_op
.r
.redirect
.sender
) {
6984 // from clause is omitted, but sender redirect is present
6985 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
6987 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
6988 if (t_var_type
->get_type_refd_last()->get_typetype() ==
6989 Type::T_COMPONENT
) {
6990 // the variable can store a component reference
6991 expr
->expr
= mputstr(expr
->expr
, "any_compref");
6993 // the variable can store an address value
6994 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6995 t_var_type
->get_genname_template(my_sb
).c_str());
6998 // neither from clause nor sender redirect is present
6999 // the operation cannot refer to address type
7000 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7004 void Statement::generate_code_expr_senderredirect(expression_struct
*expr
)
7006 if (port_op
.r
.redirect
.sender
) {
7007 expr
->expr
= mputstr(expr
->expr
, "&(");
7008 port_op
.r
.redirect
.sender
->generate_code(expr
);
7009 expr
->expr
= mputc(expr
->expr
, ')');
7010 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
7013 void Statement::generate_code_portref(expression_struct
*expr
,
7016 // make a backup of the current expression
7017 char *expr_backup
= expr
->expr
;
7018 // build the equivalent of p_ref in expr->expr
7019 expr
->expr
= mprintf("\"%s\"", p_ref
->get_id()->get_dispname().c_str());
7020 FieldOrArrayRefs
*t_subrefs
= p_ref
->get_subrefs();
7022 // array indices are present
7023 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
7024 FieldOrArrayRef
*t_ref
= t_subrefs
->get_ref(i
);
7025 if (t_ref
->get_type() != FieldOrArrayRef::ARRAY_REF
)
7026 FATAL_ERROR("Statement::generate_code_portref()");
7027 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7028 char *tmp
= expr
->expr
;
7029 expr
->expr
= mcopystr("get_port_name(");
7030 expr
->expr
= mputstr(expr
->expr
, tmp
);
7032 expr
->expr
= mputstr(expr
->expr
, ", ");
7033 t_ref
->get_val()->generate_code_expr(expr
);
7034 expr
->expr
= mputc(expr
->expr
, ')');
7037 // now expr->expr contains the equivalent of p_ref
7038 // append it to the original expression and restore the result
7039 expr_backup
= mputstr(expr_backup
, expr
->expr
);
7041 expr
->expr
= expr_backup
;
7044 void Statement::set_parent_path(WithAttribPath
* p_path
) {
7045 switch (statementtype
) {
7047 def
->set_parent_path(p_path
);
7050 block
->set_parent_path(p_path
);
7053 if_stmt
.ics
->set_parent_path(p_path
);
7054 if (if_stmt
.elseblock
)
7055 if_stmt
.elseblock
->set_parent_path(p_path
);
7058 select
.scs
->set_parent_path(p_path
);
7061 loop
.block
->set_parent_path(p_path
);
7065 loop
.block
->set_parent_path(p_path
);
7076 case S_STOP_TESTCASE
:
7080 case S_UNKNOWN_INSTANCE
:
7081 case S_FUNCTION_INSTANCE
:
7082 case S_ALTSTEP_INSTANCE
:
7093 case S_CHECK_RECEIVE
:
7096 case S_CHECK_GETCALL
:
7098 case S_CHECK_GETREPLY
:
7107 case S_START_COMP_REFD
:
7120 case S_TESTCASE_INSTANCE
:
7121 case S_TESTCASE_INSTANCE_REFD
:
7122 case S_ACTIVATE_REFD
:
7123 case S_UNKNOWN_INVOKED
:
7124 case S_FUNCTION_INVOKED
:
7125 case S_ALTSTEP_INVOKED
:
7129 FATAL_ERROR("Statement::set_parent_path()");
7133 // =================================
7135 // =================================
7137 Assignment::Assignment(Reference
*p_ref
, Template
*p_templ
)
7138 : asstype(ASS_UNKNOWN
), ref(p_ref
), templ(p_templ
), self_ref(false),
7139 template_restriction(TR_NONE
), gen_restriction_check(false)
7141 if(!ref
|| !templ
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7144 Assignment::Assignment(Reference
*p_ref
, Value
*p_val
)
7145 : asstype(ASS_VAR
), ref(p_ref
), val(p_val
), self_ref(false),
7146 template_restriction(TR_NONE
), gen_restriction_check(false)
7148 if(!ref
|| !val
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7151 Assignment::~Assignment()
7166 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7170 Assignment
*Assignment::clone() const
7172 FATAL_ERROR("Assignment::clone");
7175 void Assignment::set_my_scope(Scope
*p_scope
)
7180 ref
->set_my_scope(p_scope
);
7181 templ
->set_my_scope(p_scope
);
7184 ref
->set_my_scope(p_scope
);
7185 val
->set_my_scope(p_scope
);
7190 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7194 void Assignment::set_fullname(const string
& p_fullname
)
7196 Node::set_fullname(p_fullname
);
7200 ref
->set_fullname(p_fullname
);
7201 templ
->set_fullname(p_fullname
);
7204 ref
->set_fullname(p_fullname
);
7205 val
->set_fullname(p_fullname
);
7210 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7214 void Assignment::dump(unsigned int level
) const
7216 // warning, ref is not always set (e.g. ASS_ERROR)
7224 DEBUG(level
, "*** ERROR ***");
7228 DEBUG(level
, "*** UNKNOWN ***");
7233 templ
->dump(level
+1);
7238 void Assignment::chk_unknown_ass()
7240 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7241 if (!t_ass
) goto error
;
7242 switch (t_ass
->get_asstype()) {
7243 case Common::Assignment::A_ERROR
:
7245 case Common::Assignment::A_PAR_VAL_IN
:
7246 t_ass
->use_as_lvalue(*ref
);
7248 case Common::Assignment::A_VAR
:
7249 case Common::Assignment::A_PAR_VAL_OUT
:
7250 case Common::Assignment::A_PAR_VAL_INOUT
:
7251 if (templ
->is_Value()) {
7252 Value
*t_val
= templ
->get_Value();
7258 templ
->error("A template body with matching symbols cannot be"
7259 " assigned to a variable");
7263 case Common::Assignment::A_PAR_TEMPL_IN
:
7264 t_ass
->use_as_lvalue(*ref
);
7266 case Common::Assignment::A_VAR_TEMPLATE
: {
7267 Type::typetype_t tt
= t_ass
->get_Type()->get_typetype();
7270 case Type::T_BSTR_A
:
7275 case Type::T_UTF8STRING
:
7276 case Type::T_NUMERICSTRING
:
7277 case Type::T_PRINTABLESTRING
:
7278 case Type::T_TELETEXSTRING
:
7279 case Type::T_VIDEOTEXSTRING
:
7280 case Type::T_IA5STRING
:
7281 case Type::T_GRAPHICSTRING
:
7282 case Type::T_VISIBLESTRING
:
7283 case Type::T_GENERALSTRING
:
7284 case Type::T_UNIVERSALSTRING
:
7285 case Type::T_BMPSTRING
:
7286 case Type::T_UTCTIME
:
7287 case Type::T_GENERALIZEDTIME
:
7288 case Type::T_OBJECTDESCRIPTOR
: {
7289 Ttcn::FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7290 if (!subrefs
) break;
7291 size_t nof_subrefs
= subrefs
->get_nof_refs();
7292 if (nof_subrefs
> 0) {
7293 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
7294 ->get_ref(nof_subrefs
- 1);
7295 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
7296 if (!templ
->is_Value()) {
7297 templ
->error("A template body with matching symbols cannot be "
7298 "assigned to an element of a template variable");
7308 case Common::Assignment::A_PAR_TEMPL_OUT
:
7309 case Common::Assignment::A_PAR_TEMPL_INOUT
:
7310 asstype
= ASS_TEMPLATE
;
7314 ref
->error("Reference to a variable or template variable was expected "
7315 "instead of %s", t_ass
->get_description().c_str());
7322 asstype
= ASS_ERROR
;
7326 void Assignment::chk_var_ass()
7328 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7329 Type
*var_type
= lhs
->get_Type();
7330 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7332 var_type
->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7333 if (!type
) goto error
;
7334 val
->set_my_governor(type
);
7335 type
->chk_this_value_ref(val
);
7336 if (val
->get_value_refd_last()->get_valuetype() == Value::V_OMIT
) {
7337 Identifier
*field_id
= 0;
7338 if (subrefs
) field_id
= subrefs
->remove_last_field();
7340 val
->error("Omit value can be assigned to an optional field of "
7341 "a record or set value only");
7344 Type
*base_type
= var_type
7345 ->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7346 // Putting field_id back to subrefs.
7347 subrefs
->add(new FieldOrArrayRef(field_id
));
7348 base_type
= base_type
->get_type_refd_last();
7349 switch (base_type
->get_typetype()) {
7358 val
->error("Omit value can be assigned to an optional field of "
7359 "a record or set value only");
7362 if (!base_type
->get_comp_byName(*field_id
)->get_is_optional()) {
7363 val
->error("Assignment of `omit' to mandatory field `%s' of type "
7364 "`%s'", field_id
->get_dispname().c_str(),
7365 base_type
->get_typename().c_str());
7369 bool is_string_element
= subrefs
&& subrefs
->refers_to_string_element();
7370 self_ref
|= type
->chk_this_value(val
, lhs
, Type::EXPECTED_DYNAMIC_VALUE
,
7371 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
,
7372 (is_string_element
? NO_SUB_CHK
: SUB_CHK
), NOT_IMPLICIT_OMIT
,
7373 (is_string_element
? IS_STR_ELEM
: NOT_STR_ELEM
));
7374 if (is_string_element
) {
7375 // The length of RHS value shall be 1.
7376 Value
*v_last
= val
->get_value_refd_last();
7377 switch (type
->get_type_refd_last()->get_typetype()) {
7379 case Type::T_BSTR_A
:
7380 if (v_last
->get_valuetype() != Value::V_BSTR
) v_last
= 0;
7383 if (v_last
->get_valuetype() != Value::V_HSTR
) v_last
= 0;
7386 if (v_last
->get_valuetype() != Value::V_OSTR
) v_last
= 0;
7389 case Type::T_NUMERICSTRING
:
7390 case Type::T_PRINTABLESTRING
:
7391 case Type::T_IA5STRING
:
7392 case Type::T_VISIBLESTRING
:
7393 case Type::T_UTCTIME
:
7394 case Type::T_GENERALIZEDTIME
:
7395 if (v_last
->get_valuetype() != Value::V_CSTR
) v_last
= 0;
7398 case Type::T_UTF8STRING
:
7399 case Type::T_TELETEXSTRING
:
7400 case Type::T_VIDEOTEXSTRING
:
7401 case Type::T_GRAPHICSTRING
:
7402 case Type::T_GENERALSTRING
:
7403 case Type::T_UNIVERSALSTRING
:
7404 case Type::T_BMPSTRING
:
7405 case Type::T_OBJECTDESCRIPTOR
:
7406 if (v_last
->get_valuetype() != Value::V_USTR
) v_last
= 0;
7412 size_t string_len
= v_last
->get_val_strlen();
7413 if (string_len
!= 1) {
7414 val
->error("The length of the string to be assigned to a string "
7415 "element of type `%s' should be 1 instead of %lu",
7416 type
->get_typename().c_str(),
7417 (unsigned long)string_len
);
7427 asstype
= ASS_ERROR
;
7431 void Assignment::chk_template_ass()
7433 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7434 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7435 if (!lhs
) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7436 Type
*type
= lhs
->get_Type()->
7437 get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7438 if (!type
) goto error
;
7439 if (lhs
->get_asstype() != Common::Assignment::A_VAR_TEMPLATE
&&
7440 subrefs
&& subrefs
->refers_to_string_element()) {
7441 ref
->error("It is not allowed to index template strings");
7444 templ
->set_my_governor(type
);
7446 templ
->flatten(false);
7448 type
->chk_this_template_ref(templ
);
7449 self_ref
|= type
->chk_this_template_generic(templ
, INCOMPLETE_ALLOWED
,
7450 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, lhs
);
7451 chk_template_restriction();
7456 asstype
= ASS_ERROR
;
7460 void Assignment::chk()
7475 FATAL_ERROR("Ttcn::Assignment::chk()");
7479 void Assignment::set_code_section(
7480 GovernedSimple::code_section_t p_code_section
)
7484 ref
->set_code_section(p_code_section
);
7485 val
->set_code_section(p_code_section
);
7488 ref
->set_code_section(p_code_section
);
7489 templ
->set_code_section(p_code_section
);
7495 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7499 void Assignment::chk_template_restriction()
7501 if (asstype
!=ASS_TEMPLATE
)
7502 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7503 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7504 if (!t_ass
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7505 switch (t_ass
->get_asstype()) {
7506 case Common::Assignment::A_VAR_TEMPLATE
: {
7507 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(t_ass
);
7508 if (!dvt
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7509 template_restriction
= dvt
->get_template_restriction();
7511 case Common::Assignment::A_PAR_TEMPL_IN
:
7512 case Common::Assignment::A_PAR_TEMPL_OUT
:
7513 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
7514 FormalPar
* fp
= dynamic_cast<FormalPar
*>(t_ass
);
7515 if (!fp
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7516 template_restriction
= fp
->get_template_restriction();
7519 template_restriction
= TR_NONE
;
7521 // transform the restriction if this is a subfield
7522 template_restriction
= Template::get_sub_restriction(template_restriction
, ref
);
7523 // check the template restriction
7524 gen_restriction_check
=
7525 templ
->chk_restriction("template", template_restriction
);
7528 char *Assignment::generate_code(char *str
)
7530 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
7531 const bool rhs_copied
= self_ref
;
7534 const string
& rhs_copy
= val
->get_temporary_id();
7535 string rhs_ref
= rhs_copy
;
7536 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7537 if (val
->get_my_governor()->is_optional_field()) {
7538 str
= mputprintf(str
, "{\nOPTIONAL<%s> %s;\n",
7539 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7542 str
= mputprintf(str
, "{\n%s %s;\n",
7543 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7546 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(val
);
7549 // Most complicated case. The LHS is saved in a temporary reference,
7550 // in case we need to access it more than once, e.g:
7551 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7552 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7553 // This saves having to index x2 more than once.
7554 const string
& tmp_id
= val
->get_temporary_id(); // For "ref".
7555 const char *tmp_id_str
= tmp_id
.c_str();
7556 const string
& type_genname
=
7557 val
->get_my_governor()->get_genname_value(val
->get_my_scope());
7558 const char *type_genname_str
= type_genname
.c_str();
7559 expression_struct expr
;
7560 Code::init_expr(&expr
);
7561 ref
->generate_code(&expr
);
7565 str
= TypeConv::gen_conv_code_refd(str
, rhs_ref
.c_str(), val
);
7566 else str
= val
->generate_code_init(str
, rhs_ref
.c_str());
7569 str
= mputstr(str
, "{\n");
7570 str
= mputstr(str
, expr
.preamble
);
7571 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
7572 // The LHS is a string element.
7573 str
= mputprintf(str
, "%s_ELEMENT %s(%s);\n", type_genname_str
,
7574 tmp_id_str
, expr
.expr
);
7576 // The LHS is a normal value.
7577 str
= mputprintf(str
, "%s& %s = %s; /* 7388 */\n", type_genname_str
,
7578 tmp_id_str
, expr
.expr
);
7580 str
= mputstr(str
, expr
.postamble
);
7581 // We now have a reference to the LHS. Generate the actual assignment
7583 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7587 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, val
);
7588 else str
= val
->generate_code_init(str
, tmp_id_str
);
7590 Code::free_expr(&expr
);
7591 str
= mputstr(str
, "}\n");
7595 if (!val
->has_single_expr()) goto case3
;
7596 // C++ equivalent of RHS is a single expression.
7597 expression_struct expr
;
7598 Code::init_expr(&expr
);
7599 ref
->generate_code(&expr
);// vu.s()
7601 str
= mputprintf(str
, "%s = %s;\n",
7602 rhs_copy
.c_str(), val
->get_single_expr().c_str());
7604 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7607 expr
.expr
= mputprintf(expr
.expr
,
7608 " = %s", val
->get_single_expr().c_str());
7610 str
= Code::merge_free_expr(str
, &expr
);
7613 // The LHS is a single identifier.
7614 const string
& rhs_name
= ref
->get_refd_assignment()
7615 ->get_genname_from_scope(ref
->get_my_scope());
7616 if (val
->can_use_increment(ref
)) {
7617 switch (val
->get_optype()) {
7618 case Value::OPTYPE_ADD
:
7619 str
= mputprintf(str
, "++%s;\n", rhs_name
.c_str());
7621 case Value::OPTYPE_SUBTRACT
:
7622 str
= mputprintf(str
, "--%s;\n", rhs_name
.c_str());
7625 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7628 str
= val
->generate_code_init(str
,
7629 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7632 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7638 str
= mputstr(str
, "}\n");
7641 case ASS_TEMPLATE
: {
7642 const string
& rhs_copy
= templ
->get_temporary_id();
7643 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7644 str
= mputprintf(str
, "{\n%s %s;\n",
7645 templ
->get_my_governor()->get_genname_template(templ
->get_my_scope()).c_str(), rhs_copy
.c_str()//, rhs_copy.c_str()
7648 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(templ
);
7649 if (needs_conv
) { // case 3
7651 // Most complicated case. The LHS is saved in a temporary reference.
7652 const string
& tmp_id
= templ
->get_temporary_id();
7653 const char *tmp_id_str
= tmp_id
.c_str();
7654 expression_struct expr
;
7655 Code::init_expr(&expr
);
7656 ref
->generate_code(&expr
);
7660 str
= TypeConv::gen_conv_code_refd(str
, rhs_copy
.c_str(), templ
);
7661 else str
= templ
->generate_code_init(str
, rhs_copy
.c_str());
7664 str
= mputstr(str
, "{\n");
7665 str
= mputstr(str
, expr
.preamble
);
7666 str
= mputprintf(str
, "%s& %s = %s;\n",
7667 templ
->get_my_governor()->get_genname_template(
7668 templ
->get_my_scope()
7669 ).c_str(), tmp_id_str
, expr
.expr
);
7670 str
= mputstr(str
, expr
.postamble
);
7672 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7676 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, templ
);
7678 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7679 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7680 str
= mputprintf(str
, "%s.remove_all_permutations();\n", tmp_id_str
);
7682 str
= templ
->generate_code_init(str
, tmp_id_str
);
7685 Code::free_expr(&expr
);
7687 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7688 str
= Template::generate_restriction_check_code(str
,
7689 tmp_id_str
, template_restriction
);
7690 str
= mputstr(str
, "}\n");
7692 else { // !needs_conv
7694 if ((template_restriction
== TR_NONE
|| !gen_restriction_check
)
7695 && templ
->has_single_expr()) {
7696 // C++ equivalent of RHS is a single expression and no restriction
7697 // check. Skipped if conversion needed.
7698 expression_struct expr
;
7699 Code::init_expr(&expr
);
7700 ref
->generate_code(&expr
);
7702 str
= mputprintf(str
, "%s = %s;\n",
7703 rhs_copy
.c_str(), templ
->get_single_expr(false).c_str());
7705 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7708 expr
.expr
= mputprintf(expr
.expr
,
7709 " = %s", templ
->get_single_expr(false).c_str());
7711 str
= Code::merge_free_expr(str
, &expr
); // will add a semicolon
7716 // LHS is a single identifier
7717 const string
& rhs_name
= ref
->get_refd_assignment()
7718 ->get_genname_from_scope(ref
->get_my_scope());
7719 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7720 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7721 str
= mputprintf(str
, "%s.remove_all_permutations();\n", (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7723 str
= templ
->generate_code_init(str
,
7724 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7726 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7728 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7729 str
= Template::generate_restriction_check_code(str
,
7730 ref
->get_refd_assignment()->get_genname_from_scope(
7732 ).c_str(), template_restriction
);
7736 str
= mputstr(str
, "}\n");
7740 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7745 // =================================
7746 // ===== ParamAssignment
7747 // =================================
7749 ParamAssignment::ParamAssignment(Identifier
*p_id
, Reference
*p_ref
)
7750 : Node(), Location(), id(p_id
), ref(p_ref
)
7752 if(!id
|| !ref
) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7755 ParamAssignment::~ParamAssignment()
7761 ParamAssignment
*ParamAssignment::clone() const
7763 FATAL_ERROR("ParamAssignment::clone");
7766 void ParamAssignment::set_my_scope(Scope
*p_scope
)
7768 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7769 ref
->set_my_scope(p_scope
);
7772 void ParamAssignment::set_fullname(const string
& p_fullname
)
7774 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7775 ref
->set_fullname(p_fullname
);
7778 Reference
*ParamAssignment::get_ref() const
7780 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7784 Reference
*ParamAssignment::steal_ref()
7786 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7787 Reference
*ret_val
= ref
;
7792 // =================================
7793 // ===== ParamAssignments
7794 // =================================
7796 ParamAssignments::~ParamAssignments()
7798 for(size_t i
=0; i
<parasss
.size(); i
++)
7803 ParamAssignments
*ParamAssignments::clone() const
7805 FATAL_ERROR("ParamAssignments::clone");
7808 void ParamAssignments::set_my_scope(Scope
*p_scope
)
7810 for(size_t i
=0; i
<parasss
.size(); i
++)
7811 parasss
[i
]->set_my_scope(p_scope
);
7814 void ParamAssignments::set_fullname(const string
& p_fullname
)
7816 Node::set_fullname(p_fullname
);
7817 for(size_t i
=0; i
<parasss
.size(); i
++)
7818 parasss
[i
]->set_fullname(p_fullname
+".parass_"+Int2string(i
+1));
7821 void ParamAssignments::add_parass(ParamAssignment
*p_parass
)
7824 FATAL_ERROR("ParamAssignments::add_parass()");
7825 parasss
.add(p_parass
);
7828 // =================================
7829 // ===== VariableEntry
7830 // =================================
7832 VariableEntry::VariableEntry(Reference
*p_ref
)
7833 : Node(), Location(), ref(p_ref
)
7835 if(!ref
) FATAL_ERROR("VariableEntry::VariableEntry()");
7838 VariableEntry::~VariableEntry()
7843 VariableEntry
*VariableEntry::clone() const
7845 FATAL_ERROR("VariableEntry::clone");
7848 void VariableEntry::set_my_scope(Scope
*p_scope
)
7850 if(ref
) ref
->set_my_scope(p_scope
);
7853 void VariableEntry::set_fullname(const string
& p_fullname
)
7855 Node::set_fullname(p_fullname
);
7856 if(ref
) ref
->set_fullname(p_fullname
+".ref");
7859 // =================================
7860 // ===== VariableEntries
7861 // =================================
7863 VariableEntries::~VariableEntries()
7865 for(size_t i
=0; i
<ves
.size(); i
++)
7870 VariableEntries
*VariableEntries::clone() const
7872 FATAL_ERROR("VariableEntries::clone");
7875 void VariableEntries::set_my_scope(Scope
*p_scope
)
7877 for(size_t i
=0; i
<ves
.size(); i
++)
7878 ves
[i
]->set_my_scope(p_scope
);
7881 void VariableEntries::set_fullname(const string
& p_fullname
)
7883 Node::set_fullname(p_fullname
);
7884 for(size_t i
=0; i
<ves
.size(); i
++)
7885 ves
[i
]->set_fullname(p_fullname
+".ve_"+Int2string(i
+1));
7888 void VariableEntries::add_ve(VariableEntry
*p_ve
)
7891 FATAL_ERROR("VariableEntries::add_ve()");
7895 // =================================
7896 // ===== ParamRedirect
7897 // =================================
7899 ParamRedirect::ParamRedirect(ParamAssignments
*p_parasss
)
7900 : Node(), Location(), parredirtype(P_ASS
), parasss(p_parasss
)
7902 if(!parasss
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
7905 ParamRedirect::ParamRedirect(VariableEntries
*p_ves
)
7906 : Node(), Location(), parredirtype(P_VAR
), ves(p_ves
)
7908 if(!ves
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
7911 ParamRedirect::~ParamRedirect()
7913 switch(parredirtype
) {
7921 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
7925 ParamRedirect
*ParamRedirect::clone() const
7927 FATAL_ERROR("ParamRedirect::clone");
7930 void ParamRedirect::set_my_scope(Scope
*p_scope
)
7932 switch(parredirtype
) {
7934 parasss
->set_my_scope(p_scope
);
7937 ves
->set_my_scope(p_scope
);
7940 FATAL_ERROR("ParamRedirect::set_my_scope()");
7944 void ParamRedirect::set_fullname(const string
& p_fullname
)
7946 Node::set_fullname(p_fullname
);
7947 switch(parredirtype
) {
7949 parasss
->set_fullname(p_fullname
+".parasss");
7952 ves
->set_fullname(p_fullname
+".parvars");
7955 FATAL_ERROR("ParamRedirect::set_fullname()");
7959 void ParamRedirect::chk_erroneous()
7961 Error_Context
cntxt(this, "In parameter redirect");
7962 switch(parredirtype
) {
7964 map
<string
, ParamAssignment
> parass_m
;
7965 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
7966 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
7967 const Identifier
&t_id
= t_parass
->get_id();
7968 const string
& name
= t_id
.get_name();
7969 const char *dispname_str
= t_id
.get_dispname().c_str();
7970 if (parass_m
.has_key(name
)) {
7971 t_parass
->error("Duplicate redirect for parameter `%s'",
7973 parass_m
[name
]->note("A variable entry for parameter `%s' is "
7974 "already given here", dispname_str
);
7975 } else parass_m
.add(name
, t_parass
);
7976 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
7978 chk_variable_ref(t_parass
->get_ref(), 0);
7983 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
7984 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
7985 Error_Context
cntxt2(t_ve
, "In variable entry #%lu",
7986 (unsigned long) (i
+ 1));
7987 chk_variable_ref(t_ve
->get_ref(), 0);
7991 FATAL_ERROR("ParamRedirect::chk_erroneous()");
7995 void ParamRedirect::chk(Type
*p_sig
, bool is_out
)
7997 SignatureParamList
*t_parlist
= p_sig
->get_signature_parameters();
7999 Error_Context
cntxt(this, "In parameter redirect");
8000 switch (parredirtype
) {
8002 chk_parasss(p_sig
, t_parlist
, is_out
);
8005 chk_ves(p_sig
, t_parlist
, is_out
);
8008 FATAL_ERROR("ParamRedirect::chk()");
8011 error("Parameter redirect cannot be used because signature `%s' "
8012 "does not have parameters", p_sig
->get_typename().c_str());
8017 void ParamRedirect::chk_parasss(Type
*p_sig
, SignatureParamList
*p_parlist
,
8020 map
<string
, ParamAssignment
> parass_m
;
8021 bool error_flag
= false;
8022 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8023 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8024 const Identifier
&t_id
= t_parass
->get_id();
8025 const string
& name
= t_id
.get_name();
8026 const char *dispname_str
= t_id
.get_dispname().c_str();
8027 if (parass_m
.has_key(name
)) {
8028 t_parass
->error("Duplicate redirect for parameter `%s'",
8030 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8031 "already given here", dispname_str
);
8033 } else parass_m
.add(name
, t_parass
);
8034 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8036 if (p_parlist
->has_param_withName(t_id
)) {
8037 const SignatureParam
*t_par
= p_parlist
->get_param_byName(t_id
);
8038 SignatureParam::param_direction_t t_dir
= t_par
->get_direction();
8040 if (t_dir
== SignatureParam::PARAM_IN
) {
8041 t_parass
->error("Parameter `%s' of signature `%s' has `in' "
8042 "direction", dispname_str
, p_sig
->get_typename().c_str());
8046 if (t_dir
== SignatureParam::PARAM_OUT
) {
8047 t_parass
->error("Parameter `%s' of signature `%s' has `out' "
8048 "direction", dispname_str
, p_sig
->get_typename().c_str());
8052 chk_variable_ref(t_parass
->get_ref(), t_par
->get_type());
8054 t_parass
->error("Signature `%s' does not have parameter named `%s'",
8055 p_sig
->get_typename().c_str(), dispname_str
);
8057 chk_variable_ref(t_parass
->get_ref(), 0);
8061 // converting the AssignmentList to VariableList
8062 VariableEntries
*t_ves
= new VariableEntries
;
8063 size_t upper_limit
= is_out
?
8064 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8065 for (size_t i
= 0; i
< upper_limit
; i
++) {
8066 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8067 : p_parlist
->get_in_param_byIndex(i
);
8068 const string
& name
= t_par
->get_id().get_name();
8069 if (parass_m
.has_key(name
))
8070 t_ves
->add_ve(new VariableEntry(parass_m
[name
]->steal_ref()));
8071 else t_ves
->add_ve(new VariableEntry
);
8075 parredirtype
= P_VAR
;
8080 void ParamRedirect::chk_ves(Type
*p_sig
, SignatureParamList
*p_parlist
,
8083 size_t nof_ves
= ves
->get_nof_ves();
8084 size_t nof_pars
= is_out
?
8085 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8086 if (nof_ves
!= nof_pars
) {
8087 error("Too %s variable entries compared to the number of %s/inout "
8088 "parameters in signature `%s': %lu was expected instead of %lu",
8089 nof_ves
> nof_pars
? "many" : "few", is_out
? "out" : "in",
8090 p_sig
->get_typename().c_str(), (unsigned long) nof_pars
,
8091 (unsigned long) nof_ves
);
8093 for (size_t i
= 0; i
< nof_ves
; i
++) {
8094 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8096 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8097 : p_parlist
->get_in_param_byIndex(i
);
8098 Error_Context
cntxt(t_ve
, "In variable entry #%lu (for parameter `%s')",
8099 (unsigned long) (i
+ 1), t_par
->get_id().get_dispname().c_str());
8100 chk_variable_ref(t_ve
->get_ref(), t_par
->get_type());
8102 Error_Context
cntxt(t_ve
, "In variable entry #%lu",
8103 (unsigned long) (i
+ 1));
8104 chk_variable_ref(t_ve
->get_ref(), 0);
8109 void ParamRedirect::chk_variable_ref(Reference
*p_ref
, Type
*p_type
)
8112 Type
*t_var_type
= p_ref
->chk_variable_ref();
8113 if (p_type
&& t_var_type
&& !p_type
->is_identical(t_var_type
)) {
8114 p_ref
->error("Type mismatch in parameter redirect: "
8115 "A variable of type `%s' was expected instead of `%s'",
8116 p_type
->get_typename().c_str(),
8117 t_var_type
->get_typename().c_str());
8121 void ParamRedirect::set_code_section(
8122 GovernedSimple::code_section_t p_code_section
)
8124 // code can be generated from VariableList only
8125 switch (parredirtype
) {
8129 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8130 Reference
*t_ref
= ves
->get_ve_byIndex(i
)->get_ref();
8131 if (t_ref
) t_ref
->set_code_section(p_code_section
);
8135 FATAL_ERROR("ParamRedirect::set_code_section()");
8139 void ParamRedirect::generate_code(expression_struct_t
*expr
)
8141 // AssignmentList is converted to VariableList during checking
8142 if (parredirtype
!= P_VAR
) FATAL_ERROR("ParamRedirect::generate_code()");
8143 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8144 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
8145 Reference
*ref
= ves
->get_ve_byIndex(i
)->get_ref();
8147 // the variable reference is present
8148 expr
->expr
= mputstr(expr
->expr
, "&(");
8149 ref
->generate_code(expr
);
8150 expr
->expr
= mputc(expr
->expr
, ')');
8151 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
8155 // =================================
8156 // ===== LogArgument
8157 // =================================
8159 LogArgument::LogArgument(TemplateInstance
*p_ti
)
8160 : logargtype(L_UNDEF
)
8162 if (!p_ti
) FATAL_ERROR("LogArgument::LogArgument()");
8166 LogArgument::~LogArgument()
8168 switch (logargtype
) {
8187 FATAL_ERROR("LogArgument::~LogArgument()");
8191 LogArgument
*LogArgument::clone() const
8193 FATAL_ERROR("LogArgument::clone");
8196 void LogArgument::set_my_scope(Scope
*p_scope
)
8198 switch (logargtype
) {
8203 ti
->set_my_scope(p_scope
);
8208 val
->set_my_scope(p_scope
);
8211 ref
->set_my_scope(p_scope
);
8216 FATAL_ERROR("LogArgument::set_my_scope()");
8220 void LogArgument::set_fullname(const string
& p_fullname
)
8222 Node::set_fullname(p_fullname
);
8223 switch (logargtype
) {
8228 ti
->set_fullname(p_fullname
);
8233 val
->set_fullname(p_fullname
);
8236 ref
->set_fullname(p_fullname
);
8241 FATAL_ERROR("LogArgument::set_fullname()");
8245 const string
& LogArgument::get_str() const
8247 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::get_str()");
8251 Value
*LogArgument::get_val() const
8253 switch (logargtype
) {
8259 FATAL_ERROR("LogArgument::get_val()");
8264 Ref_base
*LogArgument::get_ref() const
8266 if (logargtype
!= L_REF
) FATAL_ERROR("LogArgument::get_ref()");
8270 TemplateInstance
*LogArgument::get_ti() const
8272 if (logargtype
!= L_TI
) FATAL_ERROR("LogArgument::get_ref()");
8276 void LogArgument::append_str(const string
& p_str
)
8278 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::append_str()");
8282 void LogArgument::chk() // determine the proper type of the log argument
8284 if (logargtype
!= L_UNDEF
) return;
8285 Template
*t_templ
= ti
->get_Template();
8286 t_templ
= t_templ
->get_template_refd_last();
8287 t_templ
->set_lowerid_to_ref();
8288 if (!ti
->get_Type() && !ti
->get_DerivedRef() && t_templ
->is_Value()) {
8289 // drop the template instance and keep only the embedded value
8290 Value
*t_val
= t_templ
->get_Value();
8296 // try to obtain the governor of the template instance
8297 Type
*governor
= ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8299 // the governor is still unknown: an error occurred
8300 // try to interpret possible enum values as references
8301 t_templ
->set_lowerid_to_ref();
8302 governor
= t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8308 t_templ
->error("Cannot determine the type of the argument");
8310 logargtype
= L_ERROR
;
8315 void LogArgument::chk_ref()
8317 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
8319 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
8321 case Common::Assignment::A_FUNCTION_RVAL
:
8322 case Common::Assignment::A_FUNCTION_RTEMP
:
8323 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
8324 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
8325 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *this, "call");
8326 case Common::Assignment::A_CONST
:
8327 case Common::Assignment::A_EXT_CONST
:
8328 case Common::Assignment::A_MODULEPAR
:
8329 case Common::Assignment::A_MODULEPAR_TEMP
:
8330 case Common::Assignment::A_TEMPLATE
:
8331 case Common::Assignment::A_VAR
:
8332 case Common::Assignment::A_VAR_TEMPLATE
:
8333 case Common::Assignment::A_PAR_VAL_IN
:
8334 case Common::Assignment::A_PAR_VAL_OUT
:
8335 case Common::Assignment::A_PAR_VAL_INOUT
:
8336 case Common::Assignment::A_PAR_TEMPL_IN
:
8337 case Common::Assignment::A_PAR_TEMPL_OUT
:
8338 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
8339 // the reference points to a value or template-like entity
8340 // checking sub-references
8341 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
8342 if (subrefs
&& t_ass
->get_Type()->get_field_type(subrefs
,
8343 Type::EXPECTED_DYNAMIC_VALUE
)) {
8344 // subrefs seems to be correct
8345 // also checking the presence of referred fields if possible
8346 if (asstype
== Common::Assignment::A_CONST
) {
8347 ReferenceChain
refch(ref
, "While searching referenced value");
8348 t_ass
->get_Value()->get_refd_sub_value(subrefs
, 0, false, &refch
);
8349 } else if (asstype
== Common::Assignment::A_TEMPLATE
) {
8350 ReferenceChain
refch(ref
, "While searching referenced template");
8351 t_ass
->get_Template()
8352 ->get_refd_sub_template(subrefs
, false, &refch
);
8356 case Common::Assignment::A_TIMER
:
8357 case Common::Assignment::A_PORT
: {
8358 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
8359 if (t_dims
) t_dims
->chk_indices(ref
, t_ass
->get_assname(), true,
8360 Type::EXPECTED_DYNAMIC_VALUE
);
8361 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8362 "cannot have field or array sub-references",
8363 t_ass
->get_description().c_str());
8365 case Common::Assignment::A_PAR_TIMER
:
8366 case Common::Assignment::A_PAR_PORT
:
8367 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8368 "field or array sub-references", t_ass
->get_description().c_str());
8370 case Common::Assignment::A_FUNCTION
:
8371 case Common::Assignment::A_EXT_FUNCTION
:
8372 ref
->error("Reference to a value, template, timer or port was expected "
8373 "instead of a call of %s, which does not have return type",
8374 t_ass
->get_description().c_str());
8377 ref
->error("Reference to a value, template, timer or port was expected "
8378 "instead of %s", t_ass
->get_description().c_str());
8382 void LogArgument::chk_val()
8384 // literal enumerated values cannot appear in this context
8385 val
->set_lowerid_to_ref();
8386 switch (val
->get_valuetype()) {
8387 case Value::V_CSTR
: {
8388 string
*t_cstr
= new string(val
->get_val_str());
8393 case Value::V_REFD
: {
8394 Ref_base
*t_ref
= val
->steal_ttcn_ref_base();
8401 if (val
->get_optype() == Value::OPTYPE_MATCH
) logargtype
= L_MATCH
;
8402 else logargtype
= L_VAL
;
8404 case Value::V_MACRO
:
8405 logargtype
= L_MACRO
;
8410 Type
*governor
= val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
8412 val
->set_my_governor(governor
);
8413 (void)governor
->chk_this_value(val
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
8414 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
8415 if (logargtype
== L_VAL
&& val
->get_valuetype() == Value::V_CSTR
8416 && !val
->is_unfoldable()) { // string value known at compile time
8417 string
*t_cstr
= new string(val
->get_val_str());
8423 if (logargtype
== L_MACRO
) {
8424 switch (val
->get_valuetype()) {
8425 case Value::V_CSTR
: {
8426 // the macro was evaluated to a charstring value
8427 string
*t_cstr
= new string(val
->get_val_str());
8432 case Value::V_MACRO
:
8433 // the macro could not be evaluated at compile time
8434 // leave logargtype as is
8437 // the macro was evaluated to other value (e.g. integer)
8442 val
->error("Cannot determine the type of the argument");
8444 logargtype
= L_ERROR
;
8448 void LogArgument::dump(unsigned int level
) const
8450 Node::dump(level
++);
8451 switch (logargtype
) {
8453 DEBUG(level
, "*error*");
8456 DEBUG(level
, "*undef*");
8459 DEBUG(level
, "TemplateInstance");
8465 DEBUG(level
, "Match");
8468 DEBUG(level
, "Macro");
8471 DEBUG(level
, "Reference");
8474 DEBUG(level
, "String=`%s'", cstr
->c_str());
8477 FATAL_ERROR("LogArgument::~LogArgument()");
8481 void LogArgument::set_code_section(
8482 GovernedSimple::code_section_t p_code_section
)
8484 switch (logargtype
) {
8487 ti
->set_code_section(p_code_section
);
8492 val
->set_code_section(p_code_section
);
8495 ref
->set_code_section(p_code_section
);
8501 FATAL_ERROR("LogArgument::set_code_section()");
8505 char *LogArgument::generate_code_log(char *str
)
8507 expression_struct expr
;
8508 Code::init_expr(&expr
);
8509 generate_code_expr(&expr
);
8510 str
= Code::merge_free_expr(str
, &expr
);
8514 void LogArgument::chk_recursions(ReferenceChain
& refch
)
8516 switch (logargtype
) {
8519 ti
->chk_recursions(refch
);
8524 val
->chk_recursions(refch
);
8527 Common::Assignment
*ass
= ref
->get_refd_assignment();
8529 refch
.add(ass
->get_fullname());
8535 FATAL_ERROR("LogArgument::chk_recursions()");
8539 bool LogArgument::has_single_expr()
8541 switch (logargtype
) {
8544 return ti
->has_single_expr();
8548 return ( val
->has_single_expr() && !val
->explicit_cast_needed() );
8550 Common::Assignment
*ass
= ref
->get_refd_assignment();
8551 switch (ass
->get_asstype()) {
8552 case Common::Assignment::A_CONST
:
8553 case Common::Assignment::A_EXT_CONST
:
8554 return ref
->has_single_expr();
8563 FATAL_ERROR("LogArgument::has_single_expr()");
8568 void LogArgument::generate_code_expr(expression_struct
*expr
)
8570 switch(logargtype
) {
8572 if (ti
->is_only_specific_value()) {
8573 // use the embedded specific value for code generation
8574 ti
->get_Template()->get_specific_value()->generate_code_log(expr
);
8576 ti
->generate_code(expr
);
8577 expr
->expr
= mputstr(expr
->expr
, ".log()");
8581 val
->generate_code_log(expr
);
8584 val
->generate_code_log_match(expr
);
8587 if (val
->has_single_expr()) {
8588 expr
->expr
= mputprintf(expr
->expr
, "TTCN_Logger::log_event_str(%s)",
8589 val
->get_single_expr().c_str());
8590 } else val
->generate_code_log(expr
);
8593 ref
->generate_code_const_ref(expr
);
8594 expr
->expr
=mputstr(expr
->expr
, ".log()");
8597 size_t str_len
= cstr
->size();
8598 const char *str_ptr
= cstr
->c_str();
8601 // the string is empty: do not generate any code
8603 // the string has one character: use log_char member
8604 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_char('");
8605 expr
->expr
= Code::translate_character(expr
->expr
, *str_ptr
, false);
8606 expr
->expr
= mputstr(expr
->expr
, "')");
8609 // the string has more characters: use log_event_str member
8610 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_event_str(\"");
8611 expr
->expr
= Code::translate_string(expr
->expr
, str_ptr
);
8612 expr
->expr
= mputstr(expr
->expr
, "\")");
8616 FATAL_ERROR("LogArgument::generate_code_expr()");
8620 // =================================
8621 // ===== LogArguments
8622 // =================================
8624 LogArguments::~LogArguments()
8626 for(size_t i
=0; i
<logargs
.size(); i
++) delete logargs
[i
];
8630 LogArguments
*LogArguments::clone() const
8632 FATAL_ERROR("LogArguments::clone");
8635 void LogArguments::add_logarg(LogArgument
*p_logarg
)
8638 FATAL_ERROR("LogArguments::add_logarg()");
8639 logargs
.add(p_logarg
);
8642 void LogArguments::set_my_scope(Scope
*p_scope
)
8644 for(size_t i
=0; i
<logargs
.size(); i
++)
8645 logargs
[i
]->set_my_scope(p_scope
);
8648 void LogArguments::set_fullname(const string
& p_fullname
)
8650 Node::set_fullname(p_fullname
);
8651 for(size_t i
=0; i
<logargs
.size(); i
++)
8652 logargs
[i
]->set_fullname(p_fullname
+".logargs_"+Int2string(i
+1));
8655 void LogArguments::chk()
8657 for(size_t i
=0; i
<logargs
.size(); i
++)
8661 void LogArguments::join_strings()
8663 // points to the previous string argument otherwise it is NULL
8664 LogArgument
*prev_arg
= 0;
8665 for (size_t i
= 0; i
< logargs
.size(); ) {
8666 LogArgument
*arg
= logargs
[i
];
8667 if (arg
->get_type() == LogArgument::L_STR
) {
8668 const string
& str
= arg
->get_str();
8669 if (str
.size() > 0) {
8670 // the current argument is a non-empty string
8672 // append str to prev_arg and drop arg
8673 prev_arg
->append_str(str
);
8675 logargs
.replace(i
, 1);
8676 // don't increment i
8678 // keep it for the next iteration
8683 // the current argument is an empty string
8684 // simply drop it unless it is the only argument
8685 // note: we must distinguish between log() and log("")
8686 if (i
> 0 || logargs
.size() > 1) {
8688 logargs
.replace(i
, 1);
8689 // don't increment i
8693 // the current argument is not a string
8694 // forget the previous arg
8701 void LogArguments::set_code_section(
8702 GovernedSimple::code_section_t p_code_section
)
8704 for (size_t i
= 0; i
< logargs
.size(); i
++)
8705 logargs
[i
]->set_code_section(p_code_section
);
8708 char *LogArguments::generate_code(char *str
)
8710 for(size_t i
=0; i
<logargs
.size(); i
++)
8711 str
=logargs
[i
]->generate_code_log(str
);
8715 void LogArguments::chk_recursions(ReferenceChain
& refch
)
8717 for (size_t i
=0; i
<logargs
.size(); i
++) {
8719 logargs
[i
]->chk_recursions(refch
);
8724 bool LogArguments::has_single_expr()
8726 bool i_have_single_expr
= true;
8727 for (size_t i
=0; i
<logargs
.size(); i
++)
8728 i_have_single_expr
= i_have_single_expr
&& logargs
[i
]->has_single_expr();
8729 return i_have_single_expr
;
8732 void LogArguments::generate_code_expr(expression_struct
*expr
)
8734 expr
->expr
= mputstr(expr
->expr
, "(TTCN_Logger::begin_event_log2str(),");
8735 for(size_t i
=0; i
<logargs
.size(); i
++) {
8736 logargs
[i
]->generate_code_expr(expr
);
8737 expr
->expr
= mputc(expr
->expr
, ','); // comma operator
8739 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::end_event_log2str())");
8742 // =================================
8744 // =================================
8746 IfClause::IfClause(Value
*p_expr
, StatementBlock
*p_block
)
8747 : expr(p_expr
), block(p_block
)
8750 FATAL_ERROR("IfClause::IfClause()");
8753 IfClause::~IfClause()
8759 IfClause
*IfClause::clone() const
8761 FATAL_ERROR("IfClause::clone");
8764 void IfClause::set_my_scope(Scope
*p_scope
)
8766 expr
->set_my_scope(p_scope
);
8767 block
->set_my_scope(p_scope
);
8770 void IfClause::set_fullname(const string
& p_fullname
)
8772 Node::set_fullname(p_fullname
);
8773 expr
->set_fullname(p_fullname
+".expr");
8774 block
->set_fullname(p_fullname
+".block");
8777 bool IfClause::has_receiving_stmt() const
8779 return block
->has_receiving_stmt();
8782 void IfClause::chk(bool& unreach
)
8784 Error_Context
cntxt(this, "In if statement");
8785 if(unreach
) warning("Control never reaches this code because of"
8786 " previous effective condition(s)");
8787 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
8788 if(!expr
->is_unfoldable()) {
8789 if(expr
->get_val_bool()) unreach
=true;
8790 else block
->warning("Control never reaches this code because the"
8791 " conditional expression evaluates to false");
8796 void IfClause::set_code_section(
8797 GovernedSimple::code_section_t p_code_section
)
8799 expr
->set_code_section(p_code_section
);
8800 block
->set_code_section(p_code_section
);
8803 char* IfClause::generate_code(char *str
, size_t& blockcount
,
8804 bool& unreach
, bool& eachfalse
)
8806 if(unreach
) return str
;
8807 if(!expr
->is_unfoldable()) {
8808 if(expr
->get_val_bool()) unreach
=true;
8811 if (!eachfalse
) str
= mputstr(str
, "else ");
8814 str
= mputstr(str
, "{\n");
8817 str
= expr
->update_location_object(str
);
8818 str
= expr
->generate_code_tmp(str
, "if (", blockcount
);
8819 str
= mputstr(str
, ") ");
8822 str
=mputstr(str
, "{\n");
8823 str
=block
->generate_code(str
);
8824 str
=mputstr(str
, "}\n");
8828 void IfClause::ilt_generate_code(ILT
*ilt
, const char *end_label
,
8832 if(!expr
->is_unfoldable()) {
8833 if(expr
->get_val_bool()) unreach
=true;
8836 char*& str
=ilt
->get_out_branches();
8839 size_t blockcount
=0;
8840 label
=mprintf("%s_l%lu",
8841 ilt
->get_my_tmpid().c_str(),
8842 (unsigned long) ilt
->get_new_label_num());
8843 str
=expr
->update_location_object(str
);
8844 str
=expr
->generate_code_tmp(str
, "if(!", blockcount
);
8845 str
=mputprintf(str
, ") goto %s;\n", label
);
8846 while(blockcount
-->0) str
=mputstr(str
, "}\n");
8848 block
->ilt_generate_code(ilt
);
8850 str
=mputprintf(str
, "goto %s;\n%s:\n",
8856 void IfClause::set_parent_path(WithAttribPath
* p_path
) {
8857 block
->set_parent_path(p_path
);
8860 void IfClause::dump(unsigned int level
) const {
8861 DEBUG(level
, "If clause!");
8862 expr
->dump(level
+ 1);
8863 block
->dump(level
+ 1);
8866 // =================================
8868 // =================================
8870 IfClauses::~IfClauses()
8872 for(size_t i
=0; i
<ics
.size(); i
++) delete ics
[i
];
8876 IfClauses
*IfClauses::clone() const
8878 FATAL_ERROR("IfClauses::clone");
8881 void IfClauses::add_ic(IfClause
*p_ic
)
8884 FATAL_ERROR("IfClauses::add_ic()");
8888 void IfClauses::add_front_ic(IfClause
*p_ic
)
8891 FATAL_ERROR("IfClauses::add_front_ic()");
8892 ics
.add_front(p_ic
);
8895 void IfClauses::set_my_scope(Scope
*p_scope
)
8897 for(size_t i
=0; i
<ics
.size(); i
++)
8898 ics
[i
]->set_my_scope(p_scope
);
8901 void IfClauses::set_fullname(const string
& p_fullname
)
8903 Node::set_fullname(p_fullname
);
8904 for(size_t i
=0; i
<ics
.size(); i
++)
8905 ics
[i
]->set_fullname(p_fullname
+".ic_"+Int2string(i
+1));
8908 void IfClauses::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
8910 for(size_t i
=0; i
<ics
.size(); i
++)
8911 ics
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
8914 void IfClauses::set_my_def(Definition
*p_def
)
8916 for(size_t i
=0; i
<ics
.size(); i
++)
8917 ics
[i
]->get_block()->set_my_def(p_def
);
8920 void IfClauses::set_my_ags(AltGuards
*p_ags
)
8922 for(size_t i
=0; i
<ics
.size(); i
++)
8923 ics
[i
]->get_block()->set_my_ags(p_ags
);
8926 void IfClauses::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
8928 for(size_t i
=0; i
<ics
.size(); i
++)
8929 ics
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
8932 StatementBlock::returnstatus_t
IfClauses::has_return
8933 (StatementBlock
*elseblock
) const
8935 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
8936 for (size_t i
= 0; i
< ics
.size(); i
++) {
8937 switch (ics
[i
]->get_block()->has_return()) {
8938 case StatementBlock::RS_NO
:
8939 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
8940 else ret_val
= StatementBlock::RS_NO
;
8942 case StatementBlock::RS_YES
:
8943 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
8944 else ret_val
= StatementBlock::RS_YES
;
8947 return StatementBlock::RS_MAYBE
;
8950 StatementBlock::returnstatus_t else_status
;
8951 if (elseblock
) else_status
= elseblock
->has_return();
8952 else else_status
= StatementBlock::RS_NO
;
8953 switch (else_status
) {
8954 case StatementBlock::RS_NO
:
8955 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
8956 else ret_val
= StatementBlock::RS_NO
;
8958 case StatementBlock::RS_YES
:
8959 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
8960 else ret_val
= StatementBlock::RS_YES
;
8963 return StatementBlock::RS_MAYBE
;
8968 bool IfClauses::has_receiving_stmt() const
8970 for(size_t i
=0; i
<ics
.size(); i
++)
8971 if(ics
[i
]->has_receiving_stmt()) return true;
8975 void IfClauses::chk(bool& unreach
)
8977 for(size_t i
=0; i
<ics
.size(); i
++)
8978 ics
[i
]->chk(unreach
);
8981 void IfClauses::chk_allowed_interleave()
8983 for (size_t i
= 0; i
< ics
.size(); i
++)
8984 ics
[i
]->get_block()->chk_allowed_interleave();
8987 void IfClauses::set_code_section(
8988 GovernedSimple::code_section_t p_code_section
)
8990 for (size_t i
= 0; i
< ics
.size(); i
++)
8991 ics
[i
]->set_code_section(p_code_section
);
8994 char* IfClauses::generate_code(char *str
, size_t& blockcount
,
8995 bool& unreach
, bool& eachfalse
)
8997 for(size_t i
=0; i
<ics
.size(); i
++) {
8998 if(unreach
) return str
;
8999 str
=ics
[i
]->generate_code(str
, blockcount
, unreach
, eachfalse
);
9004 void IfClauses::ilt_generate_code(ILT
*ilt
, const char *end_label
,
9007 for(size_t i
=0; i
<ics
.size(); i
++) {
9009 ics
[i
]->ilt_generate_code(ilt
, end_label
, unreach
);
9013 void IfClauses::set_parent_path(WithAttribPath
* p_path
) {
9014 for (size_t i
= 0; i
< ics
.size(); i
++)
9015 ics
[i
]->set_parent_path(p_path
);
9018 void IfClauses::dump(unsigned int level
) const {
9019 DEBUG(level
, "%lu if clauses", (unsigned long)ics
.size());
9020 for (size_t i
= 0; i
< ics
.size(); i
++)
9021 ics
[i
]->dump(level
+ 1);
9024 // =================================
9026 // =================================
9028 SelectCase::SelectCase(TemplateInstances
*p_tis
, StatementBlock
*p_block
)
9029 : tis(p_tis
), block(p_block
)
9032 FATAL_ERROR("SelectCase::SelectCase()");
9035 SelectCase::~SelectCase()
9041 SelectCase
*SelectCase::clone() const
9043 FATAL_ERROR("SelectCase::clone");
9046 void SelectCase::set_my_scope(Scope
*p_scope
)
9048 if(tis
) tis
->set_my_scope(p_scope
);
9049 block
->set_my_scope(p_scope
);
9052 void SelectCase::set_fullname(const string
& p_fullname
)
9054 Node::set_fullname(p_fullname
);
9055 if(tis
) tis
->set_fullname(p_fullname
+".tis");
9056 block
->set_fullname(p_fullname
+".block");
9060 void SelectCase::chk(Type
*p_gov
, bool& unreach
)
9062 Error_Context
cntxt(this, "In select case statement");
9063 if(unreach
) warning("Control never reaches this code because of"
9064 " previous effective case(s)");
9066 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++)
9067 tis
->get_ti_byIndex(i
)->chk(p_gov
);
9068 else unreach
=true; // else statement
9072 void SelectCase::set_code_section
9073 (GovernedSimple::code_section_t p_code_section
)
9075 if(tis
) tis
->set_code_section(p_code_section
);
9076 block
->set_code_section(p_code_section
);
9080 char* SelectCase::generate_code_if(char *str
, const char *tmp_prefix
,
9081 const char *expr_name
, size_t idx
,
9084 if(unreach
) return str
;
9086 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++) {
9087 TemplateInstance
*ti
=tis
->get_ti_byIndex(i
);
9088 Template
*tb
=ti
->get_Template();
9089 bool specval
= tb
->is_Value();
9090 expression_struct exprs
;
9091 Code::init_expr(&exprs
);
9092 if (!specval
) ti
->generate_code(&exprs
);
9093 else if (tb
->get_templatetype() == Template::SPECIFIC_VALUE
) {
9094 tb
->get_specific_value()->generate_code_expr_mandatory(&exprs
);
9097 Value
* val
= tb
->get_Value();
9098 val
->generate_code_expr_mandatory(&exprs
);
9101 str
=tb
->update_location_object(str
);
9102 if(!exprs
.preamble
&& !exprs
.postamble
) {
9103 str
=mputstr(str
, "if(");
9105 str
=mputprintf(str
, "%s.match(%s)", exprs
.expr
, expr_name
);
9106 else str
=mputprintf(str
, "%s == %s", expr_name
, exprs
.expr
);
9107 str
=mputprintf(str
, ") goto %s_%lu;\n", tmp_prefix
,
9108 (unsigned long) idx
);
9109 Code::free_expr(&exprs
);
9112 str
=mputprintf(str
, "{\nboolean %s_%lub;\n", tmp_prefix
,
9113 (unsigned long) idx
);
9115 exprs
.expr
=mprintf("%s_%lub = ", tmp_prefix
, (unsigned long) idx
);
9117 exprs
.expr
=mputprintf(exprs
.expr
, "%s.match(%s)", s
, expr_name
);
9118 else exprs
.expr
=mputprintf(exprs
.expr
, "(%s == %s)", expr_name
, s
);
9120 str
=Code::merge_free_expr(str
, &exprs
);
9121 str
=mputprintf(str
, "if(%s_%lub) goto %s_%lu;\n}\n",
9122 tmp_prefix
, (unsigned long) idx
, tmp_prefix
, (unsigned long) idx
);
9127 unreach
=true; // else statement
9128 str
=mputprintf(str
, "goto %s_%lu;\n", tmp_prefix
, (unsigned long) idx
);
9134 char* SelectCase::generate_code_stmt(char *str
, const char *tmp_prefix
,
9135 size_t idx
, bool& unreach
)
9137 if(unreach
) return str
;
9138 if(!tis
) unreach
=true;
9139 str
=mputprintf(str
, "%s_%lu:\n{\n", tmp_prefix
, (unsigned long) idx
);
9140 str
=block
->generate_code(str
);
9141 str
=mputprintf(str
, "goto %s_end;\n}\n", tmp_prefix
);
9145 void SelectCase::ilt_generate_code_stmt(ILT
*ilt
, const char *tmp_prefix
,
9146 size_t idx
, bool& unreach
)
9149 if(!tis
) unreach
=true;
9150 char*& str
=ilt
->get_out_branches();
9151 str
=mputprintf(str
, "%s_%lu:\n", tmp_prefix
, (unsigned long) idx
);
9152 bool has_recv
=block
->has_receiving_stmt();
9154 str
=mputstr(str
, "{\n");
9155 str
=block
->generate_code(str
);
9157 else block
->ilt_generate_code(ilt
);
9158 str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9160 str
=mputstr(str
, "}\n");
9163 void SelectCase::set_parent_path(WithAttribPath
* p_path
) {
9164 block
->set_parent_path(p_path
);
9167 // =================================
9168 // ===== SelectCases
9169 // =================================
9171 SelectCases::~SelectCases()
9173 for(size_t i
=0; i
<scs
.size(); i
++) delete scs
[i
];
9177 SelectCases
*SelectCases::clone() const
9179 FATAL_ERROR("SelectCases::clone");
9182 void SelectCases::add_sc(SelectCase
*p_sc
)
9185 FATAL_ERROR("SelectCases::add_sc()");
9189 void SelectCases::set_my_scope(Scope
*p_scope
)
9191 for(size_t i
=0; i
<scs
.size(); i
++)
9192 scs
[i
]->set_my_scope(p_scope
);
9195 void SelectCases::set_fullname(const string
& p_fullname
)
9197 Node::set_fullname(p_fullname
);
9198 for(size_t i
=0; i
<scs
.size(); i
++)
9199 scs
[i
]->set_fullname(p_fullname
+".sc_"+Int2string(i
+1));
9202 void SelectCases::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9204 for(size_t i
=0; i
<scs
.size(); i
++)
9205 scs
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9208 void SelectCases::set_my_def(Definition
*p_def
)
9210 for(size_t i
=0; i
<scs
.size(); i
++)
9211 scs
[i
]->get_block()->set_my_def(p_def
);
9214 void SelectCases::set_my_ags(AltGuards
*p_ags
)
9216 for(size_t i
=0; i
<scs
.size(); i
++)
9217 scs
[i
]->get_block()->set_my_ags(p_ags
);
9220 void SelectCases::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9222 for(size_t i
=0; i
<scs
.size(); i
++)
9223 scs
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9226 StatementBlock::returnstatus_t
SelectCases::has_return() const
9228 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9229 bool has_else
= false;
9230 for (size_t i
= 0; i
< scs
.size(); i
++) {
9231 SelectCase
*sc
= scs
[i
];
9232 switch (sc
->get_block()->has_return()) {
9233 case StatementBlock::RS_NO
:
9234 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9235 else ret_val
= StatementBlock::RS_NO
;
9237 case StatementBlock::RS_YES
:
9238 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9239 else ret_val
= StatementBlock::RS_YES
;
9242 return StatementBlock::RS_MAYBE
;
9244 if (!sc
->get_tis()) {
9249 if (!has_else
&& ret_val
== StatementBlock::RS_YES
)
9250 return StatementBlock::RS_MAYBE
;
9251 else return ret_val
;
9254 bool SelectCases::has_receiving_stmt() const
9256 for(size_t i
=0; i
<scs
.size(); i
++)
9257 if(scs
[i
]->get_block()->has_receiving_stmt()) return true;
9262 void SelectCases::chk(Type
*p_gov
)
9265 for(size_t i
=0; i
<scs
.size(); i
++)
9266 scs
[i
]->chk(p_gov
, unreach
);
9269 void SelectCases::chk_allowed_interleave()
9271 for (size_t i
= 0; i
< scs
.size(); i
++)
9272 scs
[i
]->get_block()->chk_allowed_interleave();
9275 void SelectCases::set_code_section
9276 (GovernedSimple::code_section_t p_code_section
)
9278 for(size_t i
=0; i
<scs
.size(); i
++)
9279 scs
[i
]->set_code_section(p_code_section
);
9282 char* SelectCases::generate_code(char *str
, const char *tmp_prefix
,
9283 const char *expr_name
)
9286 for(size_t i
=0; i
<scs
.size(); i
++) {
9287 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9290 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9292 for(size_t i
=0; i
<scs
.size(); i
++) {
9293 str
=scs
[i
]->generate_code_stmt(str
, tmp_prefix
, i
, unreach
);
9296 str
=mputprintf(str
, "%s_end: /* empty */;\n", tmp_prefix
);
9300 void SelectCases::ilt_generate_code(ILT
*ilt
, const char *tmp_prefix
,
9301 const char *expr_init
,
9302 const char *expr_name
)
9304 char*& str
=ilt
->get_out_branches();
9305 if(strlen(expr_init
)) {
9306 str
=mputstr(str
, "{\n"); // (1)
9307 str
=mputstr(str
, expr_init
);
9310 for(size_t i
=0; i
<scs
.size(); i
++) {
9312 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9314 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9315 if(strlen(expr_init
)) str
=mputstr(str
, "}\n"); // (1)
9317 for(size_t i
=0; i
<scs
.size(); i
++) {
9319 scs
[i
]->ilt_generate_code_stmt(ilt
, tmp_prefix
, i
, unreach
);
9321 str
=mputprintf(str
, "%s_end:\n", tmp_prefix
);
9324 void SelectCases::set_parent_path(WithAttribPath
* p_path
) {
9325 for (size_t i
= 0; i
< scs
.size(); i
++)
9326 scs
[i
]->set_parent_path(p_path
);
9329 // =================================
9331 // =================================
9333 AltGuard::AltGuard(Value
*p_expr
, Statement
*p_stmt
, StatementBlock
*p_block
)
9334 : altguardtype(AG_OP
), expr(p_expr
), stmt(p_stmt
), block(p_block
)
9336 if (!p_stmt
|| !p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9339 AltGuard::AltGuard(Value
*p_expr
, Ref_pard
*p_ref
, StatementBlock
*p_block
)
9340 : altguardtype(AG_REF
), expr(p_expr
), ref(p_ref
), block(p_block
)
9342 if (!p_ref
) FATAL_ERROR("AltGuard::AltGuard()");
9345 AltGuard::AltGuard(Value
*p_expr
, Value
*p_v
,
9346 Ttcn::TemplateInstances
*p_t_list
, StatementBlock
*p_block
)
9347 : altguardtype(AG_INVOKE
), expr(p_expr
)
9350 if(!p_v
|| !p_t_list
) FATAL_ERROR("AltGuard::AltGuard()");
9352 invoke
.t_list
= p_t_list
;
9356 AltGuard::AltGuard(StatementBlock
*p_block
)
9357 : altguardtype(AG_ELSE
), expr(0), dummy(0), block(p_block
)
9359 if (!p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9362 AltGuard::~AltGuard()
9364 switch(altguardtype
) {
9378 delete invoke
.t_list
;
9379 delete invoke
.ap_list
;
9386 FATAL_ERROR("AltGuard::~AltGuard()");
9390 AltGuard
*AltGuard::clone() const
9392 FATAL_ERROR("AltGuard::clone");
9395 void AltGuard::set_my_scope(Scope
*p_scope
)
9397 switch(altguardtype
) {
9399 if(expr
) expr
->set_my_scope(p_scope
);
9400 stmt
->set_my_scope(p_scope
);
9401 block
->set_my_scope(p_scope
);
9404 if(expr
) expr
->set_my_scope(p_scope
);
9405 ref
->set_my_scope(p_scope
);
9406 if(block
) block
->set_my_scope(p_scope
);
9409 if(expr
) expr
->set_my_scope(p_scope
);
9410 invoke
.v
->set_my_scope(p_scope
);
9411 if(invoke
.t_list
) invoke
.t_list
->set_my_scope(p_scope
);
9412 if(invoke
.ap_list
) invoke
.ap_list
->set_my_scope(p_scope
);
9413 if(block
) block
->set_my_scope(p_scope
);
9416 block
->set_my_scope(p_scope
);
9419 FATAL_ERROR("AltGuard::set_my_scope()");
9423 void AltGuard::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9425 switch(altguardtype
) {
9427 stmt
->set_my_sb(p_sb
, p_index
);
9428 block
->set_my_sb(p_sb
, p_index
);
9431 if(block
) block
->set_my_sb(p_sb
, p_index
);
9434 if(block
) block
->set_my_sb(p_sb
, p_index
);
9437 block
->set_my_sb(p_sb
, p_index
);
9440 FATAL_ERROR("AltGuard::set_my_sb()");
9444 void AltGuard::set_fullname(const string
& p_fullname
)
9446 Node::set_fullname(p_fullname
);
9447 switch(altguardtype
) {
9449 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9450 stmt
->set_fullname(p_fullname
+".stmt");
9451 block
->set_fullname(p_fullname
+".block");
9454 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9455 ref
->set_fullname(p_fullname
+".ref");
9456 if(block
) block
->set_fullname(p_fullname
+".block");
9459 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9460 invoke
.v
->set_fullname(p_fullname
+".function");
9461 if(invoke
.t_list
) invoke
.t_list
->set_fullname(p_fullname
+".argument");
9462 if(invoke
.ap_list
) invoke
.ap_list
->set_fullname(p_fullname
+".argument");
9463 if(block
) block
->set_fullname(p_fullname
+".block");
9466 block
->set_fullname(p_fullname
+".elseblock");
9469 FATAL_ERROR("AltGuard::set_fullname()");
9473 Value
*AltGuard::get_guard_expr() const
9475 if (altguardtype
== AG_ELSE
) FATAL_ERROR("AltGuard::get_guard_expr()");
9479 Ref_pard
*AltGuard::get_guard_ref() const
9481 if (altguardtype
!= AG_REF
) FATAL_ERROR("AltGuard::get_guard_ref()");
9485 Statement
*AltGuard::get_guard_stmt() const
9487 if (altguardtype
!= AG_OP
) FATAL_ERROR("AltGuard::get_guard_stmt()");
9491 void AltGuard::set_my_def(Definition
*p_def
)
9493 switch(altguardtype
) {
9495 stmt
->set_my_def(p_def
);
9496 block
->set_my_def(p_def
);
9499 if(block
) block
->set_my_def(p_def
);
9502 if(block
) block
->set_my_def(p_def
);
9505 block
->set_my_def(p_def
);
9508 FATAL_ERROR("AltGuard::set_my_def()");
9512 void AltGuard::set_my_ags(AltGuards
*p_ags
)
9514 switch (altguardtype
) {
9516 block
->set_my_ags(p_ags
);
9519 if (block
) block
->set_my_ags(p_ags
);
9522 if (block
) block
->set_my_ags(p_ags
);
9525 block
->set_my_ags(p_ags
);
9528 FATAL_ERROR("AltGuard::set_my_ags()");
9532 void AltGuard::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9534 switch (altguardtype
) {
9536 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9539 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9542 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9545 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9548 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9552 void AltGuard::chk()
9554 switch(altguardtype
) {
9557 Error_Context
cntxt(expr
, "In guard expression");
9558 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9561 Error_Context
cntxt(stmt
, "In guard operation");
9568 Error_Context
cntxt(expr
, "In guard expression");
9569 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9572 Error_Context
cntxt(ref
, "In guard statement");
9573 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
9575 if (t_ass
->get_asstype() == Common::Assignment::A_ALTSTEP
) {
9576 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *ref
, "call");
9578 ref
->error("Reference to an altstep was expected instead of %s",
9579 t_ass
->get_description().c_str());
9583 if (block
) block
->chk();
9587 Error_Context
cntxt(expr
, "In guard expression");
9588 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9591 if (!invoke
.t_list
) return; //already_checked
9592 Error_Context
cntxt(ref
, "In guard statement");
9593 switch(invoke
.v
->get_valuetype()){
9594 case Value::V_REFER
:
9596 "A value of an altstep type was expected "
9597 "in the argument instead of a `refers' statement,"
9598 " which does not specify any function type");
9600 case Value::V_TTCN3_NULL
:
9602 "A value of an altstep type was expected "
9603 "in the argument instead of a `null' value,"
9604 " which does not specify any function type");
9609 Type
*t
= invoke
.v
->get_expr_governor_last();
9611 switch (t
->get_typetype()) {
9614 case Type::T_ALTSTEP
:
9617 invoke
.v
->error("A value of type altstep was expected instead of "
9618 "`%s'", t
->get_typename().c_str());
9621 invoke
.v
->get_my_scope()->chk_runs_on_clause(t
, *this, "call");
9622 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
9623 invoke
.ap_list
= new Ttcn::ActualParList
;
9624 bool is_erroneous
= fp_list
->chk_actual_parlist(invoke
.t_list
,
9626 delete invoke
.t_list
;
9629 delete invoke
.ap_list
;
9632 invoke
.ap_list
->set_fullname(get_fullname());
9633 invoke
.ap_list
->set_my_scope(invoke
.v
->get_my_scope());
9636 if (block
) block
->chk();
9640 Error_Context
cntxt(this, "In else branch");
9642 Statement
*first_stmt
= block
->get_first_stmt();
9643 if (first_stmt
&& first_stmt
->get_statementtype() ==
9644 Statement::S_REPEAT
)
9645 first_stmt
->warning("The first statement of the [else] branch is a "
9646 "repeat statement. This will result in busy waiting");
9650 FATAL_ERROR("AltGuard::chk()");
9654 void AltGuard::set_code_section(
9655 GovernedSimple::code_section_t p_code_section
)
9657 switch(altguardtype
) {
9659 if (expr
) expr
->set_code_section(p_code_section
);
9660 stmt
->set_code_section(p_code_section
);
9661 block
->set_code_section(p_code_section
);
9664 if (expr
) expr
->set_code_section(p_code_section
);
9665 ref
->set_code_section(p_code_section
);
9666 if (block
) block
->set_code_section(p_code_section
);
9669 if (expr
) expr
->set_code_section(p_code_section
);
9670 invoke
.v
->set_code_section(p_code_section
);
9671 if(invoke
.t_list
) invoke
.t_list
->set_code_section(p_code_section
);
9673 for(size_t i
= 0; i
< invoke
.ap_list
->get_nof_pars(); i
++)
9674 invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
9675 if (block
) block
->set_code_section(p_code_section
);
9678 block
->set_code_section(p_code_section
);
9681 FATAL_ERROR("AltGuard::set_fullname()");
9685 void AltGuard::generate_code_invoke_instance(expression_struct
*p_expr
)
9687 if (altguardtype
!= AG_INVOKE
)
9688 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9689 Value
*last_v
= invoke
.v
->get_value_refd_last();
9690 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
9691 Common::Assignment
*altstep
= last_v
->get_refd_fat();
9692 p_expr
->expr
= mputprintf(p_expr
->expr
, "%s_instance(",
9693 altstep
->get_genname_from_scope(invoke
.v
->get_my_scope()).c_str());
9694 invoke
.ap_list
->generate_code_alias(p_expr
,
9695 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9697 invoke
.v
->generate_code_expr_mandatory(p_expr
);
9698 p_expr
->expr
= mputstr(p_expr
->expr
, ".invoke(");
9699 Type
* gov_last
= invoke
.v
->get_expr_governor_last();
9700 invoke
.ap_list
->generate_code_alias(p_expr
, 0,
9701 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
9703 p_expr
->expr
= mputc(p_expr
->expr
, ')');
9706 // =================================
9708 // =================================
9710 AltGuards::~AltGuards()
9712 for(size_t i
=0; i
<ags
.size(); i
++) delete ags
[i
];
9715 delete il_label_end
;
9718 AltGuards
*AltGuards::clone() const
9720 FATAL_ERROR("AltGuards::clone");
9723 void AltGuards::add_ag(AltGuard
*p_ag
)
9726 FATAL_ERROR("AltGuards::add_ag()");
9730 void AltGuards::set_my_scope(Scope
*p_scope
)
9733 for(size_t i
=0; i
<ags
.size(); i
++)
9734 ags
[i
]->set_my_scope(p_scope
);
9737 void AltGuards::set_fullname(const string
& p_fullname
)
9739 Node::set_fullname(p_fullname
);
9740 for(size_t i
=0; i
<ags
.size(); i
++)
9741 ags
[i
]->set_fullname(p_fullname
+".ag_"+Int2string(i
+1));
9744 void AltGuards::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9746 for(size_t i
=0; i
<ags
.size(); i
++)
9747 ags
[i
]->set_my_sb(p_sb
, p_index
);
9750 void AltGuards::set_my_def(Definition
*p_def
)
9752 for(size_t i
=0; i
<ags
.size(); i
++)
9753 ags
[i
]->set_my_def(p_def
);
9756 void AltGuards::set_my_ags(AltGuards
*p_ags
)
9758 for(size_t i
=0; i
<ags
.size(); i
++)
9759 ags
[i
]->set_my_ags(p_ags
);
9762 void AltGuards::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9764 for(size_t i
=0; i
<ags
.size(); i
++)
9765 ags
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9768 bool AltGuards::has_else() const
9770 for (size_t i
= 0; i
< ags
.size(); i
++)
9771 if (ags
[i
]->get_type() == AltGuard::AG_ELSE
) return true;
9775 StatementBlock::returnstatus_t
AltGuards::has_return() const
9777 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9778 for (size_t i
= 0; i
< ags
.size(); i
++) {
9779 AltGuard
*ag
= ags
[i
];
9780 StatementBlock
*block
= ag
->get_block();
9781 StatementBlock::returnstatus_t block_status
;
9782 if (block
) block_status
= block
->has_return();
9783 else block_status
= StatementBlock::RS_NO
;
9784 switch (block_status
) {
9785 case StatementBlock::RS_NO
:
9786 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9787 else ret_val
= StatementBlock::RS_NO
;
9789 case StatementBlock::RS_YES
:
9790 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9791 else ret_val
= StatementBlock::RS_YES
;
9794 return StatementBlock::RS_MAYBE
;
9796 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9801 bool AltGuards::has_receiving_stmt() const
9803 for(size_t i
=0; i
<ags
.size(); i
++)
9804 if(ags
[i
]->get_block()->has_receiving_stmt()) return true;
9808 void AltGuards::chk()
9810 bool unreach_found
= false;
9811 size_t nof_ags
= ags
.size();
9812 AltGuard
*prev_ag
= 0;
9813 for (size_t i
= 0; i
< nof_ags
; i
++) {
9814 AltGuard
*ag
= ags
[i
];
9816 if (!unreach_found
&& prev_ag
&&
9817 prev_ag
->get_type() == AltGuard::AG_ELSE
) {
9818 ag
->warning("Control never reaches this branch of alternative "
9819 "because of the previous [else] branch");
9820 unreach_found
= true;
9826 void AltGuards::chk_allowed_interleave()
9828 for (size_t i
= 0; i
< ags
.size(); i
++) {
9829 AltGuard
*ag
= ags
[i
];
9830 switch (ag
->get_type()) {
9831 case AltGuard::AG_OP
:
9833 case AltGuard::AG_REF
:
9834 case AltGuard::AG_INVOKE
:
9835 ag
->error("Invocation of an altstep is not allowed within an "
9836 "interleave statement");
9838 case AltGuard::AG_ELSE
:
9839 ag
->error("Else branch of an alternative is not allowed within an "
9840 "interleave statement");
9843 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
9845 ag
->get_block()->chk_allowed_interleave();
9849 void AltGuards::set_code_section(
9850 GovernedSimple::code_section_t p_code_section
)
9852 for (size_t i
= 0; i
< ags
.size(); i
++)
9853 ags
[i
]->set_code_section(p_code_section
);
9856 char *AltGuards::generate_code_alt(char *str
, const Location
& loc
)
9858 bool label_needed
= has_repeat
, has_else_branch
= false;
9859 for (size_t i
= 0; i
< ags
.size(); i
++) {
9860 AltGuard
*ag
= ags
[i
];
9861 switch (ag
->get_type()) {
9862 case AltGuard::AG_OP
:
9863 // trigger may return ALT_REPEAT
9864 if (ag
->get_guard_stmt()->can_repeat()) label_needed
= true;
9866 case AltGuard::AG_REF
:
9867 case AltGuard::AG_INVOKE
:
9868 // an altstep may return ALT_REPEAT
9869 label_needed
= true;
9871 case AltGuard::AG_ELSE
:
9872 has_else_branch
= true;
9875 FATAL_ERROR("AltGuards::generate_code_alt()");
9877 if (has_else_branch
) break;
9879 // if there is no [else] branch the defaults may return ALT_REPEAT
9880 if (!has_else_branch
) label_needed
= true;
9881 // opening bracket of the statement block
9882 str
= mputstr(str
, "{\n");
9883 // the label name is also used for prefixing local variables
9884 if (!my_scope
|| label
) FATAL_ERROR("AltGuards::generate_code_alt()");
9885 label
= new string(my_scope
->get_scope_mod_gen()->get_temporary_id());
9886 const char *label_str
= label
->c_str();
9887 if (label_needed
) str
= mputprintf(str
, "%s:\n", label_str
);
9888 // temporary variables used for caching of status codes
9889 for (size_t i
= 0; i
< ags
.size(); i
++) {
9890 AltGuard
*ag
= ags
[i
];
9891 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9892 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
9893 label_str
, (unsigned long) i
,
9894 ag
->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
9896 if (!has_else_branch
) {
9897 str
= mputprintf(str
, "alt_status %s_default_flag = ALT_MAYBE;\n",
9900 // the first snapshot is taken in non-blocking mode
9901 // and opening infinite for() loop
9902 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
9904 for (size_t i
= 0; i
< ags
.size(); i
++) {
9905 AltGuard
*ag
= ags
[i
];
9906 AltGuard::altguardtype_t agtype
= ag
->get_type();
9907 if (agtype
== AltGuard::AG_ELSE
) {
9908 // an else branch was found
9909 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
9910 StatementBlock
*block
= ag
->get_block();
9911 if (block
->get_nof_stmts() > 0) {
9912 str
= mputstr(str
, "{\n");
9913 str
= block
->generate_code(str
);
9914 str
= mputstr(str
, "}\n");
9916 // jump out of the infinite for() loop
9917 if (block
->has_return() != StatementBlock::RS_YES
)
9918 str
= mputstr(str
, "break;\n");
9919 // do not generate code for further branches
9922 Value
*guard_expr
= ag
->get_guard_expr();
9924 // the branch has a boolean guard expression
9925 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
9926 label_str
, (unsigned long) i
);
9927 str
= guard_expr
->update_location_object(str
);
9928 expression_struct expr
;
9929 Code::init_expr(&expr
);
9930 guard_expr
->generate_code_expr(&expr
);
9931 str
= mputstr(str
, expr
.preamble
);
9932 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
9933 "else %s_alt_flag_%lu = ALT_NO;\n", expr
.expr
, label_str
,
9934 (unsigned long) i
, label_str
, (unsigned long) i
);
9935 str
= mputstr(str
, expr
.postamble
);
9936 Code::free_expr(&expr
);
9937 str
= mputstr(str
, "}\n");
9939 // evaluation of guard operation or altstep
9940 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
9941 label_str
, (unsigned long) i
);
9942 // indicates whether the guard operation might return ALT_REPEAT
9944 expression_struct expr
;
9945 Code::init_expr(&expr
);
9946 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
9949 case AltGuard::AG_OP
: {
9950 // the guard operation is a receiving statement
9951 Statement
*stmt
= ag
->get_guard_stmt();
9952 str
= stmt
->update_location_object(str
);
9953 stmt
->generate_code_expr(&expr
);
9954 can_repeat
= stmt
->can_repeat();
9956 case AltGuard::AG_REF
: {
9957 // the guard operation is an altstep instance
9958 Ref_pard
*ref
= ag
->get_guard_ref();
9959 str
= ref
->update_location_object(str
);
9960 Common::Assignment
*altstep
= ref
->get_refd_assignment();
9961 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
9962 altstep
->get_genname_from_scope(my_scope
).c_str());
9963 ref
->get_parlist()->generate_code_alias(&expr
,
9964 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9965 expr
.expr
= mputc(expr
.expr
, ')');
9968 case AltGuard::AG_INVOKE
: {
9969 // the guard operation is an altstep invocation
9970 str
= ag
->update_location_object(str
);
9971 ag
->generate_code_invoke_instance(&expr
);
9975 FATAL_ERROR("AltGuards::generate_code_alt()");
9977 str
= Code::merge_free_expr(str
, &expr
);
9979 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
9980 label_str
, (unsigned long) i
, label_str
);
9982 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
9983 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
9984 label_str
, (unsigned long) i
);
9986 // execution of statement block if the guard was successful
9987 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
9989 StatementBlock
*block
= ag
->get_block();
9990 if (block
&& block
->get_nof_stmts() > 0) {
9991 str
= mputstr(str
, "{\n");
9992 str
= block
->generate_code(str
);
9993 if (block
->has_return() != StatementBlock::RS_YES
)
9994 str
= mputstr(str
, "break;\n");
9995 str
= mputstr(str
, "}\n");
9996 } else str
= mputstr(str
, "break;\n");
9997 // closing of if() block
9998 str
= mputstr(str
, "}\n");
10001 if (!has_else_branch
) {
10002 // calling of defaults
10003 str
= mputprintf(str
, "if (%s_default_flag == ALT_MAYBE) {\n"
10004 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10005 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10007 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10009 label_str
, label_str
, label_str
, label_str
, label_str
, label_str
);
10010 str
= loc
.update_location_object(str
);
10011 // error handling and taking the next snapshot in blocking mode
10012 str
= mputstr(str
, "if (");
10013 for (size_t i
= 0; i
< ags
.size(); i
++)
10014 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO && ", label_str
,
10015 (unsigned long) i
);
10016 str
= mputprintf(str
,"%s_default_flag == ALT_NO) "
10017 "TTCN_error(\"None of the branches can be chosen in the alt "
10018 "statement in file ", label_str
);
10019 str
= Code::translate_string(str
, loc
.get_filename());
10020 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10021 if (first_line
< last_line
) str
= mputprintf(str
,
10022 " between lines %d and %d", first_line
, last_line
);
10023 else str
= mputprintf(str
, ", line %d", first_line
);
10024 str
= mputstr(str
, ".\");\n"
10025 "TTCN_Snapshot::take_new(TRUE);\n");
10027 // end of for() statement and the statement block
10028 str
= mputstr(str
, "}\n"
10033 char *AltGuards::generate_code_altstep(char *str
)
10035 if (!my_scope
) FATAL_ERROR("AltGuards::generate_code_altstep()");
10036 Common::Module
*my_mod
= my_scope
->get_scope_mod_gen();
10037 bool has_else_branch
= has_else();
10038 if (!has_else_branch
) {
10039 str
= mputstr(str
, "alt_status ret_val = ALT_NO;\n");
10041 for (size_t i
= 0; i
< ags
.size(); i
++) {
10042 AltGuard
*ag
= ags
[i
];
10043 AltGuard::altguardtype_t agtype
= ag
->get_type();
10044 if (agtype
== AltGuard::AG_ELSE
) {
10045 // an else branch was found
10046 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10047 StatementBlock
*block
= ag
->get_block();
10048 if (block
->get_nof_stmts() > 0) {
10049 str
= mputstr(str
, "{\n");
10050 str
= block
->generate_code(str
);
10051 str
= mputstr(str
, "}\n");
10053 if (block
->has_return() != StatementBlock::RS_YES
)
10054 str
= mputstr(str
, "return ALT_YES;\n");
10055 // do not generate code for further branches
10058 size_t blockcount
= 0;
10059 Value
*guard_expr
= ag
->get_guard_expr();
10061 // the branch has a boolean guard expression
10062 str
= guard_expr
->update_location_object(str
);
10063 str
= guard_expr
->generate_code_tmp(str
, "if (", blockcount
);
10064 str
= mputstr(str
, ") {\n");
10067 // indicates whether the guard operation might return ALT_REPEAT
10069 expression_struct expr
;
10070 Code::init_expr(&expr
);
10072 case AltGuard::AG_OP
: {
10073 // the guard operation is a receiving statement
10074 Statement
*stmt
= ag
->get_guard_stmt();
10075 str
= stmt
->update_location_object(str
);
10076 stmt
->generate_code_expr(&expr
);
10077 can_repeat
= stmt
->can_repeat();
10079 case AltGuard::AG_REF
: {
10080 // the guard operation is an altstep instance
10081 Ref_pard
*ref
= ag
->get_guard_ref();
10082 str
= ref
->update_location_object(str
);
10083 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10084 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10085 altstep
->get_genname_from_scope(my_scope
).c_str());
10086 ref
->get_parlist()->generate_code_alias(&expr
,
10087 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10088 expr
.expr
= mputc(expr
.expr
, ')');
10091 case AltGuard::AG_INVOKE
: {
10092 str
= ag
->update_location_object(str
);
10093 ag
->generate_code_invoke_instance(&expr
);
10097 FATAL_ERROR("AltGuards::generate_code_altstep()");
10099 if (expr
.preamble
|| expr
.postamble
) {
10100 if (blockcount
== 0) {
10101 // open a statement block if it is not done so far
10102 str
= mputstr(str
, "{\n");
10105 const string
& tmp_id
= my_mod
->get_temporary_id();
10106 const char *tmp_id_str
= tmp_id
.c_str();
10107 str
= mputprintf(str
, "alt_status %s;\n"
10108 "{\n", tmp_id_str
);
10109 str
= mputstr(str
, expr
.preamble
);
10110 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, expr
.expr
);
10111 str
= mputstr(str
, expr
.postamble
);
10112 str
= mputprintf(str
, "}\n"
10113 "switch (%s) {\n", tmp_id_str
);
10115 str
= mputprintf(str
, "switch (%s) {\n", expr
.expr
);
10117 Code::free_expr(&expr
);
10118 str
= mputstr(str
, "case ALT_YES:\n");
10119 StatementBlock
*block
= ag
->get_block();
10120 if (block
&& block
->get_nof_stmts() > 0) {
10121 str
= mputstr(str
, "{\n");
10122 str
= block
->generate_code(str
);
10123 str
= mputstr(str
, "}\n");
10125 if (!block
|| block
->has_return() != StatementBlock::RS_YES
)
10126 str
= mputstr(str
, "return ALT_YES;\n");
10128 str
= mputstr(str
, "case ALT_REPEAT:\n"
10129 "return ALT_REPEAT;\n");
10130 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10131 str
= mputprintf(str
, "case ALT_BREAK:\n"
10132 "return ALT_BREAK;\n");
10134 if (!has_else_branch
)
10135 str
= mputstr(str
, "case ALT_MAYBE:\n"
10136 "ret_val = ALT_MAYBE;\n");
10137 str
= mputstr(str
, "default:\n"
10140 // closing statement blocks
10141 for ( ; blockcount
> 0; blockcount
--) str
= mputstr(str
, "}\n");
10144 if (!has_else_branch
) str
= mputstr(str
, "return ret_val;\n");
10148 char* AltGuards::generate_code_call_body(char *str
, const Location
& loc
,
10149 const string
& temp_id
, bool in_interleave
)
10151 if (label
) FATAL_ERROR("AltGuards::generate_code_call_body()");
10152 label
= new string(temp_id
);
10153 const char *label_str
= temp_id
.c_str();
10154 // label is needed only if there is a repeat statement in the branches
10155 if (has_repeat
) str
= mputprintf(str
, "%s:\n", label_str
);
10156 // temporary variables used for caching of status codes
10157 for (size_t i
= 0; i
< ags
.size(); i
++)
10158 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10159 label_str
, (unsigned long) i
,
10160 ags
[i
]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10161 str
= loc
.update_location_object(str
);
10162 // the first snapshot is taken in non-blocking mode
10163 // and opening infinite for() loop
10164 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10165 "for ( ; ; ) {\n"); // (1)
10166 for (size_t i
= 0; i
< ags
.size(); i
++) {
10167 AltGuard
*ag
= ags
[i
];
10168 if (ag
->get_type() != AltGuard::AG_OP
)
10169 FATAL_ERROR("AltGuards::generate_code_call_body()");
10170 Value
*guard_expr
= ag
->get_guard_expr();
10172 // the branch has a boolean guard expression
10173 str
= mputprintf(str
,
10174 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10175 label_str
, (unsigned long) i
);
10176 str
= guard_expr
->update_location_object(str
);
10177 expression_struct expr
;
10178 Code::init_expr(&expr
);
10179 guard_expr
->generate_code_expr(&expr
);
10180 str
= mputstr(str
, expr
.preamble
);
10181 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10182 "else %s_alt_flag_%lu = ALT_NO;\n",
10183 expr
.expr
, label_str
, (unsigned long) i
,
10184 label_str
, (unsigned long) i
);
10185 str
= mputstr(str
, expr
.postamble
);
10186 Code::free_expr(&expr
);
10187 str
= mputstr(str
, "}\n"); // (2)
10189 // evaluation of guard operation
10190 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10191 label_str
, (unsigned long) i
);
10192 expression_struct expr
;
10193 Code::init_expr(&expr
);
10194 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10195 (unsigned long) i
);
10196 Statement
*stmt
= ag
->get_guard_stmt();
10197 str
= stmt
->update_location_object(str
);
10198 stmt
->generate_code_expr(&expr
);
10199 str
= Code::merge_free_expr(str
, &expr
);
10200 // execution of statement block if the guard was successful
10201 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10202 (unsigned long) i
);
10203 StatementBlock
*block
= ag
->get_block();
10204 if(in_interleave
) {
10205 if(block
&& block
->get_nof_stmts() > 0) {
10206 if(block
->has_receiving_stmt()) {
10207 str
= mputprintf(str
, "goto %s_branch%lu;\n",
10208 label_str
, (unsigned long) i
);
10211 str
= mputstr(str
, "{\n"); // (3)
10212 str
= block
->generate_code(str
);
10213 str
= mputprintf(str
, "goto %s_end;\n"
10218 else str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10221 if (block
&& block
->get_nof_stmts() > 0) {
10222 str
= mputstr(str
, "{\n"); // (3)
10223 str
= block
->generate_code(str
);
10224 if (block
->has_return() != StatementBlock::RS_YES
)
10225 str
= mputstr(str
, "break;\n");
10226 str
= mputstr(str
, "}\n"); // (3)
10228 else str
= mputstr(str
, "break;\n");
10230 // closing of if() block
10231 str
= mputstr(str
, "}\n"); // (2)
10233 str
= loc
.update_location_object(str
);
10234 // error handling and taking the next snapshot in blocking mode
10235 str
= mputstr(str
, "if (");
10236 for (size_t i
= 0; i
< ags
.size(); i
++) {
10237 if (i
> 0) str
= mputstr(str
, " && ");
10238 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO", label_str
,
10239 (unsigned long) i
);
10241 str
= mputstr(str
, ") TTCN_error(\"None of the branches can be chosen in "
10242 "the response and exception handling part of call statement in file ");
10243 str
= Code::translate_string(str
, loc
.get_filename());
10244 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10245 if (first_line
< last_line
) str
= mputprintf(str
,
10246 " between lines %d and %d", first_line
, last_line
);
10247 else str
= mputprintf(str
, ", line %d", first_line
);
10248 str
= mputstr(str
, ".\");\n"
10249 "TTCN_Snapshot::take_new(TRUE);\n"
10254 void AltGuards::ilt_generate_code_call_body(ILT
*ilt
, const char *label_str
)
10256 char*& str
=ilt
->get_out_branches();
10257 for(size_t i
=0; i
<ags
.size(); i
++) {
10258 StatementBlock
*block
= ags
[i
]->get_block();
10259 if (block
&& block
->has_receiving_stmt()) {
10260 str
= mputprintf(str
, "%s_branch%lu:\n", label_str
, (unsigned long) i
);
10261 block
->ilt_generate_code(ilt
);
10262 str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10267 } // namespace Ttcn