b6f201c738d09a169d44ea297acba5f78536565b
[deliverable/titan.core.git] / compiler2 / ttcn3 / Statement.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../../common/dbgnew.hh"
9 #include "Statement.hh"
10 #include "Ttcnstuff.hh"
11 #include "../TypeCompat.hh"
12 #include "../CompType.hh"
13 #include "../CompField.hh"
14 #include "../SigParam.hh"
15 #include "TtcnTemplate.hh"
16 #include "ILT.hh"
17 #include "ArrayDimensions.hh"
18 #include "../Int.hh"
19 #include "../main.hh"
20 #include "Attributes.hh"
21
22 namespace Ttcn {
23
24 // =================================
25 // ===== StatementBlock
26 // =================================
27
28 StatementBlock::StatementBlock()
29 : Scope(), checked(false), labels_checked(false), my_sb(0), my_def(0), exception_handling(EH_NONE)
30 {
31 }
32
33 StatementBlock::~StatementBlock()
34 {
35 for(size_t i=0; i<stmts.size(); i++)
36 delete stmts[i];
37 stmts.clear();
38 defs.clear();
39 labels.clear();
40 }
41
42 StatementBlock *StatementBlock::clone() const
43 {
44 FATAL_ERROR("StatementBlock::clone");
45 }
46
47 void StatementBlock::dump(unsigned int level) const
48 {
49 size_t n = stmts.size();
50 DEBUG(level, "StatementBlock at %p with %lu", (const void*)this,
51 (unsigned long) n);
52 for (size_t i = 0; i < n; ++i) {
53 stmts[i]->dump(level+1);
54 }
55 }
56
57 void StatementBlock::add_stmt(Statement *p_stmt, bool to_front)
58 {
59 if(!p_stmt)
60 FATAL_ERROR("StatementBlock::add_stmt()");
61 if (to_front) {
62 stmts.add_front(p_stmt);
63 } else {
64 stmts.add(p_stmt);
65 }
66 p_stmt->set_my_scope(this);
67 p_stmt->set_my_sb(this, stmts.size()-1);
68 }
69
70 void StatementBlock::set_my_scope(Scope *p_scope)
71 {
72 set_parent_scope(p_scope);
73 for(size_t i=0; i<stmts.size(); i++)
74 stmts[i]->set_my_scope(this);
75 }
76
77 void StatementBlock::set_fullname(const string& p_fullname)
78 {
79 Node::set_fullname(p_fullname);
80 for(size_t i=0; i<stmts.size(); i++)
81 stmts[i]->set_fullname(p_fullname+".stmt_"+Int2string(i+1));
82 }
83
84 /** \todo handle loops and conditional statements */
85 Statement *StatementBlock::get_first_stmt() const
86 {
87 size_t nof_stmts = stmts.size();
88 for (size_t i = 0; i < nof_stmts; i++) {
89 Statement *stmt = stmts[i];
90 switch (stmt->get_statementtype()) {
91 case Statement::S_LABEL:
92 // ignore and go to the next statement
93 break;
94 case Statement::S_BLOCK: {
95 // if the block is not empty return its first statement
96 // otherwise go to the next statement
97 Statement *first_stmt = stmt->get_block()->get_first_stmt();
98 if (first_stmt) return first_stmt;
99 else break; }
100 case Statement::S_DOWHILE: {
101 // if the block is not empty return its first statement
102 // otherwise return the whole do-while statement
103 Statement *first_stmt = stmt->get_block()->get_first_stmt();
104 if (first_stmt) return first_stmt;
105 else return stmt; }
106 default:
107 return stmt;
108 }
109 }
110 return 0;
111 }
112
113 void StatementBlock::register_def(Definition *p_def)
114 {
115 if(!p_def) FATAL_ERROR("StatementBlock::register_def()");
116 const Identifier& id=p_def->get_id();
117 if (defs.has_key(id)) {
118 const char *dispname = id.get_dispname().c_str();
119 p_def->error("Duplicate definition with identifier `%s'", dispname);
120 defs[id]->note("Previous definition with identifier `%s' is here",
121 dispname);
122 } else {
123 defs.add(id, p_def);
124 if (parent_scope) {
125 if (parent_scope->has_ass_withId(id)) {
126 const char *dispname = id.get_dispname().c_str();
127 p_def->error("Definition with identifier `%s' is not unique"
128 " in the scope hierarchy", dispname);
129 Reference ref(0, id.clone());
130 Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
131 if (!ass) FATAL_ERROR("StatementBlock::register_def()");
132 ass->note("Previous definition with identifier `%s' in higher "
133 "scope unit is here", dispname);
134 } else if (parent_scope->is_valid_moduleid(id)) {
135 p_def->warning("Definition with name `%s' hides a module identifier",
136 id.get_dispname().c_str());
137 }
138 }
139 }
140 }
141
142 bool StatementBlock::has_ass_withId(const Identifier& p_id)
143 {
144 return defs.has_key(p_id) || get_parent_scope()->has_ass_withId(p_id);
145 }
146
147 Common::Assignment* StatementBlock::get_ass_bySRef(Ref_simple *p_ref)
148 {
149 if(p_ref->get_modid()) return get_parent_scope()->get_ass_bySRef(p_ref);
150 const Identifier& id=*p_ref->get_id();
151 if(defs.has_key(id)) return defs[id];
152 else return get_parent_scope()->get_ass_bySRef(p_ref);
153 }
154
155 Type *StatementBlock::get_mtc_system_comptype(bool is_system)
156 {
157 // return NULL outside test cases
158 if (!my_def || my_def->get_asstype() != Common::Assignment::A_TESTCASE)
159 return 0;
160 if (is_system) {
161 Def_Testcase *t_tc = dynamic_cast<Def_Testcase*>(my_def);
162 if (!t_tc) FATAL_ERROR("StatementBlock::get_mtc_system_comptype()");
163 Type *system_ct = t_tc->get_SystemType();
164 if (system_ct) return system_ct;
165 // otherwise (if the testcase has no system clause) the type of 'system'
166 // is the same as the type of 'mtc' (which is given in 'runs on' clause)
167 }
168 return my_def->get_RunsOnType();
169 }
170
171 Ttcn::StatementBlock *StatementBlock::get_statementblock_scope()
172 {
173 return this;
174 }
175
176 void StatementBlock::set_my_sb(StatementBlock *p_sb, size_t p_index)
177 {
178 my_sb=p_sb;
179 my_sb_index=p_index;
180 for(size_t i=0; i<stmts.size(); i++)
181 stmts[i]->set_my_sb(this, i);
182 }
183
184 size_t StatementBlock::get_my_sb_index() const
185 {
186 if(!my_sb) FATAL_ERROR("StatementBlock::get_my_sb_index()");
187 return my_sb_index;
188 }
189
190 void StatementBlock::set_my_def(Definition *p_def)
191 {
192 my_def=p_def;
193 for(size_t i=0; i<stmts.size(); i++)
194 stmts[i]->set_my_def(p_def);
195 }
196
197 void StatementBlock::set_my_ags(AltGuards *p_ags)
198 {
199 for(size_t i=0; i<stmts.size(); i++)
200 stmts[i]->set_my_ags(p_ags);
201 }
202
203 void StatementBlock::set_my_laic_stmt(AltGuards *p_ags,
204 Statement *p_loop_stmt)
205 {
206 for(size_t i=0; i<stmts.size(); i++)
207 stmts[i]->set_my_laic_stmt(p_ags, p_loop_stmt);
208 }
209
210 StatementBlock::returnstatus_t StatementBlock::has_return() const
211 {
212 returnstatus_t ret_val = RS_NO;
213 size_t nof_stmts = stmts.size();
214 for (size_t i = 0; i < nof_stmts; i++) {
215 Statement *stmt = stmts[i];
216 if (stmt->get_statementtype() == Statement::S_GOTO) {
217 if (stmt->goto_jumps_forward()) {
218 // heuristics without deep analysis of the control flow graph:
219 // skip over the next statements until a (used) label is found
220 // the behaviour will be sound (i.e. no false errors will be reported)
221 for (i++; i < nof_stmts; i++) {
222 stmt = stmts[i];
223 if (stmt->get_statementtype() == Statement::S_LABEL &&
224 stmt->label_is_used()) break;
225 }
226 } else return RS_YES;
227 } else if (stmt->get_statementtype()==Statement::S_BLOCK && stmt->get_block()->exception_handling!=EH_NONE) {
228 switch (stmt->get_block()->exception_handling) {
229 case EH_TRY: // the i-th statement is a try{} statement block, the (i+1)-th must be a catch{} block
230 if ((i+1)<nof_stmts && stmts[i+1]->get_statementtype()==Statement::S_BLOCK && stmts[i+1]->get_block()->exception_handling==EH_CATCH) {
231 returnstatus_t try_block_rs = stmt->has_return();
232 returnstatus_t catch_block_rs = stmts[i+1]->has_return();
233 // 3 x 3 combinations
234 if (try_block_rs==catch_block_rs) {
235 switch (try_block_rs) {
236 case RS_YES:
237 return RS_YES;
238 case RS_MAYBE:
239 ret_val = RS_MAYBE;
240 default:
241 break;
242 }
243 } else {
244 ret_val = RS_MAYBE;
245 }
246 } else { // if next statement is not a catch{} block then that error has already been reported
247 ret_val = RS_MAYBE; // assume the catch block was an RS_MAYBE
248 }
249 break;
250 case EH_CATCH:
251 // logically this is part of the preceding try{} block, handle it as part of it, see above case EH_TRY
252 break;
253 default:
254 FATAL_ERROR("StatementBlock::has_return()");
255 }
256 } else {
257 switch (stmt->has_return()) {
258 case RS_YES:
259 return RS_YES;
260 case RS_MAYBE:
261 ret_val = RS_MAYBE;
262 default:
263 break;
264 }
265 }
266 }
267 return ret_val;
268 }
269
270 bool StatementBlock::has_receiving_stmt(size_t start_i) const
271 {
272 for(size_t i=start_i; i<stmts.size(); i++)
273 if(stmts[i]->has_receiving_stmt()) return true;
274 return false;
275 }
276
277 bool StatementBlock::has_def_stmt_i(size_t start_i) const
278 {
279 for(size_t i=start_i; i<stmts.size(); i++)
280 if(stmts[i]->get_statementtype()==Statement::S_DEF) return true;
281 return false;
282 }
283
284 size_t StatementBlock::last_receiving_stmt_i() const
285 {
286 size_t nof_stmts = stmts.size();
287 if (nof_stmts > 0) {
288 size_t i = nof_stmts;
289 do {
290 if (stmts[--i]->has_receiving_stmt()) return i;
291 } while (i > 0);
292 }
293 return nof_stmts;
294 }
295
296 StatementBlock *StatementBlock::get_parent_block() const
297 {
298 for (Scope *s = get_parent_scope(); s; s=s->get_parent_scope()) {
299 StatementBlock *sb = dynamic_cast<StatementBlock*>(s);
300 if (sb) return sb;
301 }
302 return 0;
303 }
304
305 void StatementBlock::chk_trycatch_blocks(Statement* s1, Statement* s2) {
306 if (s1 && s1->get_statementtype()==Statement::S_BLOCK && s1->get_block()->get_exception_handling()==StatementBlock::EH_TRY) {
307 if (!(s2 && s2->get_statementtype()==Statement::S_BLOCK && s2->get_block()->get_exception_handling()==StatementBlock::EH_CATCH)) {
308 s1->error("`try' statement block must be followed by a `catch' block");
309 }
310 }
311 if (s2 && s2->get_statementtype()==Statement::S_BLOCK && s2->get_block()->get_exception_handling()==StatementBlock::EH_CATCH) {
312 if (!(s1 && s1->get_statementtype()==Statement::S_BLOCK && s1->get_block()->get_exception_handling()==StatementBlock::EH_TRY)) {
313 s2->error("`catch' statement block must be preceded by a `try' block");
314 }
315 }
316 }
317
318 void StatementBlock::chk()
319 {
320 if (checked) return;
321 chk_labels();
322 bool unreach_found = false;
323 size_t nof_stmts = stmts.size();
324 Statement *prev_stmt = 0;
325 for (size_t i = 0; i < nof_stmts; i++) {
326 Statement *stmt = stmts[i];
327 stmt->chk();
328 if (!unreach_found && stmt->get_statementtype() != Statement::S_LABEL &&
329 prev_stmt && prev_stmt->is_terminating()) {
330 // a statement is unreachable if:
331 // - it is not a label (i.e. goto cannot jump to it)
332 // - it is not the first statement of the block
333 // - the previous statement terminates the control flow
334 stmt->warning("Control never reaches this statement");
335 unreach_found = true;
336 }
337 // check try-catch statement block usage
338 chk_trycatch_blocks(prev_stmt, stmt);
339 //
340 prev_stmt = stmt;
341 }
342 chk_trycatch_blocks(prev_stmt, 0);
343 chk_unused_labels();
344 checked = true;
345 }
346
347 void StatementBlock::chk_allowed_interleave()
348 {
349 size_t nof_stmts = stmts.size();
350 for (size_t i = 0; i < nof_stmts; i++)
351 stmts[i]->chk_allowed_interleave();
352 }
353
354 void StatementBlock::chk_labels()
355 {
356 if(labels_checked) return;
357 for(size_t i=0; i<stmts.size(); i++) {
358 Statement *st=stmts[i];
359 if(st->get_statementtype()!=Statement::S_LABEL) continue;
360 const Identifier& labelid=st->get_labelid();
361 if(has_label(labelid)) {
362 const char *name=labelid.get_dispname().c_str();
363 st->error("Duplicate label `%s'", name);
364 Statement *st2=get_label(labelid);
365 st2->note("Previous definition of label `%s' is here", name);
366 }
367 else labels.add(labelid, st);
368 }
369 labels_checked=true;
370 }
371
372 void StatementBlock::chk_unused_labels()
373 {
374 size_t nof_stmts = stmts.size();
375 for (size_t i = 0; i < nof_stmts; i++) {
376 Statement *stmt = stmts[i];
377 if (stmt->get_statementtype() == Statement::S_LABEL &&
378 !stmt->label_is_used())
379 stmt->warning("Label `%s' is defined, but not used",
380 stmt->get_labelid().get_dispname().c_str());
381 }
382 }
383
384 bool StatementBlock::has_label(const Identifier& p_id) const
385 {
386 for (const StatementBlock *sb = this; sb; sb = sb->get_parent_block())
387 if (sb->labels.has_key(p_id)) return true;
388 return false;
389 }
390
391 Statement *StatementBlock::get_label(const Identifier& p_id) const
392 {
393 for (const StatementBlock *sb = this; sb; sb = sb->get_parent_block())
394 if (sb->labels.has_key(p_id)) return sb->labels[p_id];
395 FATAL_ERROR("StatementBlock::get_label()");
396 return 0;
397 }
398
399 void StatementBlock::set_code_section(
400 GovernedSimple::code_section_t p_code_section)
401 {
402 for(size_t i = 0; i < stmts.size(); i++)
403 stmts[i]->set_code_section(p_code_section);
404 }
405
406 char* StatementBlock::generate_code(char *str)
407 {
408 if (exception_handling==EH_TRY) {
409 str = mputstr(str, "TTCN_TryBlock try_block;\n");
410 }
411 if (stmts.size()>0) {
412 Statement* first_stmt = stmts[0];
413 str = first_stmt->generate_code(str);
414 if (exception_handling==EH_CATCH) {
415 if (first_stmt->get_statementtype()!=Statement::S_DEF) FATAL_ERROR("StatementBlock::generate_code()");
416 Definition* error_msg_def = first_stmt->get_def();
417 string error_msg_name = error_msg_def->get_id().get_name();
418 str = mputprintf(str, "%s = ttcn_error.get_message();\n", error_msg_name.c_str());
419 }
420 }
421 for(size_t i=1; i<stmts.size(); i++) {
422 str = stmts[i]->generate_code(str);
423 }
424 return str;
425 }
426
427 void StatementBlock::ilt_generate_code(ILT *ilt)
428 {
429 size_t nof_stmts = stmts.size();
430 if (nof_stmts == 0) return;
431 char*& str=ilt->get_out_branches();
432 size_t last_recv_stmt_i=last_receiving_stmt_i();
433 // has no receiving stmt
434 if (last_recv_stmt_i == nof_stmts) {
435 bool has_def=has_def_stmt_i();
436 if(has_def) str=mputstr(str, "{\n");
437 for(size_t i=0; i<nof_stmts; i++)
438 str=stmts[i]->generate_code(str);
439 if(has_def) str=mputstr(str, "}\n");
440 return;
441 }
442 for(size_t i=0; i<=last_recv_stmt_i; i++)
443 stmts[i]->ilt_generate_code(ilt);
444 // the last part which does not contain receiving stmt
445 if(last_recv_stmt_i==nof_stmts-1) return;
446 bool has_def=has_def_stmt_i(last_recv_stmt_i+1);
447 if(has_def) str=mputstr(str, "{\n");
448 for(size_t i=last_recv_stmt_i+1; i<nof_stmts; i++)
449 str=stmts[i]->generate_code(str);
450 if(has_def) str=mputstr(str, "}\n");
451 }
452
453 void StatementBlock::set_parent_path(WithAttribPath* p_path)
454 {
455 for (size_t i = 0; i < stmts.size(); i++)
456 stmts[i]->set_parent_path(p_path);
457 }
458
459 // =================================
460 // ===== Statement
461 // =================================
462
463 void Statement::clean_up()
464 {
465 switch (statementtype) {
466 case S_ERROR:
467 case S_BREAK:
468 case S_CONTINUE:
469 case S_STOP_EXEC:
470 case S_REPEAT:
471 case S_START_PROFILER:
472 case S_STOP_PROFILER:
473 break;
474 case S_START_UNDEF:
475 case S_STOP_UNDEF:
476 delete undefstartstop.ref;
477 delete undefstartstop.val;
478 break;
479 case S_UNKNOWN_INSTANCE:
480 case S_FUNCTION_INSTANCE:
481 case S_ALTSTEP_INSTANCE:
482 case S_ACTIVATE:
483 delete ref_pard;
484 break;
485 case S_DEF:
486 delete def;
487 break;
488 case S_ASSIGNMENT:
489 delete ass;
490 break;
491 case S_BLOCK:
492 delete block;
493 break;
494 case S_LOG:
495 case S_ACTION:
496 case S_STOP_TESTCASE:
497 delete logargs;
498 break;
499 case S_LABEL:
500 delete label.id;
501 delete label.clabel;
502 break;
503 case S_GOTO:
504 delete go_to.id;
505 break;
506 case S_IF:
507 delete if_stmt.ics;
508 delete if_stmt.elseblock;
509 delete if_stmt.elseblock_location;
510 break;
511 case S_SELECT:
512 delete select.expr;
513 delete select.scs;
514 break;
515 case S_FOR:
516 if(loop.for_stmt.varinst)
517 delete loop.for_stmt.init_varinst;
518 else
519 delete loop.for_stmt.init_ass;
520 delete loop.for_stmt.finalexpr;
521 delete loop.for_stmt.step;
522 delete loop.block;
523 if (loop.label_next)
524 delete loop.label_next;
525 if (loop.il_label_end)
526 delete loop.il_label_end;
527 break;
528 case S_WHILE:
529 case S_DOWHILE:
530 delete loop.expr;
531 delete loop.block;
532 if (loop.label_next)
533 delete loop.label_next;
534 if (loop.il_label_end)
535 delete loop.il_label_end;
536 break;
537 case S_ALT:
538 case S_INTERLEAVE:
539 delete ags;
540 break;
541 case S_RETURN:
542 delete returnexpr.v;
543 delete returnexpr.t;
544 break;
545 case S_DEACTIVATE:
546 delete deactivate;
547 break;
548 case S_SEND:
549 delete port_op.portref;
550 delete port_op.s.sendpar;
551 delete port_op.s.toclause;
552 break;
553 case S_CALL:
554 delete port_op.portref;
555 delete port_op.s.sendpar;
556 delete port_op.s.call.timer;
557 delete port_op.s.toclause;
558 delete port_op.s.call.body;
559 break;
560 case S_REPLY:
561 delete port_op.portref;
562 delete port_op.s.sendpar;
563 delete port_op.s.replyval;
564 delete port_op.s.toclause;
565 break;
566 case S_RAISE:
567 delete port_op.portref;
568 delete port_op.s.raise.signature_ref;
569 delete port_op.s.sendpar;
570 delete port_op.s.toclause;
571 break;
572 case S_RECEIVE:
573 case S_CHECK_RECEIVE:
574 case S_TRIGGER:
575 delete port_op.portref;
576 delete port_op.r.rcvpar;
577 delete port_op.r.fromclause;
578 delete port_op.r.redirect.value;
579 delete port_op.r.redirect.sender;
580 break;
581 case S_GETCALL:
582 case S_CHECK_GETCALL:
583 delete port_op.portref;
584 delete port_op.r.rcvpar;
585 delete port_op.r.fromclause;
586 delete port_op.r.redirect.param;
587 delete port_op.r.redirect.sender;
588 break;
589 case S_GETREPLY:
590 case S_CHECK_GETREPLY:
591 delete port_op.portref;
592 delete port_op.r.rcvpar;
593 delete port_op.r.getreply_valuematch;
594 delete port_op.r.fromclause;
595 delete port_op.r.redirect.value;
596 delete port_op.r.redirect.param;
597 delete port_op.r.redirect.sender;
598 break;
599 case S_CATCH:
600 case S_CHECK_CATCH:
601 delete port_op.portref;
602 delete port_op.r.ctch.signature_ref;
603 delete port_op.r.rcvpar;
604 delete port_op.r.fromclause;
605 delete port_op.r.redirect.value;
606 delete port_op.r.redirect.sender;
607 break;
608 case S_CHECK:
609 delete port_op.portref;
610 delete port_op.r.fromclause;
611 delete port_op.r.redirect.sender;
612 break;
613 case S_CLEAR:
614 case S_START_PORT:
615 case S_STOP_PORT:
616 case S_HALT:
617 delete port_op.portref;
618 break;
619 case S_START_COMP:
620 delete comp_op.compref;
621 delete comp_op.funcinstref;
622 break;
623 case S_START_COMP_REFD:
624 delete comp_op.compref;
625 delete comp_op.derefered.value;
626 delete comp_op.derefered.ap_list2;
627 break;
628 case S_STOP_COMP:
629 case S_KILL:
630 case S_KILLED:
631 delete comp_op.compref;
632 break;
633 case S_DONE:
634 if (comp_op.compref) {
635 delete comp_op.compref;
636 delete comp_op.donereturn.donematch;
637 delete comp_op.donereturn.redirect;
638 }
639 break;
640 case S_CONNECT:
641 case S_MAP:
642 case S_DISCONNECT:
643 case S_UNMAP:
644 delete config_op.compref1;
645 delete config_op.portref1;
646 delete config_op.compref2;
647 delete config_op.portref2;
648 break;
649 case S_START_TIMER:
650 delete timer_op.timerref;
651 delete timer_op.value;
652 break;
653 case S_STOP_TIMER:
654 case S_TIMEOUT:
655 delete timer_op.timerref;
656 break;
657 case S_SETVERDICT:
658 delete setverdict.verdictval;
659 delete setverdict.logargs;
660 break;
661 case S_TESTCASE_INSTANCE:
662 delete testcase_inst.tcref;
663 delete testcase_inst.timerval;
664 break;
665 case S_TESTCASE_INSTANCE_REFD:
666 delete execute_refd.value;
667 delete execute_refd.ap_list2;
668 delete execute_refd.timerval;
669 break;
670 case S_ACTIVATE_REFD:
671 case S_UNKNOWN_INVOKED:
672 case S_FUNCTION_INVOKED:
673 case S_ALTSTEP_INVOKED:
674 delete fau_refd.value;
675 delete fau_refd.ap_list2;
676 break;
677 case S_STRING2TTCN:
678 case S_INT2ENUM:
679 delete convert_op.val;
680 delete convert_op.ref;
681 break;
682 default:
683 FATAL_ERROR("Statement::clean_up()");
684 } // switch statementtype
685 }
686
687 Statement::Statement(statementtype_t p_st)
688 : statementtype(p_st), my_sb(0)
689 {
690 switch(statementtype) {
691 case S_REPEAT:
692 ags=0;
693 case S_ERROR:
694 case S_STOP_EXEC:
695 case S_START_PROFILER:
696 case S_STOP_PROFILER:
697 break;
698 case S_BREAK:
699 case S_CONTINUE:
700 brk_cnt.loop_stmt=0;
701 brk_cnt.ags=0;
702 break;
703 default:
704 FATAL_ERROR("Statement::Statement()");
705 } // switch statementtype
706 }
707
708 Statement::Statement(statementtype_t p_st, Ref_base *p_ref, Value *p_val)
709 : statementtype(p_st), my_sb(0)
710 {
711 switch(statementtype) {
712 case S_START_UNDEF:
713 if (!p_ref) FATAL_ERROR("Statement::Statement()");
714 undefstartstop.ref=p_ref;
715 undefstartstop.val=p_val;
716 break;
717 case S_STOP_UNDEF:
718 if (!p_ref || p_val) FATAL_ERROR("Statement::Statement()");
719 undefstartstop.ref=p_ref;
720 undefstartstop.val=0;
721 break;
722 default:
723 FATAL_ERROR("Statement::Statement()");
724 } // switch statementtype
725 }
726
727 Statement::Statement(statementtype_t p_st, Ref_pard *p_ref)
728 : statementtype(p_st), my_sb(0)
729 {
730 switch(statementtype) {
731 case S_UNKNOWN_INSTANCE:
732 case S_FUNCTION_INSTANCE:
733 case S_ALTSTEP_INSTANCE:
734 case S_ACTIVATE:
735 if(!p_ref)
736 FATAL_ERROR("Statement::Statement()");
737 ref_pard=p_ref;
738 break;
739 default:
740 FATAL_ERROR("Statement::Statement()");
741 } // switch statementtype
742 }
743
744 Statement::Statement(statementtype_t p_st, Value *p_derefered_value,
745 ParsedActualParameters *p_ap_list)
746 : statementtype(p_st), my_sb(0)
747 {
748 switch(statementtype) {
749 case S_ACTIVATE_REFD:
750 case S_UNKNOWN_INVOKED:
751 case S_FUNCTION_INVOKED:
752 case S_ALTSTEP_INVOKED:
753 if(!p_derefered_value || !p_ap_list)
754 FATAL_ERROR("Statement::Statement()");
755 fau_refd.value = p_derefered_value;
756 fau_refd.t_list1 = p_ap_list;
757 break;
758 default:
759 FATAL_ERROR("Statement::Statement()");
760 }
761 }
762
763 Statement::Statement(statementtype_t p_st, Definition *p_def)
764 : statementtype(p_st), my_sb(0)
765 {
766 switch(statementtype) {
767 case S_DEF:
768 if(!p_def)
769 FATAL_ERROR("Statement::Statement()");
770 def=p_def;
771 break;
772 default:
773 FATAL_ERROR("Statement::Statement()");
774 } // switch statementtype
775 }
776
777 Statement::Statement(statementtype_t p_st, Assignment *p_ass)
778 : statementtype(p_st), my_sb(0)
779 {
780 switch(statementtype) {
781 case S_ASSIGNMENT:
782 if(!p_ass)
783 FATAL_ERROR("Statement::Statement()");
784 ass=p_ass;
785 break;
786 default:
787 FATAL_ERROR("Statement::Statement()");
788 } // switch statementtype
789 }
790
791 Statement::Statement(statementtype_t p_st, StatementBlock *p_block)
792 : statementtype(p_st), my_sb(0)
793 {
794 switch (statementtype) {
795 case S_BLOCK:
796 if (!p_block) FATAL_ERROR("Statement::Statement()");
797 block = p_block;
798 break;
799 default:
800 FATAL_ERROR("Statement::Statement()");
801 } // switch statementtype
802 }
803
804 Statement::Statement(statementtype_t p_st, LogArguments *p_logargs)
805 : statementtype(p_st), my_sb(0)
806 {
807 switch(statementtype) {
808 case S_LOG:
809 case S_ACTION:
810 case S_STOP_TESTCASE:
811 logargs=p_logargs;
812 break;
813 default:
814 FATAL_ERROR("Statement::Statement()");
815 } // switch statementtype
816 }
817
818 Statement::Statement(statementtype_t p_st, Identifier *p_id)
819 : statementtype(p_st), my_sb(0)
820 {
821 if (!p_id)
822 FATAL_ERROR("Statement::Statement()");
823 switch (statementtype) {
824 case S_LABEL:
825 label.id = p_id;
826 label.stmt_idx = 0;
827 label.clabel = 0;
828 label.used = false;
829 break;
830 case S_GOTO:
831 go_to.id = p_id;
832 go_to.stmt_idx = 0;
833 go_to.label = 0;
834 go_to.jumps_forward = false;
835 break;
836 default:
837 FATAL_ERROR("Statement::Statement()");
838 } // switch statementtype
839 }
840
841 Statement::Statement(statementtype_t p_st, IfClauses *p_ics,
842 StatementBlock *p_block, Location *p_loc)
843 : statementtype(p_st), my_sb(0)
844 {
845 switch(statementtype) {
846 case S_IF:
847 if(!p_ics)
848 FATAL_ERROR("Statement::Statement()");
849 if_stmt.ics=p_ics;
850 if (p_block) {
851 if (!p_loc) FATAL_ERROR("Statement::Statement()");
852 if_stmt.elseblock = p_block;
853 if_stmt.elseblock_location = p_loc;
854 } else {
855 if (p_loc) FATAL_ERROR("Statement::Statement()");
856 if_stmt.elseblock = 0;
857 if_stmt.elseblock_location = 0;
858 }
859 break;
860 default:
861 FATAL_ERROR("Statement::Statement()");
862 } // switch statementtype
863 }
864
865 Statement::Statement(statementtype_t p_st, Value *p_expr, SelectCases *p_scs)
866 : statementtype(p_st), my_sb(0)
867 {
868 switch(statementtype) {
869 case S_SELECT:
870 if(!p_expr || !p_scs)
871 FATAL_ERROR("Statement::Statement()");
872 select.expr=p_expr;
873 select.scs=p_scs;
874 break;
875 default:
876 FATAL_ERROR("Statement::Statement()");
877 } // switch statementtype
878 }
879
880 Statement::Statement(statementtype_t p_st, Definitions *p_defs,
881 Assignment *p_ass, Value *p_final,
882 Assignment *p_step, StatementBlock *p_block)
883 : statementtype(p_st), my_sb(0)
884 {
885 switch (statementtype) {
886 case S_FOR: // precisely one of p_defs, p_ass allowed
887 if (p_defs) {
888 // it came from a for loop which looked like this:
889 // for (var integer foo:=1; foo<10; foo:=foo+1) ;
890 if (p_ass) FATAL_ERROR("Statement::Statement()");
891 loop.for_stmt.varinst = true;
892 loop.for_stmt.init_varinst = p_defs;
893 } else {
894 // it came from a for loop which looked like this:
895 // for (foo:=1; foo<10; foo:=foo+1) ;
896 if (!p_ass) FATAL_ERROR("Statement::Statement()");
897 loop.for_stmt.varinst = false;
898 loop.for_stmt.init_ass = p_ass;
899 }
900 if(!p_final || !p_step || !p_block)
901 FATAL_ERROR("Statement::Statement()");
902 loop.for_stmt.finalexpr=p_final;
903 loop.for_stmt.step=p_step;
904 loop.block=p_block;
905 loop.label_next=0;
906 loop.il_label_end=0;
907 loop.has_cnt=false;
908 loop.has_brk=false;
909 loop.has_cnt_in_ags=false;
910 loop.iterate_once=false; // not used by for
911 loop.is_ilt=false;
912 break;
913 default:
914 FATAL_ERROR("Statement::Statement()");
915 } // switch statementtype
916 }
917
918 Statement::Statement(statementtype_t p_st, Value *p_val,
919 StatementBlock *p_block)
920 : statementtype(p_st), my_sb(0)
921 {
922 switch(statementtype) {
923 case S_WHILE:
924 case S_DOWHILE:
925 if(!p_val || !p_block)
926 FATAL_ERROR("Statement::Statement()");
927 loop.expr=p_val;
928 loop.block=p_block;
929 loop.label_next=0;
930 loop.il_label_end=0;
931 loop.has_cnt=false;
932 loop.has_brk=false;
933 loop.has_cnt_in_ags=false;
934 loop.iterate_once=false; // used only by do-while
935 loop.is_ilt=false;
936 break;
937 default:
938 FATAL_ERROR("Statement::Statement()");
939 } // switch statementtype
940 }
941
942 Statement::Statement(statementtype_t p_st, AltGuards *p_ags)
943 : statementtype(p_st), my_sb(0)
944 {
945 switch(statementtype) {
946 case S_ALT:
947 case S_INTERLEAVE:
948 if(!p_ags)
949 FATAL_ERROR("Statement::Statement()");
950 ags=p_ags;
951 break;
952 default:
953 FATAL_ERROR("Statement::Statement()");
954 } // switch statementtype
955 }
956
957 Statement::Statement(statementtype_t p_st, Template *p_temp)
958 : statementtype(p_st), my_sb(0)
959 {
960 switch(statementtype) {
961 case S_RETURN:
962 returnexpr.v=0;
963 returnexpr.t=p_temp;
964 break;
965 default:
966 FATAL_ERROR("Statement::Statement()");
967 } // switch statementtype
968 }
969
970 Statement::Statement(statementtype_t p_st, Value *p_val)
971 : statementtype(p_st), my_sb(0)
972 {
973 switch (statementtype) {
974 case S_KILLED:
975 if (!p_val)
976 FATAL_ERROR("Statement::Statement()");
977 // no break
978 case S_STOP_COMP:
979 case S_KILL:
980 comp_op.compref=p_val;
981 break;
982 case S_DEACTIVATE:
983 deactivate=p_val;
984 break;
985 default:
986 FATAL_ERROR("Statement::Statement()");
987 } // switch statementtype
988 }
989
990 Statement::Statement(statementtype_t p_st, Value *p_val,
991 LogArguments *p_logargs)
992 : statementtype(p_st), my_sb(0)
993 {
994 if (!p_val || statementtype != S_SETVERDICT)
995 FATAL_ERROR("Statement::Statement()");
996 setverdict.verdictval = p_val;
997 setverdict.logargs = p_logargs;
998 }
999
1000 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1001 TemplateInstance *p_templinst, Value *p_val)
1002 : statementtype(p_st), my_sb(0)
1003 {
1004 switch(statementtype) {
1005 case S_SEND:
1006 if(!p_ref || !p_templinst)
1007 FATAL_ERROR("Statement::Statement()");
1008 port_op.portref=p_ref;
1009 port_op.s.sendpar=p_templinst;
1010 port_op.s.toclause=p_val;
1011 break;
1012 default:
1013 FATAL_ERROR("Statement::Statement()");
1014 } // switch statementtype
1015 }
1016
1017 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1018 TemplateInstance *p_templinst, Value *p_timerval,
1019 bool p_nowait, Value *p_toclause, AltGuards *p_callbody)
1020 : statementtype(p_st), my_sb(0)
1021 {
1022 switch(statementtype) {
1023 case S_CALL:
1024 if(!p_ref || !p_templinst || (p_timerval && p_nowait))
1025 FATAL_ERROR("Statement::Statement()");
1026 port_op.portref=p_ref;
1027 port_op.s.sendpar=p_templinst;
1028 port_op.s.call.timer=p_timerval;
1029 port_op.s.call.nowait=p_nowait;
1030 port_op.s.toclause=p_toclause;
1031 port_op.s.call.body=p_callbody;
1032 break;
1033 default:
1034 FATAL_ERROR("Statement::Statement()");
1035 } // switch statementtype
1036 }
1037
1038 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1039 TemplateInstance *p_templinst, Value *p_replyval,
1040 Value *p_toclause)
1041 : statementtype(p_st), my_sb(0)
1042 {
1043 switch(statementtype) {
1044 case S_REPLY:
1045 if(!p_ref || !p_templinst)
1046 FATAL_ERROR("Statement::Statement()");
1047 port_op.portref=p_ref;
1048 port_op.s.sendpar=p_templinst;
1049 port_op.s.replyval=p_replyval;
1050 port_op.s.toclause=p_toclause;
1051 break;
1052 default:
1053 FATAL_ERROR("Statement::Statement()");
1054 } // switch statementtype
1055 }
1056
1057 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1058 Reference *p_sig, TemplateInstance *p_templinst,
1059 Value *p_toclause)
1060 : statementtype(p_st), my_sb(0)
1061 {
1062 switch(statementtype) {
1063 case S_RAISE:
1064 if(!p_ref || !p_templinst || !p_sig)
1065 FATAL_ERROR("Statement::Statement()");
1066 port_op.portref=p_ref;
1067 port_op.s.raise.signature_ref=p_sig;
1068 port_op.s.raise.signature=0;
1069 port_op.s.sendpar=p_templinst;
1070 port_op.s.toclause=p_toclause;
1071 break;
1072 default:
1073 FATAL_ERROR("Statement::Statement()");
1074 } // switch statementtype
1075 }
1076
1077 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1078 TemplateInstance *p_templinst,
1079 TemplateInstance *p_fromclause,
1080 Reference *p_redirectval, Reference *p_redirectsender)
1081 : statementtype(p_st), my_sb(0)
1082 {
1083 switch(statementtype) {
1084 case S_RECEIVE:
1085 case S_CHECK_RECEIVE:
1086 case S_TRIGGER:
1087 port_op.portref=p_ref;
1088 port_op.r.rcvpar=p_templinst;
1089 port_op.r.fromclause=p_fromclause;
1090 port_op.r.redirect.value=p_redirectval;
1091 port_op.r.redirect.param=0;
1092 port_op.r.redirect.sender=p_redirectsender;
1093 break;
1094 default:
1095 FATAL_ERROR("Statement::Statement()");
1096 } // switch statementtype
1097 }
1098
1099 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1100 TemplateInstance *p_templinst,
1101 TemplateInstance *p_fromclause,
1102 ParamRedirect *p_redirectparam,
1103 Reference *p_redirectsender)
1104 : statementtype(p_st), my_sb(0)
1105 {
1106 switch(statementtype) {
1107 case S_GETCALL:
1108 case S_CHECK_GETCALL:
1109 port_op.portref=p_ref;
1110 port_op.r.rcvpar=p_templinst;
1111 port_op.r.fromclause=p_fromclause;
1112 port_op.r.redirect.value=0;
1113 port_op.r.redirect.param=p_redirectparam;
1114 port_op.r.redirect.sender=p_redirectsender;
1115 break;
1116 default:
1117 FATAL_ERROR("Statement::Statement()");
1118 } // switch statementtype
1119 }
1120
1121 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1122 TemplateInstance *p_templinst,
1123 TemplateInstance *p_valuematch,
1124 TemplateInstance *p_fromclause,
1125 Reference *p_redirectval, ParamRedirect *p_redirectparam,
1126 Reference *p_redirectsender)
1127 : statementtype(p_st), my_sb(0)
1128 {
1129 switch(statementtype) {
1130 case S_GETREPLY:
1131 case S_CHECK_GETREPLY:
1132 if (!p_templinst && p_valuematch) FATAL_ERROR("Statement::Statement()");
1133 port_op.portref=p_ref;
1134 port_op.r.rcvpar=p_templinst;
1135 port_op.r.getreply_valuematch=p_valuematch;
1136 port_op.r.fromclause=p_fromclause;
1137 port_op.r.redirect.value=p_redirectval;
1138 port_op.r.redirect.param=p_redirectparam;
1139 port_op.r.redirect.sender=p_redirectsender;
1140 break;
1141 default:
1142 FATAL_ERROR("Statement::Statement()");
1143 } // switch statementtype
1144 }
1145
1146 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1147 Reference *p_sig, TemplateInstance *p_templinst,
1148 bool p_timeout, TemplateInstance *p_fromclause,
1149 Reference *p_redirectval, Reference *p_redirectsender)
1150 : statementtype(p_st), my_sb(0)
1151 {
1152 switch(statementtype) {
1153 case S_CATCH:
1154 case S_CHECK_CATCH:
1155 if (((p_sig || p_templinst) && p_timeout) ||
1156 (p_sig && !p_templinst) || (!p_sig && p_templinst))
1157 FATAL_ERROR("Statement::Statement()");
1158 port_op.portref=p_ref;
1159 port_op.r.ctch.signature_ref=p_sig;
1160 port_op.r.ctch.signature=0;
1161 port_op.r.rcvpar=p_templinst;
1162 port_op.r.ctch.timeout=p_timeout;
1163 port_op.r.ctch.in_call=false;
1164 port_op.r.ctch.call_has_timer=false;
1165 port_op.r.fromclause=p_fromclause;
1166 port_op.r.redirect.value=p_redirectval;
1167 port_op.r.redirect.param=0;
1168 port_op.r.redirect.sender=p_redirectsender;
1169 break;
1170 default:
1171 FATAL_ERROR("Statement::Statement()");
1172 } // switch statementtype
1173 }
1174
1175 Statement::Statement(statementtype_t p_st, Reference *p_ref,
1176 TemplateInstance *p_fromclause,
1177 Reference *p_redirectsender)
1178 : statementtype(p_st), my_sb(0)
1179 {
1180 switch(statementtype) {
1181 case S_CHECK:
1182 port_op.portref=p_ref; // may be NULL for "any port.check"
1183 port_op.r.fromclause=p_fromclause;
1184 port_op.r.redirect.value=0;
1185 port_op.r.redirect.param=0;
1186 port_op.r.redirect.sender=p_redirectsender;
1187 break;
1188 default:
1189 FATAL_ERROR("Statement::Statement()");
1190 } // switch statementtype
1191 }
1192
1193 Statement::Statement(statementtype_t p_st, Reference *p_ref)
1194 : statementtype(p_st), my_sb(0)
1195 {
1196 switch(statementtype) {
1197 case S_CLEAR:
1198 case S_START_PORT:
1199 case S_STOP_PORT:
1200 case S_HALT:
1201 port_op.portref=p_ref;
1202 break;
1203 case S_STOP_TIMER:
1204 case S_TIMEOUT:
1205 timer_op.timerref=p_ref;
1206 break;
1207 default:
1208 FATAL_ERROR("Statement::Statement()");
1209 } // switch statementtype
1210 }
1211
1212 Statement::Statement(statementtype_t p_st, Value *p_compref,
1213 Ref_pard *p_funcinst)
1214 : statementtype(p_st), my_sb(0)
1215 {
1216 switch(statementtype) {
1217 case S_START_COMP:
1218 if(!p_compref || !p_funcinst)
1219 FATAL_ERROR("Statement::Statement()");
1220 comp_op.compref = p_compref;
1221 comp_op.funcinstref = p_funcinst;
1222 break;
1223 default:
1224 FATAL_ERROR("Statement::Statement()");
1225 } // switch statementtype
1226 }
1227
1228 Statement::Statement(statementtype_t p_st, Value *p_compref,
1229 Value *p_derefered_value, ParsedActualParameters *p_ap_list)
1230 : statementtype(p_st), my_sb(0)
1231 {
1232 switch(statementtype) {
1233 case S_START_COMP_REFD:
1234 if(!p_compref || !p_derefered_value || !p_ap_list)
1235 FATAL_ERROR("Statement::Statement()");
1236 comp_op.compref = p_compref;
1237 comp_op.derefered.value = p_derefered_value;
1238 comp_op.derefered.t_list1 = p_ap_list;
1239 break;
1240 default:
1241 FATAL_ERROR("Statement::Statement()");
1242 }
1243 }
1244
1245 Statement::Statement(statementtype_t p_st, Value *p_compref,
1246 TemplateInstance *p_donematch, Reference *p_redirect)
1247 : statementtype(p_st), my_sb(0)
1248 {
1249 switch (statementtype) {
1250 case S_DONE:
1251 if (!p_compref) FATAL_ERROR("Statement::Statement()");
1252 comp_op.compref = p_compref;
1253 comp_op.donereturn.donematch = p_donematch;
1254 comp_op.donereturn.redirect = p_redirect;
1255 break;
1256 default:
1257 FATAL_ERROR("Statement::Statement()");
1258 } // switch statementtype
1259 }
1260
1261 Statement::Statement(statementtype_t p_st, component_t p_anyall)
1262 : statementtype(p_st), my_sb(0)
1263 {
1264 switch (statementtype) {
1265 case S_DONE:
1266 case S_KILLED:
1267 comp_op.compref = 0;
1268 comp_op.any_or_all = p_anyall;
1269 break;
1270 default:
1271 FATAL_ERROR("Statement::Statement()");
1272 } // switch statementtype
1273 }
1274
1275 Statement::Statement(statementtype_t p_st,
1276 Value *p_compref1, Reference *p_portref1,
1277 Value *p_compref2, Reference *p_portref2)
1278 : statementtype(p_st), my_sb(0)
1279 {
1280 switch(statementtype) {
1281 case S_CONNECT:
1282 case S_MAP:
1283 case S_DISCONNECT:
1284 case S_UNMAP:
1285 if(!p_compref1 || !p_portref1 || !p_compref2 || !p_portref2)
1286 FATAL_ERROR("Statement::Statement()");
1287 config_op.compref1=p_compref1;
1288 config_op.portref1=p_portref1;
1289 config_op.compref2=p_compref2;
1290 config_op.portref2=p_portref2;
1291 break;
1292 default:
1293 FATAL_ERROR("Statement::Statement()");
1294 } // switch statementtype
1295 }
1296
1297 Statement::Statement(statementtype_t p_st, Ref_pard *p_ref, Value *p_val)
1298 : statementtype(p_st), my_sb(0)
1299 {
1300 switch(statementtype) {
1301 case S_TESTCASE_INSTANCE:
1302 if(!p_ref)
1303 FATAL_ERROR("Statement::Statement()");
1304 testcase_inst.tcref=p_ref;
1305 testcase_inst.timerval=p_val;
1306 break;
1307 default:
1308 FATAL_ERROR("Statement::Statement()");
1309 } // switch statementtype
1310 }
1311
1312 Statement::Statement(statementtype_t p_st, Value *p_derefered_value,
1313 TemplateInstances *p_ap_list, Value *p_val)
1314 : statementtype(p_st), my_sb(0)
1315 {
1316 switch(statementtype) {
1317 case S_TESTCASE_INSTANCE_REFD:
1318 if(!p_derefered_value) FATAL_ERROR("Statement::Statement()");
1319 execute_refd.value = p_derefered_value;
1320 execute_refd.t_list1 = p_ap_list;
1321 execute_refd.timerval = p_val;
1322 break;
1323 default:
1324 FATAL_ERROR("Statement::Statement()");
1325 }
1326 }
1327
1328 Statement::Statement(statementtype_t p_st, Value* p_val, Reference* p_ref)
1329 : statementtype(p_st), my_sb(0)
1330 {
1331 switch (statementtype) {
1332 case S_STRING2TTCN:
1333 case S_INT2ENUM:
1334 if (p_val==NULL || p_ref==NULL) {
1335 FATAL_ERROR("Statement::Statement()");
1336 }
1337 convert_op.val = p_val;
1338 convert_op.ref = p_ref;
1339 break;
1340 default:
1341 FATAL_ERROR("Statement::Statement()");
1342 }
1343 }
1344
1345 Statement::~Statement()
1346 {
1347 clean_up();
1348 }
1349
1350 Statement *Statement::clone() const
1351 {
1352 FATAL_ERROR("Statement::clone");
1353 }
1354
1355 void Statement::dump(unsigned int level) const
1356 {
1357 DEBUG(level, "Statement at %p, a(n) %s", (const void *)this,
1358 get_stmt_name());
1359 switch (statementtype) {
1360 case S_TESTCASE_INSTANCE:
1361 case S_TESTCASE_INSTANCE_REFD: {
1362 Common::Value *v = execute_refd.value;
1363 v->dump(level + 1);
1364 } break;
1365 case S_DEF:
1366 def->dump(level + 1);
1367 break;
1368 case S_ASSIGNMENT:
1369 ass->dump(level + 1);
1370 break;
1371 case S_BLOCK:
1372 block->dump(level + 1);
1373 break;
1374 case S_IF:
1375 if_stmt.ics->dump(level + 1);
1376 if (if_stmt.elseblock) if_stmt.elseblock->dump(level + 1);
1377 break;
1378 default:
1379 break;
1380 }
1381 }
1382
1383 size_t Statement::get_my_sb_index() const
1384 {
1385 switch (statementtype) {
1386 case S_LABEL:
1387 return label.stmt_idx;
1388 case S_GOTO:
1389 return go_to.stmt_idx;
1390 default:
1391 FATAL_ERROR("Statement::get_my_sb_index()");
1392 return 0;
1393 }
1394 }
1395
1396 const char *Statement::get_stmt_name() const
1397 {
1398 switch(statementtype) {
1399 case S_ERROR: return "<erroneous statement>";
1400 case S_START_UNDEF: return "start";
1401 case S_STOP_UNDEF: return "stop";
1402 case S_UNKNOWN_INSTANCE: return "function or altstep instance";
1403 case S_UNKNOWN_INVOKED: return "function or altstep type invocation";
1404 case S_DEF: return "definition";
1405 case S_ASSIGNMENT: return "assignment";
1406 case S_FUNCTION_INSTANCE: return "function instance";
1407 case S_FUNCTION_INVOKED: return "function type invocation";
1408 case S_BLOCK: return "statement block";
1409 case S_LOG: return "log";
1410 case S_LABEL: return "label";
1411 case S_GOTO: return "goto";
1412 case S_IF: return "if";
1413 case S_SELECT: return "select-case";
1414 case S_FOR: return "for";
1415 case S_WHILE: return "while";
1416 case S_DOWHILE: return "do-while";
1417 case S_BREAK: return "break";
1418 case S_CONTINUE: return "continue";
1419 case S_STOP_EXEC: return "stop";
1420 case S_STOP_TESTCASE: return "testcase.stop";
1421 case S_ALT: return "alt";
1422 case S_REPEAT: return "repeat";
1423 case S_INTERLEAVE: return "interleave";
1424 case S_ALTSTEP_INSTANCE: return "altstep instance";
1425 case S_ALTSTEP_INVOKED: return "altstep type invocation";
1426 case S_RETURN: return "return";
1427 case S_ACTIVATE:
1428 case S_ACTIVATE_REFD:
1429 return "activate";
1430 case S_DEACTIVATE: return "deactivate";
1431 case S_SEND: return "send";
1432 case S_CALL: return "call";
1433 case S_REPLY: return "reply";
1434 case S_RAISE: return "raise";
1435 case S_RECEIVE: return "receive";
1436 case S_TRIGGER: return "trigger";
1437 case S_GETCALL: return "getcall";
1438 case S_GETREPLY: return "getreply";
1439 case S_CATCH: return "catch";
1440 case S_CHECK: return "check";
1441 case S_CHECK_RECEIVE: return "check-receive";
1442 case S_CHECK_GETCALL: return "check-getcall";
1443 case S_CHECK_GETREPLY: return "check-getreply";
1444 case S_CHECK_CATCH: return "check-catch";
1445 case S_CLEAR: return "clear";
1446 case S_START_PORT: return "start port";
1447 case S_STOP_PORT: return "stop port";
1448 case S_HALT: return "halt";
1449 case S_START_COMP:
1450 case S_START_COMP_REFD:
1451 return "start test component";
1452 case S_STOP_COMP: return "stop test component";
1453 case S_DONE: return "done";
1454 case S_KILL: return "kill";
1455 case S_KILLED: return "killed";
1456 case S_CONNECT: return "connect";
1457 case S_MAP: return "map";
1458 case S_DISCONNECT: return "disconnect";
1459 case S_UNMAP: return "unmap";
1460 case S_START_TIMER: return "start timer";
1461 case S_STOP_TIMER: return "stop timer";
1462 case S_TIMEOUT: return "timeout";
1463 case S_SETVERDICT: return "setverdict";
1464 case S_ACTION: return "action";
1465 case S_TESTCASE_INSTANCE:
1466 case S_TESTCASE_INSTANCE_REFD:
1467 return "execute";
1468 case S_STRING2TTCN: return "string2ttcn";
1469 case S_INT2ENUM: return "int2enum";
1470 case S_START_PROFILER: return "@profiler.start";
1471 case S_STOP_PROFILER: return "@profiler.stop";
1472 default:
1473 FATAL_ERROR("Statement::get_stmt_name()");
1474 return "";
1475 } // switch statementtype
1476 }
1477
1478 const Identifier& Statement::get_labelid() const
1479 {
1480 switch (statementtype) {
1481 case S_LABEL:
1482 return *label.id;
1483 case S_GOTO:
1484 return *go_to.id;
1485 default:
1486 FATAL_ERROR("Statement::get_labelid()");
1487 return *label.id;
1488 }
1489 }
1490
1491 bool Statement::label_is_used() const
1492 {
1493 if (statementtype != S_LABEL) FATAL_ERROR("Statement::label_is_used()");
1494 return label.used;
1495 }
1496
1497 bool Statement::goto_jumps_forward() const
1498 {
1499 if (statementtype != S_GOTO) FATAL_ERROR("Statement::goto_jumps_forward()");
1500 return go_to.jumps_forward;
1501 }
1502
1503 const string& Statement::get_clabel()
1504 {
1505 if (statementtype != S_LABEL || !my_sb)
1506 FATAL_ERROR("Statement::get_clabel()");
1507 if (!label.clabel) label.clabel =
1508 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
1509 return *label.clabel;
1510 }
1511
1512 Definition *Statement::get_def() const
1513 {
1514 if (statementtype != S_DEF) FATAL_ERROR("Statement::get_def()");
1515 return def;
1516 }
1517
1518 AltGuards *Statement::get_ags() const
1519 {
1520 if (statementtype != S_ALT && statementtype != S_INTERLEAVE)
1521 FATAL_ERROR("Statement::get_ags()");
1522 return ags;
1523 }
1524
1525 StatementBlock *Statement::get_block() const
1526 {
1527 switch (statementtype) {
1528 case S_BLOCK:
1529 return block;
1530 case S_FOR:
1531 case S_WHILE:
1532 case S_DOWHILE:
1533 return loop.block;
1534 default:
1535 FATAL_ERROR("Statement::get_block()");
1536 return 0;
1537 }
1538 }
1539
1540 void Statement::set_my_scope(Scope *p_scope)
1541 {
1542 switch(statementtype) {
1543 case S_ERROR:
1544 case S_LABEL:
1545 case S_GOTO:
1546 case S_BREAK:
1547 case S_CONTINUE:
1548 case S_STOP_EXEC:
1549 case S_REPEAT:
1550 case S_START_PROFILER:
1551 case S_STOP_PROFILER:
1552 break;
1553 case S_START_UNDEF:
1554 case S_STOP_UNDEF:
1555 undefstartstop.ref->set_my_scope(p_scope);
1556 if (undefstartstop.val) undefstartstop.val->set_my_scope(p_scope);
1557 break;
1558 case S_UNKNOWN_INSTANCE:
1559 case S_FUNCTION_INSTANCE:
1560 case S_ALTSTEP_INSTANCE:
1561 case S_ACTIVATE:
1562 ref_pard->set_my_scope(p_scope);
1563 break;
1564 case S_DEF:
1565 def->set_my_scope(p_scope);
1566 break;
1567 case S_ASSIGNMENT:
1568 ass->set_my_scope(p_scope);
1569 break;
1570 case S_BLOCK:
1571 block->set_my_scope(p_scope);
1572 break;
1573 case S_LOG:
1574 case S_ACTION:
1575 case S_STOP_TESTCASE:
1576 if (logargs) logargs->set_my_scope(p_scope);
1577 break;
1578 case S_IF:
1579 if_stmt.ics->set_my_scope(p_scope);
1580 if(if_stmt.elseblock) if_stmt.elseblock->set_my_scope(p_scope);
1581 break;
1582 case S_SELECT:
1583 select.expr->set_my_scope(p_scope);
1584 select.scs->set_my_scope(p_scope);
1585 break;
1586 case S_FOR:
1587 if (loop.for_stmt.varinst) {
1588 loop.for_stmt.init_varinst->set_parent_scope(p_scope);
1589 loop.for_stmt.finalexpr->set_my_scope(loop.for_stmt.init_varinst);
1590 loop.for_stmt.step->set_my_scope(loop.for_stmt.init_varinst);
1591 loop.block->set_my_scope(loop.for_stmt.init_varinst);
1592 } else {
1593 loop.for_stmt.init_ass->set_my_scope(p_scope);
1594 loop.for_stmt.finalexpr->set_my_scope(p_scope);
1595 loop.for_stmt.step->set_my_scope(p_scope);
1596 loop.block->set_my_scope(p_scope);
1597 }
1598 break;
1599 case S_WHILE:
1600 case S_DOWHILE:
1601 loop.expr->set_my_scope(p_scope);
1602 loop.block->set_my_scope(p_scope);
1603 break;
1604 case S_ALT:
1605 case S_INTERLEAVE:
1606 ags->set_my_scope(p_scope);
1607 break;
1608 case S_RETURN:
1609 if (returnexpr.v) returnexpr.v->set_my_scope(p_scope);
1610 if (returnexpr.t) returnexpr.t->set_my_scope(p_scope);
1611 break;
1612 case S_DEACTIVATE:
1613 if (deactivate) deactivate->set_my_scope(p_scope);
1614 break;
1615 case S_SEND:
1616 port_op.portref->set_my_scope(p_scope);
1617 port_op.s.sendpar->set_my_scope(p_scope);
1618 if(port_op.s.toclause) port_op.s.toclause->set_my_scope(p_scope);
1619 break;
1620 case S_CALL:
1621 port_op.portref->set_my_scope(p_scope);
1622 port_op.s.sendpar->set_my_scope(p_scope);
1623 if(port_op.s.toclause) port_op.s.toclause->set_my_scope(p_scope);
1624 if(port_op.s.call.timer) port_op.s.call.timer->set_my_scope(p_scope);
1625 if(port_op.s.call.body) port_op.s.call.body->set_my_scope(p_scope);
1626 break;
1627 case S_REPLY:
1628 port_op.portref->set_my_scope(p_scope);
1629 port_op.s.sendpar->set_my_scope(p_scope);
1630 if(port_op.s.replyval) port_op.s.replyval->set_my_scope(p_scope);
1631 if(port_op.s.toclause) port_op.s.toclause->set_my_scope(p_scope);
1632 break;
1633 case S_RAISE:
1634 port_op.portref->set_my_scope(p_scope);
1635 port_op.s.raise.signature_ref->set_my_scope(p_scope);
1636 port_op.s.sendpar->set_my_scope(p_scope);
1637 if(port_op.s.toclause) port_op.s.toclause->set_my_scope(p_scope);
1638 break;
1639 case S_RECEIVE:
1640 case S_CHECK_RECEIVE:
1641 case S_TRIGGER:
1642 if(port_op.portref) port_op.portref->set_my_scope(p_scope);
1643 if(port_op.r.rcvpar) port_op.r.rcvpar->set_my_scope(p_scope);
1644 if(port_op.r.fromclause) port_op.r.fromclause->set_my_scope(p_scope);
1645 if(port_op.r.redirect.value)
1646 port_op.r.redirect.value->set_my_scope(p_scope);
1647 if(port_op.r.redirect.sender)
1648 port_op.r.redirect.sender->set_my_scope(p_scope);
1649 break;
1650 case S_GETCALL:
1651 case S_CHECK_GETCALL:
1652 if(port_op.portref) port_op.portref->set_my_scope(p_scope);
1653 if(port_op.r.rcvpar) port_op.r.rcvpar->set_my_scope(p_scope);
1654 if(port_op.r.fromclause) port_op.r.fromclause->set_my_scope(p_scope);
1655 if(port_op.r.redirect.param)
1656 port_op.r.redirect.param->set_my_scope(p_scope);
1657 if(port_op.r.redirect.sender)
1658 port_op.r.redirect.sender->set_my_scope(p_scope);
1659 break;
1660 case S_GETREPLY:
1661 case S_CHECK_GETREPLY:
1662 if(port_op.portref) port_op.portref->set_my_scope(p_scope);
1663 if(port_op.r.rcvpar) port_op.r.rcvpar->set_my_scope(p_scope);
1664 if(port_op.r.getreply_valuematch)
1665 port_op.r.getreply_valuematch->set_my_scope(p_scope);
1666 if(port_op.r.fromclause) port_op.r.fromclause->set_my_scope(p_scope);
1667 if(port_op.r.redirect.value)
1668 port_op.r.redirect.value->set_my_scope(p_scope);
1669 if(port_op.r.redirect.param)
1670 port_op.r.redirect.param->set_my_scope(p_scope);
1671 if(port_op.r.redirect.sender)
1672 port_op.r.redirect.sender->set_my_scope(p_scope);
1673 break;
1674 case S_CATCH:
1675 case S_CHECK_CATCH:
1676 if(port_op.portref) port_op.portref->set_my_scope(p_scope);
1677 if(port_op.r.ctch.signature_ref)
1678 port_op.r.ctch.signature_ref->set_my_scope(p_scope);
1679 if(port_op.r.rcvpar) port_op.r.rcvpar->set_my_scope(p_scope);
1680 if(port_op.r.fromclause) port_op.r.fromclause->set_my_scope(p_scope);
1681 if(port_op.r.redirect.value)
1682 port_op.r.redirect.value->set_my_scope(p_scope);
1683 if(port_op.r.redirect.sender)
1684 port_op.r.redirect.sender->set_my_scope(p_scope);
1685 break;
1686 case S_CHECK:
1687 if(port_op.portref) port_op.portref->set_my_scope(p_scope);
1688 if(port_op.r.fromclause) port_op.r.fromclause->set_my_scope(p_scope);
1689 if(port_op.r.redirect.sender)
1690 port_op.r.redirect.sender->set_my_scope(p_scope);
1691 break;
1692 case S_CLEAR:
1693 case S_START_PORT:
1694 case S_STOP_PORT:
1695 case S_HALT:
1696 if (port_op.portref) port_op.portref->set_my_scope(p_scope);
1697 break;
1698 case S_START_COMP:
1699 comp_op.compref->set_my_scope(p_scope);
1700 comp_op.funcinstref->set_my_scope(p_scope);
1701 break;
1702 case S_START_COMP_REFD:
1703 comp_op.compref->set_my_scope(p_scope);
1704 comp_op.derefered.value->set_my_scope(p_scope);
1705 comp_op.derefered.t_list1->set_my_scope(p_scope);
1706 break;
1707 case S_STOP_COMP:
1708 case S_KILL:
1709 case S_KILLED:
1710 if (comp_op.compref) comp_op.compref->set_my_scope(p_scope);
1711 break;
1712 case S_DONE:
1713 if (comp_op.compref) {
1714 comp_op.compref->set_my_scope(p_scope);
1715 if (comp_op.donereturn.donematch)
1716 comp_op.donereturn.donematch->set_my_scope(p_scope);
1717 if (comp_op.donereturn.redirect)
1718 comp_op.donereturn.redirect->set_my_scope(p_scope);
1719 }
1720 break;
1721 case S_CONNECT:
1722 case S_MAP:
1723 case S_DISCONNECT:
1724 case S_UNMAP:
1725 config_op.compref1->set_my_scope(p_scope);
1726 config_op.portref1->set_my_scope(p_scope);
1727 config_op.compref2->set_my_scope(p_scope);
1728 config_op.portref2->set_my_scope(p_scope);
1729 break;
1730 case S_START_TIMER:
1731 timer_op.timerref->set_my_scope(p_scope);
1732 if (timer_op.value) timer_op.value->set_my_scope(p_scope);
1733 break;
1734 case S_STOP_TIMER:
1735 case S_TIMEOUT:
1736 if (timer_op.timerref) timer_op.timerref->set_my_scope(p_scope);
1737 break;
1738 case S_SETVERDICT:
1739 setverdict.verdictval->set_my_scope(p_scope);
1740 if (setverdict.logargs)
1741 setverdict.logargs->set_my_scope(p_scope);
1742 break;
1743 case S_TESTCASE_INSTANCE:
1744 testcase_inst.tcref->set_my_scope(p_scope);
1745 if (testcase_inst.timerval) testcase_inst.timerval->set_my_scope(p_scope);
1746 break;
1747 case S_TESTCASE_INSTANCE_REFD:
1748 execute_refd.value->set_my_scope(p_scope);
1749 execute_refd.t_list1->set_my_scope(p_scope);
1750 if(execute_refd.timerval) execute_refd.timerval->set_my_scope(p_scope);
1751 break;
1752 case S_ACTIVATE_REFD:
1753 case S_UNKNOWN_INVOKED:
1754 case S_FUNCTION_INVOKED:
1755 case S_ALTSTEP_INVOKED:
1756 fau_refd.value->set_my_scope(p_scope);
1757 fau_refd.t_list1->set_my_scope(p_scope);
1758 break;
1759 case S_STRING2TTCN:
1760 case S_INT2ENUM:
1761 convert_op.val->set_my_scope(p_scope);
1762 convert_op.ref->set_my_scope(p_scope);
1763 break;
1764 default:
1765 FATAL_ERROR("Statement::set_my_scope()");
1766 } // switch statementtype
1767 }
1768
1769 void Statement::set_fullname(const string& p_fullname)
1770 {
1771 Node::set_fullname(p_fullname);
1772 switch (statementtype) {
1773 case S_ERROR:
1774 case S_LABEL:
1775 case S_GOTO:
1776 case S_BREAK:
1777 case S_CONTINUE:
1778 case S_STOP_EXEC:
1779 case S_REPEAT:
1780 case S_START_PROFILER:
1781 case S_STOP_PROFILER:
1782 break;
1783 case S_START_UNDEF:
1784 case S_STOP_UNDEF:
1785 undefstartstop.ref->set_fullname(p_fullname+".ref");
1786 if (undefstartstop.val)
1787 undefstartstop.val->set_fullname(p_fullname+".val");
1788 break;
1789 case S_UNKNOWN_INSTANCE:
1790 case S_FUNCTION_INSTANCE:
1791 case S_ALTSTEP_INSTANCE:
1792 case S_ACTIVATE:
1793 ref_pard->set_fullname(p_fullname+".ref");
1794 break;
1795 case S_DEF:
1796 def->set_fullname(p_fullname+".def");
1797 break;
1798 case S_ASSIGNMENT:
1799 ass->set_fullname(p_fullname+".ass");
1800 break;
1801 case S_BLOCK:
1802 block->set_fullname(p_fullname+".block");
1803 break;
1804 case S_LOG:
1805 case S_ACTION:
1806 case S_STOP_TESTCASE:
1807 if (logargs) logargs->set_fullname(p_fullname+".logargs");
1808 break;
1809 case S_IF:
1810 if_stmt.ics->set_fullname(p_fullname+".ifclauses");
1811 if (if_stmt.elseblock)
1812 if_stmt.elseblock->set_fullname(p_fullname+".elseblock");
1813 break;
1814 case S_SELECT:
1815 select.expr->set_fullname(p_fullname+".expr");
1816 select.scs->set_fullname(p_fullname+".scs");
1817 break;
1818 case S_FOR:
1819 if(loop.for_stmt.varinst)
1820 loop.for_stmt.init_varinst->set_fullname(p_fullname+".init");
1821 else
1822 loop.for_stmt.init_ass->set_fullname(p_fullname+".init");
1823 loop.for_stmt.finalexpr->set_fullname(p_fullname+".final");
1824 loop.for_stmt.step->set_fullname(p_fullname+".step");
1825 loop.block->set_fullname(p_fullname+".block");
1826 break;
1827 case S_WHILE:
1828 case S_DOWHILE:
1829 loop.expr->set_fullname(p_fullname+".expr");
1830 loop.block->set_fullname(p_fullname+".block");
1831 break;
1832 case S_ALT:
1833 case S_INTERLEAVE:
1834 ags->set_fullname(p_fullname+".ags");
1835 break;
1836 case S_RETURN:
1837 if (returnexpr.v) returnexpr.v->set_fullname(p_fullname+".returnexpr");
1838 if (returnexpr.t) returnexpr.t->set_fullname(p_fullname+".returnexpr");
1839 break;
1840 case S_DEACTIVATE:
1841 if (deactivate) deactivate->set_fullname(p_fullname+".deact");
1842 break;
1843 case S_SEND:
1844 port_op.portref->set_fullname(p_fullname+".portref");
1845 port_op.s.sendpar->set_fullname(p_fullname+".sendpar");
1846 if(port_op.s.toclause)
1847 port_op.s.toclause->set_fullname(p_fullname+".to");
1848 break;
1849 case S_CALL:
1850 port_op.portref->set_fullname(p_fullname+".portref");
1851 port_op.s.sendpar->set_fullname(p_fullname+".sendpar");
1852 if(port_op.s.toclause)
1853 port_op.s.toclause->set_fullname(p_fullname+".to");
1854 if(port_op.s.call.timer)
1855 port_op.s.call.timer->set_fullname(p_fullname+".timer");
1856 if(port_op.s.call.body)
1857 port_op.s.call.body->set_fullname(p_fullname+".body");
1858 break;
1859 case S_REPLY:
1860 port_op.portref->set_fullname(p_fullname+".portref");
1861 port_op.s.sendpar->set_fullname(p_fullname+".sendpar");
1862 if(port_op.s.replyval)
1863 port_op.s.replyval->set_fullname(p_fullname+".replyval");
1864 if(port_op.s.toclause)
1865 port_op.s.toclause->set_fullname(p_fullname+".to");
1866 break;
1867 case S_RAISE:
1868 port_op.portref->set_fullname(p_fullname+".portref");
1869 port_op.s.raise.signature_ref->set_fullname(p_fullname+".sign");
1870 port_op.s.sendpar->set_fullname(p_fullname+".sendpar");
1871 if(port_op.s.toclause)
1872 port_op.s.toclause->set_fullname(p_fullname+".to");
1873 break;
1874 case S_RECEIVE:
1875 case S_CHECK_RECEIVE:
1876 case S_TRIGGER:
1877 if(port_op.portref) port_op.portref->set_fullname(p_fullname+".portref");
1878 if(port_op.r.rcvpar)
1879 port_op.r.rcvpar->set_fullname(p_fullname+".rcvpar");
1880 if(port_op.r.fromclause)
1881 port_op.r.fromclause->set_fullname(p_fullname+".from");
1882 if(port_op.r.redirect.value)
1883 port_op.r.redirect.value->set_fullname(p_fullname+".redirval");
1884 if(port_op.r.redirect.sender)
1885 port_op.r.redirect.sender->set_fullname(p_fullname+".redirsender");
1886 break;
1887 case S_GETCALL:
1888 case S_CHECK_GETCALL:
1889 if(port_op.portref) port_op.portref->set_fullname(p_fullname+".portref");
1890 if(port_op.r.rcvpar)
1891 port_op.r.rcvpar->set_fullname(p_fullname+".rcvpar");
1892 if(port_op.r.fromclause)
1893 port_op.r.fromclause->set_fullname(p_fullname+".from");
1894 if(port_op.r.redirect.param)
1895 port_op.r.redirect.param->set_fullname(p_fullname+".pars");
1896 if(port_op.r.redirect.sender)
1897 port_op.r.redirect.sender->set_fullname(p_fullname+".redirsender");
1898 break;
1899 case S_GETREPLY:
1900 case S_CHECK_GETREPLY:
1901 if(port_op.portref) port_op.portref->set_fullname(p_fullname+".portref");
1902 if(port_op.r.rcvpar)
1903 port_op.r.rcvpar->set_fullname(p_fullname+".rcvpar");
1904 if(port_op.r.getreply_valuematch)
1905 port_op.r.getreply_valuematch->set_fullname(p_fullname+".valmatch");
1906 if(port_op.r.fromclause)
1907 port_op.r.fromclause->set_fullname(p_fullname+".from");
1908 if(port_op.r.redirect.value)
1909 port_op.r.redirect.value->set_fullname(p_fullname+".redirval");
1910 if(port_op.r.redirect.param)
1911 port_op.r.redirect.param->set_fullname(p_fullname+".pars");
1912 if(port_op.r.redirect.sender)
1913 port_op.r.redirect.sender->set_fullname(p_fullname+".redirsender");
1914 break;
1915 case S_CATCH:
1916 case S_CHECK_CATCH:
1917 if(port_op.portref) port_op.portref->set_fullname(p_fullname+".portref");
1918 if(port_op.r.ctch.signature_ref)
1919 port_op.r.ctch.signature_ref->set_fullname(p_fullname+".sign");
1920 if(port_op.r.rcvpar)
1921 port_op.r.rcvpar->set_fullname(p_fullname+".rcvpar");
1922 if(port_op.r.fromclause)
1923 port_op.r.fromclause->set_fullname(p_fullname+".from");
1924 if(port_op.r.redirect.value)
1925 port_op.r.redirect.value->set_fullname(p_fullname+".redirval");
1926 if(port_op.r.redirect.sender)
1927 port_op.r.redirect.sender->set_fullname(p_fullname+".redirsender");
1928 break;
1929 case S_CHECK:
1930 if(port_op.portref) port_op.portref->set_fullname(p_fullname+".portref");
1931 if(port_op.r.fromclause)
1932 port_op.r.fromclause->set_fullname(p_fullname+".from");
1933 if(port_op.r.redirect.sender)
1934 port_op.r.redirect.sender->set_fullname(p_fullname+".redirsender");
1935 break;
1936 case S_CLEAR:
1937 case S_START_PORT:
1938 case S_STOP_PORT:
1939 case S_HALT:
1940 if(port_op.portref) port_op.portref->set_fullname(p_fullname+".portref");
1941 break;
1942 case S_START_COMP:
1943 comp_op.compref->set_fullname(p_fullname+".compref");
1944 comp_op.funcinstref->set_fullname(p_fullname+".funcref");
1945 break;
1946 case S_START_COMP_REFD:
1947 comp_op.compref->set_fullname(p_fullname+".compref");
1948 comp_op.derefered.value->set_fullname(p_fullname+".funcref");
1949 comp_op.derefered.t_list1->set_fullname(p_fullname+".<parameters>");
1950 break;
1951 case S_STOP_COMP:
1952 case S_KILL:
1953 case S_KILLED:
1954 if (comp_op.compref) comp_op.compref->set_fullname(p_fullname+".compref");
1955 break;
1956 case S_DONE:
1957 if(comp_op.compref) {
1958 comp_op.compref->set_fullname(p_fullname+".compref");
1959 if(comp_op.donereturn.donematch)
1960 comp_op.donereturn.donematch->set_fullname(p_fullname+".donematch");
1961 if(comp_op.donereturn.redirect)
1962 comp_op.donereturn.redirect->set_fullname(p_fullname+".redir");
1963 }
1964 break;
1965 case S_CONNECT:
1966 case S_MAP:
1967 case S_DISCONNECT:
1968 case S_UNMAP:
1969 config_op.compref1->set_fullname(p_fullname+".compref1");
1970 config_op.portref1->set_fullname(p_fullname+".portref1");
1971 config_op.compref2->set_fullname(p_fullname+".compref2");
1972 config_op.portref2->set_fullname(p_fullname+".portref2");
1973 break;
1974 case S_START_TIMER:
1975 timer_op.timerref->set_fullname(p_fullname+".timerref");
1976 if(timer_op.value) timer_op.value->set_fullname(p_fullname+".timerval");
1977 break;
1978 case S_STOP_TIMER:
1979 case S_TIMEOUT:
1980 if (timer_op.timerref)
1981 timer_op.timerref->set_fullname(p_fullname+".timerref");
1982 break;
1983 case S_SETVERDICT:
1984 setverdict.verdictval->set_fullname(p_fullname+".verdictval");
1985 if (setverdict.logargs)
1986 setverdict.logargs->set_fullname(p_fullname+".verdictreason");
1987 break;
1988 case S_TESTCASE_INSTANCE:
1989 testcase_inst.tcref->set_fullname(p_fullname+".tcref");
1990 if (testcase_inst.timerval)
1991 testcase_inst.timerval->set_fullname(p_fullname+".timerval");
1992 break;
1993 case S_TESTCASE_INSTANCE_REFD:
1994 execute_refd.value->set_fullname(p_fullname+".tcref");
1995 execute_refd.t_list1->set_fullname(p_fullname+".<parameters>");
1996 if(execute_refd.timerval)
1997 execute_refd.timerval->set_fullname(p_fullname+".timerval");
1998 break;
1999 case S_ACTIVATE_REFD:
2000 case S_UNKNOWN_INVOKED:
2001 case S_FUNCTION_INVOKED:
2002 case S_ALTSTEP_INVOKED:
2003 fau_refd.value->set_fullname(p_fullname+".ref");
2004 fau_refd.t_list1->set_fullname(p_fullname+".<parameters>");
2005 break;
2006 case S_STRING2TTCN:
2007 case S_INT2ENUM:
2008 convert_op.val->set_fullname(p_fullname+".ti");
2009 convert_op.ref->set_fullname(p_fullname+".ref");
2010 break;
2011 default:
2012 FATAL_ERROR("Statement::set_fullname()");
2013 } // switch statementtype
2014 }
2015
2016 void Statement::set_my_sb(StatementBlock *p_sb, size_t p_index)
2017 {
2018 my_sb=p_sb;
2019 switch(statementtype) {
2020 case S_BLOCK:
2021 block->set_my_sb(p_sb, p_index);
2022 break;
2023 case S_LABEL:
2024 label.stmt_idx = p_index;
2025 break;
2026 case S_GOTO:
2027 go_to.stmt_idx = p_index;
2028 break;
2029 case S_IF:
2030 if_stmt.ics->set_my_sb(p_sb, p_index);
2031 if(if_stmt.elseblock) if_stmt.elseblock->set_my_sb(p_sb, p_index);
2032 break;
2033 case S_SELECT:
2034 select.scs->set_my_sb(p_sb, p_index);
2035 break;
2036 case S_FOR:
2037 case S_WHILE:
2038 case S_DOWHILE:
2039 loop.block->set_my_sb(p_sb, p_index);
2040 break;
2041 case S_ALT:
2042 case S_INTERLEAVE:
2043 ags->set_my_sb(p_sb, p_index);
2044 break;
2045 case S_CALL:
2046 if(port_op.s.call.body) port_op.s.call.body->set_my_sb(p_sb, p_index);
2047 break;
2048 default:
2049 break;
2050 } // switch statementtype
2051 }
2052
2053 void Statement::set_my_def(Definition *p_def)
2054 {
2055 switch (statementtype) {
2056 case S_BLOCK:
2057 block->set_my_def(p_def);
2058 break;
2059 case S_IF:
2060 if_stmt.ics->set_my_def(p_def);
2061 if (if_stmt.elseblock) if_stmt.elseblock->set_my_def(p_def);
2062 break;
2063 case S_SELECT:
2064 select.scs->set_my_def(p_def);
2065 break;
2066 case S_FOR:
2067 case S_WHILE:
2068 case S_DOWHILE:
2069 loop.block->set_my_def(p_def);
2070 break;
2071 case S_ALT:
2072 case S_INTERLEAVE:
2073 ags->set_my_def(p_def);
2074 break;
2075 case S_CALL:
2076 if (port_op.s.call.body) port_op.s.call.body->set_my_def(p_def);
2077 break;
2078 default:
2079 break;
2080 } // switch statementtype
2081 }
2082
2083 void Statement::set_my_ags(AltGuards *p_ags)
2084 {
2085 switch (statementtype) {
2086 case S_BLOCK:
2087 block->set_my_ags(p_ags);
2088 break;
2089 case S_IF:
2090 if_stmt.ics->set_my_ags(p_ags);
2091 if (if_stmt.elseblock) if_stmt.elseblock->set_my_ags(p_ags);
2092 break;
2093 case S_SELECT:
2094 select.scs->set_my_ags(p_ags);
2095 break;
2096 case S_FOR:
2097 case S_WHILE:
2098 case S_DOWHILE:
2099 loop.block->set_my_ags(p_ags);
2100 break;
2101 case S_REPEAT:
2102 ags = p_ags;
2103 break;
2104 default:
2105 break;
2106 } // switch statementtype
2107 }
2108
2109 void Statement::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
2110 {
2111 switch (statementtype) {
2112 case S_BLOCK:
2113 block->set_my_laic_stmt(p_ags, p_loop_stmt);
2114 break;
2115 case S_IF:
2116 if_stmt.ics->set_my_laic_stmt(p_ags, p_loop_stmt);
2117 if (if_stmt.elseblock)
2118 if_stmt.elseblock->set_my_laic_stmt(p_ags, p_loop_stmt);
2119 break;
2120 case S_SELECT:
2121 select.scs->set_my_laic_stmt(p_ags, p_loop_stmt);
2122 break;
2123 case S_ALT:
2124 case S_INTERLEAVE:
2125 if (p_loop_stmt)
2126 ags->set_my_laic_stmt(0, p_loop_stmt); // ags is set later
2127 break;
2128 case S_CALL:
2129 if (p_loop_stmt && port_op.s.call.body)
2130 port_op.s.call.body->set_my_laic_stmt(0, p_loop_stmt);
2131 // ags is set later
2132 break;
2133 case S_BREAK:
2134 case S_CONTINUE:
2135 if (p_loop_stmt)
2136 brk_cnt.loop_stmt=p_loop_stmt;
2137 brk_cnt.ags=p_ags;
2138 break;
2139 default:
2140 break;
2141 } // switch statementtype
2142 }
2143
2144 /** \todo handle blocks, loops and conditional statements
2145 * (i.e. investigate their last statements within the block) */
2146 bool Statement::is_terminating() const
2147 {
2148 switch (statementtype) {
2149 case S_GOTO:
2150 case S_BREAK:
2151 case S_CONTINUE:
2152 case S_STOP_EXEC:
2153 case S_STOP_TESTCASE:
2154 case S_REPEAT:
2155 case S_RETURN:
2156 return true;
2157 case S_STOP_COMP:
2158 case S_KILL:
2159 // checking for self.stop, self.kill, mtc.stop and mtc.kill
2160 if (comp_op.compref) {
2161 Value *v_last = comp_op.compref->get_value_refd_last();
2162 if (v_last->get_valuetype() == Value::V_EXPR) {
2163 switch (v_last->get_optype()) {
2164 case Value::OPTYPE_COMP_SELF:
2165 case Value::OPTYPE_COMP_MTC:
2166 return true;
2167 default:
2168 break;
2169 }
2170 }
2171 }
2172 return false;
2173 case S_WHILE:
2174 case S_DOWHILE:
2175 if(!loop.expr->is_unfoldable() && loop.expr->get_val_bool()) {
2176 return !loop.has_brk; // not endless loop if it has a break
2177 }
2178 return false;
2179 default:
2180 return false;
2181 }
2182 }
2183
2184 StatementBlock::returnstatus_t Statement::has_return() const
2185 {
2186 switch (statementtype) {
2187 case S_BLOCK:
2188 return block->has_return();
2189 case S_IF:
2190 return if_stmt.ics->has_return(if_stmt.elseblock);
2191 case S_SELECT:
2192 return select.scs->has_return();
2193 case S_FOR:
2194 case S_WHILE:
2195 if (loop.block->has_return() == StatementBlock::RS_NO)
2196 return StatementBlock::RS_NO;
2197 else return StatementBlock::RS_MAYBE;
2198 case S_DOWHILE:
2199 return loop.block->has_return();
2200 case S_ALT: {
2201 StatementBlock::returnstatus_t ret_val = ags->has_return();
2202 if (ret_val == StatementBlock::RS_YES && !ags->has_else()) {
2203 // the invoked defaults may skip the entire statement
2204 ret_val = StatementBlock::RS_MAYBE;
2205 }
2206 return ret_val; }
2207 case S_CALL:
2208 if (port_op.s.call.body) return port_op.s.call.body->has_return();
2209 else return StatementBlock::RS_NO;
2210 default:
2211 if (is_terminating()) return StatementBlock::RS_YES;
2212 else return StatementBlock::RS_NO;
2213 }
2214 }
2215
2216 bool Statement::is_receiving_stmt() const
2217 {
2218 switch (statementtype) {
2219 case S_ALT:
2220 case S_INTERLEAVE:
2221 case S_ALTSTEP_INSTANCE:
2222 case S_ALTSTEP_INVOKED:
2223 case S_RECEIVE:
2224 case S_CHECK_RECEIVE:
2225 case S_TRIGGER:
2226 case S_GETCALL:
2227 case S_CHECK_GETCALL:
2228 case S_GETREPLY:
2229 case S_CHECK_GETREPLY:
2230 case S_CATCH:
2231 case S_CHECK_CATCH:
2232 case S_CHECK:
2233 case S_DONE:
2234 case S_KILLED:
2235 case S_TIMEOUT:
2236 return true;
2237 default:
2238 return false;
2239 } // switch statementtype
2240 }
2241
2242 bool Statement::has_receiving_stmt() const
2243 {
2244 switch (statementtype) {
2245 case S_DEF:
2246 case S_ASSIGNMENT:
2247 case S_FUNCTION_INSTANCE:
2248 case S_FUNCTION_INVOKED:
2249 case S_LOG:
2250 case S_STRING2TTCN:
2251 case S_ACTION:
2252 case S_LABEL:
2253 case S_GOTO:
2254 case S_BREAK:
2255 case S_CONTINUE:
2256 case S_STOP_EXEC:
2257 case S_STOP_TESTCASE:
2258 case S_REPEAT:
2259 case S_RETURN:
2260 case S_ACTIVATE:
2261 case S_ACTIVATE_REFD:
2262 case S_DEACTIVATE:
2263 case S_SEND:
2264 case S_REPLY:
2265 case S_RAISE:
2266 case S_CLEAR:
2267 case S_START_PORT:
2268 case S_STOP_PORT:
2269 case S_HALT:
2270 case S_START_COMP:
2271 case S_START_COMP_REFD:
2272 case S_STOP_COMP:
2273 case S_KILL:
2274 case S_CONNECT:
2275 case S_DISCONNECT:
2276 case S_MAP:
2277 case S_UNMAP:
2278 case S_START_TIMER:
2279 case S_STOP_TIMER:
2280 case S_SETVERDICT:
2281 case S_TESTCASE_INSTANCE:
2282 case S_TESTCASE_INSTANCE_REFD:
2283 case S_START_PROFILER:
2284 case S_STOP_PROFILER:
2285 case S_INT2ENUM:
2286 return false;
2287 case S_ALT:
2288 case S_INTERLEAVE:
2289 case S_ALTSTEP_INSTANCE:
2290 case S_ALTSTEP_INVOKED:
2291 case S_RECEIVE:
2292 case S_CHECK_RECEIVE:
2293 case S_TRIGGER:
2294 case S_GETCALL:
2295 case S_CHECK_GETCALL:
2296 case S_GETREPLY:
2297 case S_CHECK_GETREPLY:
2298 case S_CATCH:
2299 case S_CHECK_CATCH:
2300 case S_CHECK:
2301 case S_DONE:
2302 case S_KILLED:
2303 case S_TIMEOUT:
2304 return true;
2305 case S_BLOCK:
2306 return block->has_receiving_stmt();
2307 case S_IF:
2308 return if_stmt.ics->has_receiving_stmt()
2309 || (if_stmt.elseblock && if_stmt.elseblock->has_receiving_stmt());
2310 case S_SELECT:
2311 return select.scs->has_receiving_stmt();
2312 case S_FOR:
2313 case S_WHILE:
2314 case S_DOWHILE:
2315 return loop.block->has_receiving_stmt();
2316 case S_CALL:
2317 return port_op.s.call.body && port_op.s.call.body->has_receiving_stmt();
2318 case S_ERROR:
2319 case S_START_UNDEF:
2320 case S_STOP_UNDEF:
2321 case S_UNKNOWN_INSTANCE:
2322 case S_UNKNOWN_INVOKED:
2323 default:
2324 FATAL_ERROR("Statement::has_receiving_stmt()");
2325 } // switch statementtype
2326 }
2327
2328 bool Statement::can_repeat() const
2329 {
2330 switch (statementtype) {
2331 case S_TRIGGER:
2332 case S_DONE:
2333 case S_KILLED:
2334 return true;
2335 case S_RECEIVE:
2336 case S_CHECK_RECEIVE:
2337 case S_GETCALL:
2338 case S_CHECK_GETCALL:
2339 case S_GETREPLY:
2340 case S_CHECK_GETREPLY:
2341 case S_CATCH:
2342 case S_CHECK_CATCH:
2343 case S_CHECK:
2344 case S_TIMEOUT:
2345 return false;
2346 default:
2347 FATAL_ERROR("Statement::can_repeat()");
2348 } // switch statementtype
2349 }
2350
2351 void Statement::chk()
2352 {
2353 switch (statementtype) {
2354 case S_ERROR:
2355 break;
2356 case S_START_UNDEF:
2357 chk_start_undef();
2358 break;
2359 case S_STOP_UNDEF:
2360 chk_stop_undef();
2361 break;
2362 case S_UNKNOWN_INSTANCE:
2363 chk_unknown_instance();
2364 break;
2365 case S_UNKNOWN_INVOKED:
2366 case S_FUNCTION_INVOKED:
2367 case S_ALTSTEP_INVOKED:
2368 chk_unknown_invoke();
2369 break;
2370 case S_DEF:
2371 def->chk();
2372 my_sb->register_def(def);
2373 break;
2374 case S_ASSIGNMENT:
2375 chk_assignment();
2376 break;
2377 case S_FUNCTION_INSTANCE:
2378 chk_function();
2379 break;
2380 case S_BLOCK:
2381 chk_block();
2382 break;
2383 case S_LOG:
2384 case S_ACTION:
2385 case S_STOP_TESTCASE:
2386 chk_log_action(logargs);
2387 break;
2388 case S_LABEL:
2389 // do nothing
2390 break;
2391 case S_GOTO:
2392 chk_goto();
2393 break;
2394 case S_IF:
2395 chk_if();
2396 break;
2397 case S_SELECT:
2398 chk_select();
2399 break;
2400 case S_FOR:
2401 chk_for();
2402 break;
2403 case S_WHILE:
2404 chk_while();
2405 break;
2406 case S_DOWHILE:
2407 chk_do_while();
2408 break;
2409 case S_BREAK:
2410 chk_break();
2411 break;
2412 case S_CONTINUE:
2413 chk_continue();
2414 break;
2415 case S_STOP_EXEC:
2416 // do nothing
2417 break;
2418 case S_ALT:
2419 chk_alt();
2420 break;
2421 case S_REPEAT:
2422 chk_repeat();
2423 break;
2424 case S_INTERLEAVE:
2425 chk_interleave();
2426 break;
2427 case S_ALTSTEP_INSTANCE:
2428 chk_altstep();
2429 break;
2430 case S_RETURN:
2431 chk_return();
2432 break;
2433 case S_ACTIVATE:
2434 chk_activate();
2435 break;
2436 case S_ACTIVATE_REFD:
2437 chk_activate_refd();
2438 break;
2439 case S_DEACTIVATE:
2440 chk_deactivate();
2441 break;
2442 case S_SEND:
2443 chk_send();
2444 break;
2445 case S_CALL:
2446 chk_call();
2447 break;
2448 case S_REPLY:
2449 chk_reply();
2450 break;
2451 case S_RAISE:
2452 chk_raise();
2453 break;
2454 case S_RECEIVE:
2455 case S_CHECK_RECEIVE:
2456 case S_TRIGGER:
2457 chk_receive();
2458 break;
2459 case S_GETCALL:
2460 case S_CHECK_GETCALL:
2461 chk_getcall();
2462 break;
2463 case S_GETREPLY:
2464 case S_CHECK_GETREPLY:
2465 chk_getreply();
2466 break;
2467 case S_CATCH:
2468 case S_CHECK_CATCH:
2469 chk_catch();
2470 break;
2471 case S_CHECK:
2472 chk_check();
2473 break;
2474 case S_CLEAR:
2475 chk_clear();
2476 break;
2477 case S_START_PORT:
2478 case S_STOP_PORT:
2479 case S_HALT:
2480 chk_start_stop_port();
2481 break;
2482 case S_START_COMP:
2483 chk_start_comp();
2484 break;
2485 case S_START_COMP_REFD:
2486 chk_start_comp_refd();
2487 break;
2488 case S_STOP_COMP:
2489 case S_KILL:
2490 chk_stop_kill_comp();
2491 break;
2492 case S_DONE:
2493 chk_done();
2494 break;
2495 case S_KILLED:
2496 chk_killed();
2497 break;
2498 case S_CONNECT:
2499 case S_DISCONNECT:
2500 chk_connect();
2501 break;
2502 case S_MAP:
2503 case S_UNMAP:
2504 chk_map();
2505 break;
2506 case S_START_TIMER:
2507 chk_start_timer();
2508 break;
2509 case S_STOP_TIMER:
2510 case S_TIMEOUT:
2511 chk_stop_timer_timeout();
2512 break;
2513 case S_SETVERDICT:
2514 chk_setverdict();
2515 chk_log_action(setverdict.logargs); // for checking verdictreason
2516 break;
2517 case S_TESTCASE_INSTANCE:
2518 chk_execute();
2519 break;
2520 case S_TESTCASE_INSTANCE_REFD:
2521 chk_execute_refd();
2522 break;
2523 case S_STRING2TTCN:
2524 chk_string2ttcn();
2525 break;
2526 case S_INT2ENUM:
2527 chk_int2enum();
2528 break;
2529 case S_START_PROFILER:
2530 case S_STOP_PROFILER:
2531 // do nothing
2532 break;
2533 default:
2534 FATAL_ERROR("Statement::chk()");
2535 } // switch statementtype
2536 }
2537
2538 void Statement::chk_string2ttcn()
2539 {
2540 Error_Context cntxt(this, "In string2ttcn() statement");
2541 convert_op.val->chk_expr_type(Type::T_CSTR, "charstring", Type::EXPECTED_DYNAMIC_VALUE);
2542 ///
2543 Common::Assignment* refd_ass = convert_op.ref->get_refd_assignment();
2544 if (refd_ass==NULL) {
2545 error("Could not determine the assignment for second parameter");
2546 goto error;
2547 }
2548 switch (refd_ass->get_asstype()) {
2549 case Definition::A_PAR_VAL_IN:
2550 case Definition::A_PAR_TEMPL_IN:
2551 refd_ass->use_as_lvalue(*convert_op.ref);
2552 case Definition::A_VAR:
2553 case Definition::A_VAR_TEMPLATE:
2554 case Definition::A_PAR_VAL_OUT:
2555 case Definition::A_PAR_VAL_INOUT:
2556 case Definition::A_PAR_TEMPL_OUT:
2557 case Definition::A_PAR_TEMPL_INOUT:
2558 // valid assignment types
2559 break;
2560 default:
2561 convert_op.ref->error("Reference to '%s' cannot be used as the second parameter", refd_ass->get_assname());
2562 goto error;
2563 }
2564 return;
2565 error:
2566 delete convert_op.val;
2567 delete convert_op.ref;
2568 statementtype = S_ERROR;
2569 }
2570
2571 void Statement::chk_int2enum()
2572 {
2573 Error_Context cntxt(this, "In int2enum() statement");
2574 convert_op.val->chk_expr_type(Type::T_INT, "integer", Type::EXPECTED_DYNAMIC_VALUE);
2575 ///
2576 Common::Assignment* refd_ass = convert_op.ref->get_refd_assignment();
2577 if (refd_ass==NULL) {
2578 error("Could not determine the assignment for second parameter");
2579 goto error;
2580 }
2581 if (Type::T_ENUM_T != convert_op.ref->chk_variable_ref()->get_type_refd_last()->get_typetype_ttcn3()) {
2582 convert_op.ref->error("A reference to variable or value parameter of "
2583 "type enumerated was expected");
2584 goto error;
2585 }
2586 return;
2587 error:
2588 delete convert_op.val;
2589 delete convert_op.ref;
2590 statementtype = S_ERROR;
2591 }
2592
2593 void Statement::chk_allowed_interleave()
2594 {
2595 switch (statementtype) {
2596 case S_BLOCK:
2597 block->chk_allowed_interleave();
2598 break;
2599 case S_LABEL:
2600 error("Label statement is not allowed within an interleave statement");
2601 break;
2602 case S_GOTO:
2603 error("Goto statement is not allowed within an interleave statement");
2604 break;
2605 case S_IF:
2606 if_stmt.ics->chk_allowed_interleave();
2607 if (if_stmt.elseblock) if_stmt.elseblock->chk_allowed_interleave();
2608 break;
2609 case S_SELECT:
2610 select.scs->chk_allowed_interleave();
2611 break;
2612 case S_FOR:
2613 case S_WHILE:
2614 case S_DOWHILE:
2615 loop.block->chk_allowed_interleave();
2616 break;
2617 case S_ALT:
2618 ags->chk_allowed_interleave();
2619 break;
2620 case S_REPEAT:
2621 error("Repeat statement is not allowed within an interleave statement");
2622 break;
2623 case S_ALTSTEP_INSTANCE:
2624 error("Invocation of an altstep is not allowed within an interleave "
2625 "statement");
2626 break;
2627 case S_ALTSTEP_INVOKED:
2628 error("Invocation of an altstep type is not allowed within an interleave"
2629 "statement");
2630 break;
2631 case S_RETURN:
2632 error("Return statement is not allowed within an interleave statement");
2633 break;
2634 case S_CALL:
2635 if (port_op.s.call.body) port_op.s.call.body->chk_allowed_interleave();
2636 break;
2637 default:
2638 // the other statements are allowed
2639 break;
2640 }
2641 }
2642
2643 void Statement::chk_start_undef()
2644 {
2645 Ref_base *t_ref = undefstartstop.ref;
2646 Value *t_val = undefstartstop.val;
2647 Common::Assignment *t_ass;
2648 {
2649 Error_Context cntxt(this, "In start statement");
2650 t_ass = t_ref->get_refd_assignment();
2651 }
2652 if (!t_ass) goto error;
2653 switch (t_ass->get_asstype()) {
2654 case Definition::A_PORT:
2655 case Definition::A_PAR_PORT:
2656 statementtype = S_START_PORT;
2657 port_op.portref = dynamic_cast<Reference*>(t_ref);
2658 if (!port_op.portref) goto error;
2659 if (t_val) {
2660 t_val->error("Start port operation cannot have argument");
2661 delete t_val;
2662 }
2663 chk_start_stop_port();
2664 break;
2665 case Definition::A_TIMER:
2666 case Definition::A_PAR_TIMER:
2667 statementtype = S_START_TIMER;
2668 timer_op.timerref = dynamic_cast<Reference*>(t_ref);
2669 if (!timer_op.timerref) goto error;
2670 timer_op.value = t_val;
2671 chk_start_timer();
2672 break;
2673 case Definition::A_CONST:
2674 case Definition::A_EXT_CONST:
2675 case Definition::A_MODULEPAR:
2676 case Definition::A_VAR:
2677 case Definition::A_FUNCTION_RVAL:
2678 case Definition::A_EXT_FUNCTION_RVAL:
2679 case Definition::A_PAR_VAL_IN:
2680 case Definition::A_PAR_VAL_OUT:
2681 case Definition::A_PAR_VAL_INOUT:
2682 statementtype = S_START_COMP;
2683 if (!t_val) {
2684 error("The argument of start operation is missing, although it cannot "
2685 "be a start timer or start port operation");
2686 goto error;
2687 } else if (t_val->get_valuetype() != Value::V_REFD) {
2688 t_val->error("The argument of start operation is not a function, "
2689 "although it cannot be a start timer or start port operation");
2690 goto error;
2691 } else {
2692 comp_op.funcinstref = t_val->steal_ttcn_ref_base();
2693 delete t_val;
2694 }
2695 comp_op.compref = new Value(Value::V_REFD, t_ref);
2696 comp_op.compref->set_my_scope(t_ref->get_my_scope());
2697 comp_op.compref->set_fullname(t_ref->get_fullname());
2698 comp_op.compref->set_location(*t_ref);
2699 chk_start_comp();
2700 break;
2701 default:
2702 t_ref->error("Port, timer or component reference was expected as the "
2703 "operand of start operation instead of %s",
2704 t_ass->get_description().c_str());
2705 goto error;
2706 }
2707 return;
2708 error:
2709 delete t_ref;
2710 delete t_val;
2711 statementtype = S_ERROR;
2712 }
2713
2714 void Statement::chk_stop_undef()
2715 {
2716 Ref_base *t_ref = undefstartstop.ref;
2717 Common::Assignment *t_ass;
2718 {
2719 Error_Context cntxt(this, "In stop statement");
2720 t_ass = t_ref->get_refd_assignment();
2721 }
2722 if (!t_ass) goto error;
2723 // Determine what it is that we are trying to stop; change statementtype
2724 switch (t_ass->get_asstype()) {
2725 case Definition::A_PORT:
2726 case Definition::A_PAR_PORT:
2727 statementtype = S_STOP_PORT;
2728 port_op.portref = dynamic_cast<Reference*>(t_ref);
2729 if (!port_op.portref) goto error;
2730 chk_start_stop_port();
2731 break;
2732 case Definition::A_TIMER:
2733 case Definition::A_PAR_TIMER:
2734 statementtype = S_STOP_TIMER;
2735 timer_op.timerref = dynamic_cast<Reference*>(t_ref);
2736 if (!timer_op.timerref) goto error;
2737 timer_op.value = 0;
2738 chk_stop_timer_timeout();
2739 break;
2740 case Definition::A_CONST:
2741 case Definition::A_EXT_CONST:
2742 case Definition::A_MODULEPAR:
2743 case Definition::A_VAR:
2744 case Definition::A_FUNCTION_RVAL:
2745 case Definition::A_EXT_FUNCTION_RVAL:
2746 case Definition::A_PAR_VAL_IN:
2747 case Definition::A_PAR_VAL_OUT:
2748 case Definition::A_PAR_VAL_INOUT:
2749 statementtype = S_STOP_COMP;
2750 comp_op.compref = new Value(Value::V_REFD, t_ref);
2751 comp_op.compref->set_my_scope(t_ref->get_my_scope());
2752 comp_op.compref->set_fullname(t_ref->get_fullname());
2753 comp_op.compref->set_location(*t_ref);
2754 chk_stop_kill_comp();
2755 break;
2756 default:
2757 t_ref->error("Port, timer or component reference was expected as the "
2758 "operand of stop operation instead of %s",
2759 t_ass->get_description().c_str());
2760 goto error;
2761 }
2762 return;
2763 error:
2764 delete t_ref;
2765 statementtype = S_ERROR;
2766 }
2767
2768 void Statement::chk_unknown_instance()
2769 {
2770 Common::Assignment *t_ass;
2771 {
2772 Error_Context cntxt(this, "In function or altstep instance");
2773 t_ass = ref_pard->get_refd_assignment(false);
2774 }
2775 if (!t_ass) goto error;
2776 switch (t_ass->get_asstype()) {
2777 case Common::Assignment::A_FUNCTION:
2778 case Common::Assignment::A_FUNCTION_RVAL:
2779 case Common::Assignment::A_FUNCTION_RTEMP:
2780 case Common::Assignment::A_EXT_FUNCTION:
2781 case Common::Assignment::A_EXT_FUNCTION_RVAL:
2782 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
2783 statementtype = S_FUNCTION_INSTANCE;
2784 chk_function();
2785 break;
2786 case Common::Assignment::A_ALTSTEP:
2787 statementtype = S_ALTSTEP_INSTANCE;
2788 chk_altstep();
2789 break;
2790 default:
2791 ref_pard->error("Reference to a function or altstep was expected "
2792 "instead of %s, which cannot be invoked",
2793 t_ass->get_description().c_str());
2794 goto error;
2795 }
2796 return;
2797 error:
2798 clean_up();
2799 statementtype = S_ERROR;
2800 }
2801
2802 void Statement::chk_unknown_invoke()
2803 {
2804 Error_Context cntxt(this, "In apply operation");
2805 Type *t = fau_refd.value->get_expr_governor_last();
2806 if (!t) goto error;
2807 switch (t->get_typetype()) {
2808 case Type::T_ERROR:
2809 goto error;
2810 case Type::T_FUNCTION:
2811 statementtype = S_FUNCTION_INVOKED;
2812 if (t->get_function_return_type()) warning("The value returned by "
2813 "function type `%s' is not used", t->get_typename().c_str());
2814 break;
2815 case Type::T_ALTSTEP:
2816 statementtype = S_ALTSTEP_INVOKED;
2817 break;
2818 default:
2819 fau_refd.value->error("A value of type function or altstep was "
2820 "expected instead of `%s'", t->get_typename().c_str());
2821 goto error;
2822 }
2823 my_sb->chk_runs_on_clause(t, *this, "call");
2824 {
2825 ActualParList *parlist = new Ttcn::ActualParList;
2826 Ttcn::FormalParList *fp_list = t->get_fat_parameters();
2827 bool is_erroneous = fp_list->fold_named_and_chk(fau_refd.t_list1,
2828 parlist);
2829 delete fau_refd.t_list1;
2830 if(is_erroneous) {
2831 delete parlist;
2832 fau_refd.ap_list2 = 0;
2833 } else {
2834 parlist->set_fullname(get_fullname());
2835 parlist->set_my_scope(my_sb);
2836 fau_refd.ap_list2 = parlist;
2837 }
2838 }
2839 return;
2840 error:
2841 clean_up();
2842 statementtype = S_ERROR;
2843 }
2844
2845 void Statement::chk_assignment()
2846 {
2847 Error_Context cntxt(this, "In variable assignment");
2848 ass->chk();
2849 }
2850
2851 void Statement::chk_function()
2852 {
2853 Error_Context cntxt(this, "In function instance");
2854 Common::Assignment *t_ass = ref_pard->get_refd_assignment();
2855 my_sb->chk_runs_on_clause(t_ass, *ref_pard, "call");
2856 if (t_ass->get_Type())
2857 ref_pard->warning("The value returned by %s is not used",
2858 t_ass->get_description().c_str());
2859 }
2860
2861 void Statement::chk_block()
2862 {
2863 Error_Context cntxt(this, "In statement block");
2864 block->chk();
2865 }
2866
2867 void Statement::chk_log_action(LogArguments *lga)
2868 {
2869 Error_Context cntxt(this, "In %s statement", get_stmt_name());
2870 if (lga) {
2871 lga->chk();
2872 if (!semantic_check_only) lga->join_strings();
2873 }
2874 }
2875
2876 void Statement::chk_goto()
2877 {
2878 Error_Context cntxt(this, "In goto statement");
2879 if (!my_sb->has_label(*go_to.id)) {
2880 error("Label `%s' is used, but not defined",
2881 go_to.id->get_dispname().c_str());
2882 go_to.label = 0;
2883 go_to.jumps_forward = false;
2884 return;
2885 }
2886 Statement *label_stmt = my_sb->get_label(*go_to.id);
2887 label_stmt->label.used = true;
2888 StatementBlock *label_sb = label_stmt->get_my_sb();
2889 // the index of the label in its own statement block
2890 size_t label_idx = label_stmt->get_my_sb_index();
2891 // the index of the goto statement (or its parent statement) in the
2892 // statement block of the label
2893 size_t goto_idx;
2894 if (my_sb == label_sb) goto_idx = go_to.stmt_idx;
2895 else {
2896 // the goto statement is within a nested statement block
2897 StatementBlock *goto_sb = my_sb, *parent_sb = my_sb->get_my_sb();
2898 while (parent_sb != label_sb) {
2899 // go up until the block of the label is found
2900 if (!parent_sb) FATAL_ERROR("Statement::chk_goto()");
2901 goto_sb = parent_sb;
2902 parent_sb = parent_sb->get_my_sb();
2903 }
2904 goto_idx = goto_sb->get_my_sb_index();
2905 }
2906 if (label_idx > goto_idx) {
2907 bool error_flag = false;
2908 for (size_t i = goto_idx + 1; i < label_idx; i++) {
2909 Statement *stmt = label_sb->get_stmt_byIndex(i);
2910 if (stmt->get_statementtype() != S_DEF) continue;
2911 if (!error_flag) {
2912 error("Jump to label `%s' crosses local definition",
2913 go_to.id->get_dispname().c_str());
2914 error_flag = true;
2915 }
2916 stmt->note("Definition of %s is here",
2917 stmt->get_def()->get_description().c_str());
2918 }
2919 if (error_flag)
2920 label_stmt->note("Label `%s' is here",
2921 go_to.id->get_dispname().c_str());
2922 go_to.jumps_forward = true;
2923 } else go_to.jumps_forward = false;
2924 go_to.label = label_stmt;
2925 }
2926
2927 void Statement::chk_if()
2928 {
2929 bool unreach=false;
2930 if_stmt.ics->chk(unreach);
2931 if(if_stmt.elseblock) {
2932 Error_Context cntxt(if_stmt.elseblock_location, "In else statement");
2933 if(unreach) if_stmt.elseblock_location->warning
2934 ("Control never reaches this code because of previous effective"
2935 " condition(s)");
2936 if_stmt.elseblock->chk();
2937 }
2938 }
2939
2940 /** \todo review */
2941 void Statement::chk_select()
2942 {
2943 Error_Context cntxt(this, "In select case statement");
2944 Type *t_gov=0;
2945 for(int turn=0; turn<2; turn++) {
2946 if(turn) select.expr->set_lowerid_to_ref();
2947 Type::typetype_t tt=select.expr->get_expr_returntype();
2948 t_gov=select.expr->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
2949 if(!t_gov || tt==Type::T_ERROR) {
2950 SelectCases *scs=select.scs;
2951 for(size_t i=0; i<scs->get_nof_scs(); i++) {
2952 TemplateInstances *tis=scs->get_sc_byIndex(i)->get_tis();
2953 if(!tis) continue;
2954 for(size_t j=0; j<tis->get_nof_tis(); j++) {
2955 TemplateInstance *ti=tis->get_ti_byIndex(j);
2956 if(turn) ti->get_Template()->set_lowerid_to_ref();
2957 t_gov=ti->get_expr_governor(Type::EXPECTED_TEMPLATE);
2958 tt=ti->get_expr_returntype(Type::EXPECTED_TEMPLATE);
2959 if(t_gov && tt!=Type::T_ERROR) break;
2960 } // for j
2961 if(t_gov) break;
2962 } // for i
2963 }
2964 else t_gov=select.expr->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
2965 } // for turn
2966 if(!t_gov) {
2967 select.expr->error("Cannot determine the type of the expression");
2968 t_gov=Type::get_pooltype(Type::T_ERROR);
2969 }
2970 select.expr->set_my_governor(t_gov);
2971 t_gov->chk_this_value_ref(select.expr);
2972 t_gov->chk_this_value(select.expr, 0, Type::EXPECTED_DYNAMIC_VALUE,
2973 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
2974 select.scs->chk(t_gov);
2975 }
2976
2977 void Statement::chk_for()
2978 {
2979 Error_Context cntxt(this, "In for statement");
2980 if (loop.for_stmt.varinst) loop.for_stmt.init_varinst->chk_for();
2981 else loop.for_stmt.init_ass->chk();
2982 loop.for_stmt.finalexpr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
2983 if(!loop.for_stmt.finalexpr->is_unfoldable()
2984 && !loop.for_stmt.finalexpr->get_val_bool())
2985 loop.for_stmt.finalexpr->warning
2986 ("Control never reaches this code because the"
2987 " final conditional expression evals to false");
2988 loop.for_stmt.step->chk();
2989 loop.block->set_my_laic_stmt(0, this);
2990 loop.block->chk();
2991 }
2992
2993 void Statement::chk_while()
2994 {
2995 Error_Context cntxt(this, "In while statement");
2996 loop.expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
2997 if(!loop.expr->is_unfoldable() && !loop.expr->get_val_bool())
2998 loop.expr->warning("Control never reaches this code because the"
2999 " conditional expression evals to false");
3000 loop.block->set_my_laic_stmt(0, this);
3001 loop.block->chk();
3002 }
3003
3004 void Statement::chk_do_while()
3005 {
3006 Error_Context cntxt(this, "In do-while statement");
3007 loop.block->set_my_laic_stmt(0, this);
3008 loop.block->chk();
3009 loop.expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
3010 }
3011
3012 void Statement::chk_break()
3013 {
3014 Error_Context cntxt(this, "In break statement");
3015 if (!brk_cnt.loop_stmt && !brk_cnt.ags)
3016 error("Break statement cannot be used outside loops, alt or interleave"
3017 " statements, altsteps or response and exception handling part of call"
3018 " operations");
3019 if (brk_cnt.loop_stmt)
3020 brk_cnt.loop_stmt->loop.has_brk=true;
3021 }
3022
3023 void Statement::chk_continue()
3024 {
3025 Error_Context cntxt(this, "In continue statement");
3026 if (brk_cnt.loop_stmt) {
3027 brk_cnt.loop_stmt->loop.has_cnt=true;
3028 if (brk_cnt.ags) brk_cnt.loop_stmt->loop.has_cnt_in_ags=true;
3029 } else
3030 error("Continue statement cannot be used outside loops");
3031 }
3032
3033 void Statement::chk_alt()
3034 {
3035 Error_Context cntxt(this, "In alt construct");
3036 ags->set_my_ags(ags);
3037 ags->set_my_laic_stmt(ags, 0);
3038 ags->chk();
3039 }
3040
3041 void Statement::chk_repeat()
3042 {
3043 Error_Context cntxt(this, "In repeat statement");
3044 if (ags) ags->repeat_found();
3045 else error("Repeat statement cannot be used outside alt statements, "
3046 "altsteps or response and exception handling part of call operations");
3047 }
3048
3049 void Statement::chk_interleave()
3050 {
3051 Error_Context cntxt(this, "In interleave statement");
3052 ags->set_my_laic_stmt(ags, 0);
3053 ags->chk();
3054 ags->chk_allowed_interleave();
3055 }
3056
3057 void Statement::chk_altstep()
3058 {
3059 Error_Context cntxt(this, "In altstep instance");
3060 Common::Assignment *t_ass = ref_pard->get_refd_assignment();
3061 my_sb->chk_runs_on_clause(t_ass, *ref_pard, "call");
3062 }
3063
3064 void Statement::chk_return()
3065 {
3066 Error_Context cntxt(this, "In return statement");
3067 Definition *my_def = my_sb->get_my_def();
3068 if (!my_def) {
3069 error("Return statement cannot be used in the control part. "
3070 "It is allowed only in functions and altsteps");
3071 goto error;
3072 }
3073 switch (my_def->get_asstype()) {
3074 case Definition::A_FUNCTION:
3075 if (returnexpr.t) {
3076 returnexpr.t->error("Unexpected return value. The function does not "
3077 "have return type");
3078 goto error;
3079 }
3080 break;
3081 case Definition::A_FUNCTION_RVAL:
3082 if (!returnexpr.t) {
3083 error("Missing return value. The function should return a value of "
3084 "type `%s'", my_def->get_Type()->get_typename().c_str());
3085 goto error;
3086 } else if (!returnexpr.t->is_Value()) {
3087 returnexpr.t->error("A specific value without matching symbols was "
3088 "expected as return value");
3089 goto error;
3090 } else {
3091 returnexpr.v = returnexpr.t->get_Value();
3092 delete returnexpr.t;
3093 returnexpr.t = 0;
3094 Type *return_type = my_def->get_Type();
3095 returnexpr.v->set_my_governor(return_type);
3096 return_type->chk_this_value_ref(returnexpr.v);
3097 return_type->chk_this_value(returnexpr.v, 0, Type::EXPECTED_DYNAMIC_VALUE,
3098 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
3099 }
3100 break;
3101 case Definition::A_FUNCTION_RTEMP:
3102 if (!returnexpr.t) {
3103 error("Missing return template. The function should return a template "
3104 "of type `%s'", my_def->get_Type()->get_typename().c_str());
3105 goto error;
3106 } else {
3107 Type *return_type = my_def->get_Type();
3108 returnexpr.t->set_my_governor(return_type);
3109 return_type->chk_this_template_ref(returnexpr.t);
3110 return_type->chk_this_template_generic(returnexpr.t, INCOMPLETE_NOT_ALLOWED,
3111 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, NOT_IMPLICIT_OMIT, 0);
3112 Def_Function_Base* dfb = dynamic_cast<Def_Function_Base*>(my_def);
3113 if (!dfb) FATAL_ERROR("Statement::chk_return()");
3114 returnexpr.gen_restriction_check =
3115 returnexpr.t->chk_restriction("return template",
3116 dfb->get_template_restriction(), this);
3117 }
3118 break;
3119 case Definition::A_ALTSTEP:
3120 if (returnexpr.t) {
3121 returnexpr.t->error("An altstep cannot return a value");
3122 goto error;
3123 }
3124 break;
3125 default:
3126 error("Return statement cannot be used in a %s. It is allowed only in "
3127 "functions and altsteps", my_def->get_assname());
3128 goto error;
3129 }
3130 return;
3131 error:
3132 delete returnexpr.t;
3133 returnexpr.t = 0;
3134 }
3135
3136 void Statement::chk_activate()
3137 {
3138 Error_Context cntxt(this, "In activate statement");
3139 if (!ref_pard->chk_activate_argument()) {
3140 clean_up();
3141 statementtype = S_ERROR;
3142 }
3143 }
3144
3145 void Statement::chk_activate_refd()
3146 {
3147 Error_Context cntxt(this, "In activate statement");
3148 Type *t = fau_refd.value->get_expr_governor_last();
3149 if (!t) goto error;
3150 switch (t->get_typetype()) {
3151 case Type::T_ERROR:
3152 goto error;
3153 case Type::T_ALTSTEP:
3154 break;
3155 default:
3156 fau_refd.value->error("A value of type altstep was expected in the "
3157 "argument of `derefers()' instead of `%s'", t->get_typename().c_str());
3158 goto error;
3159 }
3160 if (t->get_fat_runs_on_self()) {
3161 fau_refd.value->error("The argument of `derefers()' cannot be an altstep "
3162 "reference with 'runs on self' clause");
3163 goto error;
3164 }
3165 my_sb->chk_runs_on_clause(t, *this, "activate");
3166 {
3167 ActualParList *parlist = new ActualParList;
3168 Ttcn::FormalParList *fp_list = t->get_fat_parameters();
3169 bool is_erroneous = fp_list->fold_named_and_chk(fau_refd.t_list1,
3170 parlist);
3171 delete fau_refd.t_list1;
3172 if(is_erroneous) {
3173 delete parlist;
3174 fau_refd.ap_list2 = 0;
3175 goto error;
3176 } else {
3177 parlist->set_fullname(get_fullname());
3178 parlist->set_my_scope(my_sb);
3179 fau_refd.ap_list2 = parlist;
3180 if (!fp_list->chk_activate_argument(parlist,get_fullname().c_str()))
3181 goto error;
3182 }
3183 }
3184 return;
3185 error:
3186 clean_up();
3187 statementtype = S_ERROR;
3188 }
3189
3190 void Statement::chk_deactivate()
3191 {
3192 if (deactivate) {
3193 Error_Context cntxt(this, "In deactivate statement");
3194 deactivate->chk_expr_default(Type::EXPECTED_DYNAMIC_VALUE);
3195 }
3196 }
3197
3198 void Statement::chk_send()
3199 {
3200 Error_Context cntxt(this, "In send statement");
3201 // checking the port reference
3202 Type *port_type = chk_port_ref(port_op.portref);
3203 // determining the message type
3204 Type *msg_type = 0;
3205 bool msg_type_determined = false;
3206 if (port_type) {
3207 Ttcn::PortTypeBody *port_type_body = port_type->get_PortBody();
3208 TypeSet *out_msgs = port_type_body->get_out_msgs();
3209 if (out_msgs) {
3210 if (out_msgs->get_nof_types() == 1) {
3211 // there is only one outgoing message type
3212 msg_type = out_msgs->get_type_byIndex(0);
3213 } else {
3214 // there are more than one outgoing message types
3215 msg_type = get_outgoing_type(port_op.s.sendpar);
3216 if (msg_type) {
3217 size_t nof_comp_types =
3218 out_msgs->get_nof_compatible_types(msg_type);
3219 if (nof_comp_types == 0) {
3220 port_op.s.sendpar->error("Message type `%s' is not present on "
3221 "the outgoing list of port type `%s'",
3222 msg_type->get_typename().c_str(),
3223 port_type->get_typename().c_str());
3224 } else if (nof_comp_types > 1) {
3225 port_op.s.sendpar->error("Type of the message is ambiguous: "
3226 "`%s' is compatible with more than one outgoing message types "
3227 "of port type `%s'", msg_type->get_typename().c_str(),
3228 port_type->get_typename().c_str());
3229 }
3230 } else {
3231 port_op.s.sendpar->error("Cannot determine the type of the "
3232 "outgoing message");
3233 }
3234 }
3235 msg_type_determined = true;
3236 } else if (port_type_body->get_operation_mode() ==
3237 PortTypeBody::PO_PROCEDURE) {
3238 port_op.portref->error("Message-based operation `send' is not "
3239 "applicable to a procedure-based port of type `%s'",
3240 port_type->get_typename().c_str());
3241 } else {
3242 port_op.portref->error("Port type `%s' does not have any outgoing "
3243 "message types", port_type->get_typename().c_str());
3244 }
3245 }
3246 // determining the message type if it is not done so far
3247 if (!msg_type_determined) {
3248 msg_type = get_outgoing_type(port_op.s.sendpar);
3249 }
3250 if (!msg_type) msg_type = Type::get_pooltype(Type::T_ERROR);
3251 // checking the parameter (template instance)
3252 port_op.s.sendpar->chk(msg_type);
3253 // checking for invalid message types
3254 msg_type = msg_type->get_type_refd_last();
3255 switch (msg_type->get_typetype()) {
3256 case Type::T_SIGNATURE:
3257 port_op.s.sendpar->error("The type of send parameter is signature `%s', "
3258 "which cannot be a message type", msg_type->get_typename().c_str());
3259 break;
3260 case Type::T_PORT:
3261 port_op.s.sendpar->error("The type of send parameter is port type `%s', "
3262 "which cannot be a message type", msg_type->get_typename().c_str());
3263 break;
3264 case Type::T_DEFAULT:
3265 port_op.s.sendpar->error("The type of send parameter is the `default' "
3266 "type, which cannot be a message type");
3267 default:
3268 break;
3269 }
3270 // checking for presence of wildcards in the template body
3271 port_op.s.sendpar->get_Template()->chk_specific_value(false);
3272 // checking to clause
3273 chk_to_clause(port_type);
3274 }
3275
3276 void Statement::chk_call()
3277 {
3278 Error_Context cntxt(this, "In call statement");
3279 // checking the port reference
3280 Type *port_type = chk_port_ref(port_op.portref);
3281 // determining the signature of the argument
3282 Type *signature = 0;
3283 bool signature_determined = false;
3284 if (port_type) {
3285 PortTypeBody *port_type_body = port_type->get_PortBody();
3286 TypeSet *out_sigs = port_type_body->get_out_sigs();
3287 if (out_sigs) {
3288 if (out_sigs->get_nof_types() == 1) {
3289 // there is only one outgoing signature
3290 signature = out_sigs->get_type_byIndex(0);
3291 } else {
3292 // there are more than one outgoing signatures
3293 signature = get_outgoing_type(port_op.s.sendpar);
3294 if (signature) {
3295 if (!out_sigs->has_type(signature)) {
3296 port_op.s.sendpar->error("Signature `%s' is not present on the "
3297 "outgoing list of port type `%s'",
3298 signature->get_typename().c_str(),
3299 port_type->get_typename().c_str());
3300 }
3301 } else {
3302 port_op.s.sendpar->error("Cannot determine the type of the "
3303 "signature");
3304 }
3305 }
3306 signature_determined = true;
3307 } else if (port_type_body->get_operation_mode() ==
3308 PortTypeBody::PO_MESSAGE) {
3309 port_op.portref->error("Procedure-based operation `call' is not "
3310 "applicable to a message-based port of type `%s'",
3311 port_type->get_typename().c_str());
3312 } else {
3313 port_op.portref->error("Port type `%s' does not have any outgoing "
3314 "signatures", port_type->get_typename().c_str());
3315 }
3316 }
3317 if (!signature_determined)
3318 signature = get_outgoing_type(port_op.s.sendpar);
3319 if (!signature) signature = Type::get_pooltype(Type::T_ERROR);
3320 // checking the parameter (template instance)
3321 port_op.s.sendpar->chk(signature);
3322 signature = signature->get_type_refd_last();
3323 bool is_noblock_sig = false;
3324 Type::typetype_t tt = signature->get_typetype();
3325 switch (tt) {
3326 case Type::T_SIGNATURE:
3327 // the signature is known and correct
3328 is_noblock_sig = signature->is_nonblocking_signature();
3329 case Type::T_ERROR:
3330 break;
3331 default:
3332 port_op.s.sendpar->error("The type of parameter is `%s', which is not "
3333 "a signature", signature->get_typename().c_str());
3334 }
3335 // checking presence/absence of optional parts
3336 if (is_noblock_sig) {
3337 if (port_op.s.call.timer) {
3338 port_op.s.call.timer->error("A call of non-blocking signature `%s' "
3339 "cannot have call timer", signature->get_typename().c_str());
3340 } else if (port_op.s.call.nowait) {
3341 error("A call of non-blocking signature `%s' cannot use the "
3342 "`nowait' keyword", signature->get_typename().c_str());
3343 }
3344 if (port_op.s.call.body) {
3345 error("A call of non-blocking signature `%s' cannot have "
3346 "response and exception handling part",
3347 signature->get_typename().c_str());
3348 }
3349 } else if (port_op.s.call.nowait) {
3350 if (port_op.s.call.body) {
3351 error("A call with `nowait' keyword cannot have response and "
3352 "exception handling part");
3353 }
3354 } else {
3355 // do not issue any error if the signature is erroneous
3356 // because it could have been a non-blocking one
3357 if (tt == Type::T_SIGNATURE && !port_op.s.call.body) {
3358 error("Response and exception handling part is missing from "
3359 "blocking call operation");
3360 }
3361 }
3362 // checking call timer
3363 if (port_op.s.call.timer) {
3364 Error_Context cntxt2(port_op.s.call.timer, "In call timer value");
3365 port_op.s.call.timer->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE);
3366 Value *t_val = port_op.s.call.timer->get_value_refd_last();
3367 if (t_val->get_valuetype() == Value::V_REAL) {
3368 ttcn3float v_real = t_val->get_val_Real();
3369 if (v_real < 0.0) {
3370 port_op.s.call.timer->error("The call timer has "
3371 "negative duration: `%s'", Real2string(v_real).c_str());
3372 } else if (isSpecialFloatValue(v_real)) {
3373 port_op.s.call.timer->error("The call timer duration cannot be %s",
3374 Real2string(v_real).c_str());
3375 }
3376 }
3377 }
3378 // checking to clause
3379 chk_to_clause(port_type);
3380 // checking response and exception handling part
3381 if (port_op.s.call.body) chk_call_body(port_type, signature);
3382 }
3383
3384 void Statement::chk_reply()
3385 {
3386 Error_Context cntxt(this, "In reply statement");
3387 // checking the port reference
3388 Type *port_type = chk_port_ref(port_op.portref);
3389 // determining the signature of the argument
3390 Type *signature = 0;
3391 bool signature_determined = false;
3392 if (port_type) {
3393 PortTypeBody *port_type_body = port_type->get_PortBody();
3394 TypeSet *in_sigs = port_type_body->get_in_sigs();
3395 if (in_sigs) {
3396 if (in_sigs->get_nof_types() == 1) {
3397 // there is only one incoming signature
3398 signature = in_sigs->get_type_byIndex(0);
3399 } else {
3400 // there are more than one incoming signatures
3401 signature = get_outgoing_type(port_op.s.sendpar);
3402 if (signature) {
3403 if (!in_sigs->has_type(signature)) {
3404 port_op.s.sendpar->error("Signature `%s' is not present on the "
3405 "incoming list of port type `%s'",
3406 signature->get_typename().c_str(),
3407 port_type->get_typename().c_str());
3408 }
3409 } else {
3410 port_op.s.sendpar->error("Cannot determine the type of the "
3411 "signature");
3412 }
3413 }
3414 signature_determined = true;
3415 } else if (port_type_body->get_operation_mode() ==
3416 PortTypeBody::PO_MESSAGE) {
3417 port_op.portref->error("Procedure-based operation `reply' is not "
3418 "applicable to a message-based port of type `%s'",
3419 port_type->get_typename().c_str());
3420 } else {
3421 port_op.portref->error("Port type `%s' does not have any incoming "
3422 "signatures", port_type->get_typename().c_str());
3423 }
3424 }
3425 if (!signature_determined)
3426 signature = get_outgoing_type(port_op.s.sendpar);
3427 if (!signature) signature = Type::get_pooltype(Type::T_ERROR);
3428 // checking the parameter (template instance)
3429 port_op.s.sendpar->chk(signature);
3430 signature = signature->get_type_refd_last();
3431 Type *return_type = 0;
3432 switch (signature->get_typetype()) {
3433 case Type::T_SIGNATURE:
3434 // the signature is known and correct
3435 if (signature->is_nonblocking_signature())
3436 error("Operation `reply' is not applicable to non-blocking signature "
3437 "`%s'", signature->get_typename().c_str());
3438 else return_type = signature->get_signature_return_type();
3439 // checking the presence/absence of reply value
3440 if (port_op.s.replyval) {
3441 if (!return_type) {
3442 port_op.s.replyval->error("Unexpected return value. Signature "
3443 "`%s' does not have return type",
3444 signature->get_typename().c_str());
3445 }
3446 } else if (return_type) {
3447 error("Missing return value. Signature `%s' returns type `%s'",
3448 signature->get_typename().c_str(),
3449 return_type->get_typename().c_str());
3450 }
3451 case Type::T_ERROR:
3452 break;
3453 default:
3454 port_op.s.sendpar->error("The type of parameter is `%s', which is not a "
3455 "signature", signature->get_typename().c_str());
3456 }
3457 // checking the reply value if present
3458 if (port_op.s.replyval) {
3459 Error_Context cntxt2(port_op.s.replyval, "In return value");
3460 if (!return_type) return_type = Type::get_pooltype(Type::T_ERROR);
3461 port_op.s.replyval->set_my_governor(return_type);
3462 return_type->chk_this_value_ref(port_op.s.replyval);
3463 return_type->chk_this_value(port_op.s.replyval, 0,
3464 Type::EXPECTED_DYNAMIC_VALUE, INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED,
3465 SUB_CHK);
3466 }
3467 // checking to clause
3468 chk_to_clause(port_type);
3469 }
3470
3471 void Statement::chk_raise()
3472 {
3473 Error_Context cntxt(this, "In raise statement");
3474 // checking the port reference
3475 Type *port_type = chk_port_ref(port_op.portref);
3476 // determining the signature of the exception
3477 port_op.s.raise.signature =
3478 chk_signature_ref(port_op.s.raise.signature_ref);
3479 // checking whether the signature is present on the incoming list
3480 // of the respective port type
3481 if (port_type) {
3482 PortTypeBody *port_type_body = port_type->get_PortBody();
3483 TypeSet *in_sigs = port_type_body->get_in_sigs();
3484 if (port_type_body->get_operation_mode() ==
3485 PortTypeBody::PO_MESSAGE) {
3486 port_op.portref->error("Procedure-based operation `raise' is not "
3487 "applicable to a message-based port of type `%s'",
3488 port_type->get_typename().c_str());
3489 } else if (in_sigs) {
3490 if (port_op.s.raise.signature) {
3491 if (!in_sigs->has_type(port_op.s.raise.signature)) {
3492 port_op.s.raise.signature_ref->error("Signature `%s' is not "
3493 "present on the incoming list of port type `%s'",
3494 port_op.s.raise.signature->get_typename().c_str(),
3495 port_type->get_typename().c_str());
3496 }
3497 } else if (in_sigs->get_nof_types() == 1) {
3498 // if the signature is unknown and the port type has exactly one
3499 // incoming signature then use that for further checking
3500 port_op.s.raise.signature =
3501 in_sigs->get_type_byIndex(0)->get_type_refd_last();
3502 }
3503 } else {
3504 port_op.portref->error("Port type `%s' does not have any incoming "
3505 "signatures", port_type->get_typename().c_str());
3506 }
3507 }
3508 // determining the type of exception
3509 Type *exc_type = 0;
3510 bool exc_type_determined = false;
3511 if (port_op.s.raise.signature) {
3512 // the signature is known
3513 SignatureExceptions *exceptions =
3514 port_op.s.raise.signature->get_signature_exceptions();
3515 if (exceptions) {
3516 if (exceptions->get_nof_types() == 1) {
3517 // the signature has exactly one exception type
3518 // use that for checking
3519 exc_type = exceptions->get_type_byIndex(0);
3520 } else {
3521 // the signature has more than one exception types
3522 exc_type = get_outgoing_type(port_op.s.sendpar);
3523 if (exc_type) {
3524 size_t nof_comp_types =
3525 exceptions->get_nof_compatible_types(exc_type);
3526 if (nof_comp_types == 0) {
3527 port_op.s.sendpar->error("Type `%s' is not present on the "
3528 "exception list of signature `%s'",
3529 exc_type->get_typename().c_str(),
3530 port_op.s.raise.signature->get_typename().c_str());
3531 } else if (nof_comp_types > 1) {
3532 port_op.s.sendpar->error("Type of the exception is ambiguous: "
3533 "`%s' is compatible with more than one exception types of "
3534 "signature `%s'", exc_type->get_typename().c_str(),
3535 port_op.s.raise.signature->get_typename().c_str());
3536 }
3537 } else {
3538 port_op.s.sendpar->error("Cannot determine the type of the "
3539 "exception");
3540 }
3541 }
3542 exc_type_determined = true;
3543 } else {
3544 port_op.s.raise.signature_ref->error("Signature `%s' does not have "
3545 "exceptions", port_op.s.raise.signature->get_typename().c_str());
3546 }
3547 }
3548 // determining the type of exception if it is not done so far
3549 if (!exc_type_determined) {
3550 exc_type = get_outgoing_type(port_op.s.sendpar);
3551 }
3552 if (!exc_type) exc_type = Type::get_pooltype(Type::T_ERROR);
3553 // checking the exception template
3554 port_op.s.sendpar->chk(exc_type);
3555 // checking for invalid exception types
3556 exc_type = exc_type->get_type_refd_last();
3557 switch (exc_type->get_typetype()) {
3558 case Type::T_SIGNATURE:
3559 port_op.s.sendpar->error("The type of raise parameter is signature `%s', "
3560 "which cannot be an exception type",
3561 exc_type->get_typename().c_str());
3562 break;
3563 case Type::T_PORT:
3564 port_op.s.sendpar->error("The type of raise parameter is port type `%s', "
3565 "which cannot be an exception type",
3566 exc_type->get_typename().c_str());
3567 break;
3568 case Type::T_DEFAULT:
3569 port_op.s.sendpar->error("The type of raise parameter is the `default' "
3570 "type, which cannot be an exception type");
3571 default:
3572 break;
3573 }
3574 // checking for presence of wildcards in the template body
3575 port_op.s.sendpar->get_Template()->chk_specific_value(false);
3576 // checking to clause
3577 chk_to_clause(port_type);
3578 }
3579
3580 void Statement::chk_receive()
3581 {
3582 // determining statement type
3583 const char *stmt_name = get_stmt_name();
3584 Error_Context cntxt(this, "In %s statement", stmt_name);
3585 // checking the port reference
3586 Type *port_type = chk_port_ref(port_op.portref);
3587 // checking the parameter and/or value redirect
3588 if (port_op.r.rcvpar) {
3589 // the receive parameter (template instance) is present
3590 // trying to determine type of the incoming message
3591 Type *msg_type = 0;
3592 bool msg_type_determined = false, value_redirect_checked = false;
3593 if (port_type) {
3594 // the port reference is correct and the port type is known
3595 PortTypeBody *port_type_body = port_type->get_PortBody();
3596 TypeSet *in_msgs = port_type_body->get_in_msgs();
3597 if (in_msgs) {
3598 if (in_msgs->get_nof_types() == 1) {
3599 // there is only one incoming message type
3600 // use that for checking
3601 msg_type = in_msgs->get_type_byIndex(0);
3602 } else {
3603 // there are more than one incoming message types
3604 msg_type = get_incoming_type(port_op.r.rcvpar,
3605 port_op.r.redirect.value, value_redirect_checked);
3606 if (msg_type) {
3607 size_t nof_comp_types =
3608 in_msgs->get_nof_compatible_types(msg_type);
3609 if (nof_comp_types == 0) {
3610 port_op.r.rcvpar->error("Message type `%s' is not present on "
3611 "the incoming list of port of type `%s'",
3612 msg_type->get_typename().c_str(),
3613 port_type->get_typename().c_str());
3614 } else if (nof_comp_types > 1) {
3615 port_op.r.rcvpar->error("Type of the message is ambiguous: "
3616 "`%s' is compatible with more than one incoming message "
3617 "types of port type `%s'", msg_type->get_typename().c_str(),
3618 port_type->get_typename().c_str());
3619 }
3620 } else {
3621 port_op.r.rcvpar->error("Cannot determine the type of the "
3622 "incoming message");
3623 }
3624 }
3625 msg_type_determined = true;
3626 } else if (port_type_body->get_operation_mode() ==
3627 PortTypeBody::PO_PROCEDURE) {
3628 port_op.portref->error("Message-based operation `%s' is not "
3629 "applicable to a procedure-based port of type `%s'", stmt_name,
3630 port_type->get_typename().c_str());
3631 } else {
3632 port_op.portref->error("Port type `%s' does not have any incoming "
3633 "message types", port_type->get_typename().c_str());
3634 }
3635 } else if (!port_op.portref) {
3636 // the statement refers to 'any port'
3637 port_op.r.rcvpar->error("Operation `any port.%s' cannot have parameter",
3638 stmt_name);
3639 if (port_op.r.redirect.value) {
3640 port_op.r.redirect.value->error("Operation `any port.%s' cannot have "
3641 "value redirect", stmt_name);
3642 }
3643 }
3644 if (!msg_type_determined) {
3645 msg_type = get_incoming_type(port_op.r.rcvpar, port_op.r.redirect.value,
3646 value_redirect_checked);
3647 }
3648 if (!msg_type) msg_type = Type::get_pooltype(Type::T_ERROR);
3649 // check the template instance using the message type
3650 port_op.r.rcvpar->chk(msg_type);
3651 // check the value redirect if it is not done so far
3652 if (!value_redirect_checked)
3653 chk_value_redirect(port_op.r.redirect.value, msg_type);
3654 } else {
3655 // the statement does not have parameter
3656 if (port_type) {
3657 PortTypeBody *port_type_body = port_type->get_PortBody();
3658 if (!port_type_body->get_in_msgs()) {
3659 // the port type is known and it does not have incoming messages
3660 if (port_type_body->get_operation_mode() ==
3661 PortTypeBody::PO_PROCEDURE) {
3662 port_op.portref->error("Message-based operation `%s' is not "
3663 "applicable to a procedure-based port of type `%s'", stmt_name,
3664 port_type->get_typename().c_str());
3665 } else {
3666 port_op.portref->error("Port type `%s' does not have any incoming "
3667 "message types", port_type->get_typename().c_str());
3668 }
3669 }
3670 }
3671 if (port_op.r.redirect.value) {
3672 port_op.r.redirect.value->error("Value redirect cannot be used without "
3673 "receive parameter");
3674 chk_value_redirect(port_op.r.redirect.value, 0);
3675 }
3676 }
3677 // checking from clause and sender redirect
3678 chk_from_clause(port_type);
3679 }
3680
3681 void Statement::chk_getcall()
3682 {
3683 // determining statement type
3684 const char *stmt_name = get_stmt_name();
3685 Error_Context cntxt(this, "In %s statement", stmt_name);
3686 // checking the port reference
3687 Type *port_type = chk_port_ref(port_op.portref);
3688 if (port_op.r.rcvpar) {
3689 // the parameter (signature template) is present
3690 // determining the signature of the argument
3691 Type *signature = 0;
3692 bool signature_determined = false;
3693 if (port_type) {
3694 // the port reference is correct and the port type is known
3695 PortTypeBody *port_type_body = port_type->get_PortBody();
3696 TypeSet *in_sigs = port_type_body->get_in_sigs();
3697 if (in_sigs) {
3698 if (in_sigs->get_nof_types() == 1) {
3699 // there is only one incoming signature
3700 signature = in_sigs->get_type_byIndex(0);
3701 } else {
3702 // there are more than one incoming signatures
3703 signature = get_outgoing_type(port_op.r.rcvpar);
3704 if (signature) {
3705 if (!in_sigs->has_type(signature)) {
3706 port_op.r.rcvpar->error("Signature `%s' is not present on the "
3707 "incoming list of port type `%s'",
3708 signature->get_typename().c_str(),
3709 port_type->get_typename().c_str());
3710 }
3711 } else {
3712 port_op.r.rcvpar->error("Cannot determine the type of the "
3713 "signature");
3714 }
3715 }
3716 signature_determined = true;
3717 } else if (port_type_body->get_operation_mode() ==
3718 PortTypeBody::PO_MESSAGE) {
3719 port_op.portref->error("Procedure-based operation `%s' is not "
3720 "applicable to a message-based port of type `%s'", stmt_name,
3721 port_type->get_typename().c_str());
3722 } else {
3723 port_op.portref->error("Port type `%s' does not have any incoming "
3724 "signatures", port_type->get_typename().c_str());
3725 }
3726 } else if (!port_op.portref) {
3727 // the statement refers to 'any port'
3728 port_op.r.rcvpar->error("Operation `any port.%s' cannot have parameter",
3729 stmt_name);
3730 if (port_op.r.redirect.param) {
3731 port_op.r.redirect.param->error("Operation `any port.%s' cannot "
3732 "have parameter redirect", stmt_name);
3733 }
3734 }
3735 if (!signature_determined)
3736 signature = get_outgoing_type(port_op.r.rcvpar);
3737 if (!signature) signature = Type::get_pooltype(Type::T_ERROR);
3738 // checking the parameter (template instance)
3739 port_op.r.rcvpar->chk(signature);
3740 // checking whether the argument is a signature template
3741 // and checking the parameter redirect if present
3742 signature = signature->get_type_refd_last();
3743 switch (signature->get_typetype()) {
3744 case Type::T_SIGNATURE:
3745 if (port_op.r.redirect.param)
3746 port_op.r.redirect.param->chk(signature, false);
3747 break;
3748 case Type::T_ERROR:
3749 if (port_op.r.redirect.param)
3750 port_op.r.redirect.param->chk_erroneous();
3751 break;
3752 default:
3753 port_op.r.rcvpar->error("The type of parameter is `%s', which is not "
3754 "a signature", signature->get_typename().c_str());
3755 if (port_op.r.redirect.param)
3756 port_op.r.redirect.param->chk_erroneous();
3757 }
3758 } else {
3759 // the statement does not have parameter
3760 if (port_type) {
3761 PortTypeBody *port_type_body = port_type->get_PortBody();
3762 if (!port_type_body->get_in_sigs()) {
3763 // the port type is known and it does not have incoming signatures
3764 if (port_type_body->get_operation_mode() ==
3765 PortTypeBody::PO_MESSAGE) {
3766 port_op.portref->error("Procedure-based operation `%s' is not "
3767 "applicable to a message-based port of type `%s'", stmt_name,
3768 port_type->get_typename().c_str());
3769 } else {
3770 port_op.portref->error("Port type `%s' does not have any incoming "
3771 "signatures", port_type->get_typename().c_str());
3772 }
3773 }
3774 }
3775 if (port_op.r.redirect.param) {
3776 port_op.r.redirect.param->error("Parameter redirect cannot be used "
3777 "without signature template");
3778 port_op.r.redirect.param->chk_erroneous();
3779 }
3780 }
3781 // checking from clause and sender redirect
3782 chk_from_clause(port_type);
3783 }
3784
3785 void Statement::chk_getreply()
3786 {
3787 // determining statement type
3788 const char *stmt_name = get_stmt_name();
3789 Error_Context cntxt(this, "In %s statement", stmt_name);
3790 // checking the port reference
3791 Type *port_type = chk_port_ref(port_op.portref);
3792 if (port_op.r.rcvpar) {
3793 // the parameter (signature template) is present
3794 // determining the signature of the argument
3795 Type *signature = 0;
3796 bool signature_determined = false;
3797 if (port_type) {
3798 // the port reference is correct and the port type is known
3799 PortTypeBody *port_type_body = port_type->get_PortBody();
3800 if (port_type_body->getreply_allowed()) {
3801 TypeSet *out_sigs = port_type_body->get_out_sigs();
3802 if (out_sigs->get_nof_types() == 1) {
3803 // there is only one outgoing signature
3804 signature = out_sigs->get_type_byIndex(0);
3805 } else {
3806 // there are more than one outgoing signatures
3807 signature = get_outgoing_type(port_op.r.rcvpar);
3808 if (signature) {
3809 if (!out_sigs->has_type(signature)) {
3810 port_op.r.rcvpar->error("Signature `%s' is not present on the "
3811 "outgoing list of port type `%s'",
3812 signature->get_typename().c_str(),
3813 port_type->get_typename().c_str());
3814 }
3815 } else {
3816 port_op.r.rcvpar->error("Cannot determine the type of the "
3817 "signature");
3818 }
3819 }
3820 signature_determined = true;
3821 } else if (port_type_body->get_operation_mode() ==
3822 PortTypeBody::PO_MESSAGE) {
3823 port_op.portref->error("Procedure-based operation `%s' is not "
3824 "applicable to a message-based port of type `%s'", stmt_name,
3825 port_type->get_typename().c_str());
3826 } else {
3827 port_op.portref->error("Port type `%s' does not have any outgoing "
3828 "signatures that support reply", port_type->get_typename().c_str());
3829 }
3830 } else if (!port_op.portref) {
3831 // the statement refers to 'any port'
3832 port_op.r.rcvpar->error("Operation `any port.%s' cannot have parameter",
3833 stmt_name);
3834 if (port_op.r.getreply_valuematch) {
3835 port_op.r.getreply_valuematch->error("Operation `any port.%s' cannot "
3836 "have value match", stmt_name);
3837 }
3838 if (port_op.r.redirect.value) {
3839 port_op.r.redirect.value->error("Operation `any port.%s' cannot "
3840 "have value redirect", stmt_name);
3841 }
3842 if (port_op.r.redirect.param) {
3843 port_op.r.redirect.param->error("Operation `any port.%s' cannot "
3844 "have parameter redirect", stmt_name);
3845 }
3846 }
3847 if (!signature_determined)
3848 signature = get_outgoing_type(port_op.r.rcvpar);
3849 if (!signature) signature = Type::get_pooltype(Type::T_ERROR);
3850 // checking the parameter (template instance)
3851 port_op.r.rcvpar->chk(signature);
3852 // checking whether the argument is a signature template
3853 // checking the parameter redirect if present
3854 // and determining the return type of the signature
3855 signature = signature->get_type_refd_last();
3856 Type *return_type = 0;
3857 switch (signature->get_typetype()) {
3858 case Type::T_SIGNATURE:
3859 if (signature->is_nonblocking_signature())
3860 error("Operation `%s' is not applicable to non-blocking signature "
3861 "`%s'", stmt_name, signature->get_typename().c_str());
3862 else return_type = signature->get_signature_return_type();
3863 if (port_op.r.redirect.param)
3864 port_op.r.redirect.param->chk(signature, true);
3865 if (!return_type) {
3866 if (port_op.r.getreply_valuematch) {
3867 port_op.r.getreply_valuematch->error("Value match cannot be used "
3868 "because signature `%s' does not have return type",
3869 signature->get_typename().c_str());
3870 }
3871 if (port_op.r.redirect.value) {
3872 port_op.r.redirect.value->error("Value redirect cannot be used "
3873 "because signature `%s' does not have return type",
3874 signature->get_typename().c_str());
3875 }
3876 }
3877 break;
3878 case Type::T_ERROR:
3879 if (port_op.r.redirect.param)
3880 port_op.r.redirect.param->chk_erroneous();
3881 break;
3882 default:
3883 port_op.r.rcvpar->error("The type of parameter is `%s', which is not "
3884 "a signature", signature->get_typename().c_str());
3885 if (port_op.r.redirect.param)
3886 port_op.r.redirect.param->chk_erroneous();
3887 }
3888 // checking the value match if present
3889 if (port_op.r.getreply_valuematch) {
3890 Error_Context cntxt2(port_op.s.replyval, "In value match");
3891 if (!return_type) return_type = Type::get_pooltype(Type::T_ERROR);
3892 port_op.r.getreply_valuematch->chk(return_type);
3893 }
3894 // checking the value redirect if present
3895 chk_value_redirect(port_op.r.redirect.value, return_type);
3896 } else {
3897 // the statement does not have parameter (value match is also omitted)
3898 if (port_type) {
3899 PortTypeBody *port_type_body = port_type->get_PortBody();
3900 if (!port_type_body->getreply_allowed()) {
3901 // the port type is known and it does not have outgoing signatures
3902 if (port_type_body->get_operation_mode() ==
3903 PortTypeBody::PO_MESSAGE) {
3904 port_op.portref->error("Procedure-based operation `%s' is not "
3905 "applicable to a message-based port of type `%s'", stmt_name,
3906 port_type->get_typename().c_str());
3907 } else {
3908 port_op.portref->error("Port type `%s' does not have any outgoing "
3909 "signatures that support reply",
3910 port_type->get_typename().c_str());
3911 }
3912 }
3913 }
3914 if (port_op.r.redirect.value) {
3915 port_op.r.redirect.value->error("Value redirect cannot be used "
3916 "without signature template");
3917 chk_value_redirect(port_op.r.redirect.value, 0);
3918 }
3919 if (port_op.r.redirect.param) {
3920 port_op.r.redirect.param->error("Parameter redirect cannot be used "
3921 "without signature template");
3922 port_op.r.redirect.param->chk_erroneous();
3923 }
3924 }
3925 // checking from clause and sender redirect
3926 chk_from_clause(port_type);
3927 }
3928
3929 void Statement::chk_catch()
3930 {
3931 // determining statement type
3932 const char *stmt_name = get_stmt_name();
3933 Error_Context cntxt(this, "In %s statement", stmt_name);
3934 // checking the port reference
3935 Type *port_type = chk_port_ref(port_op.portref);
3936 // checking the signature reference, parameter and/or value redirect
3937 if (port_op.r.ctch.signature_ref) {
3938 // the signature reference is present
3939 port_op.r.ctch.signature =
3940 chk_signature_ref(port_op.r.ctch.signature_ref);
3941 // checking whether the signature is present on the incoming list
3942 // of the respective port type
3943 if (port_type) {
3944 PortTypeBody *port_type_body = port_type->get_PortBody();
3945 if (port_type_body->catch_allowed()) {
3946 TypeSet *out_sigs = port_type_body->get_out_sigs();
3947 if (port_op.r.ctch.signature) {
3948 if (!out_sigs->has_type(port_op.r.ctch.signature)) {
3949 port_op.r.ctch.signature_ref->error("Signature `%s' is not "
3950 "present on the outgoing list of port type `%s'",
3951 port_op.r.ctch.signature->get_typename().c_str(),
3952 port_type->get_typename().c_str());
3953 }
3954 } else if (out_sigs->get_nof_types() == 1) {
3955 // if the signature is unknown and the port type has exactly one
3956 // outgoing signature then use that for further checking
3957 port_op.r.ctch.signature =
3958 out_sigs->get_type_byIndex(0)->get_type_refd_last();
3959 }
3960 } else if (port_type_body->get_operation_mode() ==
3961 PortTypeBody::PO_MESSAGE) {
3962 port_op.portref->error("Procedure-based operation `%s' is not "
3963 "applicable to a message-based port of type `%s'", stmt_name,
3964 port_type->get_typename().c_str());
3965 } else {
3966 port_op.portref->error("Port type `%s' does not have any outgoing "
3967 "signatures that support exceptions",
3968 port_type->get_typename().c_str());
3969 }
3970 } else if (!port_op.portref) {
3971 // the statement refers to 'any port'
3972 port_op.r.rcvpar->error("Operation `any port.%s' cannot have parameter",
3973 stmt_name);
3974 if (port_op.r.redirect.value) {
3975 port_op.r.redirect.value->error("Operation `any port.%s' cannot have "
3976 "value redirect", stmt_name);
3977 }
3978 }
3979 // the receive parameter (template instance) must be also present
3980 // trying to determine type of the exception
3981 Type *exc_type = 0;
3982 bool exc_type_determined = false, value_redirect_checked = false;
3983 if (port_op.r.ctch.signature) {
3984 // the signature is known
3985 SignatureExceptions *exceptions =
3986 port_op.r.ctch.signature->get_signature_exceptions();
3987 if (exceptions) {
3988 if (exceptions->get_nof_types() == 1) {
3989 // the signature has exactly one exception type
3990 // use that for checking
3991 exc_type = exceptions->get_type_byIndex(0);
3992 } else {
3993 // the signature has more than one exception types
3994 exc_type = get_incoming_type(port_op.r.rcvpar,
3995 port_op.r.redirect.value, value_redirect_checked);
3996 if (exc_type) {
3997 size_t nof_comp_types =
3998 exceptions->get_nof_compatible_types(exc_type);
3999 if (nof_comp_types == 0) {
4000 port_op.r.rcvpar->error("Type `%s' is not present on the "
4001 "exception list of signature `%s'",
4002 exc_type->get_typename().c_str(),
4003 port_op.r.ctch.signature->get_typename().c_str());
4004 } else if (nof_comp_types > 1) {
4005 port_op.r.rcvpar->error("Type of the exception is ambiguous: "
4006 "`%s' is compatible with more than one exception types of "
4007 "signature `%s'", exc_type->get_typename().c_str(),
4008 port_op.r.ctch.signature->get_typename().c_str());
4009 }
4010 } else {
4011 port_op.r.rcvpar->error("Cannot determine the type of the "
4012 "exception");
4013 }
4014 }
4015 exc_type_determined = true;
4016 } else {
4017 port_op.r.ctch.signature_ref->error("Signature `%s' does not have "
4018 "exceptions", port_op.r.ctch.signature->get_typename().c_str());
4019 }
4020 }
4021 if (!exc_type_determined) {
4022 exc_type = get_incoming_type(port_op.r.rcvpar, port_op.r.redirect.value,
4023 value_redirect_checked);
4024 }
4025 if (!exc_type) exc_type = Type::get_pooltype(Type::T_ERROR);
4026 // check the template instance using the exception type
4027 port_op.r.rcvpar->chk(exc_type);
4028 // check the value redirect if it is not done so far
4029 if (!value_redirect_checked)
4030 chk_value_redirect(port_op.r.redirect.value, exc_type);
4031 // checking for invalid exception types
4032 exc_type = exc_type->get_type_refd_last();
4033 switch (exc_type->get_typetype()) {
4034 case Type::T_SIGNATURE:
4035 port_op.r.rcvpar->error("The type of catch parameter is signature "
4036 "`%s', which cannot be an exception type",
4037 exc_type->get_typename().c_str());
4038 break;
4039 case Type::T_PORT:
4040 port_op.r.rcvpar->error("The type of catch parameter is port type "
4041 "`%s', which cannot be an exception type",
4042 exc_type->get_typename().c_str());
4043 break;
4044 case Type::T_DEFAULT:
4045 port_op.r.rcvpar->error("The type of catch parameter is the `default' "
4046 "type, which cannot be an exception type");
4047 default:
4048 break;
4049 }
4050 } else {
4051 // the statement does not have signature reference
4052 if (port_op.r.ctch.timeout) {
4053 // the parameter is timeout
4054 if (port_op.portref) {
4055 // the port reference is present
4056 if (port_type) {
4057 PortTypeBody *port_type_body = port_type->get_PortBody();
4058 if (!port_type_body->getreply_allowed()) {
4059 // the port type is known and it does not allow blocking calls
4060 if (port_type_body->get_operation_mode() ==
4061 PortTypeBody::PO_MESSAGE) {
4062 port_op.portref->error("Timeout exception cannot be caught on "
4063 "a message-based port of type `%s'",
4064 port_type->get_typename().c_str());
4065 } else {
4066 port_op.portref->error("Timeout exception cannot be caught on "
4067 "a port of type `%s', which does not have any outgoing "
4068 "signatures that allow blocking calls",
4069 port_type->get_typename().c_str());
4070 }
4071 }
4072 }
4073 } else error("Timeout exception cannot be caught on `any port'");
4074 if (!port_op.r.ctch.in_call)
4075 error("Catching of `timeout' exception is not allowed in this "
4076 "context. It is permitted only in the response and exception "
4077 "handling part of `call' operations");
4078 else if (!port_op.r.ctch.call_has_timer)
4079 error("Catching of `timeout' exception is not allowed because the "
4080 "previous `call' operation does not have timer");
4081 if (port_op.r.fromclause) port_op.r.fromclause->error(
4082 "Operation `catch(timeout)' cannot have from clause");
4083 if (port_op.r.redirect.sender) port_op.r.redirect.sender->error(
4084 "Operation `catch(timeout)' cannot have sender redirect");
4085 } else {
4086 // the operation does not have any parameter
4087 if (port_type) {
4088 PortTypeBody *port_type_body = port_type->get_PortBody();
4089 if (!port_type_body->catch_allowed()) {
4090 // the port type is known and it does not have outgoing signatures
4091 if (port_type_body->get_operation_mode() ==
4092 PortTypeBody::PO_MESSAGE) {
4093 port_op.portref->error("Procedure-based operation `%s' is not "
4094 "applicable to a message-based port of type `%s'", stmt_name,
4095 port_type->get_typename().c_str());
4096 } else {
4097 port_op.portref->error("Port type `%s' does not have any "
4098 "outgoing signatures that support exceptions",
4099 port_type->get_typename().c_str());
4100 }
4101 }
4102 }
4103 }
4104 if (port_op.r.redirect.value) {
4105 // the statement does not have any parameter,
4106 // but the value redirect is present
4107 port_op.r.redirect.value->error("Value redirect cannot be used without "
4108 "signature and parameter");
4109 chk_value_redirect(port_op.r.redirect.value, 0);
4110 }
4111 }
4112 // checking from clause and sender redirect
4113 chk_from_clause(port_type);
4114 }
4115
4116 void Statement::chk_check()
4117 {
4118 Error_Context cntxt(this, "In check statement");
4119 Type *port_type = chk_port_ref(port_op.portref);
4120 if (port_type && !port_type->get_PortBody()->has_queue()) {
4121 // the port type is known and it does not have incoming queue
4122 port_op.portref->error("Port type `%s' does not have incoming queue "
4123 "because it has neither incoming messages nor incoming or outgoing "
4124 "signatures", port_type->get_typename().c_str());
4125 }
4126 // checking from clause and sender redirect
4127 chk_from_clause(port_type);
4128 }
4129
4130 void Statement::chk_clear()
4131 {
4132 Error_Context cntxt(this, "In clear port statement");
4133 Type *port_type = chk_port_ref(port_op.portref);
4134 if (port_type && !port_type->get_PortBody()->has_queue()) {
4135 // the port type is known and it does not have incoming queue
4136 port_op.portref->warning("Port type `%s' does not have incoming queue "
4137 "because it has neither incoming messages nor incoming or outgoing "
4138 "signatures", port_type->get_typename().c_str());
4139 }
4140 }
4141
4142 void Statement::chk_start_stop_port()
4143 {
4144 Error_Context cntxt(this, "In %s statement", get_stmt_name());
4145 chk_port_ref(port_op.portref);
4146 }
4147
4148 void Statement::chk_start_comp()
4149 {
4150 Error_Context cntxt(this, "In start test component statement");
4151 Type *comp_type = chk_comp_ref(comp_op.compref, false, false);
4152 Common::Assignment *t_ass = comp_op.funcinstref->get_refd_assignment();
4153 if (!t_ass) return;
4154 // checking whether the referred definition is a function
4155 Common::Assignment::asstype_t asstype = t_ass->get_asstype();
4156 switch (asstype) {
4157 case Common::Assignment::A_FUNCTION:
4158 case Common::Assignment::A_FUNCTION_RVAL:
4159 case Common::Assignment::A_FUNCTION_RTEMP:
4160 break;
4161 default:
4162 comp_op.funcinstref->error("Reference to a function was expected in the "
4163 "argument instead of %s", t_ass->get_description().c_str());
4164 return;
4165 }
4166 Def_Function *t_func = dynamic_cast<Def_Function*>(t_ass);
4167 if (!t_func) FATAL_ERROR("Statement::chk_start_comp()");
4168 // checking startability
4169 if (!t_func->chk_startable()) return;
4170 // checking the 'runs on' clause against the type of component reference
4171 Type *runs_on_type = t_func->get_RunsOnType();
4172 if (!comp_type || !runs_on_type) return;
4173 if (!runs_on_type->is_compatible(comp_type, NULL))
4174 comp_op.compref->error("Component type mismatch: The component reference "
4175 "is of type `%s', but %s runs on `%s'",
4176 comp_type->get_typename().c_str(), t_func->get_description().c_str(),
4177 runs_on_type->get_typename().c_str());
4178 // checking the return type
4179 switch (asstype) {
4180 case Common::Assignment::A_FUNCTION_RTEMP:
4181 comp_op.funcinstref->warning("Function `%s' returns a template of type "
4182 "`%s', which cannot be retrieved when the test component terminates",
4183 t_func->get_fullname().c_str(),
4184 t_func->get_Type()->get_typename().c_str());
4185 break;
4186 case Common::Assignment::A_FUNCTION_RVAL: {
4187 bool return_type_correct = false;
4188 Type *return_type = t_func->get_Type();
4189 for (Type *t = return_type; ; t = t->get_type_refd()) {
4190 if (t->has_done_attribute()) {
4191 return_type_correct = true;
4192 break;
4193 } else if (!t->is_ref()) break;
4194 }
4195 if (!return_type_correct)
4196 comp_op.funcinstref->warning("The return type of %s is `%s', which "
4197 "does not have the `done' extension attribute. When the test "
4198 "component terminates the returned value cannot be retrieved with "
4199 "a `done' operation", t_func->get_description().c_str(),
4200 return_type->get_typename().c_str());
4201 }
4202 default:
4203 break;
4204 }
4205 }
4206
4207 void Statement::chk_start_comp_refd()
4208 {
4209 Error_Context cntxt(this, "In start test component statement");
4210 Type *comp_type = chk_comp_ref(comp_op.compref, false, false);
4211 switch(comp_op.derefered.value->get_valuetype()){
4212 case Value::V_REFER:
4213 comp_op.derefered.value->error("A value of a function type was expected "
4214 "in the argument instead of a `refers' statement,"
4215 " which does not specify any function type");
4216 return;
4217 case Value::V_TTCN3_NULL:
4218 comp_op.derefered.value->error("A value of a function type was expected "
4219 "in the argument instead of a `null' value,"
4220 " which does not specify any function type");
4221 return;
4222 default:
4223 break;
4224 }
4225 Type *f_type = comp_op.derefered.value->get_expr_governor_last();
4226 if (!f_type) return;
4227 switch (f_type->get_typetype()) {
4228 case Type::T_ERROR:
4229 return;
4230 case Type::T_FUNCTION:
4231 break;
4232 default:
4233 comp_op.derefered.value->error("A value of type function was expected "
4234 "in the argument instead of `%s'", f_type->get_typename().c_str());
4235 return;
4236 }
4237 if (f_type->get_fat_runs_on_self()) {
4238 fau_refd.value->error("The argument cannot be a function reference with "
4239 "'runs on self' clause");
4240 return;
4241 }
4242 if(!f_type->chk_startability()) return;
4243 Type *runs_on_type = f_type->get_fat_runs_on_type();
4244 if (!comp_type || !runs_on_type) return;
4245 if (!runs_on_type->is_compatible(comp_type, NULL))
4246 comp_op.compref->error("Component type mismatch: The component reference "
4247 "is of type `%s', but functions of type `%s' run on `%s'",
4248 comp_type->get_typename().c_str(), f_type->get_typename().c_str(),
4249 runs_on_type->get_typename().c_str());
4250 Type *return_type = f_type->get_function_return_type();
4251 if (return_type) {
4252 if (f_type->get_returns_template()) {
4253 comp_op.derefered.value->warning("Functions of type `%s' return a "
4254 "template of type `%s', which cannot be retrieved when the test "
4255 "component terminates", f_type->get_typename().c_str(),
4256 return_type->get_typename().c_str());
4257 } else {
4258 bool return_type_correct = false;
4259 for (Type *t = return_type; ; t = t->get_type_refd()) {
4260 if (t->has_done_attribute()) {
4261 return_type_correct = true;
4262 break;
4263 } else if (!t->is_ref()) break;
4264 }
4265 if (!return_type_correct)
4266 comp_op.derefered.value->warning("The return type of function type "
4267 "`%s' is `%s', which does not have the `done' extension attribute. "
4268 "When the test component terminates the returned value cannot be "
4269 "retrieved with a `done' operation", f_type->get_typename().c_str(),
4270 return_type->get_typename().c_str());
4271 }
4272 }
4273 ActualParList *parlist = new ActualParList;
4274 Ttcn::FormalParList *fp_list = f_type->get_fat_parameters();
4275 if(fp_list->fold_named_and_chk(comp_op.derefered.t_list1, parlist)) {
4276 delete parlist;
4277 delete comp_op.derefered.t_list1;
4278 comp_op.derefered.ap_list2 = 0;
4279 } else {
4280 delete comp_op.derefered.t_list1;
4281 parlist->set_fullname(get_fullname());
4282 parlist->set_my_scope(my_sb);
4283 comp_op.derefered.ap_list2 = parlist;
4284 }
4285 }
4286
4287 void Statement::chk_stop_kill_comp()
4288 {
4289 Error_Context cntxt(this, "In %s statement", get_stmt_name());
4290 chk_comp_ref(comp_op.compref, true, false);
4291 }
4292
4293 void Statement::chk_done()
4294 {
4295 Error_Context cntxt(this, "In done statement");
4296 chk_comp_ref(comp_op.compref, false, false);
4297 if (!comp_op.compref) return;
4298 // value returning done can be used only when the statement contains a
4299 // specific component reference
4300 if (comp_op.donereturn.donematch) {
4301 bool value_redirect_checked = false;
4302 // try to determine the type of return value
4303 Type *return_type = get_incoming_type(comp_op.donereturn.donematch,
4304 comp_op.donereturn.redirect, value_redirect_checked);
4305 if (return_type) {
4306 bool return_type_correct = false;
4307 for (Type *t = return_type; ; t = t->get_type_refd()) {
4308 if (t->has_done_attribute()) {
4309 return_type_correct = true;
4310 break;
4311 } else if (!t->is_ref()) break;
4312 }
4313 if (!return_type_correct) {
4314 error("Return type `%s' does not have `done' extension attribute",
4315 return_type->get_typename().c_str());
4316 return_type = Type::get_pooltype(Type::T_ERROR);
4317 }
4318 } else {
4319 comp_op.donereturn.donematch->error("Cannot determine the return type "
4320 "for value returning done");
4321 return_type = Type::get_pooltype(Type::T_ERROR);
4322 }
4323 comp_op.donereturn.donematch->chk(return_type);
4324 if (!value_redirect_checked)
4325 chk_value_redirect(comp_op.donereturn.redirect, return_type);
4326 } else if (comp_op.donereturn.redirect) {
4327 comp_op.donereturn.redirect->error("Redirect cannot be used for the "
4328 "return value without a matching template");
4329 chk_value_redirect(comp_op.donereturn.redirect, 0);
4330 }
4331 }
4332
4333 void Statement::chk_killed()
4334 {
4335 Error_Context cntxt(this, "In killed statement");
4336 chk_comp_ref(comp_op.compref, false, false);
4337 }
4338
4339 void Statement::chk_connect()
4340 {
4341 Error_Context cntxt(this, "In %s statement", get_stmt_name());
4342 // checking endpoints
4343 Type *pt1, *pt2;
4344 PortTypeBody *ptb1, *ptb2;
4345 {
4346 Error_Context cntxt2(config_op.compref1, "In first endpoint");
4347 pt1 = chk_conn_endpoint(config_op.compref1, config_op.portref1, false);
4348 ptb1 = pt1 ? pt1->get_PortBody() : 0;
4349 }
4350 {
4351 Error_Context cntxt2(config_op.compref2, "In second endpoint");
4352 pt2 = chk_conn_endpoint(config_op.compref2, config_op.portref2, false);
4353 ptb2 = pt2 ? pt2->get_PortBody() : 0;
4354 }
4355 // checking consistency
4356 if (!ptb1 || !ptb2) return;
4357 if (!ptb1->is_connectable(ptb2) ||
4358 (ptb1 != ptb2 && !ptb2->is_connectable(ptb1))) {
4359 error("The connection between port types `%s' and `%s' is not consistent",
4360 pt1->get_typename().c_str(), pt2->get_typename().c_str());
4361 ptb1->report_connection_errors(ptb2);
4362 if (ptb1 != ptb2) ptb2->report_connection_errors(ptb1);
4363 }
4364 }
4365
4366 void Statement::chk_map()
4367 {
4368 Error_Context cntxt(this, "In %s statement", get_stmt_name());
4369 // checking endpoints
4370 Type *pt1, *pt2;
4371 PortTypeBody *ptb1, *ptb2;
4372 bool cref1_is_tc = false, cref1_is_system = false;
4373 bool cref2_is_tc = false, cref2_is_system = false;
4374 {
4375 Error_Context cntxt2(config_op.compref1, "In first endpoint");
4376 pt1 = chk_conn_endpoint(config_op.compref1, config_op.portref1, true);
4377 if (pt1) {
4378 ptb1 = pt1->get_PortBody();
4379 if (ptb1->is_internal()) {
4380 config_op.portref1->warning("Port type `%s' was marked as `internal'",
4381 pt1->get_typename().c_str());
4382 }
4383 } else ptb1 = 0;
4384 Value *cref1 = config_op.compref1->get_value_refd_last();
4385 if (cref1->get_valuetype() == Value::V_EXPR) {
4386 switch (cref1->get_optype()) {
4387 case Value::OPTYPE_COMP_MTC:
4388 case Value::OPTYPE_COMP_SELF:
4389 case Value::OPTYPE_COMP_CREATE:
4390 cref1_is_tc = true;
4391 break;
4392 case Value::OPTYPE_COMP_SYSTEM:
4393 cref1_is_system = true;
4394 default:
4395 break;
4396 }
4397 }
4398 }
4399 {
4400 Error_Context cntxt2(config_op.compref2, "In second endpoint");
4401 pt2 = chk_conn_endpoint(config_op.compref2, config_op.portref2, true);
4402 if (pt2) {
4403 ptb2 = pt2->get_PortBody();
4404 if (ptb2->is_internal()) {
4405 config_op.portref2->warning("Port type `%s' was marked as `internal'",
4406 pt2->get_typename().c_str());
4407 }
4408 } else ptb2 = 0;
4409 Value *cref2 = config_op.compref2->get_value_refd_last();
4410 if (cref2->get_valuetype() == Value::V_EXPR) {
4411 switch (cref2->get_optype()) {
4412 case Value::OPTYPE_COMP_MTC:
4413 case Value::OPTYPE_COMP_SELF:
4414 case Value::OPTYPE_COMP_CREATE:
4415 cref2_is_tc = true;
4416 break;
4417 case Value::OPTYPE_COMP_SYSTEM:
4418 cref2_is_system = true;
4419 default:
4420 break;
4421 }
4422 }
4423 }
4424 if (cref1_is_tc && cref2_is_tc) {
4425 error("Both endpoints of the mapping are test component ports");
4426 return;
4427 }
4428 if (cref1_is_system && cref2_is_system) {
4429 error("Both endpoints of the mapping are system ports");
4430 return;
4431 }
4432 // checking consistency
4433 if (!ptb1 || !ptb2) return;
4434 if (cref1_is_tc || cref2_is_system) {
4435 if (!ptb1->is_mappable(ptb2)) {
4436 error("The mapping between test component port type `%s' and system "
4437 "port type `%s' is not consistent", pt1->get_typename().c_str(),
4438 pt2->get_typename().c_str());
4439 ptb1->report_mapping_errors(ptb2);
4440 }
4441 } else if (cref2_is_tc || cref1_is_system) {
4442 if (!ptb2->is_mappable(ptb1)) {
4443 error("The mapping between system port type `%s' and test component "
4444 "port type `%s' is not consistent", pt1->get_typename().c_str(),
4445 pt2->get_typename().c_str());
4446 ptb2->report_mapping_errors(ptb1);
4447 }
4448 } else {
4449 // we have no idea which one is the system port
4450 if (!ptb1->is_mappable(ptb1) && !ptb2->is_mappable(ptb1)) {
4451 error("The mapping between port types `%s' and `%s' is not consistent",
4452 pt1->get_typename().c_str(), pt2->get_typename().c_str());
4453 }
4454 }
4455 }
4456
4457 void Statement::chk_start_timer()
4458 {
4459 Error_Context cntxt(this, "In start timer statement");
4460 chk_timer_ref(timer_op.timerref);
4461 if (timer_op.value) {
4462 // check the actual duration
4463 timer_op.value->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE);
4464 Value *t_val = timer_op.value->get_value_refd_last();
4465 if (t_val->get_valuetype() == Value::V_REAL) {
4466 ttcn3float v_real = t_val->get_val_Real();
4467 if (v_real < 0.0) {
4468 timer_op.value->error("The timer duration is negative: `%s'",
4469 Real2string(v_real).c_str());
4470 } else if (isSpecialFloatValue(v_real)) {
4471 timer_op.value->error("The timer duration cannot be %s",
4472 Real2string(v_real).c_str());
4473 }
4474 }
4475 } else {
4476 // check whether the timer has default duration
4477 Common::Assignment *t_ass = timer_op.timerref->get_refd_assignment();
4478 if (t_ass && t_ass->get_asstype() == Common::Assignment::A_TIMER) {
4479 Def_Timer *t_def_timer = dynamic_cast<Def_Timer*>(t_ass);
4480 if (!t_def_timer) FATAL_ERROR("Statement::chk_start_timer()");
4481 if (!t_def_timer->has_default_duration(
4482 timer_op.timerref->get_subrefs()))
4483 error("Missing duration: %s does not have default duration",
4484 t_ass->get_description().c_str());
4485 }
4486 }
4487 }
4488
4489 void Statement::chk_stop_timer_timeout()
4490 {
4491 Error_Context cntxt(this, "In %s statement", get_stmt_name());
4492 chk_timer_ref(timer_op.timerref);
4493 }
4494
4495 void Statement::chk_setverdict()
4496 {
4497 Error_Context cntxt(this, "In setverdict statement");
4498 if(!my_sb->get_my_def())
4499 error("Setverdict statement is not allowed in the control part");
4500 setverdict.verdictval->chk_expr_verdict(Type::EXPECTED_DYNAMIC_VALUE);
4501 Value *t_val = setverdict.verdictval->get_value_refd_last();
4502 if (t_val->get_valuetype() == Value::V_VERDICT &&
4503 t_val->get_val_verdict() == Value::Verdict_ERROR) {
4504 setverdict.verdictval->error("Error verdict cannot be set by the setverdict "
4505 "operation");
4506 }
4507 }
4508
4509 void Statement::chk_execute()
4510 {
4511 Error_Context cntxt(this, "In execute statement");
4512 Ref_pard *ref=testcase_inst.tcref;
4513 Common::Assignment *t_ass=ref->get_refd_assignment();
4514 if(!t_ass) goto error;
4515 if(t_ass->get_asstype()!=Common::Assignment::A_TESTCASE) {
4516 ref->error("Reference to a testcase was expected in the argument"
4517 " instead of %s", t_ass->get_description().c_str());
4518 goto error;
4519 }
4520 if(my_sb->get_scope_runs_on()) {
4521 ref->error("A definition that has `runs on' clause cannot "
4522 "execute testcases");
4523 goto error;
4524 }
4525 if (testcase_inst.timerval) {
4526 testcase_inst.timerval->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE);
4527 Value *t_val = testcase_inst.timerval->get_value_refd_last();
4528 if (t_val->get_valuetype() == Value::V_REAL) {
4529 ttcn3float v_real = t_val->get_val_Real();
4530 if (v_real < 0.0) {
4531 testcase_inst.timerval->error("The testcase guard "
4532 "timer has negative duration: `%s'", Real2string(v_real).c_str());
4533 } else if (isSpecialFloatValue(v_real)) {
4534 testcase_inst.timerval->error("The testcase guard "
4535 "timer duration cannot be %s", Real2string(v_real).c_str());
4536 }
4537 }
4538 }
4539 return;
4540 error:
4541 clean_up();
4542 statementtype=S_ERROR;
4543 }
4544
4545 void Statement::chk_execute_refd()
4546 {
4547 Error_Context cntxt(this, "In execute statement");
4548 switch(execute_refd.value->get_valuetype()){
4549 case Value::V_REFER:
4550 execute_refd.value->error("A value of a testcase type was expected "
4551 "in the argument instead of a `refers' statement,"
4552 " which does not specify any function type");
4553 return;
4554 case Value::V_TTCN3_NULL:
4555 execute_refd.value->error("A value of a testcase type was expected "
4556 "in the argument instead of a `null' value,"
4557 " which does not specify any function type");
4558 return;
4559 default:
4560 break;
4561 }
4562 Type *t = execute_refd.value->get_expr_governor_last();
4563 if (!t) goto error;
4564 switch (t->get_typetype()) {
4565 case Type::T_ERROR:
4566 goto error;
4567 case Type::T_TESTCASE:
4568 break;
4569 default:
4570 execute_refd.value->error("A value of type testcase was expected in the "
4571 "argument of `derefers()' instead of `%s'", t->get_typename().c_str());
4572 goto error;
4573 }
4574 if (my_sb->get_scope_runs_on()) {
4575 execute_refd.value->error("A definition that has `runs on' clause cannot "
4576 "execute testcases");
4577 goto error;
4578 } else {
4579 ActualParList *parlist = new ActualParList;
4580 Ttcn::FormalParList *fp_list = t->get_fat_parameters();
4581 bool is_erroneous = fp_list->chk_actual_parlist(execute_refd.t_list1,
4582 parlist);
4583 delete execute_refd.t_list1;
4584 if(is_erroneous) {
4585 delete parlist;
4586 execute_refd.ap_list2 = 0;
4587 goto error;
4588 }else {
4589 parlist->set_fullname(get_fullname());
4590 parlist->set_my_scope(my_sb);
4591 execute_refd.ap_list2 = parlist;
4592 }
4593 if(execute_refd.timerval) {
4594 execute_refd.timerval->chk_expr_float(Type::EXPECTED_DYNAMIC_VALUE);
4595 Value *t_val = execute_refd.timerval->get_value_refd_last();
4596 if(t_val->get_valuetype() == Value::V_REAL) {
4597 ttcn3float v_real = t_val->get_val_Real();
4598 if(v_real < 0.0) {
4599 execute_refd.value->error("The testcase guard "
4600 "timer has negative duration: `%s'", Real2string(v_real).c_str());
4601 } else if (isSpecialFloatValue(v_real)) {
4602 execute_refd.value->error("The testcase guard "
4603 "timer duration cannot be %s", Real2string(v_real).c_str());
4604 }
4605 }
4606 }
4607 }
4608 return;
4609 error:
4610 clean_up();
4611 statementtype=S_ERROR;
4612 }
4613
4614 Type *Statement::chk_port_ref(Reference *p_ref)
4615 {
4616 if (!my_sb->get_my_def())
4617 error("Port operation is not allowed in the control part");
4618 if (!p_ref) return 0;
4619 Common::Assignment *t_ass = p_ref->get_refd_assignment();
4620 if (!t_ass) return 0;
4621 switch (t_ass->get_asstype()) {
4622 case Common::Assignment::A_PORT: {
4623 ArrayDimensions *t_dims = t_ass->get_Dimensions();
4624 if (t_dims) t_dims->chk_indices(p_ref, "port", false,
4625 Type::EXPECTED_DYNAMIC_VALUE);
4626 else if (p_ref->get_subrefs()) p_ref->error("Reference to single %s "
4627 "cannot have field or array sub-references",
4628 t_ass->get_description().c_str());
4629 break; }
4630 case Common::Assignment::A_PAR_PORT:
4631 if (p_ref->get_subrefs()) p_ref->error("Reference to %s cannot have "
4632 "field or array sub-references", t_ass->get_description().c_str());
4633 break;
4634 default:
4635 p_ref->error("Reference to a port or port parameter was expected "
4636 "instead of %s", t_ass->get_description().c_str());
4637 return 0;
4638 }
4639 Type *ret_val = t_ass->get_Type();
4640 if (!ret_val) return 0;
4641 ret_val = ret_val->get_type_refd_last();
4642 if (ret_val->get_typetype() == Type::T_PORT) return ret_val;
4643 else return 0;
4644 }
4645
4646 void Statement::chk_to_clause(Type *port_type)
4647 {
4648 if (!port_op.s.toclause) return;
4649 // pointer to the address type
4650 Type *address_type;
4651 if (port_type) {
4652 // the port type is known
4653 address_type = port_type->get_PortBody()->get_address_type();
4654 } else {
4655 // the port type is unknown
4656 // address is permitted if it is visible from the current module
4657 address_type = my_sb->get_scope_mod()->get_address_type();
4658 }
4659 Error_Context cntxt(port_op.s.toclause, "In `to' clause");
4660 if (address_type) {
4661 // detect possible enumerated values (address may be an enumerated type)
4662 address_type->chk_this_value_ref(port_op.s.toclause);
4663 // try to figure out whether the argument is a component reference or
4664 // an SUT address
4665 bool is_address;
4666 Type *t_governor =
4667 port_op.s.toclause->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
4668 if (t_governor) is_address = address_type->is_compatible(t_governor, NULL);
4669 else is_address =
4670 port_op.s.toclause->get_expr_returntype(Type::EXPECTED_DYNAMIC_VALUE)
4671 != Type::T_COMPONENT;
4672 if (is_address) {
4673 // the argument is an address value
4674 port_op.s.toclause->set_my_governor(address_type);
4675 address_type->chk_this_value(port_op.s.toclause, 0,
4676 Type::EXPECTED_DYNAMIC_VALUE, INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED,
4677 SUB_CHK);
4678 } else {
4679 // the argument is not an address value, treat as a component reference
4680 chk_comp_ref(port_op.s.toclause, true, true);
4681 }
4682 } else {
4683 // usage of address is not allowed
4684 chk_comp_ref(port_op.s.toclause, true, true);
4685 }
4686 }
4687
4688 void Statement::chk_from_clause(Type *port_type)
4689 {
4690 if (!port_op.r.fromclause && !port_op.r.redirect.sender) return;
4691 // pointer to the address type
4692 Type *address_type;
4693 if (port_type) {
4694 // the port type is known
4695 address_type = port_type->get_PortBody()->get_address_type();
4696 } else if (port_op.portref) {
4697 // the operation refers to a specific port, but its type is unknown
4698 // address is permitted if it is visible from the current module
4699 address_type = my_sb->get_scope_mod()->get_address_type();
4700 } else {
4701 // the operation refers to 'any port'
4702 // address is not allowed
4703 address_type = 0;
4704 }
4705 bool sender_redirect_checked = false;
4706 Type *from_clause_type = 0;
4707 if (port_op.r.fromclause) {
4708 // the from clause is present
4709 Error_Context cntxt(port_op.r.fromclause, "In `from' clause");
4710 from_clause_type =
4711 port_op.r.fromclause->get_expr_governor(Type::EXPECTED_TEMPLATE);
4712 Template *templ_body = port_op.r.fromclause->get_Template();
4713 if (!from_clause_type) {
4714 // try to detect possible enumerated values
4715 if (address_type) address_type->chk_this_template_ref(templ_body);
4716 else templ_body->set_lowerid_to_ref();
4717 from_clause_type =
4718 templ_body->get_expr_governor(Type::EXPECTED_TEMPLATE);
4719 }
4720 if (!from_clause_type) {
4721 // trying to determine the type of template in from clause
4722 // based on the sender redirect
4723 from_clause_type = chk_sender_redirect(address_type);
4724 sender_redirect_checked = true;
4725 }
4726 if (!from_clause_type) {
4727 // trying to figure out whether the template is a component reference
4728 // or an SUT address
4729 bool is_compref;
4730 if (templ_body->get_expr_returntype(Type::EXPECTED_TEMPLATE)
4731 == Type::T_COMPONENT) is_compref = true;
4732 else {
4733 switch (templ_body->get_templatetype()) {
4734 case Template::SPECIFIC_VALUE:
4735 // treat 'null' as component reference
4736 if (templ_body->get_specific_value()->get_valuetype() ==
4737 Value::V_TTCN3_NULL) is_compref = true;
4738 else is_compref = false;
4739 break;
4740 case Template::ANY_VALUE:
4741 case Template::ANY_OR_OMIT:
4742 // treat generic wildcards ? and * as component references
4743 is_compref = true;
4744 break;
4745 default:
4746 is_compref = false;
4747 }
4748 }
4749 if (is_compref) {
4750 // the argument is a component reference: get a pool type
4751 from_clause_type = Type::get_pooltype(Type::T_COMPONENT);
4752 } else if (address_type) {
4753 // the argument is not a component reference: try the address type
4754 from_clause_type = address_type;
4755 }
4756 }
4757 if (from_clause_type) {
4758 // the type of from clause is known
4759 port_op.r.fromclause->chk(from_clause_type);
4760 if (!address_type
4761 || !address_type->is_compatible(from_clause_type, NULL)) {
4762 // from_clause_type must be a component type
4763 switch (from_clause_type->get_type_refd_last()->get_typetype()) {
4764 case Type::T_ERROR:
4765 // to avoid further errors in sender redirect
4766 from_clause_type = 0;
4767 case Type::T_COMPONENT:
4768 if (templ_body->get_templatetype() == Template::SPECIFIC_VALUE)
4769 chk_comp_ref(templ_body->get_specific_value(), true, true);
4770 break;
4771 default:
4772 port_op.r.fromclause->error("The type of the template should be a "
4773 "component type %sinstead of `%s'",
4774 address_type ? "or the `address' type " : "",
4775 from_clause_type->get_typename().c_str());
4776 // to avoid further errors in sender redirect
4777 from_clause_type = 0;
4778 }
4779 }
4780 } else {
4781 // the type of from clause is unknown
4782 port_op.r.fromclause->error("Cannot determine the type of the "
4783 "template");
4784 }
4785 }
4786 if (!sender_redirect_checked) {
4787 Type *sender_redirect_type = chk_sender_redirect(address_type);
4788 if (from_clause_type && sender_redirect_type &&
4789 !from_clause_type->is_identical(sender_redirect_type)) {
4790 error("The types in `from' clause and `sender' redirect are not the "
4791 "same: `%s' was expected instead of `%s'",
4792 from_clause_type->get_typename().c_str(),
4793 sender_redirect_type->get_typename().c_str());
4794 }
4795 }
4796 }
4797
4798 void Statement::chk_call_body(Type *port_type, Type *signature)
4799 {
4800 bool has_catch_timeout = false;
4801 // setting the flags whether 'catch(timeout)' statements are allowed
4802 for (size_t i = 0; i < port_op.s.call.body->get_nof_ags(); i++) {
4803 AltGuard *t_ag = port_op.s.call.body->get_ag_byIndex(i);
4804 if (t_ag->get_type() != AltGuard::AG_OP)
4805 FATAL_ERROR("Statement::chk_call_body()");
4806 Statement *t_stmt = t_ag->get_guard_stmt();
4807 if (t_stmt->statementtype == S_CATCH) {
4808 t_stmt->port_op.r.ctch.in_call = true;
4809 if (port_op.s.call.timer)
4810 t_stmt->port_op.r.ctch.call_has_timer = true;
4811 if (t_stmt->port_op.r.ctch.timeout) has_catch_timeout = true;
4812 }
4813 }
4814 Error_Context cntxt(this, "In response and exception handling part");
4815 port_op.s.call.body->set_my_laic_stmt(port_op.s.call.body, 0);
4816 port_op.s.call.body->set_my_ags(port_op.s.call.body);
4817 port_op.s.call.body->chk();
4818 if (port_type) {
4819 // checking whether getreply/catch operations refer to the same port
4820 // and same signature as the call operation
4821 for (size_t i = 0; i < port_op.s.call.body->get_nof_ags(); i++) {
4822 AltGuard *t_ag = port_op.s.call.body->get_ag_byIndex(i);
4823 if (t_ag->get_type() != AltGuard::AG_OP)
4824 FATAL_ERROR("Statement::chk_call_body()");
4825 Statement *t_stmt = t_ag->get_guard_stmt();
4826 if (t_stmt->statementtype == S_ERROR) continue;
4827 // checking port reference
4828 if (!t_stmt->port_op.portref) {
4829 t_stmt->error("The `%s' operation must refer to the same port as "
4830 "the previous `call' statement: `%s' was expected instead of "
4831 "`any port'", t_stmt->get_stmt_name(),
4832 port_op.portref->get_id()->get_dispname().c_str());
4833 } else if (*port_op.portref->get_id() !=
4834 *t_stmt->port_op.portref->get_id()) {
4835 t_stmt->port_op.portref->error("The `%s' operation refers to a "
4836 "different port than the previous `call' statement: `%s' was "
4837 "expected instead of `%s'", t_stmt->get_stmt_name(),
4838 port_op.portref->get_id()->get_dispname().c_str(),
4839 t_stmt->port_op.portref->get_id()->get_dispname().c_str());
4840 }
4841 // checking the signature
4842 switch (t_stmt->statementtype) {
4843 case S_GETREPLY:
4844 if (t_stmt->port_op.r.rcvpar) {
4845 Type *t_sig = t_stmt->port_op.r.rcvpar
4846 ->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
4847 if (!signature->is_compatible(t_sig, NULL))
4848 t_stmt->port_op.r.rcvpar->error("The `getreply' operation refers "
4849 "to a different signature than the previous `call' statement: "
4850 "`%s' was expected instead of `%s'",
4851 signature->get_typename().c_str(),
4852 t_sig->get_typename().c_str());
4853 }
4854 break;
4855 case S_CATCH:
4856 if (t_stmt->port_op.r.ctch.signature
4857 && !signature->is_compatible(t_stmt->port_op.r.ctch.signature, NULL))
4858 t_stmt->port_op.r.ctch.signature_ref->error("The `catch' "
4859 "operation refers to a different signature than the previous "
4860 "`call' statement: `%s' was expected instead of `%s'",
4861 signature->get_typename().c_str(),
4862 t_stmt->port_op.r.ctch.signature->get_typename().c_str());
4863 break;
4864 default:
4865 FATAL_ERROR("Statement::chk_call_body()");
4866 }
4867 }
4868 }
4869 if (port_op.s.call.timer && !has_catch_timeout)
4870 warning("The call operation has a timer, but the timeout exception is "
4871 "not caught");
4872 }
4873
4874 Type *Statement::get_outgoing_type(TemplateInstance *p_ti)
4875 {
4876 // first analyze the template instance as is
4877 Type *ret_val = p_ti->get_expr_governor(Type::EXPECTED_TEMPLATE);
4878 // return if this step was successful
4879 if (ret_val) return ret_val;
4880 // try to convert the undef identifier in the template instance to
4881 // a reference because it cannot be an enum value anymore
4882 Template *t_templ = p_ti->get_Template();
4883 t_templ->set_lowerid_to_ref();
4884 return t_templ->get_expr_governor(Type::EXPECTED_TEMPLATE);
4885 }
4886
4887 Type *Statement::get_incoming_type(TemplateInstance *p_ti,
4888 Reference *p_val_redir, bool& p_val_redir_checked)
4889 {
4890 // first analyze the template instance
4891 Type *ret_val = p_ti->get_expr_governor(Type::EXPECTED_TEMPLATE);
4892 // return if this step was successful
4893 if (ret_val) return ret_val;
4894 // use the variable in value redirect in the next step
4895 ret_val = chk_value_redirect(p_val_redir, 0);
4896 p_val_redir_checked = true;
4897 // return if this step was successful
4898 if (ret_val) return ret_val;
4899 // finally try to convert the undef identifier in the template instance to
4900 // a reference because it cannot be an enum value anymore
4901 Template *t_templ = p_ti->get_Template();
4902 t_templ->set_lowerid_to_ref();
4903 return t_templ->get_expr_governor(Type::EXPECTED_TEMPLATE);
4904 }
4905
4906 Type *Statement::chk_value_redirect(Reference *p_ref, Type *p_type)
4907 {
4908 if (!p_ref) return NULL;
4909 Error_Context cntxt(p_ref, "In `value' redirect");
4910 Type *t_var_type = p_ref->chk_variable_ref();
4911 if (p_type && t_var_type) {
4912 TypeCompatInfo info(my_sb->get_scope_mod(), p_type, t_var_type, true, false);
4913 if (p_ref->get_subrefs()) info.set_str2_elem(p_ref->get_subrefs()->refers_to_string_element());
4914 TypeChain l_chain;
4915 TypeChain r_chain;
4916 if (!p_type->is_compatible(t_var_type, &info, &l_chain, &r_chain)) {
4917 if (info.is_subtype_error()) {
4918 p_ref->error("%s", info.get_subtype_error().c_str());
4919 } else
4920 if (!info.is_erroneous()) {
4921 p_ref->error("Type mismatch in value redirect: "
4922 "A variable of type `%s' was expected instead of `%s'",
4923 p_type->get_typename().c_str(),
4924 t_var_type->get_typename().c_str());
4925 } else {
4926 p_ref->error("%s", info.get_error_str_str().c_str());
4927 }
4928 }
4929 }
4930 return t_var_type;
4931 }
4932
4933 Type *Statement::chk_sender_redirect(Type *address_type)
4934 {
4935 if (!port_op.r.redirect.sender) return 0;
4936 Error_Context cntxt(port_op.r.redirect.sender, "In `sender' redirect");
4937 Type *t_var_type = port_op.r.redirect.sender->chk_variable_ref();
4938 if (!t_var_type) return 0;
4939 if (!address_type || !address_type->is_identical(t_var_type)) {
4940 // t_var_type must be a component type
4941 switch (t_var_type->get_type_refd_last()->get_typetype()) {
4942 case Type::T_COMPONENT:
4943 break;
4944 case Type::T_ERROR:
4945 return 0;
4946 default:
4947 port_op.r.redirect.sender->error("The type of the variable should be "
4948 "a component type %sinstead of `%s'",
4949 address_type ? "or the `address' type " : "",
4950 t_var_type->get_typename().c_str());
4951 return 0;
4952 }
4953 }
4954 return t_var_type;
4955 }
4956
4957 Type *Statement::chk_signature_ref(Reference *p_ref)
4958 {
4959 if (!p_ref) FATAL_ERROR("Statement::chk_signature_ref()");
4960 Error_Context(p_ref, "In signature");
4961 Common::Assignment *t_ass = p_ref->get_refd_assignment();
4962 if (!t_ass) return 0;
4963 if (t_ass->get_asstype() != Common::Assignment::A_TYPE) {
4964 p_ref->error("Reference to a signature was expected instead of %s",
4965 t_ass->get_description().c_str());
4966 return 0;
4967 }
4968 Type *ret_val = t_ass->get_Type();
4969 if (!ret_val) return 0;
4970 ret_val = ret_val->get_field_type(p_ref->get_subrefs(),
4971 Type::EXPECTED_DYNAMIC_VALUE);
4972 if (!ret_val) return 0;
4973 ret_val = ret_val->get_type_refd_last();
4974 switch (ret_val->get_typetype()) {
4975 case Type::T_SIGNATURE:
4976 break;
4977 case Type::T_ERROR:
4978 return 0;
4979 case Type::T_PORT:
4980 p_ref->error("Reference to a signature was expected instead of port type "
4981 "`%s'", ret_val->get_typename().c_str());
4982 return 0;
4983 default:
4984 p_ref->error("Reference to a signature was expected instead of data type "
4985 "`%s'", ret_val->get_typename().c_str());
4986 return 0;
4987 }
4988 return ret_val;
4989 }
4990
4991 void Statement::chk_timer_ref(Reference *p_ref)
4992 {
4993 if (!p_ref) return;
4994 Common::Assignment *t_ass = p_ref->get_refd_assignment();
4995 if (!t_ass) return;
4996 switch (t_ass->get_asstype()) {
4997 case Common::Assignment::A_TIMER: {
4998 ArrayDimensions *t_dims = t_ass->get_Dimensions();
4999 if (t_dims) t_dims->chk_indices(p_ref, "timer", false,
5000 Type::EXPECTED_DYNAMIC_VALUE);
5001 else if (p_ref->get_subrefs()) p_ref->error("Reference to single %s "
5002 "cannot have field or array sub-references",
5003 t_ass->get_description().c_str());
5004 break; }
5005 case Common::Assignment::A_PAR_TIMER:
5006 if (p_ref->get_subrefs()) p_ref->error("Reference to %s cannot have "
5007 "field or array sub-references", t_ass->get_description().c_str());
5008 break;
5009 default:
5010 p_ref->error("Reference to a timer or timer parameter was expected "
5011 "instead of %s", t_ass->get_description().c_str());
5012 }
5013 }
5014
5015 Type *Statement::chk_comp_ref(Value *p_val, bool allow_mtc, bool allow_system)
5016 {
5017 if (!my_sb->get_my_def())
5018 error("Component operation is not allowed in the control part");
5019 if (!p_val) return 0;
5020 Value *v = p_val->get_value_refd_last();
5021 switch (v->get_valuetype()) {
5022 case Value::V_ERROR:
5023 return 0;
5024 case Value::V_REFD:
5025 break;
5026 case Value::V_INVOKE:
5027 if(p_val->get_expr_returntype() != Type::T_COMPONENT)
5028 p_val->error("A component reference was expected as return value");
5029 break;
5030 case Value::V_TTCN3_NULL:
5031 p_val->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
5032 break;
5033 case Value::V_EXPR:
5034 switch (v->get_optype()) {
5035 case Value::OPTYPE_COMP_NULL:
5036 p_val->error("The `null' component reference shall not be used in `%s' operation", get_stmt_name());
5037 break;
5038 case Value::OPTYPE_COMP_MTC:
5039 if (!allow_mtc)
5040 p_val->error("The `mtc' component reference shall not be used in `%s' operation", get_stmt_name());
5041 break;
5042 case Value::OPTYPE_COMP_SYSTEM:
5043 if (!allow_system)
5044 p_val->error("The `system' component reference shall not be used in `%s' operation", get_stmt_name());
5045 break;
5046 case Value::OPTYPE_COMP_SELF:
5047 case Value::OPTYPE_COMP_CREATE:
5048 break;
5049 default:
5050 p_val->error("A component reference was expected as operand");
5051 return 0;
5052 }
5053 break;
5054 default:
5055 p_val->error("A component reference was expected as operand");
5056 return 0;
5057 }
5058 Type *ret_val = p_val->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
5059 if (!ret_val) return 0;
5060 ret_val = ret_val->get_type_refd_last();
5061 switch (ret_val->get_typetype()) {
5062 case Type::T_ERROR:
5063 return 0;
5064 case Type::T_COMPONENT:
5065 return ret_val;
5066 default:
5067 p_val->error("Type mismatch: The type of the operand should be a "
5068 "component type instead of `%s'", ret_val->get_typename().c_str());
5069 return 0;
5070 }
5071 }
5072
5073 Type *Statement::chk_conn_endpoint(Value *p_compref, Reference *p_portref,
5074 bool allow_system)
5075 {
5076 Type *comp_type = chk_comp_ref(p_compref, true, allow_system);
5077 if (comp_type) {
5078 ComponentTypeBody *comp_body = comp_type->get_CompBody();
5079 p_portref->set_base_scope(comp_body);
5080 const Identifier& t_portid = *p_portref->get_id();
5081 if (!comp_body->has_local_ass_withId(t_portid)) {
5082 p_portref->error("Component type `%s' does not have port with name "
5083 "`%s'", comp_type->get_typename().c_str(),
5084 t_portid.get_dispname().c_str());
5085 return 0;
5086 }
5087 Common::Assignment *t_ass = comp_body->get_local_ass_byId(t_portid);
5088 if (t_ass->get_asstype() != Common::Assignment::A_PORT) {
5089 p_portref->error("Definition `%s' in component type `%s' is a %s and "
5090 "not a port", t_portid.get_dispname().c_str(),
5091 comp_type->get_typename().c_str(), t_ass->get_assname());
5092 return 0;
5093 }
5094 ArrayDimensions *t_dims = t_ass->get_Dimensions();
5095 if (t_dims) t_dims->chk_indices(p_portref, "port", false,
5096 Type::EXPECTED_DYNAMIC_VALUE);
5097 else if (p_portref->get_subrefs()) {
5098 p_portref->error("Port `%s' is not an array. The "
5099 "reference cannot have array indices",
5100 t_portid.get_dispname().c_str());
5101 }
5102 Type *port_type = t_ass->get_Type();
5103 if (port_type) {
5104 // check whether the external interface is provided by another port type
5105 PortTypeBody *port_body = port_type->get_PortBody();
5106 if (port_body->get_type() == PortTypeBody::PT_USER) {
5107 Type *provider_type = port_body->get_provider_type();
5108 if (provider_type) port_type = provider_type;
5109 }
5110 }
5111 return port_type;
5112 } else {
5113 // the component type cannot be determined
5114 FieldOrArrayRefs *t_subrefs = p_portref->get_subrefs();
5115 if (t_subrefs) {
5116 // check the array indices: they should be integers
5117 for (size_t i = 0; i < t_subrefs->get_nof_refs(); i++) {
5118 t_subrefs->get_ref(i)->get_val()
5119 ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE);
5120 }
5121 }
5122 return 0;
5123 }
5124 }
5125
5126 void Statement::set_code_section(
5127 GovernedSimple::code_section_t p_code_section)
5128 {
5129 switch(statementtype) {
5130 case S_ERROR:
5131 case S_DEF:
5132 case S_LABEL:
5133 case S_GOTO:
5134 case S_BREAK:
5135 case S_CONTINUE:
5136 case S_STOP_EXEC:
5137 case S_REPEAT:
5138 case S_START_PROFILER:
5139 case S_STOP_PROFILER:
5140 break;
5141 case S_ASSIGNMENT:
5142 ass->set_code_section(p_code_section);
5143 break;
5144 case S_FUNCTION_INSTANCE:
5145 case S_ALTSTEP_INSTANCE:
5146 case S_ACTIVATE:
5147 ref_pard->set_code_section(p_code_section);
5148 break;
5149 case S_BLOCK:
5150 block->set_code_section(p_code_section);
5151 break;
5152 case S_LOG:
5153 case S_ACTION:
5154 case S_STOP_TESTCASE:
5155 if (logargs) logargs->set_code_section(p_code_section);
5156 break;
5157 case S_IF:
5158 if_stmt.ics->set_code_section(p_code_section);
5159 if (if_stmt.elseblock)
5160 if_stmt.elseblock->set_code_section(p_code_section);
5161 break;
5162 case S_FOR:
5163 if (!loop.for_stmt.varinst)
5164 loop.for_stmt.init_ass->set_code_section(p_code_section);
5165 loop.for_stmt.finalexpr->set_code_section(p_code_section);
5166 loop.for_stmt.step->set_code_section(p_code_section);
5167 loop.block->set_code_section(p_code_section);
5168 break;
5169 case S_WHILE:
5170 case S_DOWHILE:
5171 loop.expr->set_code_section(p_code_section);
5172 loop.block->set_code_section(p_code_section);
5173 break;
5174 case S_SELECT:
5175 select.expr->set_code_section(p_code_section);
5176 select.scs->set_code_section(p_code_section);
5177 break;
5178 case S_ALT:
5179 case S_INTERLEAVE:
5180 ags->set_code_section(p_code_section);
5181 break;
5182 case S_RETURN:
5183 if (returnexpr.v) returnexpr.v->set_code_section(p_code_section);
5184 if (returnexpr.t) returnexpr.t->set_code_section(p_code_section);
5185 break;
5186 case S_DEACTIVATE:
5187 if (deactivate) deactivate->set_code_section(p_code_section);
5188 break;
5189 case S_SEND:
5190 port_op.portref->set_code_section(p_code_section);
5191 port_op.s.sendpar->set_code_section(p_code_section);
5192 if (port_op.s.toclause)
5193 port_op.s.toclause->set_code_section(p_code_section);
5194 break;
5195 case S_CALL:
5196 port_op.portref->set_code_section(p_code_section);
5197 port_op.s.sendpar->set_code_section(p_code_section);
5198 if (port_op.s.toclause)
5199 port_op.s.toclause->set_code_section(p_code_section);
5200 if (port_op.s.call.timer)
5201 port_op.s.call.timer->set_code_section(p_code_section);
5202 if (port_op.s.call.body)
5203 port_op.s.call.body->set_code_section(p_code_section);
5204 break;
5205 case S_REPLY:
5206 port_op.portref->set_code_section(p_code_section);
5207 port_op.s.sendpar->set_code_section(p_code_section);
5208 if (port_op.s.replyval)
5209 port_op.s.replyval->set_code_section(p_code_section);
5210 if (port_op.s.toclause)
5211 port_op.s.toclause->set_code_section(p_code_section);
5212 break;
5213 case S_RAISE:
5214 port_op.portref->set_code_section(p_code_section);
5215 port_op.s.sendpar->set_code_section(p_code_section);
5216 if (port_op.s.toclause)
5217 port_op.s.toclause->set_code_section(p_code_section);
5218 break;
5219 case S_RECEIVE:
5220 case S_CHECK_RECEIVE:
5221 case S_TRIGGER:
5222 if (port_op.portref) port_op.portref->set_code_section(p_code_section);
5223 if (port_op.r.rcvpar) port_op.r.rcvpar->set_code_section(p_code_section);
5224 if (port_op.r.fromclause)
5225 port_op.r.fromclause->set_code_section(p_code_section);
5226 if (port_op.r.redirect.value)
5227 port_op.r.redirect.value->set_code_section(p_code_section);
5228 if (port_op.r.redirect.sender)
5229 port_op.r.redirect.sender->set_code_section(p_code_section);
5230 break;
5231 case S_GETCALL:
5232 case S_CHECK_GETCALL:
5233 if (port_op.portref) port_op.portref->set_code_section(p_code_section);
5234 if (port_op.r.rcvpar) port_op.r.rcvpar->set_code_section(p_code_section);
5235 if (port_op.r.fromclause)
5236 port_op.r.fromclause->set_code_section(p_code_section);
5237 if (port_op.r.redirect.param)
5238 port_op.r.redirect.param->set_code_section(p_code_section);
5239 if (port_op.r.redirect.sender)
5240 port_op.r.redirect.sender->set_code_section(p_code_section);
5241 break;
5242 case S_GETREPLY:
5243 case S_CHECK_GETREPLY:
5244 if (port_op.portref) port_op.portref->set_code_section(p_code_section);
5245 if (port_op.r.rcvpar) port_op.r.rcvpar->set_code_section(p_code_section);
5246 if (port_op.r.getreply_valuematch)
5247 port_op.r.getreply_valuematch->set_code_section(p_code_section);
5248 if (port_op.r.fromclause)
5249 port_op.r.fromclause->set_code_section(p_code_section);
5250 if (port_op.r.redirect.value)
5251 port_op.r.redirect.value->set_code_section(p_code_section);
5252 if (port_op.r.redirect.param)
5253 port_op.r.redirect.param->set_code_section(p_code_section);
5254 if (port_op.r.redirect.sender)
5255 port_op.r.redirect.sender->set_code_section(p_code_section);
5256 break;
5257 case S_CATCH:
5258 case S_CHECK_CATCH:
5259 if (port_op.portref) port_op.portref->set_code_section(p_code_section);
5260 if (port_op.r.rcvpar) port_op.r.rcvpar->set_code_section(p_code_section);
5261 if (port_op.r.fromclause)
5262 port_op.r.fromclause->set_code_section(p_code_section);
5263 if (port_op.r.redirect.value)
5264 port_op.r.redirect.value->set_code_section(p_code_section);
5265 if (port_op.r.redirect.sender)
5266 port_op.r.redirect.sender->set_code_section(p_code_section);
5267 break;
5268 case S_CHECK:
5269 if (port_op.portref) port_op.portref->set_code_section(p_code_section);
5270 if (port_op.r.fromclause)
5271 port_op.r.fromclause->set_code_section(p_code_section);
5272 if (port_op.r.redirect.sender)
5273 port_op.r.redirect.sender->set_code_section(p_code_section);
5274 break;
5275 case S_CLEAR:
5276 case S_START_PORT:
5277 case S_STOP_PORT:
5278 case S_HALT:
5279 if (port_op.portref) port_op.portref->set_code_section(p_code_section);
5280 break;
5281 case S_START_COMP:
5282 comp_op.compref->set_code_section(p_code_section);
5283 comp_op.funcinstref->set_code_section(p_code_section);
5284 break;
5285 case S_START_COMP_REFD:
5286 comp_op.compref->set_code_section(p_code_section);
5287 comp_op.derefered.value->set_code_section(p_code_section);
5288 break;
5289 case S_STOP_COMP:
5290 case S_KILL:
5291 case S_KILLED:
5292 if (comp_op.compref) comp_op.compref->set_code_section(p_code_section);
5293 break;
5294 case S_DONE:
5295 if (comp_op.compref) {
5296 comp_op.compref->set_code_section(p_code_section);
5297 if (comp_op.donereturn.donematch)
5298 comp_op.donereturn.donematch->set_code_section(p_code_section);
5299 if (comp_op.donereturn.redirect)
5300 comp_op.donereturn.redirect->set_code_section(p_code_section);
5301 }
5302 break;
5303 case S_CONNECT:
5304 case S_MAP:
5305 case S_DISCONNECT:
5306 case S_UNMAP:
5307 config_op.compref1->set_code_section(p_code_section);
5308 config_op.portref1->set_code_section(p_code_section);
5309 config_op.compref2->set_code_section(p_code_section);
5310 config_op.portref2->set_code_section(p_code_section);
5311 break;
5312 case S_START_TIMER:
5313 timer_op.timerref->set_code_section(p_code_section);
5314 if (timer_op.value) timer_op.value->set_code_section(p_code_section);
5315 break;
5316 case S_STOP_TIMER:
5317 case S_TIMEOUT:
5318 if (timer_op.timerref)
5319 timer_op.timerref->set_code_section(p_code_section);
5320 break;
5321 case S_SETVERDICT:
5322 setverdict.verdictval->set_code_section(p_code_section);
5323 if (setverdict.logargs)
5324 setverdict.logargs->set_code_section(p_code_section);
5325 break;
5326 case S_TESTCASE_INSTANCE:
5327 testcase_inst.tcref->set_code_section(p_code_section);
5328 if (testcase_inst.timerval)
5329 testcase_inst.timerval->set_code_section(p_code_section);
5330 break;
5331 case S_TESTCASE_INSTANCE_REFD:
5332 execute_refd.value->set_code_section(p_code_section);
5333 if(execute_refd.timerval)
5334 execute_refd.timerval->set_code_section(p_code_section);
5335 break;
5336 case S_ACTIVATE_REFD:
5337 case S_FUNCTION_INVOKED:
5338 case S_ALTSTEP_INVOKED:
5339 fau_refd.value->set_code_section(p_code_section);
5340 if(fau_refd.ap_list2)
5341 for(size_t i = 0; i < fau_refd.ap_list2->get_nof_pars(); i++)
5342 fau_refd.ap_list2->get_par(i)->set_code_section(p_code_section);
5343 break;
5344 case S_STRING2TTCN:
5345 case S_INT2ENUM:
5346 convert_op.val->set_code_section(p_code_section);
5347 convert_op.ref->set_code_section(p_code_section);
5348 break;
5349 default:
5350 FATAL_ERROR("Statement::set_code_section()");
5351 } // switch statementtype
5352 }
5353
5354 char *Statement::generate_code(char *str)
5355 {
5356 switch (statementtype) {
5357 case S_BLOCK:
5358 case S_IF:
5359 case S_SELECT:
5360 case S_FOR:
5361 case S_WHILE:
5362 case S_DOWHILE:
5363 // conditional and loop statements do not need single location setting
5364 // the embedded expressions, statements have their own locations
5365 break;
5366 default:
5367 str = update_location_object(str);
5368 }
5369
5370 switch(statementtype) {
5371 case S_DEF:
5372 str=def->generate_code_str(str);
5373 break;
5374 case S_ASSIGNMENT:
5375 str=ass->generate_code(str);
5376 break;
5377 case S_FUNCTION_INSTANCE:
5378 case S_ALTSTEP_INSTANCE:
5379 str=generate_code_funcinst(str);
5380 break;
5381 case S_FUNCTION_INVOKED:
5382 case S_ALTSTEP_INVOKED:
5383 str=generate_code_invoke(str);
5384 break;
5385 case S_BLOCK:
5386 str=generate_code_block(str);
5387 break;
5388 case S_LOG:
5389 str=generate_code_log(str);
5390 break;
5391 case S_LABEL:
5392 str = generate_code_label(str);
5393 break;
5394 case S_GOTO:
5395 str = generate_code_goto(str);
5396 break;
5397 case S_IF:
5398 str=generate_code_if(str);
5399 break;
5400 case S_SELECT:
5401 str=generate_code_select(str);
5402 break;
5403 case S_FOR:
5404 str=generate_code_for(str);
5405 break;
5406 case S_WHILE:
5407 str=generate_code_while(str);
5408 break;
5409 case S_DOWHILE:
5410 str=generate_code_dowhile(str);
5411 break;
5412 case S_BREAK:
5413 str=generate_code_break(str);
5414 break;
5415 case S_CONTINUE:
5416 str=generate_code_continue(str);
5417 break;
5418 case S_STOP_EXEC:
5419 str=mputstr(str, "TTCN_Runtime::stop_execution();\n");
5420 break;
5421 case S_STOP_TESTCASE:
5422 str=generate_code_testcase_stop(str);
5423 break;
5424 case S_ALT:
5425 str=ags->generate_code_alt(str, *this);
5426 break;
5427 case S_REPEAT:
5428 str=generate_code_repeat(str);
5429 break;
5430 case S_INTERLEAVE:
5431 str=generate_code_interleave(str);
5432 break;
5433 case S_RETURN:
5434 str=generate_code_return(str);
5435 break;
5436 case S_ACTIVATE:
5437 str=generate_code_activate(str);
5438 break;
5439 case S_ACTIVATE_REFD:
5440 str=generate_code_activate_refd(str);
5441 break;
5442 case S_DEACTIVATE:
5443 str=generate_code_deactivate(str);
5444 break;
5445 case S_SEND:
5446 str = generate_code_send(str);
5447 break;
5448 case S_CALL:
5449 str = generate_code_call(str);
5450 break;
5451 case S_REPLY:
5452 str = generate_code_reply(str);
5453 break;
5454 case S_RAISE:
5455 str = generate_code_raise(str);
5456 break;
5457 case S_RECEIVE:
5458 case S_TRIGGER:
5459 case S_GETCALL:
5460 case S_GETREPLY:
5461 case S_CATCH:
5462 case S_CHECK:
5463 case S_CHECK_RECEIVE:
5464 case S_CHECK_GETCALL:
5465 case S_CHECK_GETREPLY:
5466 case S_CHECK_CATCH:
5467 case S_TIMEOUT:
5468 case S_DONE:
5469 case S_KILLED:
5470 str = generate_code_standalone(str);
5471 break;
5472 case S_CLEAR:
5473 str=generate_code_portop(str, "clear");
5474 break;
5475 case S_START_PORT:
5476 str=generate_code_portop(str, "start");
5477 break;
5478 case S_STOP_PORT:
5479 str=generate_code_portop(str, "stop");
5480 break;
5481 case S_HALT:
5482 str=generate_code_portop(str, "halt");
5483 break;
5484 case S_START_COMP:
5485 str=generate_code_startcomp(str);
5486 break;
5487 case S_START_COMP_REFD:
5488 str=generate_code_startcomp_refd(str);
5489 break;
5490 case S_STOP_COMP:
5491 str = generate_code_compop(str, "stop");
5492 break;
5493 case S_KILL:
5494 str = generate_code_compop(str, "kill");
5495 break;
5496 case S_CONNECT:
5497 str = generate_code_configop(str, "connect");
5498 break;
5499 case S_MAP:
5500 str = generate_code_configop(str, "map");
5501 break;
5502 case S_DISCONNECT:
5503 str = generate_code_configop(str, "disconnect");
5504 break;
5505 case S_UNMAP:
5506 str = generate_code_configop(str, "unmap");
5507 break;
5508 case S_START_TIMER:
5509 str=generate_code_starttimer(str);
5510 break;
5511 case S_STOP_TIMER:
5512 str=generate_code_stoptimer(str);
5513 break;
5514 case S_SETVERDICT:
5515 str=generate_code_setverdict(str);
5516 break;
5517 case S_ACTION:
5518 str=generate_code_action(str);
5519 break;
5520 case S_TESTCASE_INSTANCE:
5521 str=generate_code_testcaseinst(str);
5522 break;
5523 case S_TESTCASE_INSTANCE_REFD:
5524 str=generate_code_execute_refd(str);
5525 break;
5526 case S_STRING2TTCN:
5527 str=generate_code_string2ttcn(str);
5528 break;
5529 case S_INT2ENUM:
5530 str = generate_code_int2enum(str);
5531 break;
5532 case S_START_PROFILER:
5533 str = mputstr(str, "ttcn3_prof.start();\n");
5534 break;
5535 case S_STOP_PROFILER:
5536 str = mputstr(str, "ttcn3_prof.stop();\n");
5537 break;
5538 default:
5539 FATAL_ERROR("Statement::generate_code()");
5540 } // switch
5541 return str;
5542 }
5543
5544 char* Statement::generate_code_string2ttcn(char *str)
5545 {
5546 expression_struct val_expr;
5547 Code::init_expr(&val_expr);
5548 convert_op.val->generate_code_expr(&val_expr);
5549
5550 expression_struct ref_expr;
5551 Code::init_expr(&ref_expr);
5552 convert_op.ref->generate_code(&ref_expr);
5553
5554 str = mputstr(str, val_expr.preamble);
5555 str = mputstr(str, ref_expr.preamble);
5556
5557 str = mputprintf(str, "string_to_ttcn(%s,%s);\n", val_expr.expr, ref_expr.expr);
5558
5559 str = mputstr(str, val_expr.postamble);
5560 str = mputstr(str, ref_expr.postamble);
5561
5562 Code::free_expr(&val_expr);
5563 Code::free_expr(&ref_expr);
5564
5565 return str;
5566 }
5567
5568 char* Statement::generate_code_int2enum(char* str)
5569 {
5570 expression_struct val_expr;
5571 Code::init_expr(&val_expr);
5572 convert_op.val->generate_code_expr(&val_expr);
5573
5574 expression_struct ref_expr;
5575 Code::init_expr(&ref_expr);
5576 convert_op.ref->generate_code(&ref_expr);
5577
5578 // check if the reference is an optional field
5579 bool is_optional = false;
5580 FieldOrArrayRefs* subrefs = convert_op.ref->get_subrefs();
5581 if (NULL != subrefs) {
5582 Type* ref_type = convert_op.ref->get_refd_assignment()->get_Type()->get_type_refd_last();
5583 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
5584 FieldOrArrayRef* subref = subrefs->get_ref(i);
5585 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
5586 ref_type = ref_type->get_ofType()->get_type_refd_last();
5587 }
5588 else { // FIELD_REF
5589 CompField* cf = ref_type->get_comp_byName(*subref->get_id());
5590 if (i == subrefs->get_nof_refs() - 1 && cf->get_is_optional()) {
5591 is_optional = true;
5592 }
5593 ref_type = cf->get_type()->get_type_refd_last();
5594 }
5595 }
5596 }
5597
5598 str = mputstr(str, val_expr.preamble);
5599 str = mputstr(str, ref_expr.preamble);
5600
5601 str = mputprintf(str, "%s%s.int2enum(%s);\n", ref_expr.expr,
5602 is_optional ? "()" : "", val_expr.expr);
5603
5604 str = mputstr(str, val_expr.postamble);
5605 str = mputstr(str, ref_expr.postamble);
5606
5607 Code::free_expr(&val_expr);
5608 Code::free_expr(&ref_expr);
5609
5610 return str;
5611 }
5612
5613 void Statement::generate_code_expr(expression_struct *expr)
5614 {
5615 switch (statementtype) {
5616 case S_RECEIVE:
5617 generate_code_expr_receive(expr, "receive");
5618 break;
5619 case S_TRIGGER:
5620 generate_code_expr_receive(expr, "trigger");
5621 break;
5622 case S_CHECK_RECEIVE:
5623 generate_code_expr_receive(expr, "check_receive");
5624 break;
5625 case S_GETCALL:
5626 generate_code_expr_getcall(expr, "getcall");
5627 break;
5628 case S_CHECK_GETCALL:
5629 generate_code_expr_getcall(expr, "check_getcall");
5630 break;
5631 case S_GETREPLY:
5632 generate_code_expr_getreply(expr, "getreply");
5633 break;
5634 case S_CHECK_GETREPLY:
5635 generate_code_expr_getreply(expr, "check_getreply");
5636 break;
5637 case S_CATCH:
5638 case S_CHECK_CATCH:
5639 generate_code_expr_catch(expr);
5640 break;
5641 case S_CHECK:
5642 generate_code_expr_check(expr);
5643 break;
5644 case S_DONE:
5645 generate_code_expr_done(expr);
5646 break;
5647 case S_KILLED:
5648 generate_code_expr_killed(expr);
5649 break;
5650 case S_TIMEOUT:
5651 generate_code_expr_timeout(expr);
5652 break;
5653 default:
5654 FATAL_ERROR("Statement::generate_code_expr()");
5655 } //switch
5656 }
5657
5658 void Statement::ilt_generate_code(ILT *ilt)
5659 {
5660 switch (statementtype) {
5661 case S_INTERLEAVE:
5662 ilt_generate_code_interleave(ilt);
5663 return;
5664 case S_ALT:
5665 ilt_generate_code_alt(ilt);
5666 return;
5667 case S_DEF:
5668 ilt_generate_code_def(ilt);
5669 return;
5670 default:
5671 break;
5672 } // switch
5673 if (is_receiving_stmt()) {
5674 ilt_generate_code_receiving(ilt);
5675 return;
5676 }
5677 if (!has_receiving_stmt()) {
5678 char*& str=ilt->get_out_branches();
5679 str=generate_code(str);
5680 return;
5681 }
5682 switch (statementtype) {
5683 case S_BLOCK:
5684 block->ilt_generate_code(ilt);
5685 break;
5686 case S_IF:
5687 ilt_generate_code_if(ilt);
5688 break;
5689 case S_SELECT:
5690 ilt_generate_code_select(ilt);
5691 break;
5692 case S_CALL:
5693 ilt_generate_code_call(ilt);
5694 break;
5695 case S_FOR:
5696 ilt_generate_code_for(ilt);
5697 break;
5698 case S_WHILE:
5699 ilt_generate_code_while(ilt);
5700 break;
5701 case S_DOWHILE:
5702 ilt_generate_code_dowhile(ilt);
5703 break;
5704 default:
5705 FATAL_ERROR("Statement::ilt_generate_code()");
5706 } // switch statementtype
5707 }
5708
5709 char *Statement::generate_code_standalone(char *str)
5710 {
5711 const string& tmplabel = my_sb->get_scope_mod_gen()->get_temporary_id();
5712 const char *label_str = tmplabel.c_str();
5713 str = mputprintf(str, "{\n"
5714 "%s:\n", label_str);
5715 expression_struct expr;
5716 Code::init_expr(&expr);
5717 generate_code_expr(&expr);
5718 str = mputstr(str, expr.preamble);
5719 str = mputprintf(str, "alt_status alt_flag = ALT_UNCHECKED, "
5720 "default_flag = ALT_UNCHECKED;\n"
5721 "TTCN_Snapshot::take_new(FALSE);\n"
5722 "for ( ; ; ) {\n"
5723 "if (alt_flag != ALT_NO) {\n"
5724 "alt_flag = %s;\n"
5725 "if (alt_flag == ALT_YES) break;\n", expr.expr);
5726 if (can_repeat()) {
5727 str = mputprintf(str, "else if (alt_flag == ALT_REPEAT) goto %s;\n",
5728 label_str);
5729 }
5730 str = mputprintf(str, "}\n"
5731 "if (default_flag != ALT_NO) {\n"
5732 "default_flag = TTCN_Default::try_altsteps();\n"
5733 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) break;\n"
5734 "else if (default_flag == ALT_REPEAT) goto %s;\n"
5735 "}\n", label_str);
5736 str = update_location_object(str);
5737 str = mputprintf(str, "if (alt_flag == ALT_NO && default_flag == ALT_NO) "
5738 "TTCN_error(\"Stand-alone %s statement failed in file ", get_stmt_name());
5739 str = Code::translate_string(str, get_filename());
5740 int first_line = get_first_line(), last_line = get_last_line();
5741 if (first_line < last_line) str = mputprintf(str,
5742 " between lines %d and %d", first_line, last_line);
5743 else str = mputprintf(str, ", line %d", first_line);
5744 str = mputstr(str, ".\");\n"
5745 "TTCN_Snapshot::take_new(TRUE);\n"
5746 "}\n");
5747 str = mputstr(str, expr.postamble);
5748 str = mputstr(str, "}\n");
5749 Code::free_expr(&expr);
5750 return str;
5751 }
5752
5753 char *Statement::generate_code_funcinst(char *str)
5754 {
5755 expression_struct expr;
5756 Code::init_expr(&expr);
5757 ref_pard->generate_code_const_ref(&expr);
5758 str=Code::merge_free_expr(str, &expr);
5759 return str;
5760 }
5761
5762 char* Statement::generate_code_invoke(char *str)
5763 {
5764 expression_struct expr;
5765 Code::init_expr(&expr);
5766 Value *last_v = fau_refd.value->get_value_refd_last();
5767 switch(last_v->get_valuetype()) {
5768 case Value::V_FUNCTION:
5769 case Value::V_ALTSTEP: {
5770 Common::Assignment *t_fat = last_v->get_refd_fat();
5771 expr.expr = mputprintf(expr.expr, "%s(",
5772 t_fat->get_genname_from_scope(my_sb).c_str());
5773 fau_refd.ap_list2->generate_code_alias(&expr, t_fat->get_FormalParList(),
5774 t_fat->get_RunsOnType(), false);
5775 break; }
5776 default: {
5777 fau_refd.value->generate_code_expr_mandatory(&expr);
5778 Type *t_governor = fau_refd.value->get_expr_governor_last();
5779 expr.expr = mputprintf(expr.expr, ".%s(",
5780 t_governor->get_typetype() == Type::T_ALTSTEP ?
5781 "invoke_standalone" : "invoke");
5782 fau_refd.ap_list2->generate_code_alias(&expr, 0,
5783 t_governor->get_fat_runs_on_type(),
5784 t_governor->get_fat_runs_on_self()); }
5785 }
5786 expr.expr = mputc(expr.expr, ')');
5787 str=Code::merge_free_expr(str, &expr);
5788 return str;
5789 }
5790
5791 char *Statement::generate_code_block(char *str)
5792 {
5793 switch (block->get_exception_handling()) {
5794 case StatementBlock::EH_NONE:
5795 break;
5796 case StatementBlock::EH_TRY:
5797 str = mputstr(str, "try ");
5798 break;
5799 case StatementBlock::EH_CATCH:
5800 str = mputstr(str, "catch (const TTCN_Error& ttcn_error) ");
5801 break;
5802 default:
5803 FATAL_ERROR("Statement::generate_code_block()");
5804 }
5805 if (block->get_nof_stmts() > 0 || block->get_exception_handling()!=StatementBlock::EH_NONE) {
5806 str = mputstr(str, "{\n");
5807 str = block->generate_code(str);
5808 str = mputstr(str, "}\n");
5809 } else str = mputstr(str, "/* empty block */;\n");
5810 return str;
5811 }
5812
5813 char *Statement::generate_code_log(char *str)
5814 {
5815 if (logargs) {
5816 bool buffered_mode = true;
5817 if (logargs->get_nof_logargs() == 1) {
5818 LogArgument *first_logarg = logargs->get_logarg_byIndex(0);
5819 switch (first_logarg->get_type()) {
5820 case LogArgument::L_STR:
5821 // the argument is a simple string: use non-buffered mode
5822 str = mputstr(str, "TTCN_Logger::log_str(TTCN_USER, \"");
5823 str = Code::translate_string(str, first_logarg->get_str().c_str());
5824 str = mputstr(str, "\");\n");
5825 buffered_mode = false;
5826 break;
5827 case LogArgument::L_MACRO: {
5828 Value *t_val = first_logarg->get_val();
5829 if (t_val->has_single_expr()) {
5830 // the argument is a simple macro call: use non-buffered mode
5831 str = mputprintf(str, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5832 t_val->get_single_expr().c_str());
5833 buffered_mode = false;
5834 } }
5835 default:
5836 break;
5837 }
5838 }
5839 if (buffered_mode) {
5840 // the argument is a complicated construct: use buffered mode
5841 str = mputstr(str, "try {\n"
5842 "TTCN_Logger::begin_event(TTCN_USER);\n");
5843 str = logargs->generate_code(str);
5844 str = mputstr(str, "TTCN_Logger::end_event();\n"
5845 "} catch (...) {\n"
5846 "TTCN_Logger::finish_event();\n"
5847 "throw;\n"
5848 "}\n");
5849 }
5850 } else {
5851 // the argument is missing
5852 str = mputstr(str, "TTCN_Logger::log_str(TTCN_USER, "
5853 "\"<empty log statement>\");\n");
5854 }
5855 return str;
5856 }
5857
5858 char *Statement::generate_code_testcase_stop(char *str)
5859 {
5860 if (logargs) str = generate_code_log(str);
5861 str = mputstr(str, "TTCN_error(\"testcase.stop\");\n");
5862 return str;
5863 }
5864
5865 char *Statement::generate_code_label(char *str)
5866 {
5867 if (label.used) {
5868 return mputprintf(str, "%s: /* TTCN-3 label: %s */;\n",
5869 get_clabel().c_str(), label.id->get_dispname().c_str());
5870 } else {
5871 return mputprintf(str, "/* unused TTCN-3 label: %s */;\n",
5872 label.id->get_dispname().c_str());
5873 }
5874 }
5875
5876 char *Statement::generate_code_goto(char *str)
5877 {
5878 if (!go_to.label) FATAL_ERROR("Statement::generate_code_goto()");
5879 return mputprintf(str, "goto %s; /* TTCN-3 label: %s */\n",
5880 go_to.label->get_clabel().c_str(), go_to.id->get_dispname().c_str());
5881 return str;
5882 }
5883
5884 char* Statement::generate_code_if(char *str)
5885 {
5886 size_t blockcount=0;
5887 bool unreach=false, eachfalse=true;
5888 str=if_stmt.ics->generate_code(str, blockcount, unreach, eachfalse);
5889 if(if_stmt.elseblock && !unreach) {
5890 if(!eachfalse) str=mputstr(str, "else ");
5891 eachfalse=false;
5892 str=mputstr(str, "{\n");
5893 blockcount++;
5894 str=if_stmt.elseblock->generate_code(str);
5895 }
5896 while(blockcount-->0) str=mputstr(str, "}\n");
5897 if(eachfalse) str=mputstr(str, "/* never occurs */;\n");
5898 return str;
5899 }
5900
5901 char* Statement::generate_code_select(char *str)
5902 {
5903 const string& tmp_prefix = my_sb->get_scope_mod_gen()->get_temporary_id();
5904 char *expr_init=memptystr();
5905 char *expr_name=select.expr->generate_code_tmp(0, expr_init);
5906 if (expr_init[0]) { // some init code was generated
5907 str = update_location_object(str);
5908 str = mputstr(str, "{\n");
5909 str = mputstr(str, expr_init);
5910 }
5911 str=select.scs->generate_code(str, tmp_prefix.c_str(), expr_name);
5912 Free(expr_name);
5913 if (expr_init[0]) str=mputstr(str, "}\n");
5914 Free(expr_init);
5915 return str;
5916 }
5917
5918 char *Statement::generate_code_for(char *str)
5919 {
5920 /** \todo initial does not have its own location */
5921 // statements in initial may have side effects
5922 // generate code for them anyway
5923 if (loop.for_stmt.varinst) {
5924 str = mputstr(str, "{\n");
5925 str = loop.for_stmt.init_varinst->generate_code_str(str);
5926 } else {
5927 str = loop.for_stmt.init_ass->update_location_object(str);
5928 str = loop.for_stmt.init_ass->generate_code(str);
5929 }
5930 // check whether the final expression is constant
5931 bool final_is_true = false, final_is_false = false;
5932 if (!loop.for_stmt.finalexpr->is_unfoldable()) {
5933 if (loop.for_stmt.finalexpr->get_val_bool()) final_is_true = true;
5934 else final_is_false = true;
5935 }
5936 if (final_is_false) str = mputstr(str, "/* never occurs */;\n");
5937 else {
5938 if (loop.has_cnt)
5939 loop.label_next =
5940 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
5941 str = update_location_object(str);
5942 str = mputstr(str, "for ( ; ; ) {\n");
5943 // do not generate the exit condition for infinite loops
5944 if (!final_is_true) {
5945 str = loop.for_stmt.finalexpr->update_location_object(str);
5946 size_t blockcount = 0;
5947 str = loop.for_stmt.finalexpr->generate_code_tmp(str, "if (!",
5948 blockcount);
5949 str = mputstr(str, ") break;\n");
5950 while (blockcount-- > 0) str = mputstr(str, "}\n");
5951 }
5952 if (loop.label_next) str = mputstr(str, "{\n");
5953 str = loop.block->generate_code(str);
5954 if (loop.label_next)
5955 str = mputprintf(str, "}\n"
5956 "%s:\n", loop.label_next->c_str());
5957 str = loop.for_stmt.step->update_location_object(str);
5958 str = loop.for_stmt.step->generate_code(str);
5959 str = mputstr(str, "}\n");
5960 }
5961 if (loop.for_stmt.varinst) str = mputstr(str, "}\n");
5962 return str;
5963 }
5964
5965 char *Statement::generate_code_while(char *str)
5966 {
5967 // check whether the expression is constant
5968 bool condition_always_true = false, condition_always_false = false;
5969 if (!loop.expr->is_unfoldable()) {
5970 if (loop.expr->get_val_bool()) condition_always_true = true;
5971 else condition_always_false = true;
5972 }
5973 if (condition_always_false) str = mputstr(str, "/* never occurs */;\n");
5974 else {
5975 str = mputstr(str, "for ( ; ; ) {\n");
5976 if (loop.has_cnt_in_ags) {
5977 loop.label_next =
5978 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
5979 str = mputprintf(str, "%s:\n", loop.label_next->c_str());
5980 }
5981 // do not generate the exit condition for infinite loops
5982 if (!condition_always_true) {
5983 str = loop.expr->update_location_object(str);
5984 size_t blockcount = 0;
5985 str = loop.expr->generate_code_tmp(str, "if (!", blockcount);
5986 str = mputstr(str, ") break;\n");
5987 while(blockcount-- > 0) str = mputstr(str, "}\n");
5988 }
5989 str = loop.block->generate_code(str);
5990 str = mputstr(str, "}\n");
5991 }
5992 return str;
5993 }
5994
5995 char *Statement::generate_code_dowhile(char *str)
5996 {
5997 // check whether the expression is constant
5998 bool expr_is_const = !loop.expr->is_unfoldable();
5999 bool is_infinite_loop = false;
6000 if (expr_is_const) {
6001 if (loop.expr->get_val_bool()) is_infinite_loop = true;
6002 else loop.iterate_once = true;
6003 }
6004 if (loop.iterate_once && !loop.has_brk && !loop.has_cnt) {
6005 str = mputstr(str, "{\n");
6006 str = loop.block->generate_code(str);
6007 } else {
6008 str = mputstr(str, "for ( ; ; ) {\n");
6009 if (loop.has_cnt_in_ags || (!expr_is_const && loop.has_cnt))
6010 loop.label_next =
6011 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
6012 if (loop.label_next && is_infinite_loop)
6013 str = mputprintf(str, "%s:\n", loop.label_next->c_str());
6014 if (loop.label_next && !is_infinite_loop) str = mputstr(str, "{\n");
6015 str = loop.block->generate_code(str);
6016 // do not generate the exit condition for infinite loops
6017 if (!is_infinite_loop) {
6018 if (loop.label_next)
6019 str = mputprintf(str, "}\n"
6020 "%s:\n", loop.label_next->c_str());
6021 str = loop.expr->update_location_object(str);
6022 if (loop.iterate_once) str = mputstr(str, "break;\n");
6023 else {
6024 size_t blockcount = 0;
6025 str = loop.expr->generate_code_tmp(str, "if (!", blockcount);
6026 str = mputstr(str, ") break;\n");
6027 while (blockcount-- > 0) str = mputstr(str, "}\n");
6028 }
6029 }
6030 }
6031 str = mputstr(str, "}\n");
6032 return str;
6033 }
6034
6035 char *Statement::generate_code_break(char *str)
6036 {
6037 // in altstep (2 (=2nd if branch))
6038 // in alt and loops - not inside interleave (4)
6039 // in loops without receiving statement embedded in interleave (4)
6040 // in loops with receiving statement embedded in interleave (1)
6041 // in interleave when not embedded in enclosed loop or alt/interleave (4)
6042 // in alt/interleave embedded in interleave (3)
6043 if (brk_cnt.loop_stmt && brk_cnt.loop_stmt->loop.il_label_end)
6044 str=mputprintf(str, "goto %s;\n",
6045 brk_cnt.loop_stmt->loop.il_label_end->c_str());
6046 else if (brk_cnt.ags && brk_cnt.ags->get_is_altstep())
6047 str=mputstr(str, "return ALT_BREAK;\n");
6048 else if (brk_cnt.ags && brk_cnt.ags->get_il_label_end())
6049 str=mputprintf(str, "goto %s;\n",
6050 brk_cnt.ags->get_il_label_end()->c_str());
6051 else
6052 str=mputstr(str, "break;\n");
6053 return str;
6054 }
6055
6056 char *Statement::generate_code_continue(char *str)
6057 {
6058 // not inside interleave when continue is not inside embedded ags (2 or 1)
6059 // continue is inside ags enclosed in the loop (3)
6060 // in interleave (3, 2 or 1)
6061 if (brk_cnt.loop_stmt != 0) {
6062 if (brk_cnt.loop_stmt->loop.iterate_once && !brk_cnt.ags &&
6063 !brk_cnt.loop_stmt->loop.is_ilt)
6064 str=mputstr(str, "break;\n");
6065 else {
6066 if (!brk_cnt.loop_stmt->loop.label_next)
6067 str=mputstr(str, "continue;\n");
6068 else
6069 str=mputprintf(str, "goto %s;\n",
6070 brk_cnt.loop_stmt->loop.label_next->c_str());
6071 }
6072 } else
6073 FATAL_ERROR("Statement::generate_code_continue()");
6074 return str;
6075 }
6076
6077 char *Statement::generate_code_repeat(char *str)
6078 {
6079 string *tmplabel=ags->get_label();
6080 if(!tmplabel) str=mputstr(str, "return ALT_REPEAT;\n");
6081 else str=mputprintf(str, "goto %s;\n", tmplabel->c_str());
6082 return str;
6083 }
6084
6085 char* Statement::generate_code_interleave(char *str)
6086 {
6087 ILT_root ilt(this);
6088 str=ilt.generate_code(str);
6089 return str;
6090 }
6091
6092 void Statement::ilt_generate_code_interleave(ILT *ilt)
6093 {
6094 const string& mytmpid=ilt->get_my_tmpid();
6095 bool toplevel=ilt->is_toplevel();
6096 size_t goto_label_num=toplevel?(size_t)-1:ilt->get_new_label_num();
6097 char*& out_branches=ilt->get_out_branches();
6098 out_branches=update_location_object(out_branches);
6099 string state_cond;
6100 if(toplevel) state_cond="";
6101 else {
6102 char *label_end = mprintf("%s_l%lu", mytmpid.c_str(),
6103 (unsigned long) goto_label_num);
6104 ags->set_il_label_end (label_end);
6105 Free(label_end);
6106 ILT_branch *branch=ilt->get_as_branch();
6107 size_t state_var=branch->get_my_state_var();
6108 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6109 state_cond=branch->get_state_cond();
6110 if(!state_cond.empty()) state_cond+=" && ";
6111 char *s=mprintf("%s_state[%lu]==%lu", mytmpid.c_str(),
6112 (unsigned long) state_var, (unsigned long) state_var_val);
6113 state_cond+=s;
6114 Free(s);
6115 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n",
6116 mytmpid.c_str(),
6117 (unsigned long) state_var, (unsigned long) state_var_val);
6118 }
6119 for(size_t i=0; i<ags->get_nof_ags(); i++) {
6120 AltGuard *ag=ags->get_ag_byIndex(i);
6121 if(ag->get_type()!=AltGuard::AG_OP)
6122 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6123 size_t state_var=ilt->get_new_state_var(toplevel);
6124 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6125 ilt->add_branch(new ILT_branch(ILT_branch::BT_IL, ag, state_cond,
6126 state_var, state_var_val,
6127 goto_label_num));
6128 if(!toplevel)
6129 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n",
6130 mytmpid.c_str(),
6131 (unsigned long) state_var, (unsigned long) state_var_val);
6132 } // for
6133 if(!toplevel)
6134 out_branches=mputprintf(out_branches, "goto %s;\n"
6135 "%s_l%lu:\n",
6136 mytmpid.c_str(),
6137 mytmpid.c_str(), (unsigned long) goto_label_num);
6138 }
6139
6140 void Statement::ilt_generate_code_alt(ILT *ilt)
6141 {
6142 const string& mytmpid=ilt->get_my_tmpid();
6143 size_t goto_label_num=ilt->get_new_label_num();
6144 char *label_end = mprintf("%s_l%lu", mytmpid.c_str(),
6145 (unsigned long) goto_label_num);
6146 ags->set_il_label_end (label_end);
6147 ILT_branch *branch=ilt->get_as_branch();
6148 string state_cond=branch->get_state_cond();
6149 size_t state_var=branch->get_my_state_var();
6150 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6151 char*& out_branches=ilt->get_out_branches();
6152 for(size_t i=0; i<ags->get_nof_ags(); i++) {
6153 AltGuard *ag=ags->get_ag_byIndex(i);
6154 if(ag->get_type()!=AltGuard::AG_OP)
6155 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6156 ilt->add_branch(new ILT_branch(ILT_branch::BT_ALT, ag, state_cond,
6157 state_var, state_var_val,
6158 goto_label_num));
6159 } // for
6160 out_branches=update_location_object(out_branches);
6161 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n"
6162 "goto %s;\n"
6163 "%s:\n",
6164 mytmpid.c_str(), (unsigned long) state_var,
6165 (unsigned long) state_var_val,
6166 mytmpid.c_str(), label_end);
6167 Free(label_end);
6168 }
6169
6170 void Statement::ilt_generate_code_receiving(ILT *ilt)
6171 {
6172 const string& mytmpid=ilt->get_my_tmpid();
6173 size_t goto_label_num=ilt->get_new_label_num();
6174 ILT_branch *branch=ilt->get_as_branch();
6175 string state_cond=branch->get_state_cond();
6176 size_t state_var=branch->get_my_state_var();
6177 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6178 char*& out_branches=ilt->get_out_branches();
6179 ilt->add_branch(new ILT_branch(ILT_branch::BT_RECV, this, state_cond,
6180 state_var, state_var_val, goto_label_num));
6181 out_branches=update_location_object(out_branches);
6182 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n"
6183 "goto %s;\n"
6184 "%s_l%lu:\n",
6185 mytmpid.c_str(), (unsigned long) state_var,
6186 (unsigned long) state_var_val,
6187 mytmpid.c_str(), mytmpid.c_str(),
6188 (unsigned long) goto_label_num);
6189 }
6190
6191 void Statement::ilt_generate_code_def(ILT *ilt)
6192 {
6193 char*& str=ilt->get_out_branches();
6194 str=update_location_object(str);
6195 {
6196 char *genname=mprintf("%s_d%lu_%s", ilt->get_my_tmpid().c_str(),
6197 (unsigned long) ilt->get_new_tmpnum(),
6198 def->get_id().get_name().c_str());
6199 def->set_genname(string(genname));
6200 Free(genname);
6201 }
6202 def->ilt_generate_code(ilt);
6203 }
6204
6205 void Statement::ilt_generate_code_if(ILT *ilt)
6206 {
6207 char *end_label=mprintf("%s_l%lu",
6208 ilt->get_my_tmpid().c_str(),
6209 (unsigned long) ilt->get_new_label_num());
6210 bool unreach=false;
6211 if_stmt.ics->ilt_generate_code(ilt, end_label, unreach);
6212 if(if_stmt.elseblock && !unreach)
6213 if_stmt.elseblock->ilt_generate_code(ilt);
6214 char*& str=ilt->get_out_branches();
6215 str=mputprintf(str, "%s:\n", end_label);
6216 Free(end_label);
6217 }
6218
6219 void Statement::ilt_generate_code_select(ILT *ilt)
6220 {
6221 char*& str=ilt->get_out_branches();
6222 str=update_location_object(str);
6223 const string& tmp_prefix = my_sb->get_scope_mod_gen()->get_temporary_id();
6224 char *expr_init=memptystr();
6225 char *expr_name=select.expr->generate_code_tmp(0, expr_init);
6226 select.scs->ilt_generate_code(ilt, tmp_prefix.c_str(),
6227 expr_init, expr_name);
6228 Free(expr_name);
6229 Free(expr_init);
6230 }
6231
6232 void Statement::ilt_generate_code_call(ILT *ilt)
6233 {
6234 char*& str=ilt->get_out_branches();
6235 str=update_location_object(str);
6236 expression_struct expr;
6237 Code::init_expr(&expr);
6238 port_op.portref->generate_code(&expr);
6239 expr.expr = mputstr(expr.expr, ".call(");
6240 port_op.s.sendpar->generate_code(&expr);
6241 if(port_op.s.toclause) {
6242 expr.expr = mputstr(expr.expr, ", ");
6243 port_op.s.toclause->generate_code_expr(&expr);
6244 }
6245 expr.expr = mputc(expr.expr, ')');
6246 str = Code::merge_free_expr(str, &expr);
6247 if (port_op.s.call.body) {
6248 str = mputstr(str, "{\n"); // (1)
6249 if (port_op.s.call.timer) {
6250 str = port_op.s.call.timer->update_location_object(str);
6251 str = mputstr(str, "TIMER call_timer;\n");
6252 Code::init_expr(&expr);
6253 expr.expr = mputstr(expr.expr, "call_timer.start(");
6254 port_op.s.call.timer->generate_code_expr(&expr);
6255 expr.expr = mputc(expr.expr, ')');
6256 str = Code::merge_free_expr(str, &expr);
6257 }
6258 // the label name is used for prefixing local variables
6259 if(!my_sb) FATAL_ERROR("Statement::generate_code_call()");
6260 const string& tmplabel = my_sb->get_scope_mod_gen()->get_temporary_id();
6261 str = port_op.s.call.body->generate_code_call_body(str, *this, tmplabel,
6262 true);
6263 const char *label_str = tmplabel.c_str();
6264 str=mputprintf(str, "goto %s_end;\n"
6265 "}\n", // (1)
6266 label_str);
6267 port_op.s.call.body->ilt_generate_code_call_body(ilt, label_str);
6268 str=mputprintf(str, "%s_end:\n", label_str);
6269 }
6270 }
6271
6272 void Statement::ilt_generate_code_for(ILT *ilt)
6273 {
6274 char*& str = ilt->get_out_branches();
6275 str = update_location_object(str);
6276 // statements in initial may have side effects
6277 // generate code for them anyway
6278 if (loop.for_stmt.varinst) {
6279 char *genname = mprintf("%s_d%lu_", ilt->get_my_tmpid().c_str(),
6280 (unsigned long) ilt->get_new_tmpnum());
6281 loop.for_stmt.init_varinst->set_genname(string(genname));
6282 Free(genname);
6283 loop.for_stmt.init_varinst->ilt_generate_code(ilt);
6284 } else str = loop.for_stmt.init_ass->generate_code(str);
6285 // check whether the final expression is constant
6286 bool final_is_true = false, final_is_false = false;
6287 if (!loop.for_stmt.finalexpr->is_unfoldable()) {
6288 if (loop.for_stmt.finalexpr->get_val_bool()) final_is_true = true;
6289 else final_is_false = true;
6290 }
6291 if (final_is_false) str = mputstr(str, "/* never occurs */;\n");
6292 else {
6293 char *label_prefix = mprintf("%s_l%lu_", ilt->get_my_tmpid().c_str(),
6294 (unsigned long) ilt->get_new_label_num());
6295 str = mputprintf(str, "%sbegin:\n", label_prefix);
6296 // do not generate the exit condition for infinite loops
6297 if (!final_is_true) {
6298 str = loop.for_stmt.finalexpr->update_location_object(str);
6299 size_t blockcount = 0;
6300 str = loop.for_stmt.finalexpr->generate_code_tmp(str, "if (!",
6301 blockcount);
6302 str = mputprintf(str, ") goto %send;\n", label_prefix);
6303 while (blockcount-- > 0) str = mputstr(str, "}\n");
6304 }
6305 loop.is_ilt = true;
6306 if (loop.has_brk) {
6307 loop.il_label_end = new string(label_prefix);
6308 *loop.il_label_end += "end";
6309 }
6310 if (loop.has_cnt) {
6311 loop.label_next = new string(label_prefix);
6312 *loop.label_next += "next";
6313 }
6314 loop.block->ilt_generate_code(ilt);
6315 if (loop.label_next)
6316 str = mputprintf(str, "%snext:\n", label_prefix);
6317 str = update_location_object(str);
6318 str = loop.for_stmt.step->generate_code(str);
6319 str = mputprintf(str, "goto %sbegin;\n", label_prefix);
6320 if (!final_is_true || loop.has_brk)
6321 str = mputprintf(str, "%send:\n", label_prefix);
6322 Free(label_prefix);
6323 }
6324 }
6325
6326 void Statement::ilt_generate_code_while(ILT *ilt)
6327 {
6328 char*& str = ilt->get_out_branches();
6329 // Location need not be set here; the location is set for the expression.
6330 // check whether the expression is constant
6331 bool expr_is_true = false, expr_is_false = false;
6332 if (!loop.expr->is_unfoldable()) {
6333 if (loop.expr->get_val_bool()) expr_is_true = true;
6334 else expr_is_false = true;
6335 }
6336 if (expr_is_false) str = mputstr(str, "/* never occurs */;\n");
6337 else {
6338 char *label_prefix = mprintf("%s_l%lu_", ilt->get_my_tmpid().c_str(),
6339 (unsigned long) ilt->get_new_label_num());
6340 str = mputprintf(str, "%sbegin:\n", label_prefix);
6341 loop.is_ilt = true;
6342 if (loop.has_brk) {
6343 loop.il_label_end = new string(label_prefix);
6344 *loop.il_label_end += "end";
6345 }
6346 if (loop.has_cnt) {
6347 loop.label_next = new string(label_prefix);
6348 *loop.label_next += "begin";
6349 }
6350 // do not generate the exit condition for infinite loops
6351 if (!expr_is_true) {
6352 str = loop.expr->update_location_object(str);
6353 size_t blockcount = 0;
6354 str = loop.expr->generate_code_tmp(str, "if (!", blockcount);
6355 str = mputprintf(str, ") goto %send;\n", label_prefix);
6356 while (blockcount-- > 0) str = mputstr(str, "}\n");
6357 }
6358 loop.block->ilt_generate_code(ilt);
6359 str = update_location_object(str);
6360 str = mputprintf(str, "goto %sbegin;\n", label_prefix);
6361 if (!expr_is_true || loop.has_brk)
6362 str = mputprintf(str, "%send:\n", label_prefix);
6363 Free(label_prefix);
6364 }
6365 }
6366
6367 void Statement::ilt_generate_code_dowhile(ILT *ilt)
6368 {
6369 char*& str = ilt->get_out_branches();
6370 // Location need not be set here; there is only a label before the body.
6371 // check whether the expression is constant
6372 bool expr_is_true = false;
6373 if (!loop.expr->is_unfoldable()) {
6374 if (loop.expr->get_val_bool()) expr_is_true = true;
6375 else loop.iterate_once = true;
6376 }
6377 char *label_prefix = 0;
6378 if (!loop.iterate_once || loop.has_brk || loop.has_cnt)
6379 label_prefix = mprintf("%s_l%lu_", ilt->get_my_tmpid().c_str(),
6380 (unsigned long) ilt->get_new_label_num());
6381 loop.is_ilt = true;
6382 if (loop.has_brk) {
6383 loop.il_label_end = new string(label_prefix);
6384 *loop.il_label_end += "end";
6385 }
6386 if (loop.has_cnt)
6387 loop.label_next = new string(label_prefix);
6388 if (loop.iterate_once) {
6389 if (loop.label_next) *loop.label_next += "end";
6390 loop.block->ilt_generate_code(ilt);
6391 } else {
6392 str = mputprintf(str, "%sbegin:\n", label_prefix);
6393 if (loop.label_next)
6394 *loop.label_next += (expr_is_true ? "begin" : "next");
6395 loop.block->ilt_generate_code(ilt);
6396 if (expr_is_true) str = mputprintf(str, "goto %sbegin;\n", label_prefix);
6397 else {
6398 if (loop.label_next) str = mputprintf(str, "%snext:\n", label_prefix);
6399 str = loop.expr->update_location_object(str);
6400 size_t blockcount = 0;
6401 str = loop.expr->generate_code_tmp(str, "if (", blockcount);
6402 str = mputprintf(str, ") goto %sbegin;\n", label_prefix);
6403 while (blockcount-- > 0) str = mputstr(str, "}\n");
6404 }
6405 }
6406 if (loop.il_label_end || (loop.iterate_once && loop.label_next)) {
6407 str = mputprintf(str, "%send: ;\n", label_prefix);
6408 }
6409 Free(label_prefix);
6410 }
6411
6412 char *Statement::generate_code_return(char *str)
6413 {
6414 expression_struct expr;
6415 Code::init_expr(&expr);
6416 expr.expr = mputstr(expr.expr, "return");
6417 Definition *my_def = my_sb->get_my_def();
6418 if (returnexpr.v) {
6419 expr.expr = mputc(expr.expr, ' ');
6420 returnexpr.v->generate_code_expr_mandatory(&expr);
6421 } else if (returnexpr.t) {
6422 expr.expr = mputc(expr.expr, ' ');
6423 if (!my_def) FATAL_ERROR("Statement::generate_code_return()");
6424 Def_Function_Base* dfb = dynamic_cast<Def_Function_Base*>(my_def);
6425 if (!dfb) FATAL_ERROR("Statement::generate_code_return()");
6426 if (dfb->get_template_restriction() != TR_NONE &&
6427 returnexpr.gen_restriction_check) {
6428 returnexpr.t->generate_code_expr(&expr,
6429 dfb->get_template_restriction());
6430 } else {
6431 returnexpr.t->generate_code_expr(&expr, TR_NONE);
6432 }
6433 } else {
6434 if (my_def && my_def->get_asstype() == Definition::A_ALTSTEP)
6435 expr.expr = mputstr(expr.expr, " ALT_YES");
6436 // else it's a return with no value: the only case a blank is unneeded
6437 }
6438 return Code::merge_free_expr(str, &expr);
6439 }
6440
6441 char *Statement::generate_code_activate(char *str)
6442 {
6443 expression_struct expr;
6444 Code::init_expr(&expr);
6445 expr.expr = mputprintf(expr.expr, "%s(", ref_pard->get_refd_assignment()
6446 ->get_genname_from_scope(my_sb, "activate_").c_str());
6447 ref_pard->get_parlist()->generate_code_noalias(&expr, ref_pard->get_refd_assignment()->get_FormalParList());
6448 expr.expr = mputc(expr.expr, ')');
6449 return Code::merge_free_expr(str, &expr);
6450 }
6451
6452 char *Statement::generate_code_activate_refd(char *str)
6453 {
6454 expression_struct expr;
6455 Code::init_expr(&expr);
6456 Value *last_v = fau_refd.value->get_value_refd_last();
6457 if (last_v->get_valuetype() == Value::V_ALTSTEP) {
6458 expr.expr = mputprintf(expr.expr, "%s(", last_v->get_refd_fat()
6459 ->get_genname_from_scope(my_sb, "activate_").c_str());
6460 } else {
6461 fau_refd.value->generate_code_expr_mandatory(&expr);
6462 expr.expr = mputstr(expr.expr, ".activate(");
6463 }
6464 fau_refd.ap_list2->generate_code_noalias(&expr, NULL);
6465 expr.expr = mputc(expr.expr, ')');
6466 return Code::merge_free_expr(str, &expr);
6467 }
6468
6469 char *Statement::generate_code_deactivate(char *str)
6470 {
6471 if(!deactivate) str=mputstr(str, "TTCN_Default::deactivate_all();\n");
6472 else {
6473 expression_struct expr;
6474 Code::init_expr(&expr);
6475 expr.expr=mputstr(expr.expr, "TTCN_Default::deactivate(");
6476 deactivate->generate_code_expr(&expr);
6477 expr.expr=mputstr(expr.expr, ");\n");
6478 str=Code::merge_free_expr(str, &expr);
6479 }
6480 return str;
6481 }
6482
6483 char *Statement::generate_code_send(char *str)
6484 {
6485 expression_struct expr;
6486 Code::init_expr(&expr);
6487 port_op.portref->generate_code(&expr);
6488 expr.expr = mputstr(expr.expr, ".send(");
6489 generate_code_expr_sendpar(&expr);
6490 if (port_op.s.toclause) {
6491 expr.expr = mputstr(expr.expr, ", ");
6492 port_op.s.toclause->generate_code_expr(&expr);
6493 }
6494 expr.expr = mputc(expr.expr, ')');
6495 return Code::merge_free_expr(str, &expr);
6496 }
6497
6498 char *Statement::generate_code_call(char *str)
6499 {
6500 expression_struct expr;
6501 Code::init_expr(&expr);
6502 port_op.portref->generate_code(&expr);
6503 expr.expr = mputstr(expr.expr, ".call(");
6504 port_op.s.sendpar->generate_code(&expr);
6505 if(port_op.s.toclause) {
6506 expr.expr = mputstr(expr.expr, ", ");
6507 port_op.s.toclause->generate_code_expr(&expr);
6508 }
6509 expr.expr = mputc(expr.expr, ')');
6510 str = Code::merge_free_expr(str, &expr);
6511 if (port_op.s.call.body) {
6512 str = mputstr(str, "{\n");
6513 if (port_op.s.call.timer) {
6514 str = port_op.s.call.timer->update_location_object(str);
6515 str = mputstr(str, "TIMER call_timer;\n");
6516 Code::init_expr(&expr);
6517 expr.expr = mputstr(expr.expr, "call_timer.start(");
6518 port_op.s.call.timer->generate_code_expr(&expr);
6519 expr.expr = mputc(expr.expr, ')');
6520 str = Code::merge_free_expr(str, &expr);
6521 }
6522 // the label name is used for prefixing local variables
6523 if(!my_sb) FATAL_ERROR("Statement::generate_code_call()");
6524 str = port_op.s.call.body->generate_code_call_body(str, *this,
6525 my_sb->get_scope_mod_gen()->get_temporary_id(), false);
6526 str=mputstr(str, "}\n");
6527 }
6528 return str;
6529 }
6530
6531 char *Statement::generate_code_reply(char *str)
6532 {
6533 expression_struct expr;
6534 Code::init_expr(&expr);
6535 port_op.portref->generate_code(&expr);
6536 expr.expr=mputstr(expr.expr, ".reply(");
6537 port_op.s.sendpar->generate_code(&expr);
6538 if(port_op.s.replyval) {
6539 expr.expr=mputstr(expr.expr, ".set_value_template(");
6540 port_op.s.replyval->generate_code_expr(&expr);
6541 expr.expr=mputc(expr.expr, ')');
6542 }
6543 if(port_op.s.toclause) {
6544 expr.expr=mputstr(expr.expr, ", ");
6545 port_op.s.toclause->generate_code_expr(&expr);
6546 }
6547 expr.expr=mputc(expr.expr, ')');
6548 return Code::merge_free_expr(str, &expr);
6549 }
6550
6551 char *Statement::generate_code_raise(char *str)
6552 {
6553 expression_struct expr;
6554 Code::init_expr(&expr);
6555 port_op.portref->generate_code(&expr);
6556 expr.expr=mputstr(expr.expr, ".raise(");
6557 port_op.s.raise.signature_ref->generate_code(&expr);
6558 expr.expr=mputstr(expr.expr, "_exception(");
6559 generate_code_expr_sendpar(&expr);
6560 expr.expr=mputc(expr.expr, ')');
6561 if(port_op.s.toclause) {
6562 expr.expr=mputstr(expr.expr, ", ");
6563 port_op.s.toclause->generate_code_expr(&expr);
6564 }
6565 expr.expr=mputc(expr.expr, ')');
6566 return Code::merge_free_expr(str, &expr);
6567 }
6568
6569 char *Statement::generate_code_portop(char *str, const char *opname)
6570 {
6571 if (port_op.portref) {
6572 expression_struct expr;
6573 Code::init_expr(&expr);
6574 port_op.portref->generate_code(&expr);
6575 expr.expr=mputprintf(expr.expr, ".%s()", opname);
6576 str=Code::merge_free_expr(str, &expr);
6577 } else {
6578 str = mputprintf(str, "PORT::all_%s();\n", opname);
6579 }
6580 return str;
6581 }
6582
6583 char *Statement::generate_code_startcomp(char *str)
6584 {
6585 expression_struct expr;
6586 Code::init_expr(&expr);
6587 Common::Assignment *func = comp_op.funcinstref->get_refd_assignment();
6588 expr.expr = mputprintf(expr.expr, "%s(",
6589 func->get_genname_from_scope(my_sb, "start_").c_str());
6590 comp_op.compref->generate_code_expr(&expr);
6591 FormalParList *fplist = func->get_FormalParList();
6592 if (fplist->get_nof_fps() > 0) {
6593 expr.expr = mputstr(expr.expr, ", ");
6594 comp_op.funcinstref->get_parlist()->generate_code_noalias(&expr, fplist);
6595 }
6596 expr.expr = mputc(expr.expr, ')');
6597 return Code::merge_free_expr(str, &expr);
6598 }
6599
6600 char *Statement::generate_code_startcomp_refd(char *str)
6601 {
6602 expression_struct expr;
6603 Code::init_expr(&expr);
6604 Value *last_v = comp_op.derefered.value->get_value_refd_last();
6605 if (last_v->get_valuetype() == Value::V_FUNCTION) {
6606 expr.expr = mputprintf(expr.expr, "%s(", last_v->get_refd_fat()
6607 ->get_genname_from_scope(my_sb, "start_").c_str());
6608 } else {
6609 comp_op.derefered.value->generate_code_expr_mandatory(&expr);
6610 expr.expr = mputstr(expr.expr, ".start(");
6611 }
6612 comp_op.compref->generate_code_expr(&expr);
6613 if (comp_op.derefered.ap_list2->get_nof_pars() > 0) {
6614 expr.expr = mputstr(expr.expr, ", ");
6615 comp_op.derefered.ap_list2->generate_code_noalias(&expr, NULL);
6616 }
6617 expr.expr = mputc(expr.expr, ')');
6618 return Code::merge_free_expr(str, &expr);
6619 }
6620
6621 char *Statement::generate_code_compop(char *str, const char *opname)
6622 {
6623 expression_struct expr;
6624 Code::init_expr(&expr);
6625 if (comp_op.compref) {
6626 Value *v_last = comp_op.compref->get_value_refd_last();
6627 if (v_last->get_valuetype() == Value::V_REFD) {
6628 // the argument is a simple component reference
6629 v_last->generate_code_expr_mandatory(&expr);
6630 expr.expr = mputprintf(expr.expr, ".%s()", opname);
6631 } else {
6632 bool refers_to_self = false;
6633 if (v_last->get_valuetype() == Value::V_EXPR) {
6634 // the argument is a special component reference (mtc, self, etc.)
6635 switch (v_last->get_optype()) {
6636 case Value::OPTYPE_COMP_MTC: {
6637 Definition *my_def = my_sb->get_my_def();
6638 if (my_def && my_def->get_asstype() == Definition::A_TESTCASE)
6639 refers_to_self = true;
6640 break; }
6641 case Value::OPTYPE_COMP_SELF:
6642 refers_to_self = true;
6643 default:
6644 break;
6645 }
6646 }
6647 if (refers_to_self) {
6648 expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_execution()",
6649 opname);
6650 } else {
6651 expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_component(",
6652 opname);
6653 v_last->generate_code_expr(&expr);
6654 expr.expr = mputc(expr.expr, ')');
6655 }
6656 }
6657 } else {
6658 // the operation refers to all component
6659 expr.expr = mputprintf(expr.expr,
6660 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname);
6661 }
6662 return Code::merge_free_expr(str, &expr);
6663 }
6664
6665 char *Statement::generate_code_configop(char *str, const char *opname)
6666 {
6667 expression_struct expr;
6668 Code::init_expr(&expr);
6669 expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_port(", opname);
6670 config_op.compref1->generate_code_expr(&expr);
6671 expr.expr = mputstr(expr.expr, ", ");
6672 if (config_op.compref1->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE)) {
6673 // the component type is known
6674 // the name of the referred port can be used
6675 config_op.portref1->generate_code_portref(&expr, my_sb);
6676 expr.expr = mputstr(expr.expr, ".get_name()");
6677 } else {
6678 // the component type is unknown
6679 // a simple string shall be formed from the port name and array indices
6680 generate_code_portref(&expr, config_op.portref1);
6681 }
6682 expr.expr = mputstr(expr.expr, ", ");
6683 config_op.compref2->generate_code_expr(&expr);
6684 expr.expr = mputstr(expr.expr, ", ");
6685 if (config_op.compref2->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE)) {
6686 // the component type is known
6687 // the name of the referred port can be used
6688 config_op.portref2->generate_code_portref(&expr, my_sb);
6689 expr.expr = mputstr(expr.expr, ".get_name()");
6690 } else {
6691 // the component type is unknown
6692 // a simple string shall be formed from the port name and array indices
6693 generate_code_portref(&expr, config_op.portref2);
6694 }
6695 expr.expr = mputc(expr.expr, ')');
6696 return Code::merge_free_expr(str, &expr);
6697 }
6698
6699 char *Statement::generate_code_starttimer(char *str)
6700 {
6701 expression_struct expr;
6702 Code::init_expr(&expr);
6703 timer_op.timerref->generate_code(&expr);
6704 expr.expr=mputstr(expr.expr, ".start(");
6705 if(timer_op.value) timer_op.value->generate_code_expr(&expr);
6706 expr.expr=mputc(expr.expr, ')');
6707 str=Code::merge_free_expr(str, &expr);
6708 return str;
6709 }
6710
6711 char *Statement::generate_code_stoptimer(char *str)
6712 {
6713 if(!timer_op.timerref) str=mputstr(str, "TIMER::all_stop();\n");
6714 else {
6715 expression_struct expr;
6716 Code::init_expr(&expr);
6717 timer_op.timerref->generate_code(&expr);
6718 expr.expr=mputstr(expr.expr, ".stop()");
6719 str=Code::merge_free_expr(str, &expr);
6720 }
6721 return str;
6722 }
6723
6724 char *Statement::generate_code_setverdict(char *str)
6725 {
6726 expression_struct expr;
6727 Code::init_expr(&expr);
6728 expr.expr=mputstr(expr.expr, "TTCN_Runtime::setverdict(");
6729 setverdict.verdictval->generate_code_expr(&expr);
6730 if (setverdict.logargs) {
6731 expr.expr=mputc(expr.expr, ',');
6732 expression_struct expr_reason;
6733 Code::init_expr(&expr_reason);
6734 setverdict.logargs->generate_code_expr(&expr_reason);
6735 if (expr_reason.preamble)
6736 expr.preamble = mputprintf(expr.preamble, "%s;\n",
6737 expr_reason.preamble);
6738 if (expr_reason.postamble)
6739 expr.postamble = mputprintf(expr.postamble, "%s;\n",
6740 expr_reason.postamble);
6741 expr.expr = mputprintf(expr.expr, "%s", expr_reason.expr);
6742 Code::free_expr(&expr_reason);
6743 }
6744 expr.expr=mputc(expr.expr, ')');
6745 str=Code::merge_free_expr(str, &expr);
6746 return str;
6747 }
6748
6749 char *Statement::generate_code_action(char *str)
6750 {
6751 str=mputstr(str, "TTCN_Runtime::begin_action();\n");
6752 if(!logargs) str=mputstr(str, "TTCN_Logger::log_event_str"
6753 "(\"<empty action statement>\");\n");
6754 else str=logargs->generate_code(str);
6755 str=mputstr(str, "TTCN_Runtime::end_action();\n");
6756 return str;
6757 }
6758
6759 char *Statement::generate_code_testcaseinst(char *str)
6760 {
6761 expression_struct expr;
6762 Code::init_expr(&expr);
6763 Common::Assignment *testcase = testcase_inst.tcref->get_refd_assignment();
6764 expr.expr = mputprintf(expr.expr, "%s(",
6765 testcase->get_genname_from_scope(my_sb, "testcase_").c_str());
6766 ActualParList *t_aplist = testcase_inst.tcref->get_parlist();
6767 if (t_aplist->get_nof_pars() > 0) {
6768 t_aplist->generate_code_alias(&expr, testcase->get_FormalParList(),
6769 0, false);
6770 expr.expr = mputstr(expr.expr, ", ");
6771 }
6772 if (testcase_inst.timerval) {
6773 expr.expr = mputstr(expr.expr, "TRUE, ");
6774 testcase_inst.timerval->generate_code_expr(&expr);
6775 expr.expr = mputc(expr.expr, ')');
6776 } else expr.expr = mputstr(expr.expr, "FALSE, 0.0)");
6777 return Code::merge_free_expr(str, &expr);
6778 }
6779
6780 char *Statement::generate_code_execute_refd(char *str)
6781 {
6782 expression_struct expr;
6783 Code::init_expr(&expr);
6784 Value *last_v = fau_refd.value->get_value_refd_last();
6785 if (last_v->get_valuetype() == Value::V_TESTCASE) {
6786 Common::Assignment *testcase = last_v->get_refd_fat();
6787 expr.expr = mputprintf(expr.expr, "%s(",
6788 testcase->get_genname_from_scope(my_sb, "testcase_").c_str());
6789 execute_refd.ap_list2->generate_code_alias(&expr,
6790 testcase->get_FormalParList(), 0, false);
6791 } else {
6792 execute_refd.value->generate_code_expr_mandatory(&expr);
6793 expr.expr = mputstr(expr.expr, ".execute(");
6794 execute_refd.ap_list2->generate_code_alias(&expr, 0, 0, false);
6795 }
6796 if (execute_refd.ap_list2->get_nof_pars() > 0)
6797 expr.expr = mputstr(expr.expr, ", ");
6798 if (execute_refd.timerval) {
6799 expr.expr = mputstr(expr.expr, "TRUE, ");
6800 execute_refd.timerval->generate_code_expr(&expr);
6801 expr.expr = mputc(expr.expr, ')');
6802 } else expr.expr = mputstr(expr.expr, "FALSE, 0.0)");
6803 return Code::merge_free_expr(str,&expr);
6804 }
6805
6806 void Statement::generate_code_expr_receive(expression_struct *expr,
6807 const char *opname)
6808 {
6809 if (port_op.portref) {
6810 // The operation refers to a specific port.
6811 port_op.portref->generate_code(expr);
6812 expr->expr = mputprintf(expr->expr, ".%s(", opname);
6813 if (port_op.r.rcvpar) {
6814 // The receive parameter is present.
6815 if (use_runtime_2 && TypeConv::needs_conv_redir(port_op.r.rcvpar,
6816 port_op.r.redirect.value)) {
6817 // Don't change the first parameter. Otherwise it won't receive
6818 // anything. The only thing we need is a temporary to save the
6819 // result and a conversion at the end.
6820 TypeConv::gen_conv_code_redir(expr, port_op.r.rcvpar,
6821 port_op.r.redirect.value);
6822 } else {
6823 port_op.r.rcvpar->generate_code(expr);
6824 expr->expr = mputstr(expr->expr, ", ");
6825 if (port_op.r.redirect.value) {
6826 // Value redirect is also present.
6827 expr->expr = mputstr(expr->expr, "&(");
6828 port_op.r.redirect.value->generate_code(expr);
6829 expr->expr = mputc(expr->expr, ')');
6830 } else expr->expr = mputstr(expr->expr, "NULL");
6831 }
6832 expr->expr = mputstr(expr->expr, ", ");
6833 }
6834 } else {
6835 // the operation refers to any port
6836 expr->expr = mputprintf(expr->expr, "PORT::any_%s(", opname);
6837 }
6838 generate_code_expr_fromclause(expr);
6839 expr->expr = mputstr(expr->expr, ", ");
6840 generate_code_expr_senderredirect(expr);
6841 expr->expr = mputc(expr->expr, ')');
6842 }
6843
6844 void Statement::generate_code_expr_getcall(expression_struct *expr,
6845 const char *opname)
6846 {
6847 if (port_op.portref) {
6848 // the operation refers to a specific port
6849 port_op.portref->generate_code(expr);
6850 expr->expr = mputprintf(expr->expr, ".%s(", opname);
6851 if (port_op.r.rcvpar) {
6852 // the signature template is present
6853 port_op.r.rcvpar->generate_code(expr);
6854 expr->expr = mputstr(expr->expr, ", ");
6855 generate_code_expr_fromclause(expr);
6856 // a temporary object is needed for parameter redirect
6857 Type *signature = port_op.r.rcvpar->get_Template()->get_my_governor();
6858 expr->expr = mputprintf(expr->expr, ", %s_call_redirect(",
6859 signature->get_genname_value(my_sb).c_str());
6860 if (port_op.r.redirect.param)
6861 port_op.r.redirect.param->generate_code(expr);
6862 expr->expr = mputstr(expr->expr, "), ");
6863 generate_code_expr_senderredirect(expr);
6864 } else {
6865 // the signature parameter is not present
6866 generate_code_expr_fromclause(expr);
6867 expr->expr = mputstr(expr->expr, ", ");
6868 generate_code_expr_senderredirect(expr);
6869 }
6870 } else {
6871 // the operation refers to any port
6872 expr->expr = mputprintf(expr->expr, "PORT::any_%s(", opname);
6873 generate_code_expr_fromclause(expr);
6874 expr->expr = mputstr(expr->expr, ", ");
6875 generate_code_expr_senderredirect(expr);
6876 }
6877 expr->expr=mputc(expr->expr, ')');
6878 }
6879
6880 void Statement::generate_code_expr_getreply(expression_struct *expr,
6881 const char *opname)
6882 {
6883 if (port_op.portref) {
6884 // the operation refers to a specific port
6885 port_op.portref->generate_code(expr);
6886 expr->expr = mputprintf(expr->expr, ".%s(", opname);
6887 if (port_op.r.rcvpar) {
6888 // the signature template is present
6889 port_op.r.rcvpar->generate_code(expr);
6890 Type *signature = port_op.r.rcvpar->get_Template()->get_my_governor();
6891 Type *return_type =
6892 signature->get_type_refd_last()->get_signature_return_type();
6893 if (return_type) {
6894 expr->expr = mputstr(expr->expr, ".set_value_template(");
6895 if (port_op.r.getreply_valuematch) {
6896 // the value match is also present
6897 port_op.r.getreply_valuematch->generate_code(expr);
6898 } else {
6899 // the value match is not present
6900 // we must substitute it with ? in the signature template
6901 expr->expr = mputprintf(expr->expr, "%s(ANY_VALUE)",
6902 return_type->get_genname_template(my_sb).c_str());
6903 }
6904 expr->expr = mputc(expr->expr, ')');
6905 }
6906 expr->expr = mputstr(expr->expr, ", ");
6907 generate_code_expr_fromclause(expr);
6908 // a temporary object is needed for value and parameter redirect
6909 expr->expr = mputprintf(expr->expr, ", %s_reply_redirect(",
6910 signature->get_genname_value(my_sb).c_str());
6911 if (return_type) {
6912 // the first argument of the constructor must contain
6913 // the value redirect
6914 if (port_op.r.redirect.value) {
6915 expr->expr = mputstr(expr->expr, "&(");
6916 port_op.r.redirect.value->generate_code(expr);
6917 expr->expr = mputc(expr->expr, ')');
6918 } else expr->expr = mputstr(expr->expr, "NULL");
6919 if (port_op.r.redirect.param) expr->expr = mputstr(expr->expr, ", ");
6920 }
6921 if (port_op.r.redirect.param)
6922 port_op.r.redirect.param->generate_code(expr);
6923 expr->expr = mputstr(expr->expr, "), ");
6924 generate_code_expr_senderredirect(expr);
6925 } else {
6926 // the signature template is not present
6927 generate_code_expr_fromclause(expr);
6928 expr->expr = mputstr(expr->expr, ", ");
6929 generate_code_expr_senderredirect(expr);
6930 }
6931 } else {
6932 // the operation refers to any port
6933 expr->expr = mputprintf(expr->expr, "PORT::any_%s(", opname);
6934 generate_code_expr_fromclause(expr);
6935 expr->expr = mputstr(expr->expr, ", ");
6936 generate_code_expr_senderredirect(expr);
6937 }
6938 expr->expr = mputc(expr->expr, ')');
6939 }
6940
6941 void Statement::generate_code_expr_catch(expression_struct *expr)
6942 {
6943 if (port_op.portref) {
6944 // the operation refers to a specific port
6945 if (port_op.r.ctch.timeout) {
6946 // the operation catches the timeout exception
6947 expr->expr = mputstr(expr->expr, "call_timer.timeout()");
6948 return;
6949 }
6950 port_op.portref->generate_code(expr);
6951 expr->expr = mputprintf(expr->expr, ".%s(",
6952 statementtype == S_CHECK_CATCH ? "check_catch" : "get_exception");
6953 if (port_op.r.ctch.signature_ref) {
6954 // the signature reference and the exception template is present
6955 expr->expr = mputprintf(expr->expr, "%s_exception_template(",
6956 port_op.r.ctch.signature->get_genname_value(my_sb).c_str());
6957 port_op.r.rcvpar->generate_code(expr);
6958 expr->expr = mputstr(expr->expr, ", ");
6959 if (port_op.r.redirect.value) {
6960 // value redirect is also present
6961 expr->expr = mputstr(expr->expr, "&(");
6962 port_op.r.redirect.value->generate_code(expr);
6963 expr->expr = mputc(expr->expr, ')');
6964 } else expr->expr = mputstr(expr->expr, "NULL");
6965 expr->expr = mputstr(expr->expr, "), ");
6966 }
6967 } else {
6968 // the operation refers to any port
6969 expr->expr = mputprintf(expr->expr, "PORT::%s(",
6970 statementtype == S_CHECK_CATCH ? "any_check_catch" : "any_catch");
6971 }
6972 generate_code_expr_fromclause(expr);
6973 expr->expr = mputstr(expr->expr, ", ");
6974 generate_code_expr_senderredirect(expr);
6975 expr->expr = mputc(expr->expr, ')');
6976 }
6977
6978 void Statement::generate_code_expr_check(expression_struct *expr)
6979 {
6980 if (port_op.portref) {
6981 // the operation refers to a specific port
6982 port_op.portref->generate_code(expr);
6983 expr->expr = mputstr(expr->expr, ".check");
6984 } else {
6985 // the operation refers to any port
6986 expr->expr = mputstr(expr->expr, "PORT::any_check");
6987 }
6988 expr->expr = mputc(expr->expr, '(');
6989 generate_code_expr_fromclause(expr);
6990 expr->expr = mputstr(expr->expr, ", ");
6991 generate_code_expr_senderredirect(expr);
6992 expr->expr = mputc(expr->expr, ')');
6993 }
6994
6995 void Statement::generate_code_expr_done(expression_struct *expr)
6996 {
6997 if (comp_op.compref) {
6998 if (comp_op.donereturn.donematch) {
6999 // value returning done
7000 // figure out what type the done() function belongs to
7001 Type *t = comp_op.donereturn.donematch
7002 ->get_expr_governor(Type::EXPECTED_TEMPLATE);
7003 if (!t) FATAL_ERROR("Statement::generate_code_expr_done()");
7004 while (t->is_ref() && !t->has_done_attribute())
7005 t = t->get_type_refd();
7006 if (!t->has_done_attribute())
7007 FATAL_ERROR("Statement::generate_code_expr_done()");
7008 // determine whether the done() function is in the same module
7009 Common::Module *t_mod = t->get_my_scope()->get_scope_mod_gen();
7010 if (t_mod != my_sb->get_scope_mod_gen()) {
7011 expr->expr = mputprintf(expr->expr, "%s::",
7012 t_mod->get_modid().get_name().c_str());
7013 }
7014 expr->expr = mputstr(expr->expr, "done(");
7015 comp_op.compref->generate_code_expr(expr);
7016 expr->expr = mputstr(expr->expr, ", ");
7017 comp_op.donereturn.donematch->generate_code(expr);
7018 expr->expr = mputstr(expr->expr, ", ");
7019 if (comp_op.donereturn.redirect) {
7020 // value redirect is present
7021 expr->expr = mputstr(expr->expr, "&(");
7022 comp_op.donereturn.redirect->generate_code(expr);
7023 expr->expr = mputc(expr->expr, ')');
7024 } else {
7025 // value redirect is omitted
7026 expr->expr = mputstr(expr->expr, "NULL");
7027 }
7028 expr->expr = mputc(expr->expr, ')');
7029 } else {
7030 // simple done
7031 comp_op.compref->generate_code_expr_mandatory(expr);
7032 expr->expr = mputstr(expr->expr, ".done()");
7033 }
7034 } else if (comp_op.any_or_all == C_ANY) {
7035 // any component.done
7036 expr->expr = mputstr(expr->expr,
7037 "TTCN_Runtime::component_done(ANY_COMPREF)");
7038 } else {
7039 // all component.done
7040 expr->expr = mputstr(expr->expr,
7041 "TTCN_Runtime::component_done(ALL_COMPREF)");
7042 }
7043 }
7044
7045 void Statement::generate_code_expr_killed(expression_struct *expr)
7046 {
7047 if (comp_op.compref) {
7048 // compref.killed
7049 comp_op.compref->generate_code_expr_mandatory(expr);
7050 expr->expr = mputstr(expr->expr, ".killed()");
7051 } else if (comp_op.any_or_all == C_ANY) {
7052 // any component.killed
7053 expr->expr = mputstr(expr->expr,
7054 "TTCN_Runtime::component_killed(ANY_COMPREF)");
7055 } else {
7056 // all component.killed
7057 expr->expr = mputstr(expr->expr,
7058 "TTCN_Runtime::component_killed(ALL_COMPREF)");
7059 }
7060 }
7061
7062 void Statement::generate_code_expr_timeout(expression_struct *expr)
7063 {
7064 if (timer_op.timerref) {
7065 timer_op.timerref->generate_code(expr);
7066 expr->expr=mputstr(expr->expr, ".timeout()");
7067 } else expr->expr = mputstr(expr->expr, "TIMER::any_timeout()");
7068 }
7069
7070 void Statement::generate_code_expr_sendpar(expression_struct *expr)
7071 {
7072 Template *templ_body = port_op.s.sendpar->get_Template();
7073 if (!port_op.s.sendpar->get_DerivedRef() &&
7074 templ_body->get_templatetype() == Template::SPECIFIC_VALUE) {
7075 // the send parameter is a value: optimization is possible
7076 Value *t_val = templ_body->get_specific_value();
7077 bool cast_needed = t_val->explicit_cast_needed();
7078 if (cast_needed) {
7079 // the ambiguous C++ expression is converted to the value class
7080 expr->expr = mputprintf(expr->expr, "%s(",
7081 t_val->get_my_governor()->get_genname_value(my_sb).c_str());
7082 }
7083 t_val->generate_code_expr_mandatory(expr);
7084 if (cast_needed) expr->expr = mputc(expr->expr, ')');
7085 } else {
7086 // the send parameter is a real template: optimization is not possible
7087 port_op.s.sendpar->generate_code(expr);
7088 }
7089 }
7090
7091 void Statement::generate_code_expr_fromclause(expression_struct *expr)
7092 {
7093 if (port_op.r.fromclause) {
7094 // the from clause is present: trivial case
7095 port_op.r.fromclause->generate_code(expr);
7096 } else if (port_op.r.redirect.sender) {
7097 // from clause is omitted, but sender redirect is present
7098 Type *t_var_type = port_op.r.redirect.sender->chk_variable_ref();
7099 if (!t_var_type)
7100 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
7101 if (t_var_type->get_type_refd_last()->get_typetype() ==
7102 Type::T_COMPONENT) {
7103 // the variable can store a component reference
7104 expr->expr = mputstr(expr->expr, "any_compref");
7105 } else {
7106 // the variable can store an address value
7107 expr->expr = mputprintf(expr->expr, "%s(ANY_VALUE)",
7108 t_var_type->get_genname_template(my_sb).c_str());
7109 }
7110 } else {
7111 // neither from clause nor sender redirect is present
7112 // the operation cannot refer to address type
7113 expr->expr = mputstr(expr->expr, "any_compref");
7114 }
7115 }
7116
7117 void Statement::generate_code_expr_senderredirect(expression_struct *expr)
7118 {
7119 if (port_op.r.redirect.sender) {
7120 expr->expr = mputstr(expr->expr, "&(");
7121 port_op.r.redirect.sender->generate_code(expr);
7122 expr->expr = mputc(expr->expr, ')');
7123 } else expr->expr = mputstr(expr->expr, "NULL");
7124 }
7125
7126 void Statement::generate_code_portref(expression_struct *expr,
7127 Reference *p_ref)
7128 {
7129 // make a backup of the current expression
7130 char *expr_backup = expr->expr;
7131 // build the equivalent of p_ref in expr->expr
7132 expr->expr = mprintf("\"%s\"", p_ref->get_id()->get_dispname().c_str());
7133 FieldOrArrayRefs *t_subrefs = p_ref->get_subrefs();
7134 if (t_subrefs) {
7135 // array indices are present
7136 for (size_t i = 0; i < t_subrefs->get_nof_refs(); i++) {
7137 FieldOrArrayRef *t_ref = t_subrefs->get_ref(i);
7138 if (t_ref->get_type() != FieldOrArrayRef::ARRAY_REF)
7139 FATAL_ERROR("Statement::generate_code_portref()");
7140 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7141 char *tmp = expr->expr;
7142 expr->expr = mcopystr("get_port_name(");
7143 expr->expr = mputstr(expr->expr, tmp);
7144 Free(tmp);
7145 expr->expr = mputstr(expr->expr, ", ");
7146 t_ref->get_val()->generate_code_expr(expr);
7147 expr->expr = mputc(expr->expr, ')');
7148 }
7149 }
7150 // now expr->expr contains the equivalent of p_ref
7151 // append it to the original expression and restore the result
7152 expr_backup = mputstr(expr_backup, expr->expr);
7153 Free(expr->expr);
7154 expr->expr = expr_backup;
7155 }
7156
7157 void Statement::set_parent_path(WithAttribPath* p_path) {
7158 switch (statementtype) {
7159 case S_DEF:
7160 def->set_parent_path(p_path);
7161 break;
7162 case S_BLOCK:
7163 block->set_parent_path(p_path);
7164 break;
7165 case S_IF:
7166 if_stmt.ics->set_parent_path(p_path);
7167 if (if_stmt.elseblock)
7168 if_stmt.elseblock->set_parent_path(p_path);
7169 break;
7170 case S_SELECT:
7171 select.scs->set_parent_path(p_path);
7172 break;
7173 case S_FOR:
7174 loop.block->set_parent_path(p_path);
7175 break;
7176 case S_WHILE:
7177 case S_DOWHILE:
7178 loop.block->set_parent_path(p_path);
7179 break;
7180 case S_ASSIGNMENT:
7181 case S_LOG:
7182 case S_ACTION:
7183 case S_LABEL:
7184 case S_GOTO:
7185 case S_ERROR:
7186 case S_BREAK:
7187 case S_CONTINUE:
7188 case S_STOP_EXEC:
7189 case S_STOP_TESTCASE:
7190 case S_REPEAT:
7191 case S_START_UNDEF:
7192 case S_STOP_UNDEF:
7193 case S_UNKNOWN_INSTANCE:
7194 case S_FUNCTION_INSTANCE:
7195 case S_ALTSTEP_INSTANCE:
7196 case S_ACTIVATE:
7197 case S_ALT:
7198 case S_INTERLEAVE:
7199 case S_RETURN:
7200 case S_DEACTIVATE:
7201 case S_SEND:
7202 case S_CALL:
7203 case S_REPLY:
7204 case S_RAISE:
7205 case S_RECEIVE:
7206 case S_CHECK_RECEIVE:
7207 case S_TRIGGER:
7208 case S_GETCALL:
7209 case S_CHECK_GETCALL:
7210 case S_GETREPLY:
7211 case S_CHECK_GETREPLY:
7212 case S_CATCH:
7213 case S_CHECK_CATCH:
7214 case S_CHECK:
7215 case S_CLEAR:
7216 case S_START_PORT:
7217 case S_STOP_PORT:
7218 case S_HALT:
7219 case S_START_COMP:
7220 case S_START_COMP_REFD:
7221 case S_STOP_COMP:
7222 case S_KILL:
7223 case S_KILLED:
7224 case S_DONE:
7225 case S_CONNECT:
7226 case S_MAP:
7227 case S_DISCONNECT:
7228 case S_UNMAP:
7229 case S_START_TIMER:
7230 case S_STOP_TIMER:
7231 case S_TIMEOUT:
7232 case S_SETVERDICT:
7233 case S_TESTCASE_INSTANCE:
7234 case S_TESTCASE_INSTANCE_REFD:
7235 case S_ACTIVATE_REFD:
7236 case S_UNKNOWN_INVOKED:
7237 case S_FUNCTION_INVOKED:
7238 case S_ALTSTEP_INVOKED:
7239 case S_STRING2TTCN:
7240 case S_START_PROFILER:
7241 case S_STOP_PROFILER:
7242 case S_INT2ENUM:
7243 break;
7244 default:
7245 FATAL_ERROR("Statement::set_parent_path()");
7246 }
7247 }
7248
7249 // =================================
7250 // ===== Assignment
7251 // =================================
7252
7253 Assignment::Assignment(Reference *p_ref, Template *p_templ)
7254 : asstype(ASS_UNKNOWN), ref(p_ref), templ(p_templ), self_ref(false),
7255 template_restriction(TR_NONE), gen_restriction_check(false)
7256 {
7257 if(!ref || !templ) FATAL_ERROR("Ttcn::Assignment::Assignment");
7258 }
7259
7260 Assignment::Assignment(Reference *p_ref, Value *p_val)
7261 : asstype(ASS_VAR), ref(p_ref), val(p_val), self_ref(false),
7262 template_restriction(TR_NONE), gen_restriction_check(false)
7263 {
7264 if(!ref || !val) FATAL_ERROR("Ttcn::Assignment::Assignment");
7265 }
7266
7267 Assignment::~Assignment()
7268 {
7269 switch(asstype) {
7270 case ASS_UNKNOWN:
7271 case ASS_TEMPLATE:
7272 delete ref;
7273 delete templ;
7274 break;
7275 case ASS_VAR:
7276 delete ref;
7277 delete val;
7278 break;
7279 case ASS_ERROR:
7280 break;
7281 default:
7282 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7283 } // switch
7284 }
7285
7286 Assignment *Assignment::clone() const
7287 {
7288 FATAL_ERROR("Assignment::clone");
7289 }
7290
7291 void Assignment::set_my_scope(Scope *p_scope)
7292 {
7293 switch(asstype) {
7294 case ASS_UNKNOWN:
7295 case ASS_TEMPLATE:
7296 ref->set_my_scope(p_scope);
7297 templ->set_my_scope(p_scope);
7298 break;
7299 case ASS_VAR:
7300 ref->set_my_scope(p_scope);
7301 val->set_my_scope(p_scope);
7302 break;
7303 case ASS_ERROR:
7304 break;
7305 default:
7306 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7307 } // switch
7308 }
7309
7310 void Assignment::set_fullname(const string& p_fullname)
7311 {
7312 Node::set_fullname(p_fullname);
7313 switch(asstype) {
7314 case ASS_UNKNOWN:
7315 case ASS_TEMPLATE:
7316 ref->set_fullname(p_fullname);
7317 templ->set_fullname(p_fullname);
7318 break;
7319 case ASS_VAR:
7320 ref->set_fullname(p_fullname);
7321 val->set_fullname(p_fullname);
7322 break;
7323 case ASS_ERROR:
7324 break;
7325 default:
7326 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7327 } // switch
7328 }
7329
7330 void Assignment::dump(unsigned int level) const
7331 {
7332 // warning, ref is not always set (e.g. ASS_ERROR)
7333 switch (asstype) {
7334 case ASS_VAR:
7335 ref->dump(level+1);
7336 val->dump(level+1);
7337 break;
7338
7339 case ASS_ERROR:
7340 DEBUG(level, "*** ERROR ***");
7341 break;
7342
7343 case ASS_UNKNOWN:
7344 DEBUG(level, "*** UNKNOWN ***");
7345 break;
7346
7347 case ASS_TEMPLATE:
7348 ref->dump(level+1);
7349 templ->dump(level+1);
7350 break;
7351 }
7352 }
7353
7354 void Assignment::chk_unknown_ass()
7355 {
7356 Common::Assignment *t_ass = ref->get_refd_assignment();
7357 if (!t_ass) goto error;
7358 switch (t_ass->get_asstype()) {
7359 case Common::Assignment::A_ERROR:
7360 goto error;
7361 case Common::Assignment::A_PAR_VAL_IN:
7362 t_ass->use_as_lvalue(*ref);
7363 // no break
7364 case Common::Assignment::A_VAR:
7365 case Common::Assignment::A_PAR_VAL_OUT:
7366 case Common::Assignment::A_PAR_VAL_INOUT:
7367 if (templ->is_Value()) {
7368 Value *t_val = templ->get_Value();
7369 delete templ;
7370 val = t_val;
7371 asstype = ASS_VAR;
7372 chk_var_ass();
7373 } else {
7374 templ->error("A template body with matching symbols cannot be"
7375 " assigned to a variable");
7376 goto error;
7377 }
7378 break;
7379 case Common::Assignment::A_PAR_TEMPL_IN:
7380 t_ass->use_as_lvalue(*ref);
7381 // no break
7382 case Common::Assignment::A_VAR_TEMPLATE: {
7383 Type::typetype_t tt = t_ass->get_Type()->get_typetype();
7384 switch (tt) {
7385 case Type::T_BSTR:
7386 case Type::T_BSTR_A:
7387 case Type::T_HSTR:
7388 case Type::T_OSTR:
7389 case Type::T_CSTR:
7390 case Type::T_USTR:
7391 case Type::T_UTF8STRING:
7392 case Type::T_NUMERICSTRING:
7393 case Type::T_PRINTABLESTRING:
7394 case Type::T_TELETEXSTRING:
7395 case Type::T_VIDEOTEXSTRING:
7396 case Type::T_IA5STRING:
7397 case Type::T_GRAPHICSTRING:
7398 case Type::T_VISIBLESTRING:
7399 case Type::T_GENERALSTRING:
7400 case Type::T_UNIVERSALSTRING:
7401 case Type::T_BMPSTRING:
7402 case Type::T_UTCTIME:
7403 case Type::T_GENERALIZEDTIME:
7404 case Type::T_OBJECTDESCRIPTOR: {
7405 Ttcn::FieldOrArrayRefs *subrefs = ref->get_subrefs();
7406 if (!subrefs) break;
7407 size_t nof_subrefs = subrefs->get_nof_refs();
7408 if (nof_subrefs > 0) {
7409 Ttcn::FieldOrArrayRef *last_ref = subrefs
7410 ->get_ref(nof_subrefs - 1);
7411 if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
7412 if (!templ->is_Value()) {
7413 templ->error("A template body with matching symbols cannot be "
7414 "assigned to an element of a template variable");
7415 goto error;
7416 }
7417 }
7418 }
7419 break; }
7420 default:
7421 break;
7422 }
7423 }
7424 case Common::Assignment::A_PAR_TEMPL_OUT:
7425 case Common::Assignment::A_PAR_TEMPL_INOUT:
7426 asstype = ASS_TEMPLATE;
7427 chk_template_ass();
7428 break;
7429 default:
7430 ref->error("Reference to a variable or template variable was expected "
7431 "instead of %s", t_ass->get_description().c_str());
7432 goto error;
7433 }
7434 return;
7435 error:
7436 delete ref;
7437 delete templ;
7438 asstype = ASS_ERROR;
7439 return;
7440 }
7441
7442 void Assignment::chk_var_ass()
7443 {
7444 Common::Assignment *lhs = ref->get_refd_assignment();
7445 Type *var_type = lhs->get_Type();
7446 FieldOrArrayRefs *subrefs = ref->get_subrefs();
7447 Type *type =
7448 var_type->get_field_type(subrefs, Type::EXPECTED_DYNAMIC_VALUE);
7449 if (!type) goto error;
7450 val->set_my_governor(type);
7451 type->chk_this_value_ref(val);
7452 if (val->get_value_refd_last()->get_valuetype() == Value::V_OMIT) {
7453 Identifier *field_id = 0;
7454 if (subrefs) field_id = subrefs->remove_last_field();
7455 if (!field_id) {
7456 val->error("Omit value can be assigned to an optional field of "
7457 "a record or set value only");
7458 goto error;
7459 }
7460 Type *base_type = var_type
7461 ->get_field_type(subrefs, Type::EXPECTED_DYNAMIC_VALUE);
7462 // Putting field_id back to subrefs.
7463 subrefs->add(new FieldOrArrayRef(field_id));
7464 base_type = base_type->get_type_refd_last();
7465 switch (base_type->get_typetype()) {
7466 case Type::T_ERROR:
7467 goto error;
7468 case Type::T_SEQ_A:
7469 case Type::T_SEQ_T:
7470 case Type::T_SET_A:
7471 case Type::T_SET_T:
7472 break;
7473 default:
7474 val->error("Omit value can be assigned to an optional field of "
7475 "a record or set value only");
7476 goto error;
7477 }
7478 if (!base_type->get_comp_byName(*field_id)->get_is_optional()) {
7479 val->error("Assignment of `omit' to mandatory field `%s' of type "
7480 "`%s'", field_id->get_dispname().c_str(),
7481 base_type->get_typename().c_str());
7482 goto error;
7483 }
7484 } else {
7485 bool is_string_element = subrefs && subrefs->refers_to_string_element();
7486 self_ref |= type->chk_this_value(val, lhs, Type::EXPECTED_DYNAMIC_VALUE,
7487 INCOMPLETE_ALLOWED, OMIT_NOT_ALLOWED,
7488 (is_string_element ? NO_SUB_CHK : SUB_CHK), NOT_IMPLICIT_OMIT,
7489 (is_string_element ? IS_STR_ELEM : NOT_STR_ELEM));
7490 if (is_string_element) {
7491 // The length of RHS value shall be 1.
7492 Value *v_last = val->get_value_refd_last();
7493 switch (type->get_type_refd_last()->get_typetype()) {
7494 case Type::T_BSTR:
7495 case Type::T_BSTR_A:
7496 if (v_last->get_valuetype() != Value::V_BSTR) v_last = 0;
7497 break;
7498 case Type::T_HSTR:
7499 if (v_last->get_valuetype() != Value::V_HSTR) v_last = 0;
7500 break;
7501 case Type::T_OSTR:
7502 if (v_last->get_valuetype() != Value::V_OSTR) v_last = 0;
7503 break;
7504 case Type::T_CSTR:
7505 case Type::T_NUMERICSTRING:
7506 case Type::T_PRINTABLESTRING:
7507 case Type::T_IA5STRING:
7508 case Type::T_VISIBLESTRING:
7509 case Type::T_UTCTIME:
7510 case Type::T_GENERALIZEDTIME:
7511 if (v_last->get_valuetype() != Value::V_CSTR) v_last = 0;
7512 break;
7513 case Type::T_USTR:
7514 case Type::T_UTF8STRING:
7515 case Type::T_TELETEXSTRING:
7516 case Type::T_VIDEOTEXSTRING:
7517 case Type::T_GRAPHICSTRING:
7518 case Type::T_GENERALSTRING:
7519 case Type::T_UNIVERSALSTRING:
7520 case Type::T_BMPSTRING:
7521 case Type::T_OBJECTDESCRIPTOR:
7522 if (v_last->get_valuetype() != Value::V_USTR) v_last = 0;
7523 break;
7524 default:
7525 v_last = 0;
7526 }
7527 if (v_last) {
7528 size_t string_len = v_last->get_val_strlen();
7529 if (string_len != 1) {
7530 val->error("The length of the string to be assigned to a string "
7531 "element of type `%s' should be 1 instead of %lu",
7532 type->get_typename().c_str(),
7533 (unsigned long)string_len);
7534 goto error;
7535 }
7536 }
7537 }
7538 }
7539 return;
7540 error:
7541 delete ref;
7542 delete val;
7543 asstype = ASS_ERROR;
7544 return;
7545 }
7546
7547 void Assignment::chk_template_ass()
7548 {
7549 FieldOrArrayRefs *subrefs = ref->get_subrefs();
7550 Common::Assignment *lhs = ref->get_refd_assignment();
7551 if (!lhs) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7552 Type *type = lhs->get_Type()->
7553 get_field_type(subrefs, Type::EXPECTED_DYNAMIC_VALUE);
7554 if (!type) goto error;
7555 if (lhs->get_asstype() != Common::Assignment::A_VAR_TEMPLATE &&
7556 subrefs && subrefs->refers_to_string_element()) {
7557 ref->error("It is not allowed to index template strings");
7558 goto error;
7559 }
7560 templ->set_my_governor(type);
7561
7562 templ->flatten(false);
7563
7564 type->chk_this_template_ref(templ);
7565 self_ref |= type->chk_this_template_generic(templ, INCOMPLETE_ALLOWED,
7566 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, NOT_IMPLICIT_OMIT, lhs);
7567 chk_template_restriction();
7568 return;
7569 error:
7570 delete ref;
7571 delete templ;
7572 asstype = ASS_ERROR;
7573 return;
7574 }
7575
7576 void Assignment::chk()
7577 {
7578 switch(asstype) {
7579 case ASS_UNKNOWN:
7580 chk_unknown_ass();
7581 break;
7582 case ASS_VAR:
7583 chk_var_ass();
7584 break;
7585 case ASS_TEMPLATE:
7586 chk_template_ass();
7587 break;
7588 case ASS_ERROR:
7589 break;
7590 default:
7591 FATAL_ERROR("Ttcn::Assignment::chk()");
7592 } // switch
7593 }
7594
7595 void Assignment::set_code_section(
7596 GovernedSimple::code_section_t p_code_section)
7597 {
7598 switch(asstype) {
7599 case ASS_VAR:
7600 ref->set_code_section(p_code_section);
7601 val->set_code_section(p_code_section);
7602 break;
7603 case ASS_TEMPLATE:
7604 ref->set_code_section(p_code_section);
7605 templ->set_code_section(p_code_section);
7606 break;
7607 case ASS_UNKNOWN:
7608 case ASS_ERROR:
7609 break;
7610 default:
7611 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7612 } // switch
7613 }
7614
7615 void Assignment::chk_template_restriction()
7616 {
7617 if (asstype!=ASS_TEMPLATE)
7618 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7619 Common::Assignment *t_ass = ref->get_refd_assignment();
7620 if (!t_ass) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7621 switch (t_ass->get_asstype()) {
7622 case Common::Assignment::A_VAR_TEMPLATE: {
7623 Def_Var_Template* dvt = dynamic_cast<Def_Var_Template*>(t_ass);
7624 if (!dvt) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7625 template_restriction = dvt->get_template_restriction();
7626 } break;
7627 case Common::Assignment::A_PAR_TEMPL_IN:
7628 case Common::Assignment::A_PAR_TEMPL_OUT:
7629 case Common::Assignment::A_PAR_TEMPL_INOUT: {
7630 FormalPar* fp = dynamic_cast<FormalPar*>(t_ass);
7631 if (!fp) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7632 template_restriction = fp->get_template_restriction();
7633 } break;
7634 default:
7635 template_restriction = TR_NONE;
7636 }
7637 // transform the restriction if this is a subfield
7638 template_restriction = Template::get_sub_restriction(template_restriction, ref);
7639 // check the template restriction
7640 gen_restriction_check =
7641 templ->chk_restriction("template", template_restriction, this);
7642 }
7643
7644 char *Assignment::generate_code(char *str)
7645 {
7646 FieldOrArrayRefs *t_subrefs = ref->get_subrefs();
7647 const bool rhs_copied = self_ref;
7648 switch (asstype) {
7649 case ASS_VAR: {
7650 const string& rhs_copy = val->get_temporary_id();
7651 string rhs_ref = rhs_copy;
7652 if (rhs_copied /*&& val->get_valuetype() == Value::V_CHOICE*/) {
7653 if (val->get_my_governor()->is_optional_field()) {
7654 str = mputprintf(str, "{\nOPTIONAL<%s> %s;\n",
7655 val->get_my_governor()->get_genname_value(val->get_my_scope()).c_str(), rhs_copy.c_str());
7656 rhs_ref += "()";
7657 } else {
7658 str = mputprintf(str, "{\n%s %s;\n",
7659 val->get_my_governor()->get_genname_value(val->get_my_scope()).c_str(), rhs_copy.c_str());
7660 }
7661 }
7662 bool needs_conv = use_runtime_2 && TypeConv::needs_conv_refd(val);
7663 if (needs_conv) {
7664 case3:
7665 // Most complicated case. The LHS is saved in a temporary reference,
7666 // in case we need to access it more than once, e.g:
7667 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7668 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7669 // This saves having to index x2 more than once.
7670 const string& tmp_id = val->get_temporary_id(); // For "ref".
7671 const char *tmp_id_str = tmp_id.c_str();
7672 const string& type_genname =
7673 val->get_my_governor()->get_genname_value(val->get_my_scope());
7674 const char *type_genname_str = type_genname.c_str();
7675 expression_struct expr;
7676 Code::init_expr(&expr);
7677 ref->generate_code(&expr);
7678
7679 if (rhs_copied) {
7680 if (needs_conv)
7681 str = TypeConv::gen_conv_code_refd(str, rhs_ref.c_str(), val);
7682 else str = val->generate_code_init(str, rhs_ref.c_str());
7683 }
7684
7685 str = mputstr(str, "{\n");
7686 str = mputstr(str, expr.preamble);
7687 if (t_subrefs && t_subrefs->refers_to_string_element()) {
7688 // The LHS is a string element.
7689 str = mputprintf(str, "%s_ELEMENT %s(%s);\n", type_genname_str,
7690 tmp_id_str, expr.expr);
7691 } else {
7692 // The LHS is a normal value.
7693 str = mputprintf(str, "%s& %s = %s; /* 7388 */\n", type_genname_str,
7694 tmp_id_str, expr.expr);
7695 }
7696 str = mputstr(str, expr.postamble);
7697 // We now have a reference to the LHS. Generate the actual assignment
7698 if (rhs_copied) {
7699 str = mputprintf(str, "%s = %s;\n", tmp_id_str, rhs_copy.c_str());
7700 }
7701 else {
7702 if (needs_conv)
7703 str = TypeConv::gen_conv_code_refd(str, tmp_id_str, val);
7704 else str = val->generate_code_init(str, tmp_id_str);
7705 }
7706 Code::free_expr(&expr);
7707 str = mputstr(str, "}\n");
7708 }
7709 else {
7710 if (t_subrefs) {
7711 if (!val->has_single_expr()) goto case3;
7712 // C++ equivalent of RHS is a single expression.
7713 expression_struct expr;
7714 Code::init_expr(&expr);
7715 ref->generate_code(&expr);// vu.s()
7716 if (rhs_copied) {
7717 str = mputprintf(str, "%s = %s;\n",
7718 rhs_copy.c_str(), val->get_single_expr().c_str());
7719
7720 expr.expr = mputprintf(expr.expr, " = %s", rhs_copy.c_str());
7721 }
7722 else {
7723 expr.expr = mputprintf(expr.expr,
7724 " = %s", val->get_single_expr().c_str());
7725 }
7726 str = Code::merge_free_expr(str, &expr);
7727 }
7728 else {
7729 // The LHS is a single identifier.
7730 const string& rhs_name = ref->get_refd_assignment()
7731 ->get_genname_from_scope(ref->get_my_scope());
7732 if (val->can_use_increment(ref)) {
7733 switch (val->get_optype()) {
7734 case Value::OPTYPE_ADD:
7735 str = mputprintf(str, "++%s;\n", rhs_name.c_str());
7736 break;
7737 case Value::OPTYPE_SUBTRACT:
7738 str = mputprintf(str, "--%s;\n", rhs_name.c_str());
7739 break;
7740 default:
7741 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7742 }
7743 } else {
7744 str = val->generate_code_init(str,
7745 (rhs_copied ? rhs_copy : rhs_name).c_str());
7746
7747 if (rhs_copied) {
7748 str = mputprintf(str, "%s = %s;\n", rhs_name.c_str(), rhs_copy.c_str());
7749 }
7750 }
7751 }
7752 }
7753 if (rhs_copied) {
7754 str = mputstr(str, "}\n");
7755 }
7756 break; }
7757 case ASS_TEMPLATE: {
7758 const string& rhs_copy = templ->get_temporary_id();
7759 if (rhs_copied /*&& val->get_valuetype() == Value::V_CHOICE*/) {
7760 str = mputprintf(str, "{\n%s %s;\n",
7761 templ->get_my_governor()->get_genname_template(templ->get_my_scope()).c_str(), rhs_copy.c_str()//, rhs_copy.c_str()
7762 );
7763 }
7764 bool needs_conv = use_runtime_2 && TypeConv::needs_conv_refd(templ);
7765 if (needs_conv) { // case 3
7766 case3t:
7767 // Most complicated case. The LHS is saved in a temporary reference.
7768 const string& tmp_id = templ->get_temporary_id();
7769 const char *tmp_id_str = tmp_id.c_str();
7770 expression_struct expr;
7771 Code::init_expr(&expr);
7772 ref->generate_code(&expr);
7773
7774 if (rhs_copied) {
7775 if (needs_conv)
7776 str = TypeConv::gen_conv_code_refd(str, rhs_copy.c_str(), templ);
7777 else str = templ->generate_code_init(str, rhs_copy.c_str());
7778
7779 }
7780 str = mputstr(str, "{\n");
7781 str = mputstr(str, expr.preamble);
7782 str = mputprintf(str, "%s& %s = %s;\n",
7783 templ->get_my_governor()->get_genname_template(
7784 templ->get_my_scope()
7785 ).c_str(), tmp_id_str, expr.expr);
7786 str = mputstr(str, expr.postamble);
7787 if (rhs_copied) {
7788 str = mputprintf(str, "%s = %s;\n", tmp_id_str, rhs_copy.c_str());
7789 }
7790 else {
7791 if (needs_conv)
7792 str = TypeConv::gen_conv_code_refd(str, tmp_id_str, templ);
7793 else {
7794 if (Common::Type::T_SEQOF == templ->get_my_governor()->get_typetype() ||
7795 Common::Type::T_ARRAY == templ->get_my_governor()->get_typetype()) {
7796 str = mputprintf(str, "%s.remove_all_permutations();\n", tmp_id_str);
7797 }
7798 str = templ->generate_code_init(str, tmp_id_str);
7799 }
7800 }
7801 Code::free_expr(&expr);
7802
7803 if (template_restriction != TR_NONE && gen_restriction_check)
7804 str = Template::generate_restriction_check_code(str,
7805 tmp_id_str, template_restriction);
7806 str = mputstr(str, "}\n");
7807 }
7808 else { // !needs_conv
7809 if (t_subrefs) {
7810 if ((template_restriction == TR_NONE || !gen_restriction_check)
7811 && templ->has_single_expr()) {
7812 // C++ equivalent of RHS is a single expression and no restriction
7813 // check. Skipped if conversion needed.
7814 expression_struct expr;
7815 Code::init_expr(&expr);
7816 ref->generate_code(&expr);
7817 if (rhs_copied) {
7818 str = mputprintf(str, "%s = %s;\n",
7819 rhs_copy.c_str(), templ->get_single_expr(false).c_str());
7820
7821 expr.expr = mputprintf(expr.expr, " = %s", rhs_copy.c_str());
7822 }
7823 else {
7824 expr.expr = mputprintf(expr.expr,
7825 " = %s", templ->get_single_expr(false).c_str());
7826 }
7827 str = Code::merge_free_expr(str, &expr); // will add a semicolon
7828 }
7829 else goto case3t;
7830 }
7831 else {
7832 // LHS is a single identifier
7833 const string& rhs_name = ref->get_refd_assignment()
7834 ->get_genname_from_scope(ref->get_my_scope());
7835 if (Common::Type::T_SEQOF == templ->get_my_governor()->get_typetype() ||
7836 Common::Type::T_ARRAY == templ->get_my_governor()->get_typetype()) {
7837 str = mputprintf(str, "%s.remove_all_permutations();\n", (rhs_copied ? rhs_copy : rhs_name).c_str());
7838 }
7839 str = templ->generate_code_init(str,
7840 (rhs_copied ? rhs_copy : rhs_name).c_str());
7841 if (rhs_copied) {
7842 str = mputprintf(str, "%s = %s;\n", rhs_name.c_str(), rhs_copy.c_str());
7843 }
7844 if (template_restriction != TR_NONE && gen_restriction_check)
7845 str = Template::generate_restriction_check_code(str,
7846 ref->get_refd_assignment()->get_genname_from_scope(
7847 ref->get_my_scope()
7848 ).c_str(), template_restriction);
7849 }
7850 }
7851 if (rhs_copied) {
7852 str = mputstr(str, "}\n");
7853 }
7854 break; }
7855 default:
7856 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7857 } // switch
7858 return str;
7859 }
7860
7861 // =================================
7862 // ===== ParamAssignment
7863 // =================================
7864
7865 ParamAssignment::ParamAssignment(Identifier *p_id, Reference *p_ref)
7866 : Node(), Location(), id(p_id), ref(p_ref)
7867 {
7868 if(!id || !ref) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7869 }
7870
7871 ParamAssignment::~ParamAssignment()
7872 {
7873 delete id;
7874 delete ref;
7875 }
7876
7877 ParamAssignment *ParamAssignment::clone() const
7878 {
7879 FATAL_ERROR("ParamAssignment::clone");
7880 }
7881
7882 void ParamAssignment::set_my_scope(Scope *p_scope)
7883 {
7884 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7885 ref->set_my_scope(p_scope);
7886 }
7887
7888 void ParamAssignment::set_fullname(const string& p_fullname)
7889 {
7890 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7891 ref->set_fullname(p_fullname);
7892 }
7893
7894 Reference *ParamAssignment::get_ref() const
7895 {
7896 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7897 return ref;
7898 }
7899
7900 Reference *ParamAssignment::steal_ref()
7901 {
7902 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7903 Reference *ret_val = ref;
7904 ref = 0;
7905 return ret_val;
7906 }
7907
7908 // =================================
7909 // ===== ParamAssignments
7910 // =================================
7911
7912 ParamAssignments::~ParamAssignments()
7913 {
7914 for(size_t i=0; i<parasss.size(); i++)
7915 delete parasss[i];
7916 parasss.clear();
7917 }
7918
7919 ParamAssignments *ParamAssignments::clone() const
7920 {
7921 FATAL_ERROR("ParamAssignments::clone");
7922 }
7923
7924 void ParamAssignments::set_my_scope(Scope *p_scope)
7925 {
7926 for(size_t i=0; i<parasss.size(); i++)
7927 parasss[i]->set_my_scope(p_scope);
7928 }
7929
7930 void ParamAssignments::set_fullname(const string& p_fullname)
7931 {
7932 Node::set_fullname(p_fullname);
7933 for(size_t i=0; i<parasss.size(); i++)
7934 parasss[i]->set_fullname(p_fullname+".parass_"+Int2string(i+1));
7935 }
7936
7937 void ParamAssignments::add_parass(ParamAssignment *p_parass)
7938 {
7939 if(!p_parass)
7940 FATAL_ERROR("ParamAssignments::add_parass()");
7941 parasss.add(p_parass);
7942 }
7943
7944 // =================================
7945 // ===== VariableEntry
7946 // =================================
7947
7948 VariableEntry::VariableEntry(Reference *p_ref)
7949 : Node(), Location(), ref(p_ref)
7950 {
7951 if(!ref) FATAL_ERROR("VariableEntry::VariableEntry()");
7952 }
7953
7954 VariableEntry::~VariableEntry()
7955 {
7956 delete ref;
7957 }
7958
7959 VariableEntry *VariableEntry::clone() const
7960 {
7961 FATAL_ERROR("VariableEntry::clone");
7962 }
7963
7964 void VariableEntry::set_my_scope(Scope *p_scope)
7965 {
7966 if(ref) ref->set_my_scope(p_scope);
7967 }
7968
7969 void VariableEntry::set_fullname(const string& p_fullname)
7970 {
7971 Node::set_fullname(p_fullname);
7972 if(ref) ref->set_fullname(p_fullname+".ref");
7973 }
7974
7975 // =================================
7976 // ===== VariableEntries
7977 // =================================
7978
7979 VariableEntries::~VariableEntries()
7980 {
7981 for(size_t i=0; i<ves.size(); i++)
7982 delete ves[i];
7983 ves.clear();
7984 }
7985
7986 VariableEntries *VariableEntries::clone() const
7987 {
7988 FATAL_ERROR("VariableEntries::clone");
7989 }
7990
7991 void VariableEntries::set_my_scope(Scope *p_scope)
7992 {
7993 for(size_t i=0; i<ves.size(); i++)
7994 ves[i]->set_my_scope(p_scope);
7995 }
7996
7997 void VariableEntries::set_fullname(const string& p_fullname)
7998 {
7999 Node::set_fullname(p_fullname);
8000 for(size_t i=0; i<ves.size(); i++)
8001 ves[i]->set_fullname(p_fullname+".ve_"+Int2string(i+1));
8002 }
8003
8004 void VariableEntries::add_ve(VariableEntry *p_ve)
8005 {
8006 if(!p_ve)
8007 FATAL_ERROR("VariableEntries::add_ve()");
8008 ves.add(p_ve);
8009 }
8010
8011 // =================================
8012 // ===== ParamRedirect
8013 // =================================
8014
8015 ParamRedirect::ParamRedirect(ParamAssignments *p_parasss)
8016 : Node(), Location(), parredirtype(P_ASS), parasss(p_parasss)
8017 {
8018 if(!parasss) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8019 }
8020
8021 ParamRedirect::ParamRedirect(VariableEntries *p_ves)
8022 : Node(), Location(), parredirtype(P_VAR), ves(p_ves)
8023 {
8024 if(!ves) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8025 }
8026
8027 ParamRedirect::~ParamRedirect()
8028 {
8029 switch(parredirtype) {
8030 case P_ASS:
8031 delete parasss;
8032 break;
8033 case P_VAR:
8034 delete ves;
8035 break;
8036 default:
8037 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
8038 } // switch
8039 }
8040
8041 ParamRedirect *ParamRedirect::clone() const
8042 {
8043 FATAL_ERROR("ParamRedirect::clone");
8044 }
8045
8046 void ParamRedirect::set_my_scope(Scope *p_scope)
8047 {
8048 switch(parredirtype) {
8049 case P_ASS:
8050 parasss->set_my_scope(p_scope);
8051 break;
8052 case P_VAR:
8053 ves->set_my_scope(p_scope);
8054 break;
8055 default:
8056 FATAL_ERROR("ParamRedirect::set_my_scope()");
8057 } // switch
8058 }
8059
8060 void ParamRedirect::set_fullname(const string& p_fullname)
8061 {
8062 Node::set_fullname(p_fullname);
8063 switch(parredirtype) {
8064 case P_ASS:
8065 parasss->set_fullname(p_fullname+".parasss");
8066 break;
8067 case P_VAR:
8068 ves->set_fullname(p_fullname+".parvars");
8069 break;
8070 default:
8071 FATAL_ERROR("ParamRedirect::set_fullname()");
8072 } // switch
8073 }
8074
8075 void ParamRedirect::chk_erroneous()
8076 {
8077 Error_Context cntxt(this, "In parameter redirect");
8078 switch(parredirtype) {
8079 case P_ASS: {
8080 map<string, ParamAssignment> parass_m;
8081 for (size_t i = 0; i < parasss->get_nof_parasss(); i++) {
8082 ParamAssignment *t_parass = parasss->get_parass_byIndex(i);
8083 const Identifier &t_id = t_parass->get_id();
8084 const string& name = t_id.get_name();
8085 const char *dispname_str = t_id.get_dispname().c_str();
8086 if (parass_m.has_key(name)) {
8087 t_parass->error("Duplicate redirect for parameter `%s'",
8088 dispname_str);
8089 parass_m[name]->note("A variable entry for parameter `%s' is "
8090 "already given here", dispname_str);
8091 } else parass_m.add(name, t_parass);
8092 Error_Context cntxt2(t_parass, "In redirect for parameter `%s'",
8093 dispname_str);
8094 chk_variable_ref(t_parass->get_ref(), 0);
8095 }
8096 parass_m.clear();
8097 break; }
8098 case P_VAR:
8099 for (size_t i = 0; i < ves->get_nof_ves(); i++) {
8100 VariableEntry *t_ve = ves->get_ve_byIndex(i);
8101 Error_Context cntxt2(t_ve, "In variable entry #%lu",
8102 (unsigned long) (i + 1));
8103 chk_variable_ref(t_ve->get_ref(), 0);
8104 }
8105 break;
8106 default:
8107 FATAL_ERROR("ParamRedirect::chk_erroneous()");
8108 } // switch
8109 }
8110
8111 void ParamRedirect::chk(Type *p_sig, bool is_out)
8112 {
8113 SignatureParamList *t_parlist = p_sig->get_signature_parameters();
8114 if (t_parlist) {
8115 Error_Context cntxt(this, "In parameter redirect");
8116 switch (parredirtype) {
8117 case P_ASS:
8118 chk_parasss(p_sig, t_parlist, is_out);
8119 break;
8120 case P_VAR:
8121 chk_ves(p_sig, t_parlist, is_out);
8122 break;
8123 default:
8124 FATAL_ERROR("ParamRedirect::chk()");
8125 }
8126 } else {
8127 error("Parameter redirect cannot be used because signature `%s' "
8128 "does not have parameters", p_sig->get_typename().c_str());
8129 chk_erroneous();
8130 }
8131 }
8132
8133 void ParamRedirect::chk_parasss(Type *p_sig, SignatureParamList *p_parlist,
8134 bool is_out)
8135 {
8136 map<string, ParamAssignment> parass_m;
8137 bool error_flag = false;
8138 for (size_t i = 0; i < parasss->get_nof_parasss(); i++) {
8139 ParamAssignment *t_parass = parasss->get_parass_byIndex(i);
8140 const Identifier &t_id = t_parass->get_id();
8141 const string& name = t_id.get_name();
8142 const char *dispname_str = t_id.get_dispname().c_str();
8143 if (parass_m.has_key(name)) {
8144 t_parass->error("Duplicate redirect for parameter `%s'",
8145 dispname_str);
8146 parass_m[name]->note("A variable entry for parameter `%s' is "
8147 "already given here", dispname_str);
8148 error_flag = true;
8149 } else parass_m.add(name, t_parass);
8150 Error_Context cntxt2(t_parass, "In redirect for parameter `%s'",
8151 dispname_str);
8152 if (p_parlist->has_param_withName(t_id)) {
8153 const SignatureParam *t_par = p_parlist->get_param_byName(t_id);
8154 SignatureParam::param_direction_t t_dir = t_par->get_direction();
8155 if (is_out) {
8156 if (t_dir == SignatureParam::PARAM_IN) {
8157 t_parass->error("Parameter `%s' of signature `%s' has `in' "
8158 "direction", dispname_str, p_sig->get_typename().c_str());
8159 error_flag = true;
8160 }
8161 } else {
8162 if (t_dir == SignatureParam::PARAM_OUT) {
8163 t_parass->error("Parameter `%s' of signature `%s' has `out' "
8164 "direction", dispname_str, p_sig->get_typename().c_str());
8165 error_flag = true;
8166 }
8167 }
8168 chk_variable_ref(t_parass->get_ref(), t_par->get_type());
8169 } else {
8170 t_parass->error("Signature `%s' does not have parameter named `%s'",
8171 p_sig->get_typename().c_str(), dispname_str);
8172 error_flag = true;
8173 chk_variable_ref(t_parass->get_ref(), 0);
8174 }
8175 }
8176 if (!error_flag) {
8177 // converting the AssignmentList to VariableList
8178 VariableEntries *t_ves = new VariableEntries;
8179 size_t upper_limit = is_out ?
8180 p_parlist->get_nof_out_params() : p_parlist->get_nof_in_params();
8181 for (size_t i = 0; i < upper_limit; i++) {
8182 SignatureParam *t_par = is_out ? p_parlist->get_out_param_byIndex(i)
8183 : p_parlist->get_in_param_byIndex(i);
8184 const string& name = t_par->get_id().get_name();
8185 if (parass_m.has_key(name))
8186 t_ves->add_ve(new VariableEntry(parass_m[name]->steal_ref()));
8187 else t_ves->add_ve(new VariableEntry);
8188 }
8189 delete parasss;
8190 ves = t_ves;
8191 parredirtype = P_VAR;
8192 }
8193 parass_m.clear();
8194 }
8195
8196 void ParamRedirect::chk_ves(Type *p_sig, SignatureParamList *p_parlist,
8197 bool is_out)
8198 {
8199 size_t nof_ves = ves->get_nof_ves();
8200 size_t nof_pars = is_out ?
8201 p_parlist->get_nof_out_params() : p_parlist->get_nof_in_params();
8202 if (nof_ves != nof_pars) {
8203 error("Too %s variable entries compared to the number of %s/inout "
8204 "parameters in signature `%s': %lu was expected instead of %lu",
8205 nof_ves > nof_pars ? "many" : "few", is_out ? "out" : "in",
8206 p_sig->get_typename().c_str(), (unsigned long) nof_pars,
8207 (unsigned long) nof_ves);
8208 }
8209 for (size_t i = 0; i < nof_ves; i++) {
8210 VariableEntry *t_ve = ves->get_ve_byIndex(i);
8211 if (i < nof_pars) {
8212 SignatureParam *t_par = is_out ? p_parlist->get_out_param_byIndex(i)
8213 : p_parlist->get_in_param_byIndex(i);
8214 Error_Context cntxt(t_ve, "In variable entry #%lu (for parameter `%s')",
8215 (unsigned long) (i + 1), t_par->get_id().get_dispname().c_str());
8216 chk_variable_ref(t_ve->get_ref(), t_par->get_type());
8217 } else {
8218 Error_Context cntxt(t_ve, "In variable entry #%lu",
8219 (unsigned long) (i + 1));
8220 chk_variable_ref(t_ve->get_ref(), 0);
8221 }
8222 }
8223 }
8224
8225 void ParamRedirect::chk_variable_ref(Reference *p_ref, Type *p_type)
8226 {
8227 if (!p_ref) return;
8228 Type *t_var_type = p_ref->chk_variable_ref();
8229 if (p_type && t_var_type && !p_type->is_identical(t_var_type)) {
8230 p_ref->error("Type mismatch in parameter redirect: "
8231 "A variable of type `%s' was expected instead of `%s'",
8232 p_type->get_typename().c_str(),
8233 t_var_type->get_typename().c_str());
8234 }
8235 }
8236
8237 void ParamRedirect::set_code_section(
8238 GovernedSimple::code_section_t p_code_section)
8239 {
8240 // code can be generated from VariableList only
8241 switch (parredirtype) {
8242 case P_ASS:
8243 break;
8244 case P_VAR:
8245 for (size_t i = 0; i < ves->get_nof_ves(); i++) {
8246 Reference *t_ref = ves->get_ve_byIndex(i)->get_ref();
8247 if (t_ref) t_ref->set_code_section(p_code_section);
8248 }
8249 break;
8250 default:
8251 FATAL_ERROR("ParamRedirect::set_code_section()");
8252 }
8253 }
8254
8255 void ParamRedirect::generate_code(expression_struct_t *expr)
8256 {
8257 // AssignmentList is converted to VariableList during checking
8258 if (parredirtype != P_VAR) FATAL_ERROR("ParamRedirect::generate_code()");
8259 for (size_t i = 0; i < ves->get_nof_ves(); i++) {
8260 if (i > 0) expr->expr = mputstr(expr->expr, ", ");
8261 Reference *ref = ves->get_ve_byIndex(i)->get_ref();
8262 if (ref) {
8263 // the variable reference is present
8264 expr->expr = mputstr(expr->expr, "&(");
8265 ref->generate_code(expr);
8266 expr->expr = mputc(expr->expr, ')');
8267 } else expr->expr = mputstr(expr->expr, "NULL");
8268 }
8269 }
8270
8271 // =================================
8272 // ===== LogArgument
8273 // =================================
8274
8275 LogArgument::LogArgument(TemplateInstance *p_ti)
8276 : logargtype(L_UNDEF)
8277 {
8278 if (!p_ti) FATAL_ERROR("LogArgument::LogArgument()");
8279 ti = p_ti;
8280 }
8281
8282 LogArgument::~LogArgument()
8283 {
8284 switch (logargtype) {
8285 case L_ERROR:
8286 break;
8287 case L_UNDEF:
8288 case L_TI:
8289 delete ti;
8290 break;
8291 case L_VAL:
8292 case L_MATCH:
8293 case L_MACRO:
8294 delete val;
8295 break;
8296 case L_REF:
8297 delete ref;
8298 break;
8299 case L_STR:
8300 delete cstr;
8301 break;
8302 default:
8303 FATAL_ERROR("LogArgument::~LogArgument()");
8304 } // switch
8305 }
8306
8307 LogArgument *LogArgument::clone() const
8308 {
8309 FATAL_ERROR("LogArgument::clone");
8310 }
8311
8312 void LogArgument::set_my_scope(Scope *p_scope)
8313 {
8314 switch (logargtype) {
8315 case L_ERROR:
8316 break;
8317 case L_UNDEF:
8318 case L_TI:
8319 ti->set_my_scope(p_scope);
8320 break;
8321 case L_VAL:
8322 case L_MATCH:
8323 case L_MACRO:
8324 val->set_my_scope(p_scope);
8325 break;
8326 case L_REF:
8327 ref->set_my_scope(p_scope);
8328 break;
8329 case L_STR:
8330 break;
8331 default:
8332 FATAL_ERROR("LogArgument::set_my_scope()");
8333 } // switch
8334 }
8335
8336 void LogArgument::set_fullname(const string& p_fullname)
8337 {
8338 Node::set_fullname(p_fullname);
8339 switch (logargtype) {
8340 case L_ERROR:
8341 break;
8342 case L_UNDEF:
8343 case L_TI:
8344 ti->set_fullname(p_fullname);
8345 break;
8346 case L_VAL:
8347 case L_MATCH:
8348 case L_MACRO:
8349 val->set_fullname(p_fullname);
8350 break;
8351 case L_REF:
8352 ref->set_fullname(p_fullname);
8353 break;
8354 case L_STR:
8355 break;
8356 default:
8357 FATAL_ERROR("LogArgument::set_fullname()");
8358 } // switch
8359 }
8360
8361 const string& LogArgument::get_str() const
8362 {
8363 if (logargtype != L_STR) FATAL_ERROR("LogArgument::get_str()");
8364 return *cstr;
8365 }
8366
8367 Value *LogArgument::get_val() const
8368 {
8369 switch (logargtype) {
8370 case L_VAL:
8371 case L_MATCH:
8372 case L_MACRO:
8373 break;
8374 default:
8375 FATAL_ERROR("LogArgument::get_val()");
8376 }
8377 return val;
8378 }
8379
8380 Ref_base *LogArgument::get_ref() const
8381 {
8382 if (logargtype != L_REF) FATAL_ERROR("LogArgument::get_ref()");
8383 return ref;
8384 }
8385
8386 TemplateInstance *LogArgument::get_ti() const
8387 {
8388 if (logargtype != L_TI) FATAL_ERROR("LogArgument::get_ref()");
8389 return ti;
8390 }
8391
8392 void LogArgument::append_str(const string& p_str)
8393 {
8394 if (logargtype != L_STR) FATAL_ERROR("LogArgument::append_str()");
8395 *cstr += p_str;
8396 }
8397
8398 void LogArgument::chk() // determine the proper type of the log argument
8399 {
8400 if (logargtype != L_UNDEF) return;
8401 Template *t_templ = ti->get_Template();
8402 t_templ = t_templ->get_template_refd_last();
8403 t_templ->set_lowerid_to_ref();
8404 if (!ti->get_Type() && !ti->get_DerivedRef() && t_templ->is_Value()) {
8405 // drop the template instance and keep only the embedded value
8406 Value *t_val = t_templ->get_Value();
8407 delete ti;
8408 logargtype = L_VAL;
8409 val = t_val;
8410 chk_val();
8411 } else {
8412 // try to obtain the governor of the template instance
8413 Type *governor = ti->get_expr_governor(Type::EXPECTED_TEMPLATE);
8414 if (!governor) {
8415 // the governor is still unknown: an error occurred
8416 // try to interpret possible enum values as references
8417 t_templ->set_lowerid_to_ref();
8418 governor = t_templ->get_expr_governor(Type::EXPECTED_TEMPLATE);
8419 }
8420 if (governor) {
8421 logargtype = L_TI;
8422 ti->chk(governor);
8423 } else {
8424 t_templ->error("Cannot determine the type of the argument");
8425 delete ti;
8426 logargtype = L_ERROR;
8427 }
8428 }
8429 }
8430
8431 void LogArgument::chk_ref()
8432 {
8433 Common::Assignment *t_ass = ref->get_refd_assignment();
8434 if (!t_ass) return;
8435 Common::Assignment::asstype_t asstype = t_ass->get_asstype();
8436 switch (asstype) {
8437 case Common::Assignment::A_FUNCTION_RVAL:
8438 case Common::Assignment::A_FUNCTION_RTEMP:
8439 case Common::Assignment::A_EXT_FUNCTION_RVAL:
8440 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
8441 ref->get_my_scope()->chk_runs_on_clause(t_ass, *this, "call");
8442 case Common::Assignment::A_CONST:
8443 case Common::Assignment::A_EXT_CONST:
8444 case Common::Assignment::A_MODULEPAR:
8445 case Common::Assignment::A_MODULEPAR_TEMP:
8446 case Common::Assignment::A_TEMPLATE:
8447 case Common::Assignment::A_VAR:
8448 case Common::Assignment::A_VAR_TEMPLATE:
8449 case Common::Assignment::A_PAR_VAL_IN:
8450 case Common::Assignment::A_PAR_VAL_OUT:
8451 case Common::Assignment::A_PAR_VAL_INOUT:
8452 case Common::Assignment::A_PAR_TEMPL_IN:
8453 case Common::Assignment::A_PAR_TEMPL_OUT:
8454 case Common::Assignment::A_PAR_TEMPL_INOUT: {
8455 // the reference points to a value or template-like entity
8456 // checking sub-references
8457 FieldOrArrayRefs *subrefs = ref->get_subrefs();
8458 if (subrefs && t_ass->get_Type()->get_field_type(subrefs,
8459 Type::EXPECTED_DYNAMIC_VALUE)) {
8460 // subrefs seems to be correct
8461 // also checking the presence of referred fields if possible
8462 if (asstype == Common::Assignment::A_CONST) {
8463 ReferenceChain refch(ref, "While searching referenced value");
8464 t_ass->get_Value()->get_refd_sub_value(subrefs, 0, false, &refch);
8465 } else if (asstype == Common::Assignment::A_TEMPLATE) {
8466 ReferenceChain refch(ref, "While searching referenced template");
8467 t_ass->get_Template()
8468 ->get_refd_sub_template(subrefs, false, &refch);
8469 }
8470 }
8471 break; }
8472 case Common::Assignment::A_TIMER:
8473 case Common::Assignment::A_PORT: {
8474 ArrayDimensions *t_dims = t_ass->get_Dimensions();
8475 if (t_dims) t_dims->chk_indices(ref, t_ass->get_assname(), true,
8476 Type::EXPECTED_DYNAMIC_VALUE);
8477 else if (ref->get_subrefs()) ref->error("Reference to single %s "
8478 "cannot have field or array sub-references",
8479 t_ass->get_description().c_str());
8480 break; }
8481 case Common::Assignment::A_PAR_TIMER:
8482 case Common::Assignment::A_PAR_PORT:
8483 if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
8484 "field or array sub-references", t_ass->get_description().c_str());
8485 break;
8486 case Common::Assignment::A_FUNCTION:
8487 case Common::Assignment::A_EXT_FUNCTION:
8488 ref->error("Reference to a value, template, timer or port was expected "
8489 "instead of a call of %s, which does not have return type",
8490 t_ass->get_description().c_str());
8491 break;
8492 default:
8493 ref->error("Reference to a value, template, timer or port was expected "
8494 "instead of %s", t_ass->get_description().c_str());
8495 }
8496 }
8497
8498 void LogArgument::chk_val()
8499 {
8500 // literal enumerated values cannot appear in this context
8501 val->set_lowerid_to_ref();
8502 switch (val->get_valuetype()) {
8503 case Value::V_CSTR: {
8504 string *t_cstr = new string(val->get_val_str());
8505 delete val;
8506 cstr = t_cstr;
8507 logargtype = L_STR;
8508 return; }
8509 case Value::V_REFD: {
8510 Ref_base *t_ref = val->steal_ttcn_ref_base();
8511 delete val;
8512 ref = t_ref;
8513 logargtype = L_REF;
8514 chk_ref();
8515 return; }
8516 case Value::V_EXPR:
8517 if (val->get_optype() == Value::OPTYPE_MATCH) logargtype = L_MATCH;
8518 else logargtype = L_VAL;
8519 break;
8520 case Value::V_MACRO:
8521 logargtype = L_MACRO;
8522 break;
8523 default:
8524 logargtype = L_VAL;
8525 } // switch
8526 Type *governor = val->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
8527 if (governor) {
8528 val->set_my_governor(governor);
8529 (void)governor->chk_this_value(val, 0, Type::EXPECTED_DYNAMIC_VALUE,
8530 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
8531 if (logargtype == L_VAL && val->get_valuetype() == Value::V_CSTR
8532 && !val->is_unfoldable()) { // string value known at compile time
8533 string *t_cstr = new string(val->get_val_str());
8534 delete val;
8535 cstr = t_cstr;
8536 logargtype = L_STR;
8537 return;
8538 }
8539 if (logargtype == L_MACRO) {
8540 switch (val->get_valuetype()) {
8541 case Value::V_CSTR: {
8542 // the macro was evaluated to a charstring value
8543 string *t_cstr = new string(val->get_val_str());
8544 delete val;
8545 cstr = t_cstr;
8546 logargtype = L_STR;
8547 break; }
8548 case Value::V_MACRO:
8549 // the macro could not be evaluated at compile time
8550 // leave logargtype as is
8551 break;
8552 default:
8553 // the macro was evaluated to other value (e.g. integer)
8554 logargtype = L_VAL;
8555 }
8556 }
8557 } else {
8558 val->error("Cannot determine the type of the argument");
8559 delete val;
8560 logargtype = L_ERROR;
8561 }
8562 }
8563
8564 void LogArgument::dump(unsigned int level) const
8565 {
8566 Node::dump(level++);
8567 switch (logargtype) {
8568 case L_ERROR:
8569 DEBUG(level, "*error*");
8570 break;
8571 case L_UNDEF:
8572 DEBUG(level, "*undef*");
8573 break;
8574 case L_TI:
8575 DEBUG(level, "TemplateInstance");
8576 break;
8577 case L_VAL:
8578 val->dump(level);
8579 break;
8580 case L_MATCH:
8581 DEBUG(level, "Match");
8582 break;
8583 case L_MACRO:
8584 DEBUG(level, "Macro");
8585 break;
8586 case L_REF:
8587 DEBUG(level, "Reference");
8588 break;
8589 case L_STR:
8590 DEBUG(level, "String=`%s'", cstr->c_str());
8591 break;
8592 default:
8593 FATAL_ERROR("LogArgument::~LogArgument()");
8594 } // switch
8595 }
8596
8597 void LogArgument::set_code_section(
8598 GovernedSimple::code_section_t p_code_section)
8599 {
8600 switch (logargtype) {
8601 case L_UNDEF:
8602 case L_TI:
8603 ti->set_code_section(p_code_section);
8604 break;
8605 case L_VAL:
8606 case L_MATCH:
8607 case L_MACRO:
8608 val->set_code_section(p_code_section);
8609 break;
8610 case L_REF:
8611 ref->set_code_section(p_code_section);
8612 break;
8613 case L_STR:
8614 case L_ERROR:
8615 break;
8616 default:
8617 FATAL_ERROR("LogArgument::set_code_section()");
8618 } // switch
8619 }
8620
8621 char *LogArgument::generate_code_log(char *str)
8622 {
8623 expression_struct expr;
8624 Code::init_expr(&expr);
8625 generate_code_expr(&expr);
8626 str = Code::merge_free_expr(str, &expr);
8627 return str;
8628 }
8629
8630 void LogArgument::chk_recursions(ReferenceChain& refch)
8631 {
8632 switch (logargtype) {
8633 case L_UNDEF:
8634 case L_TI:
8635 ti->chk_recursions(refch);
8636 break;
8637 case L_VAL:
8638 case L_MATCH:
8639 case L_MACRO:
8640 val->chk_recursions(refch);
8641 break;
8642 case L_REF: {
8643 Common::Assignment *ass = ref->get_refd_assignment();
8644 if (!ass) break;
8645 refch.add(ass->get_fullname());
8646 } break;
8647 case L_STR:
8648 case L_ERROR:
8649 break;
8650 default:
8651 FATAL_ERROR("LogArgument::chk_recursions()");
8652 } // switch
8653 }
8654
8655 bool LogArgument::has_single_expr()
8656 {
8657 switch (logargtype) {
8658 case L_UNDEF:
8659 case L_TI:
8660 return ti->has_single_expr();
8661 case L_VAL:
8662 case L_MATCH:
8663 case L_MACRO:
8664 return ( val->has_single_expr() && !val->explicit_cast_needed() );
8665 case L_REF: {
8666 Common::Assignment *ass = ref->get_refd_assignment();
8667 switch (ass->get_asstype()) {
8668 case Common::Assignment::A_CONST:
8669 case Common::Assignment::A_EXT_CONST:
8670 return ref->has_single_expr();
8671 default:
8672 return false;
8673 }
8674 break; }
8675 case L_STR:
8676 case L_ERROR:
8677 return true;
8678 default:
8679 FATAL_ERROR("LogArgument::has_single_expr()");
8680 } // switch
8681 return true;
8682 }
8683
8684 void LogArgument::generate_code_expr(expression_struct *expr)
8685 {
8686 switch(logargtype) {
8687 case L_TI: {
8688 if (ti->is_only_specific_value()) {
8689 // use the embedded specific value for code generation
8690 ti->get_Template()->get_specific_value()->generate_code_log(expr);
8691 } else {
8692 ti->generate_code(expr);
8693 expr->expr = mputstr(expr->expr, ".log()");
8694 }
8695 break; }
8696 case L_VAL:
8697 val->generate_code_log(expr);
8698 break;
8699 case L_MATCH:
8700 val->generate_code_log_match(expr);
8701 break;
8702 case L_MACRO:
8703 if (val->has_single_expr()) {
8704 expr->expr = mputprintf(expr->expr, "TTCN_Logger::log_event_str(%s)",
8705 val->get_single_expr().c_str());
8706 } else val->generate_code_log(expr);
8707 break;
8708 case L_REF: {
8709 ref->generate_code_const_ref(expr);
8710 expr->expr=mputstr(expr->expr, ".log()");
8711 break;}
8712 case L_STR: {
8713 size_t str_len = cstr->size();
8714 const char *str_ptr = cstr->c_str();
8715 switch (str_len) {
8716 case 0:
8717 // the string is empty: do not generate any code
8718 case 1:
8719 // the string has one character: use log_char member
8720 expr->expr = mputstr(expr->expr, "TTCN_Logger::log_char('");
8721 expr->expr = Code::translate_character(expr->expr, *str_ptr, false);
8722 expr->expr = mputstr(expr->expr, "')");
8723 break;
8724 default:
8725 // the string has more characters: use log_event_str member
8726 expr->expr = mputstr(expr->expr, "TTCN_Logger::log_event_str(\"");
8727 expr->expr = Code::translate_string(expr->expr, str_ptr);
8728 expr->expr = mputstr(expr->expr, "\")");
8729 }
8730 break; }
8731 default:
8732 FATAL_ERROR("LogArgument::generate_code_expr()");
8733 } // switch
8734 }
8735
8736 // =================================
8737 // ===== LogArguments
8738 // =================================
8739
8740 LogArguments::~LogArguments()
8741 {
8742 for(size_t i=0; i<logargs.size(); i++) delete logargs[i];
8743 logargs.clear();
8744 }
8745
8746 LogArguments *LogArguments::clone() const
8747 {
8748 FATAL_ERROR("LogArguments::clone");
8749 }
8750
8751 void LogArguments::add_logarg(LogArgument *p_logarg)
8752 {
8753 if(!p_logarg)
8754 FATAL_ERROR("LogArguments::add_logarg()");
8755 logargs.add(p_logarg);
8756 }
8757
8758 void LogArguments::set_my_scope(Scope *p_scope)
8759 {
8760 for(size_t i=0; i<logargs.size(); i++)
8761 logargs[i]->set_my_scope(p_scope);
8762 }
8763
8764 void LogArguments::set_fullname(const string& p_fullname)
8765 {
8766 Node::set_fullname(p_fullname);
8767 for(size_t i=0; i<logargs.size(); i++)
8768 logargs[i]->set_fullname(p_fullname+".logargs_"+Int2string(i+1));
8769 }
8770
8771 void LogArguments::chk()
8772 {
8773 for(size_t i=0; i<logargs.size(); i++)
8774 logargs[i]->chk();
8775 }
8776
8777 void LogArguments::join_strings()
8778 {
8779 // points to the previous string argument otherwise it is NULL
8780 LogArgument *prev_arg = 0;
8781 for (size_t i = 0; i < logargs.size(); ) {
8782 LogArgument *arg = logargs[i];
8783 if (arg->get_type() == LogArgument::L_STR) {
8784 const string& str = arg->get_str();
8785 if (str.size() > 0) {
8786 // the current argument is a non-empty string
8787 if (prev_arg) {
8788 // append str to prev_arg and drop arg
8789 prev_arg->append_str(str);
8790 delete arg;
8791 logargs.replace(i, 1);
8792 // don't increment i
8793 } else {
8794 // keep it for the next iteration
8795 prev_arg = arg;
8796 i++;
8797 }
8798 } else {
8799 // the current argument is an empty string
8800 // simply drop it unless it is the only argument
8801 // note: we must distinguish between log() and log("")
8802 if (i > 0 || logargs.size() > 1) {
8803 delete arg;
8804 logargs.replace(i, 1);
8805 // don't increment i
8806 } else break;
8807 }
8808 } else {
8809 // the current argument is not a string
8810 // forget the previous arg
8811 prev_arg = 0;
8812 i++;
8813 }
8814 }
8815 }
8816
8817 void LogArguments::set_code_section(
8818 GovernedSimple::code_section_t p_code_section)
8819 {
8820 for (size_t i = 0; i < logargs.size(); i++)
8821 logargs[i]->set_code_section(p_code_section);
8822 }
8823
8824 char *LogArguments::generate_code(char *str)
8825 {
8826 for(size_t i=0; i<logargs.size(); i++)
8827 str=logargs[i]->generate_code_log(str);
8828 return str;
8829 }
8830
8831 void LogArguments::chk_recursions(ReferenceChain& refch)
8832 {
8833 for (size_t i=0; i<logargs.size(); i++) {
8834 refch.mark_state();
8835 logargs[i]->chk_recursions(refch);
8836 refch.prev_state();
8837 }
8838 }
8839
8840 bool LogArguments::has_single_expr()
8841 {
8842 bool i_have_single_expr = true;
8843 for (size_t i=0; i<logargs.size(); i++)
8844 i_have_single_expr = i_have_single_expr && logargs[i]->has_single_expr();
8845 return i_have_single_expr;
8846 }
8847
8848 void LogArguments::generate_code_expr(expression_struct *expr)
8849 {
8850 expr->expr = mputstr(expr->expr, "(TTCN_Logger::begin_event_log2str(),");
8851 for(size_t i=0; i<logargs.size(); i++) {
8852 logargs[i]->generate_code_expr(expr);
8853 expr->expr = mputc(expr->expr, ','); // comma operator
8854 }
8855 expr->expr = mputstr(expr->expr, "TTCN_Logger::end_event_log2str())");
8856 }
8857
8858 // =================================
8859 // ===== IfClause
8860 // =================================
8861
8862 IfClause::IfClause(Value *p_expr, StatementBlock *p_block)
8863 : expr(p_expr), block(p_block)
8864 {
8865 if(!expr || !block)
8866 FATAL_ERROR("IfClause::IfClause()");
8867 }
8868
8869 IfClause::~IfClause()
8870 {
8871 delete expr;
8872 delete block;
8873 }
8874
8875 IfClause *IfClause::clone() const
8876 {
8877 FATAL_ERROR("IfClause::clone");
8878 }
8879
8880 void IfClause::set_my_scope(Scope *p_scope)
8881 {
8882 expr->set_my_scope(p_scope);
8883 block->set_my_scope(p_scope);
8884 }
8885
8886 void IfClause::set_fullname(const string& p_fullname)
8887 {
8888 Node::set_fullname(p_fullname);
8889 expr->set_fullname(p_fullname+".expr");
8890 block->set_fullname(p_fullname+".block");
8891 }
8892
8893 bool IfClause::has_receiving_stmt() const
8894 {
8895 return block->has_receiving_stmt();
8896 }
8897
8898 void IfClause::chk(bool& unreach)
8899 {
8900 Error_Context cntxt(this, "In if statement");
8901 if(unreach) warning("Control never reaches this code because of"
8902 " previous effective condition(s)");
8903 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
8904 if(!expr->is_unfoldable()) {
8905 if(expr->get_val_bool()) unreach=true;
8906 else block->warning("Control never reaches this code because the"
8907 " conditional expression evaluates to false");
8908 }
8909 block->chk();
8910 }
8911
8912 void IfClause::set_code_section(
8913 GovernedSimple::code_section_t p_code_section)
8914 {
8915 expr->set_code_section(p_code_section);
8916 block->set_code_section(p_code_section);
8917 }
8918
8919 char* IfClause::generate_code(char *str, size_t& blockcount,
8920 bool& unreach, bool& eachfalse)
8921 {
8922 if(unreach) return str;
8923 if(!expr->is_unfoldable()) {
8924 if(expr->get_val_bool()) unreach=true;
8925 else return str;
8926 }
8927 if (!eachfalse) str = mputstr(str, "else ");
8928 if (!unreach) {
8929 if (!eachfalse) {
8930 str = mputstr(str, "{\n");
8931 blockcount++;
8932 }
8933 str = expr->update_location_object(str);
8934 str = expr->generate_code_tmp(str, "if (", blockcount);
8935 str = mputstr(str, ") ");
8936 }
8937 eachfalse = false;
8938 str=mputstr(str, "{\n");
8939 str=block->generate_code(str);
8940 str=mputstr(str, "}\n");
8941 return str;
8942 }
8943
8944 void IfClause::ilt_generate_code(ILT *ilt, const char *end_label,
8945 bool& unreach)
8946 {
8947 if(unreach) return;
8948 if(!expr->is_unfoldable()) {
8949 if(expr->get_val_bool()) unreach=true;
8950 else return;
8951 }
8952 char*& str=ilt->get_out_branches();
8953 char *label=0;
8954 if(!unreach) {
8955 size_t blockcount=0;
8956 label=mprintf("%s_l%lu",
8957 ilt->get_my_tmpid().c_str(),
8958 (unsigned long) ilt->get_new_label_num());
8959 str=expr->update_location_object(str);
8960 str=expr->generate_code_tmp(str, "if(!", blockcount);
8961 str=mputprintf(str, ") goto %s;\n", label);
8962 while(blockcount-->0) str=mputstr(str, "}\n");
8963 }
8964 block->ilt_generate_code(ilt);
8965 if(!unreach) {
8966 str=mputprintf(str, "goto %s;\n%s:\n",
8967 end_label, label);
8968 Free(label);
8969 }
8970 }
8971
8972 void IfClause::set_parent_path(WithAttribPath* p_path) {
8973 block->set_parent_path(p_path);
8974 }
8975
8976 void IfClause::dump(unsigned int level) const {
8977 DEBUG(level, "If clause!");
8978 expr->dump(level + 1);
8979 block->dump(level + 1);
8980 }
8981
8982 // =================================
8983 // ===== IfClauses
8984 // =================================
8985
8986 IfClauses::~IfClauses()
8987 {
8988 for(size_t i=0; i<ics.size(); i++) delete ics[i];
8989 ics.clear();
8990 }
8991
8992 IfClauses *IfClauses::clone() const
8993 {
8994 FATAL_ERROR("IfClauses::clone");
8995 }
8996
8997 void IfClauses::add_ic(IfClause *p_ic)
8998 {
8999 if(!p_ic)
9000 FATAL_ERROR("IfClauses::add_ic()");
9001 ics.add(p_ic);
9002 }
9003
9004 void IfClauses::add_front_ic(IfClause *p_ic)
9005 {
9006 if(!p_ic)
9007 FATAL_ERROR("IfClauses::add_front_ic()");
9008 ics.add_front(p_ic);
9009 }
9010
9011 void IfClauses::set_my_scope(Scope *p_scope)
9012 {
9013 for(size_t i=0; i<ics.size(); i++)
9014 ics[i]->set_my_scope(p_scope);
9015 }
9016
9017 void IfClauses::set_fullname(const string& p_fullname)
9018 {
9019 Node::set_fullname(p_fullname);
9020 for(size_t i=0; i<ics.size(); i++)
9021 ics[i]->set_fullname(p_fullname+".ic_"+Int2string(i+1));
9022 }
9023
9024 void IfClauses::set_my_sb(StatementBlock *p_sb, size_t p_index)
9025 {
9026 for(size_t i=0; i<ics.size(); i++)
9027 ics[i]->get_block()->set_my_sb(p_sb, p_index);
9028 }
9029
9030 void IfClauses::set_my_def(Definition *p_def)
9031 {
9032 for(size_t i=0; i<ics.size(); i++)
9033 ics[i]->get_block()->set_my_def(p_def);
9034 }
9035
9036 void IfClauses::set_my_ags(AltGuards *p_ags)
9037 {
9038 for(size_t i=0; i<ics.size(); i++)
9039 ics[i]->get_block()->set_my_ags(p_ags);
9040 }
9041
9042 void IfClauses::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9043 {
9044 for(size_t i=0; i<ics.size(); i++)
9045 ics[i]->get_block()->set_my_laic_stmt(p_ags, p_loop_stmt);
9046 }
9047
9048 StatementBlock::returnstatus_t IfClauses::has_return
9049 (StatementBlock *elseblock) const
9050 {
9051 StatementBlock::returnstatus_t ret_val = StatementBlock::RS_MAYBE;
9052 for (size_t i = 0; i < ics.size(); i++) {
9053 switch (ics[i]->get_block()->has_return()) {
9054 case StatementBlock::RS_NO:
9055 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9056 else ret_val = StatementBlock::RS_NO;
9057 break;
9058 case StatementBlock::RS_YES:
9059 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9060 else ret_val = StatementBlock::RS_YES;
9061 break;
9062 default:
9063 return StatementBlock::RS_MAYBE;
9064 }
9065 }
9066 StatementBlock::returnstatus_t else_status;
9067 if (elseblock) else_status = elseblock->has_return();
9068 else else_status = StatementBlock::RS_NO;
9069 switch (else_status) {
9070 case StatementBlock::RS_NO:
9071 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9072 else ret_val = StatementBlock::RS_NO;
9073 break;
9074 case StatementBlock::RS_YES:
9075 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9076 else ret_val = StatementBlock::RS_YES;
9077 break;
9078 default:
9079 return StatementBlock::RS_MAYBE;
9080 }
9081 return ret_val;
9082 }
9083
9084 bool IfClauses::has_receiving_stmt() const
9085 {
9086 for(size_t i=0; i<ics.size(); i++)
9087 if(ics[i]->has_receiving_stmt()) return true;
9088 return false;
9089 }
9090
9091 void IfClauses::chk(bool& unreach)
9092 {
9093 for(size_t i=0; i<ics.size(); i++)
9094 ics[i]->chk(unreach);
9095 }
9096
9097 void IfClauses::chk_allowed_interleave()
9098 {
9099 for (size_t i = 0; i < ics.size(); i++)
9100 ics[i]->get_block()->chk_allowed_interleave();
9101 }
9102
9103 void IfClauses::set_code_section(
9104 GovernedSimple::code_section_t p_code_section)
9105 {
9106 for (size_t i = 0; i < ics.size(); i++)
9107 ics[i]->set_code_section(p_code_section);
9108 }
9109
9110 char* IfClauses::generate_code(char *str, size_t& blockcount,
9111 bool& unreach, bool& eachfalse)
9112 {
9113 for(size_t i=0; i<ics.size(); i++) {
9114 if(unreach) return str;
9115 str=ics[i]->generate_code(str, blockcount, unreach, eachfalse);
9116 }
9117 return str;
9118 }
9119
9120 void IfClauses::ilt_generate_code(ILT *ilt, const char *end_label,
9121 bool& unreach)
9122 {
9123 for(size_t i=0; i<ics.size(); i++) {
9124 if(unreach) return;
9125 ics[i]->ilt_generate_code(ilt, end_label, unreach);
9126 }
9127 }
9128
9129 void IfClauses::set_parent_path(WithAttribPath* p_path) {
9130 for (size_t i = 0; i < ics.size(); i++)
9131 ics[i]->set_parent_path(p_path);
9132 }
9133
9134 void IfClauses::dump(unsigned int level) const {
9135 DEBUG(level, "%lu if clauses", (unsigned long)ics.size());
9136 for (size_t i = 0; i < ics.size(); i++)
9137 ics[i]->dump(level + 1);
9138 }
9139
9140 // =================================
9141 // ===== SelectCase
9142 // =================================
9143
9144 SelectCase::SelectCase(TemplateInstances *p_tis, StatementBlock *p_block)
9145 : tis(p_tis), block(p_block)
9146 {
9147 if(!block)
9148 FATAL_ERROR("SelectCase::SelectCase()");
9149 }
9150
9151 SelectCase::~SelectCase()
9152 {
9153 delete tis;
9154 delete block;
9155 }
9156
9157 SelectCase *SelectCase::clone() const
9158 {
9159 FATAL_ERROR("SelectCase::clone");
9160 }
9161
9162 void SelectCase::set_my_scope(Scope *p_scope)
9163 {
9164 if(tis) tis->set_my_scope(p_scope);
9165 block->set_my_scope(p_scope);
9166 }
9167
9168 void SelectCase::set_fullname(const string& p_fullname)
9169 {
9170 Node::set_fullname(p_fullname);
9171 if(tis) tis->set_fullname(p_fullname+".tis");
9172 block->set_fullname(p_fullname+".block");
9173 }
9174
9175 /** \todo review */
9176 void SelectCase::chk(Type *p_gov, bool& unreach)
9177 {
9178 Error_Context cntxt(this, "In select case statement");
9179 if(unreach) warning("Control never reaches this code because of"
9180 " previous effective case(s)");
9181 if(tis)
9182 for(size_t i=0; i<tis->get_nof_tis(); i++)
9183 tis->get_ti_byIndex(i)->chk(p_gov);
9184 else unreach=true; // else statement
9185 block->chk();
9186 }
9187
9188 void SelectCase::set_code_section
9189 (GovernedSimple::code_section_t p_code_section)
9190 {
9191 if(tis) tis->set_code_section(p_code_section);
9192 block->set_code_section(p_code_section);
9193 }
9194
9195 /** \todo review */
9196 char* SelectCase::generate_code_if(char *str, const char *tmp_prefix,
9197 const char *expr_name, size_t idx,
9198 bool& unreach)
9199 {
9200 if(unreach) return str;
9201 if(tis) {
9202 for(size_t i=0; i<tis->get_nof_tis(); i++) {
9203 TemplateInstance *ti=tis->get_ti_byIndex(i);
9204 Template *tb=ti->get_Template();
9205 bool is_value = NULL == ti->get_DerivedRef() && tb->is_Value();
9206 expression_struct exprs;
9207 Code::init_expr(&exprs);
9208 if (is_value) {
9209 if (tb->get_templatetype() == Template::SPECIFIC_VALUE) {
9210 tb->get_specific_value()->generate_code_expr_mandatory(&exprs);
9211 }
9212 else {
9213 Value* val = tb->get_Value();
9214 if (NULL == val->get_my_governor()) {
9215 // the value's governor could not be determined, treat it as a non-value template
9216 is_value = false;
9217 }
9218 else {
9219 val->generate_code_expr_mandatory(&exprs);
9220 }
9221 delete val;
9222 }
9223 }
9224 if (!is_value) {
9225 ti->generate_code(&exprs);
9226 }
9227 str=tb->update_location_object(str);
9228 if(!exprs.preamble && !exprs.postamble) {
9229 str=mputstr(str, "if(");
9230 if(!is_value)
9231 str=mputprintf(str, "%s.match(%s%s)", exprs.expr, expr_name,
9232 omit_in_value_list ? ", TRUE" : "");
9233 else str=mputprintf(str, "%s == %s", expr_name, exprs.expr);
9234 str=mputprintf(str, ") goto %s_%lu;\n", tmp_prefix,
9235 (unsigned long) idx);
9236 Code::free_expr(&exprs);
9237 }
9238 else {
9239 str=mputprintf(str, "{\nboolean %s_%lub;\n", tmp_prefix,
9240 (unsigned long) idx);
9241 char *s=exprs.expr;
9242 exprs.expr=mprintf("%s_%lub = ", tmp_prefix, (unsigned long) idx);
9243 if(!is_value)
9244 exprs.expr=mputprintf(exprs.expr, "%s.match(%s%s)", s, expr_name,
9245 omit_in_value_list ? ", TRUE" : "");
9246 else exprs.expr=mputprintf(exprs.expr, "(%s == %s)", expr_name, s);
9247 Free(s);
9248 str=Code::merge_free_expr(str, &exprs);
9249 str=mputprintf(str, "if(%s_%lub) goto %s_%lu;\n}\n",
9250 tmp_prefix, (unsigned long) idx, tmp_prefix, (unsigned long) idx);
9251 }
9252 } // for i
9253 } // if tis
9254 else {
9255 unreach=true; // else statement
9256 str=mputprintf(str, "goto %s_%lu;\n", tmp_prefix, (unsigned long) idx);
9257 }
9258 return str;
9259 }
9260
9261 /** \todo review */
9262 char* SelectCase::generate_code_stmt(char *str, const char *tmp_prefix,
9263 size_t idx, bool& unreach)
9264 {
9265 if(unreach) return str;
9266 if(!tis) unreach=true;
9267 str=mputprintf(str, "%s_%lu:\n{\n", tmp_prefix, (unsigned long) idx);
9268 str=block->generate_code(str);
9269 str=mputprintf(str, "goto %s_end;\n}\n", tmp_prefix);
9270 return str;
9271 }
9272
9273 void SelectCase::ilt_generate_code_stmt(ILT *ilt, const char *tmp_prefix,
9274 size_t idx, bool& unreach)
9275 {
9276 if(unreach) return;
9277 if(!tis) unreach=true;
9278 char*& str=ilt->get_out_branches();
9279 str=mputprintf(str, "%s_%lu:\n", tmp_prefix, (unsigned long) idx);
9280 bool has_recv=block->has_receiving_stmt();
9281 if(!has_recv) {
9282 str=mputstr(str, "{\n");
9283 str=block->generate_code(str);
9284 }
9285 else block->ilt_generate_code(ilt);
9286 str=mputprintf(str, "goto %s_end;\n", tmp_prefix);
9287 if(!has_recv)
9288 str=mputstr(str, "}\n");
9289 }
9290
9291 void SelectCase::set_parent_path(WithAttribPath* p_path) {
9292 block->set_parent_path(p_path);
9293 }
9294
9295 // =================================
9296 // ===== SelectCases
9297 // =================================
9298
9299 SelectCases::~SelectCases()
9300 {
9301 for(size_t i=0; i<scs.size(); i++) delete scs[i];
9302 scs.clear();
9303 }
9304
9305 SelectCases *SelectCases::clone() const
9306 {
9307 FATAL_ERROR("SelectCases::clone");
9308 }
9309
9310 void SelectCases::add_sc(SelectCase *p_sc)
9311 {
9312 if(!p_sc)
9313 FATAL_ERROR("SelectCases::add_sc()");
9314 scs.add(p_sc);
9315 }
9316
9317 void SelectCases::set_my_scope(Scope *p_scope)
9318 {
9319 for(size_t i=0; i<scs.size(); i++)
9320 scs[i]->set_my_scope(p_scope);
9321 }
9322
9323 void SelectCases::set_fullname(const string& p_fullname)
9324 {
9325 Node::set_fullname(p_fullname);
9326 for(size_t i=0; i<scs.size(); i++)
9327 scs[i]->set_fullname(p_fullname+".sc_"+Int2string(i+1));
9328 }
9329
9330 void SelectCases::set_my_sb(StatementBlock *p_sb, size_t p_index)
9331 {
9332 for(size_t i=0; i<scs.size(); i++)
9333 scs[i]->get_block()->set_my_sb(p_sb, p_index);
9334 }
9335
9336 void SelectCases::set_my_def(Definition *p_def)
9337 {
9338 for(size_t i=0; i<scs.size(); i++)
9339 scs[i]->get_block()->set_my_def(p_def);
9340 }
9341
9342 void SelectCases::set_my_ags(AltGuards *p_ags)
9343 {
9344 for(size_t i=0; i<scs.size(); i++)
9345 scs[i]->get_block()->set_my_ags(p_ags);
9346 }
9347
9348 void SelectCases::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9349 {
9350 for(size_t i=0; i<scs.size(); i++)
9351 scs[i]->get_block()->set_my_laic_stmt(p_ags, p_loop_stmt);
9352 }
9353
9354 StatementBlock::returnstatus_t SelectCases::has_return() const
9355 {
9356 StatementBlock::returnstatus_t ret_val = StatementBlock::RS_MAYBE;
9357 bool has_else = false;
9358 for (size_t i = 0; i < scs.size(); i++) {
9359 SelectCase *sc = scs[i];
9360 switch (sc->get_block()->has_return()) {
9361 case StatementBlock::RS_NO:
9362 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9363 else ret_val = StatementBlock::RS_NO;
9364 break;
9365 case StatementBlock::RS_YES:
9366 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9367 else ret_val = StatementBlock::RS_YES;
9368 break;
9369 default:
9370 return StatementBlock::RS_MAYBE;
9371 }
9372 if (!sc->get_tis()) {
9373 has_else = true;
9374 break;
9375 }
9376 }
9377 if (!has_else && ret_val == StatementBlock::RS_YES)
9378 return StatementBlock::RS_MAYBE;
9379 else return ret_val;
9380 }
9381
9382 bool SelectCases::has_receiving_stmt() const
9383 {
9384 for(size_t i=0; i<scs.size(); i++)
9385 if(scs[i]->get_block()->has_receiving_stmt()) return true;
9386 return false;
9387 }
9388
9389 /** \todo review */
9390 void SelectCases::chk(Type *p_gov)
9391 {
9392 bool unreach=false;
9393 for(size_t i=0; i<scs.size(); i++)
9394 scs[i]->chk(p_gov, unreach);
9395 }
9396
9397 void SelectCases::chk_allowed_interleave()
9398 {
9399 for (size_t i = 0; i < scs.size(); i++)
9400 scs[i]->get_block()->chk_allowed_interleave();
9401 }
9402
9403 void SelectCases::set_code_section
9404 (GovernedSimple::code_section_t p_code_section)
9405 {
9406 for(size_t i=0; i<scs.size(); i++)
9407 scs[i]->set_code_section(p_code_section);
9408 }
9409
9410 char* SelectCases::generate_code(char *str, const char *tmp_prefix,
9411 const char *expr_name)
9412 {
9413 bool unreach=false;
9414 for(size_t i=0; i<scs.size(); i++) {
9415 str=scs[i]->generate_code_if(str, tmp_prefix, expr_name, i, unreach);
9416 if(unreach) break;
9417 }
9418 if(!unreach) str=mputprintf(str, "goto %s_end;\n", tmp_prefix);
9419 unreach=false;
9420 for(size_t i=0; i<scs.size(); i++) {
9421 str=scs[i]->generate_code_stmt(str, tmp_prefix, i, unreach);
9422 if(unreach) break;
9423 }
9424 str=mputprintf(str, "%s_end: /* empty */;\n", tmp_prefix);
9425 return str;
9426 }
9427
9428 void SelectCases::ilt_generate_code(ILT *ilt, const char *tmp_prefix,
9429 const char *expr_init,
9430 const char *expr_name)
9431 {
9432 char*& str=ilt->get_out_branches();
9433 if(strlen(expr_init)) {
9434 str=mputstr(str, "{\n"); // (1)
9435 str=mputstr(str, expr_init);
9436 }
9437 bool unreach=false;
9438 for(size_t i=0; i<scs.size(); i++) {
9439 if(unreach) break;
9440 str=scs[i]->generate_code_if(str, tmp_prefix, expr_name, i, unreach);
9441 }
9442 if(!unreach) str=mputprintf(str, "goto %s_end;\n", tmp_prefix);
9443 if(strlen(expr_init)) str=mputstr(str, "}\n"); // (1)
9444 unreach=false;
9445 for(size_t i=0; i<scs.size(); i++) {
9446 if(unreach) break;
9447 scs[i]->ilt_generate_code_stmt(ilt, tmp_prefix, i, unreach);
9448 }
9449 str=mputprintf(str, "%s_end:\n", tmp_prefix);
9450 }
9451
9452 void SelectCases::set_parent_path(WithAttribPath* p_path) {
9453 for (size_t i = 0; i < scs.size(); i++)
9454 scs[i]->set_parent_path(p_path);
9455 }
9456
9457 // =================================
9458 // ===== AltGuard
9459 // =================================
9460
9461 AltGuard::AltGuard(Value *p_expr, Statement *p_stmt, StatementBlock *p_block)
9462 : altguardtype(AG_OP), expr(p_expr), stmt(p_stmt), block(p_block)
9463 {
9464 if (!p_stmt || !p_block) FATAL_ERROR("AltGuard::AltGuard()");
9465 }
9466
9467 AltGuard::AltGuard(Value *p_expr, Ref_pard *p_ref, StatementBlock *p_block)
9468 : altguardtype(AG_REF), expr(p_expr), ref(p_ref), block(p_block)
9469 {
9470 if (!p_ref) FATAL_ERROR("AltGuard::AltGuard()");
9471 }
9472
9473 AltGuard::AltGuard(Value *p_expr, Value *p_v,
9474 Ttcn::TemplateInstances *p_t_list, StatementBlock *p_block)
9475 : altguardtype(AG_INVOKE), expr(p_expr)
9476 , block(p_block)
9477 {
9478 if(!p_v || !p_t_list) FATAL_ERROR("AltGuard::AltGuard()");
9479 invoke.v = p_v;
9480 invoke.t_list = p_t_list;
9481 invoke.ap_list = 0;
9482 }
9483
9484 AltGuard::AltGuard(StatementBlock *p_block)
9485 : altguardtype(AG_ELSE), expr(0), dummy(0), block(p_block)
9486 {
9487 if (!p_block) FATAL_ERROR("AltGuard::AltGuard()");
9488 }
9489
9490 AltGuard::~AltGuard()
9491 {
9492 switch(altguardtype) {
9493 case AG_OP:
9494 delete expr;
9495 delete stmt;
9496 delete block;
9497 break;
9498 case AG_REF:
9499 delete expr;
9500 delete ref;
9501 delete block;
9502 break;
9503 case AG_INVOKE:
9504 delete expr;
9505 delete invoke.v;
9506 delete invoke.t_list;
9507 delete invoke.ap_list;
9508 delete block;
9509 break;
9510 case AG_ELSE:
9511 delete block;
9512 break;
9513 default:
9514 FATAL_ERROR("AltGuard::~AltGuard()");
9515 } // switch
9516 }
9517
9518 AltGuard *AltGuard::clone() const
9519 {
9520 FATAL_ERROR("AltGuard::clone");
9521 }
9522
9523 void AltGuard::set_my_scope(Scope *p_scope)
9524 {
9525 switch(altguardtype) {
9526 case AG_OP:
9527 if(expr) expr->set_my_scope(p_scope);
9528 stmt->set_my_scope(p_scope);
9529 block->set_my_scope(p_scope);
9530 break;
9531 case AG_REF:
9532 if(expr) expr->set_my_scope(p_scope);
9533 ref->set_my_scope(p_scope);
9534 if(block) block->set_my_scope(p_scope);
9535 break;
9536 case AG_INVOKE:
9537 if(expr) expr->set_my_scope(p_scope);
9538 invoke.v->set_my_scope(p_scope);
9539 if(invoke.t_list) invoke.t_list->set_my_scope(p_scope);
9540 if(invoke.ap_list) invoke.ap_list->set_my_scope(p_scope);
9541 if(block) block->set_my_scope(p_scope);
9542 break;
9543 case AG_ELSE:
9544 block->set_my_scope(p_scope);
9545 break;
9546 default:
9547 FATAL_ERROR("AltGuard::set_my_scope()");
9548 } // switch
9549 }
9550
9551 void AltGuard::set_my_sb(StatementBlock *p_sb, size_t p_index)
9552 {
9553 switch(altguardtype) {
9554 case AG_OP:
9555 stmt->set_my_sb(p_sb, p_index);
9556 block->set_my_sb(p_sb, p_index);
9557 break;
9558 case AG_REF:
9559 if(block) block->set_my_sb(p_sb, p_index);
9560 break;
9561 case AG_INVOKE:
9562 if(block) block->set_my_sb(p_sb, p_index);
9563 break;
9564 case AG_ELSE:
9565 block->set_my_sb(p_sb, p_index);
9566 break;
9567 default:
9568 FATAL_ERROR("AltGuard::set_my_sb()");
9569 } // switch
9570 }
9571
9572 void AltGuard::set_fullname(const string& p_fullname)
9573 {
9574 Node::set_fullname(p_fullname);
9575 switch(altguardtype) {
9576 case AG_OP:
9577 if(expr) expr->set_fullname(p_fullname+".expr");
9578 stmt->set_fullname(p_fullname+".stmt");
9579 block->set_fullname(p_fullname+".block");
9580 break;
9581 case AG_REF:
9582 if(expr) expr->set_fullname(p_fullname+".expr");
9583 ref->set_fullname(p_fullname+".ref");
9584 if(block) block->set_fullname(p_fullname+".block");
9585 break;
9586 case AG_INVOKE:
9587 if(expr) expr->set_fullname(p_fullname+".expr");
9588 invoke.v->set_fullname(p_fullname+".function");
9589 if(invoke.t_list) invoke.t_list->set_fullname(p_fullname+".argument");
9590 if(invoke.ap_list) invoke.ap_list->set_fullname(p_fullname+".argument");
9591 if(block) block->set_fullname(p_fullname+".block");
9592 break;
9593 case AG_ELSE:
9594 block->set_fullname(p_fullname+".elseblock");
9595 break;
9596 default:
9597 FATAL_ERROR("AltGuard::set_fullname()");
9598 } // switch
9599 }
9600
9601 Value *AltGuard::get_guard_expr() const
9602 {
9603 if (altguardtype == AG_ELSE) FATAL_ERROR("AltGuard::get_guard_expr()");
9604 return expr;
9605 }
9606
9607 Ref_pard *AltGuard::get_guard_ref() const
9608 {
9609 if (altguardtype != AG_REF) FATAL_ERROR("AltGuard::get_guard_ref()");
9610 return ref;
9611 }
9612
9613 Statement *AltGuard::get_guard_stmt() const
9614 {
9615 if (altguardtype != AG_OP) FATAL_ERROR("AltGuard::get_guard_stmt()");
9616 return stmt;
9617 }
9618
9619 void AltGuard::set_my_def(Definition *p_def)
9620 {
9621 switch(altguardtype) {
9622 case AG_OP:
9623 stmt->set_my_def(p_def);
9624 block->set_my_def(p_def);
9625 break;
9626 case AG_REF:
9627 if(block) block->set_my_def(p_def);
9628 break;
9629 case AG_INVOKE:
9630 if(block) block->set_my_def(p_def);
9631 break;
9632 case AG_ELSE:
9633 block->set_my_def(p_def);
9634 break;
9635 default:
9636 FATAL_ERROR("AltGuard::set_my_def()");
9637 } // switch
9638 }
9639
9640 void AltGuard::set_my_ags(AltGuards *p_ags)
9641 {
9642 switch (altguardtype) {
9643 case AG_OP:
9644 block->set_my_ags(p_ags);
9645 break;
9646 case AG_REF:
9647 if (block) block->set_my_ags(p_ags);
9648 break;
9649 case AG_INVOKE:
9650 if (block) block->set_my_ags(p_ags);
9651 break;
9652 case AG_ELSE:
9653 block->set_my_ags(p_ags);
9654 break;
9655 default:
9656 FATAL_ERROR("AltGuard::set_my_ags()");
9657 } // switch
9658 }
9659
9660 void AltGuard::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9661 {
9662 switch (altguardtype) {
9663 case AG_OP:
9664 block->set_my_laic_stmt(p_ags, p_loop_stmt);
9665 break;
9666 case AG_REF:
9667 if (block) block->set_my_laic_stmt(p_ags, p_loop_stmt);
9668 break;
9669 case AG_INVOKE:
9670 if (block) block->set_my_laic_stmt(p_ags, p_loop_stmt);
9671 break;
9672 case AG_ELSE:
9673 block->set_my_laic_stmt(p_ags, p_loop_stmt);
9674 break;
9675 default:
9676 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9677 } // switch
9678 }
9679
9680 void AltGuard::chk()
9681 {
9682 switch(altguardtype) {
9683 case AG_OP:
9684 if (expr) {
9685 Error_Context cntxt(expr, "In guard expression");
9686 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
9687 }
9688 {
9689 Error_Context cntxt(stmt, "In guard operation");
9690 stmt->chk();
9691 }
9692 block->chk();
9693 break;
9694 case AG_REF:
9695 if (expr) {
9696 Error_Context cntxt(expr, "In guard expression");
9697 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
9698 }
9699 {
9700 Error_Context cntxt(ref, "In guard statement");
9701 Common::Assignment *t_ass = ref->get_refd_assignment();
9702 if (t_ass) {
9703 if (t_ass->get_asstype() == Common::Assignment::A_ALTSTEP) {
9704 ref->get_my_scope()->chk_runs_on_clause(t_ass, *ref, "call");
9705 } else {
9706 ref->error("Reference to an altstep was expected instead of %s",
9707 t_ass->get_description().c_str());
9708 }
9709 }
9710 }
9711 if (block) block->chk();
9712 break;
9713 case AG_INVOKE:
9714 if (expr) {
9715 Error_Context cntxt(expr, "In guard expression");
9716 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
9717 }
9718 {
9719 if (!invoke.t_list) return; //already_checked
9720 Error_Context cntxt(ref, "In guard statement");
9721 switch(invoke.v->get_valuetype()){
9722 case Value::V_REFER:
9723 invoke.v->error(
9724 "A value of an altstep type was expected "
9725 "in the argument instead of a `refers' statement,"
9726 " which does not specify any function type");
9727 return;
9728 case Value::V_TTCN3_NULL:
9729 invoke.v->error(
9730 "A value of an altstep type was expected "
9731 "in the argument instead of a `null' value,"
9732 " which does not specify any function type");
9733 return;
9734 default:
9735 break;
9736 }
9737 Type *t = invoke.v->get_expr_governor_last();
9738 if (!t) return;
9739 switch (t->get_typetype()) {
9740 case Type::T_ERROR:
9741 return;
9742 case Type::T_ALTSTEP:
9743 break;
9744 default:
9745 invoke.v->error("A value of type altstep was expected instead of "
9746 "`%s'", t->get_typename().c_str());
9747 return;
9748 }
9749 invoke.v->get_my_scope()->chk_runs_on_clause(t, *this, "call");
9750 Ttcn::FormalParList *fp_list = t->get_fat_parameters();
9751 invoke.ap_list = new Ttcn::ActualParList;
9752 bool is_erroneous = fp_list->chk_actual_parlist(invoke.t_list,
9753 invoke.ap_list);
9754 delete invoke.t_list;
9755 invoke.t_list = 0;
9756 if(is_erroneous) {
9757 delete invoke.ap_list;
9758 invoke.ap_list = 0;
9759 } else {
9760 invoke.ap_list->set_fullname(get_fullname());
9761 invoke.ap_list->set_my_scope(invoke.v->get_my_scope());
9762 }
9763 }
9764 if (block) block->chk();
9765 break;
9766 case AG_ELSE:
9767 {
9768 Error_Context cntxt(this, "In else branch");
9769 block->chk();
9770 Statement *first_stmt = block->get_first_stmt();
9771 if (first_stmt && first_stmt->get_statementtype() ==
9772 Statement::S_REPEAT)
9773 first_stmt->warning("The first statement of the [else] branch is a "
9774 "repeat statement. This will result in busy waiting");
9775 }
9776 break;
9777 default:
9778 FATAL_ERROR("AltGuard::chk()");
9779 } // switch
9780 }
9781
9782 void AltGuard::set_code_section(
9783 GovernedSimple::code_section_t p_code_section)
9784 {
9785 switch(altguardtype) {
9786 case AG_OP:
9787 if (expr) expr->set_code_section(p_code_section);
9788 stmt->set_code_section(p_code_section);
9789 block->set_code_section(p_code_section);
9790 break;
9791 case AG_REF:
9792 if (expr) expr->set_code_section(p_code_section);
9793 ref->set_code_section(p_code_section);
9794 if (block) block->set_code_section(p_code_section);
9795 break;
9796 case AG_INVOKE:
9797 if (expr) expr->set_code_section(p_code_section);
9798 invoke.v->set_code_section(p_code_section);
9799 if(invoke.t_list) invoke.t_list->set_code_section(p_code_section);
9800 if(invoke.ap_list)
9801 for(size_t i = 0; i < invoke.ap_list->get_nof_pars(); i++)
9802 invoke.ap_list->get_par(i)->set_code_section(p_code_section);
9803 if (block) block->set_code_section(p_code_section);
9804 break;
9805 case AG_ELSE:
9806 block->set_code_section(p_code_section);
9807 break;
9808 default:
9809 FATAL_ERROR("AltGuard::set_fullname()");
9810 } // switch
9811 }
9812
9813 void AltGuard::generate_code_invoke_instance(expression_struct *p_expr)
9814 {
9815 if (altguardtype != AG_INVOKE)
9816 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9817 Value *last_v = invoke.v->get_value_refd_last();
9818 if (last_v->get_valuetype() == Value::V_ALTSTEP) {
9819 Common::Assignment *altstep = last_v->get_refd_fat();
9820 p_expr->expr = mputprintf(p_expr->expr, "%s_instance(",
9821 altstep->get_genname_from_scope(invoke.v->get_my_scope()).c_str());
9822 invoke.ap_list->generate_code_alias(p_expr,
9823 altstep->get_FormalParList(), altstep->get_RunsOnType(), false);
9824 } else {
9825 invoke.v->generate_code_expr_mandatory(p_expr);
9826 p_expr->expr = mputstr(p_expr->expr, ".invoke(");
9827 Type* gov_last = invoke.v->get_expr_governor_last();
9828 invoke.ap_list->generate_code_alias(p_expr, 0,
9829 gov_last->get_fat_runs_on_type(), gov_last->get_fat_runs_on_self());
9830 }
9831 p_expr->expr = mputc(p_expr->expr, ')');
9832 }
9833
9834 // =================================
9835 // ===== AltGuards
9836 // =================================
9837
9838 AltGuards::~AltGuards()
9839 {
9840 for(size_t i=0; i<ags.size(); i++) delete ags[i];
9841 ags.clear();
9842 delete label;
9843 delete il_label_end;
9844 }
9845
9846 AltGuards *AltGuards::clone() const
9847 {
9848 FATAL_ERROR("AltGuards::clone");
9849 }
9850
9851 void AltGuards::add_ag(AltGuard *p_ag)
9852 {
9853 if(!p_ag)
9854 FATAL_ERROR("AltGuards::add_ag()");
9855 ags.add(p_ag);
9856 }
9857
9858 void AltGuards::set_my_scope(Scope *p_scope)
9859 {
9860 my_scope = p_scope;
9861 for(size_t i=0; i<ags.size(); i++)
9862 ags[i]->set_my_scope(p_scope);
9863 }
9864
9865 void AltGuards::set_fullname(const string& p_fullname)
9866 {
9867 Node::set_fullname(p_fullname);
9868 for(size_t i=0; i<ags.size(); i++)
9869 ags[i]->set_fullname(p_fullname+".ag_"+Int2string(i+1));
9870 }
9871
9872 void AltGuards::set_my_sb(StatementBlock *p_sb, size_t p_index)
9873 {
9874 for(size_t i=0; i<ags.size(); i++)
9875 ags[i]->set_my_sb(p_sb, p_index);
9876 }
9877
9878 void AltGuards::set_my_def(Definition *p_def)
9879 {
9880 for(size_t i=0; i<ags.size(); i++)
9881 ags[i]->set_my_def(p_def);
9882 }
9883
9884 void AltGuards::set_my_ags(AltGuards *p_ags)
9885 {
9886 for(size_t i=0; i<ags.size(); i++)
9887 ags[i]->set_my_ags(p_ags);
9888 }
9889
9890 void AltGuards::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9891 {
9892 for(size_t i=0; i<ags.size(); i++)
9893 ags[i]->set_my_laic_stmt(p_ags, p_loop_stmt);
9894 }
9895
9896 bool AltGuards::has_else() const
9897 {
9898 for (size_t i = 0; i < ags.size(); i++)
9899 if (ags[i]->get_type() == AltGuard::AG_ELSE) return true;
9900 return false;
9901 }
9902
9903 StatementBlock::returnstatus_t AltGuards::has_return() const
9904 {
9905 StatementBlock::returnstatus_t ret_val = StatementBlock::RS_MAYBE;
9906 for (size_t i = 0; i < ags.size(); i++) {
9907 AltGuard *ag = ags[i];
9908 StatementBlock *block = ag->get_block();
9909 StatementBlock::returnstatus_t block_status;
9910 if (block) block_status = block->has_return();
9911 else block_status = StatementBlock::RS_NO;
9912 switch (block_status) {
9913 case StatementBlock::RS_NO:
9914 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9915 else ret_val = StatementBlock::RS_NO;
9916 break;
9917 case StatementBlock::RS_YES:
9918 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9919 else ret_val = StatementBlock::RS_YES;
9920 break;
9921 default:
9922 return StatementBlock::RS_MAYBE;
9923 }
9924 if (ag->get_type() == AltGuard::AG_ELSE) break;
9925 }
9926 return ret_val;
9927 }
9928
9929 bool AltGuards::has_receiving_stmt() const
9930 {
9931 for(size_t i=0; i<ags.size(); i++)
9932 if(ags[i]->get_block()->has_receiving_stmt()) return true;
9933 return false;
9934 }
9935
9936 void AltGuards::chk()
9937 {
9938 bool unreach_found = false;
9939 size_t nof_ags = ags.size();
9940 AltGuard *prev_ag = 0;
9941 for (size_t i = 0; i < nof_ags; i++) {
9942 AltGuard *ag = ags[i];
9943 ag->chk();
9944 if (!unreach_found && prev_ag &&
9945 prev_ag->get_type() == AltGuard::AG_ELSE) {
9946 ag->warning("Control never reaches this branch of alternative "
9947 "because of the previous [else] branch");
9948 unreach_found = true;
9949 }
9950 prev_ag = ag;
9951 }
9952 }
9953
9954 void AltGuards::chk_allowed_interleave()
9955 {
9956 for (size_t i = 0; i < ags.size(); i++) {
9957 AltGuard *ag = ags[i];
9958 switch (ag->get_type()) {
9959 case AltGuard::AG_OP:
9960 break;
9961 case AltGuard::AG_REF:
9962 case AltGuard::AG_INVOKE:
9963 ag->error("Invocation of an altstep is not allowed within an "
9964 "interleave statement");
9965 break;
9966 case AltGuard::AG_ELSE:
9967 ag->error("Else branch of an alternative is not allowed within an "
9968 "interleave statement");
9969 break;
9970 default:
9971 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
9972 }
9973 ag->get_block()->chk_allowed_interleave();
9974 }
9975 }
9976
9977 void AltGuards::set_code_section(
9978 GovernedSimple::code_section_t p_code_section)
9979 {
9980 for (size_t i = 0; i < ags.size(); i++)
9981 ags[i]->set_code_section(p_code_section);
9982 }
9983
9984 char *AltGuards::generate_code_alt(char *str, const Location& loc)
9985 {
9986 bool label_needed = has_repeat, has_else_branch = false;
9987 for (size_t i = 0; i < ags.size(); i++) {
9988 AltGuard *ag = ags[i];
9989 switch (ag->get_type()) {
9990 case AltGuard::AG_OP:
9991 // trigger may return ALT_REPEAT
9992 if (ag->get_guard_stmt()->can_repeat()) label_needed = true;
9993 break;
9994 case AltGuard::AG_REF:
9995 case AltGuard::AG_INVOKE:
9996 // an altstep may return ALT_REPEAT
9997 label_needed = true;
9998 break;
9999 case AltGuard::AG_ELSE:
10000 has_else_branch = true;
10001 break;
10002 default:
10003 FATAL_ERROR("AltGuards::generate_code_alt()");
10004 }
10005 if (has_else_branch) break;
10006 }
10007 // if there is no [else] branch the defaults may return ALT_REPEAT
10008 if (!has_else_branch) label_needed = true;
10009 // opening bracket of the statement block
10010 str = mputstr(str, "{\n");
10011 // the label name is also used for prefixing local variables
10012 if (!my_scope || label) FATAL_ERROR("AltGuards::generate_code_alt()");
10013 label = new string(my_scope->get_scope_mod_gen()->get_temporary_id());
10014 const char *label_str = label->c_str();
10015 if (label_needed) str = mputprintf(str, "%s:\n", label_str);
10016 // temporary variables used for caching of status codes
10017 for (size_t i = 0; i < ags.size(); i++) {
10018 AltGuard *ag = ags[i];
10019 if (ag->get_type() == AltGuard::AG_ELSE) break;
10020 str = mputprintf(str, "alt_status %s_alt_flag_%lu = %s;\n",
10021 label_str, (unsigned long) i,
10022 ag->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
10023 }
10024 if (!has_else_branch) {
10025 str = mputprintf(str, "alt_status %s_default_flag = ALT_MAYBE;\n",
10026 label_str);
10027 }
10028 // the first snapshot is taken in non-blocking mode
10029 // and opening infinite for() loop
10030 str = mputstr(str, "TTCN_Snapshot::take_new(FALSE);\n"
10031 "for ( ; ; ) {\n");
10032 for (size_t i = 0; i < ags.size(); i++) {
10033 AltGuard *ag = ags[i];
10034 AltGuard::altguardtype_t agtype = ag->get_type();
10035 if (agtype == AltGuard::AG_ELSE) {
10036 // an else branch was found
10037 str = mputstr(str, "TTCN_Snapshot::else_branch_reached();\n");
10038 StatementBlock *block = ag->get_block();
10039 if (block->get_nof_stmts() > 0) {
10040 str = mputstr(str, "{\n");
10041 str = block->generate_code(str);
10042 str = mputstr(str, "}\n");
10043 }
10044 // jump out of the infinite for() loop
10045 if (block->has_return() != StatementBlock::RS_YES)
10046 str = mputstr(str, "break;\n");
10047 // do not generate code for further branches
10048 break;
10049 } else {
10050 Value *guard_expr = ag->get_guard_expr();
10051 if (guard_expr) {
10052 // the branch has a boolean guard expression
10053 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
10054 label_str, (unsigned long) i);
10055 str = guard_expr->update_location_object(str);
10056 expression_struct expr;
10057 Code::init_expr(&expr);
10058 guard_expr->generate_code_expr(&expr);
10059 str = mputstr(str, expr.preamble);
10060 str = mputprintf(str, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10061 "else %s_alt_flag_%lu = ALT_NO;\n", expr.expr, label_str,
10062 (unsigned long) i, label_str, (unsigned long) i);
10063 str = mputstr(str, expr.postamble);
10064 Code::free_expr(&expr);
10065 str = mputstr(str, "}\n");
10066 }
10067 // evaluation of guard operation or altstep
10068 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
10069 label_str, (unsigned long) i);
10070 // indicates whether the guard operation might return ALT_REPEAT
10071 bool can_repeat;
10072 expression_struct expr;
10073 Code::init_expr(&expr);
10074 expr.expr = mputprintf(expr.expr, "%s_alt_flag_%lu = ", label_str,
10075 (unsigned long) i);
10076 switch (agtype) {
10077 case AltGuard::AG_OP: {
10078 // the guard operation is a receiving statement
10079 Statement *stmt = ag->get_guard_stmt();
10080 str = stmt->update_location_object(str);
10081 stmt->generate_code_expr(&expr);
10082 can_repeat = stmt->can_repeat();
10083 break; }
10084 case AltGuard::AG_REF: {
10085 // the guard operation is an altstep instance
10086 Ref_pard *ref = ag->get_guard_ref();
10087 str = ref->update_location_object(str);
10088 Common::Assignment *altstep = ref->get_refd_assignment();
10089 expr.expr = mputprintf(expr.expr, "%s_instance(",
10090 altstep->get_genname_from_scope(my_scope).c_str());
10091 ref->get_parlist()->generate_code_alias(&expr,
10092 altstep->get_FormalParList(), altstep->get_RunsOnType(), false);
10093 expr.expr = mputc(expr.expr, ')');
10094 can_repeat = true;
10095 break; }
10096 case AltGuard::AG_INVOKE: {
10097 // the guard operation is an altstep invocation
10098 str = ag->update_location_object(str);
10099 ag->generate_code_invoke_instance(&expr);
10100 can_repeat = true;
10101 break; }
10102 default:
10103 FATAL_ERROR("AltGuards::generate_code_alt()");
10104 }
10105 str = Code::merge_free_expr(str, &expr);
10106 if (can_repeat) {
10107 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
10108 label_str, (unsigned long) i, label_str);
10109 }
10110 if (agtype == AltGuard::AG_REF || agtype == AltGuard::AG_INVOKE) {
10111 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
10112 label_str, (unsigned long) i);
10113 }
10114 // execution of statement block if the guard was successful
10115 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_YES) ", label_str,
10116 (unsigned long) i);
10117 StatementBlock *block = ag->get_block();
10118 if (block && block->get_nof_stmts() > 0) {
10119 str = mputstr(str, "{\n");
10120 str = block->generate_code(str);
10121 if (block->has_return() != StatementBlock::RS_YES)
10122 str = mputstr(str, "break;\n");
10123 str = mputstr(str, "}\n");
10124 } else str = mputstr(str, "break;\n");
10125 // closing of if() block
10126 str = mputstr(str, "}\n");
10127 }
10128 }
10129 if (!has_else_branch) {
10130 // calling of defaults
10131 str = mputprintf(str, "if (%s_default_flag == ALT_MAYBE) {\n"
10132 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10133 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10134 " break;\n"
10135 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10136 "}\n",
10137 label_str, label_str, label_str, label_str, label_str, label_str);
10138 str = loc.update_location_object(str);
10139 // error handling and taking the next snapshot in blocking mode
10140 str = mputstr(str, "if (");
10141 for (size_t i = 0; i < ags.size(); i++)
10142 str = mputprintf(str, "%s_alt_flag_%lu == ALT_NO && ", label_str,
10143 (unsigned long) i);
10144 str = mputprintf(str,"%s_default_flag == ALT_NO) "
10145 "TTCN_error(\"None of the branches can be chosen in the alt "
10146 "statement in file ", label_str);
10147 str = Code::translate_string(str, loc.get_filename());
10148 int first_line = loc.get_first_line(), last_line = loc.get_last_line();
10149 if (first_line < last_line) str = mputprintf(str,
10150 " between lines %d and %d", first_line, last_line);
10151 else str = mputprintf(str, ", line %d", first_line);
10152 str = mputstr(str, ".\");\n"
10153 "TTCN_Snapshot::take_new(TRUE);\n");
10154 }
10155 // end of for() statement and the statement block
10156 str = mputstr(str, "}\n"
10157 "}\n");
10158 return str;
10159 }
10160
10161 char *AltGuards::generate_code_altstep(char *str)
10162 {
10163 if (!my_scope) FATAL_ERROR("AltGuards::generate_code_altstep()");
10164 Common::Module *my_mod = my_scope->get_scope_mod_gen();
10165 bool has_else_branch = has_else();
10166 if (!has_else_branch) {
10167 str = mputstr(str, "alt_status ret_val = ALT_NO;\n");
10168 }
10169 for (size_t i = 0; i < ags.size(); i++) {
10170 AltGuard *ag = ags[i];
10171 AltGuard::altguardtype_t agtype = ag->get_type();
10172 if (agtype == AltGuard::AG_ELSE) {
10173 // an else branch was found
10174 str = mputstr(str, "TTCN_Snapshot::else_branch_reached();\n");
10175 StatementBlock *block = ag->get_block();
10176 if (block->get_nof_stmts() > 0) {
10177 str = mputstr(str, "{\n");
10178 str = block->generate_code(str);
10179 str = mputstr(str, "}\n");
10180 }
10181 if (block->has_return() != StatementBlock::RS_YES)
10182 str = mputstr(str, "return ALT_YES;\n");
10183 // do not generate code for further branches
10184 break;
10185 } else {
10186 size_t blockcount = 0;
10187 Value *guard_expr = ag->get_guard_expr();
10188 if (guard_expr) {
10189 // the branch has a boolean guard expression
10190 str = guard_expr->update_location_object(str);
10191 str = guard_expr->generate_code_tmp(str, "if (", blockcount);
10192 str = mputstr(str, ") {\n");
10193 blockcount++;
10194 }
10195 // indicates whether the guard operation might return ALT_REPEAT
10196 bool can_repeat;
10197 expression_struct expr;
10198 Code::init_expr(&expr);
10199 switch (agtype) {
10200 case AltGuard::AG_OP: {
10201 // the guard operation is a receiving statement
10202 Statement *stmt = ag->get_guard_stmt();
10203 str = stmt->update_location_object(str);
10204 stmt->generate_code_expr(&expr);
10205 can_repeat = stmt->can_repeat();
10206 break; }
10207 case AltGuard::AG_REF: {
10208 // the guard operation is an altstep instance
10209 Ref_pard *ref = ag->get_guard_ref();
10210 str = ref->update_location_object(str);
10211 Common::Assignment *altstep = ref->get_refd_assignment();
10212 expr.expr = mputprintf(expr.expr, "%s_instance(",
10213 altstep->get_genname_from_scope(my_scope).c_str());
10214 ref->get_parlist()->generate_code_alias(&expr,
10215 altstep->get_FormalParList(), altstep->get_RunsOnType(), false);
10216 expr.expr = mputc(expr.expr, ')');
10217 can_repeat = true;
10218 break; }
10219 case AltGuard::AG_INVOKE: {
10220 str = ag->update_location_object(str);
10221 ag->generate_code_invoke_instance(&expr);
10222 can_repeat = true;
10223 break; }
10224 default:
10225 FATAL_ERROR("AltGuards::generate_code_altstep()");
10226 }
10227 if (expr.preamble || expr.postamble) {
10228 if (blockcount == 0) {
10229 // open a statement block if it is not done so far
10230 str = mputstr(str, "{\n");
10231 blockcount++;
10232 }
10233 const string& tmp_id = my_mod->get_temporary_id();
10234 const char *tmp_id_str = tmp_id.c_str();
10235 str = mputprintf(str, "alt_status %s;\n"
10236 "{\n", tmp_id_str);
10237 str = mputstr(str, expr.preamble);
10238 str = mputprintf(str, "%s = %s;\n", tmp_id_str, expr.expr);
10239 str = mputstr(str, expr.postamble);
10240 str = mputprintf(str, "}\n"
10241 "switch (%s) {\n", tmp_id_str);
10242 } else {
10243 str = mputprintf(str, "switch (%s) {\n", expr.expr);
10244 }
10245 Code::free_expr(&expr);
10246 str = mputstr(str, "case ALT_YES:\n");
10247 StatementBlock *block = ag->get_block();
10248 if (block && block->get_nof_stmts() > 0) {
10249 str = mputstr(str, "{\n");
10250 str = block->generate_code(str);
10251 str = mputstr(str, "}\n");
10252 }
10253 if (!block || block->has_return() != StatementBlock::RS_YES)
10254 str = mputstr(str, "return ALT_YES;\n");
10255 if (can_repeat)
10256 str = mputstr(str, "case ALT_REPEAT:\n"
10257 "return ALT_REPEAT;\n");
10258 if (agtype == AltGuard::AG_REF || agtype == AltGuard::AG_INVOKE) {
10259 str = mputprintf(str, "case ALT_BREAK:\n"
10260 "return ALT_BREAK;\n");
10261 }
10262 if (!has_else_branch)
10263 str = mputstr(str, "case ALT_MAYBE:\n"
10264 "ret_val = ALT_MAYBE;\n");
10265 str = mputstr(str, "default:\n"
10266 "break;\n"
10267 "}\n");
10268 // closing statement blocks
10269 for ( ; blockcount > 0; blockcount--) str = mputstr(str, "}\n");
10270 }
10271 }
10272 if (!has_else_branch) str = mputstr(str, "return ret_val;\n");
10273 return str;
10274 }
10275
10276 char* AltGuards::generate_code_call_body(char *str, const Location& loc,
10277 const string& temp_id, bool in_interleave)
10278 {
10279 if (label) FATAL_ERROR("AltGuards::generate_code_call_body()");
10280 label = new string(temp_id);
10281 const char *label_str = temp_id.c_str();
10282 // label is needed only if there is a repeat statement in the branches
10283 if (has_repeat) str = mputprintf(str, "%s:\n", label_str);
10284 // temporary variables used for caching of status codes
10285 for (size_t i = 0; i < ags.size(); i++)
10286 str = mputprintf(str, "alt_status %s_alt_flag_%lu = %s;\n",
10287 label_str, (unsigned long) i,
10288 ags[i]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10289 str = loc.update_location_object(str);
10290 // the first snapshot is taken in non-blocking mode
10291 // and opening infinite for() loop
10292 str = mputstr(str, "TTCN_Snapshot::take_new(FALSE);\n"
10293 "for ( ; ; ) {\n"); // (1)
10294 for (size_t i = 0; i < ags.size(); i++) {
10295 AltGuard *ag = ags[i];
10296 if (ag->get_type() != AltGuard::AG_OP)
10297 FATAL_ERROR("AltGuards::generate_code_call_body()");
10298 Value *guard_expr = ag->get_guard_expr();
10299 if (guard_expr) {
10300 // the branch has a boolean guard expression
10301 str = mputprintf(str,
10302 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10303 label_str, (unsigned long) i);
10304 str = guard_expr->update_location_object(str);
10305 expression_struct expr;
10306 Code::init_expr(&expr);
10307 guard_expr->generate_code_expr(&expr);
10308 str = mputstr(str, expr.preamble);
10309 str = mputprintf(str, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10310 "else %s_alt_flag_%lu = ALT_NO;\n",
10311 expr.expr, label_str, (unsigned long) i,
10312 label_str, (unsigned long) i);
10313 str = mputstr(str, expr.postamble);
10314 Code::free_expr(&expr);
10315 str = mputstr(str, "}\n"); // (2)
10316 }
10317 // evaluation of guard operation
10318 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10319 label_str, (unsigned long) i);
10320 expression_struct expr;
10321 Code::init_expr(&expr);
10322 expr.expr = mputprintf(expr.expr, "%s_alt_flag_%lu = ", label_str,
10323 (unsigned long) i);
10324 Statement *stmt = ag->get_guard_stmt();
10325 str = stmt->update_location_object(str);
10326 stmt->generate_code_expr(&expr);
10327 str = Code::merge_free_expr(str, &expr);
10328 // execution of statement block if the guard was successful
10329 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_YES) ", label_str,
10330 (unsigned long) i);
10331 StatementBlock *block = ag->get_block();
10332 if(in_interleave) {
10333 if(block && block->get_nof_stmts() > 0) {
10334 if(block->has_receiving_stmt()) {
10335 str = mputprintf(str, "goto %s_branch%lu;\n",
10336 label_str, (unsigned long) i);
10337 }
10338 else {
10339 str = mputstr(str, "{\n"); // (3)
10340 str = block->generate_code(str);
10341 str = mputprintf(str, "goto %s_end;\n"
10342 "}\n", // (3)
10343 label_str);
10344 }
10345 }
10346 else str = mputprintf(str, "goto %s_end;\n", label_str);
10347 }
10348 else {
10349 if (block && block->get_nof_stmts() > 0) {
10350 str = mputstr(str, "{\n"); // (3)
10351 str = block->generate_code(str);
10352 if (block->has_return() != StatementBlock::RS_YES)
10353 str = mputstr(str, "break;\n");
10354 str = mputstr(str, "}\n"); // (3)
10355 }
10356 else str = mputstr(str, "break;\n");
10357 }
10358 // closing of if() block
10359 str = mputstr(str, "}\n"); // (2)
10360 }
10361 str = loc.update_location_object(str);
10362 // error handling and taking the next snapshot in blocking mode
10363 str = mputstr(str, "if (");
10364 for (size_t i = 0; i < ags.size(); i++) {
10365 if (i > 0) str = mputstr(str, " && ");
10366 str = mputprintf(str, "%s_alt_flag_%lu == ALT_NO", label_str,
10367 (unsigned long) i);
10368 }
10369 str = mputstr(str, ") TTCN_error(\"None of the branches can be chosen in "
10370 "the response and exception handling part of call statement in file ");
10371 str = Code::translate_string(str, loc.get_filename());
10372 int first_line = loc.get_first_line(), last_line = loc.get_last_line();
10373 if (first_line < last_line) str = mputprintf(str,
10374 " between lines %d and %d", first_line, last_line);
10375 else str = mputprintf(str, ", line %d", first_line);
10376 str = mputstr(str, ".\");\n"
10377 "TTCN_Snapshot::take_new(TRUE);\n"
10378 "}\n"); // (1) for
10379 return str;
10380 }
10381
10382 void AltGuards::ilt_generate_code_call_body(ILT *ilt, const char *label_str)
10383 {
10384 char*& str=ilt->get_out_branches();
10385 for(size_t i=0; i<ags.size(); i++) {
10386 StatementBlock *block = ags[i]->get_block();
10387 if (block && block->has_receiving_stmt()) {
10388 str = mputprintf(str, "%s_branch%lu:\n", label_str, (unsigned long) i);
10389 block->ilt_generate_code(ilt);
10390 str = mputprintf(str, "goto %s_end;\n", label_str);
10391 }
10392 } // for i
10393 }
10394
10395 } // namespace Ttcn
This page took 0.266084 seconds and 5 git commands to generate.