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