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