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