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