1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
19 * Szabo, Janos Zoltan – initial implementation
20 * Zalanyi, Balazs Andor
22 ******************************************************************************/
23 #include "../../common/dbgnew.hh"
24 #include "Statement.hh"
25 #include "Ttcnstuff.hh"
26 #include "../TypeCompat.hh"
27 #include "../CompType.hh"
28 #include "../CompField.hh"
29 #include "../SigParam.hh"
30 #include "TtcnTemplate.hh"
32 #include "ArrayDimensions.hh"
35 #include "Attributes.hh"
39 // =================================
40 // ===== StatementBlock
41 // =================================
43 StatementBlock::StatementBlock()
44 : Scope(), checked(false), labels_checked(false), my_sb(0), my_def(0), exception_handling(EH_NONE
)
48 StatementBlock::~StatementBlock()
50 for(size_t i
=0; i
<stmts
.size(); i
++)
57 StatementBlock
*StatementBlock::clone() const
59 FATAL_ERROR("StatementBlock::clone");
62 void StatementBlock::dump(unsigned int level
) const
64 size_t n
= stmts
.size();
65 DEBUG(level
, "StatementBlock at %p with %lu", (const void*)this,
67 for (size_t i
= 0; i
< n
; ++i
) {
68 stmts
[i
]->dump(level
+1);
72 void StatementBlock::add_stmt(Statement
*p_stmt
, bool to_front
)
75 FATAL_ERROR("StatementBlock::add_stmt()");
77 stmts
.add_front(p_stmt
);
81 p_stmt
->set_my_scope(this);
82 p_stmt
->set_my_sb(this, stmts
.size()-1);
85 void StatementBlock::set_my_scope(Scope
*p_scope
)
87 set_parent_scope(p_scope
);
88 for(size_t i
=0; i
<stmts
.size(); i
++)
89 stmts
[i
]->set_my_scope(this);
92 void StatementBlock::set_fullname(const string
& p_fullname
)
94 Node::set_fullname(p_fullname
);
95 for(size_t i
=0; i
<stmts
.size(); i
++)
96 stmts
[i
]->set_fullname(p_fullname
+".stmt_"+Int2string(i
+1));
99 /** \todo handle loops and conditional statements */
100 Statement
*StatementBlock::get_first_stmt() const
102 size_t nof_stmts
= stmts
.size();
103 for (size_t i
= 0; i
< nof_stmts
; i
++) {
104 Statement
*stmt
= stmts
[i
];
105 switch (stmt
->get_statementtype()) {
106 case Statement::S_LABEL
:
107 // ignore and go to the next statement
109 case Statement::S_BLOCK
: {
110 // if the block is not empty return its first statement
111 // otherwise go to the next statement
112 Statement
*first_stmt
= stmt
->get_block()->get_first_stmt();
113 if (first_stmt
) return first_stmt
;
115 case Statement::S_DOWHILE
: {
116 // if the block is not empty return its first statement
117 // otherwise return the whole do-while statement
118 Statement
*first_stmt
= stmt
->get_block()->get_first_stmt();
119 if (first_stmt
) return first_stmt
;
128 void StatementBlock::register_def(Definition
*p_def
)
130 if(!p_def
) FATAL_ERROR("StatementBlock::register_def()");
131 const Identifier
& id
=p_def
->get_id();
132 if (defs
.has_key(id
)) {
133 const char *dispname
= id
.get_dispname().c_str();
134 p_def
->error("Duplicate definition with identifier `%s'", dispname
);
135 defs
[id
]->note("Previous definition with identifier `%s' is here",
140 if (parent_scope
->has_ass_withId(id
)) {
141 const char *dispname
= id
.get_dispname().c_str();
142 p_def
->error("Definition with identifier `%s' is not unique"
143 " in the scope hierarchy", dispname
);
144 Reference
ref(0, id
.clone());
145 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
146 if (!ass
) FATAL_ERROR("StatementBlock::register_def()");
147 ass
->note("Previous definition with identifier `%s' in higher "
148 "scope unit is here", dispname
);
149 } else if (parent_scope
->is_valid_moduleid(id
)) {
150 p_def
->warning("Definition with name `%s' hides a module identifier",
151 id
.get_dispname().c_str());
157 bool StatementBlock::has_ass_withId(const Identifier
& p_id
)
159 return defs
.has_key(p_id
) || get_parent_scope()->has_ass_withId(p_id
);
162 Common::Assignment
* StatementBlock::get_ass_bySRef(Ref_simple
*p_ref
)
164 if(p_ref
->get_modid()) return get_parent_scope()->get_ass_bySRef(p_ref
);
165 const Identifier
& id
=*p_ref
->get_id();
166 if(defs
.has_key(id
)) return defs
[id
];
167 else return get_parent_scope()->get_ass_bySRef(p_ref
);
170 Type
*StatementBlock::get_mtc_system_comptype(bool is_system
)
172 // return NULL outside test cases
173 if (!my_def
|| my_def
->get_asstype() != Common::Assignment::A_TESTCASE
)
176 Def_Testcase
*t_tc
= dynamic_cast<Def_Testcase
*>(my_def
);
177 if (!t_tc
) FATAL_ERROR("StatementBlock::get_mtc_system_comptype()");
178 Type
*system_ct
= t_tc
->get_SystemType();
179 if (system_ct
) return system_ct
;
180 // otherwise (if the testcase has no system clause) the type of 'system'
181 // is the same as the type of 'mtc' (which is given in 'runs on' clause)
183 return my_def
->get_RunsOnType();
186 Ttcn::StatementBlock
*StatementBlock::get_statementblock_scope()
191 void StatementBlock::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
195 for(size_t i
=0; i
<stmts
.size(); i
++)
196 stmts
[i
]->set_my_sb(this, i
);
199 size_t StatementBlock::get_my_sb_index() const
201 if(!my_sb
) FATAL_ERROR("StatementBlock::get_my_sb_index()");
205 void StatementBlock::set_my_def(Definition
*p_def
)
208 for(size_t i
=0; i
<stmts
.size(); i
++)
209 stmts
[i
]->set_my_def(p_def
);
212 void StatementBlock::set_my_ags(AltGuards
*p_ags
)
214 for(size_t i
=0; i
<stmts
.size(); i
++)
215 stmts
[i
]->set_my_ags(p_ags
);
218 void StatementBlock::set_my_laic_stmt(AltGuards
*p_ags
,
219 Statement
*p_loop_stmt
)
221 for(size_t i
=0; i
<stmts
.size(); i
++)
222 stmts
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
225 StatementBlock::returnstatus_t
StatementBlock::has_return() const
227 returnstatus_t ret_val
= RS_NO
;
228 size_t nof_stmts
= stmts
.size();
229 for (size_t i
= 0; i
< nof_stmts
; i
++) {
230 Statement
*stmt
= stmts
[i
];
231 if (stmt
->get_statementtype() == Statement::S_GOTO
) {
232 if (stmt
->goto_jumps_forward()) {
233 // heuristics without deep analysis of the control flow graph:
234 // skip over the next statements until a (used) label is found
235 // the behaviour will be sound (i.e. no false errors will be reported)
236 for (i
++; i
< nof_stmts
; i
++) {
238 if (stmt
->get_statementtype() == Statement::S_LABEL
&&
239 stmt
->label_is_used()) break;
241 } else return RS_YES
;
242 } else if (stmt
->get_statementtype()==Statement::S_BLOCK
&& stmt
->get_block()->exception_handling
!=EH_NONE
) {
243 switch (stmt
->get_block()->exception_handling
) {
244 case EH_TRY
: // the i-th statement is a try{} statement block, the (i+1)-th must be a catch{} block
245 if ((i
+1)<nof_stmts
&& stmts
[i
+1]->get_statementtype()==Statement::S_BLOCK
&& stmts
[i
+1]->get_block()->exception_handling
==EH_CATCH
) {
246 returnstatus_t try_block_rs
= stmt
->has_return();
247 returnstatus_t catch_block_rs
= stmts
[i
+1]->has_return();
248 // 3 x 3 combinations
249 if (try_block_rs
==catch_block_rs
) {
250 switch (try_block_rs
) {
261 } else { // if next statement is not a catch{} block then that error has already been reported
262 ret_val
= RS_MAYBE
; // assume the catch block was an RS_MAYBE
266 // logically this is part of the preceding try{} block, handle it as part of it, see above case EH_TRY
269 FATAL_ERROR("StatementBlock::has_return()");
272 switch (stmt
->has_return()) {
285 bool StatementBlock::has_receiving_stmt(size_t start_i
) const
287 for(size_t i
=start_i
; i
<stmts
.size(); i
++)
288 if(stmts
[i
]->has_receiving_stmt()) return true;
292 bool StatementBlock::has_def_stmt_i(size_t start_i
) const
294 for(size_t i
=start_i
; i
<stmts
.size(); i
++)
295 if(stmts
[i
]->get_statementtype()==Statement::S_DEF
) return true;
299 size_t StatementBlock::last_receiving_stmt_i() const
301 size_t nof_stmts
= stmts
.size();
303 size_t i
= nof_stmts
;
305 if (stmts
[--i
]->has_receiving_stmt()) return i
;
311 StatementBlock
*StatementBlock::get_parent_block() const
313 for (Scope
*s
= get_parent_scope(); s
; s
=s
->get_parent_scope()) {
314 StatementBlock
*sb
= dynamic_cast<StatementBlock
*>(s
);
320 void StatementBlock::chk_trycatch_blocks(Statement
* s1
, Statement
* s2
) {
321 if (s1
&& s1
->get_statementtype()==Statement::S_BLOCK
&& s1
->get_block()->get_exception_handling()==StatementBlock::EH_TRY
) {
322 if (!(s2
&& s2
->get_statementtype()==Statement::S_BLOCK
&& s2
->get_block()->get_exception_handling()==StatementBlock::EH_CATCH
)) {
323 s1
->error("`try' statement block must be followed by a `catch' block");
326 if (s2
&& s2
->get_statementtype()==Statement::S_BLOCK
&& s2
->get_block()->get_exception_handling()==StatementBlock::EH_CATCH
) {
327 if (!(s1
&& s1
->get_statementtype()==Statement::S_BLOCK
&& s1
->get_block()->get_exception_handling()==StatementBlock::EH_TRY
)) {
328 s2
->error("`catch' statement block must be preceded by a `try' block");
333 void StatementBlock::chk()
337 bool unreach_found
= false;
338 size_t nof_stmts
= stmts
.size();
339 Statement
*prev_stmt
= 0;
340 for (size_t i
= 0; i
< nof_stmts
; i
++) {
341 Statement
*stmt
= stmts
[i
];
343 if (!unreach_found
&& stmt
->get_statementtype() != Statement::S_LABEL
&&
344 prev_stmt
&& prev_stmt
->is_terminating()) {
345 // a statement is unreachable if:
346 // - it is not a label (i.e. goto cannot jump to it)
347 // - it is not the first statement of the block
348 // - the previous statement terminates the control flow
349 stmt
->warning("Control never reaches this statement");
350 unreach_found
= true;
352 // check try-catch statement block usage
353 chk_trycatch_blocks(prev_stmt
, stmt
);
357 chk_trycatch_blocks(prev_stmt
, 0);
362 void StatementBlock::chk_allowed_interleave()
364 size_t nof_stmts
= stmts
.size();
365 for (size_t i
= 0; i
< nof_stmts
; i
++)
366 stmts
[i
]->chk_allowed_interleave();
369 void StatementBlock::chk_labels()
371 if(labels_checked
) return;
372 for(size_t i
=0; i
<stmts
.size(); i
++) {
373 Statement
*st
=stmts
[i
];
374 if(st
->get_statementtype()!=Statement::S_LABEL
) continue;
375 const Identifier
& labelid
=st
->get_labelid();
376 if(has_label(labelid
)) {
377 const char *name
=labelid
.get_dispname().c_str();
378 st
->error("Duplicate label `%s'", name
);
379 Statement
*st2
=get_label(labelid
);
380 st2
->note("Previous definition of label `%s' is here", name
);
382 else labels
.add(labelid
, st
);
387 void StatementBlock::chk_unused_labels()
389 size_t nof_stmts
= stmts
.size();
390 for (size_t i
= 0; i
< nof_stmts
; i
++) {
391 Statement
*stmt
= stmts
[i
];
392 if (stmt
->get_statementtype() == Statement::S_LABEL
&&
393 !stmt
->label_is_used())
394 stmt
->warning("Label `%s' is defined, but not used",
395 stmt
->get_labelid().get_dispname().c_str());
399 bool StatementBlock::has_label(const Identifier
& p_id
) const
401 for (const StatementBlock
*sb
= this; sb
; sb
= sb
->get_parent_block())
402 if (sb
->labels
.has_key(p_id
)) return true;
406 Statement
*StatementBlock::get_label(const Identifier
& p_id
) const
408 for (const StatementBlock
*sb
= this; sb
; sb
= sb
->get_parent_block())
409 if (sb
->labels
.has_key(p_id
)) return sb
->labels
[p_id
];
410 FATAL_ERROR("StatementBlock::get_label()");
414 void StatementBlock::set_code_section(
415 GovernedSimple::code_section_t p_code_section
)
417 for(size_t i
= 0; i
< stmts
.size(); i
++)
418 stmts
[i
]->set_code_section(p_code_section
);
421 char* StatementBlock::generate_code(char *str
)
423 if (exception_handling
==EH_TRY
) {
424 str
= mputstr(str
, "TTCN_TryBlock try_block;\n");
426 if (stmts
.size()>0) {
427 Statement
* first_stmt
= stmts
[0];
428 str
= first_stmt
->generate_code(str
);
429 if (exception_handling
==EH_CATCH
) {
430 if (first_stmt
->get_statementtype()!=Statement::S_DEF
) FATAL_ERROR("StatementBlock::generate_code()");
431 Definition
* error_msg_def
= first_stmt
->get_def();
432 string error_msg_name
= error_msg_def
->get_id().get_name();
433 str
= mputprintf(str
, "%s = ttcn_error.get_message();\n", error_msg_name
.c_str());
436 for(size_t i
=1; i
<stmts
.size(); i
++) {
437 str
= stmts
[i
]->generate_code(str
);
442 void StatementBlock::ilt_generate_code(ILT
*ilt
)
444 size_t nof_stmts
= stmts
.size();
445 if (nof_stmts
== 0) return;
446 char*& str
=ilt
->get_out_branches();
447 size_t last_recv_stmt_i
=last_receiving_stmt_i();
448 // has no receiving stmt
449 if (last_recv_stmt_i
== nof_stmts
) {
450 bool has_def
=has_def_stmt_i();
451 if(has_def
) str
=mputstr(str
, "{\n");
452 for(size_t i
=0; i
<nof_stmts
; i
++)
453 str
=stmts
[i
]->generate_code(str
);
454 if(has_def
) str
=mputstr(str
, "}\n");
457 for(size_t i
=0; i
<=last_recv_stmt_i
; i
++)
458 stmts
[i
]->ilt_generate_code(ilt
);
459 // the last part which does not contain receiving stmt
460 if(last_recv_stmt_i
==nof_stmts
-1) return;
461 bool has_def
=has_def_stmt_i(last_recv_stmt_i
+1);
462 if(has_def
) str
=mputstr(str
, "{\n");
463 for(size_t i
=last_recv_stmt_i
+1; i
<nof_stmts
; i
++)
464 str
=stmts
[i
]->generate_code(str
);
465 if(has_def
) str
=mputstr(str
, "}\n");
468 void StatementBlock::set_parent_path(WithAttribPath
* p_path
)
470 for (size_t i
= 0; i
< stmts
.size(); i
++)
471 stmts
[i
]->set_parent_path(p_path
);
474 // =================================
476 // =================================
478 void Statement::clean_up()
480 switch (statementtype
) {
486 case S_START_PROFILER
:
487 case S_STOP_PROFILER
:
491 delete undefstartstop
.ref
;
492 delete undefstartstop
.val
;
494 case S_UNKNOWN_INSTANCE
:
495 case S_FUNCTION_INSTANCE
:
496 case S_ALTSTEP_INSTANCE
:
511 case S_STOP_TESTCASE
:
523 delete if_stmt
.elseblock
;
524 delete if_stmt
.elseblock_location
;
531 if(loop
.for_stmt
.varinst
)
532 delete loop
.for_stmt
.init_varinst
;
534 delete loop
.for_stmt
.init_ass
;
535 delete loop
.for_stmt
.finalexpr
;
536 delete loop
.for_stmt
.step
;
539 delete loop
.label_next
;
540 if (loop
.il_label_end
)
541 delete loop
.il_label_end
;
548 delete loop
.label_next
;
549 if (loop
.il_label_end
)
550 delete loop
.il_label_end
;
564 delete port_op
.portref
;
565 delete port_op
.s
.sendpar
;
566 delete port_op
.s
.toclause
;
569 delete port_op
.portref
;
570 delete port_op
.s
.sendpar
;
571 delete port_op
.s
.call
.timer
;
572 delete port_op
.s
.toclause
;
573 delete port_op
.s
.call
.body
;
576 delete port_op
.portref
;
577 delete port_op
.s
.sendpar
;
578 delete port_op
.s
.replyval
;
579 delete port_op
.s
.toclause
;
582 delete port_op
.portref
;
583 delete port_op
.s
.raise
.signature_ref
;
584 delete port_op
.s
.sendpar
;
585 delete port_op
.s
.toclause
;
588 case S_CHECK_RECEIVE
:
590 delete port_op
.portref
;
591 delete port_op
.r
.rcvpar
;
592 delete port_op
.r
.fromclause
;
593 delete port_op
.r
.redirect
.value
;
594 delete port_op
.r
.redirect
.sender
;
597 case S_CHECK_GETCALL
:
598 delete port_op
.portref
;
599 delete port_op
.r
.rcvpar
;
600 delete port_op
.r
.fromclause
;
601 delete port_op
.r
.redirect
.param
;
602 delete port_op
.r
.redirect
.sender
;
605 case S_CHECK_GETREPLY
:
606 delete port_op
.portref
;
607 delete port_op
.r
.rcvpar
;
608 delete port_op
.r
.getreply_valuematch
;
609 delete port_op
.r
.fromclause
;
610 delete port_op
.r
.redirect
.value
;
611 delete port_op
.r
.redirect
.param
;
612 delete port_op
.r
.redirect
.sender
;
616 delete port_op
.portref
;
617 delete port_op
.r
.ctch
.signature_ref
;
618 delete port_op
.r
.rcvpar
;
619 delete port_op
.r
.fromclause
;
620 delete port_op
.r
.redirect
.value
;
621 delete port_op
.r
.redirect
.sender
;
624 delete port_op
.portref
;
625 delete port_op
.r
.fromclause
;
626 delete port_op
.r
.redirect
.sender
;
632 delete port_op
.portref
;
635 delete comp_op
.compref
;
636 delete comp_op
.funcinstref
;
638 case S_START_COMP_REFD
:
639 delete comp_op
.compref
;
640 delete comp_op
.derefered
.value
;
641 delete comp_op
.derefered
.ap_list2
;
646 delete comp_op
.compref
;
649 if (comp_op
.compref
) {
650 delete comp_op
.compref
;
651 delete comp_op
.donereturn
.donematch
;
652 delete comp_op
.donereturn
.redirect
;
659 delete config_op
.compref1
;
660 delete config_op
.portref1
;
661 delete config_op
.compref2
;
662 delete config_op
.portref2
;
665 delete timer_op
.timerref
;
666 delete timer_op
.value
;
670 delete timer_op
.timerref
;
673 delete setverdict
.verdictval
;
674 delete setverdict
.logargs
;
676 case S_TESTCASE_INSTANCE
:
677 delete testcase_inst
.tcref
;
678 delete testcase_inst
.timerval
;
680 case S_TESTCASE_INSTANCE_REFD
:
681 delete execute_refd
.value
;
682 delete execute_refd
.ap_list2
;
683 delete execute_refd
.timerval
;
685 case S_ACTIVATE_REFD
:
686 case S_UNKNOWN_INVOKED
:
687 case S_FUNCTION_INVOKED
:
688 case S_ALTSTEP_INVOKED
:
689 delete fau_refd
.value
;
690 delete fau_refd
.ap_list2
;
694 delete convert_op
.val
;
695 delete convert_op
.ref
;
698 FATAL_ERROR("Statement::clean_up()");
699 } // switch statementtype
702 Statement::Statement(statementtype_t p_st
)
703 : statementtype(p_st
), my_sb(0)
705 switch(statementtype
) {
710 case S_START_PROFILER
:
711 case S_STOP_PROFILER
:
719 FATAL_ERROR("Statement::Statement()");
720 } // switch statementtype
723 Statement::Statement(statementtype_t p_st
, Ref_base
*p_ref
, Value
*p_val
)
724 : statementtype(p_st
), my_sb(0)
726 switch(statementtype
) {
728 if (!p_ref
) FATAL_ERROR("Statement::Statement()");
729 undefstartstop
.ref
=p_ref
;
730 undefstartstop
.val
=p_val
;
733 if (!p_ref
|| p_val
) FATAL_ERROR("Statement::Statement()");
734 undefstartstop
.ref
=p_ref
;
735 undefstartstop
.val
=0;
738 FATAL_ERROR("Statement::Statement()");
739 } // switch statementtype
742 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
)
743 : statementtype(p_st
), my_sb(0)
745 switch(statementtype
) {
746 case S_UNKNOWN_INSTANCE
:
747 case S_FUNCTION_INSTANCE
:
748 case S_ALTSTEP_INSTANCE
:
751 FATAL_ERROR("Statement::Statement()");
755 FATAL_ERROR("Statement::Statement()");
756 } // switch statementtype
759 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
760 ParsedActualParameters
*p_ap_list
)
761 : statementtype(p_st
), my_sb(0)
763 switch(statementtype
) {
764 case S_ACTIVATE_REFD
:
765 case S_UNKNOWN_INVOKED
:
766 case S_FUNCTION_INVOKED
:
767 case S_ALTSTEP_INVOKED
:
768 if(!p_derefered_value
|| !p_ap_list
)
769 FATAL_ERROR("Statement::Statement()");
770 fau_refd
.value
= p_derefered_value
;
771 fau_refd
.t_list1
= p_ap_list
;
774 FATAL_ERROR("Statement::Statement()");
778 Statement::Statement(statementtype_t p_st
, Definition
*p_def
)
779 : statementtype(p_st
), my_sb(0)
781 switch(statementtype
) {
784 FATAL_ERROR("Statement::Statement()");
788 FATAL_ERROR("Statement::Statement()");
789 } // switch statementtype
792 Statement::Statement(statementtype_t p_st
, Assignment
*p_ass
)
793 : statementtype(p_st
), my_sb(0)
795 switch(statementtype
) {
798 FATAL_ERROR("Statement::Statement()");
802 FATAL_ERROR("Statement::Statement()");
803 } // switch statementtype
806 Statement::Statement(statementtype_t p_st
, StatementBlock
*p_block
)
807 : statementtype(p_st
), my_sb(0)
809 switch (statementtype
) {
811 if (!p_block
) FATAL_ERROR("Statement::Statement()");
815 FATAL_ERROR("Statement::Statement()");
816 } // switch statementtype
819 Statement::Statement(statementtype_t p_st
, LogArguments
*p_logargs
)
820 : statementtype(p_st
), my_sb(0)
822 switch(statementtype
) {
825 case S_STOP_TESTCASE
:
829 FATAL_ERROR("Statement::Statement()");
830 } // switch statementtype
833 Statement::Statement(statementtype_t p_st
, Identifier
*p_id
)
834 : statementtype(p_st
), my_sb(0)
837 FATAL_ERROR("Statement::Statement()");
838 switch (statementtype
) {
849 go_to
.jumps_forward
= false;
852 FATAL_ERROR("Statement::Statement()");
853 } // switch statementtype
856 Statement::Statement(statementtype_t p_st
, IfClauses
*p_ics
,
857 StatementBlock
*p_block
, Location
*p_loc
)
858 : statementtype(p_st
), my_sb(0)
860 switch(statementtype
) {
863 FATAL_ERROR("Statement::Statement()");
866 if (!p_loc
) FATAL_ERROR("Statement::Statement()");
867 if_stmt
.elseblock
= p_block
;
868 if_stmt
.elseblock_location
= p_loc
;
870 if (p_loc
) FATAL_ERROR("Statement::Statement()");
871 if_stmt
.elseblock
= 0;
872 if_stmt
.elseblock_location
= 0;
876 FATAL_ERROR("Statement::Statement()");
877 } // switch statementtype
880 Statement::Statement(statementtype_t p_st
, Value
*p_expr
, SelectCases
*p_scs
)
881 : statementtype(p_st
), my_sb(0)
883 switch(statementtype
) {
885 if(!p_expr
|| !p_scs
)
886 FATAL_ERROR("Statement::Statement()");
891 FATAL_ERROR("Statement::Statement()");
892 } // switch statementtype
895 Statement::Statement(statementtype_t p_st
, Definitions
*p_defs
,
896 Assignment
*p_ass
, Value
*p_final
,
897 Assignment
*p_step
, StatementBlock
*p_block
)
898 : statementtype(p_st
), my_sb(0)
900 switch (statementtype
) {
901 case S_FOR
: // precisely one of p_defs, p_ass allowed
903 // it came from a for loop which looked like this:
904 // for (var integer foo:=1; foo<10; foo:=foo+1) ;
905 if (p_ass
) FATAL_ERROR("Statement::Statement()");
906 loop
.for_stmt
.varinst
= true;
907 loop
.for_stmt
.init_varinst
= p_defs
;
909 // it came from a for loop which looked like this:
910 // for (foo:=1; foo<10; foo:=foo+1) ;
911 if (!p_ass
) FATAL_ERROR("Statement::Statement()");
912 loop
.for_stmt
.varinst
= false;
913 loop
.for_stmt
.init_ass
= p_ass
;
915 if(!p_final
|| !p_step
|| !p_block
)
916 FATAL_ERROR("Statement::Statement()");
917 loop
.for_stmt
.finalexpr
=p_final
;
918 loop
.for_stmt
.step
=p_step
;
924 loop
.has_cnt_in_ags
=false;
925 loop
.iterate_once
=false; // not used by for
929 FATAL_ERROR("Statement::Statement()");
930 } // switch statementtype
933 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
934 StatementBlock
*p_block
)
935 : statementtype(p_st
), my_sb(0)
937 switch(statementtype
) {
940 if(!p_val
|| !p_block
)
941 FATAL_ERROR("Statement::Statement()");
948 loop
.has_cnt_in_ags
=false;
949 loop
.iterate_once
=false; // used only by do-while
953 FATAL_ERROR("Statement::Statement()");
954 } // switch statementtype
957 Statement::Statement(statementtype_t p_st
, AltGuards
*p_ags
)
958 : statementtype(p_st
), my_sb(0)
960 switch(statementtype
) {
964 FATAL_ERROR("Statement::Statement()");
968 FATAL_ERROR("Statement::Statement()");
969 } // switch statementtype
972 Statement::Statement(statementtype_t p_st
, Template
*p_temp
)
973 : statementtype(p_st
), my_sb(0)
975 switch(statementtype
) {
981 FATAL_ERROR("Statement::Statement()");
982 } // switch statementtype
985 Statement::Statement(statementtype_t p_st
, Value
*p_val
)
986 : statementtype(p_st
), my_sb(0)
988 switch (statementtype
) {
991 FATAL_ERROR("Statement::Statement()");
995 comp_op
.compref
=p_val
;
1001 FATAL_ERROR("Statement::Statement()");
1002 } // switch statementtype
1005 Statement::Statement(statementtype_t p_st
, Value
*p_val
,
1006 LogArguments
*p_logargs
)
1007 : statementtype(p_st
), my_sb(0)
1009 if (!p_val
|| statementtype
!= S_SETVERDICT
)
1010 FATAL_ERROR("Statement::Statement()");
1011 setverdict
.verdictval
= p_val
;
1012 setverdict
.logargs
= p_logargs
;
1015 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1016 TemplateInstance
*p_templinst
, Value
*p_val
)
1017 : statementtype(p_st
), my_sb(0)
1019 switch(statementtype
) {
1021 if(!p_ref
|| !p_templinst
)
1022 FATAL_ERROR("Statement::Statement()");
1023 port_op
.portref
=p_ref
;
1024 port_op
.s
.sendpar
=p_templinst
;
1025 port_op
.s
.toclause
=p_val
;
1028 FATAL_ERROR("Statement::Statement()");
1029 } // switch statementtype
1032 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1033 TemplateInstance
*p_templinst
, Value
*p_timerval
,
1034 bool p_nowait
, Value
*p_toclause
, AltGuards
*p_callbody
)
1035 : statementtype(p_st
), my_sb(0)
1037 switch(statementtype
) {
1039 if(!p_ref
|| !p_templinst
|| (p_timerval
&& p_nowait
))
1040 FATAL_ERROR("Statement::Statement()");
1041 port_op
.portref
=p_ref
;
1042 port_op
.s
.sendpar
=p_templinst
;
1043 port_op
.s
.call
.timer
=p_timerval
;
1044 port_op
.s
.call
.nowait
=p_nowait
;
1045 port_op
.s
.toclause
=p_toclause
;
1046 port_op
.s
.call
.body
=p_callbody
;
1049 FATAL_ERROR("Statement::Statement()");
1050 } // switch statementtype
1053 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1054 TemplateInstance
*p_templinst
, Value
*p_replyval
,
1056 : statementtype(p_st
), my_sb(0)
1058 switch(statementtype
) {
1060 if(!p_ref
|| !p_templinst
)
1061 FATAL_ERROR("Statement::Statement()");
1062 port_op
.portref
=p_ref
;
1063 port_op
.s
.sendpar
=p_templinst
;
1064 port_op
.s
.replyval
=p_replyval
;
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 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1075 : statementtype(p_st
), my_sb(0)
1077 switch(statementtype
) {
1079 if(!p_ref
|| !p_templinst
|| !p_sig
)
1080 FATAL_ERROR("Statement::Statement()");
1081 port_op
.portref
=p_ref
;
1082 port_op
.s
.raise
.signature_ref
=p_sig
;
1083 port_op
.s
.raise
.signature
=0;
1084 port_op
.s
.sendpar
=p_templinst
;
1085 port_op
.s
.toclause
=p_toclause
;
1088 FATAL_ERROR("Statement::Statement()");
1089 } // switch statementtype
1092 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1093 TemplateInstance
*p_templinst
,
1094 TemplateInstance
*p_fromclause
,
1095 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1096 : statementtype(p_st
), my_sb(0)
1098 switch(statementtype
) {
1100 case S_CHECK_RECEIVE
:
1102 port_op
.portref
=p_ref
;
1103 port_op
.r
.rcvpar
=p_templinst
;
1104 port_op
.r
.fromclause
=p_fromclause
;
1105 port_op
.r
.redirect
.value
=p_redirectval
;
1106 port_op
.r
.redirect
.param
=0;
1107 port_op
.r
.redirect
.sender
=p_redirectsender
;
1110 FATAL_ERROR("Statement::Statement()");
1111 } // switch statementtype
1114 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1115 TemplateInstance
*p_templinst
,
1116 TemplateInstance
*p_fromclause
,
1117 ParamRedirect
*p_redirectparam
,
1118 Reference
*p_redirectsender
)
1119 : statementtype(p_st
), my_sb(0)
1121 switch(statementtype
) {
1123 case S_CHECK_GETCALL
:
1124 port_op
.portref
=p_ref
;
1125 port_op
.r
.rcvpar
=p_templinst
;
1126 port_op
.r
.fromclause
=p_fromclause
;
1127 port_op
.r
.redirect
.value
=0;
1128 port_op
.r
.redirect
.param
=p_redirectparam
;
1129 port_op
.r
.redirect
.sender
=p_redirectsender
;
1132 FATAL_ERROR("Statement::Statement()");
1133 } // switch statementtype
1136 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1137 TemplateInstance
*p_templinst
,
1138 TemplateInstance
*p_valuematch
,
1139 TemplateInstance
*p_fromclause
,
1140 Reference
*p_redirectval
, ParamRedirect
*p_redirectparam
,
1141 Reference
*p_redirectsender
)
1142 : statementtype(p_st
), my_sb(0)
1144 switch(statementtype
) {
1146 case S_CHECK_GETREPLY
:
1147 if (!p_templinst
&& p_valuematch
) FATAL_ERROR("Statement::Statement()");
1148 port_op
.portref
=p_ref
;
1149 port_op
.r
.rcvpar
=p_templinst
;
1150 port_op
.r
.getreply_valuematch
=p_valuematch
;
1151 port_op
.r
.fromclause
=p_fromclause
;
1152 port_op
.r
.redirect
.value
=p_redirectval
;
1153 port_op
.r
.redirect
.param
=p_redirectparam
;
1154 port_op
.r
.redirect
.sender
=p_redirectsender
;
1157 FATAL_ERROR("Statement::Statement()");
1158 } // switch statementtype
1161 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1162 Reference
*p_sig
, TemplateInstance
*p_templinst
,
1163 bool p_timeout
, TemplateInstance
*p_fromclause
,
1164 Reference
*p_redirectval
, Reference
*p_redirectsender
)
1165 : statementtype(p_st
), my_sb(0)
1167 switch(statementtype
) {
1170 if (((p_sig
|| p_templinst
) && p_timeout
) ||
1171 (p_sig
&& !p_templinst
) || (!p_sig
&& p_templinst
))
1172 FATAL_ERROR("Statement::Statement()");
1173 port_op
.portref
=p_ref
;
1174 port_op
.r
.ctch
.signature_ref
=p_sig
;
1175 port_op
.r
.ctch
.signature
=0;
1176 port_op
.r
.rcvpar
=p_templinst
;
1177 port_op
.r
.ctch
.timeout
=p_timeout
;
1178 port_op
.r
.ctch
.in_call
=false;
1179 port_op
.r
.ctch
.call_has_timer
=false;
1180 port_op
.r
.fromclause
=p_fromclause
;
1181 port_op
.r
.redirect
.value
=p_redirectval
;
1182 port_op
.r
.redirect
.param
=0;
1183 port_op
.r
.redirect
.sender
=p_redirectsender
;
1186 FATAL_ERROR("Statement::Statement()");
1187 } // switch statementtype
1190 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
,
1191 TemplateInstance
*p_fromclause
,
1192 Reference
*p_redirectsender
)
1193 : statementtype(p_st
), my_sb(0)
1195 switch(statementtype
) {
1197 port_op
.portref
=p_ref
; // may be NULL for "any port.check"
1198 port_op
.r
.fromclause
=p_fromclause
;
1199 port_op
.r
.redirect
.value
=0;
1200 port_op
.r
.redirect
.param
=0;
1201 port_op
.r
.redirect
.sender
=p_redirectsender
;
1204 FATAL_ERROR("Statement::Statement()");
1205 } // switch statementtype
1208 Statement::Statement(statementtype_t p_st
, Reference
*p_ref
)
1209 : statementtype(p_st
), my_sb(0)
1211 switch(statementtype
) {
1216 port_op
.portref
=p_ref
;
1220 timer_op
.timerref
=p_ref
;
1223 FATAL_ERROR("Statement::Statement()");
1224 } // switch statementtype
1227 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1228 Ref_pard
*p_funcinst
)
1229 : statementtype(p_st
), my_sb(0)
1231 switch(statementtype
) {
1233 if(!p_compref
|| !p_funcinst
)
1234 FATAL_ERROR("Statement::Statement()");
1235 comp_op
.compref
= p_compref
;
1236 comp_op
.funcinstref
= p_funcinst
;
1239 FATAL_ERROR("Statement::Statement()");
1240 } // switch statementtype
1243 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1244 Value
*p_derefered_value
, ParsedActualParameters
*p_ap_list
)
1245 : statementtype(p_st
), my_sb(0)
1247 switch(statementtype
) {
1248 case S_START_COMP_REFD
:
1249 if(!p_compref
|| !p_derefered_value
|| !p_ap_list
)
1250 FATAL_ERROR("Statement::Statement()");
1251 comp_op
.compref
= p_compref
;
1252 comp_op
.derefered
.value
= p_derefered_value
;
1253 comp_op
.derefered
.t_list1
= p_ap_list
;
1256 FATAL_ERROR("Statement::Statement()");
1260 Statement::Statement(statementtype_t p_st
, Value
*p_compref
,
1261 TemplateInstance
*p_donematch
, Reference
*p_redirect
)
1262 : statementtype(p_st
), my_sb(0)
1264 switch (statementtype
) {
1266 if (!p_compref
) FATAL_ERROR("Statement::Statement()");
1267 comp_op
.compref
= p_compref
;
1268 comp_op
.donereturn
.donematch
= p_donematch
;
1269 comp_op
.donereturn
.redirect
= p_redirect
;
1272 FATAL_ERROR("Statement::Statement()");
1273 } // switch statementtype
1276 Statement::Statement(statementtype_t p_st
, component_t p_anyall
)
1277 : statementtype(p_st
), my_sb(0)
1279 switch (statementtype
) {
1282 comp_op
.compref
= 0;
1283 comp_op
.any_or_all
= p_anyall
;
1286 FATAL_ERROR("Statement::Statement()");
1287 } // switch statementtype
1290 Statement::Statement(statementtype_t p_st
,
1291 Value
*p_compref1
, Reference
*p_portref1
,
1292 Value
*p_compref2
, Reference
*p_portref2
)
1293 : statementtype(p_st
), my_sb(0)
1295 switch(statementtype
) {
1300 if(!p_compref1
|| !p_portref1
|| !p_compref2
|| !p_portref2
)
1301 FATAL_ERROR("Statement::Statement()");
1302 config_op
.compref1
=p_compref1
;
1303 config_op
.portref1
=p_portref1
;
1304 config_op
.compref2
=p_compref2
;
1305 config_op
.portref2
=p_portref2
;
1308 FATAL_ERROR("Statement::Statement()");
1309 } // switch statementtype
1312 Statement::Statement(statementtype_t p_st
, Ref_pard
*p_ref
, Value
*p_val
)
1313 : statementtype(p_st
), my_sb(0)
1315 switch(statementtype
) {
1316 case S_TESTCASE_INSTANCE
:
1318 FATAL_ERROR("Statement::Statement()");
1319 testcase_inst
.tcref
=p_ref
;
1320 testcase_inst
.timerval
=p_val
;
1323 FATAL_ERROR("Statement::Statement()");
1324 } // switch statementtype
1327 Statement::Statement(statementtype_t p_st
, Value
*p_derefered_value
,
1328 TemplateInstances
*p_ap_list
, Value
*p_val
)
1329 : statementtype(p_st
), my_sb(0)
1331 switch(statementtype
) {
1332 case S_TESTCASE_INSTANCE_REFD
:
1333 if(!p_derefered_value
) FATAL_ERROR("Statement::Statement()");
1334 execute_refd
.value
= p_derefered_value
;
1335 execute_refd
.t_list1
= p_ap_list
;
1336 execute_refd
.timerval
= p_val
;
1339 FATAL_ERROR("Statement::Statement()");
1343 Statement::Statement(statementtype_t p_st
, Value
* p_val
, Reference
* p_ref
)
1344 : statementtype(p_st
), my_sb(0)
1346 switch (statementtype
) {
1349 if (p_val
==NULL
|| p_ref
==NULL
) {
1350 FATAL_ERROR("Statement::Statement()");
1352 convert_op
.val
= p_val
;
1353 convert_op
.ref
= p_ref
;
1356 FATAL_ERROR("Statement::Statement()");
1360 Statement::~Statement()
1365 Statement
*Statement::clone() const
1367 FATAL_ERROR("Statement::clone");
1370 void Statement::dump(unsigned int level
) const
1372 DEBUG(level
, "Statement at %p, a(n) %s", (const void *)this,
1374 switch (statementtype
) {
1375 case S_TESTCASE_INSTANCE
:
1376 case S_TESTCASE_INSTANCE_REFD
: {
1377 Common::Value
*v
= execute_refd
.value
;
1381 def
->dump(level
+ 1);
1384 ass
->dump(level
+ 1);
1387 block
->dump(level
+ 1);
1390 if_stmt
.ics
->dump(level
+ 1);
1391 if (if_stmt
.elseblock
) if_stmt
.elseblock
->dump(level
+ 1);
1398 size_t Statement::get_my_sb_index() const
1400 switch (statementtype
) {
1402 return label
.stmt_idx
;
1404 return go_to
.stmt_idx
;
1406 FATAL_ERROR("Statement::get_my_sb_index()");
1411 const char *Statement::get_stmt_name() const
1413 switch(statementtype
) {
1414 case S_ERROR
: return "<erroneous statement>";
1415 case S_START_UNDEF
: return "start";
1416 case S_STOP_UNDEF
: return "stop";
1417 case S_UNKNOWN_INSTANCE
: return "function or altstep instance";
1418 case S_UNKNOWN_INVOKED
: return "function or altstep type invocation";
1419 case S_DEF
: return "definition";
1420 case S_ASSIGNMENT
: return "assignment";
1421 case S_FUNCTION_INSTANCE
: return "function instance";
1422 case S_FUNCTION_INVOKED
: return "function type invocation";
1423 case S_BLOCK
: return "statement block";
1424 case S_LOG
: return "log";
1425 case S_LABEL
: return "label";
1426 case S_GOTO
: return "goto";
1427 case S_IF
: return "if";
1428 case S_SELECT
: return "select-case";
1429 case S_FOR
: return "for";
1430 case S_WHILE
: return "while";
1431 case S_DOWHILE
: return "do-while";
1432 case S_BREAK
: return "break";
1433 case S_CONTINUE
: return "continue";
1434 case S_STOP_EXEC
: return "stop";
1435 case S_STOP_TESTCASE
: return "testcase.stop";
1436 case S_ALT
: return "alt";
1437 case S_REPEAT
: return "repeat";
1438 case S_INTERLEAVE
: return "interleave";
1439 case S_ALTSTEP_INSTANCE
: return "altstep instance";
1440 case S_ALTSTEP_INVOKED
: return "altstep type invocation";
1441 case S_RETURN
: return "return";
1443 case S_ACTIVATE_REFD
:
1445 case S_DEACTIVATE
: return "deactivate";
1446 case S_SEND
: return "send";
1447 case S_CALL
: return "call";
1448 case S_REPLY
: return "reply";
1449 case S_RAISE
: return "raise";
1450 case S_RECEIVE
: return "receive";
1451 case S_TRIGGER
: return "trigger";
1452 case S_GETCALL
: return "getcall";
1453 case S_GETREPLY
: return "getreply";
1454 case S_CATCH
: return "catch";
1455 case S_CHECK
: return "check";
1456 case S_CHECK_RECEIVE
: return "check-receive";
1457 case S_CHECK_GETCALL
: return "check-getcall";
1458 case S_CHECK_GETREPLY
: return "check-getreply";
1459 case S_CHECK_CATCH
: return "check-catch";
1460 case S_CLEAR
: return "clear";
1461 case S_START_PORT
: return "start port";
1462 case S_STOP_PORT
: return "stop port";
1463 case S_HALT
: return "halt";
1465 case S_START_COMP_REFD
:
1466 return "start test component";
1467 case S_STOP_COMP
: return "stop test component";
1468 case S_DONE
: return "done";
1469 case S_KILL
: return "kill";
1470 case S_KILLED
: return "killed";
1471 case S_CONNECT
: return "connect";
1472 case S_MAP
: return "map";
1473 case S_DISCONNECT
: return "disconnect";
1474 case S_UNMAP
: return "unmap";
1475 case S_START_TIMER
: return "start timer";
1476 case S_STOP_TIMER
: return "stop timer";
1477 case S_TIMEOUT
: return "timeout";
1478 case S_SETVERDICT
: return "setverdict";
1479 case S_ACTION
: return "action";
1480 case S_TESTCASE_INSTANCE
:
1481 case S_TESTCASE_INSTANCE_REFD
:
1483 case S_STRING2TTCN
: return "string2ttcn";
1484 case S_INT2ENUM
: return "int2enum";
1485 case S_START_PROFILER
: return "@profiler.start";
1486 case S_STOP_PROFILER
: return "@profiler.stop";
1488 FATAL_ERROR("Statement::get_stmt_name()");
1490 } // switch statementtype
1493 const Identifier
& Statement::get_labelid() const
1495 switch (statementtype
) {
1501 FATAL_ERROR("Statement::get_labelid()");
1506 bool Statement::label_is_used() const
1508 if (statementtype
!= S_LABEL
) FATAL_ERROR("Statement::label_is_used()");
1512 bool Statement::goto_jumps_forward() const
1514 if (statementtype
!= S_GOTO
) FATAL_ERROR("Statement::goto_jumps_forward()");
1515 return go_to
.jumps_forward
;
1518 const string
& Statement::get_clabel()
1520 if (statementtype
!= S_LABEL
|| !my_sb
)
1521 FATAL_ERROR("Statement::get_clabel()");
1522 if (!label
.clabel
) label
.clabel
=
1523 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
1524 return *label
.clabel
;
1527 Definition
*Statement::get_def() const
1529 if (statementtype
!= S_DEF
) FATAL_ERROR("Statement::get_def()");
1533 AltGuards
*Statement::get_ags() const
1535 if (statementtype
!= S_ALT
&& statementtype
!= S_INTERLEAVE
)
1536 FATAL_ERROR("Statement::get_ags()");
1540 StatementBlock
*Statement::get_block() const
1542 switch (statementtype
) {
1550 FATAL_ERROR("Statement::get_block()");
1555 void Statement::set_my_scope(Scope
*p_scope
)
1557 switch(statementtype
) {
1565 case S_START_PROFILER
:
1566 case S_STOP_PROFILER
:
1570 undefstartstop
.ref
->set_my_scope(p_scope
);
1571 if (undefstartstop
.val
) undefstartstop
.val
->set_my_scope(p_scope
);
1573 case S_UNKNOWN_INSTANCE
:
1574 case S_FUNCTION_INSTANCE
:
1575 case S_ALTSTEP_INSTANCE
:
1577 ref_pard
->set_my_scope(p_scope
);
1580 def
->set_my_scope(p_scope
);
1583 ass
->set_my_scope(p_scope
);
1586 block
->set_my_scope(p_scope
);
1590 case S_STOP_TESTCASE
:
1591 if (logargs
) logargs
->set_my_scope(p_scope
);
1594 if_stmt
.ics
->set_my_scope(p_scope
);
1595 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_scope(p_scope
);
1598 select
.expr
->set_my_scope(p_scope
);
1599 select
.scs
->set_my_scope(p_scope
);
1602 if (loop
.for_stmt
.varinst
) {
1603 loop
.for_stmt
.init_varinst
->set_parent_scope(p_scope
);
1604 loop
.for_stmt
.finalexpr
->set_my_scope(loop
.for_stmt
.init_varinst
);
1605 loop
.for_stmt
.step
->set_my_scope(loop
.for_stmt
.init_varinst
);
1606 loop
.block
->set_my_scope(loop
.for_stmt
.init_varinst
);
1608 loop
.for_stmt
.init_ass
->set_my_scope(p_scope
);
1609 loop
.for_stmt
.finalexpr
->set_my_scope(p_scope
);
1610 loop
.for_stmt
.step
->set_my_scope(p_scope
);
1611 loop
.block
->set_my_scope(p_scope
);
1616 loop
.expr
->set_my_scope(p_scope
);
1617 loop
.block
->set_my_scope(p_scope
);
1621 ags
->set_my_scope(p_scope
);
1624 if (returnexpr
.v
) returnexpr
.v
->set_my_scope(p_scope
);
1625 if (returnexpr
.t
) returnexpr
.t
->set_my_scope(p_scope
);
1628 if (deactivate
) deactivate
->set_my_scope(p_scope
);
1631 port_op
.portref
->set_my_scope(p_scope
);
1632 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1633 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1636 port_op
.portref
->set_my_scope(p_scope
);
1637 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1638 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1639 if(port_op
.s
.call
.timer
) port_op
.s
.call
.timer
->set_my_scope(p_scope
);
1640 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_scope(p_scope
);
1643 port_op
.portref
->set_my_scope(p_scope
);
1644 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1645 if(port_op
.s
.replyval
) port_op
.s
.replyval
->set_my_scope(p_scope
);
1646 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1649 port_op
.portref
->set_my_scope(p_scope
);
1650 port_op
.s
.raise
.signature_ref
->set_my_scope(p_scope
);
1651 port_op
.s
.sendpar
->set_my_scope(p_scope
);
1652 if(port_op
.s
.toclause
) port_op
.s
.toclause
->set_my_scope(p_scope
);
1655 case S_CHECK_RECEIVE
:
1657 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1658 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1659 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1660 if(port_op
.r
.redirect
.value
)
1661 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1662 if(port_op
.r
.redirect
.sender
)
1663 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1666 case S_CHECK_GETCALL
:
1667 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1668 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1669 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1670 if(port_op
.r
.redirect
.param
)
1671 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1672 if(port_op
.r
.redirect
.sender
)
1673 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1676 case S_CHECK_GETREPLY
:
1677 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1678 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1679 if(port_op
.r
.getreply_valuematch
)
1680 port_op
.r
.getreply_valuematch
->set_my_scope(p_scope
);
1681 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1682 if(port_op
.r
.redirect
.value
)
1683 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1684 if(port_op
.r
.redirect
.param
)
1685 port_op
.r
.redirect
.param
->set_my_scope(p_scope
);
1686 if(port_op
.r
.redirect
.sender
)
1687 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1691 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1692 if(port_op
.r
.ctch
.signature_ref
)
1693 port_op
.r
.ctch
.signature_ref
->set_my_scope(p_scope
);
1694 if(port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_my_scope(p_scope
);
1695 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1696 if(port_op
.r
.redirect
.value
)
1697 port_op
.r
.redirect
.value
->set_my_scope(p_scope
);
1698 if(port_op
.r
.redirect
.sender
)
1699 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1702 if(port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1703 if(port_op
.r
.fromclause
) port_op
.r
.fromclause
->set_my_scope(p_scope
);
1704 if(port_op
.r
.redirect
.sender
)
1705 port_op
.r
.redirect
.sender
->set_my_scope(p_scope
);
1711 if (port_op
.portref
) port_op
.portref
->set_my_scope(p_scope
);
1714 comp_op
.compref
->set_my_scope(p_scope
);
1715 comp_op
.funcinstref
->set_my_scope(p_scope
);
1717 case S_START_COMP_REFD
:
1718 comp_op
.compref
->set_my_scope(p_scope
);
1719 comp_op
.derefered
.value
->set_my_scope(p_scope
);
1720 comp_op
.derefered
.t_list1
->set_my_scope(p_scope
);
1725 if (comp_op
.compref
) comp_op
.compref
->set_my_scope(p_scope
);
1728 if (comp_op
.compref
) {
1729 comp_op
.compref
->set_my_scope(p_scope
);
1730 if (comp_op
.donereturn
.donematch
)
1731 comp_op
.donereturn
.donematch
->set_my_scope(p_scope
);
1732 if (comp_op
.donereturn
.redirect
)
1733 comp_op
.donereturn
.redirect
->set_my_scope(p_scope
);
1740 config_op
.compref1
->set_my_scope(p_scope
);
1741 config_op
.portref1
->set_my_scope(p_scope
);
1742 config_op
.compref2
->set_my_scope(p_scope
);
1743 config_op
.portref2
->set_my_scope(p_scope
);
1746 timer_op
.timerref
->set_my_scope(p_scope
);
1747 if (timer_op
.value
) timer_op
.value
->set_my_scope(p_scope
);
1751 if (timer_op
.timerref
) timer_op
.timerref
->set_my_scope(p_scope
);
1754 setverdict
.verdictval
->set_my_scope(p_scope
);
1755 if (setverdict
.logargs
)
1756 setverdict
.logargs
->set_my_scope(p_scope
);
1758 case S_TESTCASE_INSTANCE
:
1759 testcase_inst
.tcref
->set_my_scope(p_scope
);
1760 if (testcase_inst
.timerval
) testcase_inst
.timerval
->set_my_scope(p_scope
);
1762 case S_TESTCASE_INSTANCE_REFD
:
1763 execute_refd
.value
->set_my_scope(p_scope
);
1764 execute_refd
.t_list1
->set_my_scope(p_scope
);
1765 if(execute_refd
.timerval
) execute_refd
.timerval
->set_my_scope(p_scope
);
1767 case S_ACTIVATE_REFD
:
1768 case S_UNKNOWN_INVOKED
:
1769 case S_FUNCTION_INVOKED
:
1770 case S_ALTSTEP_INVOKED
:
1771 fau_refd
.value
->set_my_scope(p_scope
);
1772 fau_refd
.t_list1
->set_my_scope(p_scope
);
1776 convert_op
.val
->set_my_scope(p_scope
);
1777 convert_op
.ref
->set_my_scope(p_scope
);
1780 FATAL_ERROR("Statement::set_my_scope()");
1781 } // switch statementtype
1784 void Statement::set_fullname(const string
& p_fullname
)
1786 Node::set_fullname(p_fullname
);
1787 switch (statementtype
) {
1795 case S_START_PROFILER
:
1796 case S_STOP_PROFILER
:
1800 undefstartstop
.ref
->set_fullname(p_fullname
+".ref");
1801 if (undefstartstop
.val
)
1802 undefstartstop
.val
->set_fullname(p_fullname
+".val");
1804 case S_UNKNOWN_INSTANCE
:
1805 case S_FUNCTION_INSTANCE
:
1806 case S_ALTSTEP_INSTANCE
:
1808 ref_pard
->set_fullname(p_fullname
+".ref");
1811 def
->set_fullname(p_fullname
+".def");
1814 ass
->set_fullname(p_fullname
+".ass");
1817 block
->set_fullname(p_fullname
+".block");
1821 case S_STOP_TESTCASE
:
1822 if (logargs
) logargs
->set_fullname(p_fullname
+".logargs");
1825 if_stmt
.ics
->set_fullname(p_fullname
+".ifclauses");
1826 if (if_stmt
.elseblock
)
1827 if_stmt
.elseblock
->set_fullname(p_fullname
+".elseblock");
1830 select
.expr
->set_fullname(p_fullname
+".expr");
1831 select
.scs
->set_fullname(p_fullname
+".scs");
1834 if(loop
.for_stmt
.varinst
)
1835 loop
.for_stmt
.init_varinst
->set_fullname(p_fullname
+".init");
1837 loop
.for_stmt
.init_ass
->set_fullname(p_fullname
+".init");
1838 loop
.for_stmt
.finalexpr
->set_fullname(p_fullname
+".final");
1839 loop
.for_stmt
.step
->set_fullname(p_fullname
+".step");
1840 loop
.block
->set_fullname(p_fullname
+".block");
1844 loop
.expr
->set_fullname(p_fullname
+".expr");
1845 loop
.block
->set_fullname(p_fullname
+".block");
1849 ags
->set_fullname(p_fullname
+".ags");
1852 if (returnexpr
.v
) returnexpr
.v
->set_fullname(p_fullname
+".returnexpr");
1853 if (returnexpr
.t
) returnexpr
.t
->set_fullname(p_fullname
+".returnexpr");
1856 if (deactivate
) deactivate
->set_fullname(p_fullname
+".deact");
1859 port_op
.portref
->set_fullname(p_fullname
+".portref");
1860 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1861 if(port_op
.s
.toclause
)
1862 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1865 port_op
.portref
->set_fullname(p_fullname
+".portref");
1866 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1867 if(port_op
.s
.toclause
)
1868 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1869 if(port_op
.s
.call
.timer
)
1870 port_op
.s
.call
.timer
->set_fullname(p_fullname
+".timer");
1871 if(port_op
.s
.call
.body
)
1872 port_op
.s
.call
.body
->set_fullname(p_fullname
+".body");
1875 port_op
.portref
->set_fullname(p_fullname
+".portref");
1876 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1877 if(port_op
.s
.replyval
)
1878 port_op
.s
.replyval
->set_fullname(p_fullname
+".replyval");
1879 if(port_op
.s
.toclause
)
1880 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1883 port_op
.portref
->set_fullname(p_fullname
+".portref");
1884 port_op
.s
.raise
.signature_ref
->set_fullname(p_fullname
+".sign");
1885 port_op
.s
.sendpar
->set_fullname(p_fullname
+".sendpar");
1886 if(port_op
.s
.toclause
)
1887 port_op
.s
.toclause
->set_fullname(p_fullname
+".to");
1890 case S_CHECK_RECEIVE
:
1892 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1893 if(port_op
.r
.rcvpar
)
1894 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1895 if(port_op
.r
.fromclause
)
1896 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1897 if(port_op
.r
.redirect
.value
)
1898 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1899 if(port_op
.r
.redirect
.sender
)
1900 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1903 case S_CHECK_GETCALL
:
1904 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1905 if(port_op
.r
.rcvpar
)
1906 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1907 if(port_op
.r
.fromclause
)
1908 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1909 if(port_op
.r
.redirect
.param
)
1910 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1911 if(port_op
.r
.redirect
.sender
)
1912 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1915 case S_CHECK_GETREPLY
:
1916 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1917 if(port_op
.r
.rcvpar
)
1918 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1919 if(port_op
.r
.getreply_valuematch
)
1920 port_op
.r
.getreply_valuematch
->set_fullname(p_fullname
+".valmatch");
1921 if(port_op
.r
.fromclause
)
1922 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1923 if(port_op
.r
.redirect
.value
)
1924 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1925 if(port_op
.r
.redirect
.param
)
1926 port_op
.r
.redirect
.param
->set_fullname(p_fullname
+".pars");
1927 if(port_op
.r
.redirect
.sender
)
1928 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1932 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1933 if(port_op
.r
.ctch
.signature_ref
)
1934 port_op
.r
.ctch
.signature_ref
->set_fullname(p_fullname
+".sign");
1935 if(port_op
.r
.rcvpar
)
1936 port_op
.r
.rcvpar
->set_fullname(p_fullname
+".rcvpar");
1937 if(port_op
.r
.fromclause
)
1938 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1939 if(port_op
.r
.redirect
.value
)
1940 port_op
.r
.redirect
.value
->set_fullname(p_fullname
+".redirval");
1941 if(port_op
.r
.redirect
.sender
)
1942 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1945 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1946 if(port_op
.r
.fromclause
)
1947 port_op
.r
.fromclause
->set_fullname(p_fullname
+".from");
1948 if(port_op
.r
.redirect
.sender
)
1949 port_op
.r
.redirect
.sender
->set_fullname(p_fullname
+".redirsender");
1955 if(port_op
.portref
) port_op
.portref
->set_fullname(p_fullname
+".portref");
1958 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1959 comp_op
.funcinstref
->set_fullname(p_fullname
+".funcref");
1961 case S_START_COMP_REFD
:
1962 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1963 comp_op
.derefered
.value
->set_fullname(p_fullname
+".funcref");
1964 comp_op
.derefered
.t_list1
->set_fullname(p_fullname
+".<parameters>");
1969 if (comp_op
.compref
) comp_op
.compref
->set_fullname(p_fullname
+".compref");
1972 if(comp_op
.compref
) {
1973 comp_op
.compref
->set_fullname(p_fullname
+".compref");
1974 if(comp_op
.donereturn
.donematch
)
1975 comp_op
.donereturn
.donematch
->set_fullname(p_fullname
+".donematch");
1976 if(comp_op
.donereturn
.redirect
)
1977 comp_op
.donereturn
.redirect
->set_fullname(p_fullname
+".redir");
1984 config_op
.compref1
->set_fullname(p_fullname
+".compref1");
1985 config_op
.portref1
->set_fullname(p_fullname
+".portref1");
1986 config_op
.compref2
->set_fullname(p_fullname
+".compref2");
1987 config_op
.portref2
->set_fullname(p_fullname
+".portref2");
1990 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1991 if(timer_op
.value
) timer_op
.value
->set_fullname(p_fullname
+".timerval");
1995 if (timer_op
.timerref
)
1996 timer_op
.timerref
->set_fullname(p_fullname
+".timerref");
1999 setverdict
.verdictval
->set_fullname(p_fullname
+".verdictval");
2000 if (setverdict
.logargs
)
2001 setverdict
.logargs
->set_fullname(p_fullname
+".verdictreason");
2003 case S_TESTCASE_INSTANCE
:
2004 testcase_inst
.tcref
->set_fullname(p_fullname
+".tcref");
2005 if (testcase_inst
.timerval
)
2006 testcase_inst
.timerval
->set_fullname(p_fullname
+".timerval");
2008 case S_TESTCASE_INSTANCE_REFD
:
2009 execute_refd
.value
->set_fullname(p_fullname
+".tcref");
2010 execute_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
2011 if(execute_refd
.timerval
)
2012 execute_refd
.timerval
->set_fullname(p_fullname
+".timerval");
2014 case S_ACTIVATE_REFD
:
2015 case S_UNKNOWN_INVOKED
:
2016 case S_FUNCTION_INVOKED
:
2017 case S_ALTSTEP_INVOKED
:
2018 fau_refd
.value
->set_fullname(p_fullname
+".ref");
2019 fau_refd
.t_list1
->set_fullname(p_fullname
+".<parameters>");
2023 convert_op
.val
->set_fullname(p_fullname
+".ti");
2024 convert_op
.ref
->set_fullname(p_fullname
+".ref");
2027 FATAL_ERROR("Statement::set_fullname()");
2028 } // switch statementtype
2031 void Statement::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
2034 switch(statementtype
) {
2036 block
->set_my_sb(p_sb
, p_index
);
2039 label
.stmt_idx
= p_index
;
2042 go_to
.stmt_idx
= p_index
;
2045 if_stmt
.ics
->set_my_sb(p_sb
, p_index
);
2046 if(if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_sb(p_sb
, p_index
);
2049 select
.scs
->set_my_sb(p_sb
, p_index
);
2054 loop
.block
->set_my_sb(p_sb
, p_index
);
2058 ags
->set_my_sb(p_sb
, p_index
);
2061 if(port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_sb(p_sb
, p_index
);
2065 } // switch statementtype
2068 void Statement::set_my_def(Definition
*p_def
)
2070 switch (statementtype
) {
2072 block
->set_my_def(p_def
);
2075 if_stmt
.ics
->set_my_def(p_def
);
2076 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_def(p_def
);
2079 select
.scs
->set_my_def(p_def
);
2084 loop
.block
->set_my_def(p_def
);
2088 ags
->set_my_def(p_def
);
2091 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->set_my_def(p_def
);
2095 } // switch statementtype
2098 void Statement::set_my_ags(AltGuards
*p_ags
)
2100 switch (statementtype
) {
2102 block
->set_my_ags(p_ags
);
2105 if_stmt
.ics
->set_my_ags(p_ags
);
2106 if (if_stmt
.elseblock
) if_stmt
.elseblock
->set_my_ags(p_ags
);
2109 select
.scs
->set_my_ags(p_ags
);
2114 loop
.block
->set_my_ags(p_ags
);
2121 } // switch statementtype
2124 void Statement::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
2126 switch (statementtype
) {
2128 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2131 if_stmt
.ics
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2132 if (if_stmt
.elseblock
)
2133 if_stmt
.elseblock
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2136 select
.scs
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
2141 ags
->set_my_laic_stmt(0, p_loop_stmt
); // ags is set later
2144 if (p_loop_stmt
&& port_op
.s
.call
.body
)
2145 port_op
.s
.call
.body
->set_my_laic_stmt(0, p_loop_stmt
);
2151 brk_cnt
.loop_stmt
=p_loop_stmt
;
2156 } // switch statementtype
2159 /** \todo handle blocks, loops and conditional statements
2160 * (i.e. investigate their last statements within the block) */
2161 bool Statement::is_terminating() const
2163 switch (statementtype
) {
2168 case S_STOP_TESTCASE
:
2174 // checking for self.stop, self.kill, mtc.stop and mtc.kill
2175 if (comp_op
.compref
) {
2176 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
2177 if (v_last
->get_valuetype() == Value::V_EXPR
) {
2178 switch (v_last
->get_optype()) {
2179 case Value::OPTYPE_COMP_SELF
:
2180 case Value::OPTYPE_COMP_MTC
:
2190 if(!loop
.expr
->is_unfoldable() && loop
.expr
->get_val_bool()) {
2191 return !loop
.has_brk
; // not endless loop if it has a break
2199 StatementBlock::returnstatus_t
Statement::has_return() const
2201 switch (statementtype
) {
2203 return block
->has_return();
2205 return if_stmt
.ics
->has_return(if_stmt
.elseblock
);
2207 return select
.scs
->has_return();
2210 if (loop
.block
->has_return() == StatementBlock::RS_NO
)
2211 return StatementBlock::RS_NO
;
2212 else return StatementBlock::RS_MAYBE
;
2214 return loop
.block
->has_return();
2216 StatementBlock::returnstatus_t ret_val
= ags
->has_return();
2217 if (ret_val
== StatementBlock::RS_YES
&& !ags
->has_else()) {
2218 // the invoked defaults may skip the entire statement
2219 ret_val
= StatementBlock::RS_MAYBE
;
2223 if (port_op
.s
.call
.body
) return port_op
.s
.call
.body
->has_return();
2224 else return StatementBlock::RS_NO
;
2226 if (is_terminating()) return StatementBlock::RS_YES
;
2227 else return StatementBlock::RS_NO
;
2231 bool Statement::is_receiving_stmt() const
2233 switch (statementtype
) {
2236 case S_ALTSTEP_INSTANCE
:
2237 case S_ALTSTEP_INVOKED
:
2239 case S_CHECK_RECEIVE
:
2242 case S_CHECK_GETCALL
:
2244 case S_CHECK_GETREPLY
:
2254 } // switch statementtype
2257 bool Statement::has_receiving_stmt() const
2259 switch (statementtype
) {
2262 case S_FUNCTION_INSTANCE
:
2263 case S_FUNCTION_INVOKED
:
2272 case S_STOP_TESTCASE
:
2276 case S_ACTIVATE_REFD
:
2286 case S_START_COMP_REFD
:
2296 case S_TESTCASE_INSTANCE
:
2297 case S_TESTCASE_INSTANCE_REFD
:
2298 case S_START_PROFILER
:
2299 case S_STOP_PROFILER
:
2304 case S_ALTSTEP_INSTANCE
:
2305 case S_ALTSTEP_INVOKED
:
2307 case S_CHECK_RECEIVE
:
2310 case S_CHECK_GETCALL
:
2312 case S_CHECK_GETREPLY
:
2321 return block
->has_receiving_stmt();
2323 return if_stmt
.ics
->has_receiving_stmt()
2324 || (if_stmt
.elseblock
&& if_stmt
.elseblock
->has_receiving_stmt());
2326 return select
.scs
->has_receiving_stmt();
2330 return loop
.block
->has_receiving_stmt();
2332 return port_op
.s
.call
.body
&& port_op
.s
.call
.body
->has_receiving_stmt();
2336 case S_UNKNOWN_INSTANCE
:
2337 case S_UNKNOWN_INVOKED
:
2339 FATAL_ERROR("Statement::has_receiving_stmt()");
2340 } // switch statementtype
2343 bool Statement::can_repeat() const
2345 switch (statementtype
) {
2351 case S_CHECK_RECEIVE
:
2353 case S_CHECK_GETCALL
:
2355 case S_CHECK_GETREPLY
:
2362 FATAL_ERROR("Statement::can_repeat()");
2363 } // switch statementtype
2366 void Statement::chk()
2368 switch (statementtype
) {
2377 case S_UNKNOWN_INSTANCE
:
2378 chk_unknown_instance();
2380 case S_UNKNOWN_INVOKED
:
2381 case S_FUNCTION_INVOKED
:
2382 case S_ALTSTEP_INVOKED
:
2383 chk_unknown_invoke();
2387 my_sb
->register_def(def
);
2392 case S_FUNCTION_INSTANCE
:
2400 case S_STOP_TESTCASE
:
2401 chk_log_action(logargs
);
2442 case S_ALTSTEP_INSTANCE
:
2451 case S_ACTIVATE_REFD
:
2452 chk_activate_refd();
2470 case S_CHECK_RECEIVE
:
2475 case S_CHECK_GETCALL
:
2479 case S_CHECK_GETREPLY
:
2495 chk_start_stop_port();
2500 case S_START_COMP_REFD
:
2501 chk_start_comp_refd();
2505 chk_stop_kill_comp();
2526 chk_stop_timer_timeout();
2530 chk_log_action(setverdict
.logargs
); // for checking verdictreason
2532 case S_TESTCASE_INSTANCE
:
2535 case S_TESTCASE_INSTANCE_REFD
:
2544 case S_START_PROFILER
:
2545 case S_STOP_PROFILER
:
2549 FATAL_ERROR("Statement::chk()");
2550 } // switch statementtype
2553 void Statement::chk_string2ttcn()
2555 Error_Context
cntxt(this, "In string2ttcn() statement");
2556 convert_op
.val
->chk_expr_type(Type::T_CSTR
, "charstring", Type::EXPECTED_DYNAMIC_VALUE
);
2558 Common::Assignment
* refd_ass
= convert_op
.ref
->get_refd_assignment();
2559 if (refd_ass
==NULL
) {
2560 error("Could not determine the assignment for second parameter");
2563 switch (refd_ass
->get_asstype()) {
2564 case Definition::A_PAR_VAL_IN
:
2565 case Definition::A_PAR_TEMPL_IN
:
2566 refd_ass
->use_as_lvalue(*convert_op
.ref
);
2567 case Definition::A_VAR
:
2568 case Definition::A_VAR_TEMPLATE
:
2569 case Definition::A_PAR_VAL_OUT
:
2570 case Definition::A_PAR_VAL_INOUT
:
2571 case Definition::A_PAR_TEMPL_OUT
:
2572 case Definition::A_PAR_TEMPL_INOUT
:
2573 // valid assignment types
2576 convert_op
.ref
->error("Reference to '%s' cannot be used as the second parameter", refd_ass
->get_assname());
2581 delete convert_op
.val
;
2582 delete convert_op
.ref
;
2583 statementtype
= S_ERROR
;
2586 void Statement::chk_int2enum()
2588 Error_Context
cntxt(this, "In int2enum() statement");
2589 convert_op
.val
->chk_expr_type(Type::T_INT
, "integer", Type::EXPECTED_DYNAMIC_VALUE
);
2591 Common::Assignment
* refd_ass
= convert_op
.ref
->get_refd_assignment();
2592 if (refd_ass
==NULL
) {
2593 error("Could not determine the assignment for second parameter");
2596 if (Type::T_ENUM_T
!= convert_op
.ref
->chk_variable_ref()->get_type_refd_last()->get_typetype_ttcn3()) {
2597 convert_op
.ref
->error("A reference to variable or value parameter of "
2598 "type enumerated was expected");
2603 delete convert_op
.val
;
2604 delete convert_op
.ref
;
2605 statementtype
= S_ERROR
;
2608 void Statement::chk_allowed_interleave()
2610 switch (statementtype
) {
2612 block
->chk_allowed_interleave();
2615 error("Label statement is not allowed within an interleave statement");
2618 error("Goto statement is not allowed within an interleave statement");
2621 if_stmt
.ics
->chk_allowed_interleave();
2622 if (if_stmt
.elseblock
) if_stmt
.elseblock
->chk_allowed_interleave();
2625 select
.scs
->chk_allowed_interleave();
2630 loop
.block
->chk_allowed_interleave();
2633 ags
->chk_allowed_interleave();
2636 error("Repeat statement is not allowed within an interleave statement");
2638 case S_ALTSTEP_INSTANCE
:
2639 error("Invocation of an altstep is not allowed within an interleave "
2642 case S_ALTSTEP_INVOKED
:
2643 error("Invocation of an altstep type is not allowed within an interleave"
2647 error("Return statement is not allowed within an interleave statement");
2650 if (port_op
.s
.call
.body
) port_op
.s
.call
.body
->chk_allowed_interleave();
2653 // the other statements are allowed
2658 void Statement::chk_start_undef()
2660 Ref_base
*t_ref
= undefstartstop
.ref
;
2661 Value
*t_val
= undefstartstop
.val
;
2662 Common::Assignment
*t_ass
;
2664 Error_Context
cntxt(this, "In start statement");
2665 t_ass
= t_ref
->get_refd_assignment();
2667 if (!t_ass
) goto error
;
2668 switch (t_ass
->get_asstype()) {
2669 case Definition::A_PORT
:
2670 case Definition::A_PAR_PORT
:
2671 statementtype
= S_START_PORT
;
2672 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2673 if (!port_op
.portref
) goto error
;
2675 t_val
->error("Start port operation cannot have argument");
2678 chk_start_stop_port();
2680 case Definition::A_TIMER
:
2681 case Definition::A_PAR_TIMER
:
2682 statementtype
= S_START_TIMER
;
2683 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2684 if (!timer_op
.timerref
) goto error
;
2685 timer_op
.value
= t_val
;
2688 case Definition::A_CONST
:
2689 case Definition::A_EXT_CONST
:
2690 case Definition::A_MODULEPAR
:
2691 case Definition::A_VAR
:
2692 case Definition::A_FUNCTION_RVAL
:
2693 case Definition::A_EXT_FUNCTION_RVAL
:
2694 case Definition::A_PAR_VAL_IN
:
2695 case Definition::A_PAR_VAL_OUT
:
2696 case Definition::A_PAR_VAL_INOUT
:
2697 statementtype
= S_START_COMP
;
2699 error("The argument of start operation is missing, although it cannot "
2700 "be a start timer or start port operation");
2702 } else if (t_val
->get_valuetype() != Value::V_REFD
) {
2703 t_val
->error("The argument of start operation is not a function, "
2704 "although it cannot be a start timer or start port operation");
2707 comp_op
.funcinstref
= t_val
->steal_ttcn_ref_base();
2710 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2711 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2712 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2713 comp_op
.compref
->set_location(*t_ref
);
2717 t_ref
->error("Port, timer or component reference was expected as the "
2718 "operand of start operation instead of %s",
2719 t_ass
->get_description().c_str());
2726 statementtype
= S_ERROR
;
2729 void Statement::chk_stop_undef()
2731 Ref_base
*t_ref
= undefstartstop
.ref
;
2732 Common::Assignment
*t_ass
;
2734 Error_Context
cntxt(this, "In stop statement");
2735 t_ass
= t_ref
->get_refd_assignment();
2737 if (!t_ass
) goto error
;
2738 // Determine what it is that we are trying to stop; change statementtype
2739 switch (t_ass
->get_asstype()) {
2740 case Definition::A_PORT
:
2741 case Definition::A_PAR_PORT
:
2742 statementtype
= S_STOP_PORT
;
2743 port_op
.portref
= dynamic_cast<Reference
*>(t_ref
);
2744 if (!port_op
.portref
) goto error
;
2745 chk_start_stop_port();
2747 case Definition::A_TIMER
:
2748 case Definition::A_PAR_TIMER
:
2749 statementtype
= S_STOP_TIMER
;
2750 timer_op
.timerref
= dynamic_cast<Reference
*>(t_ref
);
2751 if (!timer_op
.timerref
) goto error
;
2753 chk_stop_timer_timeout();
2755 case Definition::A_CONST
:
2756 case Definition::A_EXT_CONST
:
2757 case Definition::A_MODULEPAR
:
2758 case Definition::A_VAR
:
2759 case Definition::A_FUNCTION_RVAL
:
2760 case Definition::A_EXT_FUNCTION_RVAL
:
2761 case Definition::A_PAR_VAL_IN
:
2762 case Definition::A_PAR_VAL_OUT
:
2763 case Definition::A_PAR_VAL_INOUT
:
2764 statementtype
= S_STOP_COMP
;
2765 comp_op
.compref
= new Value(Value::V_REFD
, t_ref
);
2766 comp_op
.compref
->set_my_scope(t_ref
->get_my_scope());
2767 comp_op
.compref
->set_fullname(t_ref
->get_fullname());
2768 comp_op
.compref
->set_location(*t_ref
);
2769 chk_stop_kill_comp();
2772 t_ref
->error("Port, timer or component reference was expected as the "
2773 "operand of stop operation instead of %s",
2774 t_ass
->get_description().c_str());
2780 statementtype
= S_ERROR
;
2783 void Statement::chk_unknown_instance()
2785 Common::Assignment
*t_ass
;
2787 Error_Context
cntxt(this, "In function or altstep instance");
2788 t_ass
= ref_pard
->get_refd_assignment(false);
2790 if (!t_ass
) goto error
;
2791 switch (t_ass
->get_asstype()) {
2792 case Common::Assignment::A_FUNCTION
:
2793 case Common::Assignment::A_FUNCTION_RVAL
:
2794 case Common::Assignment::A_FUNCTION_RTEMP
:
2795 case Common::Assignment::A_EXT_FUNCTION
:
2796 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2797 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2798 statementtype
= S_FUNCTION_INSTANCE
;
2801 case Common::Assignment::A_ALTSTEP
:
2802 statementtype
= S_ALTSTEP_INSTANCE
;
2806 ref_pard
->error("Reference to a function or altstep was expected "
2807 "instead of %s, which cannot be invoked",
2808 t_ass
->get_description().c_str());
2814 statementtype
= S_ERROR
;
2817 void Statement::chk_unknown_invoke()
2819 Error_Context
cntxt(this, "In apply operation");
2820 Type
*t
= fau_refd
.value
->get_expr_governor_last();
2822 switch (t
->get_typetype()) {
2825 case Type::T_FUNCTION
:
2826 statementtype
= S_FUNCTION_INVOKED
;
2827 if (t
->get_function_return_type()) warning("The value returned by "
2828 "function type `%s' is not used", t
->get_typename().c_str());
2830 case Type::T_ALTSTEP
:
2831 statementtype
= S_ALTSTEP_INVOKED
;
2834 fau_refd
.value
->error("A value of type function or altstep was "
2835 "expected instead of `%s'", t
->get_typename().c_str());
2838 my_sb
->chk_runs_on_clause(t
, *this, "call");
2840 ActualParList
*parlist
= new Ttcn::ActualParList
;
2841 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
2842 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
2844 delete fau_refd
.t_list1
;
2847 fau_refd
.ap_list2
= 0;
2849 parlist
->set_fullname(get_fullname());
2850 parlist
->set_my_scope(my_sb
);
2851 fau_refd
.ap_list2
= parlist
;
2857 statementtype
= S_ERROR
;
2860 void Statement::chk_assignment()
2862 Error_Context
cntxt(this, "In variable assignment");
2866 void Statement::chk_function()
2868 Error_Context
cntxt(this, "In function instance");
2869 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
2870 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
2871 if (t_ass
->get_Type())
2872 ref_pard
->warning("The value returned by %s is not used",
2873 t_ass
->get_description().c_str());
2876 void Statement::chk_block()
2878 Error_Context
cntxt(this, "In statement block");
2882 void Statement::chk_log_action(LogArguments
*lga
)
2884 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
2887 if (!semantic_check_only
) lga
->join_strings();
2891 void Statement::chk_goto()
2893 Error_Context
cntxt(this, "In goto statement");
2894 if (!my_sb
->has_label(*go_to
.id
)) {
2895 error("Label `%s' is used, but not defined",
2896 go_to
.id
->get_dispname().c_str());
2898 go_to
.jumps_forward
= false;
2901 Statement
*label_stmt
= my_sb
->get_label(*go_to
.id
);
2902 label_stmt
->label
.used
= true;
2903 StatementBlock
*label_sb
= label_stmt
->get_my_sb();
2904 // the index of the label in its own statement block
2905 size_t label_idx
= label_stmt
->get_my_sb_index();
2906 // the index of the goto statement (or its parent statement) in the
2907 // statement block of the label
2909 if (my_sb
== label_sb
) goto_idx
= go_to
.stmt_idx
;
2911 // the goto statement is within a nested statement block
2912 StatementBlock
*goto_sb
= my_sb
, *parent_sb
= my_sb
->get_my_sb();
2913 while (parent_sb
!= label_sb
) {
2914 // go up until the block of the label is found
2915 if (!parent_sb
) FATAL_ERROR("Statement::chk_goto()");
2916 goto_sb
= parent_sb
;
2917 parent_sb
= parent_sb
->get_my_sb();
2919 goto_idx
= goto_sb
->get_my_sb_index();
2921 if (label_idx
> goto_idx
) {
2922 bool error_flag
= false;
2923 for (size_t i
= goto_idx
+ 1; i
< label_idx
; i
++) {
2924 Statement
*stmt
= label_sb
->get_stmt_byIndex(i
);
2925 if (stmt
->get_statementtype() != S_DEF
) continue;
2927 error("Jump to label `%s' crosses local definition",
2928 go_to
.id
->get_dispname().c_str());
2931 stmt
->note("Definition of %s is here",
2932 stmt
->get_def()->get_description().c_str());
2935 label_stmt
->note("Label `%s' is here",
2936 go_to
.id
->get_dispname().c_str());
2937 go_to
.jumps_forward
= true;
2938 } else go_to
.jumps_forward
= false;
2939 go_to
.label
= label_stmt
;
2942 void Statement::chk_if()
2945 if_stmt
.ics
->chk(unreach
);
2946 if(if_stmt
.elseblock
) {
2947 Error_Context
cntxt(if_stmt
.elseblock_location
, "In else statement");
2948 if(unreach
) if_stmt
.elseblock_location
->warning
2949 ("Control never reaches this code because of previous effective"
2951 if_stmt
.elseblock
->chk();
2956 void Statement::chk_select()
2958 Error_Context
cntxt(this, "In select case statement");
2960 for(int turn
=0; turn
<2; turn
++) {
2961 if(turn
) select
.expr
->set_lowerid_to_ref();
2962 Type::typetype_t tt
=select
.expr
->get_expr_returntype();
2963 t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2964 if(!t_gov
|| tt
==Type::T_ERROR
) {
2965 SelectCases
*scs
=select
.scs
;
2966 for(size_t i
=0; i
<scs
->get_nof_scs(); i
++) {
2967 TemplateInstances
*tis
=scs
->get_sc_byIndex(i
)->get_tis();
2969 for(size_t j
=0; j
<tis
->get_nof_tis(); j
++) {
2970 TemplateInstance
*ti
=tis
->get_ti_byIndex(j
);
2971 if(turn
) ti
->get_Template()->set_lowerid_to_ref();
2972 t_gov
=ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
2973 tt
=ti
->get_expr_returntype(Type::EXPECTED_TEMPLATE
);
2974 if(t_gov
&& tt
!=Type::T_ERROR
) break;
2979 else t_gov
=select
.expr
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
2982 select
.expr
->error("Cannot determine the type of the expression");
2983 t_gov
=Type::get_pooltype(Type::T_ERROR
);
2985 select
.expr
->set_my_governor(t_gov
);
2986 t_gov
->chk_this_value_ref(select
.expr
);
2987 t_gov
->chk_this_value(select
.expr
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
2988 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2989 select
.scs
->chk(t_gov
);
2992 void Statement::chk_for()
2994 Error_Context
cntxt(this, "In for statement");
2995 if (loop
.for_stmt
.varinst
) loop
.for_stmt
.init_varinst
->chk_for();
2996 else loop
.for_stmt
.init_ass
->chk();
2997 loop
.for_stmt
.finalexpr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
2998 if(!loop
.for_stmt
.finalexpr
->is_unfoldable()
2999 && !loop
.for_stmt
.finalexpr
->get_val_bool())
3000 loop
.for_stmt
.finalexpr
->warning
3001 ("Control never reaches this code because the"
3002 " final conditional expression evals to false");
3003 loop
.for_stmt
.step
->chk();
3004 loop
.block
->set_my_laic_stmt(0, this);
3008 void Statement::chk_while()
3010 Error_Context
cntxt(this, "In while statement");
3011 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
3012 if(!loop
.expr
->is_unfoldable() && !loop
.expr
->get_val_bool())
3013 loop
.expr
->warning("Control never reaches this code because the"
3014 " conditional expression evals to false");
3015 loop
.block
->set_my_laic_stmt(0, this);
3019 void Statement::chk_do_while()
3021 Error_Context
cntxt(this, "In do-while statement");
3022 loop
.block
->set_my_laic_stmt(0, this);
3024 loop
.expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
3027 void Statement::chk_break()
3029 Error_Context
cntxt(this, "In break statement");
3030 if (!brk_cnt
.loop_stmt
&& !brk_cnt
.ags
)
3031 error("Break statement cannot be used outside loops, alt or interleave"
3032 " statements, altsteps or response and exception handling part of call"
3034 if (brk_cnt
.loop_stmt
)
3035 brk_cnt
.loop_stmt
->loop
.has_brk
=true;
3038 void Statement::chk_continue()
3040 Error_Context
cntxt(this, "In continue statement");
3041 if (brk_cnt
.loop_stmt
) {
3042 brk_cnt
.loop_stmt
->loop
.has_cnt
=true;
3043 if (brk_cnt
.ags
) brk_cnt
.loop_stmt
->loop
.has_cnt_in_ags
=true;
3045 error("Continue statement cannot be used outside loops");
3048 void Statement::chk_alt()
3050 Error_Context
cntxt(this, "In alt construct");
3051 ags
->set_my_ags(ags
);
3052 ags
->set_my_laic_stmt(ags
, 0);
3056 void Statement::chk_repeat()
3058 Error_Context
cntxt(this, "In repeat statement");
3059 if (ags
) ags
->repeat_found();
3060 else error("Repeat statement cannot be used outside alt statements, "
3061 "altsteps or response and exception handling part of call operations");
3064 void Statement::chk_interleave()
3066 Error_Context
cntxt(this, "In interleave statement");
3067 ags
->set_my_laic_stmt(ags
, 0);
3069 ags
->chk_allowed_interleave();
3072 void Statement::chk_altstep()
3074 Error_Context
cntxt(this, "In altstep instance");
3075 Common::Assignment
*t_ass
= ref_pard
->get_refd_assignment();
3076 my_sb
->chk_runs_on_clause(t_ass
, *ref_pard
, "call");
3079 void Statement::chk_return()
3081 Error_Context
cntxt(this, "In return statement");
3082 Definition
*my_def
= my_sb
->get_my_def();
3084 error("Return statement cannot be used in the control part. "
3085 "It is allowed only in functions and altsteps");
3088 switch (my_def
->get_asstype()) {
3089 case Definition::A_FUNCTION
:
3091 returnexpr
.t
->error("Unexpected return value. The function does not "
3092 "have return type");
3096 case Definition::A_FUNCTION_RVAL
:
3097 if (!returnexpr
.t
) {
3098 error("Missing return value. The function should return a value of "
3099 "type `%s'", my_def
->get_Type()->get_typename().c_str());
3101 } else if (!returnexpr
.t
->is_Value()) {
3102 returnexpr
.t
->error("A specific value without matching symbols was "
3103 "expected as return value");
3106 returnexpr
.v
= returnexpr
.t
->get_Value();
3107 delete returnexpr
.t
;
3109 Type
*return_type
= my_def
->get_Type();
3110 returnexpr
.v
->set_my_governor(return_type
);
3111 return_type
->chk_this_value_ref(returnexpr
.v
);
3112 return_type
->chk_this_value(returnexpr
.v
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
3113 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
3116 case Definition::A_FUNCTION_RTEMP
:
3117 if (!returnexpr
.t
) {
3118 error("Missing return template. The function should return a template "
3119 "of type `%s'", my_def
->get_Type()->get_typename().c_str());
3122 Type
*return_type
= my_def
->get_Type();
3123 returnexpr
.t
->set_my_governor(return_type
);
3124 return_type
->chk_this_template_ref(returnexpr
.t
);
3125 return_type
->chk_this_template_generic(returnexpr
.t
, INCOMPLETE_NOT_ALLOWED
,
3126 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
3127 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
3128 if (!dfb
) FATAL_ERROR("Statement::chk_return()");
3129 returnexpr
.gen_restriction_check
=
3130 returnexpr
.t
->chk_restriction("return template",
3131 dfb
->get_template_restriction(), this);
3134 case Definition::A_ALTSTEP
:
3136 returnexpr
.t
->error("An altstep cannot return a value");
3141 error("Return statement cannot be used in a %s. It is allowed only in "
3142 "functions and altsteps", my_def
->get_assname());
3147 delete returnexpr
.t
;
3151 void Statement::chk_activate()
3153 Error_Context
cntxt(this, "In activate statement");
3154 if (!ref_pard
->chk_activate_argument()) {
3156 statementtype
= S_ERROR
;
3160 void Statement::chk_activate_refd()
3162 Error_Context
cntxt(this, "In activate statement");
3163 Type
*t
= fau_refd
.value
->get_expr_governor_last();
3165 switch (t
->get_typetype()) {
3168 case Type::T_ALTSTEP
:
3171 fau_refd
.value
->error("A value of type altstep was expected in the "
3172 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
3175 if (t
->get_fat_runs_on_self()) {
3176 fau_refd
.value
->error("The argument of `derefers()' cannot be an altstep "
3177 "reference with 'runs on self' clause");
3180 my_sb
->chk_runs_on_clause(t
, *this, "activate");
3182 ActualParList
*parlist
= new ActualParList
;
3183 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
3184 bool is_erroneous
= fp_list
->fold_named_and_chk(fau_refd
.t_list1
,
3186 delete fau_refd
.t_list1
;
3189 fau_refd
.ap_list2
= 0;
3192 parlist
->set_fullname(get_fullname());
3193 parlist
->set_my_scope(my_sb
);
3194 fau_refd
.ap_list2
= parlist
;
3195 if (!fp_list
->chk_activate_argument(parlist
,get_fullname().c_str()))
3202 statementtype
= S_ERROR
;
3205 void Statement::chk_deactivate()
3208 Error_Context
cntxt(this, "In deactivate statement");
3209 deactivate
->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE
);
3213 void Statement::chk_send()
3215 Error_Context
cntxt(this, "In send statement");
3216 // checking the port reference
3217 Type
*port_type
= chk_port_ref(port_op
.portref
);
3218 // determining the message type
3220 bool msg_type_determined
= false;
3222 Ttcn::PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3223 TypeSet
*out_msgs
= port_type_body
->get_out_msgs();
3225 if (out_msgs
->get_nof_types() == 1) {
3226 // there is only one outgoing message type
3227 msg_type
= out_msgs
->get_type_byIndex(0);
3229 // there are more than one outgoing message types
3230 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3232 size_t nof_comp_types
=
3233 out_msgs
->get_nof_compatible_types(msg_type
);
3234 if (nof_comp_types
== 0) {
3235 port_op
.s
.sendpar
->error("Message type `%s' is not present on "
3236 "the outgoing list of port type `%s'",
3237 msg_type
->get_typename().c_str(),
3238 port_type
->get_typename().c_str());
3239 } else if (nof_comp_types
> 1) {
3240 port_op
.s
.sendpar
->error("Type of the message is ambiguous: "
3241 "`%s' is compatible with more than one outgoing message types "
3242 "of port type `%s'", msg_type
->get_typename().c_str(),
3243 port_type
->get_typename().c_str());
3246 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3247 "outgoing message");
3250 msg_type_determined
= true;
3251 } else if (port_type_body
->get_operation_mode() ==
3252 PortTypeBody::PO_PROCEDURE
) {
3253 port_op
.portref
->error("Message-based operation `send' is not "
3254 "applicable to a procedure-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 "message types", port_type
->get_typename().c_str());
3261 // determining the message type if it is not done so far
3262 if (!msg_type_determined
) {
3263 msg_type
= get_outgoing_type(port_op
.s
.sendpar
);
3265 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3266 // checking the parameter (template instance)
3267 port_op
.s
.sendpar
->chk(msg_type
);
3268 // checking for invalid message types
3269 msg_type
= msg_type
->get_type_refd_last();
3270 switch (msg_type
->get_typetype()) {
3271 case Type::T_SIGNATURE
:
3272 port_op
.s
.sendpar
->error("The type of send parameter is signature `%s', "
3273 "which cannot be a message type", msg_type
->get_typename().c_str());
3276 port_op
.s
.sendpar
->error("The type of send parameter is port type `%s', "
3277 "which cannot be a message type", msg_type
->get_typename().c_str());
3279 case Type::T_DEFAULT
:
3280 port_op
.s
.sendpar
->error("The type of send parameter is the `default' "
3281 "type, which cannot be a message type");
3285 // checking for presence of wildcards in the template body
3286 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3287 // checking to clause
3288 chk_to_clause(port_type
);
3291 void Statement::chk_call()
3293 Error_Context
cntxt(this, "In call statement");
3294 // checking the port reference
3295 Type
*port_type
= chk_port_ref(port_op
.portref
);
3296 // determining the signature of the argument
3297 Type
*signature
= 0;
3298 bool signature_determined
= false;
3300 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3301 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3303 if (out_sigs
->get_nof_types() == 1) {
3304 // there is only one outgoing signature
3305 signature
= out_sigs
->get_type_byIndex(0);
3307 // there are more than one outgoing signatures
3308 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3310 if (!out_sigs
->has_type(signature
)) {
3311 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3312 "outgoing list of port type `%s'",
3313 signature
->get_typename().c_str(),
3314 port_type
->get_typename().c_str());
3317 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3321 signature_determined
= true;
3322 } else if (port_type_body
->get_operation_mode() ==
3323 PortTypeBody::PO_MESSAGE
) {
3324 port_op
.portref
->error("Procedure-based operation `call' is not "
3325 "applicable to a message-based port of type `%s'",
3326 port_type
->get_typename().c_str());
3328 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3329 "signatures", port_type
->get_typename().c_str());
3332 if (!signature_determined
)
3333 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3334 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3335 // checking the parameter (template instance)
3336 port_op
.s
.sendpar
->chk(signature
);
3337 signature
= signature
->get_type_refd_last();
3338 bool is_noblock_sig
= false;
3339 Type::typetype_t tt
= signature
->get_typetype();
3341 case Type::T_SIGNATURE
:
3342 // the signature is known and correct
3343 is_noblock_sig
= signature
->is_nonblocking_signature();
3347 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not "
3348 "a signature", signature
->get_typename().c_str());
3350 // checking presence/absence of optional parts
3351 if (is_noblock_sig
) {
3352 if (port_op
.s
.call
.timer
) {
3353 port_op
.s
.call
.timer
->error("A call of non-blocking signature `%s' "
3354 "cannot have call timer", signature
->get_typename().c_str());
3355 } else if (port_op
.s
.call
.nowait
) {
3356 error("A call of non-blocking signature `%s' cannot use the "
3357 "`nowait' keyword", signature
->get_typename().c_str());
3359 if (port_op
.s
.call
.body
) {
3360 error("A call of non-blocking signature `%s' cannot have "
3361 "response and exception handling part",
3362 signature
->get_typename().c_str());
3364 } else if (port_op
.s
.call
.nowait
) {
3365 if (port_op
.s
.call
.body
) {
3366 error("A call with `nowait' keyword cannot have response and "
3367 "exception handling part");
3370 // do not issue any error if the signature is erroneous
3371 // because it could have been a non-blocking one
3372 if (tt
== Type::T_SIGNATURE
&& !port_op
.s
.call
.body
) {
3373 error("Response and exception handling part is missing from "
3374 "blocking call operation");
3377 // checking call timer
3378 if (port_op
.s
.call
.timer
) {
3379 Error_Context
cntxt2(port_op
.s
.call
.timer
, "In call timer value");
3380 port_op
.s
.call
.timer
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
3381 Value
*t_val
= port_op
.s
.call
.timer
->get_value_refd_last();
3382 if (t_val
->get_valuetype() == Value::V_REAL
) {
3383 ttcn3float v_real
= t_val
->get_val_Real();
3385 port_op
.s
.call
.timer
->error("The call timer has "
3386 "negative duration: `%s'", Real2string(v_real
).c_str());
3387 } else if (isSpecialFloatValue(v_real
)) {
3388 port_op
.s
.call
.timer
->error("The call timer duration cannot be %s",
3389 Real2string(v_real
).c_str());
3393 // checking to clause
3394 chk_to_clause(port_type
);
3395 // checking response and exception handling part
3396 if (port_op
.s
.call
.body
) chk_call_body(port_type
, signature
);
3399 void Statement::chk_reply()
3401 Error_Context
cntxt(this, "In reply statement");
3402 // checking the port reference
3403 Type
*port_type
= chk_port_ref(port_op
.portref
);
3404 // determining the signature of the argument
3405 Type
*signature
= 0;
3406 bool signature_determined
= false;
3408 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3409 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3411 if (in_sigs
->get_nof_types() == 1) {
3412 // there is only one incoming signature
3413 signature
= in_sigs
->get_type_byIndex(0);
3415 // there are more than one incoming signatures
3416 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3418 if (!in_sigs
->has_type(signature
)) {
3419 port_op
.s
.sendpar
->error("Signature `%s' is not present on the "
3420 "incoming list of port type `%s'",
3421 signature
->get_typename().c_str(),
3422 port_type
->get_typename().c_str());
3425 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3429 signature_determined
= true;
3430 } else if (port_type_body
->get_operation_mode() ==
3431 PortTypeBody::PO_MESSAGE
) {
3432 port_op
.portref
->error("Procedure-based operation `reply' is not "
3433 "applicable to a message-based port of type `%s'",
3434 port_type
->get_typename().c_str());
3436 port_op
.portref
->error("Port type `%s' does not have any incoming "
3437 "signatures", port_type
->get_typename().c_str());
3440 if (!signature_determined
)
3441 signature
= get_outgoing_type(port_op
.s
.sendpar
);
3442 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3443 // checking the parameter (template instance)
3444 port_op
.s
.sendpar
->chk(signature
);
3445 signature
= signature
->get_type_refd_last();
3446 Type
*return_type
= 0;
3447 switch (signature
->get_typetype()) {
3448 case Type::T_SIGNATURE
:
3449 // the signature is known and correct
3450 if (signature
->is_nonblocking_signature())
3451 error("Operation `reply' is not applicable to non-blocking signature "
3452 "`%s'", signature
->get_typename().c_str());
3453 else return_type
= signature
->get_signature_return_type();
3454 // checking the presence/absence of reply value
3455 if (port_op
.s
.replyval
) {
3457 port_op
.s
.replyval
->error("Unexpected return value. Signature "
3458 "`%s' does not have return type",
3459 signature
->get_typename().c_str());
3461 } else if (return_type
) {
3462 error("Missing return value. Signature `%s' returns type `%s'",
3463 signature
->get_typename().c_str(),
3464 return_type
->get_typename().c_str());
3469 port_op
.s
.sendpar
->error("The type of parameter is `%s', which is not a "
3470 "signature", signature
->get_typename().c_str());
3472 // checking the reply value if present
3473 if (port_op
.s
.replyval
) {
3474 Error_Context
cntxt2(port_op
.s
.replyval
, "In return value");
3475 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3476 port_op
.s
.replyval
->set_my_governor(return_type
);
3477 return_type
->chk_this_value_ref(port_op
.s
.replyval
);
3478 return_type
->chk_this_value(port_op
.s
.replyval
, 0,
3479 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
3482 // checking to clause
3483 chk_to_clause(port_type
);
3486 void Statement::chk_raise()
3488 Error_Context
cntxt(this, "In raise statement");
3489 // checking the port reference
3490 Type
*port_type
= chk_port_ref(port_op
.portref
);
3491 // determining the signature of the exception
3492 port_op
.s
.raise
.signature
=
3493 chk_signature_ref(port_op
.s
.raise
.signature_ref
);
3494 // checking whether the signature is present on the incoming list
3495 // of the respective port type
3497 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3498 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3499 if (port_type_body
->get_operation_mode() ==
3500 PortTypeBody::PO_MESSAGE
) {
3501 port_op
.portref
->error("Procedure-based operation `raise' is not "
3502 "applicable to a message-based port of type `%s'",
3503 port_type
->get_typename().c_str());
3504 } else if (in_sigs
) {
3505 if (port_op
.s
.raise
.signature
) {
3506 if (!in_sigs
->has_type(port_op
.s
.raise
.signature
)) {
3507 port_op
.s
.raise
.signature_ref
->error("Signature `%s' is not "
3508 "present on the incoming list of port type `%s'",
3509 port_op
.s
.raise
.signature
->get_typename().c_str(),
3510 port_type
->get_typename().c_str());
3512 } else if (in_sigs
->get_nof_types() == 1) {
3513 // if the signature is unknown and the port type has exactly one
3514 // incoming signature then use that for further checking
3515 port_op
.s
.raise
.signature
=
3516 in_sigs
->get_type_byIndex(0)->get_type_refd_last();
3519 port_op
.portref
->error("Port type `%s' does not have any incoming "
3520 "signatures", port_type
->get_typename().c_str());
3523 // determining the type of exception
3525 bool exc_type_determined
= false;
3526 if (port_op
.s
.raise
.signature
) {
3527 // the signature is known
3528 SignatureExceptions
*exceptions
=
3529 port_op
.s
.raise
.signature
->get_signature_exceptions();
3531 if (exceptions
->get_nof_types() == 1) {
3532 // the signature has exactly one exception type
3533 // use that for checking
3534 exc_type
= exceptions
->get_type_byIndex(0);
3536 // the signature has more than one exception types
3537 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3539 size_t nof_comp_types
=
3540 exceptions
->get_nof_compatible_types(exc_type
);
3541 if (nof_comp_types
== 0) {
3542 port_op
.s
.sendpar
->error("Type `%s' is not present on the "
3543 "exception list of signature `%s'",
3544 exc_type
->get_typename().c_str(),
3545 port_op
.s
.raise
.signature
->get_typename().c_str());
3546 } else if (nof_comp_types
> 1) {
3547 port_op
.s
.sendpar
->error("Type of the exception is ambiguous: "
3548 "`%s' is compatible with more than one exception types of "
3549 "signature `%s'", exc_type
->get_typename().c_str(),
3550 port_op
.s
.raise
.signature
->get_typename().c_str());
3553 port_op
.s
.sendpar
->error("Cannot determine the type of the "
3557 exc_type_determined
= true;
3559 port_op
.s
.raise
.signature_ref
->error("Signature `%s' does not have "
3560 "exceptions", port_op
.s
.raise
.signature
->get_typename().c_str());
3563 // determining the type of exception if it is not done so far
3564 if (!exc_type_determined
) {
3565 exc_type
= get_outgoing_type(port_op
.s
.sendpar
);
3567 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
3568 // checking the exception template
3569 port_op
.s
.sendpar
->chk(exc_type
);
3570 // checking for invalid exception types
3571 exc_type
= exc_type
->get_type_refd_last();
3572 switch (exc_type
->get_typetype()) {
3573 case Type::T_SIGNATURE
:
3574 port_op
.s
.sendpar
->error("The type of raise parameter is signature `%s', "
3575 "which cannot be an exception type",
3576 exc_type
->get_typename().c_str());
3579 port_op
.s
.sendpar
->error("The type of raise parameter is port type `%s', "
3580 "which cannot be an exception type",
3581 exc_type
->get_typename().c_str());
3583 case Type::T_DEFAULT
:
3584 port_op
.s
.sendpar
->error("The type of raise parameter is the `default' "
3585 "type, which cannot be an exception type");
3589 // checking for presence of wildcards in the template body
3590 port_op
.s
.sendpar
->get_Template()->chk_specific_value(false);
3591 // checking to clause
3592 chk_to_clause(port_type
);
3595 void Statement::chk_receive()
3597 // determining statement type
3598 const char *stmt_name
= get_stmt_name();
3599 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3600 // checking the port reference
3601 Type
*port_type
= chk_port_ref(port_op
.portref
);
3602 // checking the parameter and/or value redirect
3603 if (port_op
.r
.rcvpar
) {
3604 // the receive parameter (template instance) is present
3605 // trying to determine type of the incoming message
3607 bool msg_type_determined
= false, value_redirect_checked
= false;
3609 // the port reference is correct and the port type is known
3610 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3611 TypeSet
*in_msgs
= port_type_body
->get_in_msgs();
3613 if (in_msgs
->get_nof_types() == 1) {
3614 // there is only one incoming message type
3615 // use that for checking
3616 msg_type
= in_msgs
->get_type_byIndex(0);
3618 // there are more than one incoming message types
3619 msg_type
= get_incoming_type(port_op
.r
.rcvpar
,
3620 port_op
.r
.redirect
.value
, value_redirect_checked
);
3622 size_t nof_comp_types
=
3623 in_msgs
->get_nof_compatible_types(msg_type
);
3624 if (nof_comp_types
== 0) {
3625 port_op
.r
.rcvpar
->error("Message type `%s' is not present on "
3626 "the incoming list of port of type `%s'",
3627 msg_type
->get_typename().c_str(),
3628 port_type
->get_typename().c_str());
3629 } else if (nof_comp_types
> 1) {
3630 port_op
.r
.rcvpar
->error("Type of the message is ambiguous: "
3631 "`%s' is compatible with more than one incoming message "
3632 "types of port type `%s'", msg_type
->get_typename().c_str(),
3633 port_type
->get_typename().c_str());
3636 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3637 "incoming message");
3640 msg_type_determined
= true;
3641 } else if (port_type_body
->get_operation_mode() ==
3642 PortTypeBody::PO_PROCEDURE
) {
3643 port_op
.portref
->error("Message-based operation `%s' is not "
3644 "applicable to a procedure-based port of type `%s'", stmt_name
,
3645 port_type
->get_typename().c_str());
3647 port_op
.portref
->error("Port type `%s' does not have any incoming "
3648 "message types", port_type
->get_typename().c_str());
3650 } else if (!port_op
.portref
) {
3651 // the statement refers to 'any port'
3652 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3654 if (port_op
.r
.redirect
.value
) {
3655 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3656 "value redirect", stmt_name
);
3659 if (!msg_type_determined
) {
3660 msg_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
3661 value_redirect_checked
);
3663 if (!msg_type
) msg_type
= Type::get_pooltype(Type::T_ERROR
);
3664 // check the template instance using the message type
3665 port_op
.r
.rcvpar
->chk(msg_type
);
3666 // check the value redirect if it is not done so far
3667 if (!value_redirect_checked
)
3668 chk_value_redirect(port_op
.r
.redirect
.value
, msg_type
);
3670 // the statement does not have parameter
3672 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3673 if (!port_type_body
->get_in_msgs()) {
3674 // the port type is known and it does not have incoming messages
3675 if (port_type_body
->get_operation_mode() ==
3676 PortTypeBody::PO_PROCEDURE
) {
3677 port_op
.portref
->error("Message-based operation `%s' is not "
3678 "applicable to a procedure-based port of type `%s'", stmt_name
,
3679 port_type
->get_typename().c_str());
3681 port_op
.portref
->error("Port type `%s' does not have any incoming "
3682 "message types", port_type
->get_typename().c_str());
3686 if (port_op
.r
.redirect
.value
) {
3687 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
3688 "receive parameter");
3689 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3692 // checking from clause and sender redirect
3693 chk_from_clause(port_type
);
3696 void Statement::chk_getcall()
3698 // determining statement type
3699 const char *stmt_name
= get_stmt_name();
3700 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3701 // checking the port reference
3702 Type
*port_type
= chk_port_ref(port_op
.portref
);
3703 if (port_op
.r
.rcvpar
) {
3704 // the parameter (signature template) is present
3705 // determining the signature of the argument
3706 Type
*signature
= 0;
3707 bool signature_determined
= false;
3709 // the port reference is correct and the port type is known
3710 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3711 TypeSet
*in_sigs
= port_type_body
->get_in_sigs();
3713 if (in_sigs
->get_nof_types() == 1) {
3714 // there is only one incoming signature
3715 signature
= in_sigs
->get_type_byIndex(0);
3717 // there are more than one incoming signatures
3718 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3720 if (!in_sigs
->has_type(signature
)) {
3721 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3722 "incoming list of port type `%s'",
3723 signature
->get_typename().c_str(),
3724 port_type
->get_typename().c_str());
3727 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3731 signature_determined
= true;
3732 } else if (port_type_body
->get_operation_mode() ==
3733 PortTypeBody::PO_MESSAGE
) {
3734 port_op
.portref
->error("Procedure-based operation `%s' is not "
3735 "applicable to a message-based port of type `%s'", stmt_name
,
3736 port_type
->get_typename().c_str());
3738 port_op
.portref
->error("Port type `%s' does not have any incoming "
3739 "signatures", port_type
->get_typename().c_str());
3741 } else if (!port_op
.portref
) {
3742 // the statement refers to 'any port'
3743 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3745 if (port_op
.r
.redirect
.param
) {
3746 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3747 "have parameter redirect", stmt_name
);
3750 if (!signature_determined
)
3751 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3752 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3753 // checking the parameter (template instance)
3754 port_op
.r
.rcvpar
->chk(signature
);
3755 // checking whether the argument is a signature template
3756 // and checking the parameter redirect if present
3757 signature
= signature
->get_type_refd_last();
3758 switch (signature
->get_typetype()) {
3759 case Type::T_SIGNATURE
:
3760 if (port_op
.r
.redirect
.param
)
3761 port_op
.r
.redirect
.param
->chk(signature
, false);
3764 if (port_op
.r
.redirect
.param
)
3765 port_op
.r
.redirect
.param
->chk_erroneous();
3768 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3769 "a signature", signature
->get_typename().c_str());
3770 if (port_op
.r
.redirect
.param
)
3771 port_op
.r
.redirect
.param
->chk_erroneous();
3774 // the statement does not have parameter
3776 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3777 if (!port_type_body
->get_in_sigs()) {
3778 // the port type is known and it does not have incoming signatures
3779 if (port_type_body
->get_operation_mode() ==
3780 PortTypeBody::PO_MESSAGE
) {
3781 port_op
.portref
->error("Procedure-based operation `%s' is not "
3782 "applicable to a message-based port of type `%s'", stmt_name
,
3783 port_type
->get_typename().c_str());
3785 port_op
.portref
->error("Port type `%s' does not have any incoming "
3786 "signatures", port_type
->get_typename().c_str());
3790 if (port_op
.r
.redirect
.param
) {
3791 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3792 "without signature template");
3793 port_op
.r
.redirect
.param
->chk_erroneous();
3796 // checking from clause and sender redirect
3797 chk_from_clause(port_type
);
3800 void Statement::chk_getreply()
3802 // determining statement type
3803 const char *stmt_name
= get_stmt_name();
3804 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3805 // checking the port reference
3806 Type
*port_type
= chk_port_ref(port_op
.portref
);
3807 if (port_op
.r
.rcvpar
) {
3808 // the parameter (signature template) is present
3809 // determining the signature of the argument
3810 Type
*signature
= 0;
3811 bool signature_determined
= false;
3813 // the port reference is correct and the port type is known
3814 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3815 if (port_type_body
->getreply_allowed()) {
3816 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3817 if (out_sigs
->get_nof_types() == 1) {
3818 // there is only one outgoing signature
3819 signature
= out_sigs
->get_type_byIndex(0);
3821 // there are more than one outgoing signatures
3822 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3824 if (!out_sigs
->has_type(signature
)) {
3825 port_op
.r
.rcvpar
->error("Signature `%s' is not present on the "
3826 "outgoing list of port type `%s'",
3827 signature
->get_typename().c_str(),
3828 port_type
->get_typename().c_str());
3831 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
3835 signature_determined
= true;
3836 } else if (port_type_body
->get_operation_mode() ==
3837 PortTypeBody::PO_MESSAGE
) {
3838 port_op
.portref
->error("Procedure-based operation `%s' is not "
3839 "applicable to a message-based port of type `%s'", stmt_name
,
3840 port_type
->get_typename().c_str());
3842 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3843 "signatures that support reply", port_type
->get_typename().c_str());
3845 } else if (!port_op
.portref
) {
3846 // the statement refers to 'any port'
3847 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3849 if (port_op
.r
.getreply_valuematch
) {
3850 port_op
.r
.getreply_valuematch
->error("Operation `any port.%s' cannot "
3851 "have value match", stmt_name
);
3853 if (port_op
.r
.redirect
.value
) {
3854 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot "
3855 "have value redirect", stmt_name
);
3857 if (port_op
.r
.redirect
.param
) {
3858 port_op
.r
.redirect
.param
->error("Operation `any port.%s' cannot "
3859 "have parameter redirect", stmt_name
);
3862 if (!signature_determined
)
3863 signature
= get_outgoing_type(port_op
.r
.rcvpar
);
3864 if (!signature
) signature
= Type::get_pooltype(Type::T_ERROR
);
3865 // checking the parameter (template instance)
3866 port_op
.r
.rcvpar
->chk(signature
);
3867 // checking whether the argument is a signature template
3868 // checking the parameter redirect if present
3869 // and determining the return type of the signature
3870 signature
= signature
->get_type_refd_last();
3871 Type
*return_type
= 0;
3872 switch (signature
->get_typetype()) {
3873 case Type::T_SIGNATURE
:
3874 if (signature
->is_nonblocking_signature())
3875 error("Operation `%s' is not applicable to non-blocking signature "
3876 "`%s'", stmt_name
, signature
->get_typename().c_str());
3877 else return_type
= signature
->get_signature_return_type();
3878 if (port_op
.r
.redirect
.param
)
3879 port_op
.r
.redirect
.param
->chk(signature
, true);
3881 if (port_op
.r
.getreply_valuematch
) {
3882 port_op
.r
.getreply_valuematch
->error("Value match cannot be used "
3883 "because signature `%s' does not have return type",
3884 signature
->get_typename().c_str());
3886 if (port_op
.r
.redirect
.value
) {
3887 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3888 "because signature `%s' does not have return type",
3889 signature
->get_typename().c_str());
3894 if (port_op
.r
.redirect
.param
)
3895 port_op
.r
.redirect
.param
->chk_erroneous();
3898 port_op
.r
.rcvpar
->error("The type of parameter is `%s', which is not "
3899 "a signature", signature
->get_typename().c_str());
3900 if (port_op
.r
.redirect
.param
)
3901 port_op
.r
.redirect
.param
->chk_erroneous();
3903 // checking the value match if present
3904 if (port_op
.r
.getreply_valuematch
) {
3905 Error_Context
cntxt2(port_op
.s
.replyval
, "In value match");
3906 if (!return_type
) return_type
= Type::get_pooltype(Type::T_ERROR
);
3907 port_op
.r
.getreply_valuematch
->chk(return_type
);
3909 // checking the value redirect if present
3910 chk_value_redirect(port_op
.r
.redirect
.value
, return_type
);
3912 // the statement does not have parameter (value match is also omitted)
3914 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3915 if (!port_type_body
->getreply_allowed()) {
3916 // the port type is known and it does not have outgoing signatures
3917 if (port_type_body
->get_operation_mode() ==
3918 PortTypeBody::PO_MESSAGE
) {
3919 port_op
.portref
->error("Procedure-based operation `%s' is not "
3920 "applicable to a message-based port of type `%s'", stmt_name
,
3921 port_type
->get_typename().c_str());
3923 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3924 "signatures that support reply",
3925 port_type
->get_typename().c_str());
3929 if (port_op
.r
.redirect
.value
) {
3930 port_op
.r
.redirect
.value
->error("Value redirect cannot be used "
3931 "without signature template");
3932 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
3934 if (port_op
.r
.redirect
.param
) {
3935 port_op
.r
.redirect
.param
->error("Parameter redirect cannot be used "
3936 "without signature template");
3937 port_op
.r
.redirect
.param
->chk_erroneous();
3940 // checking from clause and sender redirect
3941 chk_from_clause(port_type
);
3944 void Statement::chk_catch()
3946 // determining statement type
3947 const char *stmt_name
= get_stmt_name();
3948 Error_Context
cntxt(this, "In %s statement", stmt_name
);
3949 // checking the port reference
3950 Type
*port_type
= chk_port_ref(port_op
.portref
);
3951 // checking the signature reference, parameter and/or value redirect
3952 if (port_op
.r
.ctch
.signature_ref
) {
3953 // the signature reference is present
3954 port_op
.r
.ctch
.signature
=
3955 chk_signature_ref(port_op
.r
.ctch
.signature_ref
);
3956 // checking whether the signature is present on the incoming list
3957 // of the respective port type
3959 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
3960 if (port_type_body
->catch_allowed()) {
3961 TypeSet
*out_sigs
= port_type_body
->get_out_sigs();
3962 if (port_op
.r
.ctch
.signature
) {
3963 if (!out_sigs
->has_type(port_op
.r
.ctch
.signature
)) {
3964 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' is not "
3965 "present on the outgoing list of port type `%s'",
3966 port_op
.r
.ctch
.signature
->get_typename().c_str(),
3967 port_type
->get_typename().c_str());
3969 } else if (out_sigs
->get_nof_types() == 1) {
3970 // if the signature is unknown and the port type has exactly one
3971 // outgoing signature then use that for further checking
3972 port_op
.r
.ctch
.signature
=
3973 out_sigs
->get_type_byIndex(0)->get_type_refd_last();
3975 } else if (port_type_body
->get_operation_mode() ==
3976 PortTypeBody::PO_MESSAGE
) {
3977 port_op
.portref
->error("Procedure-based operation `%s' is not "
3978 "applicable to a message-based port of type `%s'", stmt_name
,
3979 port_type
->get_typename().c_str());
3981 port_op
.portref
->error("Port type `%s' does not have any outgoing "
3982 "signatures that support exceptions",
3983 port_type
->get_typename().c_str());
3985 } else if (!port_op
.portref
) {
3986 // the statement refers to 'any port'
3987 port_op
.r
.rcvpar
->error("Operation `any port.%s' cannot have parameter",
3989 if (port_op
.r
.redirect
.value
) {
3990 port_op
.r
.redirect
.value
->error("Operation `any port.%s' cannot have "
3991 "value redirect", stmt_name
);
3994 // the receive parameter (template instance) must be also present
3995 // trying to determine type of the exception
3997 bool exc_type_determined
= false, value_redirect_checked
= false;
3998 if (port_op
.r
.ctch
.signature
) {
3999 // the signature is known
4000 SignatureExceptions
*exceptions
=
4001 port_op
.r
.ctch
.signature
->get_signature_exceptions();
4003 if (exceptions
->get_nof_types() == 1) {
4004 // the signature has exactly one exception type
4005 // use that for checking
4006 exc_type
= exceptions
->get_type_byIndex(0);
4008 // the signature has more than one exception types
4009 exc_type
= get_incoming_type(port_op
.r
.rcvpar
,
4010 port_op
.r
.redirect
.value
, value_redirect_checked
);
4012 size_t nof_comp_types
=
4013 exceptions
->get_nof_compatible_types(exc_type
);
4014 if (nof_comp_types
== 0) {
4015 port_op
.r
.rcvpar
->error("Type `%s' is not present on the "
4016 "exception list of signature `%s'",
4017 exc_type
->get_typename().c_str(),
4018 port_op
.r
.ctch
.signature
->get_typename().c_str());
4019 } else if (nof_comp_types
> 1) {
4020 port_op
.r
.rcvpar
->error("Type of the exception is ambiguous: "
4021 "`%s' is compatible with more than one exception types of "
4022 "signature `%s'", exc_type
->get_typename().c_str(),
4023 port_op
.r
.ctch
.signature
->get_typename().c_str());
4026 port_op
.r
.rcvpar
->error("Cannot determine the type of the "
4030 exc_type_determined
= true;
4032 port_op
.r
.ctch
.signature_ref
->error("Signature `%s' does not have "
4033 "exceptions", port_op
.r
.ctch
.signature
->get_typename().c_str());
4036 if (!exc_type_determined
) {
4037 exc_type
= get_incoming_type(port_op
.r
.rcvpar
, port_op
.r
.redirect
.value
,
4038 value_redirect_checked
);
4040 if (!exc_type
) exc_type
= Type::get_pooltype(Type::T_ERROR
);
4041 // check the template instance using the exception type
4042 port_op
.r
.rcvpar
->chk(exc_type
);
4043 // check the value redirect if it is not done so far
4044 if (!value_redirect_checked
)
4045 chk_value_redirect(port_op
.r
.redirect
.value
, exc_type
);
4046 // checking for invalid exception types
4047 exc_type
= exc_type
->get_type_refd_last();
4048 switch (exc_type
->get_typetype()) {
4049 case Type::T_SIGNATURE
:
4050 port_op
.r
.rcvpar
->error("The type of catch parameter is signature "
4051 "`%s', which cannot be an exception type",
4052 exc_type
->get_typename().c_str());
4055 port_op
.r
.rcvpar
->error("The type of catch parameter is port type "
4056 "`%s', which cannot be an exception type",
4057 exc_type
->get_typename().c_str());
4059 case Type::T_DEFAULT
:
4060 port_op
.r
.rcvpar
->error("The type of catch parameter is the `default' "
4061 "type, which cannot be an exception type");
4066 // the statement does not have signature reference
4067 if (port_op
.r
.ctch
.timeout
) {
4068 // the parameter is timeout
4069 if (port_op
.portref
) {
4070 // the port reference is present
4072 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4073 if (!port_type_body
->getreply_allowed()) {
4074 // the port type is known and it does not allow blocking calls
4075 if (port_type_body
->get_operation_mode() ==
4076 PortTypeBody::PO_MESSAGE
) {
4077 port_op
.portref
->error("Timeout exception cannot be caught on "
4078 "a message-based port of type `%s'",
4079 port_type
->get_typename().c_str());
4081 port_op
.portref
->error("Timeout exception cannot be caught on "
4082 "a port of type `%s', which does not have any outgoing "
4083 "signatures that allow blocking calls",
4084 port_type
->get_typename().c_str());
4088 } else error("Timeout exception cannot be caught on `any port'");
4089 if (!port_op
.r
.ctch
.in_call
)
4090 error("Catching of `timeout' exception is not allowed in this "
4091 "context. It is permitted only in the response and exception "
4092 "handling part of `call' operations");
4093 else if (!port_op
.r
.ctch
.call_has_timer
)
4094 error("Catching of `timeout' exception is not allowed because the "
4095 "previous `call' operation does not have timer");
4096 if (port_op
.r
.fromclause
) port_op
.r
.fromclause
->error(
4097 "Operation `catch(timeout)' cannot have from clause");
4098 if (port_op
.r
.redirect
.sender
) port_op
.r
.redirect
.sender
->error(
4099 "Operation `catch(timeout)' cannot have sender redirect");
4101 // the operation does not have any parameter
4103 PortTypeBody
*port_type_body
= port_type
->get_PortBody();
4104 if (!port_type_body
->catch_allowed()) {
4105 // the port type is known and it does not have outgoing signatures
4106 if (port_type_body
->get_operation_mode() ==
4107 PortTypeBody::PO_MESSAGE
) {
4108 port_op
.portref
->error("Procedure-based operation `%s' is not "
4109 "applicable to a message-based port of type `%s'", stmt_name
,
4110 port_type
->get_typename().c_str());
4112 port_op
.portref
->error("Port type `%s' does not have any "
4113 "outgoing signatures that support exceptions",
4114 port_type
->get_typename().c_str());
4119 if (port_op
.r
.redirect
.value
) {
4120 // the statement does not have any parameter,
4121 // but the value redirect is present
4122 port_op
.r
.redirect
.value
->error("Value redirect cannot be used without "
4123 "signature and parameter");
4124 chk_value_redirect(port_op
.r
.redirect
.value
, 0);
4127 // checking from clause and sender redirect
4128 chk_from_clause(port_type
);
4131 void Statement::chk_check()
4133 Error_Context
cntxt(this, "In check statement");
4134 Type
*port_type
= chk_port_ref(port_op
.portref
);
4135 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4136 // the port type is known and it does not have incoming queue
4137 port_op
.portref
->error("Port type `%s' does not have incoming queue "
4138 "because it has neither incoming messages nor incoming or outgoing "
4139 "signatures", port_type
->get_typename().c_str());
4141 // checking from clause and sender redirect
4142 chk_from_clause(port_type
);
4145 void Statement::chk_clear()
4147 Error_Context
cntxt(this, "In clear port statement");
4148 Type
*port_type
= chk_port_ref(port_op
.portref
);
4149 if (port_type
&& !port_type
->get_PortBody()->has_queue()) {
4150 // the port type is known and it does not have incoming queue
4151 port_op
.portref
->warning("Port type `%s' does not have incoming queue "
4152 "because it has neither incoming messages nor incoming or outgoing "
4153 "signatures", port_type
->get_typename().c_str());
4157 void Statement::chk_start_stop_port()
4159 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4160 chk_port_ref(port_op
.portref
);
4163 void Statement::chk_start_comp()
4165 Error_Context
cntxt(this, "In start test component statement");
4166 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4167 Common::Assignment
*t_ass
= comp_op
.funcinstref
->get_refd_assignment();
4169 // checking whether the referred definition is a function
4170 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
4172 case Common::Assignment::A_FUNCTION
:
4173 case Common::Assignment::A_FUNCTION_RVAL
:
4174 case Common::Assignment::A_FUNCTION_RTEMP
:
4177 comp_op
.funcinstref
->error("Reference to a function was expected in the "
4178 "argument instead of %s", t_ass
->get_description().c_str());
4181 Def_Function
*t_func
= dynamic_cast<Def_Function
*>(t_ass
);
4182 if (!t_func
) FATAL_ERROR("Statement::chk_start_comp()");
4183 // checking startability
4184 if (!t_func
->chk_startable()) return;
4185 // checking the 'runs on' clause against the type of component reference
4186 Type
*runs_on_type
= t_func
->get_RunsOnType();
4187 if (!comp_type
|| !runs_on_type
) return;
4188 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4189 comp_op
.compref
->error("Component type mismatch: The component reference "
4190 "is of type `%s', but %s runs on `%s'",
4191 comp_type
->get_typename().c_str(), t_func
->get_description().c_str(),
4192 runs_on_type
->get_typename().c_str());
4193 // checking the return type
4195 case Common::Assignment::A_FUNCTION_RTEMP
:
4196 comp_op
.funcinstref
->warning("Function `%s' returns a template of type "
4197 "`%s', which cannot be retrieved when the test component terminates",
4198 t_func
->get_fullname().c_str(),
4199 t_func
->get_Type()->get_typename().c_str());
4201 case Common::Assignment::A_FUNCTION_RVAL
: {
4202 bool return_type_correct
= false;
4203 Type
*return_type
= t_func
->get_Type();
4204 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4205 if (t
->has_done_attribute()) {
4206 return_type_correct
= true;
4208 } else if (!t
->is_ref()) break;
4210 if (!return_type_correct
)
4211 comp_op
.funcinstref
->warning("The return type of %s is `%s', which "
4212 "does not have the `done' extension attribute. When the test "
4213 "component terminates the returned value cannot be retrieved with "
4214 "a `done' operation", t_func
->get_description().c_str(),
4215 return_type
->get_typename().c_str());
4222 void Statement::chk_start_comp_refd()
4224 Error_Context
cntxt(this, "In start test component statement");
4225 Type
*comp_type
= chk_comp_ref(comp_op
.compref
, false, false);
4226 switch(comp_op
.derefered
.value
->get_valuetype()){
4227 case Value::V_REFER
:
4228 comp_op
.derefered
.value
->error("A value of a function type was expected "
4229 "in the argument instead of a `refers' statement,"
4230 " which does not specify any function type");
4232 case Value::V_TTCN3_NULL
:
4233 comp_op
.derefered
.value
->error("A value of a function type was expected "
4234 "in the argument instead of a `null' value,"
4235 " which does not specify any function type");
4240 Type
*f_type
= comp_op
.derefered
.value
->get_expr_governor_last();
4241 if (!f_type
) return;
4242 switch (f_type
->get_typetype()) {
4245 case Type::T_FUNCTION
:
4248 comp_op
.derefered
.value
->error("A value of type function was expected "
4249 "in the argument instead of `%s'", f_type
->get_typename().c_str());
4252 if (f_type
->get_fat_runs_on_self()) {
4253 fau_refd
.value
->error("The argument cannot be a function reference with "
4254 "'runs on self' clause");
4257 if(!f_type
->chk_startability()) return;
4258 Type
*runs_on_type
= f_type
->get_fat_runs_on_type();
4259 if (!comp_type
|| !runs_on_type
) return;
4260 if (!runs_on_type
->is_compatible(comp_type
, NULL
))
4261 comp_op
.compref
->error("Component type mismatch: The component reference "
4262 "is of type `%s', but functions of type `%s' run on `%s'",
4263 comp_type
->get_typename().c_str(), f_type
->get_typename().c_str(),
4264 runs_on_type
->get_typename().c_str());
4265 Type
*return_type
= f_type
->get_function_return_type();
4267 if (f_type
->get_returns_template()) {
4268 comp_op
.derefered
.value
->warning("Functions of type `%s' return a "
4269 "template of type `%s', which cannot be retrieved when the test "
4270 "component terminates", f_type
->get_typename().c_str(),
4271 return_type
->get_typename().c_str());
4273 bool return_type_correct
= false;
4274 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4275 if (t
->has_done_attribute()) {
4276 return_type_correct
= true;
4278 } else if (!t
->is_ref()) break;
4280 if (!return_type_correct
)
4281 comp_op
.derefered
.value
->warning("The return type of function type "
4282 "`%s' is `%s', which does not have the `done' extension attribute. "
4283 "When the test component terminates the returned value cannot be "
4284 "retrieved with a `done' operation", f_type
->get_typename().c_str(),
4285 return_type
->get_typename().c_str());
4288 ActualParList
*parlist
= new ActualParList
;
4289 Ttcn::FormalParList
*fp_list
= f_type
->get_fat_parameters();
4290 if(fp_list
->fold_named_and_chk(comp_op
.derefered
.t_list1
, parlist
)) {
4292 delete comp_op
.derefered
.t_list1
;
4293 comp_op
.derefered
.ap_list2
= 0;
4295 delete comp_op
.derefered
.t_list1
;
4296 parlist
->set_fullname(get_fullname());
4297 parlist
->set_my_scope(my_sb
);
4298 comp_op
.derefered
.ap_list2
= parlist
;
4302 void Statement::chk_stop_kill_comp()
4304 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4305 chk_comp_ref(comp_op
.compref
, true, false);
4308 void Statement::chk_done()
4310 Error_Context
cntxt(this, "In done statement");
4311 chk_comp_ref(comp_op
.compref
, false, false);
4312 if (!comp_op
.compref
) return;
4313 // value returning done can be used only when the statement contains a
4314 // specific component reference
4315 if (comp_op
.donereturn
.donematch
) {
4316 bool value_redirect_checked
= false;
4317 // try to determine the type of return value
4318 Type
*return_type
= get_incoming_type(comp_op
.donereturn
.donematch
,
4319 comp_op
.donereturn
.redirect
, value_redirect_checked
);
4321 bool return_type_correct
= false;
4322 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
4323 if (t
->has_done_attribute()) {
4324 return_type_correct
= true;
4326 } else if (!t
->is_ref()) break;
4328 if (!return_type_correct
) {
4329 error("Return type `%s' does not have `done' extension attribute",
4330 return_type
->get_typename().c_str());
4331 return_type
= Type::get_pooltype(Type::T_ERROR
);
4334 comp_op
.donereturn
.donematch
->error("Cannot determine the return type "
4335 "for value returning done");
4336 return_type
= Type::get_pooltype(Type::T_ERROR
);
4338 comp_op
.donereturn
.donematch
->chk(return_type
);
4339 if (!value_redirect_checked
)
4340 chk_value_redirect(comp_op
.donereturn
.redirect
, return_type
);
4341 } else if (comp_op
.donereturn
.redirect
) {
4342 comp_op
.donereturn
.redirect
->error("Redirect cannot be used for the "
4343 "return value without a matching template");
4344 chk_value_redirect(comp_op
.donereturn
.redirect
, 0);
4348 void Statement::chk_killed()
4350 Error_Context
cntxt(this, "In killed statement");
4351 chk_comp_ref(comp_op
.compref
, false, false);
4354 void Statement::chk_connect()
4356 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4357 // checking endpoints
4359 PortTypeBody
*ptb1
, *ptb2
;
4361 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4362 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, false);
4363 ptb1
= pt1
? pt1
->get_PortBody() : 0;
4366 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4367 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, false);
4368 ptb2
= pt2
? pt2
->get_PortBody() : 0;
4370 // checking consistency
4371 if (!ptb1
|| !ptb2
) return;
4372 if (!ptb1
->is_connectable(ptb2
) ||
4373 (ptb1
!= ptb2
&& !ptb2
->is_connectable(ptb1
))) {
4374 error("The connection between port types `%s' and `%s' is not consistent",
4375 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4376 ptb1
->report_connection_errors(ptb2
);
4377 if (ptb1
!= ptb2
) ptb2
->report_connection_errors(ptb1
);
4381 void Statement::chk_map()
4383 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4384 // checking endpoints
4386 PortTypeBody
*ptb1
, *ptb2
;
4387 bool cref1_is_tc
= false, cref1_is_system
= false;
4388 bool cref2_is_tc
= false, cref2_is_system
= false;
4390 Error_Context
cntxt2(config_op
.compref1
, "In first endpoint");
4391 pt1
= chk_conn_endpoint(config_op
.compref1
, config_op
.portref1
, true);
4393 ptb1
= pt1
->get_PortBody();
4394 if (ptb1
->is_internal()) {
4395 config_op
.portref1
->warning("Port type `%s' was marked as `internal'",
4396 pt1
->get_typename().c_str());
4399 Value
*cref1
= config_op
.compref1
->get_value_refd_last();
4400 if (cref1
->get_valuetype() == Value::V_EXPR
) {
4401 switch (cref1
->get_optype()) {
4402 case Value::OPTYPE_COMP_MTC
:
4403 case Value::OPTYPE_COMP_SELF
:
4404 case Value::OPTYPE_COMP_CREATE
:
4407 case Value::OPTYPE_COMP_SYSTEM
:
4408 cref1_is_system
= true;
4415 Error_Context
cntxt2(config_op
.compref2
, "In second endpoint");
4416 pt2
= chk_conn_endpoint(config_op
.compref2
, config_op
.portref2
, true);
4418 ptb2
= pt2
->get_PortBody();
4419 if (ptb2
->is_internal()) {
4420 config_op
.portref2
->warning("Port type `%s' was marked as `internal'",
4421 pt2
->get_typename().c_str());
4424 Value
*cref2
= config_op
.compref2
->get_value_refd_last();
4425 if (cref2
->get_valuetype() == Value::V_EXPR
) {
4426 switch (cref2
->get_optype()) {
4427 case Value::OPTYPE_COMP_MTC
:
4428 case Value::OPTYPE_COMP_SELF
:
4429 case Value::OPTYPE_COMP_CREATE
:
4432 case Value::OPTYPE_COMP_SYSTEM
:
4433 cref2_is_system
= true;
4439 if (cref1_is_tc
&& cref2_is_tc
) {
4440 error("Both endpoints of the mapping are test component ports");
4443 if (cref1_is_system
&& cref2_is_system
) {
4444 error("Both endpoints of the mapping are system ports");
4447 // checking consistency
4448 if (!ptb1
|| !ptb2
) return;
4449 if (cref1_is_tc
|| cref2_is_system
) {
4450 if (!ptb1
->is_mappable(ptb2
)) {
4451 error("The mapping between test component port type `%s' and system "
4452 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4453 pt2
->get_typename().c_str());
4454 ptb1
->report_mapping_errors(ptb2
);
4456 } else if (cref2_is_tc
|| cref1_is_system
) {
4457 if (!ptb2
->is_mappable(ptb1
)) {
4458 error("The mapping between system port type `%s' and test component "
4459 "port type `%s' is not consistent", pt1
->get_typename().c_str(),
4460 pt2
->get_typename().c_str());
4461 ptb2
->report_mapping_errors(ptb1
);
4464 // we have no idea which one is the system port
4465 if (!ptb1
->is_mappable(ptb1
) && !ptb2
->is_mappable(ptb1
)) {
4466 error("The mapping between port types `%s' and `%s' is not consistent",
4467 pt1
->get_typename().c_str(), pt2
->get_typename().c_str());
4472 void Statement::chk_start_timer()
4474 Error_Context
cntxt(this, "In start timer statement");
4475 chk_timer_ref(timer_op
.timerref
);
4476 if (timer_op
.value
) {
4477 // check the actual duration
4478 timer_op
.value
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4479 Value
*t_val
= timer_op
.value
->get_value_refd_last();
4480 if (t_val
->get_valuetype() == Value::V_REAL
) {
4481 ttcn3float v_real
= t_val
->get_val_Real();
4483 timer_op
.value
->error("The timer duration is negative: `%s'",
4484 Real2string(v_real
).c_str());
4485 } else if (isSpecialFloatValue(v_real
)) {
4486 timer_op
.value
->error("The timer duration cannot be %s",
4487 Real2string(v_real
).c_str());
4491 // check whether the timer has default duration
4492 Common::Assignment
*t_ass
= timer_op
.timerref
->get_refd_assignment();
4493 if (t_ass
&& t_ass
->get_asstype() == Common::Assignment::A_TIMER
) {
4494 Def_Timer
*t_def_timer
= dynamic_cast<Def_Timer
*>(t_ass
);
4495 if (!t_def_timer
) FATAL_ERROR("Statement::chk_start_timer()");
4496 if (!t_def_timer
->has_default_duration(
4497 timer_op
.timerref
->get_subrefs()))
4498 error("Missing duration: %s does not have default duration",
4499 t_ass
->get_description().c_str());
4504 void Statement::chk_stop_timer_timeout()
4506 Error_Context
cntxt(this, "In %s statement", get_stmt_name());
4507 chk_timer_ref(timer_op
.timerref
);
4510 void Statement::chk_setverdict()
4512 Error_Context
cntxt(this, "In setverdict statement");
4513 if(!my_sb
->get_my_def())
4514 error("Setverdict statement is not allowed in the control part");
4515 setverdict
.verdictval
->chk_expr_verdict(Type::EXPECTED_DYNAMIC_VALUE
);
4516 Value
*t_val
= setverdict
.verdictval
->get_value_refd_last();
4517 if (t_val
->get_valuetype() == Value::V_VERDICT
&&
4518 t_val
->get_val_verdict() == Value::Verdict_ERROR
) {
4519 setverdict
.verdictval
->error("Error verdict cannot be set by the setverdict "
4524 void Statement::chk_execute()
4526 Error_Context
cntxt(this, "In execute statement");
4527 Ref_pard
*ref
=testcase_inst
.tcref
;
4528 Common::Assignment
*t_ass
=ref
->get_refd_assignment();
4529 if(!t_ass
) goto error
;
4530 if(t_ass
->get_asstype()!=Common::Assignment::A_TESTCASE
) {
4531 ref
->error("Reference to a testcase was expected in the argument"
4532 " instead of %s", t_ass
->get_description().c_str());
4535 if(my_sb
->get_scope_runs_on()) {
4536 ref
->error("A definition that has `runs on' clause cannot "
4537 "execute testcases");
4540 if (testcase_inst
.timerval
) {
4541 testcase_inst
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4542 Value
*t_val
= testcase_inst
.timerval
->get_value_refd_last();
4543 if (t_val
->get_valuetype() == Value::V_REAL
) {
4544 ttcn3float v_real
= t_val
->get_val_Real();
4546 testcase_inst
.timerval
->error("The testcase guard "
4547 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4548 } else if (isSpecialFloatValue(v_real
)) {
4549 testcase_inst
.timerval
->error("The testcase guard "
4550 "timer duration cannot be %s", Real2string(v_real
).c_str());
4557 statementtype
=S_ERROR
;
4560 void Statement::chk_execute_refd()
4562 Error_Context
cntxt(this, "In execute statement");
4563 switch(execute_refd
.value
->get_valuetype()){
4564 case Value::V_REFER
:
4565 execute_refd
.value
->error("A value of a testcase type was expected "
4566 "in the argument instead of a `refers' statement,"
4567 " which does not specify any function type");
4569 case Value::V_TTCN3_NULL
:
4570 execute_refd
.value
->error("A value of a testcase type was expected "
4571 "in the argument instead of a `null' value,"
4572 " which does not specify any function type");
4577 Type
*t
= execute_refd
.value
->get_expr_governor_last();
4579 switch (t
->get_typetype()) {
4582 case Type::T_TESTCASE
:
4585 execute_refd
.value
->error("A value of type testcase was expected in the "
4586 "argument of `derefers()' instead of `%s'", t
->get_typename().c_str());
4589 if (my_sb
->get_scope_runs_on()) {
4590 execute_refd
.value
->error("A definition that has `runs on' clause cannot "
4591 "execute testcases");
4594 ActualParList
*parlist
= new ActualParList
;
4595 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
4596 bool is_erroneous
= fp_list
->chk_actual_parlist(execute_refd
.t_list1
,
4598 delete execute_refd
.t_list1
;
4601 execute_refd
.ap_list2
= 0;
4604 parlist
->set_fullname(get_fullname());
4605 parlist
->set_my_scope(my_sb
);
4606 execute_refd
.ap_list2
= parlist
;
4608 if(execute_refd
.timerval
) {
4609 execute_refd
.timerval
->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE
);
4610 Value
*t_val
= execute_refd
.timerval
->get_value_refd_last();
4611 if(t_val
->get_valuetype() == Value::V_REAL
) {
4612 ttcn3float v_real
= t_val
->get_val_Real();
4614 execute_refd
.value
->error("The testcase guard "
4615 "timer has negative duration: `%s'", Real2string(v_real
).c_str());
4616 } else if (isSpecialFloatValue(v_real
)) {
4617 execute_refd
.value
->error("The testcase guard "
4618 "timer duration cannot be %s", Real2string(v_real
).c_str());
4626 statementtype
=S_ERROR
;
4629 Type
*Statement::chk_port_ref(Reference
*p_ref
)
4631 if (!my_sb
->get_my_def())
4632 error("Port operation is not allowed in the control part");
4633 if (!p_ref
) return 0;
4634 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4635 if (!t_ass
) return 0;
4636 switch (t_ass
->get_asstype()) {
4637 case Common::Assignment::A_PORT
: {
4638 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
4639 if (t_dims
) t_dims
->chk_indices(p_ref
, "port", false,
4640 Type::EXPECTED_DYNAMIC_VALUE
);
4641 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
4642 "cannot have field or array sub-references",
4643 t_ass
->get_description().c_str());
4645 case Common::Assignment::A_PAR_PORT
:
4646 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
4647 "field or array sub-references", t_ass
->get_description().c_str());
4650 p_ref
->error("Reference to a port or port parameter was expected "
4651 "instead of %s", t_ass
->get_description().c_str());
4654 Type
*ret_val
= t_ass
->get_Type();
4655 if (!ret_val
) return 0;
4656 ret_val
= ret_val
->get_type_refd_last();
4657 if (ret_val
->get_typetype() == Type::T_PORT
) return ret_val
;
4661 void Statement::chk_to_clause(Type
*port_type
)
4663 if (!port_op
.s
.toclause
) return;
4664 // pointer to the address type
4667 // the port type is known
4668 address_type
= port_type
->get_PortBody()->get_address_type();
4670 // the port type is unknown
4671 // address is permitted if it is visible from the current module
4672 address_type
= my_sb
->get_scope_mod()->get_address_type();
4674 Error_Context
cntxt(port_op
.s
.toclause
, "In `to' clause");
4676 // detect possible enumerated values (address may be an enumerated type)
4677 address_type
->chk_this_value_ref(port_op
.s
.toclause
);
4678 // try to figure out whether the argument is a component reference or
4682 port_op
.s
.toclause
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4683 if (t_governor
) is_address
= address_type
->is_compatible(t_governor
, NULL
);
4685 port_op
.s
.toclause
->get_expr_returntype(Type::EXPECTED_DYNAMIC_VALUE
)
4686 != Type::T_COMPONENT
;
4688 // the argument is an address value
4689 port_op
.s
.toclause
->set_my_governor(address_type
);
4690 address_type
->chk_this_value(port_op
.s
.toclause
, 0,
4691 Type::EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
,
4694 // the argument is not an address value, treat as a component reference
4695 chk_comp_ref(port_op
.s
.toclause
, true, true);
4698 // usage of address is not allowed
4699 chk_comp_ref(port_op
.s
.toclause
, true, true);
4703 void Statement::chk_from_clause(Type
*port_type
)
4705 if (!port_op
.r
.fromclause
&& !port_op
.r
.redirect
.sender
) return;
4706 // pointer to the address type
4709 // the port type is known
4710 address_type
= port_type
->get_PortBody()->get_address_type();
4711 } else if (port_op
.portref
) {
4712 // the operation refers to a specific port, but its type is unknown
4713 // address is permitted if it is visible from the current module
4714 address_type
= my_sb
->get_scope_mod()->get_address_type();
4716 // the operation refers to 'any port'
4717 // address is not allowed
4720 bool sender_redirect_checked
= false;
4721 Type
*from_clause_type
= 0;
4722 if (port_op
.r
.fromclause
) {
4723 // the from clause is present
4724 Error_Context
cntxt(port_op
.r
.fromclause
, "In `from' clause");
4726 port_op
.r
.fromclause
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4727 Template
*templ_body
= port_op
.r
.fromclause
->get_Template();
4728 if (!from_clause_type
) {
4729 // try to detect possible enumerated values
4730 if (address_type
) address_type
->chk_this_template_ref(templ_body
);
4731 else templ_body
->set_lowerid_to_ref();
4733 templ_body
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4735 if (!from_clause_type
) {
4736 // trying to determine the type of template in from clause
4737 // based on the sender redirect
4738 from_clause_type
= chk_sender_redirect(address_type
);
4739 sender_redirect_checked
= true;
4741 if (!from_clause_type
) {
4742 // trying to figure out whether the template is a component reference
4743 // or an SUT address
4745 if (templ_body
->get_expr_returntype(Type::EXPECTED_TEMPLATE
)
4746 == Type::T_COMPONENT
) is_compref
= true;
4748 switch (templ_body
->get_templatetype()) {
4749 case Template::SPECIFIC_VALUE
:
4750 // treat 'null' as component reference
4751 if (templ_body
->get_specific_value()->get_valuetype() ==
4752 Value::V_TTCN3_NULL
) is_compref
= true;
4753 else is_compref
= false;
4755 case Template::ANY_VALUE
:
4756 case Template::ANY_OR_OMIT
:
4757 // treat generic wildcards ? and * as component references
4765 // the argument is a component reference: get a pool type
4766 from_clause_type
= Type::get_pooltype(Type::T_COMPONENT
);
4767 } else if (address_type
) {
4768 // the argument is not a component reference: try the address type
4769 from_clause_type
= address_type
;
4772 if (from_clause_type
) {
4773 // the type of from clause is known
4774 port_op
.r
.fromclause
->chk(from_clause_type
);
4776 || !address_type
->is_compatible(from_clause_type
, NULL
)) {
4777 // from_clause_type must be a component type
4778 switch (from_clause_type
->get_type_refd_last()->get_typetype()) {
4780 // to avoid further errors in sender redirect
4781 from_clause_type
= 0;
4782 case Type::T_COMPONENT
:
4783 if (templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
)
4784 chk_comp_ref(templ_body
->get_specific_value(), true, true);
4787 port_op
.r
.fromclause
->error("The type of the template should be a "
4788 "component type %sinstead of `%s'",
4789 address_type
? "or the `address' type " : "",
4790 from_clause_type
->get_typename().c_str());
4791 // to avoid further errors in sender redirect
4792 from_clause_type
= 0;
4796 // the type of from clause is unknown
4797 port_op
.r
.fromclause
->error("Cannot determine the type of the "
4801 if (!sender_redirect_checked
) {
4802 Type
*sender_redirect_type
= chk_sender_redirect(address_type
);
4803 if (from_clause_type
&& sender_redirect_type
&&
4804 !from_clause_type
->is_identical(sender_redirect_type
)) {
4805 error("The types in `from' clause and `sender' redirect are not the "
4806 "same: `%s' was expected instead of `%s'",
4807 from_clause_type
->get_typename().c_str(),
4808 sender_redirect_type
->get_typename().c_str());
4813 void Statement::chk_call_body(Type
*port_type
, Type
*signature
)
4815 bool has_catch_timeout
= false;
4816 // setting the flags whether 'catch(timeout)' statements are allowed
4817 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4818 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4819 if (t_ag
->get_type() != AltGuard::AG_OP
)
4820 FATAL_ERROR("Statement::chk_call_body()");
4821 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4822 if (t_stmt
->statementtype
== S_CATCH
) {
4823 t_stmt
->port_op
.r
.ctch
.in_call
= true;
4824 if (port_op
.s
.call
.timer
)
4825 t_stmt
->port_op
.r
.ctch
.call_has_timer
= true;
4826 if (t_stmt
->port_op
.r
.ctch
.timeout
) has_catch_timeout
= true;
4829 Error_Context
cntxt(this, "In response and exception handling part");
4830 port_op
.s
.call
.body
->set_my_laic_stmt(port_op
.s
.call
.body
, 0);
4831 port_op
.s
.call
.body
->set_my_ags(port_op
.s
.call
.body
);
4832 port_op
.s
.call
.body
->chk();
4834 // checking whether getreply/catch operations refer to the same port
4835 // and same signature as the call operation
4836 for (size_t i
= 0; i
< port_op
.s
.call
.body
->get_nof_ags(); i
++) {
4837 AltGuard
*t_ag
= port_op
.s
.call
.body
->get_ag_byIndex(i
);
4838 if (t_ag
->get_type() != AltGuard::AG_OP
)
4839 FATAL_ERROR("Statement::chk_call_body()");
4840 Statement
*t_stmt
= t_ag
->get_guard_stmt();
4841 if (t_stmt
->statementtype
== S_ERROR
) continue;
4842 // checking port reference
4843 if (!t_stmt
->port_op
.portref
) {
4844 t_stmt
->error("The `%s' operation must refer to the same port as "
4845 "the previous `call' statement: `%s' was expected instead of "
4846 "`any port'", t_stmt
->get_stmt_name(),
4847 port_op
.portref
->get_id()->get_dispname().c_str());
4848 } else if (*port_op
.portref
->get_id() !=
4849 *t_stmt
->port_op
.portref
->get_id()) {
4850 t_stmt
->port_op
.portref
->error("The `%s' operation refers to a "
4851 "different port than the previous `call' statement: `%s' was "
4852 "expected instead of `%s'", t_stmt
->get_stmt_name(),
4853 port_op
.portref
->get_id()->get_dispname().c_str(),
4854 t_stmt
->port_op
.portref
->get_id()->get_dispname().c_str());
4856 // checking the signature
4857 switch (t_stmt
->statementtype
) {
4859 if (t_stmt
->port_op
.r
.rcvpar
) {
4860 Type
*t_sig
= t_stmt
->port_op
.r
.rcvpar
4861 ->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
4862 if (!signature
->is_compatible(t_sig
, NULL
))
4863 t_stmt
->port_op
.r
.rcvpar
->error("The `getreply' operation refers "
4864 "to a different signature than the previous `call' statement: "
4865 "`%s' was expected instead of `%s'",
4866 signature
->get_typename().c_str(),
4867 t_sig
->get_typename().c_str());
4871 if (t_stmt
->port_op
.r
.ctch
.signature
4872 && !signature
->is_compatible(t_stmt
->port_op
.r
.ctch
.signature
, NULL
))
4873 t_stmt
->port_op
.r
.ctch
.signature_ref
->error("The `catch' "
4874 "operation refers to a different signature than the previous "
4875 "`call' statement: `%s' was expected instead of `%s'",
4876 signature
->get_typename().c_str(),
4877 t_stmt
->port_op
.r
.ctch
.signature
->get_typename().c_str());
4880 FATAL_ERROR("Statement::chk_call_body()");
4884 if (port_op
.s
.call
.timer
&& !has_catch_timeout
)
4885 warning("The call operation has a timer, but the timeout exception is "
4889 Type
*Statement::get_outgoing_type(TemplateInstance
*p_ti
)
4891 // first analyze the template instance as is
4892 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4893 // return if this step was successful
4894 if (ret_val
) return ret_val
;
4895 // try to convert the undef identifier in the template instance to
4896 // a reference because it cannot be an enum value anymore
4897 Template
*t_templ
= p_ti
->get_Template();
4898 t_templ
->set_lowerid_to_ref();
4899 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4902 Type
*Statement::get_incoming_type(TemplateInstance
*p_ti
,
4903 Reference
*p_val_redir
, bool& p_val_redir_checked
)
4905 // first analyze the template instance
4906 Type
*ret_val
= p_ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4907 // return if this step was successful
4908 if (ret_val
) return ret_val
;
4909 // use the variable in value redirect in the next step
4910 ret_val
= chk_value_redirect(p_val_redir
, 0);
4911 p_val_redir_checked
= true;
4912 // return if this step was successful
4913 if (ret_val
) return ret_val
;
4914 // finally try to convert the undef identifier in the template instance to
4915 // a reference because it cannot be an enum value anymore
4916 Template
*t_templ
= p_ti
->get_Template();
4917 t_templ
->set_lowerid_to_ref();
4918 return t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
4921 Type
*Statement::chk_value_redirect(Reference
*p_ref
, Type
*p_type
)
4923 if (!p_ref
) return NULL
;
4924 Error_Context
cntxt(p_ref
, "In `value' redirect");
4925 Type
*t_var_type
= p_ref
->chk_variable_ref();
4926 if (p_type
&& t_var_type
) {
4927 TypeCompatInfo
info(my_sb
->get_scope_mod(), p_type
, t_var_type
, true, false);
4928 if (p_ref
->get_subrefs()) info
.set_str2_elem(p_ref
->get_subrefs()->refers_to_string_element());
4931 if (!p_type
->is_compatible(t_var_type
, &info
, &l_chain
, &r_chain
)) {
4932 if (info
.is_subtype_error()) {
4933 p_ref
->error("%s", info
.get_subtype_error().c_str());
4935 if (!info
.is_erroneous()) {
4936 p_ref
->error("Type mismatch in value redirect: "
4937 "A variable of type `%s' was expected instead of `%s'",
4938 p_type
->get_typename().c_str(),
4939 t_var_type
->get_typename().c_str());
4941 p_ref
->error("%s", info
.get_error_str_str().c_str());
4948 Type
*Statement::chk_sender_redirect(Type
*address_type
)
4950 if (!port_op
.r
.redirect
.sender
) return 0;
4951 Error_Context
cntxt(port_op
.r
.redirect
.sender
, "In `sender' redirect");
4952 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
4953 if (!t_var_type
) return 0;
4954 if (!address_type
|| !address_type
->is_identical(t_var_type
)) {
4955 // t_var_type must be a component type
4956 switch (t_var_type
->get_type_refd_last()->get_typetype()) {
4957 case Type::T_COMPONENT
:
4962 port_op
.r
.redirect
.sender
->error("The type of the variable should be "
4963 "a component type %sinstead of `%s'",
4964 address_type
? "or the `address' type " : "",
4965 t_var_type
->get_typename().c_str());
4972 Type
*Statement::chk_signature_ref(Reference
*p_ref
)
4974 if (!p_ref
) FATAL_ERROR("Statement::chk_signature_ref()");
4975 Error_Context(p_ref
, "In signature");
4976 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
4977 if (!t_ass
) return 0;
4978 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
) {
4979 p_ref
->error("Reference to a signature was expected instead of %s",
4980 t_ass
->get_description().c_str());
4983 Type
*ret_val
= t_ass
->get_Type();
4984 if (!ret_val
) return 0;
4985 ret_val
= ret_val
->get_field_type(p_ref
->get_subrefs(),
4986 Type::EXPECTED_DYNAMIC_VALUE
);
4987 if (!ret_val
) return 0;
4988 ret_val
= ret_val
->get_type_refd_last();
4989 switch (ret_val
->get_typetype()) {
4990 case Type::T_SIGNATURE
:
4995 p_ref
->error("Reference to a signature was expected instead of port type "
4996 "`%s'", ret_val
->get_typename().c_str());
4999 p_ref
->error("Reference to a signature was expected instead of data type "
5000 "`%s'", ret_val
->get_typename().c_str());
5006 void Statement::chk_timer_ref(Reference
*p_ref
)
5009 Common::Assignment
*t_ass
= p_ref
->get_refd_assignment();
5011 switch (t_ass
->get_asstype()) {
5012 case Common::Assignment::A_TIMER
: {
5013 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
5014 if (t_dims
) t_dims
->chk_indices(p_ref
, "timer", false,
5015 Type::EXPECTED_DYNAMIC_VALUE
);
5016 else if (p_ref
->get_subrefs()) p_ref
->error("Reference to single %s "
5017 "cannot have field or array sub-references",
5018 t_ass
->get_description().c_str());
5020 case Common::Assignment::A_PAR_TIMER
:
5021 if (p_ref
->get_subrefs()) p_ref
->error("Reference to %s cannot have "
5022 "field or array sub-references", t_ass
->get_description().c_str());
5025 p_ref
->error("Reference to a timer or timer parameter was expected "
5026 "instead of %s", t_ass
->get_description().c_str());
5030 Type
*Statement::chk_comp_ref(Value
*p_val
, bool allow_mtc
, bool allow_system
)
5032 if (!my_sb
->get_my_def())
5033 error("Component operation is not allowed in the control part");
5034 if (!p_val
) return 0;
5035 Value
*v
= p_val
->get_value_refd_last();
5036 switch (v
->get_valuetype()) {
5037 case Value::V_ERROR
:
5041 case Value::V_INVOKE
:
5042 if(p_val
->get_expr_returntype() != Type::T_COMPONENT
)
5043 p_val
->error("A component reference was expected as return value");
5045 case Value::V_TTCN3_NULL
:
5046 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
5049 switch (v
->get_optype()) {
5050 case Value::OPTYPE_COMP_NULL
:
5051 p_val
->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
5053 case Value::OPTYPE_COMP_MTC
:
5055 p_val
->error("The `mtc' component reference shall not be used in `%s' operation", get_stmt_name());
5057 case Value::OPTYPE_COMP_SYSTEM
:
5059 p_val
->error("The `system' component reference shall not be used in `%s' operation", get_stmt_name());
5061 case Value::OPTYPE_COMP_SELF
:
5062 case Value::OPTYPE_COMP_CREATE
:
5065 p_val
->error("A component reference was expected as operand");
5070 p_val
->error("A component reference was expected as operand");
5073 Type
*ret_val
= p_val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
5074 if (!ret_val
) return 0;
5075 ret_val
= ret_val
->get_type_refd_last();
5076 switch (ret_val
->get_typetype()) {
5079 case Type::T_COMPONENT
:
5082 p_val
->error("Type mismatch: The type of the operand should be a "
5083 "component type instead of `%s'", ret_val
->get_typename().c_str());
5088 Type
*Statement::chk_conn_endpoint(Value
*p_compref
, Reference
*p_portref
,
5091 Type
*comp_type
= chk_comp_ref(p_compref
, true, allow_system
);
5093 ComponentTypeBody
*comp_body
= comp_type
->get_CompBody();
5094 p_portref
->set_base_scope(comp_body
);
5095 const Identifier
& t_portid
= *p_portref
->get_id();
5096 if (!comp_body
->has_local_ass_withId(t_portid
)) {
5097 p_portref
->error("Component type `%s' does not have port with name "
5098 "`%s'", comp_type
->get_typename().c_str(),
5099 t_portid
.get_dispname().c_str());
5102 Common::Assignment
*t_ass
= comp_body
->get_local_ass_byId(t_portid
);
5103 if (t_ass
->get_asstype() != Common::Assignment::A_PORT
) {
5104 p_portref
->error("Definition `%s' in component type `%s' is a %s and "
5105 "not a port", t_portid
.get_dispname().c_str(),
5106 comp_type
->get_typename().c_str(), t_ass
->get_assname());
5109 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
5110 if (t_dims
) t_dims
->chk_indices(p_portref
, "port", false,
5111 Type::EXPECTED_DYNAMIC_VALUE
);
5112 else if (p_portref
->get_subrefs()) {
5113 p_portref
->error("Port `%s' is not an array. The "
5114 "reference cannot have array indices",
5115 t_portid
.get_dispname().c_str());
5117 Type
*port_type
= t_ass
->get_Type();
5119 // check whether the external interface is provided by another port type
5120 PortTypeBody
*port_body
= port_type
->get_PortBody();
5121 if (port_body
->get_type() == PortTypeBody::PT_USER
) {
5122 Type
*provider_type
= port_body
->get_provider_type();
5123 if (provider_type
) port_type
= provider_type
;
5128 // the component type cannot be determined
5129 FieldOrArrayRefs
*t_subrefs
= p_portref
->get_subrefs();
5131 // check the array indices: they should be integers
5132 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
5133 t_subrefs
->get_ref(i
)->get_val()
5134 ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
5141 void Statement::set_code_section(
5142 GovernedSimple::code_section_t p_code_section
)
5144 switch(statementtype
) {
5153 case S_START_PROFILER
:
5154 case S_STOP_PROFILER
:
5157 ass
->set_code_section(p_code_section
);
5159 case S_FUNCTION_INSTANCE
:
5160 case S_ALTSTEP_INSTANCE
:
5162 ref_pard
->set_code_section(p_code_section
);
5165 block
->set_code_section(p_code_section
);
5169 case S_STOP_TESTCASE
:
5170 if (logargs
) logargs
->set_code_section(p_code_section
);
5173 if_stmt
.ics
->set_code_section(p_code_section
);
5174 if (if_stmt
.elseblock
)
5175 if_stmt
.elseblock
->set_code_section(p_code_section
);
5178 if (!loop
.for_stmt
.varinst
)
5179 loop
.for_stmt
.init_ass
->set_code_section(p_code_section
);
5180 loop
.for_stmt
.finalexpr
->set_code_section(p_code_section
);
5181 loop
.for_stmt
.step
->set_code_section(p_code_section
);
5182 loop
.block
->set_code_section(p_code_section
);
5186 loop
.expr
->set_code_section(p_code_section
);
5187 loop
.block
->set_code_section(p_code_section
);
5190 select
.expr
->set_code_section(p_code_section
);
5191 select
.scs
->set_code_section(p_code_section
);
5195 ags
->set_code_section(p_code_section
);
5198 if (returnexpr
.v
) returnexpr
.v
->set_code_section(p_code_section
);
5199 if (returnexpr
.t
) returnexpr
.t
->set_code_section(p_code_section
);
5202 if (deactivate
) deactivate
->set_code_section(p_code_section
);
5205 port_op
.portref
->set_code_section(p_code_section
);
5206 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5207 if (port_op
.s
.toclause
)
5208 port_op
.s
.toclause
->set_code_section(p_code_section
);
5211 port_op
.portref
->set_code_section(p_code_section
);
5212 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5213 if (port_op
.s
.toclause
)
5214 port_op
.s
.toclause
->set_code_section(p_code_section
);
5215 if (port_op
.s
.call
.timer
)
5216 port_op
.s
.call
.timer
->set_code_section(p_code_section
);
5217 if (port_op
.s
.call
.body
)
5218 port_op
.s
.call
.body
->set_code_section(p_code_section
);
5221 port_op
.portref
->set_code_section(p_code_section
);
5222 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5223 if (port_op
.s
.replyval
)
5224 port_op
.s
.replyval
->set_code_section(p_code_section
);
5225 if (port_op
.s
.toclause
)
5226 port_op
.s
.toclause
->set_code_section(p_code_section
);
5229 port_op
.portref
->set_code_section(p_code_section
);
5230 port_op
.s
.sendpar
->set_code_section(p_code_section
);
5231 if (port_op
.s
.toclause
)
5232 port_op
.s
.toclause
->set_code_section(p_code_section
);
5235 case S_CHECK_RECEIVE
:
5237 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5238 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5239 if (port_op
.r
.fromclause
)
5240 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5241 if (port_op
.r
.redirect
.value
)
5242 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5243 if (port_op
.r
.redirect
.sender
)
5244 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5247 case S_CHECK_GETCALL
:
5248 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5249 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5250 if (port_op
.r
.fromclause
)
5251 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5252 if (port_op
.r
.redirect
.param
)
5253 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5254 if (port_op
.r
.redirect
.sender
)
5255 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5258 case S_CHECK_GETREPLY
:
5259 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5260 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5261 if (port_op
.r
.getreply_valuematch
)
5262 port_op
.r
.getreply_valuematch
->set_code_section(p_code_section
);
5263 if (port_op
.r
.fromclause
)
5264 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5265 if (port_op
.r
.redirect
.value
)
5266 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5267 if (port_op
.r
.redirect
.param
)
5268 port_op
.r
.redirect
.param
->set_code_section(p_code_section
);
5269 if (port_op
.r
.redirect
.sender
)
5270 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5274 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5275 if (port_op
.r
.rcvpar
) port_op
.r
.rcvpar
->set_code_section(p_code_section
);
5276 if (port_op
.r
.fromclause
)
5277 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5278 if (port_op
.r
.redirect
.value
)
5279 port_op
.r
.redirect
.value
->set_code_section(p_code_section
);
5280 if (port_op
.r
.redirect
.sender
)
5281 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5284 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5285 if (port_op
.r
.fromclause
)
5286 port_op
.r
.fromclause
->set_code_section(p_code_section
);
5287 if (port_op
.r
.redirect
.sender
)
5288 port_op
.r
.redirect
.sender
->set_code_section(p_code_section
);
5294 if (port_op
.portref
) port_op
.portref
->set_code_section(p_code_section
);
5297 comp_op
.compref
->set_code_section(p_code_section
);
5298 comp_op
.funcinstref
->set_code_section(p_code_section
);
5300 case S_START_COMP_REFD
:
5301 comp_op
.compref
->set_code_section(p_code_section
);
5302 comp_op
.derefered
.value
->set_code_section(p_code_section
);
5307 if (comp_op
.compref
) comp_op
.compref
->set_code_section(p_code_section
);
5310 if (comp_op
.compref
) {
5311 comp_op
.compref
->set_code_section(p_code_section
);
5312 if (comp_op
.donereturn
.donematch
)
5313 comp_op
.donereturn
.donematch
->set_code_section(p_code_section
);
5314 if (comp_op
.donereturn
.redirect
)
5315 comp_op
.donereturn
.redirect
->set_code_section(p_code_section
);
5322 config_op
.compref1
->set_code_section(p_code_section
);
5323 config_op
.portref1
->set_code_section(p_code_section
);
5324 config_op
.compref2
->set_code_section(p_code_section
);
5325 config_op
.portref2
->set_code_section(p_code_section
);
5328 timer_op
.timerref
->set_code_section(p_code_section
);
5329 if (timer_op
.value
) timer_op
.value
->set_code_section(p_code_section
);
5333 if (timer_op
.timerref
)
5334 timer_op
.timerref
->set_code_section(p_code_section
);
5337 setverdict
.verdictval
->set_code_section(p_code_section
);
5338 if (setverdict
.logargs
)
5339 setverdict
.logargs
->set_code_section(p_code_section
);
5341 case S_TESTCASE_INSTANCE
:
5342 testcase_inst
.tcref
->set_code_section(p_code_section
);
5343 if (testcase_inst
.timerval
)
5344 testcase_inst
.timerval
->set_code_section(p_code_section
);
5346 case S_TESTCASE_INSTANCE_REFD
:
5347 execute_refd
.value
->set_code_section(p_code_section
);
5348 if(execute_refd
.timerval
)
5349 execute_refd
.timerval
->set_code_section(p_code_section
);
5351 case S_ACTIVATE_REFD
:
5352 case S_FUNCTION_INVOKED
:
5353 case S_ALTSTEP_INVOKED
:
5354 fau_refd
.value
->set_code_section(p_code_section
);
5355 if(fau_refd
.ap_list2
)
5356 for(size_t i
= 0; i
< fau_refd
.ap_list2
->get_nof_pars(); i
++)
5357 fau_refd
.ap_list2
->get_par(i
)->set_code_section(p_code_section
);
5361 convert_op
.val
->set_code_section(p_code_section
);
5362 convert_op
.ref
->set_code_section(p_code_section
);
5365 FATAL_ERROR("Statement::set_code_section()");
5366 } // switch statementtype
5369 char *Statement::generate_code(char *str
)
5371 switch (statementtype
) {
5378 // conditional and loop statements do not need single location setting
5379 // the embedded expressions, statements have their own locations
5382 str
= update_location_object(str
);
5385 switch(statementtype
) {
5387 str
=def
->generate_code_str(str
);
5390 str
=ass
->generate_code(str
);
5392 case S_FUNCTION_INSTANCE
:
5393 case S_ALTSTEP_INSTANCE
:
5394 str
=generate_code_funcinst(str
);
5396 case S_FUNCTION_INVOKED
:
5397 case S_ALTSTEP_INVOKED
:
5398 str
=generate_code_invoke(str
);
5401 str
=generate_code_block(str
);
5404 str
=generate_code_log(str
);
5407 str
= generate_code_label(str
);
5410 str
= generate_code_goto(str
);
5413 str
=generate_code_if(str
);
5416 str
=generate_code_select(str
);
5419 str
=generate_code_for(str
);
5422 str
=generate_code_while(str
);
5425 str
=generate_code_dowhile(str
);
5428 str
=generate_code_break(str
);
5431 str
=generate_code_continue(str
);
5434 str
=mputstr(str
, "TTCN_Runtime::stop_execution();\n");
5436 case S_STOP_TESTCASE
:
5437 str
=generate_code_testcase_stop(str
);
5440 str
=ags
->generate_code_alt(str
, *this);
5443 str
=generate_code_repeat(str
);
5446 str
=generate_code_interleave(str
);
5449 str
=generate_code_return(str
);
5452 str
=generate_code_activate(str
);
5454 case S_ACTIVATE_REFD
:
5455 str
=generate_code_activate_refd(str
);
5458 str
=generate_code_deactivate(str
);
5461 str
= generate_code_send(str
);
5464 str
= generate_code_call(str
);
5467 str
= generate_code_reply(str
);
5470 str
= generate_code_raise(str
);
5478 case S_CHECK_RECEIVE
:
5479 case S_CHECK_GETCALL
:
5480 case S_CHECK_GETREPLY
:
5485 str
= generate_code_standalone(str
);
5488 str
=generate_code_portop(str
, "clear");
5491 str
=generate_code_portop(str
, "start");
5494 str
=generate_code_portop(str
, "stop");
5497 str
=generate_code_portop(str
, "halt");
5500 str
=generate_code_startcomp(str
);
5502 case S_START_COMP_REFD
:
5503 str
=generate_code_startcomp_refd(str
);
5506 str
= generate_code_compop(str
, "stop");
5509 str
= generate_code_compop(str
, "kill");
5512 str
= generate_code_configop(str
, "connect");
5515 str
= generate_code_configop(str
, "map");
5518 str
= generate_code_configop(str
, "disconnect");
5521 str
= generate_code_configop(str
, "unmap");
5524 str
=generate_code_starttimer(str
);
5527 str
=generate_code_stoptimer(str
);
5530 str
=generate_code_setverdict(str
);
5533 str
=generate_code_action(str
);
5535 case S_TESTCASE_INSTANCE
:
5536 str
=generate_code_testcaseinst(str
);
5538 case S_TESTCASE_INSTANCE_REFD
:
5539 str
=generate_code_execute_refd(str
);
5542 str
=generate_code_string2ttcn(str
);
5545 str
= generate_code_int2enum(str
);
5547 case S_START_PROFILER
:
5548 str
= mputstr(str
, "ttcn3_prof.start();\n");
5550 case S_STOP_PROFILER
:
5551 str
= mputstr(str
, "ttcn3_prof.stop();\n");
5554 FATAL_ERROR("Statement::generate_code()");
5559 char* Statement::generate_code_string2ttcn(char *str
)
5561 expression_struct val_expr
;
5562 Code::init_expr(&val_expr
);
5563 convert_op
.val
->generate_code_expr(&val_expr
);
5565 expression_struct ref_expr
;
5566 Code::init_expr(&ref_expr
);
5567 convert_op
.ref
->generate_code(&ref_expr
);
5569 str
= mputstr(str
, val_expr
.preamble
);
5570 str
= mputstr(str
, ref_expr
.preamble
);
5572 str
= mputprintf(str
, "string_to_ttcn(%s,%s);\n", val_expr
.expr
, ref_expr
.expr
);
5574 str
= mputstr(str
, val_expr
.postamble
);
5575 str
= mputstr(str
, ref_expr
.postamble
);
5577 Code::free_expr(&val_expr
);
5578 Code::free_expr(&ref_expr
);
5583 char* Statement::generate_code_int2enum(char* str
)
5585 expression_struct val_expr
;
5586 Code::init_expr(&val_expr
);
5587 convert_op
.val
->generate_code_expr(&val_expr
);
5589 expression_struct ref_expr
;
5590 Code::init_expr(&ref_expr
);
5591 convert_op
.ref
->generate_code(&ref_expr
);
5593 // check if the reference is an optional field
5594 bool is_optional
= false;
5595 FieldOrArrayRefs
* subrefs
= convert_op
.ref
->get_subrefs();
5596 if (NULL
!= subrefs
) {
5597 Type
* ref_type
= convert_op
.ref
->get_refd_assignment()->get_Type()->get_type_refd_last();
5598 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
5599 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
5600 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
5601 ref_type
= ref_type
->get_ofType()->get_type_refd_last();
5604 CompField
* cf
= ref_type
->get_comp_byName(*subref
->get_id());
5605 if (i
== subrefs
->get_nof_refs() - 1 && cf
->get_is_optional()) {
5608 ref_type
= cf
->get_type()->get_type_refd_last();
5613 str
= mputstr(str
, val_expr
.preamble
);
5614 str
= mputstr(str
, ref_expr
.preamble
);
5616 str
= mputprintf(str
, "%s%s.int2enum(%s);\n", ref_expr
.expr
,
5617 is_optional
? "()" : "", val_expr
.expr
);
5619 str
= mputstr(str
, val_expr
.postamble
);
5620 str
= mputstr(str
, ref_expr
.postamble
);
5622 Code::free_expr(&val_expr
);
5623 Code::free_expr(&ref_expr
);
5628 void Statement::generate_code_expr(expression_struct
*expr
)
5630 switch (statementtype
) {
5632 generate_code_expr_receive(expr
, "receive");
5635 generate_code_expr_receive(expr
, "trigger");
5637 case S_CHECK_RECEIVE
:
5638 generate_code_expr_receive(expr
, "check_receive");
5641 generate_code_expr_getcall(expr
, "getcall");
5643 case S_CHECK_GETCALL
:
5644 generate_code_expr_getcall(expr
, "check_getcall");
5647 generate_code_expr_getreply(expr
, "getreply");
5649 case S_CHECK_GETREPLY
:
5650 generate_code_expr_getreply(expr
, "check_getreply");
5654 generate_code_expr_catch(expr
);
5657 generate_code_expr_check(expr
);
5660 generate_code_expr_done(expr
);
5663 generate_code_expr_killed(expr
);
5666 generate_code_expr_timeout(expr
);
5669 FATAL_ERROR("Statement::generate_code_expr()");
5673 void Statement::ilt_generate_code(ILT
*ilt
)
5675 switch (statementtype
) {
5677 ilt_generate_code_interleave(ilt
);
5680 ilt_generate_code_alt(ilt
);
5683 ilt_generate_code_def(ilt
);
5688 if (is_receiving_stmt()) {
5689 ilt_generate_code_receiving(ilt
);
5692 if (!has_receiving_stmt()) {
5693 char*& str
=ilt
->get_out_branches();
5694 str
=generate_code(str
);
5697 switch (statementtype
) {
5699 block
->ilt_generate_code(ilt
);
5702 ilt_generate_code_if(ilt
);
5705 ilt_generate_code_select(ilt
);
5708 ilt_generate_code_call(ilt
);
5711 ilt_generate_code_for(ilt
);
5714 ilt_generate_code_while(ilt
);
5717 ilt_generate_code_dowhile(ilt
);
5720 FATAL_ERROR("Statement::ilt_generate_code()");
5721 } // switch statementtype
5724 char *Statement::generate_code_standalone(char *str
)
5726 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5727 const char *label_str
= tmplabel
.c_str();
5728 str
= mputprintf(str
, "{\n"
5729 "%s:\n", label_str
);
5730 expression_struct expr
;
5731 Code::init_expr(&expr
);
5732 generate_code_expr(&expr
);
5733 str
= mputstr(str
, expr
.preamble
);
5734 str
= mputprintf(str
, "alt_status alt_flag = ALT_UNCHECKED, "
5735 "default_flag = ALT_UNCHECKED;\n"
5736 "TTCN_Snapshot::take_new(FALSE);\n"
5738 "if (alt_flag != ALT_NO) {\n"
5740 "if (alt_flag == ALT_YES) break;\n", expr
.expr
);
5742 str
= mputprintf(str
, "else if (alt_flag == ALT_REPEAT) goto %s;\n",
5745 str
= mputprintf(str
, "}\n"
5746 "if (default_flag != ALT_NO) {\n"
5747 "default_flag = TTCN_Default::try_altsteps();\n"
5748 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) break;\n"
5749 "else if (default_flag == ALT_REPEAT) goto %s;\n"
5751 str
= update_location_object(str
);
5752 str
= mputprintf(str
, "if (alt_flag == ALT_NO && default_flag == ALT_NO) "
5753 "TTCN_error(\"Stand-alone %s statement failed in file ", get_stmt_name());
5754 str
= Code::translate_string(str
, get_filename());
5755 int first_line
= get_first_line(), last_line
= get_last_line();
5756 if (first_line
< last_line
) str
= mputprintf(str
,
5757 " between lines %d and %d", first_line
, last_line
);
5758 else str
= mputprintf(str
, ", line %d", first_line
);
5759 str
= mputstr(str
, ".\");\n"
5760 "TTCN_Snapshot::take_new(TRUE);\n"
5762 str
= mputstr(str
, expr
.postamble
);
5763 str
= mputstr(str
, "}\n");
5764 Code::free_expr(&expr
);
5768 char *Statement::generate_code_funcinst(char *str
)
5770 expression_struct expr
;
5771 Code::init_expr(&expr
);
5772 ref_pard
->generate_code_const_ref(&expr
);
5773 str
=Code::merge_free_expr(str
, &expr
);
5777 char* Statement::generate_code_invoke(char *str
)
5779 expression_struct expr
;
5780 Code::init_expr(&expr
);
5781 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
5782 switch(last_v
->get_valuetype()) {
5783 case Value::V_FUNCTION
:
5784 case Value::V_ALTSTEP
: {
5785 Common::Assignment
*t_fat
= last_v
->get_refd_fat();
5786 expr
.expr
= mputprintf(expr
.expr
, "%s(",
5787 t_fat
->get_genname_from_scope(my_sb
).c_str());
5788 fau_refd
.ap_list2
->generate_code_alias(&expr
, t_fat
->get_FormalParList(),
5789 t_fat
->get_RunsOnType(), false);
5792 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
5793 Type
*t_governor
= fau_refd
.value
->get_expr_governor_last();
5794 expr
.expr
= mputprintf(expr
.expr
, ".%s(",
5795 t_governor
->get_typetype() == Type::T_ALTSTEP
?
5796 "invoke_standalone" : "invoke");
5797 fau_refd
.ap_list2
->generate_code_alias(&expr
, 0,
5798 t_governor
->get_fat_runs_on_type(),
5799 t_governor
->get_fat_runs_on_self()); }
5801 expr
.expr
= mputc(expr
.expr
, ')');
5802 str
=Code::merge_free_expr(str
, &expr
);
5806 char *Statement::generate_code_block(char *str
)
5808 switch (block
->get_exception_handling()) {
5809 case StatementBlock::EH_NONE
:
5811 case StatementBlock::EH_TRY
:
5812 str
= mputstr(str
, "try ");
5814 case StatementBlock::EH_CATCH
:
5815 str
= mputstr(str
, "catch (const TTCN_Error& ttcn_error) ");
5818 FATAL_ERROR("Statement::generate_code_block()");
5820 if (block
->get_nof_stmts() > 0 || block
->get_exception_handling()!=StatementBlock::EH_NONE
) {
5821 str
= mputstr(str
, "{\n");
5822 if (debugger_active
) {
5823 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
5825 str
= block
->generate_code(str
);
5826 str
= mputstr(str
, "}\n");
5827 } else str
= mputstr(str
, "/* empty block */;\n");
5831 char *Statement::generate_code_log(char *str
)
5834 bool buffered_mode
= true;
5835 if (logargs
->get_nof_logargs() == 1) {
5836 LogArgument
*first_logarg
= logargs
->get_logarg_byIndex(0);
5837 switch (first_logarg
->get_type()) {
5838 case LogArgument::L_STR
:
5839 // the argument is a simple string: use non-buffered mode
5840 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, \"");
5841 str
= Code::translate_string(str
, first_logarg
->get_str().c_str());
5842 str
= mputstr(str
, "\");\n");
5843 buffered_mode
= false;
5845 case LogArgument::L_MACRO
: {
5846 Value
*t_val
= first_logarg
->get_val();
5847 if (t_val
->has_single_expr()) {
5848 // the argument is a simple macro call: use non-buffered mode
5849 str
= mputprintf(str
, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5850 t_val
->get_single_expr().c_str());
5851 buffered_mode
= false;
5857 if (buffered_mode
) {
5858 // the argument is a complicated construct: use buffered mode
5859 str
= mputstr(str
, "try {\n"
5860 "TTCN_Logger::begin_event(TTCN_USER);\n");
5861 str
= logargs
->generate_code(str
);
5862 str
= mputstr(str
, "TTCN_Logger::end_event();\n"
5864 "TTCN_Logger::finish_event();\n"
5869 // the argument is missing
5870 str
= mputstr(str
, "TTCN_Logger::log_str(TTCN_USER, "
5871 "\"<empty log statement>\");\n");
5876 char *Statement::generate_code_testcase_stop(char *str
)
5878 if (logargs
) str
= generate_code_log(str
);
5879 str
= mputstr(str
, "TTCN_error(\"testcase.stop\");\n");
5883 char *Statement::generate_code_label(char *str
)
5886 return mputprintf(str
, "%s: /* TTCN-3 label: %s */;\n",
5887 get_clabel().c_str(), label
.id
->get_dispname().c_str());
5889 return mputprintf(str
, "/* unused TTCN-3 label: %s */;\n",
5890 label
.id
->get_dispname().c_str());
5894 char *Statement::generate_code_goto(char *str
)
5896 if (!go_to
.label
) FATAL_ERROR("Statement::generate_code_goto()");
5897 return mputprintf(str
, "goto %s; /* TTCN-3 label: %s */\n",
5898 go_to
.label
->get_clabel().c_str(), go_to
.id
->get_dispname().c_str());
5902 char* Statement::generate_code_if(char *str
)
5904 size_t blockcount
=0;
5905 bool unreach
=false, eachfalse
=true;
5906 str
=if_stmt
.ics
->generate_code(str
, blockcount
, unreach
, eachfalse
);
5907 if(if_stmt
.elseblock
&& !unreach
) {
5908 if(!eachfalse
) str
=mputstr(str
, "else ");
5910 str
=mputstr(str
, "{\n");
5911 if (debugger_active
) {
5912 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
5915 str
=if_stmt
.elseblock
->generate_code(str
);
5917 while(blockcount
-->0) str
=mputstr(str
, "}\n");
5918 if(eachfalse
) str
=mputstr(str
, "/* never occurs */;\n");
5922 char* Statement::generate_code_select(char *str
)
5924 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
5925 char *expr_init
=memptystr();
5926 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
5927 if (expr_init
[0]) { // some init code was generated
5928 str
= update_location_object(str
);
5929 str
= mputstr(str
, "{\n");
5930 str
= mputstr(str
, expr_init
);
5932 str
=select
.scs
->generate_code(str
, tmp_prefix
.c_str(), expr_name
);
5934 if (expr_init
[0]) str
=mputstr(str
, "}\n");
5939 char *Statement::generate_code_for(char *str
)
5941 /** \todo initial does not have its own location */
5942 // statements in initial may have side effects
5943 // generate code for them anyway
5944 if (loop
.for_stmt
.varinst
) {
5945 str
= mputstr(str
, "{\n");
5946 if (debugger_active
) {
5947 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
5949 str
= loop
.for_stmt
.init_varinst
->generate_code_str(str
);
5951 str
= loop
.for_stmt
.init_ass
->update_location_object(str
);
5952 str
= loop
.for_stmt
.init_ass
->generate_code(str
);
5954 // check whether the final expression is constant
5955 bool final_is_true
= false, final_is_false
= false;
5956 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
5957 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
5958 else final_is_false
= true;
5960 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
5964 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
5965 str
= update_location_object(str
);
5966 str
= mputstr(str
, "for ( ; ; ) {\n");
5967 // do not generate the exit condition for infinite loops
5968 if (!final_is_true
) {
5969 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
5970 size_t blockcount
= 0;
5971 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
5973 str
= mputstr(str
, ") break;\n");
5974 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
5976 if (loop
.label_next
) str
= mputstr(str
, "{\n");
5977 if (debugger_active
) {
5978 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
5980 str
= loop
.block
->generate_code(str
);
5981 if (loop
.label_next
)
5982 str
= mputprintf(str
, "}\n"
5983 "%s:\n", loop
.label_next
->c_str());
5984 str
= loop
.for_stmt
.step
->update_location_object(str
);
5985 str
= loop
.for_stmt
.step
->generate_code(str
);
5986 str
= mputstr(str
, "}\n");
5988 if (loop
.for_stmt
.varinst
) str
= mputstr(str
, "}\n");
5992 char *Statement::generate_code_while(char *str
)
5994 // check whether the expression is constant
5995 bool condition_always_true
= false, condition_always_false
= false;
5996 if (!loop
.expr
->is_unfoldable()) {
5997 if (loop
.expr
->get_val_bool()) condition_always_true
= true;
5998 else condition_always_false
= true;
6000 if (condition_always_false
) str
= mputstr(str
, "/* never occurs */;\n");
6002 str
= mputstr(str
, "for ( ; ; ) {\n");
6003 if (loop
.has_cnt_in_ags
) {
6005 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
6006 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
6008 // do not generate the exit condition for infinite loops
6009 if (!condition_always_true
) {
6010 str
= loop
.expr
->update_location_object(str
);
6011 size_t blockcount
= 0;
6012 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6013 str
= mputstr(str
, ") break;\n");
6014 while(blockcount
-- > 0) str
= mputstr(str
, "}\n");
6016 if (debugger_active
) {
6017 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
6019 str
= loop
.block
->generate_code(str
);
6020 str
= mputstr(str
, "}\n");
6025 char *Statement::generate_code_dowhile(char *str
)
6027 // check whether the expression is constant
6028 bool expr_is_const
= !loop
.expr
->is_unfoldable();
6029 bool is_infinite_loop
= false;
6030 if (expr_is_const
) {
6031 if (loop
.expr
->get_val_bool()) is_infinite_loop
= true;
6032 else loop
.iterate_once
= true;
6034 if (loop
.iterate_once
&& !loop
.has_brk
&& !loop
.has_cnt
) {
6035 str
= mputstr(str
, "{\n");
6036 if (debugger_active
) {
6037 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
6039 str
= loop
.block
->generate_code(str
);
6041 str
= mputstr(str
, "for ( ; ; ) {\n");
6042 if (loop
.has_cnt_in_ags
|| (!expr_is_const
&& loop
.has_cnt
))
6044 new string(my_sb
->get_scope_mod_gen()->get_temporary_id());
6045 if (loop
.label_next
&& is_infinite_loop
)
6046 str
= mputprintf(str
, "%s:\n", loop
.label_next
->c_str());
6047 if (loop
.label_next
&& !is_infinite_loop
) str
= mputstr(str
, "{\n");
6048 if (debugger_active
) {
6049 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
6051 str
= loop
.block
->generate_code(str
);
6052 // do not generate the exit condition for infinite loops
6053 if (!is_infinite_loop
) {
6054 if (loop
.label_next
)
6055 str
= mputprintf(str
, "}\n"
6056 "%s:\n", loop
.label_next
->c_str());
6057 str
= loop
.expr
->update_location_object(str
);
6058 if (loop
.iterate_once
) str
= mputstr(str
, "break;\n");
6060 size_t blockcount
= 0;
6061 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6062 str
= mputstr(str
, ") break;\n");
6063 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6067 str
= mputstr(str
, "}\n");
6071 char *Statement::generate_code_break(char *str
)
6073 // in altstep (2 (=2nd if branch))
6074 // in alt and loops - not inside interleave (4)
6075 // in loops without receiving statement embedded in interleave (4)
6076 // in loops with receiving statement embedded in interleave (1)
6077 // in interleave when not embedded in enclosed loop or alt/interleave (4)
6078 // in alt/interleave embedded in interleave (3)
6079 if (brk_cnt
.loop_stmt
&& brk_cnt
.loop_stmt
->loop
.il_label_end
)
6080 str
=mputprintf(str
, "goto %s;\n",
6081 brk_cnt
.loop_stmt
->loop
.il_label_end
->c_str());
6082 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_is_altstep())
6083 str
=mputstr(str
, "return ALT_BREAK;\n");
6084 else if (brk_cnt
.ags
&& brk_cnt
.ags
->get_il_label_end())
6085 str
=mputprintf(str
, "goto %s;\n",
6086 brk_cnt
.ags
->get_il_label_end()->c_str());
6088 str
=mputstr(str
, "break;\n");
6092 char *Statement::generate_code_continue(char *str
)
6094 // not inside interleave when continue is not inside embedded ags (2 or 1)
6095 // continue is inside ags enclosed in the loop (3)
6096 // in interleave (3, 2 or 1)
6097 if (brk_cnt
.loop_stmt
!= 0) {
6098 if (brk_cnt
.loop_stmt
->loop
.iterate_once
&& !brk_cnt
.ags
&&
6099 !brk_cnt
.loop_stmt
->loop
.is_ilt
)
6100 str
=mputstr(str
, "break;\n");
6102 if (!brk_cnt
.loop_stmt
->loop
.label_next
)
6103 str
=mputstr(str
, "continue;\n");
6105 str
=mputprintf(str
, "goto %s;\n",
6106 brk_cnt
.loop_stmt
->loop
.label_next
->c_str());
6109 FATAL_ERROR("Statement::generate_code_continue()");
6113 char *Statement::generate_code_repeat(char *str
)
6115 string
*tmplabel
=ags
->get_label();
6116 if(!tmplabel
) str
=mputstr(str
, "return ALT_REPEAT;\n");
6117 else str
=mputprintf(str
, "goto %s;\n", tmplabel
->c_str());
6121 char* Statement::generate_code_interleave(char *str
)
6124 str
=ilt
.generate_code(str
);
6128 void Statement::ilt_generate_code_interleave(ILT
*ilt
)
6130 const string
& mytmpid
=ilt
->get_my_tmpid();
6131 bool toplevel
=ilt
->is_toplevel();
6132 size_t goto_label_num
=toplevel
?(size_t)-1:ilt
->get_new_label_num();
6133 char*& out_branches
=ilt
->get_out_branches();
6134 out_branches
=update_location_object(out_branches
);
6136 if(toplevel
) state_cond
="";
6138 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6139 (unsigned long) goto_label_num
);
6140 ags
->set_il_label_end (label_end
);
6142 ILT_branch
*branch
=ilt
->get_as_branch();
6143 size_t state_var
=branch
->get_my_state_var();
6144 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6145 state_cond
=branch
->get_state_cond();
6146 if(!state_cond
.empty()) state_cond
+=" && ";
6147 char *s
=mprintf("%s_state[%lu]==%lu", mytmpid
.c_str(),
6148 (unsigned long) state_var
, (unsigned long) state_var_val
);
6151 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6153 (unsigned long) state_var
, (unsigned long) state_var_val
);
6155 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6156 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6157 if(ag
->get_type()!=AltGuard::AG_OP
)
6158 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6159 size_t state_var
=ilt
->get_new_state_var(toplevel
);
6160 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6161 ilt
->add_branch(new ILT_branch(ILT_branch::BT_IL
, ag
, state_cond
,
6162 state_var
, state_var_val
,
6165 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n",
6167 (unsigned long) state_var
, (unsigned long) state_var_val
);
6170 out_branches
=mputprintf(out_branches
, "goto %s;\n"
6173 mytmpid
.c_str(), (unsigned long) goto_label_num
);
6176 void Statement::ilt_generate_code_alt(ILT
*ilt
)
6178 const string
& mytmpid
=ilt
->get_my_tmpid();
6179 size_t goto_label_num
=ilt
->get_new_label_num();
6180 char *label_end
= mprintf("%s_l%lu", mytmpid
.c_str(),
6181 (unsigned long) goto_label_num
);
6182 ags
->set_il_label_end (label_end
);
6183 ILT_branch
*branch
=ilt
->get_as_branch();
6184 string state_cond
=branch
->get_state_cond();
6185 size_t state_var
=branch
->get_my_state_var();
6186 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6187 char*& out_branches
=ilt
->get_out_branches();
6188 for(size_t i
=0; i
<ags
->get_nof_ags(); i
++) {
6189 AltGuard
*ag
=ags
->get_ag_byIndex(i
);
6190 if(ag
->get_type()!=AltGuard::AG_OP
)
6191 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6192 ilt
->add_branch(new ILT_branch(ILT_branch::BT_ALT
, ag
, state_cond
,
6193 state_var
, state_var_val
,
6196 out_branches
=update_location_object(out_branches
);
6197 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6200 mytmpid
.c_str(), (unsigned long) state_var
,
6201 (unsigned long) state_var_val
,
6202 mytmpid
.c_str(), label_end
);
6206 void Statement::ilt_generate_code_receiving(ILT
*ilt
)
6208 const string
& mytmpid
=ilt
->get_my_tmpid();
6209 size_t goto_label_num
=ilt
->get_new_label_num();
6210 ILT_branch
*branch
=ilt
->get_as_branch();
6211 string state_cond
=branch
->get_state_cond();
6212 size_t state_var
=branch
->get_my_state_var();
6213 size_t state_var_val
=ilt
->get_new_state_var_val(state_var
);
6214 char*& out_branches
=ilt
->get_out_branches();
6215 ilt
->add_branch(new ILT_branch(ILT_branch::BT_RECV
, this, state_cond
,
6216 state_var
, state_var_val
, goto_label_num
));
6217 out_branches
=update_location_object(out_branches
);
6218 out_branches
=mputprintf(out_branches
, "%s_state[%lu]=%lu;\n"
6221 mytmpid
.c_str(), (unsigned long) state_var
,
6222 (unsigned long) state_var_val
,
6223 mytmpid
.c_str(), mytmpid
.c_str(),
6224 (unsigned long) goto_label_num
);
6227 void Statement::ilt_generate_code_def(ILT
*ilt
)
6229 char*& str
=ilt
->get_out_branches();
6230 str
=update_location_object(str
);
6232 char *genname
=mprintf("%s_d%lu_%s", ilt
->get_my_tmpid().c_str(),
6233 (unsigned long) ilt
->get_new_tmpnum(),
6234 def
->get_id().get_name().c_str());
6235 def
->set_genname(string(genname
));
6238 def
->ilt_generate_code(ilt
);
6241 void Statement::ilt_generate_code_if(ILT
*ilt
)
6243 char *end_label
=mprintf("%s_l%lu",
6244 ilt
->get_my_tmpid().c_str(),
6245 (unsigned long) ilt
->get_new_label_num());
6247 if_stmt
.ics
->ilt_generate_code(ilt
, end_label
, unreach
);
6248 if(if_stmt
.elseblock
&& !unreach
)
6249 if_stmt
.elseblock
->ilt_generate_code(ilt
);
6250 char*& str
=ilt
->get_out_branches();
6251 str
=mputprintf(str
, "%s:\n", end_label
);
6255 void Statement::ilt_generate_code_select(ILT
*ilt
)
6257 char*& str
=ilt
->get_out_branches();
6258 str
=update_location_object(str
);
6259 const string
& tmp_prefix
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6260 char *expr_init
=memptystr();
6261 char *expr_name
=select
.expr
->generate_code_tmp(0, expr_init
);
6262 select
.scs
->ilt_generate_code(ilt
, tmp_prefix
.c_str(),
6263 expr_init
, expr_name
);
6268 void Statement::ilt_generate_code_call(ILT
*ilt
)
6270 char*& str
=ilt
->get_out_branches();
6271 str
=update_location_object(str
);
6272 expression_struct expr
;
6273 Code::init_expr(&expr
);
6274 port_op
.portref
->generate_code(&expr
);
6275 expr
.expr
= mputstr(expr
.expr
, ".call(");
6276 port_op
.s
.sendpar
->generate_code(&expr
);
6277 if(port_op
.s
.toclause
) {
6278 expr
.expr
= mputstr(expr
.expr
, ", ");
6279 port_op
.s
.toclause
->generate_code_expr(&expr
);
6281 expr
.expr
= mputc(expr
.expr
, ')');
6282 str
= Code::merge_free_expr(str
, &expr
);
6283 if (port_op
.s
.call
.body
) {
6284 str
= mputstr(str
, "{\n"); // (1)
6285 if (port_op
.s
.call
.timer
) {
6286 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6287 str
= mputstr(str
, "TIMER call_timer;\n");
6288 Code::init_expr(&expr
);
6289 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6290 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6291 expr
.expr
= mputc(expr
.expr
, ')');
6292 str
= Code::merge_free_expr(str
, &expr
);
6294 // the label name is used for prefixing local variables
6295 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6296 const string
& tmplabel
= my_sb
->get_scope_mod_gen()->get_temporary_id();
6297 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this, tmplabel
,
6299 const char *label_str
= tmplabel
.c_str();
6300 str
=mputprintf(str
, "goto %s_end;\n"
6303 port_op
.s
.call
.body
->ilt_generate_code_call_body(ilt
, label_str
);
6304 str
=mputprintf(str
, "%s_end:\n", label_str
);
6308 void Statement::ilt_generate_code_for(ILT
*ilt
)
6310 char*& str
= ilt
->get_out_branches();
6311 str
= update_location_object(str
);
6312 // statements in initial may have side effects
6313 // generate code for them anyway
6314 if (loop
.for_stmt
.varinst
) {
6315 char *genname
= mprintf("%s_d%lu_", ilt
->get_my_tmpid().c_str(),
6316 (unsigned long) ilt
->get_new_tmpnum());
6317 loop
.for_stmt
.init_varinst
->set_genname(string(genname
));
6319 loop
.for_stmt
.init_varinst
->ilt_generate_code(ilt
);
6320 } else str
= loop
.for_stmt
.init_ass
->generate_code(str
);
6321 // check whether the final expression is constant
6322 bool final_is_true
= false, final_is_false
= false;
6323 if (!loop
.for_stmt
.finalexpr
->is_unfoldable()) {
6324 if (loop
.for_stmt
.finalexpr
->get_val_bool()) final_is_true
= true;
6325 else final_is_false
= true;
6327 if (final_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6329 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6330 (unsigned long) ilt
->get_new_label_num());
6331 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6332 // do not generate the exit condition for infinite loops
6333 if (!final_is_true
) {
6334 str
= loop
.for_stmt
.finalexpr
->update_location_object(str
);
6335 size_t blockcount
= 0;
6336 str
= loop
.for_stmt
.finalexpr
->generate_code_tmp(str
, "if (!",
6338 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6339 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6343 loop
.il_label_end
= new string(label_prefix
);
6344 *loop
.il_label_end
+= "end";
6347 loop
.label_next
= new string(label_prefix
);
6348 *loop
.label_next
+= "next";
6350 loop
.block
->ilt_generate_code(ilt
);
6351 if (loop
.label_next
)
6352 str
= mputprintf(str
, "%snext:\n", label_prefix
);
6353 str
= update_location_object(str
);
6354 str
= loop
.for_stmt
.step
->generate_code(str
);
6355 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6356 if (!final_is_true
|| loop
.has_brk
)
6357 str
= mputprintf(str
, "%send:\n", label_prefix
);
6362 void Statement::ilt_generate_code_while(ILT
*ilt
)
6364 char*& str
= ilt
->get_out_branches();
6365 // Location need not be set here; the location is set for the expression.
6366 // check whether the expression is constant
6367 bool expr_is_true
= false, expr_is_false
= false;
6368 if (!loop
.expr
->is_unfoldable()) {
6369 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6370 else expr_is_false
= true;
6372 if (expr_is_false
) str
= mputstr(str
, "/* never occurs */;\n");
6374 char *label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6375 (unsigned long) ilt
->get_new_label_num());
6376 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6379 loop
.il_label_end
= new string(label_prefix
);
6380 *loop
.il_label_end
+= "end";
6383 loop
.label_next
= new string(label_prefix
);
6384 *loop
.label_next
+= "begin";
6386 // do not generate the exit condition for infinite loops
6387 if (!expr_is_true
) {
6388 str
= loop
.expr
->update_location_object(str
);
6389 size_t blockcount
= 0;
6390 str
= loop
.expr
->generate_code_tmp(str
, "if (!", blockcount
);
6391 str
= mputprintf(str
, ") goto %send;\n", label_prefix
);
6392 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6394 loop
.block
->ilt_generate_code(ilt
);
6395 str
= update_location_object(str
);
6396 str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6397 if (!expr_is_true
|| loop
.has_brk
)
6398 str
= mputprintf(str
, "%send:\n", label_prefix
);
6403 void Statement::ilt_generate_code_dowhile(ILT
*ilt
)
6405 char*& str
= ilt
->get_out_branches();
6406 // Location need not be set here; there is only a label before the body.
6407 // check whether the expression is constant
6408 bool expr_is_true
= false;
6409 if (!loop
.expr
->is_unfoldable()) {
6410 if (loop
.expr
->get_val_bool()) expr_is_true
= true;
6411 else loop
.iterate_once
= true;
6413 char *label_prefix
= 0;
6414 if (!loop
.iterate_once
|| loop
.has_brk
|| loop
.has_cnt
)
6415 label_prefix
= mprintf("%s_l%lu_", ilt
->get_my_tmpid().c_str(),
6416 (unsigned long) ilt
->get_new_label_num());
6419 loop
.il_label_end
= new string(label_prefix
);
6420 *loop
.il_label_end
+= "end";
6423 loop
.label_next
= new string(label_prefix
);
6424 if (loop
.iterate_once
) {
6425 if (loop
.label_next
) *loop
.label_next
+= "end";
6426 loop
.block
->ilt_generate_code(ilt
);
6428 str
= mputprintf(str
, "%sbegin:\n", label_prefix
);
6429 if (loop
.label_next
)
6430 *loop
.label_next
+= (expr_is_true
? "begin" : "next");
6431 loop
.block
->ilt_generate_code(ilt
);
6432 if (expr_is_true
) str
= mputprintf(str
, "goto %sbegin;\n", label_prefix
);
6434 if (loop
.label_next
) str
= mputprintf(str
, "%snext:\n", label_prefix
);
6435 str
= loop
.expr
->update_location_object(str
);
6436 size_t blockcount
= 0;
6437 str
= loop
.expr
->generate_code_tmp(str
, "if (", blockcount
);
6438 str
= mputprintf(str
, ") goto %sbegin;\n", label_prefix
);
6439 while (blockcount
-- > 0) str
= mputstr(str
, "}\n");
6442 if (loop
.il_label_end
|| (loop
.iterate_once
&& loop
.label_next
)) {
6443 str
= mputprintf(str
, "%send: ;\n", label_prefix
);
6448 char *Statement::generate_code_return(char *str
)
6450 expression_struct expr
;
6451 Code::init_expr(&expr
);
6452 expr
.expr
= mputstr(expr
.expr
, "return");
6453 Definition
*my_def
= my_sb
->get_my_def();
6455 expr
.expr
= mputc(expr
.expr
, ' ');
6456 if (debugger_active
) {
6457 // the debugger's return value storing macro requires a temporary,
6458 // so the returned expression isn't evaluated twice
6459 string tmp_id
= my_def
->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
6460 expr
.preamble
= mputprintf(expr
.preamble
, "%s %s;\n",
6461 returnexpr
.v
->get_expr_governor_last()->get_genname_value(my_def
->get_my_scope()).c_str(),
6463 expr
.expr
= mputprintf(expr
.expr
, "DEBUGGER_STORE_RETURN_VALUE(%s, ", tmp_id
.c_str());
6465 returnexpr
.v
->generate_code_expr_mandatory(&expr
);
6466 if (debugger_active
) {
6467 expr
.expr
= mputc(expr
.expr
, ')');
6469 } else if (returnexpr
.t
) {
6470 expr
.expr
= mputc(expr
.expr
, ' ');
6471 if (!my_def
) FATAL_ERROR("Statement::generate_code_return()");
6472 if (debugger_active
) {
6473 // the debugger's return value storing macro requires a temporary,
6474 // so the returned expression isn't evaluated twice
6475 string tmp_id
= my_def
->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
6476 expr
.preamble
= mputprintf(expr
.preamble
, "%s_template %s;\n",
6477 returnexpr
.t
->get_my_governor()->get_genname_value(my_def
->get_my_scope()).c_str(),
6479 expr
.expr
= mputprintf(expr
.expr
, "DEBUGGER_STORE_RETURN_VALUE(%s, ", tmp_id
.c_str());
6481 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(my_def
);
6482 if (!dfb
) FATAL_ERROR("Statement::generate_code_return()");
6483 if (dfb
->get_template_restriction() != TR_NONE
&&
6484 returnexpr
.gen_restriction_check
) {
6485 returnexpr
.t
->generate_code_expr(&expr
,
6486 dfb
->get_template_restriction());
6488 returnexpr
.t
->generate_code_expr(&expr
, TR_NONE
);
6490 if (debugger_active
) {
6491 expr
.expr
= mputc(expr
.expr
, ')');
6494 if (my_def
&& my_def
->get_asstype() == Definition::A_ALTSTEP
)
6495 expr
.expr
= mputstr(expr
.expr
, " ALT_YES");
6496 // else it's a return with no value: the only case a blank is unneeded
6498 return Code::merge_free_expr(str
, &expr
);
6501 char *Statement::generate_code_activate(char *str
)
6503 expression_struct expr
;
6504 Code::init_expr(&expr
);
6505 expr
.expr
= mputprintf(expr
.expr
, "%s(", ref_pard
->get_refd_assignment()
6506 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6507 ref_pard
->get_parlist()->generate_code_noalias(&expr
, ref_pard
->get_refd_assignment()->get_FormalParList());
6508 expr
.expr
= mputc(expr
.expr
, ')');
6509 return Code::merge_free_expr(str
, &expr
);
6512 char *Statement::generate_code_activate_refd(char *str
)
6514 expression_struct expr
;
6515 Code::init_expr(&expr
);
6516 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6517 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
6518 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6519 ->get_genname_from_scope(my_sb
, "activate_").c_str());
6521 fau_refd
.value
->generate_code_expr_mandatory(&expr
);
6522 expr
.expr
= mputstr(expr
.expr
, ".activate(");
6524 fau_refd
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6525 expr
.expr
= mputc(expr
.expr
, ')');
6526 return Code::merge_free_expr(str
, &expr
);
6529 char *Statement::generate_code_deactivate(char *str
)
6531 if(!deactivate
) str
=mputstr(str
, "TTCN_Default::deactivate_all();\n");
6533 expression_struct expr
;
6534 Code::init_expr(&expr
);
6535 expr
.expr
=mputstr(expr
.expr
, "TTCN_Default::deactivate(");
6536 deactivate
->generate_code_expr(&expr
);
6537 expr
.expr
=mputstr(expr
.expr
, ");\n");
6538 str
=Code::merge_free_expr(str
, &expr
);
6543 char *Statement::generate_code_send(char *str
)
6545 expression_struct expr
;
6546 Code::init_expr(&expr
);
6547 port_op
.portref
->generate_code(&expr
);
6548 expr
.expr
= mputstr(expr
.expr
, ".send(");
6549 generate_code_expr_sendpar(&expr
);
6550 if (port_op
.s
.toclause
) {
6551 expr
.expr
= mputstr(expr
.expr
, ", ");
6552 port_op
.s
.toclause
->generate_code_expr(&expr
);
6554 expr
.expr
= mputc(expr
.expr
, ')');
6555 return Code::merge_free_expr(str
, &expr
);
6558 char *Statement::generate_code_call(char *str
)
6560 expression_struct expr
;
6561 Code::init_expr(&expr
);
6562 port_op
.portref
->generate_code(&expr
);
6563 expr
.expr
= mputstr(expr
.expr
, ".call(");
6564 port_op
.s
.sendpar
->generate_code(&expr
);
6565 if(port_op
.s
.toclause
) {
6566 expr
.expr
= mputstr(expr
.expr
, ", ");
6567 port_op
.s
.toclause
->generate_code_expr(&expr
);
6569 expr
.expr
= mputc(expr
.expr
, ')');
6570 str
= Code::merge_free_expr(str
, &expr
);
6571 if (port_op
.s
.call
.body
) {
6572 str
= mputstr(str
, "{\n");
6573 if (port_op
.s
.call
.timer
) {
6574 str
= port_op
.s
.call
.timer
->update_location_object(str
);
6575 str
= mputstr(str
, "TIMER call_timer;\n");
6576 Code::init_expr(&expr
);
6577 expr
.expr
= mputstr(expr
.expr
, "call_timer.start(");
6578 port_op
.s
.call
.timer
->generate_code_expr(&expr
);
6579 expr
.expr
= mputc(expr
.expr
, ')');
6580 str
= Code::merge_free_expr(str
, &expr
);
6582 // the label name is used for prefixing local variables
6583 if(!my_sb
) FATAL_ERROR("Statement::generate_code_call()");
6584 str
= port_op
.s
.call
.body
->generate_code_call_body(str
, *this,
6585 my_sb
->get_scope_mod_gen()->get_temporary_id(), false);
6586 str
=mputstr(str
, "}\n");
6591 char *Statement::generate_code_reply(char *str
)
6593 expression_struct expr
;
6594 Code::init_expr(&expr
);
6595 port_op
.portref
->generate_code(&expr
);
6596 expr
.expr
=mputstr(expr
.expr
, ".reply(");
6597 port_op
.s
.sendpar
->generate_code(&expr
);
6598 if(port_op
.s
.replyval
) {
6599 expr
.expr
=mputstr(expr
.expr
, ".set_value_template(");
6600 port_op
.s
.replyval
->generate_code_expr(&expr
);
6601 expr
.expr
=mputc(expr
.expr
, ')');
6603 if(port_op
.s
.toclause
) {
6604 expr
.expr
=mputstr(expr
.expr
, ", ");
6605 port_op
.s
.toclause
->generate_code_expr(&expr
);
6607 expr
.expr
=mputc(expr
.expr
, ')');
6608 return Code::merge_free_expr(str
, &expr
);
6611 char *Statement::generate_code_raise(char *str
)
6613 expression_struct expr
;
6614 Code::init_expr(&expr
);
6615 port_op
.portref
->generate_code(&expr
);
6616 expr
.expr
=mputstr(expr
.expr
, ".raise(");
6617 port_op
.s
.raise
.signature_ref
->generate_code(&expr
);
6618 expr
.expr
=mputstr(expr
.expr
, "_exception(");
6619 generate_code_expr_sendpar(&expr
);
6620 expr
.expr
=mputc(expr
.expr
, ')');
6621 if(port_op
.s
.toclause
) {
6622 expr
.expr
=mputstr(expr
.expr
, ", ");
6623 port_op
.s
.toclause
->generate_code_expr(&expr
);
6625 expr
.expr
=mputc(expr
.expr
, ')');
6626 return Code::merge_free_expr(str
, &expr
);
6629 char *Statement::generate_code_portop(char *str
, const char *opname
)
6631 if (port_op
.portref
) {
6632 expression_struct expr
;
6633 Code::init_expr(&expr
);
6634 port_op
.portref
->generate_code(&expr
);
6635 expr
.expr
=mputprintf(expr
.expr
, ".%s()", opname
);
6636 str
=Code::merge_free_expr(str
, &expr
);
6638 str
= mputprintf(str
, "PORT::all_%s();\n", opname
);
6643 char *Statement::generate_code_startcomp(char *str
)
6645 expression_struct expr
;
6646 Code::init_expr(&expr
);
6647 Common::Assignment
*func
= comp_op
.funcinstref
->get_refd_assignment();
6648 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6649 func
->get_genname_from_scope(my_sb
, "start_").c_str());
6650 comp_op
.compref
->generate_code_expr(&expr
);
6651 FormalParList
*fplist
= func
->get_FormalParList();
6652 if (fplist
->get_nof_fps() > 0) {
6653 expr
.expr
= mputstr(expr
.expr
, ", ");
6654 comp_op
.funcinstref
->get_parlist()->generate_code_noalias(&expr
, fplist
);
6656 expr
.expr
= mputc(expr
.expr
, ')');
6657 return Code::merge_free_expr(str
, &expr
);
6660 char *Statement::generate_code_startcomp_refd(char *str
)
6662 expression_struct expr
;
6663 Code::init_expr(&expr
);
6664 Value
*last_v
= comp_op
.derefered
.value
->get_value_refd_last();
6665 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
6666 expr
.expr
= mputprintf(expr
.expr
, "%s(", last_v
->get_refd_fat()
6667 ->get_genname_from_scope(my_sb
, "start_").c_str());
6669 comp_op
.derefered
.value
->generate_code_expr_mandatory(&expr
);
6670 expr
.expr
= mputstr(expr
.expr
, ".start(");
6672 comp_op
.compref
->generate_code_expr(&expr
);
6673 if (comp_op
.derefered
.ap_list2
->get_nof_pars() > 0) {
6674 expr
.expr
= mputstr(expr
.expr
, ", ");
6675 comp_op
.derefered
.ap_list2
->generate_code_noalias(&expr
, NULL
);
6677 expr
.expr
= mputc(expr
.expr
, ')');
6678 return Code::merge_free_expr(str
, &expr
);
6681 char *Statement::generate_code_compop(char *str
, const char *opname
)
6683 expression_struct expr
;
6684 Code::init_expr(&expr
);
6685 if (comp_op
.compref
) {
6686 Value
*v_last
= comp_op
.compref
->get_value_refd_last();
6687 if (v_last
->get_valuetype() == Value::V_REFD
) {
6688 // the argument is a simple component reference
6689 v_last
->generate_code_expr_mandatory(&expr
);
6690 expr
.expr
= mputprintf(expr
.expr
, ".%s()", opname
);
6692 bool refers_to_self
= false;
6693 if (v_last
->get_valuetype() == Value::V_EXPR
) {
6694 // the argument is a special component reference (mtc, self, etc.)
6695 switch (v_last
->get_optype()) {
6696 case Value::OPTYPE_COMP_MTC
: {
6697 Definition
*my_def
= my_sb
->get_my_def();
6698 if (my_def
&& my_def
->get_asstype() == Definition::A_TESTCASE
)
6699 refers_to_self
= true;
6701 case Value::OPTYPE_COMP_SELF
:
6702 refers_to_self
= true;
6707 if (refers_to_self
) {
6708 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_execution()",
6711 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_component(",
6713 v_last
->generate_code_expr(&expr
);
6714 expr
.expr
= mputc(expr
.expr
, ')');
6718 // the operation refers to all component
6719 expr
.expr
= mputprintf(expr
.expr
,
6720 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname
);
6722 return Code::merge_free_expr(str
, &expr
);
6725 char *Statement::generate_code_configop(char *str
, const char *opname
)
6727 expression_struct expr
;
6728 Code::init_expr(&expr
);
6729 expr
.expr
= mputprintf(expr
.expr
, "TTCN_Runtime::%s_port(", opname
);
6730 config_op
.compref1
->generate_code_expr(&expr
);
6731 expr
.expr
= mputstr(expr
.expr
, ", ");
6732 if (config_op
.compref1
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6733 // the component type is known
6734 // the name of the referred port can be used
6735 config_op
.portref1
->generate_code_portref(&expr
, my_sb
);
6736 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6738 // the component type is unknown
6739 // a simple string shall be formed from the port name and array indices
6740 generate_code_portref(&expr
, config_op
.portref1
);
6742 expr
.expr
= mputstr(expr
.expr
, ", ");
6743 config_op
.compref2
->generate_code_expr(&expr
);
6744 expr
.expr
= mputstr(expr
.expr
, ", ");
6745 if (config_op
.compref2
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
)) {
6746 // the component type is known
6747 // the name of the referred port can be used
6748 config_op
.portref2
->generate_code_portref(&expr
, my_sb
);
6749 expr
.expr
= mputstr(expr
.expr
, ".get_name()");
6751 // the component type is unknown
6752 // a simple string shall be formed from the port name and array indices
6753 generate_code_portref(&expr
, config_op
.portref2
);
6755 expr
.expr
= mputc(expr
.expr
, ')');
6756 return Code::merge_free_expr(str
, &expr
);
6759 char *Statement::generate_code_starttimer(char *str
)
6761 expression_struct expr
;
6762 Code::init_expr(&expr
);
6763 timer_op
.timerref
->generate_code(&expr
);
6764 expr
.expr
=mputstr(expr
.expr
, ".start(");
6765 if(timer_op
.value
) timer_op
.value
->generate_code_expr(&expr
);
6766 expr
.expr
=mputc(expr
.expr
, ')');
6767 str
=Code::merge_free_expr(str
, &expr
);
6771 char *Statement::generate_code_stoptimer(char *str
)
6773 if(!timer_op
.timerref
) str
=mputstr(str
, "TIMER::all_stop();\n");
6775 expression_struct expr
;
6776 Code::init_expr(&expr
);
6777 timer_op
.timerref
->generate_code(&expr
);
6778 expr
.expr
=mputstr(expr
.expr
, ".stop()");
6779 str
=Code::merge_free_expr(str
, &expr
);
6784 char *Statement::generate_code_setverdict(char *str
)
6786 expression_struct expr
;
6787 Code::init_expr(&expr
);
6788 expr
.expr
=mputstr(expr
.expr
, "TTCN_Runtime::setverdict(");
6789 setverdict
.verdictval
->generate_code_expr(&expr
);
6790 if (setverdict
.logargs
) {
6791 expr
.expr
=mputc(expr
.expr
, ',');
6792 expression_struct expr_reason
;
6793 Code::init_expr(&expr_reason
);
6794 setverdict
.logargs
->generate_code_expr(&expr_reason
);
6795 if (expr_reason
.preamble
)
6796 expr
.preamble
= mputprintf(expr
.preamble
, "%s;\n",
6797 expr_reason
.preamble
);
6798 if (expr_reason
.postamble
)
6799 expr
.postamble
= mputprintf(expr
.postamble
, "%s;\n",
6800 expr_reason
.postamble
);
6801 expr
.expr
= mputprintf(expr
.expr
, "%s", expr_reason
.expr
);
6802 Code::free_expr(&expr_reason
);
6804 expr
.expr
=mputc(expr
.expr
, ')');
6805 str
=Code::merge_free_expr(str
, &expr
);
6809 char *Statement::generate_code_action(char *str
)
6811 str
=mputstr(str
, "TTCN_Runtime::begin_action();\n");
6812 if(!logargs
) str
=mputstr(str
, "TTCN_Logger::log_event_str"
6813 "(\"<empty action statement>\");\n");
6814 else str
=logargs
->generate_code(str
);
6815 str
=mputstr(str
, "TTCN_Runtime::end_action();\n");
6819 char *Statement::generate_code_testcaseinst(char *str
)
6821 expression_struct expr
;
6822 Code::init_expr(&expr
);
6823 Common::Assignment
*testcase
= testcase_inst
.tcref
->get_refd_assignment();
6824 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6825 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6826 ActualParList
*t_aplist
= testcase_inst
.tcref
->get_parlist();
6827 if (t_aplist
->get_nof_pars() > 0) {
6828 t_aplist
->generate_code_alias(&expr
, testcase
->get_FormalParList(),
6830 expr
.expr
= mputstr(expr
.expr
, ", ");
6832 if (testcase_inst
.timerval
) {
6833 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6834 testcase_inst
.timerval
->generate_code_expr(&expr
);
6835 expr
.expr
= mputc(expr
.expr
, ')');
6836 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6837 return Code::merge_free_expr(str
, &expr
);
6840 char *Statement::generate_code_execute_refd(char *str
)
6842 expression_struct expr
;
6843 Code::init_expr(&expr
);
6844 Value
*last_v
= fau_refd
.value
->get_value_refd_last();
6845 if (last_v
->get_valuetype() == Value::V_TESTCASE
) {
6846 Common::Assignment
*testcase
= last_v
->get_refd_fat();
6847 expr
.expr
= mputprintf(expr
.expr
, "%s(",
6848 testcase
->get_genname_from_scope(my_sb
, "testcase_").c_str());
6849 execute_refd
.ap_list2
->generate_code_alias(&expr
,
6850 testcase
->get_FormalParList(), 0, false);
6852 execute_refd
.value
->generate_code_expr_mandatory(&expr
);
6853 expr
.expr
= mputstr(expr
.expr
, ".execute(");
6854 execute_refd
.ap_list2
->generate_code_alias(&expr
, 0, 0, false);
6856 if (execute_refd
.ap_list2
->get_nof_pars() > 0)
6857 expr
.expr
= mputstr(expr
.expr
, ", ");
6858 if (execute_refd
.timerval
) {
6859 expr
.expr
= mputstr(expr
.expr
, "TRUE, ");
6860 execute_refd
.timerval
->generate_code_expr(&expr
);
6861 expr
.expr
= mputc(expr
.expr
, ')');
6862 } else expr
.expr
= mputstr(expr
.expr
, "FALSE, 0.0)");
6863 return Code::merge_free_expr(str
,&expr
);
6866 void Statement::generate_code_expr_receive(expression_struct
*expr
,
6869 if (port_op
.portref
) {
6870 // The operation refers to a specific port.
6871 port_op
.portref
->generate_code(expr
);
6872 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6873 if (port_op
.r
.rcvpar
) {
6874 // The receive parameter is present.
6875 if (use_runtime_2
&& TypeConv::needs_conv_redir(port_op
.r
.rcvpar
,
6876 port_op
.r
.redirect
.value
)) {
6877 // Don't change the first parameter. Otherwise it won't receive
6878 // anything. The only thing we need is a temporary to save the
6879 // result and a conversion at the end.
6880 TypeConv::gen_conv_code_redir(expr
, port_op
.r
.rcvpar
,
6881 port_op
.r
.redirect
.value
);
6883 port_op
.r
.rcvpar
->generate_code(expr
);
6884 expr
->expr
= mputstr(expr
->expr
, ", ");
6885 if (port_op
.r
.redirect
.value
) {
6886 // Value redirect is also present.
6887 expr
->expr
= mputstr(expr
->expr
, "&(");
6888 port_op
.r
.redirect
.value
->generate_code(expr
);
6889 expr
->expr
= mputc(expr
->expr
, ')');
6890 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6892 expr
->expr
= mputstr(expr
->expr
, ", ");
6895 // the operation refers to any port
6896 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6898 generate_code_expr_fromclause(expr
);
6899 expr
->expr
= mputstr(expr
->expr
, ", ");
6900 generate_code_expr_senderredirect(expr
);
6901 expr
->expr
= mputc(expr
->expr
, ')');
6904 void Statement::generate_code_expr_getcall(expression_struct
*expr
,
6907 if (port_op
.portref
) {
6908 // the operation refers to a specific port
6909 port_op
.portref
->generate_code(expr
);
6910 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6911 if (port_op
.r
.rcvpar
) {
6912 // the signature template is present
6913 port_op
.r
.rcvpar
->generate_code(expr
);
6914 expr
->expr
= mputstr(expr
->expr
, ", ");
6915 generate_code_expr_fromclause(expr
);
6916 // a temporary object is needed for parameter redirect
6917 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6918 expr
->expr
= mputprintf(expr
->expr
, ", %s_call_redirect(",
6919 signature
->get_genname_value(my_sb
).c_str());
6920 if (port_op
.r
.redirect
.param
)
6921 port_op
.r
.redirect
.param
->generate_code(expr
);
6922 expr
->expr
= mputstr(expr
->expr
, "), ");
6923 generate_code_expr_senderredirect(expr
);
6925 // the signature parameter is not present
6926 generate_code_expr_fromclause(expr
);
6927 expr
->expr
= mputstr(expr
->expr
, ", ");
6928 generate_code_expr_senderredirect(expr
);
6931 // the operation refers to any port
6932 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6933 generate_code_expr_fromclause(expr
);
6934 expr
->expr
= mputstr(expr
->expr
, ", ");
6935 generate_code_expr_senderredirect(expr
);
6937 expr
->expr
=mputc(expr
->expr
, ')');
6940 void Statement::generate_code_expr_getreply(expression_struct
*expr
,
6943 if (port_op
.portref
) {
6944 // the operation refers to a specific port
6945 port_op
.portref
->generate_code(expr
);
6946 expr
->expr
= mputprintf(expr
->expr
, ".%s(", opname
);
6947 if (port_op
.r
.rcvpar
) {
6948 // the signature template is present
6949 port_op
.r
.rcvpar
->generate_code(expr
);
6950 Type
*signature
= port_op
.r
.rcvpar
->get_Template()->get_my_governor();
6952 signature
->get_type_refd_last()->get_signature_return_type();
6954 expr
->expr
= mputstr(expr
->expr
, ".set_value_template(");
6955 if (port_op
.r
.getreply_valuematch
) {
6956 // the value match is also present
6957 port_op
.r
.getreply_valuematch
->generate_code(expr
);
6959 // the value match is not present
6960 // we must substitute it with ? in the signature template
6961 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
6962 return_type
->get_genname_template(my_sb
).c_str());
6964 expr
->expr
= mputc(expr
->expr
, ')');
6966 expr
->expr
= mputstr(expr
->expr
, ", ");
6967 generate_code_expr_fromclause(expr
);
6968 // a temporary object is needed for value and parameter redirect
6969 expr
->expr
= mputprintf(expr
->expr
, ", %s_reply_redirect(",
6970 signature
->get_genname_value(my_sb
).c_str());
6972 // the first argument of the constructor must contain
6973 // the value redirect
6974 if (port_op
.r
.redirect
.value
) {
6975 expr
->expr
= mputstr(expr
->expr
, "&(");
6976 port_op
.r
.redirect
.value
->generate_code(expr
);
6977 expr
->expr
= mputc(expr
->expr
, ')');
6978 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
6979 if (port_op
.r
.redirect
.param
) expr
->expr
= mputstr(expr
->expr
, ", ");
6981 if (port_op
.r
.redirect
.param
)
6982 port_op
.r
.redirect
.param
->generate_code(expr
);
6983 expr
->expr
= mputstr(expr
->expr
, "), ");
6984 generate_code_expr_senderredirect(expr
);
6986 // the signature template is not present
6987 generate_code_expr_fromclause(expr
);
6988 expr
->expr
= mputstr(expr
->expr
, ", ");
6989 generate_code_expr_senderredirect(expr
);
6992 // the operation refers to any port
6993 expr
->expr
= mputprintf(expr
->expr
, "PORT::any_%s(", opname
);
6994 generate_code_expr_fromclause(expr
);
6995 expr
->expr
= mputstr(expr
->expr
, ", ");
6996 generate_code_expr_senderredirect(expr
);
6998 expr
->expr
= mputc(expr
->expr
, ')');
7001 void Statement::generate_code_expr_catch(expression_struct
*expr
)
7003 if (port_op
.portref
) {
7004 // the operation refers to a specific port
7005 if (port_op
.r
.ctch
.timeout
) {
7006 // the operation catches the timeout exception
7007 expr
->expr
= mputstr(expr
->expr
, "call_timer.timeout()");
7010 port_op
.portref
->generate_code(expr
);
7011 expr
->expr
= mputprintf(expr
->expr
, ".%s(",
7012 statementtype
== S_CHECK_CATCH
? "check_catch" : "get_exception");
7013 if (port_op
.r
.ctch
.signature_ref
) {
7014 // the signature reference and the exception template is present
7015 expr
->expr
= mputprintf(expr
->expr
, "%s_exception_template(",
7016 port_op
.r
.ctch
.signature
->get_genname_value(my_sb
).c_str());
7017 port_op
.r
.rcvpar
->generate_code(expr
);
7018 expr
->expr
= mputstr(expr
->expr
, ", ");
7019 if (port_op
.r
.redirect
.value
) {
7020 // value redirect is also present
7021 expr
->expr
= mputstr(expr
->expr
, "&(");
7022 port_op
.r
.redirect
.value
->generate_code(expr
);
7023 expr
->expr
= mputc(expr
->expr
, ')');
7024 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
7025 expr
->expr
= mputstr(expr
->expr
, "), ");
7028 // the operation refers to any port
7029 expr
->expr
= mputprintf(expr
->expr
, "PORT::%s(",
7030 statementtype
== S_CHECK_CATCH
? "any_check_catch" : "any_catch");
7032 generate_code_expr_fromclause(expr
);
7033 expr
->expr
= mputstr(expr
->expr
, ", ");
7034 generate_code_expr_senderredirect(expr
);
7035 expr
->expr
= mputc(expr
->expr
, ')');
7038 void Statement::generate_code_expr_check(expression_struct
*expr
)
7040 if (port_op
.portref
) {
7041 // the operation refers to a specific port
7042 port_op
.portref
->generate_code(expr
);
7043 expr
->expr
= mputstr(expr
->expr
, ".check");
7045 // the operation refers to any port
7046 expr
->expr
= mputstr(expr
->expr
, "PORT::any_check");
7048 expr
->expr
= mputc(expr
->expr
, '(');
7049 generate_code_expr_fromclause(expr
);
7050 expr
->expr
= mputstr(expr
->expr
, ", ");
7051 generate_code_expr_senderredirect(expr
);
7052 expr
->expr
= mputc(expr
->expr
, ')');
7055 void Statement::generate_code_expr_done(expression_struct
*expr
)
7057 if (comp_op
.compref
) {
7058 if (comp_op
.donereturn
.donematch
) {
7059 // value returning done
7060 // figure out what type the done() function belongs to
7061 Type
*t
= comp_op
.donereturn
.donematch
7062 ->get_expr_governor(Type::EXPECTED_TEMPLATE
);
7063 if (!t
) FATAL_ERROR("Statement::generate_code_expr_done()");
7064 while (t
->is_ref() && !t
->has_done_attribute())
7065 t
= t
->get_type_refd();
7066 if (!t
->has_done_attribute())
7067 FATAL_ERROR("Statement::generate_code_expr_done()");
7068 // determine whether the done() function is in the same module
7069 Common::Module
*t_mod
= t
->get_my_scope()->get_scope_mod_gen();
7070 if (t_mod
!= my_sb
->get_scope_mod_gen()) {
7071 expr
->expr
= mputprintf(expr
->expr
, "%s::",
7072 t_mod
->get_modid().get_name().c_str());
7074 expr
->expr
= mputstr(expr
->expr
, "done(");
7075 comp_op
.compref
->generate_code_expr(expr
);
7076 expr
->expr
= mputstr(expr
->expr
, ", ");
7077 comp_op
.donereturn
.donematch
->generate_code(expr
);
7078 expr
->expr
= mputstr(expr
->expr
, ", ");
7079 if (comp_op
.donereturn
.redirect
) {
7080 // value redirect is present
7081 expr
->expr
= mputstr(expr
->expr
, "&(");
7082 comp_op
.donereturn
.redirect
->generate_code(expr
);
7083 expr
->expr
= mputc(expr
->expr
, ')');
7085 // value redirect is omitted
7086 expr
->expr
= mputstr(expr
->expr
, "NULL");
7088 expr
->expr
= mputc(expr
->expr
, ')');
7091 comp_op
.compref
->generate_code_expr_mandatory(expr
);
7092 expr
->expr
= mputstr(expr
->expr
, ".done()");
7094 } else if (comp_op
.any_or_all
== C_ANY
) {
7095 // any component.done
7096 expr
->expr
= mputstr(expr
->expr
,
7097 "TTCN_Runtime::component_done(ANY_COMPREF)");
7099 // all component.done
7100 expr
->expr
= mputstr(expr
->expr
,
7101 "TTCN_Runtime::component_done(ALL_COMPREF)");
7105 void Statement::generate_code_expr_killed(expression_struct
*expr
)
7107 if (comp_op
.compref
) {
7109 comp_op
.compref
->generate_code_expr_mandatory(expr
);
7110 expr
->expr
= mputstr(expr
->expr
, ".killed()");
7111 } else if (comp_op
.any_or_all
== C_ANY
) {
7112 // any component.killed
7113 expr
->expr
= mputstr(expr
->expr
,
7114 "TTCN_Runtime::component_killed(ANY_COMPREF)");
7116 // all component.killed
7117 expr
->expr
= mputstr(expr
->expr
,
7118 "TTCN_Runtime::component_killed(ALL_COMPREF)");
7122 void Statement::generate_code_expr_timeout(expression_struct
*expr
)
7124 if (timer_op
.timerref
) {
7125 timer_op
.timerref
->generate_code(expr
);
7126 expr
->expr
=mputstr(expr
->expr
, ".timeout()");
7127 } else expr
->expr
= mputstr(expr
->expr
, "TIMER::any_timeout()");
7130 void Statement::generate_code_expr_sendpar(expression_struct
*expr
)
7132 Template
*templ_body
= port_op
.s
.sendpar
->get_Template();
7133 if (!port_op
.s
.sendpar
->get_DerivedRef() &&
7134 templ_body
->get_templatetype() == Template::SPECIFIC_VALUE
) {
7135 // the send parameter is a value: optimization is possible
7136 Value
*t_val
= templ_body
->get_specific_value();
7137 bool cast_needed
= t_val
->explicit_cast_needed();
7139 // the ambiguous C++ expression is converted to the value class
7140 expr
->expr
= mputprintf(expr
->expr
, "%s(",
7141 t_val
->get_my_governor()->get_genname_value(my_sb
).c_str());
7143 t_val
->generate_code_expr_mandatory(expr
);
7144 if (cast_needed
) expr
->expr
= mputc(expr
->expr
, ')');
7146 // the send parameter is a real template: optimization is not possible
7147 port_op
.s
.sendpar
->generate_code(expr
);
7151 void Statement::generate_code_expr_fromclause(expression_struct
*expr
)
7153 if (port_op
.r
.fromclause
) {
7154 // the from clause is present: trivial case
7155 port_op
.r
.fromclause
->generate_code(expr
);
7156 } else if (port_op
.r
.redirect
.sender
) {
7157 // from clause is omitted, but sender redirect is present
7158 Type
*t_var_type
= port_op
.r
.redirect
.sender
->chk_variable_ref();
7160 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
7161 if (t_var_type
->get_type_refd_last()->get_typetype() ==
7162 Type::T_COMPONENT
) {
7163 // the variable can store a component reference
7164 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7166 // the variable can store an address value
7167 expr
->expr
= mputprintf(expr
->expr
, "%s(ANY_VALUE)",
7168 t_var_type
->get_genname_template(my_sb
).c_str());
7171 // neither from clause nor sender redirect is present
7172 // the operation cannot refer to address type
7173 expr
->expr
= mputstr(expr
->expr
, "any_compref");
7177 void Statement::generate_code_expr_senderredirect(expression_struct
*expr
)
7179 if (port_op
.r
.redirect
.sender
) {
7180 expr
->expr
= mputstr(expr
->expr
, "&(");
7181 port_op
.r
.redirect
.sender
->generate_code(expr
);
7182 expr
->expr
= mputc(expr
->expr
, ')');
7183 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
7186 void Statement::generate_code_portref(expression_struct
*expr
,
7189 // make a backup of the current expression
7190 char *expr_backup
= expr
->expr
;
7191 // build the equivalent of p_ref in expr->expr
7192 expr
->expr
= mprintf("\"%s\"", p_ref
->get_id()->get_dispname().c_str());
7193 FieldOrArrayRefs
*t_subrefs
= p_ref
->get_subrefs();
7195 // array indices are present
7196 for (size_t i
= 0; i
< t_subrefs
->get_nof_refs(); i
++) {
7197 FieldOrArrayRef
*t_ref
= t_subrefs
->get_ref(i
);
7198 if (t_ref
->get_type() != FieldOrArrayRef::ARRAY_REF
)
7199 FATAL_ERROR("Statement::generate_code_portref()");
7200 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7201 char *tmp
= expr
->expr
;
7202 expr
->expr
= mcopystr("get_port_name(");
7203 expr
->expr
= mputstr(expr
->expr
, tmp
);
7205 expr
->expr
= mputstr(expr
->expr
, ", ");
7206 t_ref
->get_val()->generate_code_expr(expr
);
7207 expr
->expr
= mputc(expr
->expr
, ')');
7210 // now expr->expr contains the equivalent of p_ref
7211 // append it to the original expression and restore the result
7212 expr_backup
= mputstr(expr_backup
, expr
->expr
);
7214 expr
->expr
= expr_backup
;
7217 void Statement::set_parent_path(WithAttribPath
* p_path
) {
7218 switch (statementtype
) {
7220 def
->set_parent_path(p_path
);
7223 block
->set_parent_path(p_path
);
7226 if_stmt
.ics
->set_parent_path(p_path
);
7227 if (if_stmt
.elseblock
)
7228 if_stmt
.elseblock
->set_parent_path(p_path
);
7231 select
.scs
->set_parent_path(p_path
);
7234 loop
.block
->set_parent_path(p_path
);
7238 loop
.block
->set_parent_path(p_path
);
7249 case S_STOP_TESTCASE
:
7253 case S_UNKNOWN_INSTANCE
:
7254 case S_FUNCTION_INSTANCE
:
7255 case S_ALTSTEP_INSTANCE
:
7266 case S_CHECK_RECEIVE
:
7269 case S_CHECK_GETCALL
:
7271 case S_CHECK_GETREPLY
:
7280 case S_START_COMP_REFD
:
7293 case S_TESTCASE_INSTANCE
:
7294 case S_TESTCASE_INSTANCE_REFD
:
7295 case S_ACTIVATE_REFD
:
7296 case S_UNKNOWN_INVOKED
:
7297 case S_FUNCTION_INVOKED
:
7298 case S_ALTSTEP_INVOKED
:
7300 case S_START_PROFILER
:
7301 case S_STOP_PROFILER
:
7305 FATAL_ERROR("Statement::set_parent_path()");
7309 // =================================
7311 // =================================
7313 Assignment::Assignment(Reference
*p_ref
, Template
*p_templ
)
7314 : asstype(ASS_UNKNOWN
), ref(p_ref
), templ(p_templ
), self_ref(false),
7315 template_restriction(TR_NONE
), gen_restriction_check(false)
7317 if(!ref
|| !templ
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7320 Assignment::Assignment(Reference
*p_ref
, Value
*p_val
)
7321 : asstype(ASS_VAR
), ref(p_ref
), val(p_val
), self_ref(false),
7322 template_restriction(TR_NONE
), gen_restriction_check(false)
7324 if(!ref
|| !val
) FATAL_ERROR("Ttcn::Assignment::Assignment");
7327 Assignment::~Assignment()
7342 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7346 Assignment
*Assignment::clone() const
7348 FATAL_ERROR("Assignment::clone");
7351 void Assignment::set_my_scope(Scope
*p_scope
)
7356 ref
->set_my_scope(p_scope
);
7357 templ
->set_my_scope(p_scope
);
7360 ref
->set_my_scope(p_scope
);
7361 val
->set_my_scope(p_scope
);
7366 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7370 void Assignment::set_fullname(const string
& p_fullname
)
7372 Node::set_fullname(p_fullname
);
7376 ref
->set_fullname(p_fullname
);
7377 templ
->set_fullname(p_fullname
);
7380 ref
->set_fullname(p_fullname
);
7381 val
->set_fullname(p_fullname
);
7386 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7390 void Assignment::dump(unsigned int level
) const
7392 // warning, ref is not always set (e.g. ASS_ERROR)
7400 DEBUG(level
, "*** ERROR ***");
7404 DEBUG(level
, "*** UNKNOWN ***");
7409 templ
->dump(level
+1);
7414 void Assignment::chk_unknown_ass()
7416 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7417 if (!t_ass
) goto error
;
7418 switch (t_ass
->get_asstype()) {
7419 case Common::Assignment::A_ERROR
:
7421 case Common::Assignment::A_PAR_VAL_IN
:
7422 t_ass
->use_as_lvalue(*ref
);
7424 case Common::Assignment::A_VAR
:
7425 case Common::Assignment::A_PAR_VAL_OUT
:
7426 case Common::Assignment::A_PAR_VAL_INOUT
:
7427 if (templ
->is_Value()) {
7428 Value
*t_val
= templ
->get_Value();
7434 templ
->error("A template body with matching symbols cannot be"
7435 " assigned to a variable");
7439 case Common::Assignment::A_PAR_TEMPL_IN
:
7440 t_ass
->use_as_lvalue(*ref
);
7442 case Common::Assignment::A_VAR_TEMPLATE
: {
7443 Type::typetype_t tt
= t_ass
->get_Type()->get_typetype();
7446 case Type::T_BSTR_A
:
7451 case Type::T_UTF8STRING
:
7452 case Type::T_NUMERICSTRING
:
7453 case Type::T_PRINTABLESTRING
:
7454 case Type::T_TELETEXSTRING
:
7455 case Type::T_VIDEOTEXSTRING
:
7456 case Type::T_IA5STRING
:
7457 case Type::T_GRAPHICSTRING
:
7458 case Type::T_VISIBLESTRING
:
7459 case Type::T_GENERALSTRING
:
7460 case Type::T_UNIVERSALSTRING
:
7461 case Type::T_BMPSTRING
:
7462 case Type::T_UTCTIME
:
7463 case Type::T_GENERALIZEDTIME
:
7464 case Type::T_OBJECTDESCRIPTOR
: {
7465 Ttcn::FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7466 if (!subrefs
) break;
7467 size_t nof_subrefs
= subrefs
->get_nof_refs();
7468 if (nof_subrefs
> 0) {
7469 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
7470 ->get_ref(nof_subrefs
- 1);
7471 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
7472 if (!templ
->is_Value()) {
7473 templ
->error("A template body with matching symbols cannot be "
7474 "assigned to an element of a template variable");
7484 case Common::Assignment::A_PAR_TEMPL_OUT
:
7485 case Common::Assignment::A_PAR_TEMPL_INOUT
:
7486 asstype
= ASS_TEMPLATE
;
7490 ref
->error("Reference to a variable or template variable was expected "
7491 "instead of %s", t_ass
->get_description().c_str());
7498 asstype
= ASS_ERROR
;
7502 void Assignment::chk_var_ass()
7504 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7505 Type
*var_type
= lhs
->get_Type();
7506 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7508 var_type
->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7509 if (!type
) goto error
;
7510 val
->set_my_governor(type
);
7511 type
->chk_this_value_ref(val
);
7512 if (val
->get_value_refd_last()->get_valuetype() == Value::V_OMIT
) {
7513 Identifier
*field_id
= 0;
7514 if (subrefs
) field_id
= subrefs
->remove_last_field();
7516 val
->error("Omit value can be assigned to an optional field of "
7517 "a record or set value only");
7520 Type
*base_type
= var_type
7521 ->get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7522 // Putting field_id back to subrefs.
7523 subrefs
->add(new FieldOrArrayRef(field_id
));
7524 base_type
= base_type
->get_type_refd_last();
7525 switch (base_type
->get_typetype()) {
7534 val
->error("Omit value can be assigned to an optional field of "
7535 "a record or set value only");
7538 if (!base_type
->get_comp_byName(*field_id
)->get_is_optional()) {
7539 val
->error("Assignment of `omit' to mandatory field `%s' of type "
7540 "`%s'", field_id
->get_dispname().c_str(),
7541 base_type
->get_typename().c_str());
7545 bool is_string_element
= subrefs
&& subrefs
->refers_to_string_element();
7546 self_ref
|= type
->chk_this_value(val
, lhs
, Type::EXPECTED_DYNAMIC_VALUE
,
7547 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
,
7548 (is_string_element
? NO_SUB_CHK
: SUB_CHK
), NOT_IMPLICIT_OMIT
,
7549 (is_string_element
? IS_STR_ELEM
: NOT_STR_ELEM
));
7550 if (is_string_element
) {
7551 // The length of RHS value shall be 1.
7552 Value
*v_last
= val
->get_value_refd_last();
7553 switch (type
->get_type_refd_last()->get_typetype()) {
7555 case Type::T_BSTR_A
:
7556 if (v_last
->get_valuetype() != Value::V_BSTR
) v_last
= 0;
7559 if (v_last
->get_valuetype() != Value::V_HSTR
) v_last
= 0;
7562 if (v_last
->get_valuetype() != Value::V_OSTR
) v_last
= 0;
7565 case Type::T_NUMERICSTRING
:
7566 case Type::T_PRINTABLESTRING
:
7567 case Type::T_IA5STRING
:
7568 case Type::T_VISIBLESTRING
:
7569 case Type::T_UTCTIME
:
7570 case Type::T_GENERALIZEDTIME
:
7571 if (v_last
->get_valuetype() != Value::V_CSTR
) v_last
= 0;
7574 case Type::T_UTF8STRING
:
7575 case Type::T_TELETEXSTRING
:
7576 case Type::T_VIDEOTEXSTRING
:
7577 case Type::T_GRAPHICSTRING
:
7578 case Type::T_GENERALSTRING
:
7579 case Type::T_UNIVERSALSTRING
:
7580 case Type::T_BMPSTRING
:
7581 case Type::T_OBJECTDESCRIPTOR
:
7582 if (v_last
->get_valuetype() != Value::V_USTR
) v_last
= 0;
7588 size_t string_len
= v_last
->get_val_strlen();
7589 if (string_len
!= 1) {
7590 val
->error("The length of the string to be assigned to a string "
7591 "element of type `%s' should be 1 instead of %lu",
7592 type
->get_typename().c_str(),
7593 (unsigned long)string_len
);
7603 asstype
= ASS_ERROR
;
7607 void Assignment::chk_template_ass()
7609 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
7610 Common::Assignment
*lhs
= ref
->get_refd_assignment();
7611 if (!lhs
) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7612 Type
*type
= lhs
->get_Type()->
7613 get_field_type(subrefs
, Type::EXPECTED_DYNAMIC_VALUE
);
7614 if (!type
) goto error
;
7615 if (lhs
->get_asstype() != Common::Assignment::A_VAR_TEMPLATE
&&
7616 subrefs
&& subrefs
->refers_to_string_element()) {
7617 ref
->error("It is not allowed to index template strings");
7620 templ
->set_my_governor(type
);
7622 templ
->flatten(false);
7624 type
->chk_this_template_ref(templ
);
7625 self_ref
|= type
->chk_this_template_generic(templ
, INCOMPLETE_ALLOWED
,
7626 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, lhs
);
7627 chk_template_restriction();
7632 asstype
= ASS_ERROR
;
7636 void Assignment::chk()
7651 FATAL_ERROR("Ttcn::Assignment::chk()");
7655 void Assignment::set_code_section(
7656 GovernedSimple::code_section_t p_code_section
)
7660 ref
->set_code_section(p_code_section
);
7661 val
->set_code_section(p_code_section
);
7664 ref
->set_code_section(p_code_section
);
7665 templ
->set_code_section(p_code_section
);
7671 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7675 void Assignment::chk_template_restriction()
7677 if (asstype
!=ASS_TEMPLATE
)
7678 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7679 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
7680 if (!t_ass
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7681 switch (t_ass
->get_asstype()) {
7682 case Common::Assignment::A_VAR_TEMPLATE
: {
7683 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(t_ass
);
7684 if (!dvt
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7685 template_restriction
= dvt
->get_template_restriction();
7687 case Common::Assignment::A_PAR_TEMPL_IN
:
7688 case Common::Assignment::A_PAR_TEMPL_OUT
:
7689 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
7690 FormalPar
* fp
= dynamic_cast<FormalPar
*>(t_ass
);
7691 if (!fp
) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7692 template_restriction
= fp
->get_template_restriction();
7695 template_restriction
= TR_NONE
;
7697 // transform the restriction if this is a subfield
7698 template_restriction
= Template::get_sub_restriction(template_restriction
, ref
);
7699 // check the template restriction
7700 gen_restriction_check
=
7701 templ
->chk_restriction("template", template_restriction
, this);
7704 char *Assignment::generate_code(char *str
)
7706 // check if the LHS reference is a parameter, mark it as used if it is
7707 ref
->refd_param_usage_found();
7708 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
7709 const bool rhs_copied
= self_ref
;
7712 const string
& rhs_copy
= val
->get_temporary_id();
7713 string rhs_ref
= rhs_copy
;
7714 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7715 if (val
->get_my_governor()->is_optional_field()) {
7716 str
= mputprintf(str
, "{\nOPTIONAL<%s> %s;\n",
7717 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7720 str
= mputprintf(str
, "{\n%s %s;\n",
7721 val
->get_my_governor()->get_genname_value(val
->get_my_scope()).c_str(), rhs_copy
.c_str());
7724 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(val
);
7727 // Most complicated case. The LHS is saved in a temporary reference,
7728 // in case we need to access it more than once, e.g:
7729 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7730 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7731 // This saves having to index x2 more than once.
7732 const string
& tmp_id
= val
->get_temporary_id(); // For "ref".
7733 const char *tmp_id_str
= tmp_id
.c_str();
7734 const string
& type_genname
=
7735 val
->get_my_governor()->get_genname_value(val
->get_my_scope());
7736 const char *type_genname_str
= type_genname
.c_str();
7737 expression_struct expr
;
7738 Code::init_expr(&expr
);
7739 ref
->generate_code(&expr
);
7743 str
= TypeConv::gen_conv_code_refd(str
, rhs_ref
.c_str(), val
);
7744 else str
= val
->generate_code_init(str
, rhs_ref
.c_str());
7747 str
= mputstr(str
, "{\n");
7748 str
= mputstr(str
, expr
.preamble
);
7749 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
7750 // The LHS is a string element.
7751 str
= mputprintf(str
, "%s_ELEMENT %s(%s);\n", type_genname_str
,
7752 tmp_id_str
, expr
.expr
);
7754 // The LHS is a normal value.
7755 str
= mputprintf(str
, "%s& %s = %s; /* 7388 */\n", type_genname_str
,
7756 tmp_id_str
, expr
.expr
);
7758 str
= mputstr(str
, expr
.postamble
);
7759 // We now have a reference to the LHS. Generate the actual assignment
7761 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7765 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, val
);
7766 else str
= val
->generate_code_init(str
, tmp_id_str
);
7768 Code::free_expr(&expr
);
7769 str
= mputstr(str
, "}\n");
7773 if (!val
->has_single_expr()) goto case3
;
7774 // C++ equivalent of RHS is a single expression.
7775 expression_struct expr
;
7776 Code::init_expr(&expr
);
7777 ref
->generate_code(&expr
);// vu.s()
7779 str
= mputprintf(str
, "%s = %s;\n",
7780 rhs_copy
.c_str(), val
->get_single_expr().c_str());
7782 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7785 expr
.expr
= mputprintf(expr
.expr
,
7786 " = %s", val
->get_single_expr().c_str());
7788 str
= Code::merge_free_expr(str
, &expr
);
7791 // The LHS is a single identifier.
7792 const string
& rhs_name
= ref
->get_refd_assignment()
7793 ->get_genname_from_scope(ref
->get_my_scope());
7794 if (val
->can_use_increment(ref
)) {
7795 switch (val
->get_optype()) {
7796 case Value::OPTYPE_ADD
:
7797 str
= mputprintf(str
, "++%s;\n", rhs_name
.c_str());
7799 case Value::OPTYPE_SUBTRACT
:
7800 str
= mputprintf(str
, "--%s;\n", rhs_name
.c_str());
7803 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7806 str
= val
->generate_code_init(str
,
7807 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7810 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7816 str
= mputstr(str
, "}\n");
7819 case ASS_TEMPLATE
: {
7820 const string
& rhs_copy
= templ
->get_temporary_id();
7821 if (rhs_copied
/*&& val->get_valuetype() == Value::V_CHOICE*/) {
7822 str
= mputprintf(str
, "{\n%s %s;\n",
7823 templ
->get_my_governor()->get_genname_template(templ
->get_my_scope()).c_str(), rhs_copy
.c_str()//, rhs_copy.c_str()
7826 bool needs_conv
= use_runtime_2
&& TypeConv::needs_conv_refd(templ
);
7827 if (needs_conv
) { // case 3
7829 // Most complicated case. The LHS is saved in a temporary reference.
7830 const string
& tmp_id
= templ
->get_temporary_id();
7831 const char *tmp_id_str
= tmp_id
.c_str();
7832 expression_struct expr
;
7833 Code::init_expr(&expr
);
7834 ref
->generate_code(&expr
);
7838 str
= TypeConv::gen_conv_code_refd(str
, rhs_copy
.c_str(), templ
);
7839 else str
= templ
->generate_code_init(str
, rhs_copy
.c_str());
7842 str
= mputstr(str
, "{\n");
7843 str
= mputstr(str
, expr
.preamble
);
7844 str
= mputprintf(str
, "%s& %s = %s;\n",
7845 templ
->get_my_governor()->get_genname_template(
7846 templ
->get_my_scope()
7847 ).c_str(), tmp_id_str
, expr
.expr
);
7848 str
= mputstr(str
, expr
.postamble
);
7850 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, rhs_copy
.c_str());
7854 str
= TypeConv::gen_conv_code_refd(str
, tmp_id_str
, templ
);
7856 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7857 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7858 str
= mputprintf(str
, "%s.remove_all_permutations();\n", tmp_id_str
);
7860 str
= templ
->generate_code_init(str
, tmp_id_str
);
7863 Code::free_expr(&expr
);
7865 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7866 str
= Template::generate_restriction_check_code(str
,
7867 tmp_id_str
, template_restriction
);
7868 str
= mputstr(str
, "}\n");
7870 else { // !needs_conv
7872 if ((template_restriction
== TR_NONE
|| !gen_restriction_check
)
7873 && templ
->has_single_expr()) {
7874 // C++ equivalent of RHS is a single expression and no restriction
7875 // check. Skipped if conversion needed.
7876 expression_struct expr
;
7877 Code::init_expr(&expr
);
7878 ref
->generate_code(&expr
);
7880 str
= mputprintf(str
, "%s = %s;\n",
7881 rhs_copy
.c_str(), templ
->get_single_expr(false).c_str());
7883 expr
.expr
= mputprintf(expr
.expr
, " = %s", rhs_copy
.c_str());
7886 expr
.expr
= mputprintf(expr
.expr
,
7887 " = %s", templ
->get_single_expr(false).c_str());
7889 str
= Code::merge_free_expr(str
, &expr
); // will add a semicolon
7894 // LHS is a single identifier
7895 const string
& rhs_name
= ref
->get_refd_assignment()
7896 ->get_genname_from_scope(ref
->get_my_scope());
7897 if (Common::Type::T_SEQOF
== templ
->get_my_governor()->get_typetype() ||
7898 Common::Type::T_ARRAY
== templ
->get_my_governor()->get_typetype()) {
7899 str
= mputprintf(str
, "%s.remove_all_permutations();\n", (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7901 str
= templ
->generate_code_init(str
,
7902 (rhs_copied
? rhs_copy
: rhs_name
).c_str());
7904 str
= mputprintf(str
, "%s = %s;\n", rhs_name
.c_str(), rhs_copy
.c_str());
7906 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
7907 str
= Template::generate_restriction_check_code(str
,
7908 ref
->get_refd_assignment()->get_genname_from_scope(
7910 ).c_str(), template_restriction
);
7914 str
= mputstr(str
, "}\n");
7918 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7923 // =================================
7924 // ===== ParamAssignment
7925 // =================================
7927 ParamAssignment::ParamAssignment(Identifier
*p_id
, Reference
*p_ref
)
7928 : Node(), Location(), id(p_id
), ref(p_ref
)
7930 if(!id
|| !ref
) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7933 ParamAssignment::~ParamAssignment()
7939 ParamAssignment
*ParamAssignment::clone() const
7941 FATAL_ERROR("ParamAssignment::clone");
7944 void ParamAssignment::set_my_scope(Scope
*p_scope
)
7946 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7947 ref
->set_my_scope(p_scope
);
7950 void ParamAssignment::set_fullname(const string
& p_fullname
)
7952 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7953 ref
->set_fullname(p_fullname
);
7956 Reference
*ParamAssignment::get_ref() const
7958 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7962 Reference
*ParamAssignment::steal_ref()
7964 if (!ref
) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7965 Reference
*ret_val
= ref
;
7970 // =================================
7971 // ===== ParamAssignments
7972 // =================================
7974 ParamAssignments::~ParamAssignments()
7976 for(size_t i
=0; i
<parasss
.size(); i
++)
7981 ParamAssignments
*ParamAssignments::clone() const
7983 FATAL_ERROR("ParamAssignments::clone");
7986 void ParamAssignments::set_my_scope(Scope
*p_scope
)
7988 for(size_t i
=0; i
<parasss
.size(); i
++)
7989 parasss
[i
]->set_my_scope(p_scope
);
7992 void ParamAssignments::set_fullname(const string
& p_fullname
)
7994 Node::set_fullname(p_fullname
);
7995 for(size_t i
=0; i
<parasss
.size(); i
++)
7996 parasss
[i
]->set_fullname(p_fullname
+".parass_"+Int2string(i
+1));
7999 void ParamAssignments::add_parass(ParamAssignment
*p_parass
)
8002 FATAL_ERROR("ParamAssignments::add_parass()");
8003 parasss
.add(p_parass
);
8006 // =================================
8007 // ===== VariableEntry
8008 // =================================
8010 VariableEntry::VariableEntry(Reference
*p_ref
)
8011 : Node(), Location(), ref(p_ref
)
8013 if(!ref
) FATAL_ERROR("VariableEntry::VariableEntry()");
8016 VariableEntry::~VariableEntry()
8021 VariableEntry
*VariableEntry::clone() const
8023 FATAL_ERROR("VariableEntry::clone");
8026 void VariableEntry::set_my_scope(Scope
*p_scope
)
8028 if(ref
) ref
->set_my_scope(p_scope
);
8031 void VariableEntry::set_fullname(const string
& p_fullname
)
8033 Node::set_fullname(p_fullname
);
8034 if(ref
) ref
->set_fullname(p_fullname
+".ref");
8037 // =================================
8038 // ===== VariableEntries
8039 // =================================
8041 VariableEntries::~VariableEntries()
8043 for(size_t i
=0; i
<ves
.size(); i
++)
8048 VariableEntries
*VariableEntries::clone() const
8050 FATAL_ERROR("VariableEntries::clone");
8053 void VariableEntries::set_my_scope(Scope
*p_scope
)
8055 for(size_t i
=0; i
<ves
.size(); i
++)
8056 ves
[i
]->set_my_scope(p_scope
);
8059 void VariableEntries::set_fullname(const string
& p_fullname
)
8061 Node::set_fullname(p_fullname
);
8062 for(size_t i
=0; i
<ves
.size(); i
++)
8063 ves
[i
]->set_fullname(p_fullname
+".ve_"+Int2string(i
+1));
8066 void VariableEntries::add_ve(VariableEntry
*p_ve
)
8069 FATAL_ERROR("VariableEntries::add_ve()");
8073 // =================================
8074 // ===== ParamRedirect
8075 // =================================
8077 ParamRedirect::ParamRedirect(ParamAssignments
*p_parasss
)
8078 : Node(), Location(), parredirtype(P_ASS
), parasss(p_parasss
)
8080 if(!parasss
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8083 ParamRedirect::ParamRedirect(VariableEntries
*p_ves
)
8084 : Node(), Location(), parredirtype(P_VAR
), ves(p_ves
)
8086 if(!ves
) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8089 ParamRedirect::~ParamRedirect()
8091 switch(parredirtype
) {
8099 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
8103 ParamRedirect
*ParamRedirect::clone() const
8105 FATAL_ERROR("ParamRedirect::clone");
8108 void ParamRedirect::set_my_scope(Scope
*p_scope
)
8110 switch(parredirtype
) {
8112 parasss
->set_my_scope(p_scope
);
8115 ves
->set_my_scope(p_scope
);
8118 FATAL_ERROR("ParamRedirect::set_my_scope()");
8122 void ParamRedirect::set_fullname(const string
& p_fullname
)
8124 Node::set_fullname(p_fullname
);
8125 switch(parredirtype
) {
8127 parasss
->set_fullname(p_fullname
+".parasss");
8130 ves
->set_fullname(p_fullname
+".parvars");
8133 FATAL_ERROR("ParamRedirect::set_fullname()");
8137 void ParamRedirect::chk_erroneous()
8139 Error_Context
cntxt(this, "In parameter redirect");
8140 switch(parredirtype
) {
8142 map
<string
, ParamAssignment
> parass_m
;
8143 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8144 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8145 const Identifier
&t_id
= t_parass
->get_id();
8146 const string
& name
= t_id
.get_name();
8147 const char *dispname_str
= t_id
.get_dispname().c_str();
8148 if (parass_m
.has_key(name
)) {
8149 t_parass
->error("Duplicate redirect for parameter `%s'",
8151 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8152 "already given here", dispname_str
);
8153 } else parass_m
.add(name
, t_parass
);
8154 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8156 chk_variable_ref(t_parass
->get_ref(), 0);
8161 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8162 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8163 Error_Context
cntxt2(t_ve
, "In variable entry #%lu",
8164 (unsigned long) (i
+ 1));
8165 chk_variable_ref(t_ve
->get_ref(), 0);
8169 FATAL_ERROR("ParamRedirect::chk_erroneous()");
8173 void ParamRedirect::chk(Type
*p_sig
, bool is_out
)
8175 SignatureParamList
*t_parlist
= p_sig
->get_signature_parameters();
8177 Error_Context
cntxt(this, "In parameter redirect");
8178 switch (parredirtype
) {
8180 chk_parasss(p_sig
, t_parlist
, is_out
);
8183 chk_ves(p_sig
, t_parlist
, is_out
);
8186 FATAL_ERROR("ParamRedirect::chk()");
8189 error("Parameter redirect cannot be used because signature `%s' "
8190 "does not have parameters", p_sig
->get_typename().c_str());
8195 void ParamRedirect::chk_parasss(Type
*p_sig
, SignatureParamList
*p_parlist
,
8198 map
<string
, ParamAssignment
> parass_m
;
8199 bool error_flag
= false;
8200 for (size_t i
= 0; i
< parasss
->get_nof_parasss(); i
++) {
8201 ParamAssignment
*t_parass
= parasss
->get_parass_byIndex(i
);
8202 const Identifier
&t_id
= t_parass
->get_id();
8203 const string
& name
= t_id
.get_name();
8204 const char *dispname_str
= t_id
.get_dispname().c_str();
8205 if (parass_m
.has_key(name
)) {
8206 t_parass
->error("Duplicate redirect for parameter `%s'",
8208 parass_m
[name
]->note("A variable entry for parameter `%s' is "
8209 "already given here", dispname_str
);
8211 } else parass_m
.add(name
, t_parass
);
8212 Error_Context
cntxt2(t_parass
, "In redirect for parameter `%s'",
8214 if (p_parlist
->has_param_withName(t_id
)) {
8215 const SignatureParam
*t_par
= p_parlist
->get_param_byName(t_id
);
8216 SignatureParam::param_direction_t t_dir
= t_par
->get_direction();
8218 if (t_dir
== SignatureParam::PARAM_IN
) {
8219 t_parass
->error("Parameter `%s' of signature `%s' has `in' "
8220 "direction", dispname_str
, p_sig
->get_typename().c_str());
8224 if (t_dir
== SignatureParam::PARAM_OUT
) {
8225 t_parass
->error("Parameter `%s' of signature `%s' has `out' "
8226 "direction", dispname_str
, p_sig
->get_typename().c_str());
8230 chk_variable_ref(t_parass
->get_ref(), t_par
->get_type());
8232 t_parass
->error("Signature `%s' does not have parameter named `%s'",
8233 p_sig
->get_typename().c_str(), dispname_str
);
8235 chk_variable_ref(t_parass
->get_ref(), 0);
8239 // converting the AssignmentList to VariableList
8240 VariableEntries
*t_ves
= new VariableEntries
;
8241 size_t upper_limit
= is_out
?
8242 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8243 for (size_t i
= 0; i
< upper_limit
; i
++) {
8244 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8245 : p_parlist
->get_in_param_byIndex(i
);
8246 const string
& name
= t_par
->get_id().get_name();
8247 if (parass_m
.has_key(name
))
8248 t_ves
->add_ve(new VariableEntry(parass_m
[name
]->steal_ref()));
8249 else t_ves
->add_ve(new VariableEntry
);
8253 parredirtype
= P_VAR
;
8258 void ParamRedirect::chk_ves(Type
*p_sig
, SignatureParamList
*p_parlist
,
8261 size_t nof_ves
= ves
->get_nof_ves();
8262 size_t nof_pars
= is_out
?
8263 p_parlist
->get_nof_out_params() : p_parlist
->get_nof_in_params();
8264 if (nof_ves
!= nof_pars
) {
8265 error("Too %s variable entries compared to the number of %s/inout "
8266 "parameters in signature `%s': %lu was expected instead of %lu",
8267 nof_ves
> nof_pars
? "many" : "few", is_out
? "out" : "in",
8268 p_sig
->get_typename().c_str(), (unsigned long) nof_pars
,
8269 (unsigned long) nof_ves
);
8271 for (size_t i
= 0; i
< nof_ves
; i
++) {
8272 VariableEntry
*t_ve
= ves
->get_ve_byIndex(i
);
8274 SignatureParam
*t_par
= is_out
? p_parlist
->get_out_param_byIndex(i
)
8275 : p_parlist
->get_in_param_byIndex(i
);
8276 Error_Context
cntxt(t_ve
, "In variable entry #%lu (for parameter `%s')",
8277 (unsigned long) (i
+ 1), t_par
->get_id().get_dispname().c_str());
8278 chk_variable_ref(t_ve
->get_ref(), t_par
->get_type());
8280 Error_Context
cntxt(t_ve
, "In variable entry #%lu",
8281 (unsigned long) (i
+ 1));
8282 chk_variable_ref(t_ve
->get_ref(), 0);
8287 void ParamRedirect::chk_variable_ref(Reference
*p_ref
, Type
*p_type
)
8290 Type
*t_var_type
= p_ref
->chk_variable_ref();
8291 if (p_type
&& t_var_type
&& !p_type
->is_identical(t_var_type
)) {
8292 p_ref
->error("Type mismatch in parameter redirect: "
8293 "A variable of type `%s' was expected instead of `%s'",
8294 p_type
->get_typename().c_str(),
8295 t_var_type
->get_typename().c_str());
8299 void ParamRedirect::set_code_section(
8300 GovernedSimple::code_section_t p_code_section
)
8302 // code can be generated from VariableList only
8303 switch (parredirtype
) {
8307 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8308 Reference
*t_ref
= ves
->get_ve_byIndex(i
)->get_ref();
8309 if (t_ref
) t_ref
->set_code_section(p_code_section
);
8313 FATAL_ERROR("ParamRedirect::set_code_section()");
8317 void ParamRedirect::generate_code(expression_struct_t
*expr
)
8319 // AssignmentList is converted to VariableList during checking
8320 if (parredirtype
!= P_VAR
) FATAL_ERROR("ParamRedirect::generate_code()");
8321 for (size_t i
= 0; i
< ves
->get_nof_ves(); i
++) {
8322 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
8323 Reference
*ref
= ves
->get_ve_byIndex(i
)->get_ref();
8325 // the variable reference is present
8326 expr
->expr
= mputstr(expr
->expr
, "&(");
8327 ref
->generate_code(expr
);
8328 expr
->expr
= mputc(expr
->expr
, ')');
8329 } else expr
->expr
= mputstr(expr
->expr
, "NULL");
8333 // =================================
8334 // ===== LogArgument
8335 // =================================
8337 LogArgument::LogArgument(TemplateInstance
*p_ti
)
8338 : logargtype(L_UNDEF
)
8340 if (!p_ti
) FATAL_ERROR("LogArgument::LogArgument()");
8344 LogArgument::~LogArgument()
8346 switch (logargtype
) {
8365 FATAL_ERROR("LogArgument::~LogArgument()");
8369 LogArgument
*LogArgument::clone() const
8371 FATAL_ERROR("LogArgument::clone");
8374 void LogArgument::set_my_scope(Scope
*p_scope
)
8376 switch (logargtype
) {
8381 ti
->set_my_scope(p_scope
);
8386 val
->set_my_scope(p_scope
);
8389 ref
->set_my_scope(p_scope
);
8394 FATAL_ERROR("LogArgument::set_my_scope()");
8398 void LogArgument::set_fullname(const string
& p_fullname
)
8400 Node::set_fullname(p_fullname
);
8401 switch (logargtype
) {
8406 ti
->set_fullname(p_fullname
);
8411 val
->set_fullname(p_fullname
);
8414 ref
->set_fullname(p_fullname
);
8419 FATAL_ERROR("LogArgument::set_fullname()");
8423 const string
& LogArgument::get_str() const
8425 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::get_str()");
8429 Value
*LogArgument::get_val() const
8431 switch (logargtype
) {
8437 FATAL_ERROR("LogArgument::get_val()");
8442 Ref_base
*LogArgument::get_ref() const
8444 if (logargtype
!= L_REF
) FATAL_ERROR("LogArgument::get_ref()");
8448 TemplateInstance
*LogArgument::get_ti() const
8450 if (logargtype
!= L_TI
) FATAL_ERROR("LogArgument::get_ref()");
8454 void LogArgument::append_str(const string
& p_str
)
8456 if (logargtype
!= L_STR
) FATAL_ERROR("LogArgument::append_str()");
8460 void LogArgument::chk() // determine the proper type of the log argument
8462 if (logargtype
!= L_UNDEF
) return;
8463 Template
*t_templ
= ti
->get_Template();
8464 t_templ
= t_templ
->get_template_refd_last();
8465 t_templ
->set_lowerid_to_ref();
8466 if (!ti
->get_Type() && !ti
->get_DerivedRef() && t_templ
->is_Value()) {
8467 // drop the template instance and keep only the embedded value
8468 Value
*t_val
= t_templ
->get_Value();
8474 // try to obtain the governor of the template instance
8475 Type
*governor
= ti
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8477 // the governor is still unknown: an error occurred
8478 // try to interpret possible enum values as references
8479 t_templ
->set_lowerid_to_ref();
8480 governor
= t_templ
->get_expr_governor(Type::EXPECTED_TEMPLATE
);
8486 t_templ
->error("Cannot determine the type of the argument");
8488 logargtype
= L_ERROR
;
8493 void LogArgument::chk_ref()
8495 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
8497 Common::Assignment::asstype_t asstype
= t_ass
->get_asstype();
8499 case Common::Assignment::A_FUNCTION_RVAL
:
8500 case Common::Assignment::A_FUNCTION_RTEMP
:
8501 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
8502 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
8503 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *this, "call");
8504 case Common::Assignment::A_CONST
:
8505 case Common::Assignment::A_EXT_CONST
:
8506 case Common::Assignment::A_MODULEPAR
:
8507 case Common::Assignment::A_MODULEPAR_TEMP
:
8508 case Common::Assignment::A_TEMPLATE
:
8509 case Common::Assignment::A_VAR
:
8510 case Common::Assignment::A_VAR_TEMPLATE
:
8511 case Common::Assignment::A_PAR_VAL_IN
:
8512 case Common::Assignment::A_PAR_VAL_OUT
:
8513 case Common::Assignment::A_PAR_VAL_INOUT
:
8514 case Common::Assignment::A_PAR_TEMPL_IN
:
8515 case Common::Assignment::A_PAR_TEMPL_OUT
:
8516 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
8517 // the reference points to a value or template-like entity
8518 // checking sub-references
8519 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
8520 if (subrefs
&& t_ass
->get_Type()->get_field_type(subrefs
,
8521 Type::EXPECTED_DYNAMIC_VALUE
)) {
8522 // subrefs seems to be correct
8523 // also checking the presence of referred fields if possible
8524 if (asstype
== Common::Assignment::A_CONST
) {
8525 ReferenceChain
refch(ref
, "While searching referenced value");
8526 t_ass
->get_Value()->get_refd_sub_value(subrefs
, 0, false, &refch
);
8527 } else if (asstype
== Common::Assignment::A_TEMPLATE
) {
8528 ReferenceChain
refch(ref
, "While searching referenced template");
8529 t_ass
->get_Template()
8530 ->get_refd_sub_template(subrefs
, false, &refch
);
8534 case Common::Assignment::A_TIMER
:
8535 case Common::Assignment::A_PORT
: {
8536 ArrayDimensions
*t_dims
= t_ass
->get_Dimensions();
8537 if (t_dims
) t_dims
->chk_indices(ref
, t_ass
->get_assname(), true,
8538 Type::EXPECTED_DYNAMIC_VALUE
);
8539 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8540 "cannot have field or array sub-references",
8541 t_ass
->get_description().c_str());
8543 case Common::Assignment::A_PAR_TIMER
:
8544 case Common::Assignment::A_PAR_PORT
:
8545 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8546 "field or array sub-references", t_ass
->get_description().c_str());
8548 case Common::Assignment::A_FUNCTION
:
8549 case Common::Assignment::A_EXT_FUNCTION
:
8550 ref
->error("Reference to a value, template, timer or port was expected "
8551 "instead of a call of %s, which does not have return type",
8552 t_ass
->get_description().c_str());
8555 ref
->error("Reference to a value, template, timer or port was expected "
8556 "instead of %s", t_ass
->get_description().c_str());
8560 void LogArgument::chk_val()
8562 // literal enumerated values cannot appear in this context
8563 val
->set_lowerid_to_ref();
8564 switch (val
->get_valuetype()) {
8565 case Value::V_CSTR
: {
8566 string
*t_cstr
= new string(val
->get_val_str());
8571 case Value::V_REFD
: {
8572 Ref_base
*t_ref
= val
->steal_ttcn_ref_base();
8579 if (val
->get_optype() == Value::OPTYPE_MATCH
) logargtype
= L_MATCH
;
8580 else logargtype
= L_VAL
;
8582 case Value::V_MACRO
:
8583 logargtype
= L_MACRO
;
8588 Type
*governor
= val
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
8590 val
->set_my_governor(governor
);
8591 (void)governor
->chk_this_value(val
, 0, Type::EXPECTED_DYNAMIC_VALUE
,
8592 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
8593 if (logargtype
== L_VAL
&& val
->get_valuetype() == Value::V_CSTR
8594 && !val
->is_unfoldable()) { // string value known at compile time
8595 string
*t_cstr
= new string(val
->get_val_str());
8601 if (logargtype
== L_MACRO
) {
8602 switch (val
->get_valuetype()) {
8603 case Value::V_CSTR
: {
8604 // the macro was evaluated to a charstring value
8605 string
*t_cstr
= new string(val
->get_val_str());
8610 case Value::V_MACRO
:
8611 // the macro could not be evaluated at compile time
8612 // leave logargtype as is
8615 // the macro was evaluated to other value (e.g. integer)
8620 val
->error("Cannot determine the type of the argument");
8622 logargtype
= L_ERROR
;
8626 void LogArgument::dump(unsigned int level
) const
8628 Node::dump(level
++);
8629 switch (logargtype
) {
8631 DEBUG(level
, "*error*");
8634 DEBUG(level
, "*undef*");
8637 DEBUG(level
, "TemplateInstance");
8643 DEBUG(level
, "Match");
8646 DEBUG(level
, "Macro");
8649 DEBUG(level
, "Reference");
8652 DEBUG(level
, "String=`%s'", cstr
->c_str());
8655 FATAL_ERROR("LogArgument::~LogArgument()");
8659 void LogArgument::set_code_section(
8660 GovernedSimple::code_section_t p_code_section
)
8662 switch (logargtype
) {
8665 ti
->set_code_section(p_code_section
);
8670 val
->set_code_section(p_code_section
);
8673 ref
->set_code_section(p_code_section
);
8679 FATAL_ERROR("LogArgument::set_code_section()");
8683 char *LogArgument::generate_code_log(char *str
)
8685 expression_struct expr
;
8686 Code::init_expr(&expr
);
8687 generate_code_expr(&expr
);
8688 str
= Code::merge_free_expr(str
, &expr
);
8692 void LogArgument::chk_recursions(ReferenceChain
& refch
)
8694 switch (logargtype
) {
8697 ti
->chk_recursions(refch
);
8702 val
->chk_recursions(refch
);
8705 Common::Assignment
*ass
= ref
->get_refd_assignment();
8707 refch
.add(ass
->get_fullname());
8713 FATAL_ERROR("LogArgument::chk_recursions()");
8717 bool LogArgument::has_single_expr()
8719 switch (logargtype
) {
8722 return ti
->has_single_expr();
8726 return ( val
->has_single_expr() && !val
->explicit_cast_needed() );
8728 Common::Assignment
*ass
= ref
->get_refd_assignment();
8729 switch (ass
->get_asstype()) {
8730 case Common::Assignment::A_CONST
:
8731 case Common::Assignment::A_EXT_CONST
:
8732 return ref
->has_single_expr();
8741 FATAL_ERROR("LogArgument::has_single_expr()");
8746 void LogArgument::generate_code_expr(expression_struct
*expr
)
8748 switch(logargtype
) {
8750 if (ti
->is_only_specific_value()) {
8751 // use the embedded specific value for code generation
8752 ti
->get_Template()->get_specific_value()->generate_code_log(expr
);
8754 ti
->generate_code(expr
);
8755 expr
->expr
= mputstr(expr
->expr
, ".log()");
8759 val
->generate_code_log(expr
);
8762 val
->generate_code_log_match(expr
);
8765 if (val
->has_single_expr()) {
8766 expr
->expr
= mputprintf(expr
->expr
, "TTCN_Logger::log_event_str(%s)",
8767 val
->get_single_expr().c_str());
8768 } else val
->generate_code_log(expr
);
8771 ref
->generate_code_const_ref(expr
);
8772 expr
->expr
=mputstr(expr
->expr
, ".log()");
8775 size_t str_len
= cstr
->size();
8776 const char *str_ptr
= cstr
->c_str();
8779 // the string is empty: do not generate any code
8781 // the string has one character: use log_char member
8782 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_char('");
8783 expr
->expr
= Code::translate_character(expr
->expr
, *str_ptr
, false);
8784 expr
->expr
= mputstr(expr
->expr
, "')");
8787 // the string has more characters: use log_event_str member
8788 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::log_event_str(\"");
8789 expr
->expr
= Code::translate_string(expr
->expr
, str_ptr
);
8790 expr
->expr
= mputstr(expr
->expr
, "\")");
8794 FATAL_ERROR("LogArgument::generate_code_expr()");
8798 // =================================
8799 // ===== LogArguments
8800 // =================================
8802 LogArguments::~LogArguments()
8804 for(size_t i
=0; i
<logargs
.size(); i
++) delete logargs
[i
];
8808 LogArguments
*LogArguments::clone() const
8810 FATAL_ERROR("LogArguments::clone");
8813 void LogArguments::add_logarg(LogArgument
*p_logarg
)
8816 FATAL_ERROR("LogArguments::add_logarg()");
8817 logargs
.add(p_logarg
);
8820 void LogArguments::set_my_scope(Scope
*p_scope
)
8822 for(size_t i
=0; i
<logargs
.size(); i
++)
8823 logargs
[i
]->set_my_scope(p_scope
);
8826 void LogArguments::set_fullname(const string
& p_fullname
)
8828 Node::set_fullname(p_fullname
);
8829 for(size_t i
=0; i
<logargs
.size(); i
++)
8830 logargs
[i
]->set_fullname(p_fullname
+".logargs_"+Int2string(i
+1));
8833 void LogArguments::chk()
8835 for(size_t i
=0; i
<logargs
.size(); i
++)
8839 void LogArguments::join_strings()
8841 // points to the previous string argument otherwise it is NULL
8842 LogArgument
*prev_arg
= 0;
8843 for (size_t i
= 0; i
< logargs
.size(); ) {
8844 LogArgument
*arg
= logargs
[i
];
8845 if (arg
->get_type() == LogArgument::L_STR
) {
8846 const string
& str
= arg
->get_str();
8847 if (str
.size() > 0) {
8848 // the current argument is a non-empty string
8850 // append str to prev_arg and drop arg
8851 prev_arg
->append_str(str
);
8853 logargs
.replace(i
, 1);
8854 // don't increment i
8856 // keep it for the next iteration
8861 // the current argument is an empty string
8862 // simply drop it unless it is the only argument
8863 // note: we must distinguish between log() and log("")
8864 if (i
> 0 || logargs
.size() > 1) {
8866 logargs
.replace(i
, 1);
8867 // don't increment i
8871 // the current argument is not a string
8872 // forget the previous arg
8879 void LogArguments::set_code_section(
8880 GovernedSimple::code_section_t p_code_section
)
8882 for (size_t i
= 0; i
< logargs
.size(); i
++)
8883 logargs
[i
]->set_code_section(p_code_section
);
8886 char *LogArguments::generate_code(char *str
)
8888 for(size_t i
=0; i
<logargs
.size(); i
++)
8889 str
=logargs
[i
]->generate_code_log(str
);
8893 void LogArguments::chk_recursions(ReferenceChain
& refch
)
8895 for (size_t i
=0; i
<logargs
.size(); i
++) {
8897 logargs
[i
]->chk_recursions(refch
);
8902 bool LogArguments::has_single_expr()
8904 bool i_have_single_expr
= true;
8905 for (size_t i
=0; i
<logargs
.size(); i
++)
8906 i_have_single_expr
= i_have_single_expr
&& logargs
[i
]->has_single_expr();
8907 return i_have_single_expr
;
8910 void LogArguments::generate_code_expr(expression_struct
*expr
)
8912 expr
->expr
= mputstr(expr
->expr
, "(TTCN_Logger::begin_event_log2str(),");
8913 for(size_t i
=0; i
<logargs
.size(); i
++) {
8914 logargs
[i
]->generate_code_expr(expr
);
8915 expr
->expr
= mputc(expr
->expr
, ','); // comma operator
8917 expr
->expr
= mputstr(expr
->expr
, "TTCN_Logger::end_event_log2str())");
8920 // =================================
8922 // =================================
8924 IfClause::IfClause(Value
*p_expr
, StatementBlock
*p_block
)
8925 : expr(p_expr
), block(p_block
)
8928 FATAL_ERROR("IfClause::IfClause()");
8931 IfClause::~IfClause()
8937 IfClause
*IfClause::clone() const
8939 FATAL_ERROR("IfClause::clone");
8942 void IfClause::set_my_scope(Scope
*p_scope
)
8944 expr
->set_my_scope(p_scope
);
8945 block
->set_my_scope(p_scope
);
8948 void IfClause::set_fullname(const string
& p_fullname
)
8950 Node::set_fullname(p_fullname
);
8951 expr
->set_fullname(p_fullname
+".expr");
8952 block
->set_fullname(p_fullname
+".block");
8955 bool IfClause::has_receiving_stmt() const
8957 return block
->has_receiving_stmt();
8960 void IfClause::chk(bool& unreach
)
8962 Error_Context
cntxt(this, "In if statement");
8963 if(unreach
) warning("Control never reaches this code because of"
8964 " previous effective condition(s)");
8965 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
8966 if(!expr
->is_unfoldable()) {
8967 if(expr
->get_val_bool()) unreach
=true;
8968 else block
->warning("Control never reaches this code because the"
8969 " conditional expression evaluates to false");
8974 void IfClause::set_code_section(
8975 GovernedSimple::code_section_t p_code_section
)
8977 expr
->set_code_section(p_code_section
);
8978 block
->set_code_section(p_code_section
);
8981 char* IfClause::generate_code(char *str
, size_t& blockcount
,
8982 bool& unreach
, bool& eachfalse
)
8984 if(unreach
) return str
;
8985 if(!expr
->is_unfoldable()) {
8986 if(expr
->get_val_bool()) unreach
=true;
8989 if (!eachfalse
) str
= mputstr(str
, "else ");
8992 str
= mputstr(str
, "{\n");
8995 str
= expr
->update_location_object(str
);
8996 str
= expr
->generate_code_tmp(str
, "if (", blockcount
);
8997 str
= mputstr(str
, ") ");
9000 str
=mputstr(str
, "{\n");
9001 if (debugger_active
) {
9002 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
9004 str
=block
->generate_code(str
);
9005 str
=mputstr(str
, "}\n");
9009 void IfClause::ilt_generate_code(ILT
*ilt
, const char *end_label
,
9013 if(!expr
->is_unfoldable()) {
9014 if(expr
->get_val_bool()) unreach
=true;
9017 char*& str
=ilt
->get_out_branches();
9020 size_t blockcount
=0;
9021 label
=mprintf("%s_l%lu",
9022 ilt
->get_my_tmpid().c_str(),
9023 (unsigned long) ilt
->get_new_label_num());
9024 str
=expr
->update_location_object(str
);
9025 str
=expr
->generate_code_tmp(str
, "if(!", blockcount
);
9026 str
=mputprintf(str
, ") goto %s;\n", label
);
9027 while(blockcount
-->0) str
=mputstr(str
, "}\n");
9029 block
->ilt_generate_code(ilt
);
9031 str
=mputprintf(str
, "goto %s;\n%s:\n",
9037 void IfClause::set_parent_path(WithAttribPath
* p_path
) {
9038 block
->set_parent_path(p_path
);
9041 void IfClause::dump(unsigned int level
) const {
9042 DEBUG(level
, "If clause!");
9043 expr
->dump(level
+ 1);
9044 block
->dump(level
+ 1);
9047 // =================================
9049 // =================================
9051 IfClauses::~IfClauses()
9053 for(size_t i
=0; i
<ics
.size(); i
++) delete ics
[i
];
9057 IfClauses
*IfClauses::clone() const
9059 FATAL_ERROR("IfClauses::clone");
9062 void IfClauses::add_ic(IfClause
*p_ic
)
9065 FATAL_ERROR("IfClauses::add_ic()");
9069 void IfClauses::add_front_ic(IfClause
*p_ic
)
9072 FATAL_ERROR("IfClauses::add_front_ic()");
9073 ics
.add_front(p_ic
);
9076 void IfClauses::set_my_scope(Scope
*p_scope
)
9078 for(size_t i
=0; i
<ics
.size(); i
++)
9079 ics
[i
]->set_my_scope(p_scope
);
9082 void IfClauses::set_fullname(const string
& p_fullname
)
9084 Node::set_fullname(p_fullname
);
9085 for(size_t i
=0; i
<ics
.size(); i
++)
9086 ics
[i
]->set_fullname(p_fullname
+".ic_"+Int2string(i
+1));
9089 void IfClauses::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9091 for(size_t i
=0; i
<ics
.size(); i
++)
9092 ics
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9095 void IfClauses::set_my_def(Definition
*p_def
)
9097 for(size_t i
=0; i
<ics
.size(); i
++)
9098 ics
[i
]->get_block()->set_my_def(p_def
);
9101 void IfClauses::set_my_ags(AltGuards
*p_ags
)
9103 for(size_t i
=0; i
<ics
.size(); i
++)
9104 ics
[i
]->get_block()->set_my_ags(p_ags
);
9107 void IfClauses::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9109 for(size_t i
=0; i
<ics
.size(); i
++)
9110 ics
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9113 StatementBlock::returnstatus_t
IfClauses::has_return
9114 (StatementBlock
*elseblock
) const
9116 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9117 for (size_t i
= 0; i
< ics
.size(); i
++) {
9118 switch (ics
[i
]->get_block()->has_return()) {
9119 case StatementBlock::RS_NO
:
9120 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9121 else ret_val
= StatementBlock::RS_NO
;
9123 case StatementBlock::RS_YES
:
9124 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9125 else ret_val
= StatementBlock::RS_YES
;
9128 return StatementBlock::RS_MAYBE
;
9131 StatementBlock::returnstatus_t else_status
;
9132 if (elseblock
) else_status
= elseblock
->has_return();
9133 else else_status
= StatementBlock::RS_NO
;
9134 switch (else_status
) {
9135 case StatementBlock::RS_NO
:
9136 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9137 else ret_val
= StatementBlock::RS_NO
;
9139 case StatementBlock::RS_YES
:
9140 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9141 else ret_val
= StatementBlock::RS_YES
;
9144 return StatementBlock::RS_MAYBE
;
9149 bool IfClauses::has_receiving_stmt() const
9151 for(size_t i
=0; i
<ics
.size(); i
++)
9152 if(ics
[i
]->has_receiving_stmt()) return true;
9156 void IfClauses::chk(bool& unreach
)
9158 for(size_t i
=0; i
<ics
.size(); i
++)
9159 ics
[i
]->chk(unreach
);
9162 void IfClauses::chk_allowed_interleave()
9164 for (size_t i
= 0; i
< ics
.size(); i
++)
9165 ics
[i
]->get_block()->chk_allowed_interleave();
9168 void IfClauses::set_code_section(
9169 GovernedSimple::code_section_t p_code_section
)
9171 for (size_t i
= 0; i
< ics
.size(); i
++)
9172 ics
[i
]->set_code_section(p_code_section
);
9175 char* IfClauses::generate_code(char *str
, size_t& blockcount
,
9176 bool& unreach
, bool& eachfalse
)
9178 for(size_t i
=0; i
<ics
.size(); i
++) {
9179 if(unreach
) return str
;
9180 str
=ics
[i
]->generate_code(str
, blockcount
, unreach
, eachfalse
);
9185 void IfClauses::ilt_generate_code(ILT
*ilt
, const char *end_label
,
9188 for(size_t i
=0; i
<ics
.size(); i
++) {
9190 ics
[i
]->ilt_generate_code(ilt
, end_label
, unreach
);
9194 void IfClauses::set_parent_path(WithAttribPath
* p_path
) {
9195 for (size_t i
= 0; i
< ics
.size(); i
++)
9196 ics
[i
]->set_parent_path(p_path
);
9199 void IfClauses::dump(unsigned int level
) const {
9200 DEBUG(level
, "%lu if clauses", (unsigned long)ics
.size());
9201 for (size_t i
= 0; i
< ics
.size(); i
++)
9202 ics
[i
]->dump(level
+ 1);
9205 // =================================
9207 // =================================
9209 SelectCase::SelectCase(TemplateInstances
*p_tis
, StatementBlock
*p_block
)
9210 : tis(p_tis
), block(p_block
)
9213 FATAL_ERROR("SelectCase::SelectCase()");
9216 SelectCase::~SelectCase()
9222 SelectCase
*SelectCase::clone() const
9224 FATAL_ERROR("SelectCase::clone");
9227 void SelectCase::set_my_scope(Scope
*p_scope
)
9229 if(tis
) tis
->set_my_scope(p_scope
);
9230 block
->set_my_scope(p_scope
);
9233 void SelectCase::set_fullname(const string
& p_fullname
)
9235 Node::set_fullname(p_fullname
);
9236 if(tis
) tis
->set_fullname(p_fullname
+".tis");
9237 block
->set_fullname(p_fullname
+".block");
9241 void SelectCase::chk(Type
*p_gov
, bool& unreach
)
9243 Error_Context
cntxt(this, "In select case statement");
9244 if(unreach
) warning("Control never reaches this code because of"
9245 " previous effective case(s)");
9247 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++)
9248 tis
->get_ti_byIndex(i
)->chk(p_gov
);
9249 else unreach
=true; // else statement
9253 void SelectCase::set_code_section
9254 (GovernedSimple::code_section_t p_code_section
)
9256 if(tis
) tis
->set_code_section(p_code_section
);
9257 block
->set_code_section(p_code_section
);
9261 char* SelectCase::generate_code_if(char *str
, const char *tmp_prefix
,
9262 const char *expr_name
, size_t idx
,
9265 if(unreach
) return str
;
9267 for(size_t i
=0; i
<tis
->get_nof_tis(); i
++) {
9268 TemplateInstance
*ti
=tis
->get_ti_byIndex(i
);
9269 Template
*tb
=ti
->get_Template();
9270 bool is_value
= NULL
== ti
->get_DerivedRef() && tb
->is_Value();
9271 expression_struct exprs
;
9272 Code::init_expr(&exprs
);
9274 if (tb
->get_templatetype() == Template::SPECIFIC_VALUE
) {
9275 tb
->get_specific_value()->generate_code_expr_mandatory(&exprs
);
9278 Value
* val
= tb
->get_Value();
9279 if (NULL
== val
->get_my_governor()) {
9280 // the value's governor could not be determined, treat it as a non-value template
9284 val
->generate_code_expr_mandatory(&exprs
);
9290 ti
->generate_code(&exprs
);
9292 str
=tb
->update_location_object(str
);
9293 if(!exprs
.preamble
&& !exprs
.postamble
) {
9294 str
=mputstr(str
, "if(");
9296 str
=mputprintf(str
, "%s.match(%s%s)", exprs
.expr
, expr_name
,
9297 omit_in_value_list
? ", TRUE" : "");
9298 else str
=mputprintf(str
, "%s == %s", expr_name
, exprs
.expr
);
9299 str
=mputprintf(str
, ") goto %s_%lu;\n", tmp_prefix
,
9300 (unsigned long) idx
);
9301 Code::free_expr(&exprs
);
9304 str
=mputprintf(str
, "{\nboolean %s_%lub;\n", tmp_prefix
,
9305 (unsigned long) idx
);
9307 exprs
.expr
=mprintf("%s_%lub = ", tmp_prefix
, (unsigned long) idx
);
9309 exprs
.expr
=mputprintf(exprs
.expr
, "%s.match(%s%s)", s
, expr_name
,
9310 omit_in_value_list
? ", TRUE" : "");
9311 else exprs
.expr
=mputprintf(exprs
.expr
, "(%s == %s)", expr_name
, s
);
9313 str
=Code::merge_free_expr(str
, &exprs
);
9314 str
=mputprintf(str
, "if(%s_%lub) goto %s_%lu;\n}\n",
9315 tmp_prefix
, (unsigned long) idx
, tmp_prefix
, (unsigned long) idx
);
9320 unreach
=true; // else statement
9321 str
=mputprintf(str
, "goto %s_%lu;\n", tmp_prefix
, (unsigned long) idx
);
9327 char* SelectCase::generate_code_stmt(char *str
, const char *tmp_prefix
,
9328 size_t idx
, bool& unreach
)
9330 if(unreach
) return str
;
9331 if(!tis
) unreach
=true;
9332 str
=mputprintf(str
, "%s_%lu:\n{\n", tmp_prefix
, (unsigned long) idx
);
9333 if (debugger_active
) {
9334 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
9336 str
=block
->generate_code(str
);
9337 str
=mputprintf(str
, "goto %s_end;\n}\n", tmp_prefix
);
9341 void SelectCase::ilt_generate_code_stmt(ILT
*ilt
, const char *tmp_prefix
,
9342 size_t idx
, bool& unreach
)
9345 if(!tis
) unreach
=true;
9346 char*& str
=ilt
->get_out_branches();
9347 str
=mputprintf(str
, "%s_%lu:\n", tmp_prefix
, (unsigned long) idx
);
9348 bool has_recv
=block
->has_receiving_stmt();
9350 str
=mputstr(str
, "{\n");
9351 str
=block
->generate_code(str
);
9353 else block
->ilt_generate_code(ilt
);
9354 str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9356 str
=mputstr(str
, "}\n");
9359 void SelectCase::set_parent_path(WithAttribPath
* p_path
) {
9360 block
->set_parent_path(p_path
);
9363 // =================================
9364 // ===== SelectCases
9365 // =================================
9367 SelectCases::~SelectCases()
9369 for(size_t i
=0; i
<scs
.size(); i
++) delete scs
[i
];
9373 SelectCases
*SelectCases::clone() const
9375 FATAL_ERROR("SelectCases::clone");
9378 void SelectCases::add_sc(SelectCase
*p_sc
)
9381 FATAL_ERROR("SelectCases::add_sc()");
9385 void SelectCases::set_my_scope(Scope
*p_scope
)
9387 for(size_t i
=0; i
<scs
.size(); i
++)
9388 scs
[i
]->set_my_scope(p_scope
);
9391 void SelectCases::set_fullname(const string
& p_fullname
)
9393 Node::set_fullname(p_fullname
);
9394 for(size_t i
=0; i
<scs
.size(); i
++)
9395 scs
[i
]->set_fullname(p_fullname
+".sc_"+Int2string(i
+1));
9398 void SelectCases::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9400 for(size_t i
=0; i
<scs
.size(); i
++)
9401 scs
[i
]->get_block()->set_my_sb(p_sb
, p_index
);
9404 void SelectCases::set_my_def(Definition
*p_def
)
9406 for(size_t i
=0; i
<scs
.size(); i
++)
9407 scs
[i
]->get_block()->set_my_def(p_def
);
9410 void SelectCases::set_my_ags(AltGuards
*p_ags
)
9412 for(size_t i
=0; i
<scs
.size(); i
++)
9413 scs
[i
]->get_block()->set_my_ags(p_ags
);
9416 void SelectCases::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9418 for(size_t i
=0; i
<scs
.size(); i
++)
9419 scs
[i
]->get_block()->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9422 StatementBlock::returnstatus_t
SelectCases::has_return() const
9424 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9425 bool has_else
= false;
9426 for (size_t i
= 0; i
< scs
.size(); i
++) {
9427 SelectCase
*sc
= scs
[i
];
9428 switch (sc
->get_block()->has_return()) {
9429 case StatementBlock::RS_NO
:
9430 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9431 else ret_val
= StatementBlock::RS_NO
;
9433 case StatementBlock::RS_YES
:
9434 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9435 else ret_val
= StatementBlock::RS_YES
;
9438 return StatementBlock::RS_MAYBE
;
9440 if (!sc
->get_tis()) {
9445 if (!has_else
&& ret_val
== StatementBlock::RS_YES
)
9446 return StatementBlock::RS_MAYBE
;
9447 else return ret_val
;
9450 bool SelectCases::has_receiving_stmt() const
9452 for(size_t i
=0; i
<scs
.size(); i
++)
9453 if(scs
[i
]->get_block()->has_receiving_stmt()) return true;
9458 void SelectCases::chk(Type
*p_gov
)
9461 for(size_t i
=0; i
<scs
.size(); i
++)
9462 scs
[i
]->chk(p_gov
, unreach
);
9465 void SelectCases::chk_allowed_interleave()
9467 for (size_t i
= 0; i
< scs
.size(); i
++)
9468 scs
[i
]->get_block()->chk_allowed_interleave();
9471 void SelectCases::set_code_section
9472 (GovernedSimple::code_section_t p_code_section
)
9474 for(size_t i
=0; i
<scs
.size(); i
++)
9475 scs
[i
]->set_code_section(p_code_section
);
9478 char* SelectCases::generate_code(char *str
, const char *tmp_prefix
,
9479 const char *expr_name
)
9482 for(size_t i
=0; i
<scs
.size(); i
++) {
9483 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9486 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9488 for(size_t i
=0; i
<scs
.size(); i
++) {
9489 str
=scs
[i
]->generate_code_stmt(str
, tmp_prefix
, i
, unreach
);
9492 str
=mputprintf(str
, "%s_end: /* empty */;\n", tmp_prefix
);
9496 void SelectCases::ilt_generate_code(ILT
*ilt
, const char *tmp_prefix
,
9497 const char *expr_init
,
9498 const char *expr_name
)
9500 char*& str
=ilt
->get_out_branches();
9501 if(strlen(expr_init
)) {
9502 str
=mputstr(str
, "{\n"); // (1)
9503 str
=mputstr(str
, expr_init
);
9506 for(size_t i
=0; i
<scs
.size(); i
++) {
9508 str
=scs
[i
]->generate_code_if(str
, tmp_prefix
, expr_name
, i
, unreach
);
9510 if(!unreach
) str
=mputprintf(str
, "goto %s_end;\n", tmp_prefix
);
9511 if(strlen(expr_init
)) str
=mputstr(str
, "}\n"); // (1)
9513 for(size_t i
=0; i
<scs
.size(); i
++) {
9515 scs
[i
]->ilt_generate_code_stmt(ilt
, tmp_prefix
, i
, unreach
);
9517 str
=mputprintf(str
, "%s_end:\n", tmp_prefix
);
9520 void SelectCases::set_parent_path(WithAttribPath
* p_path
) {
9521 for (size_t i
= 0; i
< scs
.size(); i
++)
9522 scs
[i
]->set_parent_path(p_path
);
9525 // =================================
9527 // =================================
9529 AltGuard::AltGuard(Value
*p_expr
, Statement
*p_stmt
, StatementBlock
*p_block
)
9530 : altguardtype(AG_OP
), expr(p_expr
), stmt(p_stmt
), block(p_block
)
9532 if (!p_stmt
|| !p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9535 AltGuard::AltGuard(Value
*p_expr
, Ref_pard
*p_ref
, StatementBlock
*p_block
)
9536 : altguardtype(AG_REF
), expr(p_expr
), ref(p_ref
), block(p_block
)
9538 if (!p_ref
) FATAL_ERROR("AltGuard::AltGuard()");
9541 AltGuard::AltGuard(Value
*p_expr
, Value
*p_v
,
9542 Ttcn::TemplateInstances
*p_t_list
, StatementBlock
*p_block
)
9543 : altguardtype(AG_INVOKE
), expr(p_expr
)
9546 if(!p_v
|| !p_t_list
) FATAL_ERROR("AltGuard::AltGuard()");
9548 invoke
.t_list
= p_t_list
;
9552 AltGuard::AltGuard(StatementBlock
*p_block
)
9553 : altguardtype(AG_ELSE
), expr(0), dummy(0), block(p_block
)
9555 if (!p_block
) FATAL_ERROR("AltGuard::AltGuard()");
9558 AltGuard::~AltGuard()
9560 switch(altguardtype
) {
9574 delete invoke
.t_list
;
9575 delete invoke
.ap_list
;
9582 FATAL_ERROR("AltGuard::~AltGuard()");
9586 AltGuard
*AltGuard::clone() const
9588 FATAL_ERROR("AltGuard::clone");
9591 void AltGuard::set_my_scope(Scope
*p_scope
)
9593 switch(altguardtype
) {
9595 if(expr
) expr
->set_my_scope(p_scope
);
9596 stmt
->set_my_scope(p_scope
);
9597 block
->set_my_scope(p_scope
);
9600 if(expr
) expr
->set_my_scope(p_scope
);
9601 ref
->set_my_scope(p_scope
);
9602 if(block
) block
->set_my_scope(p_scope
);
9605 if(expr
) expr
->set_my_scope(p_scope
);
9606 invoke
.v
->set_my_scope(p_scope
);
9607 if(invoke
.t_list
) invoke
.t_list
->set_my_scope(p_scope
);
9608 if(invoke
.ap_list
) invoke
.ap_list
->set_my_scope(p_scope
);
9609 if(block
) block
->set_my_scope(p_scope
);
9612 block
->set_my_scope(p_scope
);
9615 FATAL_ERROR("AltGuard::set_my_scope()");
9619 void AltGuard::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9621 switch(altguardtype
) {
9623 stmt
->set_my_sb(p_sb
, p_index
);
9624 block
->set_my_sb(p_sb
, p_index
);
9627 if(block
) block
->set_my_sb(p_sb
, p_index
);
9630 if(block
) block
->set_my_sb(p_sb
, p_index
);
9633 block
->set_my_sb(p_sb
, p_index
);
9636 FATAL_ERROR("AltGuard::set_my_sb()");
9640 void AltGuard::set_fullname(const string
& p_fullname
)
9642 Node::set_fullname(p_fullname
);
9643 switch(altguardtype
) {
9645 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9646 stmt
->set_fullname(p_fullname
+".stmt");
9647 block
->set_fullname(p_fullname
+".block");
9650 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9651 ref
->set_fullname(p_fullname
+".ref");
9652 if(block
) block
->set_fullname(p_fullname
+".block");
9655 if(expr
) expr
->set_fullname(p_fullname
+".expr");
9656 invoke
.v
->set_fullname(p_fullname
+".function");
9657 if(invoke
.t_list
) invoke
.t_list
->set_fullname(p_fullname
+".argument");
9658 if(invoke
.ap_list
) invoke
.ap_list
->set_fullname(p_fullname
+".argument");
9659 if(block
) block
->set_fullname(p_fullname
+".block");
9662 block
->set_fullname(p_fullname
+".elseblock");
9665 FATAL_ERROR("AltGuard::set_fullname()");
9669 Value
*AltGuard::get_guard_expr() const
9671 if (altguardtype
== AG_ELSE
) FATAL_ERROR("AltGuard::get_guard_expr()");
9675 Ref_pard
*AltGuard::get_guard_ref() const
9677 if (altguardtype
!= AG_REF
) FATAL_ERROR("AltGuard::get_guard_ref()");
9681 Statement
*AltGuard::get_guard_stmt() const
9683 if (altguardtype
!= AG_OP
) FATAL_ERROR("AltGuard::get_guard_stmt()");
9687 void AltGuard::set_my_def(Definition
*p_def
)
9689 switch(altguardtype
) {
9691 stmt
->set_my_def(p_def
);
9692 block
->set_my_def(p_def
);
9695 if(block
) block
->set_my_def(p_def
);
9698 if(block
) block
->set_my_def(p_def
);
9701 block
->set_my_def(p_def
);
9704 FATAL_ERROR("AltGuard::set_my_def()");
9708 void AltGuard::set_my_ags(AltGuards
*p_ags
)
9710 switch (altguardtype
) {
9712 block
->set_my_ags(p_ags
);
9715 if (block
) block
->set_my_ags(p_ags
);
9718 if (block
) block
->set_my_ags(p_ags
);
9721 block
->set_my_ags(p_ags
);
9724 FATAL_ERROR("AltGuard::set_my_ags()");
9728 void AltGuard::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9730 switch (altguardtype
) {
9732 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9735 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9738 if (block
) block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9741 block
->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9744 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9748 void AltGuard::chk()
9750 switch(altguardtype
) {
9753 Error_Context
cntxt(expr
, "In guard expression");
9754 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9757 Error_Context
cntxt(stmt
, "In guard operation");
9764 Error_Context
cntxt(expr
, "In guard expression");
9765 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9768 Error_Context
cntxt(ref
, "In guard statement");
9769 Common::Assignment
*t_ass
= ref
->get_refd_assignment();
9771 if (t_ass
->get_asstype() == Common::Assignment::A_ALTSTEP
) {
9772 ref
->get_my_scope()->chk_runs_on_clause(t_ass
, *ref
, "call");
9774 ref
->error("Reference to an altstep was expected instead of %s",
9775 t_ass
->get_description().c_str());
9779 if (block
) block
->chk();
9783 Error_Context
cntxt(expr
, "In guard expression");
9784 expr
->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE
);
9787 if (!invoke
.t_list
) return; //already_checked
9788 Error_Context
cntxt(ref
, "In guard statement");
9789 switch(invoke
.v
->get_valuetype()){
9790 case Value::V_REFER
:
9792 "A value of an altstep type was expected "
9793 "in the argument instead of a `refers' statement,"
9794 " which does not specify any function type");
9796 case Value::V_TTCN3_NULL
:
9798 "A value of an altstep type was expected "
9799 "in the argument instead of a `null' value,"
9800 " which does not specify any function type");
9805 Type
*t
= invoke
.v
->get_expr_governor_last();
9807 switch (t
->get_typetype()) {
9810 case Type::T_ALTSTEP
:
9813 invoke
.v
->error("A value of type altstep was expected instead of "
9814 "`%s'", t
->get_typename().c_str());
9817 invoke
.v
->get_my_scope()->chk_runs_on_clause(t
, *this, "call");
9818 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
9819 invoke
.ap_list
= new Ttcn::ActualParList
;
9820 bool is_erroneous
= fp_list
->chk_actual_parlist(invoke
.t_list
,
9822 delete invoke
.t_list
;
9825 delete invoke
.ap_list
;
9828 invoke
.ap_list
->set_fullname(get_fullname());
9829 invoke
.ap_list
->set_my_scope(invoke
.v
->get_my_scope());
9832 if (block
) block
->chk();
9836 Error_Context
cntxt(this, "In else branch");
9838 Statement
*first_stmt
= block
->get_first_stmt();
9839 if (first_stmt
&& first_stmt
->get_statementtype() ==
9840 Statement::S_REPEAT
)
9841 first_stmt
->warning("The first statement of the [else] branch is a "
9842 "repeat statement. This will result in busy waiting");
9846 FATAL_ERROR("AltGuard::chk()");
9850 void AltGuard::set_code_section(
9851 GovernedSimple::code_section_t p_code_section
)
9853 switch(altguardtype
) {
9855 if (expr
) expr
->set_code_section(p_code_section
);
9856 stmt
->set_code_section(p_code_section
);
9857 block
->set_code_section(p_code_section
);
9860 if (expr
) expr
->set_code_section(p_code_section
);
9861 ref
->set_code_section(p_code_section
);
9862 if (block
) block
->set_code_section(p_code_section
);
9865 if (expr
) expr
->set_code_section(p_code_section
);
9866 invoke
.v
->set_code_section(p_code_section
);
9867 if(invoke
.t_list
) invoke
.t_list
->set_code_section(p_code_section
);
9869 for(size_t i
= 0; i
< invoke
.ap_list
->get_nof_pars(); i
++)
9870 invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
9871 if (block
) block
->set_code_section(p_code_section
);
9874 block
->set_code_section(p_code_section
);
9877 FATAL_ERROR("AltGuard::set_fullname()");
9881 void AltGuard::generate_code_invoke_instance(expression_struct
*p_expr
)
9883 if (altguardtype
!= AG_INVOKE
)
9884 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9885 Value
*last_v
= invoke
.v
->get_value_refd_last();
9886 if (last_v
->get_valuetype() == Value::V_ALTSTEP
) {
9887 Common::Assignment
*altstep
= last_v
->get_refd_fat();
9888 p_expr
->expr
= mputprintf(p_expr
->expr
, "%s_instance(",
9889 altstep
->get_genname_from_scope(invoke
.v
->get_my_scope()).c_str());
9890 invoke
.ap_list
->generate_code_alias(p_expr
,
9891 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
9893 invoke
.v
->generate_code_expr_mandatory(p_expr
);
9894 p_expr
->expr
= mputstr(p_expr
->expr
, ".invoke(");
9895 Type
* gov_last
= invoke
.v
->get_expr_governor_last();
9896 invoke
.ap_list
->generate_code_alias(p_expr
, 0,
9897 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
9899 p_expr
->expr
= mputc(p_expr
->expr
, ')');
9902 // =================================
9904 // =================================
9906 AltGuards::~AltGuards()
9908 for(size_t i
=0; i
<ags
.size(); i
++) delete ags
[i
];
9911 delete il_label_end
;
9914 AltGuards
*AltGuards::clone() const
9916 FATAL_ERROR("AltGuards::clone");
9919 void AltGuards::add_ag(AltGuard
*p_ag
)
9922 FATAL_ERROR("AltGuards::add_ag()");
9926 void AltGuards::set_my_scope(Scope
*p_scope
)
9929 for(size_t i
=0; i
<ags
.size(); i
++)
9930 ags
[i
]->set_my_scope(p_scope
);
9933 void AltGuards::set_fullname(const string
& p_fullname
)
9935 Node::set_fullname(p_fullname
);
9936 for(size_t i
=0; i
<ags
.size(); i
++)
9937 ags
[i
]->set_fullname(p_fullname
+".ag_"+Int2string(i
+1));
9940 void AltGuards::set_my_sb(StatementBlock
*p_sb
, size_t p_index
)
9942 for(size_t i
=0; i
<ags
.size(); i
++)
9943 ags
[i
]->set_my_sb(p_sb
, p_index
);
9946 void AltGuards::set_my_def(Definition
*p_def
)
9948 for(size_t i
=0; i
<ags
.size(); i
++)
9949 ags
[i
]->set_my_def(p_def
);
9952 void AltGuards::set_my_ags(AltGuards
*p_ags
)
9954 for(size_t i
=0; i
<ags
.size(); i
++)
9955 ags
[i
]->set_my_ags(p_ags
);
9958 void AltGuards::set_my_laic_stmt(AltGuards
*p_ags
, Statement
*p_loop_stmt
)
9960 for(size_t i
=0; i
<ags
.size(); i
++)
9961 ags
[i
]->set_my_laic_stmt(p_ags
, p_loop_stmt
);
9964 bool AltGuards::has_else() const
9966 for (size_t i
= 0; i
< ags
.size(); i
++)
9967 if (ags
[i
]->get_type() == AltGuard::AG_ELSE
) return true;
9971 StatementBlock::returnstatus_t
AltGuards::has_return() const
9973 StatementBlock::returnstatus_t ret_val
= StatementBlock::RS_MAYBE
;
9974 for (size_t i
= 0; i
< ags
.size(); i
++) {
9975 AltGuard
*ag
= ags
[i
];
9976 StatementBlock
*block
= ag
->get_block();
9977 StatementBlock::returnstatus_t block_status
;
9978 if (block
) block_status
= block
->has_return();
9979 else block_status
= StatementBlock::RS_NO
;
9980 switch (block_status
) {
9981 case StatementBlock::RS_NO
:
9982 if (ret_val
== StatementBlock::RS_YES
) return StatementBlock::RS_MAYBE
;
9983 else ret_val
= StatementBlock::RS_NO
;
9985 case StatementBlock::RS_YES
:
9986 if (ret_val
== StatementBlock::RS_NO
) return StatementBlock::RS_MAYBE
;
9987 else ret_val
= StatementBlock::RS_YES
;
9990 return StatementBlock::RS_MAYBE
;
9992 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
9997 bool AltGuards::has_receiving_stmt() const
9999 for(size_t i
=0; i
<ags
.size(); i
++)
10000 if(ags
[i
]->get_block()->has_receiving_stmt()) return true;
10004 void AltGuards::chk()
10006 bool unreach_found
= false;
10007 size_t nof_ags
= ags
.size();
10008 AltGuard
*prev_ag
= 0;
10009 for (size_t i
= 0; i
< nof_ags
; i
++) {
10010 AltGuard
*ag
= ags
[i
];
10012 if (!unreach_found
&& prev_ag
&&
10013 prev_ag
->get_type() == AltGuard::AG_ELSE
) {
10014 ag
->warning("Control never reaches this branch of alternative "
10015 "because of the previous [else] branch");
10016 unreach_found
= true;
10022 void AltGuards::chk_allowed_interleave()
10024 for (size_t i
= 0; i
< ags
.size(); i
++) {
10025 AltGuard
*ag
= ags
[i
];
10026 switch (ag
->get_type()) {
10027 case AltGuard::AG_OP
:
10029 case AltGuard::AG_REF
:
10030 case AltGuard::AG_INVOKE
:
10031 ag
->error("Invocation of an altstep is not allowed within an "
10032 "interleave statement");
10034 case AltGuard::AG_ELSE
:
10035 ag
->error("Else branch of an alternative is not allowed within an "
10036 "interleave statement");
10039 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
10041 ag
->get_block()->chk_allowed_interleave();
10045 void AltGuards::set_code_section(
10046 GovernedSimple::code_section_t p_code_section
)
10048 for (size_t i
= 0; i
< ags
.size(); i
++)
10049 ags
[i
]->set_code_section(p_code_section
);
10052 char *AltGuards::generate_code_alt(char *str
, const Location
& loc
)
10054 bool label_needed
= has_repeat
, has_else_branch
= false;
10055 for (size_t i
= 0; i
< ags
.size(); i
++) {
10056 AltGuard
*ag
= ags
[i
];
10057 switch (ag
->get_type()) {
10058 case AltGuard::AG_OP
:
10059 // trigger may return ALT_REPEAT
10060 if (ag
->get_guard_stmt()->can_repeat()) label_needed
= true;
10062 case AltGuard::AG_REF
:
10063 case AltGuard::AG_INVOKE
:
10064 // an altstep may return ALT_REPEAT
10065 label_needed
= true;
10067 case AltGuard::AG_ELSE
:
10068 has_else_branch
= true;
10071 FATAL_ERROR("AltGuards::generate_code_alt()");
10073 if (has_else_branch
) break;
10075 // if there is no [else] branch the defaults may return ALT_REPEAT
10076 if (!has_else_branch
) label_needed
= true;
10077 // opening bracket of the statement block
10078 str
= mputstr(str
, "{\n");
10079 // the label name is also used for prefixing local variables
10080 if (!my_scope
|| label
) FATAL_ERROR("AltGuards::generate_code_alt()");
10081 label
= new string(my_scope
->get_scope_mod_gen()->get_temporary_id());
10082 const char *label_str
= label
->c_str();
10083 if (label_needed
) str
= mputprintf(str
, "%s:\n", label_str
);
10084 // temporary variables used for caching of status codes
10085 for (size_t i
= 0; i
< ags
.size(); i
++) {
10086 AltGuard
*ag
= ags
[i
];
10087 if (ag
->get_type() == AltGuard::AG_ELSE
) break;
10088 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10089 label_str
, (unsigned long) i
,
10090 ag
->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
10092 if (!has_else_branch
) {
10093 str
= mputprintf(str
, "alt_status %s_default_flag = ALT_MAYBE;\n",
10096 // the first snapshot is taken in non-blocking mode
10097 // and opening infinite for() loop
10098 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10099 "for ( ; ; ) {\n");
10100 for (size_t i
= 0; i
< ags
.size(); i
++) {
10101 AltGuard
*ag
= ags
[i
];
10102 AltGuard::altguardtype_t agtype
= ag
->get_type();
10103 if (agtype
== AltGuard::AG_ELSE
) {
10104 // an else branch was found
10105 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10106 StatementBlock
*block
= ag
->get_block();
10107 if (block
->get_nof_stmts() > 0) {
10108 str
= mputstr(str
, "{\n");
10109 if (debugger_active
) {
10110 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
10112 str
= block
->generate_code(str
);
10113 str
= mputstr(str
, "}\n");
10115 // jump out of the infinite for() loop
10116 if (block
->has_return() != StatementBlock::RS_YES
)
10117 str
= mputstr(str
, "break;\n");
10118 // do not generate code for further branches
10121 Value
*guard_expr
= ag
->get_guard_expr();
10123 // the branch has a boolean guard expression
10124 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
10125 label_str
, (unsigned long) i
);
10126 str
= guard_expr
->update_location_object(str
);
10127 expression_struct expr
;
10128 Code::init_expr(&expr
);
10129 guard_expr
->generate_code_expr(&expr
);
10130 str
= mputstr(str
, expr
.preamble
);
10131 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10132 "else %s_alt_flag_%lu = ALT_NO;\n", expr
.expr
, label_str
,
10133 (unsigned long) i
, label_str
, (unsigned long) i
);
10134 str
= mputstr(str
, expr
.postamble
);
10135 Code::free_expr(&expr
);
10136 str
= mputstr(str
, "}\n");
10138 // evaluation of guard operation or altstep
10139 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
10140 label_str
, (unsigned long) i
);
10141 // indicates whether the guard operation might return ALT_REPEAT
10143 expression_struct expr
;
10144 Code::init_expr(&expr
);
10145 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10146 (unsigned long) i
);
10148 case AltGuard::AG_OP
: {
10149 // the guard operation is a receiving statement
10150 Statement
*stmt
= ag
->get_guard_stmt();
10151 str
= stmt
->update_location_object(str
);
10152 stmt
->generate_code_expr(&expr
);
10153 can_repeat
= stmt
->can_repeat();
10155 case AltGuard::AG_REF
: {
10156 // the guard operation is an altstep instance
10157 Ref_pard
*ref
= ag
->get_guard_ref();
10158 str
= ref
->update_location_object(str
);
10159 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10160 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10161 altstep
->get_genname_from_scope(my_scope
).c_str());
10162 ref
->get_parlist()->generate_code_alias(&expr
,
10163 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10164 expr
.expr
= mputc(expr
.expr
, ')');
10167 case AltGuard::AG_INVOKE
: {
10168 // the guard operation is an altstep invocation
10169 str
= ag
->update_location_object(str
);
10170 ag
->generate_code_invoke_instance(&expr
);
10174 FATAL_ERROR("AltGuards::generate_code_alt()");
10176 str
= Code::merge_free_expr(str
, &expr
);
10178 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
10179 label_str
, (unsigned long) i
, label_str
);
10181 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10182 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
10183 label_str
, (unsigned long) i
);
10185 // execution of statement block if the guard was successful
10186 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10187 (unsigned long) i
);
10188 StatementBlock
*block
= ag
->get_block();
10189 if (block
&& block
->get_nof_stmts() > 0) {
10190 str
= mputstr(str
, "{\n");
10191 if (debugger_active
) {
10192 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
10194 str
= block
->generate_code(str
);
10195 if (block
->has_return() != StatementBlock::RS_YES
)
10196 str
= mputstr(str
, "break;\n");
10197 str
= mputstr(str
, "}\n");
10198 } else str
= mputstr(str
, "break;\n");
10199 // closing of if() block
10200 str
= mputstr(str
, "}\n");
10203 if (!has_else_branch
) {
10204 // calling of defaults
10205 str
= mputprintf(str
, "if (%s_default_flag == ALT_MAYBE) {\n"
10206 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10207 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10209 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10211 label_str
, label_str
, label_str
, label_str
, label_str
, label_str
);
10212 str
= loc
.update_location_object(str
);
10213 // error handling and taking the next snapshot in blocking mode
10214 str
= mputstr(str
, "if (");
10215 for (size_t i
= 0; i
< ags
.size(); i
++)
10216 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO && ", label_str
,
10217 (unsigned long) i
);
10218 str
= mputprintf(str
,"%s_default_flag == ALT_NO) "
10219 "TTCN_error(\"None of the branches can be chosen in the alt "
10220 "statement in file ", label_str
);
10221 str
= Code::translate_string(str
, loc
.get_filename());
10222 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10223 if (first_line
< last_line
) str
= mputprintf(str
,
10224 " between lines %d and %d", first_line
, last_line
);
10225 else str
= mputprintf(str
, ", line %d", first_line
);
10226 str
= mputstr(str
, ".\");\n"
10227 "TTCN_Snapshot::take_new(TRUE);\n");
10229 // end of for() statement and the statement block
10230 str
= mputstr(str
, "}\n"
10235 char *AltGuards::generate_code_altstep(char *str
)
10237 if (!my_scope
) FATAL_ERROR("AltGuards::generate_code_altstep()");
10238 Common::Module
*my_mod
= my_scope
->get_scope_mod_gen();
10239 bool has_else_branch
= has_else();
10240 if (!has_else_branch
) {
10241 str
= mputstr(str
, "alt_status ret_val = ALT_NO;\n");
10243 for (size_t i
= 0; i
< ags
.size(); i
++) {
10244 AltGuard
*ag
= ags
[i
];
10245 AltGuard::altguardtype_t agtype
= ag
->get_type();
10246 if (agtype
== AltGuard::AG_ELSE
) {
10247 // an else branch was found
10248 str
= mputstr(str
, "TTCN_Snapshot::else_branch_reached();\n");
10249 StatementBlock
*block
= ag
->get_block();
10250 if (block
->get_nof_stmts() > 0) {
10251 str
= mputstr(str
, "{\n");
10252 if (debugger_active
) {
10253 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
10255 str
= block
->generate_code(str
);
10256 str
= mputstr(str
, "}\n");
10258 if (block
->has_return() != StatementBlock::RS_YES
)
10259 str
= mputstr(str
, "return ALT_YES;\n");
10260 // do not generate code for further branches
10263 size_t blockcount
= 0;
10264 Value
*guard_expr
= ag
->get_guard_expr();
10266 // the branch has a boolean guard expression
10267 str
= guard_expr
->update_location_object(str
);
10268 str
= guard_expr
->generate_code_tmp(str
, "if (", blockcount
);
10269 str
= mputstr(str
, ") {\n");
10272 // indicates whether the guard operation might return ALT_REPEAT
10274 expression_struct expr
;
10275 Code::init_expr(&expr
);
10277 case AltGuard::AG_OP
: {
10278 // the guard operation is a receiving statement
10279 Statement
*stmt
= ag
->get_guard_stmt();
10280 str
= stmt
->update_location_object(str
);
10281 stmt
->generate_code_expr(&expr
);
10282 can_repeat
= stmt
->can_repeat();
10284 case AltGuard::AG_REF
: {
10285 // the guard operation is an altstep instance
10286 Ref_pard
*ref
= ag
->get_guard_ref();
10287 str
= ref
->update_location_object(str
);
10288 Common::Assignment
*altstep
= ref
->get_refd_assignment();
10289 expr
.expr
= mputprintf(expr
.expr
, "%s_instance(",
10290 altstep
->get_genname_from_scope(my_scope
).c_str());
10291 ref
->get_parlist()->generate_code_alias(&expr
,
10292 altstep
->get_FormalParList(), altstep
->get_RunsOnType(), false);
10293 expr
.expr
= mputc(expr
.expr
, ')');
10296 case AltGuard::AG_INVOKE
: {
10297 str
= ag
->update_location_object(str
);
10298 ag
->generate_code_invoke_instance(&expr
);
10302 FATAL_ERROR("AltGuards::generate_code_altstep()");
10304 if (expr
.preamble
|| expr
.postamble
) {
10305 if (blockcount
== 0) {
10306 // open a statement block if it is not done so far
10307 str
= mputstr(str
, "{\n");
10310 const string
& tmp_id
= my_mod
->get_temporary_id();
10311 const char *tmp_id_str
= tmp_id
.c_str();
10312 str
= mputprintf(str
, "alt_status %s;\n"
10313 "{\n", tmp_id_str
);
10314 str
= mputstr(str
, expr
.preamble
);
10315 str
= mputprintf(str
, "%s = %s;\n", tmp_id_str
, expr
.expr
);
10316 str
= mputstr(str
, expr
.postamble
);
10317 str
= mputprintf(str
, "}\n"
10318 "switch (%s) {\n", tmp_id_str
);
10320 str
= mputprintf(str
, "switch (%s) {\n", expr
.expr
);
10322 Code::free_expr(&expr
);
10323 str
= mputstr(str
, "case ALT_YES:\n");
10324 StatementBlock
*block
= ag
->get_block();
10325 if (block
&& block
->get_nof_stmts() > 0) {
10326 str
= mputstr(str
, "{\n");
10327 if (debugger_active
) {
10328 str
= mputstr(str
, "TTCN3_Debug_Scope debug_scope;\n");
10330 str
= block
->generate_code(str
);
10331 str
= mputstr(str
, "}\n");
10333 if (!block
|| block
->has_return() != StatementBlock::RS_YES
)
10334 str
= mputstr(str
, "return ALT_YES;\n");
10336 str
= mputstr(str
, "case ALT_REPEAT:\n"
10337 "return ALT_REPEAT;\n");
10338 if (agtype
== AltGuard::AG_REF
|| agtype
== AltGuard::AG_INVOKE
) {
10339 str
= mputprintf(str
, "case ALT_BREAK:\n"
10340 "return ALT_BREAK;\n");
10342 if (!has_else_branch
)
10343 str
= mputstr(str
, "case ALT_MAYBE:\n"
10344 "ret_val = ALT_MAYBE;\n");
10345 str
= mputstr(str
, "default:\n"
10348 // closing statement blocks
10349 for ( ; blockcount
> 0; blockcount
--) str
= mputstr(str
, "}\n");
10352 if (!has_else_branch
) str
= mputstr(str
, "return ret_val;\n");
10356 char* AltGuards::generate_code_call_body(char *str
, const Location
& loc
,
10357 const string
& temp_id
, bool in_interleave
)
10359 if (label
) FATAL_ERROR("AltGuards::generate_code_call_body()");
10360 label
= new string(temp_id
);
10361 const char *label_str
= temp_id
.c_str();
10362 // label is needed only if there is a repeat statement in the branches
10363 if (has_repeat
) str
= mputprintf(str
, "%s:\n", label_str
);
10364 // temporary variables used for caching of status codes
10365 for (size_t i
= 0; i
< ags
.size(); i
++)
10366 str
= mputprintf(str
, "alt_status %s_alt_flag_%lu = %s;\n",
10367 label_str
, (unsigned long) i
,
10368 ags
[i
]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10369 str
= loc
.update_location_object(str
);
10370 // the first snapshot is taken in non-blocking mode
10371 // and opening infinite for() loop
10372 str
= mputstr(str
, "TTCN_Snapshot::take_new(FALSE);\n"
10373 "for ( ; ; ) {\n"); // (1)
10374 for (size_t i
= 0; i
< ags
.size(); i
++) {
10375 AltGuard
*ag
= ags
[i
];
10376 if (ag
->get_type() != AltGuard::AG_OP
)
10377 FATAL_ERROR("AltGuards::generate_code_call_body()");
10378 Value
*guard_expr
= ag
->get_guard_expr();
10380 // the branch has a boolean guard expression
10381 str
= mputprintf(str
,
10382 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10383 label_str
, (unsigned long) i
);
10384 str
= guard_expr
->update_location_object(str
);
10385 expression_struct expr
;
10386 Code::init_expr(&expr
);
10387 guard_expr
->generate_code_expr(&expr
);
10388 str
= mputstr(str
, expr
.preamble
);
10389 str
= mputprintf(str
, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10390 "else %s_alt_flag_%lu = ALT_NO;\n",
10391 expr
.expr
, label_str
, (unsigned long) i
,
10392 label_str
, (unsigned long) i
);
10393 str
= mputstr(str
, expr
.postamble
);
10394 Code::free_expr(&expr
);
10395 str
= mputstr(str
, "}\n"); // (2)
10397 // evaluation of guard operation
10398 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10399 label_str
, (unsigned long) i
);
10400 expression_struct expr
;
10401 Code::init_expr(&expr
);
10402 expr
.expr
= mputprintf(expr
.expr
, "%s_alt_flag_%lu = ", label_str
,
10403 (unsigned long) i
);
10404 Statement
*stmt
= ag
->get_guard_stmt();
10405 str
= stmt
->update_location_object(str
);
10406 stmt
->generate_code_expr(&expr
);
10407 str
= Code::merge_free_expr(str
, &expr
);
10408 // execution of statement block if the guard was successful
10409 str
= mputprintf(str
, "if (%s_alt_flag_%lu == ALT_YES) ", label_str
,
10410 (unsigned long) i
);
10411 StatementBlock
*block
= ag
->get_block();
10412 if(in_interleave
) {
10413 if(block
&& block
->get_nof_stmts() > 0) {
10414 if(block
->has_receiving_stmt()) {
10415 str
= mputprintf(str
, "goto %s_branch%lu;\n",
10416 label_str
, (unsigned long) i
);
10419 str
= mputstr(str
, "{\n"); // (3)
10420 str
= block
->generate_code(str
);
10421 str
= mputprintf(str
, "goto %s_end;\n"
10426 else str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10429 if (block
&& block
->get_nof_stmts() > 0) {
10430 str
= mputstr(str
, "{\n"); // (3)
10431 str
= block
->generate_code(str
);
10432 if (block
->has_return() != StatementBlock::RS_YES
)
10433 str
= mputstr(str
, "break;\n");
10434 str
= mputstr(str
, "}\n"); // (3)
10436 else str
= mputstr(str
, "break;\n");
10438 // closing of if() block
10439 str
= mputstr(str
, "}\n"); // (2)
10441 str
= loc
.update_location_object(str
);
10442 // error handling and taking the next snapshot in blocking mode
10443 str
= mputstr(str
, "if (");
10444 for (size_t i
= 0; i
< ags
.size(); i
++) {
10445 if (i
> 0) str
= mputstr(str
, " && ");
10446 str
= mputprintf(str
, "%s_alt_flag_%lu == ALT_NO", label_str
,
10447 (unsigned long) i
);
10449 str
= mputstr(str
, ") TTCN_error(\"None of the branches can be chosen in "
10450 "the response and exception handling part of call statement in file ");
10451 str
= Code::translate_string(str
, loc
.get_filename());
10452 int first_line
= loc
.get_first_line(), last_line
= loc
.get_last_line();
10453 if (first_line
< last_line
) str
= mputprintf(str
,
10454 " between lines %d and %d", first_line
, last_line
);
10455 else str
= mputprintf(str
, ", line %d", first_line
);
10456 str
= mputstr(str
, ".\");\n"
10457 "TTCN_Snapshot::take_new(TRUE);\n"
10462 void AltGuards::ilt_generate_code_call_body(ILT
*ilt
, const char *label_str
)
10464 char*& str
=ilt
->get_out_branches();
10465 for(size_t i
=0; i
<ags
.size(); i
++) {
10466 StatementBlock
*block
= ags
[i
]->get_block();
10467 if (block
&& block
->has_receiving_stmt()) {
10468 str
= mputprintf(str
, "%s_branch%lu:\n", label_str
, (unsigned long) i
);
10469 block
->ilt_generate_code(ilt
);
10470 str
= mputprintf(str
, "goto %s_end;\n", label_str
);
10475 } // namespace Ttcn