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