Last sync 2016.04.01
[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");
5822 str = block->generate_code(str);
5823 str = mputstr(str, "}\n");
5824 } else str = mputstr(str, "/* empty block */;\n");
5825 return str;
5826 }
5827
5828 char *Statement::generate_code_log(char *str)
5829 {
5830 if (logargs) {
5831 bool buffered_mode = true;
5832 if (logargs->get_nof_logargs() == 1) {
5833 LogArgument *first_logarg = logargs->get_logarg_byIndex(0);
5834 switch (first_logarg->get_type()) {
5835 case LogArgument::L_STR:
5836 // the argument is a simple string: use non-buffered mode
5837 str = mputstr(str, "TTCN_Logger::log_str(TTCN_USER, \"");
5838 str = Code::translate_string(str, first_logarg->get_str().c_str());
5839 str = mputstr(str, "\");\n");
5840 buffered_mode = false;
5841 break;
5842 case LogArgument::L_MACRO: {
5843 Value *t_val = first_logarg->get_val();
5844 if (t_val->has_single_expr()) {
5845 // the argument is a simple macro call: use non-buffered mode
5846 str = mputprintf(str, "TTCN_Logger::log_str(TTCN_USER, %s);\n",
5847 t_val->get_single_expr().c_str());
5848 buffered_mode = false;
5849 } }
5850 default:
5851 break;
5852 }
5853 }
5854 if (buffered_mode) {
5855 // the argument is a complicated construct: use buffered mode
5856 str = mputstr(str, "try {\n"
5857 "TTCN_Logger::begin_event(TTCN_USER);\n");
5858 str = logargs->generate_code(str);
5859 str = mputstr(str, "TTCN_Logger::end_event();\n"
5860 "} catch (...) {\n"
5861 "TTCN_Logger::finish_event();\n"
5862 "throw;\n"
5863 "}\n");
5864 }
5865 } else {
5866 // the argument is missing
5867 str = mputstr(str, "TTCN_Logger::log_str(TTCN_USER, "
5868 "\"<empty log statement>\");\n");
5869 }
5870 return str;
5871 }
5872
5873 char *Statement::generate_code_testcase_stop(char *str)
5874 {
5875 if (logargs) str = generate_code_log(str);
5876 str = mputstr(str, "TTCN_error(\"testcase.stop\");\n");
5877 return str;
5878 }
5879
5880 char *Statement::generate_code_label(char *str)
5881 {
5882 if (label.used) {
5883 return mputprintf(str, "%s: /* TTCN-3 label: %s */;\n",
5884 get_clabel().c_str(), label.id->get_dispname().c_str());
5885 } else {
5886 return mputprintf(str, "/* unused TTCN-3 label: %s */;\n",
5887 label.id->get_dispname().c_str());
5888 }
5889 }
5890
5891 char *Statement::generate_code_goto(char *str)
5892 {
5893 if (!go_to.label) FATAL_ERROR("Statement::generate_code_goto()");
5894 return mputprintf(str, "goto %s; /* TTCN-3 label: %s */\n",
5895 go_to.label->get_clabel().c_str(), go_to.id->get_dispname().c_str());
5896 return str;
5897 }
5898
5899 char* Statement::generate_code_if(char *str)
5900 {
5901 size_t blockcount=0;
5902 bool unreach=false, eachfalse=true;
5903 str=if_stmt.ics->generate_code(str, blockcount, unreach, eachfalse);
5904 if(if_stmt.elseblock && !unreach) {
5905 if(!eachfalse) str=mputstr(str, "else ");
5906 eachfalse=false;
5907 str=mputstr(str, "{\n");
5908 blockcount++;
5909 str=if_stmt.elseblock->generate_code(str);
5910 }
5911 while(blockcount-->0) str=mputstr(str, "}\n");
5912 if(eachfalse) str=mputstr(str, "/* never occurs */;\n");
5913 return str;
5914 }
5915
5916 char* Statement::generate_code_select(char *str)
5917 {
5918 const string& tmp_prefix = my_sb->get_scope_mod_gen()->get_temporary_id();
5919 char *expr_init=memptystr();
5920 char *expr_name=select.expr->generate_code_tmp(0, expr_init);
5921 if (expr_init[0]) { // some init code was generated
5922 str = update_location_object(str);
5923 str = mputstr(str, "{\n");
5924 str = mputstr(str, expr_init);
5925 }
5926 str=select.scs->generate_code(str, tmp_prefix.c_str(), expr_name);
5927 Free(expr_name);
5928 if (expr_init[0]) str=mputstr(str, "}\n");
5929 Free(expr_init);
5930 return str;
5931 }
5932
5933 char *Statement::generate_code_for(char *str)
5934 {
5935 /** \todo initial does not have its own location */
5936 // statements in initial may have side effects
5937 // generate code for them anyway
5938 if (loop.for_stmt.varinst) {
5939 str = mputstr(str, "{\n");
5940 str = loop.for_stmt.init_varinst->generate_code_str(str);
5941 } else {
5942 str = loop.for_stmt.init_ass->update_location_object(str);
5943 str = loop.for_stmt.init_ass->generate_code(str);
5944 }
5945 // check whether the final expression is constant
5946 bool final_is_true = false, final_is_false = false;
5947 if (!loop.for_stmt.finalexpr->is_unfoldable()) {
5948 if (loop.for_stmt.finalexpr->get_val_bool()) final_is_true = true;
5949 else final_is_false = true;
5950 }
5951 if (final_is_false) str = mputstr(str, "/* never occurs */;\n");
5952 else {
5953 if (loop.has_cnt)
5954 loop.label_next =
5955 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
5956 str = update_location_object(str);
5957 str = mputstr(str, "for ( ; ; ) {\n");
5958 // do not generate the exit condition for infinite loops
5959 if (!final_is_true) {
5960 str = loop.for_stmt.finalexpr->update_location_object(str);
5961 size_t blockcount = 0;
5962 str = loop.for_stmt.finalexpr->generate_code_tmp(str, "if (!",
5963 blockcount);
5964 str = mputstr(str, ") break;\n");
5965 while (blockcount-- > 0) str = mputstr(str, "}\n");
5966 }
5967 if (loop.label_next) str = mputstr(str, "{\n");
5968 str = loop.block->generate_code(str);
5969 if (loop.label_next)
5970 str = mputprintf(str, "}\n"
5971 "%s:\n", loop.label_next->c_str());
5972 str = loop.for_stmt.step->update_location_object(str);
5973 str = loop.for_stmt.step->generate_code(str);
5974 str = mputstr(str, "}\n");
5975 }
5976 if (loop.for_stmt.varinst) str = mputstr(str, "}\n");
5977 return str;
5978 }
5979
5980 char *Statement::generate_code_while(char *str)
5981 {
5982 // check whether the expression is constant
5983 bool condition_always_true = false, condition_always_false = false;
5984 if (!loop.expr->is_unfoldable()) {
5985 if (loop.expr->get_val_bool()) condition_always_true = true;
5986 else condition_always_false = true;
5987 }
5988 if (condition_always_false) str = mputstr(str, "/* never occurs */;\n");
5989 else {
5990 str = mputstr(str, "for ( ; ; ) {\n");
5991 if (loop.has_cnt_in_ags) {
5992 loop.label_next =
5993 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
5994 str = mputprintf(str, "%s:\n", loop.label_next->c_str());
5995 }
5996 // do not generate the exit condition for infinite loops
5997 if (!condition_always_true) {
5998 str = loop.expr->update_location_object(str);
5999 size_t blockcount = 0;
6000 str = loop.expr->generate_code_tmp(str, "if (!", blockcount);
6001 str = mputstr(str, ") break;\n");
6002 while(blockcount-- > 0) str = mputstr(str, "}\n");
6003 }
6004 str = loop.block->generate_code(str);
6005 str = mputstr(str, "}\n");
6006 }
6007 return str;
6008 }
6009
6010 char *Statement::generate_code_dowhile(char *str)
6011 {
6012 // check whether the expression is constant
6013 bool expr_is_const = !loop.expr->is_unfoldable();
6014 bool is_infinite_loop = false;
6015 if (expr_is_const) {
6016 if (loop.expr->get_val_bool()) is_infinite_loop = true;
6017 else loop.iterate_once = true;
6018 }
6019 if (loop.iterate_once && !loop.has_brk && !loop.has_cnt) {
6020 str = mputstr(str, "{\n");
6021 str = loop.block->generate_code(str);
6022 } else {
6023 str = mputstr(str, "for ( ; ; ) {\n");
6024 if (loop.has_cnt_in_ags || (!expr_is_const && loop.has_cnt))
6025 loop.label_next =
6026 new string(my_sb->get_scope_mod_gen()->get_temporary_id());
6027 if (loop.label_next && is_infinite_loop)
6028 str = mputprintf(str, "%s:\n", loop.label_next->c_str());
6029 if (loop.label_next && !is_infinite_loop) str = mputstr(str, "{\n");
6030 str = loop.block->generate_code(str);
6031 // do not generate the exit condition for infinite loops
6032 if (!is_infinite_loop) {
6033 if (loop.label_next)
6034 str = mputprintf(str, "}\n"
6035 "%s:\n", loop.label_next->c_str());
6036 str = loop.expr->update_location_object(str);
6037 if (loop.iterate_once) str = mputstr(str, "break;\n");
6038 else {
6039 size_t blockcount = 0;
6040 str = loop.expr->generate_code_tmp(str, "if (!", blockcount);
6041 str = mputstr(str, ") break;\n");
6042 while (blockcount-- > 0) str = mputstr(str, "}\n");
6043 }
6044 }
6045 }
6046 str = mputstr(str, "}\n");
6047 return str;
6048 }
6049
6050 char *Statement::generate_code_break(char *str)
6051 {
6052 // in altstep (2 (=2nd if branch))
6053 // in alt and loops - not inside interleave (4)
6054 // in loops without receiving statement embedded in interleave (4)
6055 // in loops with receiving statement embedded in interleave (1)
6056 // in interleave when not embedded in enclosed loop or alt/interleave (4)
6057 // in alt/interleave embedded in interleave (3)
6058 if (brk_cnt.loop_stmt && brk_cnt.loop_stmt->loop.il_label_end)
6059 str=mputprintf(str, "goto %s;\n",
6060 brk_cnt.loop_stmt->loop.il_label_end->c_str());
6061 else if (brk_cnt.ags && brk_cnt.ags->get_is_altstep())
6062 str=mputstr(str, "return ALT_BREAK;\n");
6063 else if (brk_cnt.ags && brk_cnt.ags->get_il_label_end())
6064 str=mputprintf(str, "goto %s;\n",
6065 brk_cnt.ags->get_il_label_end()->c_str());
6066 else
6067 str=mputstr(str, "break;\n");
6068 return str;
6069 }
6070
6071 char *Statement::generate_code_continue(char *str)
6072 {
6073 // not inside interleave when continue is not inside embedded ags (2 or 1)
6074 // continue is inside ags enclosed in the loop (3)
6075 // in interleave (3, 2 or 1)
6076 if (brk_cnt.loop_stmt != 0) {
6077 if (brk_cnt.loop_stmt->loop.iterate_once && !brk_cnt.ags &&
6078 !brk_cnt.loop_stmt->loop.is_ilt)
6079 str=mputstr(str, "break;\n");
6080 else {
6081 if (!brk_cnt.loop_stmt->loop.label_next)
6082 str=mputstr(str, "continue;\n");
6083 else
6084 str=mputprintf(str, "goto %s;\n",
6085 brk_cnt.loop_stmt->loop.label_next->c_str());
6086 }
6087 } else
6088 FATAL_ERROR("Statement::generate_code_continue()");
6089 return str;
6090 }
6091
6092 char *Statement::generate_code_repeat(char *str)
6093 {
6094 string *tmplabel=ags->get_label();
6095 if(!tmplabel) str=mputstr(str, "return ALT_REPEAT;\n");
6096 else str=mputprintf(str, "goto %s;\n", tmplabel->c_str());
6097 return str;
6098 }
6099
6100 char* Statement::generate_code_interleave(char *str)
6101 {
6102 ILT_root ilt(this);
6103 str=ilt.generate_code(str);
6104 return str;
6105 }
6106
6107 void Statement::ilt_generate_code_interleave(ILT *ilt)
6108 {
6109 const string& mytmpid=ilt->get_my_tmpid();
6110 bool toplevel=ilt->is_toplevel();
6111 size_t goto_label_num=toplevel?(size_t)-1:ilt->get_new_label_num();
6112 char*& out_branches=ilt->get_out_branches();
6113 out_branches=update_location_object(out_branches);
6114 string state_cond;
6115 if(toplevel) state_cond="";
6116 else {
6117 char *label_end = mprintf("%s_l%lu", mytmpid.c_str(),
6118 (unsigned long) goto_label_num);
6119 ags->set_il_label_end (label_end);
6120 Free(label_end);
6121 ILT_branch *branch=ilt->get_as_branch();
6122 size_t state_var=branch->get_my_state_var();
6123 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6124 state_cond=branch->get_state_cond();
6125 if(!state_cond.empty()) state_cond+=" && ";
6126 char *s=mprintf("%s_state[%lu]==%lu", mytmpid.c_str(),
6127 (unsigned long) state_var, (unsigned long) state_var_val);
6128 state_cond+=s;
6129 Free(s);
6130 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n",
6131 mytmpid.c_str(),
6132 (unsigned long) state_var, (unsigned long) state_var_val);
6133 }
6134 for(size_t i=0; i<ags->get_nof_ags(); i++) {
6135 AltGuard *ag=ags->get_ag_byIndex(i);
6136 if(ag->get_type()!=AltGuard::AG_OP)
6137 FATAL_ERROR("Statement::ilt_generate_code_interleave()");
6138 size_t state_var=ilt->get_new_state_var(toplevel);
6139 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6140 ilt->add_branch(new ILT_branch(ILT_branch::BT_IL, ag, state_cond,
6141 state_var, state_var_val,
6142 goto_label_num));
6143 if(!toplevel)
6144 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n",
6145 mytmpid.c_str(),
6146 (unsigned long) state_var, (unsigned long) state_var_val);
6147 } // for
6148 if(!toplevel)
6149 out_branches=mputprintf(out_branches, "goto %s;\n"
6150 "%s_l%lu:\n",
6151 mytmpid.c_str(),
6152 mytmpid.c_str(), (unsigned long) goto_label_num);
6153 }
6154
6155 void Statement::ilt_generate_code_alt(ILT *ilt)
6156 {
6157 const string& mytmpid=ilt->get_my_tmpid();
6158 size_t goto_label_num=ilt->get_new_label_num();
6159 char *label_end = mprintf("%s_l%lu", mytmpid.c_str(),
6160 (unsigned long) goto_label_num);
6161 ags->set_il_label_end (label_end);
6162 ILT_branch *branch=ilt->get_as_branch();
6163 string state_cond=branch->get_state_cond();
6164 size_t state_var=branch->get_my_state_var();
6165 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6166 char*& out_branches=ilt->get_out_branches();
6167 for(size_t i=0; i<ags->get_nof_ags(); i++) {
6168 AltGuard *ag=ags->get_ag_byIndex(i);
6169 if(ag->get_type()!=AltGuard::AG_OP)
6170 FATAL_ERROR("Statement::ilt_generate_code_alt()");
6171 ilt->add_branch(new ILT_branch(ILT_branch::BT_ALT, ag, state_cond,
6172 state_var, state_var_val,
6173 goto_label_num));
6174 } // for
6175 out_branches=update_location_object(out_branches);
6176 out_branches=mputprintf(out_branches, "%s_state[%lu]=%lu;\n"
6177 "goto %s;\n"
6178 "%s:\n",
6179 mytmpid.c_str(), (unsigned long) state_var,
6180 (unsigned long) state_var_val,
6181 mytmpid.c_str(), label_end);
6182 Free(label_end);
6183 }
6184
6185 void Statement::ilt_generate_code_receiving(ILT *ilt)
6186 {
6187 const string& mytmpid=ilt->get_my_tmpid();
6188 size_t goto_label_num=ilt->get_new_label_num();
6189 ILT_branch *branch=ilt->get_as_branch();
6190 string state_cond=branch->get_state_cond();
6191 size_t state_var=branch->get_my_state_var();
6192 size_t state_var_val=ilt->get_new_state_var_val(state_var);
6193 char*& out_branches=ilt->get_out_branches();
6194 ilt->add_branch(new ILT_branch(ILT_branch::BT_RECV, this, state_cond,
6195 state_var, state_var_val, goto_label_num));
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_l%lu:\n",
6200 mytmpid.c_str(), (unsigned long) state_var,
6201 (unsigned long) state_var_val,
6202 mytmpid.c_str(), mytmpid.c_str(),
6203 (unsigned long) goto_label_num);
6204 }
6205
6206 void Statement::ilt_generate_code_def(ILT *ilt)
6207 {
6208 char*& str=ilt->get_out_branches();
6209 str=update_location_object(str);
6210 {
6211 char *genname=mprintf("%s_d%lu_%s", ilt->get_my_tmpid().c_str(),
6212 (unsigned long) ilt->get_new_tmpnum(),
6213 def->get_id().get_name().c_str());
6214 def->set_genname(string(genname));
6215 Free(genname);
6216 }
6217 def->ilt_generate_code(ilt);
6218 }
6219
6220 void Statement::ilt_generate_code_if(ILT *ilt)
6221 {
6222 char *end_label=mprintf("%s_l%lu",
6223 ilt->get_my_tmpid().c_str(),
6224 (unsigned long) ilt->get_new_label_num());
6225 bool unreach=false;
6226 if_stmt.ics->ilt_generate_code(ilt, end_label, unreach);
6227 if(if_stmt.elseblock && !unreach)
6228 if_stmt.elseblock->ilt_generate_code(ilt);
6229 char*& str=ilt->get_out_branches();
6230 str=mputprintf(str, "%s:\n", end_label);
6231 Free(end_label);
6232 }
6233
6234 void Statement::ilt_generate_code_select(ILT *ilt)
6235 {
6236 char*& str=ilt->get_out_branches();
6237 str=update_location_object(str);
6238 const string& tmp_prefix = my_sb->get_scope_mod_gen()->get_temporary_id();
6239 char *expr_init=memptystr();
6240 char *expr_name=select.expr->generate_code_tmp(0, expr_init);
6241 select.scs->ilt_generate_code(ilt, tmp_prefix.c_str(),
6242 expr_init, expr_name);
6243 Free(expr_name);
6244 Free(expr_init);
6245 }
6246
6247 void Statement::ilt_generate_code_call(ILT *ilt)
6248 {
6249 char*& str=ilt->get_out_branches();
6250 str=update_location_object(str);
6251 expression_struct expr;
6252 Code::init_expr(&expr);
6253 port_op.portref->generate_code(&expr);
6254 expr.expr = mputstr(expr.expr, ".call(");
6255 port_op.s.sendpar->generate_code(&expr);
6256 if(port_op.s.toclause) {
6257 expr.expr = mputstr(expr.expr, ", ");
6258 port_op.s.toclause->generate_code_expr(&expr);
6259 }
6260 expr.expr = mputc(expr.expr, ')');
6261 str = Code::merge_free_expr(str, &expr);
6262 if (port_op.s.call.body) {
6263 str = mputstr(str, "{\n"); // (1)
6264 if (port_op.s.call.timer) {
6265 str = port_op.s.call.timer->update_location_object(str);
6266 str = mputstr(str, "TIMER call_timer;\n");
6267 Code::init_expr(&expr);
6268 expr.expr = mputstr(expr.expr, "call_timer.start(");
6269 port_op.s.call.timer->generate_code_expr(&expr);
6270 expr.expr = mputc(expr.expr, ')');
6271 str = Code::merge_free_expr(str, &expr);
6272 }
6273 // the label name is used for prefixing local variables
6274 if(!my_sb) FATAL_ERROR("Statement::generate_code_call()");
6275 const string& tmplabel = my_sb->get_scope_mod_gen()->get_temporary_id();
6276 str = port_op.s.call.body->generate_code_call_body(str, *this, tmplabel,
6277 true);
6278 const char *label_str = tmplabel.c_str();
6279 str=mputprintf(str, "goto %s_end;\n"
6280 "}\n", // (1)
6281 label_str);
6282 port_op.s.call.body->ilt_generate_code_call_body(ilt, label_str);
6283 str=mputprintf(str, "%s_end:\n", label_str);
6284 }
6285 }
6286
6287 void Statement::ilt_generate_code_for(ILT *ilt)
6288 {
6289 char*& str = ilt->get_out_branches();
6290 str = update_location_object(str);
6291 // statements in initial may have side effects
6292 // generate code for them anyway
6293 if (loop.for_stmt.varinst) {
6294 char *genname = mprintf("%s_d%lu_", ilt->get_my_tmpid().c_str(),
6295 (unsigned long) ilt->get_new_tmpnum());
6296 loop.for_stmt.init_varinst->set_genname(string(genname));
6297 Free(genname);
6298 loop.for_stmt.init_varinst->ilt_generate_code(ilt);
6299 } else str = loop.for_stmt.init_ass->generate_code(str);
6300 // check whether the final expression is constant
6301 bool final_is_true = false, final_is_false = false;
6302 if (!loop.for_stmt.finalexpr->is_unfoldable()) {
6303 if (loop.for_stmt.finalexpr->get_val_bool()) final_is_true = true;
6304 else final_is_false = true;
6305 }
6306 if (final_is_false) str = mputstr(str, "/* never occurs */;\n");
6307 else {
6308 char *label_prefix = mprintf("%s_l%lu_", ilt->get_my_tmpid().c_str(),
6309 (unsigned long) ilt->get_new_label_num());
6310 str = mputprintf(str, "%sbegin:\n", label_prefix);
6311 // do not generate the exit condition for infinite loops
6312 if (!final_is_true) {
6313 str = loop.for_stmt.finalexpr->update_location_object(str);
6314 size_t blockcount = 0;
6315 str = loop.for_stmt.finalexpr->generate_code_tmp(str, "if (!",
6316 blockcount);
6317 str = mputprintf(str, ") goto %send;\n", label_prefix);
6318 while (blockcount-- > 0) str = mputstr(str, "}\n");
6319 }
6320 loop.is_ilt = true;
6321 if (loop.has_brk) {
6322 loop.il_label_end = new string(label_prefix);
6323 *loop.il_label_end += "end";
6324 }
6325 if (loop.has_cnt) {
6326 loop.label_next = new string(label_prefix);
6327 *loop.label_next += "next";
6328 }
6329 loop.block->ilt_generate_code(ilt);
6330 if (loop.label_next)
6331 str = mputprintf(str, "%snext:\n", label_prefix);
6332 str = update_location_object(str);
6333 str = loop.for_stmt.step->generate_code(str);
6334 str = mputprintf(str, "goto %sbegin;\n", label_prefix);
6335 if (!final_is_true || loop.has_brk)
6336 str = mputprintf(str, "%send:\n", label_prefix);
6337 Free(label_prefix);
6338 }
6339 }
6340
6341 void Statement::ilt_generate_code_while(ILT *ilt)
6342 {
6343 char*& str = ilt->get_out_branches();
6344 // Location need not be set here; the location is set for the expression.
6345 // check whether the expression is constant
6346 bool expr_is_true = false, expr_is_false = false;
6347 if (!loop.expr->is_unfoldable()) {
6348 if (loop.expr->get_val_bool()) expr_is_true = true;
6349 else expr_is_false = true;
6350 }
6351 if (expr_is_false) str = mputstr(str, "/* never occurs */;\n");
6352 else {
6353 char *label_prefix = mprintf("%s_l%lu_", ilt->get_my_tmpid().c_str(),
6354 (unsigned long) ilt->get_new_label_num());
6355 str = mputprintf(str, "%sbegin:\n", label_prefix);
6356 loop.is_ilt = true;
6357 if (loop.has_brk) {
6358 loop.il_label_end = new string(label_prefix);
6359 *loop.il_label_end += "end";
6360 }
6361 if (loop.has_cnt) {
6362 loop.label_next = new string(label_prefix);
6363 *loop.label_next += "begin";
6364 }
6365 // do not generate the exit condition for infinite loops
6366 if (!expr_is_true) {
6367 str = loop.expr->update_location_object(str);
6368 size_t blockcount = 0;
6369 str = loop.expr->generate_code_tmp(str, "if (!", blockcount);
6370 str = mputprintf(str, ") goto %send;\n", label_prefix);
6371 while (blockcount-- > 0) str = mputstr(str, "}\n");
6372 }
6373 loop.block->ilt_generate_code(ilt);
6374 str = update_location_object(str);
6375 str = mputprintf(str, "goto %sbegin;\n", label_prefix);
6376 if (!expr_is_true || loop.has_brk)
6377 str = mputprintf(str, "%send:\n", label_prefix);
6378 Free(label_prefix);
6379 }
6380 }
6381
6382 void Statement::ilt_generate_code_dowhile(ILT *ilt)
6383 {
6384 char*& str = ilt->get_out_branches();
6385 // Location need not be set here; there is only a label before the body.
6386 // check whether the expression is constant
6387 bool expr_is_true = false;
6388 if (!loop.expr->is_unfoldable()) {
6389 if (loop.expr->get_val_bool()) expr_is_true = true;
6390 else loop.iterate_once = true;
6391 }
6392 char *label_prefix = 0;
6393 if (!loop.iterate_once || loop.has_brk || loop.has_cnt)
6394 label_prefix = mprintf("%s_l%lu_", ilt->get_my_tmpid().c_str(),
6395 (unsigned long) ilt->get_new_label_num());
6396 loop.is_ilt = true;
6397 if (loop.has_brk) {
6398 loop.il_label_end = new string(label_prefix);
6399 *loop.il_label_end += "end";
6400 }
6401 if (loop.has_cnt)
6402 loop.label_next = new string(label_prefix);
6403 if (loop.iterate_once) {
6404 if (loop.label_next) *loop.label_next += "end";
6405 loop.block->ilt_generate_code(ilt);
6406 } else {
6407 str = mputprintf(str, "%sbegin:\n", label_prefix);
6408 if (loop.label_next)
6409 *loop.label_next += (expr_is_true ? "begin" : "next");
6410 loop.block->ilt_generate_code(ilt);
6411 if (expr_is_true) str = mputprintf(str, "goto %sbegin;\n", label_prefix);
6412 else {
6413 if (loop.label_next) str = mputprintf(str, "%snext:\n", label_prefix);
6414 str = loop.expr->update_location_object(str);
6415 size_t blockcount = 0;
6416 str = loop.expr->generate_code_tmp(str, "if (", blockcount);
6417 str = mputprintf(str, ") goto %sbegin;\n", label_prefix);
6418 while (blockcount-- > 0) str = mputstr(str, "}\n");
6419 }
6420 }
6421 if (loop.il_label_end || (loop.iterate_once && loop.label_next)) {
6422 str = mputprintf(str, "%send: ;\n", label_prefix);
6423 }
6424 Free(label_prefix);
6425 }
6426
6427 char *Statement::generate_code_return(char *str)
6428 {
6429 expression_struct expr;
6430 Code::init_expr(&expr);
6431 expr.expr = mputstr(expr.expr, "return");
6432 Definition *my_def = my_sb->get_my_def();
6433 if (returnexpr.v) {
6434 expr.expr = mputc(expr.expr, ' ');
6435 returnexpr.v->generate_code_expr_mandatory(&expr);
6436 } else if (returnexpr.t) {
6437 expr.expr = mputc(expr.expr, ' ');
6438 if (!my_def) FATAL_ERROR("Statement::generate_code_return()");
6439 Def_Function_Base* dfb = dynamic_cast<Def_Function_Base*>(my_def);
6440 if (!dfb) FATAL_ERROR("Statement::generate_code_return()");
6441 if (dfb->get_template_restriction() != TR_NONE &&
6442 returnexpr.gen_restriction_check) {
6443 returnexpr.t->generate_code_expr(&expr,
6444 dfb->get_template_restriction());
6445 } else {
6446 returnexpr.t->generate_code_expr(&expr, TR_NONE);
6447 }
6448 } else {
6449 if (my_def && my_def->get_asstype() == Definition::A_ALTSTEP)
6450 expr.expr = mputstr(expr.expr, " ALT_YES");
6451 // else it's a return with no value: the only case a blank is unneeded
6452 }
6453 return Code::merge_free_expr(str, &expr);
6454 }
6455
6456 char *Statement::generate_code_activate(char *str)
6457 {
6458 expression_struct expr;
6459 Code::init_expr(&expr);
6460 expr.expr = mputprintf(expr.expr, "%s(", ref_pard->get_refd_assignment()
6461 ->get_genname_from_scope(my_sb, "activate_").c_str());
6462 ref_pard->get_parlist()->generate_code_noalias(&expr, ref_pard->get_refd_assignment()->get_FormalParList());
6463 expr.expr = mputc(expr.expr, ')');
6464 return Code::merge_free_expr(str, &expr);
6465 }
6466
6467 char *Statement::generate_code_activate_refd(char *str)
6468 {
6469 expression_struct expr;
6470 Code::init_expr(&expr);
6471 Value *last_v = fau_refd.value->get_value_refd_last();
6472 if (last_v->get_valuetype() == Value::V_ALTSTEP) {
6473 expr.expr = mputprintf(expr.expr, "%s(", last_v->get_refd_fat()
6474 ->get_genname_from_scope(my_sb, "activate_").c_str());
6475 } else {
6476 fau_refd.value->generate_code_expr_mandatory(&expr);
6477 expr.expr = mputstr(expr.expr, ".activate(");
6478 }
6479 fau_refd.ap_list2->generate_code_noalias(&expr, NULL);
6480 expr.expr = mputc(expr.expr, ')');
6481 return Code::merge_free_expr(str, &expr);
6482 }
6483
6484 char *Statement::generate_code_deactivate(char *str)
6485 {
6486 if(!deactivate) str=mputstr(str, "TTCN_Default::deactivate_all();\n");
6487 else {
6488 expression_struct expr;
6489 Code::init_expr(&expr);
6490 expr.expr=mputstr(expr.expr, "TTCN_Default::deactivate(");
6491 deactivate->generate_code_expr(&expr);
6492 expr.expr=mputstr(expr.expr, ");\n");
6493 str=Code::merge_free_expr(str, &expr);
6494 }
6495 return str;
6496 }
6497
6498 char *Statement::generate_code_send(char *str)
6499 {
6500 expression_struct expr;
6501 Code::init_expr(&expr);
6502 port_op.portref->generate_code(&expr);
6503 expr.expr = mputstr(expr.expr, ".send(");
6504 generate_code_expr_sendpar(&expr);
6505 if (port_op.s.toclause) {
6506 expr.expr = mputstr(expr.expr, ", ");
6507 port_op.s.toclause->generate_code_expr(&expr);
6508 }
6509 expr.expr = mputc(expr.expr, ')');
6510 return Code::merge_free_expr(str, &expr);
6511 }
6512
6513 char *Statement::generate_code_call(char *str)
6514 {
6515 expression_struct expr;
6516 Code::init_expr(&expr);
6517 port_op.portref->generate_code(&expr);
6518 expr.expr = mputstr(expr.expr, ".call(");
6519 port_op.s.sendpar->generate_code(&expr);
6520 if(port_op.s.toclause) {
6521 expr.expr = mputstr(expr.expr, ", ");
6522 port_op.s.toclause->generate_code_expr(&expr);
6523 }
6524 expr.expr = mputc(expr.expr, ')');
6525 str = Code::merge_free_expr(str, &expr);
6526 if (port_op.s.call.body) {
6527 str = mputstr(str, "{\n");
6528 if (port_op.s.call.timer) {
6529 str = port_op.s.call.timer->update_location_object(str);
6530 str = mputstr(str, "TIMER call_timer;\n");
6531 Code::init_expr(&expr);
6532 expr.expr = mputstr(expr.expr, "call_timer.start(");
6533 port_op.s.call.timer->generate_code_expr(&expr);
6534 expr.expr = mputc(expr.expr, ')');
6535 str = Code::merge_free_expr(str, &expr);
6536 }
6537 // the label name is used for prefixing local variables
6538 if(!my_sb) FATAL_ERROR("Statement::generate_code_call()");
6539 str = port_op.s.call.body->generate_code_call_body(str, *this,
6540 my_sb->get_scope_mod_gen()->get_temporary_id(), false);
6541 str=mputstr(str, "}\n");
6542 }
6543 return str;
6544 }
6545
6546 char *Statement::generate_code_reply(char *str)
6547 {
6548 expression_struct expr;
6549 Code::init_expr(&expr);
6550 port_op.portref->generate_code(&expr);
6551 expr.expr=mputstr(expr.expr, ".reply(");
6552 port_op.s.sendpar->generate_code(&expr);
6553 if(port_op.s.replyval) {
6554 expr.expr=mputstr(expr.expr, ".set_value_template(");
6555 port_op.s.replyval->generate_code_expr(&expr);
6556 expr.expr=mputc(expr.expr, ')');
6557 }
6558 if(port_op.s.toclause) {
6559 expr.expr=mputstr(expr.expr, ", ");
6560 port_op.s.toclause->generate_code_expr(&expr);
6561 }
6562 expr.expr=mputc(expr.expr, ')');
6563 return Code::merge_free_expr(str, &expr);
6564 }
6565
6566 char *Statement::generate_code_raise(char *str)
6567 {
6568 expression_struct expr;
6569 Code::init_expr(&expr);
6570 port_op.portref->generate_code(&expr);
6571 expr.expr=mputstr(expr.expr, ".raise(");
6572 port_op.s.raise.signature_ref->generate_code(&expr);
6573 expr.expr=mputstr(expr.expr, "_exception(");
6574 generate_code_expr_sendpar(&expr);
6575 expr.expr=mputc(expr.expr, ')');
6576 if(port_op.s.toclause) {
6577 expr.expr=mputstr(expr.expr, ", ");
6578 port_op.s.toclause->generate_code_expr(&expr);
6579 }
6580 expr.expr=mputc(expr.expr, ')');
6581 return Code::merge_free_expr(str, &expr);
6582 }
6583
6584 char *Statement::generate_code_portop(char *str, const char *opname)
6585 {
6586 if (port_op.portref) {
6587 expression_struct expr;
6588 Code::init_expr(&expr);
6589 port_op.portref->generate_code(&expr);
6590 expr.expr=mputprintf(expr.expr, ".%s()", opname);
6591 str=Code::merge_free_expr(str, &expr);
6592 } else {
6593 str = mputprintf(str, "PORT::all_%s();\n", opname);
6594 }
6595 return str;
6596 }
6597
6598 char *Statement::generate_code_startcomp(char *str)
6599 {
6600 expression_struct expr;
6601 Code::init_expr(&expr);
6602 Common::Assignment *func = comp_op.funcinstref->get_refd_assignment();
6603 expr.expr = mputprintf(expr.expr, "%s(",
6604 func->get_genname_from_scope(my_sb, "start_").c_str());
6605 comp_op.compref->generate_code_expr(&expr);
6606 FormalParList *fplist = func->get_FormalParList();
6607 if (fplist->get_nof_fps() > 0) {
6608 expr.expr = mputstr(expr.expr, ", ");
6609 comp_op.funcinstref->get_parlist()->generate_code_noalias(&expr, fplist);
6610 }
6611 expr.expr = mputc(expr.expr, ')');
6612 return Code::merge_free_expr(str, &expr);
6613 }
6614
6615 char *Statement::generate_code_startcomp_refd(char *str)
6616 {
6617 expression_struct expr;
6618 Code::init_expr(&expr);
6619 Value *last_v = comp_op.derefered.value->get_value_refd_last();
6620 if (last_v->get_valuetype() == Value::V_FUNCTION) {
6621 expr.expr = mputprintf(expr.expr, "%s(", last_v->get_refd_fat()
6622 ->get_genname_from_scope(my_sb, "start_").c_str());
6623 } else {
6624 comp_op.derefered.value->generate_code_expr_mandatory(&expr);
6625 expr.expr = mputstr(expr.expr, ".start(");
6626 }
6627 comp_op.compref->generate_code_expr(&expr);
6628 if (comp_op.derefered.ap_list2->get_nof_pars() > 0) {
6629 expr.expr = mputstr(expr.expr, ", ");
6630 comp_op.derefered.ap_list2->generate_code_noalias(&expr, NULL);
6631 }
6632 expr.expr = mputc(expr.expr, ')');
6633 return Code::merge_free_expr(str, &expr);
6634 }
6635
6636 char *Statement::generate_code_compop(char *str, const char *opname)
6637 {
6638 expression_struct expr;
6639 Code::init_expr(&expr);
6640 if (comp_op.compref) {
6641 Value *v_last = comp_op.compref->get_value_refd_last();
6642 if (v_last->get_valuetype() == Value::V_REFD) {
6643 // the argument is a simple component reference
6644 v_last->generate_code_expr_mandatory(&expr);
6645 expr.expr = mputprintf(expr.expr, ".%s()", opname);
6646 } else {
6647 bool refers_to_self = false;
6648 if (v_last->get_valuetype() == Value::V_EXPR) {
6649 // the argument is a special component reference (mtc, self, etc.)
6650 switch (v_last->get_optype()) {
6651 case Value::OPTYPE_COMP_MTC: {
6652 Definition *my_def = my_sb->get_my_def();
6653 if (my_def && my_def->get_asstype() == Definition::A_TESTCASE)
6654 refers_to_self = true;
6655 break; }
6656 case Value::OPTYPE_COMP_SELF:
6657 refers_to_self = true;
6658 default:
6659 break;
6660 }
6661 }
6662 if (refers_to_self) {
6663 expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_execution()",
6664 opname);
6665 } else {
6666 expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_component(",
6667 opname);
6668 v_last->generate_code_expr(&expr);
6669 expr.expr = mputc(expr.expr, ')');
6670 }
6671 }
6672 } else {
6673 // the operation refers to all component
6674 expr.expr = mputprintf(expr.expr,
6675 "TTCN_Runtime::%s_component(ALL_COMPREF)", opname);
6676 }
6677 return Code::merge_free_expr(str, &expr);
6678 }
6679
6680 char *Statement::generate_code_configop(char *str, const char *opname)
6681 {
6682 expression_struct expr;
6683 Code::init_expr(&expr);
6684 expr.expr = mputprintf(expr.expr, "TTCN_Runtime::%s_port(", opname);
6685 config_op.compref1->generate_code_expr(&expr);
6686 expr.expr = mputstr(expr.expr, ", ");
6687 if (config_op.compref1->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE)) {
6688 // the component type is known
6689 // the name of the referred port can be used
6690 config_op.portref1->generate_code_portref(&expr, my_sb);
6691 expr.expr = mputstr(expr.expr, ".get_name()");
6692 } else {
6693 // the component type is unknown
6694 // a simple string shall be formed from the port name and array indices
6695 generate_code_portref(&expr, config_op.portref1);
6696 }
6697 expr.expr = mputstr(expr.expr, ", ");
6698 config_op.compref2->generate_code_expr(&expr);
6699 expr.expr = mputstr(expr.expr, ", ");
6700 if (config_op.compref2->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE)) {
6701 // the component type is known
6702 // the name of the referred port can be used
6703 config_op.portref2->generate_code_portref(&expr, my_sb);
6704 expr.expr = mputstr(expr.expr, ".get_name()");
6705 } else {
6706 // the component type is unknown
6707 // a simple string shall be formed from the port name and array indices
6708 generate_code_portref(&expr, config_op.portref2);
6709 }
6710 expr.expr = mputc(expr.expr, ')');
6711 return Code::merge_free_expr(str, &expr);
6712 }
6713
6714 char *Statement::generate_code_starttimer(char *str)
6715 {
6716 expression_struct expr;
6717 Code::init_expr(&expr);
6718 timer_op.timerref->generate_code(&expr);
6719 expr.expr=mputstr(expr.expr, ".start(");
6720 if(timer_op.value) timer_op.value->generate_code_expr(&expr);
6721 expr.expr=mputc(expr.expr, ')');
6722 str=Code::merge_free_expr(str, &expr);
6723 return str;
6724 }
6725
6726 char *Statement::generate_code_stoptimer(char *str)
6727 {
6728 if(!timer_op.timerref) str=mputstr(str, "TIMER::all_stop();\n");
6729 else {
6730 expression_struct expr;
6731 Code::init_expr(&expr);
6732 timer_op.timerref->generate_code(&expr);
6733 expr.expr=mputstr(expr.expr, ".stop()");
6734 str=Code::merge_free_expr(str, &expr);
6735 }
6736 return str;
6737 }
6738
6739 char *Statement::generate_code_setverdict(char *str)
6740 {
6741 expression_struct expr;
6742 Code::init_expr(&expr);
6743 expr.expr=mputstr(expr.expr, "TTCN_Runtime::setverdict(");
6744 setverdict.verdictval->generate_code_expr(&expr);
6745 if (setverdict.logargs) {
6746 expr.expr=mputc(expr.expr, ',');
6747 expression_struct expr_reason;
6748 Code::init_expr(&expr_reason);
6749 setverdict.logargs->generate_code_expr(&expr_reason);
6750 if (expr_reason.preamble)
6751 expr.preamble = mputprintf(expr.preamble, "%s;\n",
6752 expr_reason.preamble);
6753 if (expr_reason.postamble)
6754 expr.postamble = mputprintf(expr.postamble, "%s;\n",
6755 expr_reason.postamble);
6756 expr.expr = mputprintf(expr.expr, "%s", expr_reason.expr);
6757 Code::free_expr(&expr_reason);
6758 }
6759 expr.expr=mputc(expr.expr, ')');
6760 str=Code::merge_free_expr(str, &expr);
6761 return str;
6762 }
6763
6764 char *Statement::generate_code_action(char *str)
6765 {
6766 str=mputstr(str, "TTCN_Runtime::begin_action();\n");
6767 if(!logargs) str=mputstr(str, "TTCN_Logger::log_event_str"
6768 "(\"<empty action statement>\");\n");
6769 else str=logargs->generate_code(str);
6770 str=mputstr(str, "TTCN_Runtime::end_action();\n");
6771 return str;
6772 }
6773
6774 char *Statement::generate_code_testcaseinst(char *str)
6775 {
6776 expression_struct expr;
6777 Code::init_expr(&expr);
6778 Common::Assignment *testcase = testcase_inst.tcref->get_refd_assignment();
6779 expr.expr = mputprintf(expr.expr, "%s(",
6780 testcase->get_genname_from_scope(my_sb, "testcase_").c_str());
6781 ActualParList *t_aplist = testcase_inst.tcref->get_parlist();
6782 if (t_aplist->get_nof_pars() > 0) {
6783 t_aplist->generate_code_alias(&expr, testcase->get_FormalParList(),
6784 0, false);
6785 expr.expr = mputstr(expr.expr, ", ");
6786 }
6787 if (testcase_inst.timerval) {
6788 expr.expr = mputstr(expr.expr, "TRUE, ");
6789 testcase_inst.timerval->generate_code_expr(&expr);
6790 expr.expr = mputc(expr.expr, ')');
6791 } else expr.expr = mputstr(expr.expr, "FALSE, 0.0)");
6792 return Code::merge_free_expr(str, &expr);
6793 }
6794
6795 char *Statement::generate_code_execute_refd(char *str)
6796 {
6797 expression_struct expr;
6798 Code::init_expr(&expr);
6799 Value *last_v = fau_refd.value->get_value_refd_last();
6800 if (last_v->get_valuetype() == Value::V_TESTCASE) {
6801 Common::Assignment *testcase = last_v->get_refd_fat();
6802 expr.expr = mputprintf(expr.expr, "%s(",
6803 testcase->get_genname_from_scope(my_sb, "testcase_").c_str());
6804 execute_refd.ap_list2->generate_code_alias(&expr,
6805 testcase->get_FormalParList(), 0, false);
6806 } else {
6807 execute_refd.value->generate_code_expr_mandatory(&expr);
6808 expr.expr = mputstr(expr.expr, ".execute(");
6809 execute_refd.ap_list2->generate_code_alias(&expr, 0, 0, false);
6810 }
6811 if (execute_refd.ap_list2->get_nof_pars() > 0)
6812 expr.expr = mputstr(expr.expr, ", ");
6813 if (execute_refd.timerval) {
6814 expr.expr = mputstr(expr.expr, "TRUE, ");
6815 execute_refd.timerval->generate_code_expr(&expr);
6816 expr.expr = mputc(expr.expr, ')');
6817 } else expr.expr = mputstr(expr.expr, "FALSE, 0.0)");
6818 return Code::merge_free_expr(str,&expr);
6819 }
6820
6821 void Statement::generate_code_expr_receive(expression_struct *expr,
6822 const char *opname)
6823 {
6824 if (port_op.portref) {
6825 // The operation refers to a specific port.
6826 port_op.portref->generate_code(expr);
6827 expr->expr = mputprintf(expr->expr, ".%s(", opname);
6828 if (port_op.r.rcvpar) {
6829 // The receive parameter is present.
6830 if (use_runtime_2 && TypeConv::needs_conv_redir(port_op.r.rcvpar,
6831 port_op.r.redirect.value)) {
6832 // Don't change the first parameter. Otherwise it won't receive
6833 // anything. The only thing we need is a temporary to save the
6834 // result and a conversion at the end.
6835 TypeConv::gen_conv_code_redir(expr, port_op.r.rcvpar,
6836 port_op.r.redirect.value);
6837 } else {
6838 port_op.r.rcvpar->generate_code(expr);
6839 expr->expr = mputstr(expr->expr, ", ");
6840 if (port_op.r.redirect.value) {
6841 // Value redirect is also present.
6842 expr->expr = mputstr(expr->expr, "&(");
6843 port_op.r.redirect.value->generate_code(expr);
6844 expr->expr = mputc(expr->expr, ')');
6845 } else expr->expr = mputstr(expr->expr, "NULL");
6846 }
6847 expr->expr = mputstr(expr->expr, ", ");
6848 }
6849 } else {
6850 // the operation refers to any port
6851 expr->expr = mputprintf(expr->expr, "PORT::any_%s(", opname);
6852 }
6853 generate_code_expr_fromclause(expr);
6854 expr->expr = mputstr(expr->expr, ", ");
6855 generate_code_expr_senderredirect(expr);
6856 expr->expr = mputc(expr->expr, ')');
6857 }
6858
6859 void Statement::generate_code_expr_getcall(expression_struct *expr,
6860 const char *opname)
6861 {
6862 if (port_op.portref) {
6863 // the operation refers to a specific port
6864 port_op.portref->generate_code(expr);
6865 expr->expr = mputprintf(expr->expr, ".%s(", opname);
6866 if (port_op.r.rcvpar) {
6867 // the signature template is present
6868 port_op.r.rcvpar->generate_code(expr);
6869 expr->expr = mputstr(expr->expr, ", ");
6870 generate_code_expr_fromclause(expr);
6871 // a temporary object is needed for parameter redirect
6872 Type *signature = port_op.r.rcvpar->get_Template()->get_my_governor();
6873 expr->expr = mputprintf(expr->expr, ", %s_call_redirect(",
6874 signature->get_genname_value(my_sb).c_str());
6875 if (port_op.r.redirect.param)
6876 port_op.r.redirect.param->generate_code(expr);
6877 expr->expr = mputstr(expr->expr, "), ");
6878 generate_code_expr_senderredirect(expr);
6879 } else {
6880 // the signature parameter is not present
6881 generate_code_expr_fromclause(expr);
6882 expr->expr = mputstr(expr->expr, ", ");
6883 generate_code_expr_senderredirect(expr);
6884 }
6885 } else {
6886 // the operation refers to any port
6887 expr->expr = mputprintf(expr->expr, "PORT::any_%s(", opname);
6888 generate_code_expr_fromclause(expr);
6889 expr->expr = mputstr(expr->expr, ", ");
6890 generate_code_expr_senderredirect(expr);
6891 }
6892 expr->expr=mputc(expr->expr, ')');
6893 }
6894
6895 void Statement::generate_code_expr_getreply(expression_struct *expr,
6896 const char *opname)
6897 {
6898 if (port_op.portref) {
6899 // the operation refers to a specific port
6900 port_op.portref->generate_code(expr);
6901 expr->expr = mputprintf(expr->expr, ".%s(", opname);
6902 if (port_op.r.rcvpar) {
6903 // the signature template is present
6904 port_op.r.rcvpar->generate_code(expr);
6905 Type *signature = port_op.r.rcvpar->get_Template()->get_my_governor();
6906 Type *return_type =
6907 signature->get_type_refd_last()->get_signature_return_type();
6908 if (return_type) {
6909 expr->expr = mputstr(expr->expr, ".set_value_template(");
6910 if (port_op.r.getreply_valuematch) {
6911 // the value match is also present
6912 port_op.r.getreply_valuematch->generate_code(expr);
6913 } else {
6914 // the value match is not present
6915 // we must substitute it with ? in the signature template
6916 expr->expr = mputprintf(expr->expr, "%s(ANY_VALUE)",
6917 return_type->get_genname_template(my_sb).c_str());
6918 }
6919 expr->expr = mputc(expr->expr, ')');
6920 }
6921 expr->expr = mputstr(expr->expr, ", ");
6922 generate_code_expr_fromclause(expr);
6923 // a temporary object is needed for value and parameter redirect
6924 expr->expr = mputprintf(expr->expr, ", %s_reply_redirect(",
6925 signature->get_genname_value(my_sb).c_str());
6926 if (return_type) {
6927 // the first argument of the constructor must contain
6928 // the value redirect
6929 if (port_op.r.redirect.value) {
6930 expr->expr = mputstr(expr->expr, "&(");
6931 port_op.r.redirect.value->generate_code(expr);
6932 expr->expr = mputc(expr->expr, ')');
6933 } else expr->expr = mputstr(expr->expr, "NULL");
6934 if (port_op.r.redirect.param) expr->expr = mputstr(expr->expr, ", ");
6935 }
6936 if (port_op.r.redirect.param)
6937 port_op.r.redirect.param->generate_code(expr);
6938 expr->expr = mputstr(expr->expr, "), ");
6939 generate_code_expr_senderredirect(expr);
6940 } else {
6941 // the signature template is not present
6942 generate_code_expr_fromclause(expr);
6943 expr->expr = mputstr(expr->expr, ", ");
6944 generate_code_expr_senderredirect(expr);
6945 }
6946 } else {
6947 // the operation refers to any port
6948 expr->expr = mputprintf(expr->expr, "PORT::any_%s(", opname);
6949 generate_code_expr_fromclause(expr);
6950 expr->expr = mputstr(expr->expr, ", ");
6951 generate_code_expr_senderredirect(expr);
6952 }
6953 expr->expr = mputc(expr->expr, ')');
6954 }
6955
6956 void Statement::generate_code_expr_catch(expression_struct *expr)
6957 {
6958 if (port_op.portref) {
6959 // the operation refers to a specific port
6960 if (port_op.r.ctch.timeout) {
6961 // the operation catches the timeout exception
6962 expr->expr = mputstr(expr->expr, "call_timer.timeout()");
6963 return;
6964 }
6965 port_op.portref->generate_code(expr);
6966 expr->expr = mputprintf(expr->expr, ".%s(",
6967 statementtype == S_CHECK_CATCH ? "check_catch" : "get_exception");
6968 if (port_op.r.ctch.signature_ref) {
6969 // the signature reference and the exception template is present
6970 expr->expr = mputprintf(expr->expr, "%s_exception_template(",
6971 port_op.r.ctch.signature->get_genname_value(my_sb).c_str());
6972 port_op.r.rcvpar->generate_code(expr);
6973 expr->expr = mputstr(expr->expr, ", ");
6974 if (port_op.r.redirect.value) {
6975 // value redirect is also present
6976 expr->expr = mputstr(expr->expr, "&(");
6977 port_op.r.redirect.value->generate_code(expr);
6978 expr->expr = mputc(expr->expr, ')');
6979 } else expr->expr = mputstr(expr->expr, "NULL");
6980 expr->expr = mputstr(expr->expr, "), ");
6981 }
6982 } else {
6983 // the operation refers to any port
6984 expr->expr = mputprintf(expr->expr, "PORT::%s(",
6985 statementtype == S_CHECK_CATCH ? "any_check_catch" : "any_catch");
6986 }
6987 generate_code_expr_fromclause(expr);
6988 expr->expr = mputstr(expr->expr, ", ");
6989 generate_code_expr_senderredirect(expr);
6990 expr->expr = mputc(expr->expr, ')');
6991 }
6992
6993 void Statement::generate_code_expr_check(expression_struct *expr)
6994 {
6995 if (port_op.portref) {
6996 // the operation refers to a specific port
6997 port_op.portref->generate_code(expr);
6998 expr->expr = mputstr(expr->expr, ".check");
6999 } else {
7000 // the operation refers to any port
7001 expr->expr = mputstr(expr->expr, "PORT::any_check");
7002 }
7003 expr->expr = mputc(expr->expr, '(');
7004 generate_code_expr_fromclause(expr);
7005 expr->expr = mputstr(expr->expr, ", ");
7006 generate_code_expr_senderredirect(expr);
7007 expr->expr = mputc(expr->expr, ')');
7008 }
7009
7010 void Statement::generate_code_expr_done(expression_struct *expr)
7011 {
7012 if (comp_op.compref) {
7013 if (comp_op.donereturn.donematch) {
7014 // value returning done
7015 // figure out what type the done() function belongs to
7016 Type *t = comp_op.donereturn.donematch
7017 ->get_expr_governor(Type::EXPECTED_TEMPLATE);
7018 if (!t) FATAL_ERROR("Statement::generate_code_expr_done()");
7019 while (t->is_ref() && !t->has_done_attribute())
7020 t = t->get_type_refd();
7021 if (!t->has_done_attribute())
7022 FATAL_ERROR("Statement::generate_code_expr_done()");
7023 // determine whether the done() function is in the same module
7024 Common::Module *t_mod = t->get_my_scope()->get_scope_mod_gen();
7025 if (t_mod != my_sb->get_scope_mod_gen()) {
7026 expr->expr = mputprintf(expr->expr, "%s::",
7027 t_mod->get_modid().get_name().c_str());
7028 }
7029 expr->expr = mputstr(expr->expr, "done(");
7030 comp_op.compref->generate_code_expr(expr);
7031 expr->expr = mputstr(expr->expr, ", ");
7032 comp_op.donereturn.donematch->generate_code(expr);
7033 expr->expr = mputstr(expr->expr, ", ");
7034 if (comp_op.donereturn.redirect) {
7035 // value redirect is present
7036 expr->expr = mputstr(expr->expr, "&(");
7037 comp_op.donereturn.redirect->generate_code(expr);
7038 expr->expr = mputc(expr->expr, ')');
7039 } else {
7040 // value redirect is omitted
7041 expr->expr = mputstr(expr->expr, "NULL");
7042 }
7043 expr->expr = mputc(expr->expr, ')');
7044 } else {
7045 // simple done
7046 comp_op.compref->generate_code_expr_mandatory(expr);
7047 expr->expr = mputstr(expr->expr, ".done()");
7048 }
7049 } else if (comp_op.any_or_all == C_ANY) {
7050 // any component.done
7051 expr->expr = mputstr(expr->expr,
7052 "TTCN_Runtime::component_done(ANY_COMPREF)");
7053 } else {
7054 // all component.done
7055 expr->expr = mputstr(expr->expr,
7056 "TTCN_Runtime::component_done(ALL_COMPREF)");
7057 }
7058 }
7059
7060 void Statement::generate_code_expr_killed(expression_struct *expr)
7061 {
7062 if (comp_op.compref) {
7063 // compref.killed
7064 comp_op.compref->generate_code_expr_mandatory(expr);
7065 expr->expr = mputstr(expr->expr, ".killed()");
7066 } else if (comp_op.any_or_all == C_ANY) {
7067 // any component.killed
7068 expr->expr = mputstr(expr->expr,
7069 "TTCN_Runtime::component_killed(ANY_COMPREF)");
7070 } else {
7071 // all component.killed
7072 expr->expr = mputstr(expr->expr,
7073 "TTCN_Runtime::component_killed(ALL_COMPREF)");
7074 }
7075 }
7076
7077 void Statement::generate_code_expr_timeout(expression_struct *expr)
7078 {
7079 if (timer_op.timerref) {
7080 timer_op.timerref->generate_code(expr);
7081 expr->expr=mputstr(expr->expr, ".timeout()");
7082 } else expr->expr = mputstr(expr->expr, "TIMER::any_timeout()");
7083 }
7084
7085 void Statement::generate_code_expr_sendpar(expression_struct *expr)
7086 {
7087 Template *templ_body = port_op.s.sendpar->get_Template();
7088 if (!port_op.s.sendpar->get_DerivedRef() &&
7089 templ_body->get_templatetype() == Template::SPECIFIC_VALUE) {
7090 // the send parameter is a value: optimization is possible
7091 Value *t_val = templ_body->get_specific_value();
7092 bool cast_needed = t_val->explicit_cast_needed();
7093 if (cast_needed) {
7094 // the ambiguous C++ expression is converted to the value class
7095 expr->expr = mputprintf(expr->expr, "%s(",
7096 t_val->get_my_governor()->get_genname_value(my_sb).c_str());
7097 }
7098 t_val->generate_code_expr_mandatory(expr);
7099 if (cast_needed) expr->expr = mputc(expr->expr, ')');
7100 } else {
7101 // the send parameter is a real template: optimization is not possible
7102 port_op.s.sendpar->generate_code(expr);
7103 }
7104 }
7105
7106 void Statement::generate_code_expr_fromclause(expression_struct *expr)
7107 {
7108 if (port_op.r.fromclause) {
7109 // the from clause is present: trivial case
7110 port_op.r.fromclause->generate_code(expr);
7111 } else if (port_op.r.redirect.sender) {
7112 // from clause is omitted, but sender redirect is present
7113 Type *t_var_type = port_op.r.redirect.sender->chk_variable_ref();
7114 if (!t_var_type)
7115 FATAL_ERROR("Statement::generate_code_expr_fromclause()");
7116 if (t_var_type->get_type_refd_last()->get_typetype() ==
7117 Type::T_COMPONENT) {
7118 // the variable can store a component reference
7119 expr->expr = mputstr(expr->expr, "any_compref");
7120 } else {
7121 // the variable can store an address value
7122 expr->expr = mputprintf(expr->expr, "%s(ANY_VALUE)",
7123 t_var_type->get_genname_template(my_sb).c_str());
7124 }
7125 } else {
7126 // neither from clause nor sender redirect is present
7127 // the operation cannot refer to address type
7128 expr->expr = mputstr(expr->expr, "any_compref");
7129 }
7130 }
7131
7132 void Statement::generate_code_expr_senderredirect(expression_struct *expr)
7133 {
7134 if (port_op.r.redirect.sender) {
7135 expr->expr = mputstr(expr->expr, "&(");
7136 port_op.r.redirect.sender->generate_code(expr);
7137 expr->expr = mputc(expr->expr, ')');
7138 } else expr->expr = mputstr(expr->expr, "NULL");
7139 }
7140
7141 void Statement::generate_code_portref(expression_struct *expr,
7142 Reference *p_ref)
7143 {
7144 // make a backup of the current expression
7145 char *expr_backup = expr->expr;
7146 // build the equivalent of p_ref in expr->expr
7147 expr->expr = mprintf("\"%s\"", p_ref->get_id()->get_dispname().c_str());
7148 FieldOrArrayRefs *t_subrefs = p_ref->get_subrefs();
7149 if (t_subrefs) {
7150 // array indices are present
7151 for (size_t i = 0; i < t_subrefs->get_nof_refs(); i++) {
7152 FieldOrArrayRef *t_ref = t_subrefs->get_ref(i);
7153 if (t_ref->get_type() != FieldOrArrayRef::ARRAY_REF)
7154 FATAL_ERROR("Statement::generate_code_portref()");
7155 // transform expr->expr: XXXX -> get_port_name(XXXX, index)
7156 char *tmp = expr->expr;
7157 expr->expr = mcopystr("get_port_name(");
7158 expr->expr = mputstr(expr->expr, tmp);
7159 Free(tmp);
7160 expr->expr = mputstr(expr->expr, ", ");
7161 t_ref->get_val()->generate_code_expr(expr);
7162 expr->expr = mputc(expr->expr, ')');
7163 }
7164 }
7165 // now expr->expr contains the equivalent of p_ref
7166 // append it to the original expression and restore the result
7167 expr_backup = mputstr(expr_backup, expr->expr);
7168 Free(expr->expr);
7169 expr->expr = expr_backup;
7170 }
7171
7172 void Statement::set_parent_path(WithAttribPath* p_path) {
7173 switch (statementtype) {
7174 case S_DEF:
7175 def->set_parent_path(p_path);
7176 break;
7177 case S_BLOCK:
7178 block->set_parent_path(p_path);
7179 break;
7180 case S_IF:
7181 if_stmt.ics->set_parent_path(p_path);
7182 if (if_stmt.elseblock)
7183 if_stmt.elseblock->set_parent_path(p_path);
7184 break;
7185 case S_SELECT:
7186 select.scs->set_parent_path(p_path);
7187 break;
7188 case S_FOR:
7189 loop.block->set_parent_path(p_path);
7190 break;
7191 case S_WHILE:
7192 case S_DOWHILE:
7193 loop.block->set_parent_path(p_path);
7194 break;
7195 case S_ASSIGNMENT:
7196 case S_LOG:
7197 case S_ACTION:
7198 case S_LABEL:
7199 case S_GOTO:
7200 case S_ERROR:
7201 case S_BREAK:
7202 case S_CONTINUE:
7203 case S_STOP_EXEC:
7204 case S_STOP_TESTCASE:
7205 case S_REPEAT:
7206 case S_START_UNDEF:
7207 case S_STOP_UNDEF:
7208 case S_UNKNOWN_INSTANCE:
7209 case S_FUNCTION_INSTANCE:
7210 case S_ALTSTEP_INSTANCE:
7211 case S_ACTIVATE:
7212 case S_ALT:
7213 case S_INTERLEAVE:
7214 case S_RETURN:
7215 case S_DEACTIVATE:
7216 case S_SEND:
7217 case S_CALL:
7218 case S_REPLY:
7219 case S_RAISE:
7220 case S_RECEIVE:
7221 case S_CHECK_RECEIVE:
7222 case S_TRIGGER:
7223 case S_GETCALL:
7224 case S_CHECK_GETCALL:
7225 case S_GETREPLY:
7226 case S_CHECK_GETREPLY:
7227 case S_CATCH:
7228 case S_CHECK_CATCH:
7229 case S_CHECK:
7230 case S_CLEAR:
7231 case S_START_PORT:
7232 case S_STOP_PORT:
7233 case S_HALT:
7234 case S_START_COMP:
7235 case S_START_COMP_REFD:
7236 case S_STOP_COMP:
7237 case S_KILL:
7238 case S_KILLED:
7239 case S_DONE:
7240 case S_CONNECT:
7241 case S_MAP:
7242 case S_DISCONNECT:
7243 case S_UNMAP:
7244 case S_START_TIMER:
7245 case S_STOP_TIMER:
7246 case S_TIMEOUT:
7247 case S_SETVERDICT:
7248 case S_TESTCASE_INSTANCE:
7249 case S_TESTCASE_INSTANCE_REFD:
7250 case S_ACTIVATE_REFD:
7251 case S_UNKNOWN_INVOKED:
7252 case S_FUNCTION_INVOKED:
7253 case S_ALTSTEP_INVOKED:
7254 case S_STRING2TTCN:
a38c6d4c 7255 case S_START_PROFILER:
7256 case S_STOP_PROFILER:
3abe9331 7257 case S_INT2ENUM:
970ed795
EL
7258 break;
7259 default:
7260 FATAL_ERROR("Statement::set_parent_path()");
7261 }
7262 }
7263
7264 // =================================
7265 // ===== Assignment
7266 // =================================
7267
7268 Assignment::Assignment(Reference *p_ref, Template *p_templ)
7269 : asstype(ASS_UNKNOWN), ref(p_ref), templ(p_templ), self_ref(false),
7270 template_restriction(TR_NONE), gen_restriction_check(false)
7271 {
7272 if(!ref || !templ) FATAL_ERROR("Ttcn::Assignment::Assignment");
7273 }
7274
7275 Assignment::Assignment(Reference *p_ref, Value *p_val)
7276 : asstype(ASS_VAR), ref(p_ref), val(p_val), self_ref(false),
7277 template_restriction(TR_NONE), gen_restriction_check(false)
7278 {
7279 if(!ref || !val) FATAL_ERROR("Ttcn::Assignment::Assignment");
7280 }
7281
7282 Assignment::~Assignment()
7283 {
7284 switch(asstype) {
7285 case ASS_UNKNOWN:
7286 case ASS_TEMPLATE:
7287 delete ref;
7288 delete templ;
7289 break;
7290 case ASS_VAR:
7291 delete ref;
7292 delete val;
7293 break;
7294 case ASS_ERROR:
7295 break;
7296 default:
7297 FATAL_ERROR("Ttcn::Assignment::~Assignment()");
7298 } // switch
7299 }
7300
7301 Assignment *Assignment::clone() const
7302 {
7303 FATAL_ERROR("Assignment::clone");
7304 }
7305
7306 void Assignment::set_my_scope(Scope *p_scope)
7307 {
7308 switch(asstype) {
7309 case ASS_UNKNOWN:
7310 case ASS_TEMPLATE:
7311 ref->set_my_scope(p_scope);
7312 templ->set_my_scope(p_scope);
7313 break;
7314 case ASS_VAR:
7315 ref->set_my_scope(p_scope);
7316 val->set_my_scope(p_scope);
7317 break;
7318 case ASS_ERROR:
7319 break;
7320 default:
7321 FATAL_ERROR("Ttcn::Assignment::set_my_scope()");
7322 } // switch
7323 }
7324
7325 void Assignment::set_fullname(const string& p_fullname)
7326 {
7327 Node::set_fullname(p_fullname);
7328 switch(asstype) {
7329 case ASS_UNKNOWN:
7330 case ASS_TEMPLATE:
7331 ref->set_fullname(p_fullname);
7332 templ->set_fullname(p_fullname);
7333 break;
7334 case ASS_VAR:
7335 ref->set_fullname(p_fullname);
7336 val->set_fullname(p_fullname);
7337 break;
7338 case ASS_ERROR:
7339 break;
7340 default:
7341 FATAL_ERROR("Ttcn::Assignment::set_fullname()");
7342 } // switch
7343 }
7344
7345 void Assignment::dump(unsigned int level) const
7346 {
7347 // warning, ref is not always set (e.g. ASS_ERROR)
7348 switch (asstype) {
7349 case ASS_VAR:
7350 ref->dump(level+1);
7351 val->dump(level+1);
7352 break;
7353
7354 case ASS_ERROR:
7355 DEBUG(level, "*** ERROR ***");
7356 break;
7357
7358 case ASS_UNKNOWN:
7359 DEBUG(level, "*** UNKNOWN ***");
7360 break;
7361
7362 case ASS_TEMPLATE:
7363 ref->dump(level+1);
7364 templ->dump(level+1);
7365 break;
7366 }
7367 }
7368
7369 void Assignment::chk_unknown_ass()
7370 {
7371 Common::Assignment *t_ass = ref->get_refd_assignment();
7372 if (!t_ass) goto error;
7373 switch (t_ass->get_asstype()) {
7374 case Common::Assignment::A_ERROR:
7375 goto error;
7376 case Common::Assignment::A_PAR_VAL_IN:
7377 t_ass->use_as_lvalue(*ref);
7378 // no break
7379 case Common::Assignment::A_VAR:
7380 case Common::Assignment::A_PAR_VAL_OUT:
7381 case Common::Assignment::A_PAR_VAL_INOUT:
7382 if (templ->is_Value()) {
7383 Value *t_val = templ->get_Value();
7384 delete templ;
7385 val = t_val;
7386 asstype = ASS_VAR;
7387 chk_var_ass();
7388 } else {
7389 templ->error("A template body with matching symbols cannot be"
7390 " assigned to a variable");
7391 goto error;
7392 }
7393 break;
7394 case Common::Assignment::A_PAR_TEMPL_IN:
7395 t_ass->use_as_lvalue(*ref);
7396 // no break
7397 case Common::Assignment::A_VAR_TEMPLATE: {
7398 Type::typetype_t tt = t_ass->get_Type()->get_typetype();
7399 switch (tt) {
7400 case Type::T_BSTR:
7401 case Type::T_BSTR_A:
7402 case Type::T_HSTR:
7403 case Type::T_OSTR:
7404 case Type::T_CSTR:
7405 case Type::T_USTR:
7406 case Type::T_UTF8STRING:
7407 case Type::T_NUMERICSTRING:
7408 case Type::T_PRINTABLESTRING:
7409 case Type::T_TELETEXSTRING:
7410 case Type::T_VIDEOTEXSTRING:
7411 case Type::T_IA5STRING:
7412 case Type::T_GRAPHICSTRING:
7413 case Type::T_VISIBLESTRING:
7414 case Type::T_GENERALSTRING:
7415 case Type::T_UNIVERSALSTRING:
7416 case Type::T_BMPSTRING:
7417 case Type::T_UTCTIME:
7418 case Type::T_GENERALIZEDTIME:
7419 case Type::T_OBJECTDESCRIPTOR: {
7420 Ttcn::FieldOrArrayRefs *subrefs = ref->get_subrefs();
7421 if (!subrefs) break;
7422 size_t nof_subrefs = subrefs->get_nof_refs();
7423 if (nof_subrefs > 0) {
7424 Ttcn::FieldOrArrayRef *last_ref = subrefs
7425 ->get_ref(nof_subrefs - 1);
7426 if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
7427 if (!templ->is_Value()) {
7428 templ->error("A template body with matching symbols cannot be "
7429 "assigned to an element of a template variable");
7430 goto error;
7431 }
7432 }
7433 }
7434 break; }
7435 default:
7436 break;
7437 }
7438 }
7439 case Common::Assignment::A_PAR_TEMPL_OUT:
7440 case Common::Assignment::A_PAR_TEMPL_INOUT:
7441 asstype = ASS_TEMPLATE;
7442 chk_template_ass();
7443 break;
7444 default:
7445 ref->error("Reference to a variable or template variable was expected "
7446 "instead of %s", t_ass->get_description().c_str());
7447 goto error;
7448 }
7449 return;
7450 error:
7451 delete ref;
7452 delete templ;
7453 asstype = ASS_ERROR;
7454 return;
7455 }
7456
7457 void Assignment::chk_var_ass()
7458 {
7459 Common::Assignment *lhs = ref->get_refd_assignment();
7460 Type *var_type = lhs->get_Type();
7461 FieldOrArrayRefs *subrefs = ref->get_subrefs();
7462 Type *type =
7463 var_type->get_field_type(subrefs, Type::EXPECTED_DYNAMIC_VALUE);
7464 if (!type) goto error;
7465 val->set_my_governor(type);
7466 type->chk_this_value_ref(val);
7467 if (val->get_value_refd_last()->get_valuetype() == Value::V_OMIT) {
7468 Identifier *field_id = 0;
7469 if (subrefs) field_id = subrefs->remove_last_field();
7470 if (!field_id) {
7471 val->error("Omit value can be assigned to an optional field of "
7472 "a record or set value only");
7473 goto error;
7474 }
7475 Type *base_type = var_type
7476 ->get_field_type(subrefs, Type::EXPECTED_DYNAMIC_VALUE);
7477 // Putting field_id back to subrefs.
7478 subrefs->add(new FieldOrArrayRef(field_id));
7479 base_type = base_type->get_type_refd_last();
7480 switch (base_type->get_typetype()) {
7481 case Type::T_ERROR:
7482 goto error;
7483 case Type::T_SEQ_A:
7484 case Type::T_SEQ_T:
7485 case Type::T_SET_A:
7486 case Type::T_SET_T:
7487 break;
7488 default:
7489 val->error("Omit value can be assigned to an optional field of "
7490 "a record or set value only");
7491 goto error;
7492 }
7493 if (!base_type->get_comp_byName(*field_id)->get_is_optional()) {
7494 val->error("Assignment of `omit' to mandatory field `%s' of type "
7495 "`%s'", field_id->get_dispname().c_str(),
7496 base_type->get_typename().c_str());
7497 goto error;
7498 }
7499 } else {
7500 bool is_string_element = subrefs && subrefs->refers_to_string_element();
7501 self_ref |= type->chk_this_value(val, lhs, Type::EXPECTED_DYNAMIC_VALUE,
7502 INCOMPLETE_ALLOWED, OMIT_NOT_ALLOWED,
7503 (is_string_element ? NO_SUB_CHK : SUB_CHK), NOT_IMPLICIT_OMIT,
7504 (is_string_element ? IS_STR_ELEM : NOT_STR_ELEM));
7505 if (is_string_element) {
7506 // The length of RHS value shall be 1.
7507 Value *v_last = val->get_value_refd_last();
7508 switch (type->get_type_refd_last()->get_typetype()) {
7509 case Type::T_BSTR:
7510 case Type::T_BSTR_A:
7511 if (v_last->get_valuetype() != Value::V_BSTR) v_last = 0;
7512 break;
7513 case Type::T_HSTR:
7514 if (v_last->get_valuetype() != Value::V_HSTR) v_last = 0;
7515 break;
7516 case Type::T_OSTR:
7517 if (v_last->get_valuetype() != Value::V_OSTR) v_last = 0;
7518 break;
7519 case Type::T_CSTR:
7520 case Type::T_NUMERICSTRING:
7521 case Type::T_PRINTABLESTRING:
7522 case Type::T_IA5STRING:
7523 case Type::T_VISIBLESTRING:
7524 case Type::T_UTCTIME:
7525 case Type::T_GENERALIZEDTIME:
7526 if (v_last->get_valuetype() != Value::V_CSTR) v_last = 0;
7527 break;
7528 case Type::T_USTR:
7529 case Type::T_UTF8STRING:
7530 case Type::T_TELETEXSTRING:
7531 case Type::T_VIDEOTEXSTRING:
7532 case Type::T_GRAPHICSTRING:
7533 case Type::T_GENERALSTRING:
7534 case Type::T_UNIVERSALSTRING:
7535 case Type::T_BMPSTRING:
7536 case Type::T_OBJECTDESCRIPTOR:
7537 if (v_last->get_valuetype() != Value::V_USTR) v_last = 0;
7538 break;
7539 default:
7540 v_last = 0;
7541 }
7542 if (v_last) {
7543 size_t string_len = v_last->get_val_strlen();
7544 if (string_len != 1) {
7545 val->error("The length of the string to be assigned to a string "
7546 "element of type `%s' should be 1 instead of %lu",
7547 type->get_typename().c_str(),
7548 (unsigned long)string_len);
7549 goto error;
7550 }
7551 }
7552 }
7553 }
7554 return;
7555 error:
7556 delete ref;
7557 delete val;
7558 asstype = ASS_ERROR;
7559 return;
7560 }
7561
7562 void Assignment::chk_template_ass()
7563 {
7564 FieldOrArrayRefs *subrefs = ref->get_subrefs();
7565 Common::Assignment *lhs = ref->get_refd_assignment();
7566 if (!lhs) FATAL_ERROR("Ttcn::Assignment::chk_template_ass()");
7567 Type *type = lhs->get_Type()->
7568 get_field_type(subrefs, Type::EXPECTED_DYNAMIC_VALUE);
7569 if (!type) goto error;
7570 if (lhs->get_asstype() != Common::Assignment::A_VAR_TEMPLATE &&
7571 subrefs && subrefs->refers_to_string_element()) {
7572 ref->error("It is not allowed to index template strings");
7573 goto error;
7574 }
7575 templ->set_my_governor(type);
7576
7577 templ->flatten(false);
7578
7579 type->chk_this_template_ref(templ);
7580 self_ref |= type->chk_this_template_generic(templ, INCOMPLETE_ALLOWED,
7581 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, NOT_IMPLICIT_OMIT, lhs);
7582 chk_template_restriction();
7583 return;
7584 error:
7585 delete ref;
7586 delete templ;
7587 asstype = ASS_ERROR;
7588 return;
7589 }
7590
7591 void Assignment::chk()
7592 {
7593 switch(asstype) {
7594 case ASS_UNKNOWN:
7595 chk_unknown_ass();
7596 break;
7597 case ASS_VAR:
7598 chk_var_ass();
7599 break;
7600 case ASS_TEMPLATE:
7601 chk_template_ass();
7602 break;
7603 case ASS_ERROR:
7604 break;
7605 default:
7606 FATAL_ERROR("Ttcn::Assignment::chk()");
7607 } // switch
7608 }
7609
7610 void Assignment::set_code_section(
7611 GovernedSimple::code_section_t p_code_section)
7612 {
7613 switch(asstype) {
7614 case ASS_VAR:
7615 ref->set_code_section(p_code_section);
7616 val->set_code_section(p_code_section);
7617 break;
7618 case ASS_TEMPLATE:
7619 ref->set_code_section(p_code_section);
7620 templ->set_code_section(p_code_section);
7621 break;
7622 case ASS_UNKNOWN:
7623 case ASS_ERROR:
7624 break;
7625 default:
7626 FATAL_ERROR("Ttcn::Assignment::set_code_section()");
7627 } // switch
7628 }
7629
7630 void Assignment::chk_template_restriction()
7631 {
7632 if (asstype!=ASS_TEMPLATE)
7633 FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7634 Common::Assignment *t_ass = ref->get_refd_assignment();
7635 if (!t_ass) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7636 switch (t_ass->get_asstype()) {
7637 case Common::Assignment::A_VAR_TEMPLATE: {
7638 Def_Var_Template* dvt = dynamic_cast<Def_Var_Template*>(t_ass);
7639 if (!dvt) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7640 template_restriction = dvt->get_template_restriction();
7641 } break;
7642 case Common::Assignment::A_PAR_TEMPL_IN:
7643 case Common::Assignment::A_PAR_TEMPL_OUT:
7644 case Common::Assignment::A_PAR_TEMPL_INOUT: {
7645 FormalPar* fp = dynamic_cast<FormalPar*>(t_ass);
7646 if (!fp) FATAL_ERROR("Ttcn::Assignment::chk_template_restriction()");
7647 template_restriction = fp->get_template_restriction();
7648 } break;
7649 default:
7650 template_restriction = TR_NONE;
7651 }
7652 // transform the restriction if this is a subfield
7653 template_restriction = Template::get_sub_restriction(template_restriction, ref);
7654 // check the template restriction
7655 gen_restriction_check =
3abe9331 7656 templ->chk_restriction("template", template_restriction, this);
970ed795
EL
7657 }
7658
7659 char *Assignment::generate_code(char *str)
7660 {
3f84031e 7661 // check if the LHS reference is a parameter, mark it as used if it is
7662 ref->refd_param_usage_found();
970ed795
EL
7663 FieldOrArrayRefs *t_subrefs = ref->get_subrefs();
7664 const bool rhs_copied = self_ref;
7665 switch (asstype) {
7666 case ASS_VAR: {
7667 const string& rhs_copy = val->get_temporary_id();
7668 string rhs_ref = rhs_copy;
7669 if (rhs_copied /*&& val->get_valuetype() == Value::V_CHOICE*/) {
7670 if (val->get_my_governor()->is_optional_field()) {
7671 str = mputprintf(str, "{\nOPTIONAL<%s> %s;\n",
7672 val->get_my_governor()->get_genname_value(val->get_my_scope()).c_str(), rhs_copy.c_str());
7673 rhs_ref += "()";
7674 } else {
7675 str = mputprintf(str, "{\n%s %s;\n",
7676 val->get_my_governor()->get_genname_value(val->get_my_scope()).c_str(), rhs_copy.c_str());
7677 }
7678 }
7679 bool needs_conv = use_runtime_2 && TypeConv::needs_conv_refd(val);
7680 if (needs_conv) {
7681 case3:
7682 // Most complicated case. The LHS is saved in a temporary reference,
7683 // in case we need to access it more than once, e.g:
7684 // x2[1] := { f1 := ..., f2 := ... } in TTCN-3 becomes
7685 // rectype& tmp = x2[1]; tmp.f1() = ...; tmp.f2() = ...;
7686 // This saves having to index x2 more than once.
7687 const string& tmp_id = val->get_temporary_id(); // For "ref".
7688 const char *tmp_id_str = tmp_id.c_str();
7689 const string& type_genname =
7690 val->get_my_governor()->get_genname_value(val->get_my_scope());
7691 const char *type_genname_str = type_genname.c_str();
7692 expression_struct expr;
7693 Code::init_expr(&expr);
7694 ref->generate_code(&expr);
7695
7696 if (rhs_copied) {
7697 if (needs_conv)
7698 str = TypeConv::gen_conv_code_refd(str, rhs_ref.c_str(), val);
7699 else str = val->generate_code_init(str, rhs_ref.c_str());
7700 }
7701
7702 str = mputstr(str, "{\n");
7703 str = mputstr(str, expr.preamble);
7704 if (t_subrefs && t_subrefs->refers_to_string_element()) {
7705 // The LHS is a string element.
7706 str = mputprintf(str, "%s_ELEMENT %s(%s);\n", type_genname_str,
7707 tmp_id_str, expr.expr);
7708 } else {
7709 // The LHS is a normal value.
7710 str = mputprintf(str, "%s& %s = %s; /* 7388 */\n", type_genname_str,
7711 tmp_id_str, expr.expr);
7712 }
7713 str = mputstr(str, expr.postamble);
7714 // We now have a reference to the LHS. Generate the actual assignment
7715 if (rhs_copied) {
7716 str = mputprintf(str, "%s = %s;\n", tmp_id_str, rhs_copy.c_str());
7717 }
7718 else {
7719 if (needs_conv)
7720 str = TypeConv::gen_conv_code_refd(str, tmp_id_str, val);
7721 else str = val->generate_code_init(str, tmp_id_str);
7722 }
7723 Code::free_expr(&expr);
7724 str = mputstr(str, "}\n");
7725 }
7726 else {
7727 if (t_subrefs) {
7728 if (!val->has_single_expr()) goto case3;
7729 // C++ equivalent of RHS is a single expression.
7730 expression_struct expr;
7731 Code::init_expr(&expr);
7732 ref->generate_code(&expr);// vu.s()
7733 if (rhs_copied) {
7734 str = mputprintf(str, "%s = %s;\n",
7735 rhs_copy.c_str(), val->get_single_expr().c_str());
7736
7737 expr.expr = mputprintf(expr.expr, " = %s", rhs_copy.c_str());
7738 }
7739 else {
7740 expr.expr = mputprintf(expr.expr,
7741 " = %s", val->get_single_expr().c_str());
7742 }
7743 str = Code::merge_free_expr(str, &expr);
7744 }
7745 else {
7746 // The LHS is a single identifier.
7747 const string& rhs_name = ref->get_refd_assignment()
7748 ->get_genname_from_scope(ref->get_my_scope());
7749 if (val->can_use_increment(ref)) {
7750 switch (val->get_optype()) {
7751 case Value::OPTYPE_ADD:
7752 str = mputprintf(str, "++%s;\n", rhs_name.c_str());
7753 break;
7754 case Value::OPTYPE_SUBTRACT:
7755 str = mputprintf(str, "--%s;\n", rhs_name.c_str());
7756 break;
7757 default:
7758 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7759 }
7760 } else {
7761 str = val->generate_code_init(str,
7762 (rhs_copied ? rhs_copy : rhs_name).c_str());
7763
7764 if (rhs_copied) {
7765 str = mputprintf(str, "%s = %s;\n", rhs_name.c_str(), rhs_copy.c_str());
7766 }
7767 }
7768 }
7769 }
7770 if (rhs_copied) {
7771 str = mputstr(str, "}\n");
7772 }
7773 break; }
7774 case ASS_TEMPLATE: {
7775 const string& rhs_copy = templ->get_temporary_id();
7776 if (rhs_copied /*&& val->get_valuetype() == Value::V_CHOICE*/) {
7777 str = mputprintf(str, "{\n%s %s;\n",
7778 templ->get_my_governor()->get_genname_template(templ->get_my_scope()).c_str(), rhs_copy.c_str()//, rhs_copy.c_str()
7779 );
7780 }
7781 bool needs_conv = use_runtime_2 && TypeConv::needs_conv_refd(templ);
7782 if (needs_conv) { // case 3
7783 case3t:
7784 // Most complicated case. The LHS is saved in a temporary reference.
7785 const string& tmp_id = templ->get_temporary_id();
7786 const char *tmp_id_str = tmp_id.c_str();
7787 expression_struct expr;
7788 Code::init_expr(&expr);
7789 ref->generate_code(&expr);
7790
7791 if (rhs_copied) {
7792 if (needs_conv)
7793 str = TypeConv::gen_conv_code_refd(str, rhs_copy.c_str(), templ);
7794 else str = templ->generate_code_init(str, rhs_copy.c_str());
7795
7796 }
7797 str = mputstr(str, "{\n");
7798 str = mputstr(str, expr.preamble);
7799 str = mputprintf(str, "%s& %s = %s;\n",
7800 templ->get_my_governor()->get_genname_template(
7801 templ->get_my_scope()
7802 ).c_str(), tmp_id_str, expr.expr);
7803 str = mputstr(str, expr.postamble);
7804 if (rhs_copied) {
7805 str = mputprintf(str, "%s = %s;\n", tmp_id_str, rhs_copy.c_str());
7806 }
7807 else {
7808 if (needs_conv)
7809 str = TypeConv::gen_conv_code_refd(str, tmp_id_str, templ);
7810 else {
7811 if (Common::Type::T_SEQOF == templ->get_my_governor()->get_typetype() ||
7812 Common::Type::T_ARRAY == templ->get_my_governor()->get_typetype()) {
7813 str = mputprintf(str, "%s.remove_all_permutations();\n", tmp_id_str);
7814 }
7815 str = templ->generate_code_init(str, tmp_id_str);
7816 }
7817 }
7818 Code::free_expr(&expr);
7819
7820 if (template_restriction != TR_NONE && gen_restriction_check)
7821 str = Template::generate_restriction_check_code(str,
7822 tmp_id_str, template_restriction);
7823 str = mputstr(str, "}\n");
7824 }
7825 else { // !needs_conv
7826 if (t_subrefs) {
7827 if ((template_restriction == TR_NONE || !gen_restriction_check)
7828 && templ->has_single_expr()) {
7829 // C++ equivalent of RHS is a single expression and no restriction
7830 // check. Skipped if conversion needed.
7831 expression_struct expr;
7832 Code::init_expr(&expr);
7833 ref->generate_code(&expr);
7834 if (rhs_copied) {
7835 str = mputprintf(str, "%s = %s;\n",
7836 rhs_copy.c_str(), templ->get_single_expr(false).c_str());
7837
7838 expr.expr = mputprintf(expr.expr, " = %s", rhs_copy.c_str());
7839 }
7840 else {
7841 expr.expr = mputprintf(expr.expr,
7842 " = %s", templ->get_single_expr(false).c_str());
7843 }
7844 str = Code::merge_free_expr(str, &expr); // will add a semicolon
7845 }
7846 else goto case3t;
7847 }
7848 else {
7849 // LHS is a single identifier
7850 const string& rhs_name = ref->get_refd_assignment()
7851 ->get_genname_from_scope(ref->get_my_scope());
7852 if (Common::Type::T_SEQOF == templ->get_my_governor()->get_typetype() ||
7853 Common::Type::T_ARRAY == templ->get_my_governor()->get_typetype()) {
7854 str = mputprintf(str, "%s.remove_all_permutations();\n", (rhs_copied ? rhs_copy : rhs_name).c_str());
7855 }
7856 str = templ->generate_code_init(str,
7857 (rhs_copied ? rhs_copy : rhs_name).c_str());
7858 if (rhs_copied) {
7859 str = mputprintf(str, "%s = %s;\n", rhs_name.c_str(), rhs_copy.c_str());
7860 }
7861 if (template_restriction != TR_NONE && gen_restriction_check)
7862 str = Template::generate_restriction_check_code(str,
7863 ref->get_refd_assignment()->get_genname_from_scope(
7864 ref->get_my_scope()
7865 ).c_str(), template_restriction);
7866 }
7867 }
7868 if (rhs_copied) {
7869 str = mputstr(str, "}\n");
7870 }
7871 break; }
7872 default:
7873 FATAL_ERROR("Ttcn::Assignment::generate_code()");
7874 } // switch
7875 return str;
7876 }
7877
7878 // =================================
7879 // ===== ParamAssignment
7880 // =================================
7881
7882 ParamAssignment::ParamAssignment(Identifier *p_id, Reference *p_ref)
7883 : Node(), Location(), id(p_id), ref(p_ref)
7884 {
7885 if(!id || !ref) FATAL_ERROR("Ttcn::ParamAssignment::ParamAssignment()");
7886 }
7887
7888 ParamAssignment::~ParamAssignment()
7889 {
7890 delete id;
7891 delete ref;
7892 }
7893
7894 ParamAssignment *ParamAssignment::clone() const
7895 {
7896 FATAL_ERROR("ParamAssignment::clone");
7897 }
7898
7899 void ParamAssignment::set_my_scope(Scope *p_scope)
7900 {
7901 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::set_my_scope()");
7902 ref->set_my_scope(p_scope);
7903 }
7904
7905 void ParamAssignment::set_fullname(const string& p_fullname)
7906 {
7907 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::set_fullname()");
7908 ref->set_fullname(p_fullname);
7909 }
7910
7911 Reference *ParamAssignment::get_ref() const
7912 {
7913 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::get_ref()");
7914 return ref;
7915 }
7916
7917 Reference *ParamAssignment::steal_ref()
7918 {
7919 if (!ref) FATAL_ERROR("Ttcn::ParamAssignment::steal_ref()");
7920 Reference *ret_val = ref;
7921 ref = 0;
7922 return ret_val;
7923 }
7924
7925 // =================================
7926 // ===== ParamAssignments
7927 // =================================
7928
7929 ParamAssignments::~ParamAssignments()
7930 {
7931 for(size_t i=0; i<parasss.size(); i++)
7932 delete parasss[i];
7933 parasss.clear();
7934 }
7935
7936 ParamAssignments *ParamAssignments::clone() const
7937 {
7938 FATAL_ERROR("ParamAssignments::clone");
7939 }
7940
7941 void ParamAssignments::set_my_scope(Scope *p_scope)
7942 {
7943 for(size_t i=0; i<parasss.size(); i++)
7944 parasss[i]->set_my_scope(p_scope);
7945 }
7946
7947 void ParamAssignments::set_fullname(const string& p_fullname)
7948 {
7949 Node::set_fullname(p_fullname);
7950 for(size_t i=0; i<parasss.size(); i++)
7951 parasss[i]->set_fullname(p_fullname+".parass_"+Int2string(i+1));
7952 }
7953
7954 void ParamAssignments::add_parass(ParamAssignment *p_parass)
7955 {
7956 if(!p_parass)
7957 FATAL_ERROR("ParamAssignments::add_parass()");
7958 parasss.add(p_parass);
7959 }
7960
7961 // =================================
7962 // ===== VariableEntry
7963 // =================================
7964
7965 VariableEntry::VariableEntry(Reference *p_ref)
7966 : Node(), Location(), ref(p_ref)
7967 {
7968 if(!ref) FATAL_ERROR("VariableEntry::VariableEntry()");
7969 }
7970
7971 VariableEntry::~VariableEntry()
7972 {
7973 delete ref;
7974 }
7975
7976 VariableEntry *VariableEntry::clone() const
7977 {
7978 FATAL_ERROR("VariableEntry::clone");
7979 }
7980
7981 void VariableEntry::set_my_scope(Scope *p_scope)
7982 {
7983 if(ref) ref->set_my_scope(p_scope);
7984 }
7985
7986 void VariableEntry::set_fullname(const string& p_fullname)
7987 {
7988 Node::set_fullname(p_fullname);
7989 if(ref) ref->set_fullname(p_fullname+".ref");
7990 }
7991
7992 // =================================
7993 // ===== VariableEntries
7994 // =================================
7995
7996 VariableEntries::~VariableEntries()
7997 {
7998 for(size_t i=0; i<ves.size(); i++)
7999 delete ves[i];
8000 ves.clear();
8001 }
8002
8003 VariableEntries *VariableEntries::clone() const
8004 {
8005 FATAL_ERROR("VariableEntries::clone");
8006 }
8007
8008 void VariableEntries::set_my_scope(Scope *p_scope)
8009 {
8010 for(size_t i=0; i<ves.size(); i++)
8011 ves[i]->set_my_scope(p_scope);
8012 }
8013
8014 void VariableEntries::set_fullname(const string& p_fullname)
8015 {
8016 Node::set_fullname(p_fullname);
8017 for(size_t i=0; i<ves.size(); i++)
8018 ves[i]->set_fullname(p_fullname+".ve_"+Int2string(i+1));
8019 }
8020
8021 void VariableEntries::add_ve(VariableEntry *p_ve)
8022 {
8023 if(!p_ve)
8024 FATAL_ERROR("VariableEntries::add_ve()");
8025 ves.add(p_ve);
8026 }
8027
8028 // =================================
8029 // ===== ParamRedirect
8030 // =================================
8031
8032 ParamRedirect::ParamRedirect(ParamAssignments *p_parasss)
8033 : Node(), Location(), parredirtype(P_ASS), parasss(p_parasss)
8034 {
8035 if(!parasss) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8036 }
8037
8038 ParamRedirect::ParamRedirect(VariableEntries *p_ves)
8039 : Node(), Location(), parredirtype(P_VAR), ves(p_ves)
8040 {
8041 if(!ves) FATAL_ERROR("ParamRedirect::ParamRedirect()");
8042 }
8043
8044 ParamRedirect::~ParamRedirect()
8045 {
8046 switch(parredirtype) {
8047 case P_ASS:
8048 delete parasss;
8049 break;
8050 case P_VAR:
8051 delete ves;
8052 break;
8053 default:
8054 FATAL_ERROR("ParamRedirect::~ParamRedirect()");
8055 } // switch
8056 }
8057
8058 ParamRedirect *ParamRedirect::clone() const
8059 {
8060 FATAL_ERROR("ParamRedirect::clone");
8061 }
8062
8063 void ParamRedirect::set_my_scope(Scope *p_scope)
8064 {
8065 switch(parredirtype) {
8066 case P_ASS:
8067 parasss->set_my_scope(p_scope);
8068 break;
8069 case P_VAR:
8070 ves->set_my_scope(p_scope);
8071 break;
8072 default:
8073 FATAL_ERROR("ParamRedirect::set_my_scope()");
8074 } // switch
8075 }
8076
8077 void ParamRedirect::set_fullname(const string& p_fullname)
8078 {
8079 Node::set_fullname(p_fullname);
8080 switch(parredirtype) {
8081 case P_ASS:
8082 parasss->set_fullname(p_fullname+".parasss");
8083 break;
8084 case P_VAR:
8085 ves->set_fullname(p_fullname+".parvars");
8086 break;
8087 default:
8088 FATAL_ERROR("ParamRedirect::set_fullname()");
8089 } // switch
8090 }
8091
8092 void ParamRedirect::chk_erroneous()
8093 {
8094 Error_Context cntxt(this, "In parameter redirect");
8095 switch(parredirtype) {
8096 case P_ASS: {
8097 map<string, ParamAssignment> parass_m;
8098 for (size_t i = 0; i < parasss->get_nof_parasss(); i++) {
8099 ParamAssignment *t_parass = parasss->get_parass_byIndex(i);
8100 const Identifier &t_id = t_parass->get_id();
8101 const string& name = t_id.get_name();
8102 const char *dispname_str = t_id.get_dispname().c_str();
8103 if (parass_m.has_key(name)) {
8104 t_parass->error("Duplicate redirect for parameter `%s'",
8105 dispname_str);
8106 parass_m[name]->note("A variable entry for parameter `%s' is "
8107 "already given here", dispname_str);
8108 } else parass_m.add(name, t_parass);
8109 Error_Context cntxt2(t_parass, "In redirect for parameter `%s'",
8110 dispname_str);
8111 chk_variable_ref(t_parass->get_ref(), 0);
8112 }
8113 parass_m.clear();
8114 break; }
8115 case P_VAR:
8116 for (size_t i = 0; i < ves->get_nof_ves(); i++) {
8117 VariableEntry *t_ve = ves->get_ve_byIndex(i);
8118 Error_Context cntxt2(t_ve, "In variable entry #%lu",
8119 (unsigned long) (i + 1));
8120 chk_variable_ref(t_ve->get_ref(), 0);
8121 }
8122 break;
8123 default:
8124 FATAL_ERROR("ParamRedirect::chk_erroneous()");
8125 } // switch
8126 }
8127
8128 void ParamRedirect::chk(Type *p_sig, bool is_out)
8129 {
8130 SignatureParamList *t_parlist = p_sig->get_signature_parameters();
8131 if (t_parlist) {
8132 Error_Context cntxt(this, "In parameter redirect");
8133 switch (parredirtype) {
8134 case P_ASS:
8135 chk_parasss(p_sig, t_parlist, is_out);
8136 break;
8137 case P_VAR:
8138 chk_ves(p_sig, t_parlist, is_out);
8139 break;
8140 default:
8141 FATAL_ERROR("ParamRedirect::chk()");
8142 }
8143 } else {
8144 error("Parameter redirect cannot be used because signature `%s' "
8145 "does not have parameters", p_sig->get_typename().c_str());
8146 chk_erroneous();
8147 }
8148 }
8149
8150 void ParamRedirect::chk_parasss(Type *p_sig, SignatureParamList *p_parlist,
8151 bool is_out)
8152 {
8153 map<string, ParamAssignment> parass_m;
8154 bool error_flag = false;
8155 for (size_t i = 0; i < parasss->get_nof_parasss(); i++) {
8156 ParamAssignment *t_parass = parasss->get_parass_byIndex(i);
8157 const Identifier &t_id = t_parass->get_id();
8158 const string& name = t_id.get_name();
8159 const char *dispname_str = t_id.get_dispname().c_str();
8160 if (parass_m.has_key(name)) {
8161 t_parass->error("Duplicate redirect for parameter `%s'",
8162 dispname_str);
8163 parass_m[name]->note("A variable entry for parameter `%s' is "
8164 "already given here", dispname_str);
8165 error_flag = true;
8166 } else parass_m.add(name, t_parass);
8167 Error_Context cntxt2(t_parass, "In redirect for parameter `%s'",
8168 dispname_str);
8169 if (p_parlist->has_param_withName(t_id)) {
8170 const SignatureParam *t_par = p_parlist->get_param_byName(t_id);
8171 SignatureParam::param_direction_t t_dir = t_par->get_direction();
8172 if (is_out) {
8173 if (t_dir == SignatureParam::PARAM_IN) {
8174 t_parass->error("Parameter `%s' of signature `%s' has `in' "
8175 "direction", dispname_str, p_sig->get_typename().c_str());
8176 error_flag = true;
8177 }
8178 } else {
8179 if (t_dir == SignatureParam::PARAM_OUT) {
8180 t_parass->error("Parameter `%s' of signature `%s' has `out' "
8181 "direction", dispname_str, p_sig->get_typename().c_str());
8182 error_flag = true;
8183 }
8184 }
8185 chk_variable_ref(t_parass->get_ref(), t_par->get_type());
8186 } else {
8187 t_parass->error("Signature `%s' does not have parameter named `%s'",
8188 p_sig->get_typename().c_str(), dispname_str);
8189 error_flag = true;
8190 chk_variable_ref(t_parass->get_ref(), 0);
8191 }
8192 }
8193 if (!error_flag) {
8194 // converting the AssignmentList to VariableList
8195 VariableEntries *t_ves = new VariableEntries;
8196 size_t upper_limit = is_out ?
8197 p_parlist->get_nof_out_params() : p_parlist->get_nof_in_params();
8198 for (size_t i = 0; i < upper_limit; i++) {
8199 SignatureParam *t_par = is_out ? p_parlist->get_out_param_byIndex(i)
8200 : p_parlist->get_in_param_byIndex(i);
8201 const string& name = t_par->get_id().get_name();
8202 if (parass_m.has_key(name))
8203 t_ves->add_ve(new VariableEntry(parass_m[name]->steal_ref()));
8204 else t_ves->add_ve(new VariableEntry);
8205 }
8206 delete parasss;
8207 ves = t_ves;
8208 parredirtype = P_VAR;
8209 }
8210 parass_m.clear();
8211 }
8212
8213 void ParamRedirect::chk_ves(Type *p_sig, SignatureParamList *p_parlist,
8214 bool is_out)
8215 {
8216 size_t nof_ves = ves->get_nof_ves();
8217 size_t nof_pars = is_out ?
8218 p_parlist->get_nof_out_params() : p_parlist->get_nof_in_params();
8219 if (nof_ves != nof_pars) {
8220 error("Too %s variable entries compared to the number of %s/inout "
8221 "parameters in signature `%s': %lu was expected instead of %lu",
8222 nof_ves > nof_pars ? "many" : "few", is_out ? "out" : "in",
8223 p_sig->get_typename().c_str(), (unsigned long) nof_pars,
8224 (unsigned long) nof_ves);
8225 }
8226 for (size_t i = 0; i < nof_ves; i++) {
8227 VariableEntry *t_ve = ves->get_ve_byIndex(i);
8228 if (i < nof_pars) {
8229 SignatureParam *t_par = is_out ? p_parlist->get_out_param_byIndex(i)
8230 : p_parlist->get_in_param_byIndex(i);
8231 Error_Context cntxt(t_ve, "In variable entry #%lu (for parameter `%s')",
8232 (unsigned long) (i + 1), t_par->get_id().get_dispname().c_str());
8233 chk_variable_ref(t_ve->get_ref(), t_par->get_type());
8234 } else {
8235 Error_Context cntxt(t_ve, "In variable entry #%lu",
8236 (unsigned long) (i + 1));
8237 chk_variable_ref(t_ve->get_ref(), 0);
8238 }
8239 }
8240 }
8241
8242 void ParamRedirect::chk_variable_ref(Reference *p_ref, Type *p_type)
8243 {
8244 if (!p_ref) return;
8245 Type *t_var_type = p_ref->chk_variable_ref();
8246 if (p_type && t_var_type && !p_type->is_identical(t_var_type)) {
8247 p_ref->error("Type mismatch in parameter redirect: "
8248 "A variable of type `%s' was expected instead of `%s'",
8249 p_type->get_typename().c_str(),
8250 t_var_type->get_typename().c_str());
8251 }
8252 }
8253
8254 void ParamRedirect::set_code_section(
8255 GovernedSimple::code_section_t p_code_section)
8256 {
8257 // code can be generated from VariableList only
8258 switch (parredirtype) {
8259 case P_ASS:
8260 break;
8261 case P_VAR:
8262 for (size_t i = 0; i < ves->get_nof_ves(); i++) {
8263 Reference *t_ref = ves->get_ve_byIndex(i)->get_ref();
8264 if (t_ref) t_ref->set_code_section(p_code_section);
8265 }
8266 break;
8267 default:
8268 FATAL_ERROR("ParamRedirect::set_code_section()");
8269 }
8270 }
8271
8272 void ParamRedirect::generate_code(expression_struct_t *expr)
8273 {
8274 // AssignmentList is converted to VariableList during checking
8275 if (parredirtype != P_VAR) FATAL_ERROR("ParamRedirect::generate_code()");
8276 for (size_t i = 0; i < ves->get_nof_ves(); i++) {
8277 if (i > 0) expr->expr = mputstr(expr->expr, ", ");
8278 Reference *ref = ves->get_ve_byIndex(i)->get_ref();
8279 if (ref) {
8280 // the variable reference is present
8281 expr->expr = mputstr(expr->expr, "&(");
8282 ref->generate_code(expr);
8283 expr->expr = mputc(expr->expr, ')');
8284 } else expr->expr = mputstr(expr->expr, "NULL");
8285 }
8286 }
8287
8288 // =================================
8289 // ===== LogArgument
8290 // =================================
8291
8292 LogArgument::LogArgument(TemplateInstance *p_ti)
8293 : logargtype(L_UNDEF)
8294 {
8295 if (!p_ti) FATAL_ERROR("LogArgument::LogArgument()");
8296 ti = p_ti;
8297 }
8298
8299 LogArgument::~LogArgument()
8300 {
8301 switch (logargtype) {
8302 case L_ERROR:
8303 break;
8304 case L_UNDEF:
8305 case L_TI:
8306 delete ti;
8307 break;
8308 case L_VAL:
8309 case L_MATCH:
8310 case L_MACRO:
8311 delete val;
8312 break;
8313 case L_REF:
8314 delete ref;
8315 break;
8316 case L_STR:
8317 delete cstr;
8318 break;
8319 default:
8320 FATAL_ERROR("LogArgument::~LogArgument()");
8321 } // switch
8322 }
8323
8324 LogArgument *LogArgument::clone() const
8325 {
8326 FATAL_ERROR("LogArgument::clone");
8327 }
8328
8329 void LogArgument::set_my_scope(Scope *p_scope)
8330 {
8331 switch (logargtype) {
8332 case L_ERROR:
8333 break;
8334 case L_UNDEF:
8335 case L_TI:
8336 ti->set_my_scope(p_scope);
8337 break;
8338 case L_VAL:
8339 case L_MATCH:
8340 case L_MACRO:
8341 val->set_my_scope(p_scope);
8342 break;
8343 case L_REF:
8344 ref->set_my_scope(p_scope);
8345 break;
8346 case L_STR:
8347 break;
8348 default:
8349 FATAL_ERROR("LogArgument::set_my_scope()");
8350 } // switch
8351 }
8352
8353 void LogArgument::set_fullname(const string& p_fullname)
8354 {
8355 Node::set_fullname(p_fullname);
8356 switch (logargtype) {
8357 case L_ERROR:
8358 break;
8359 case L_UNDEF:
8360 case L_TI:
8361 ti->set_fullname(p_fullname);
8362 break;
8363 case L_VAL:
8364 case L_MATCH:
8365 case L_MACRO:
8366 val->set_fullname(p_fullname);
8367 break;
8368 case L_REF:
8369 ref->set_fullname(p_fullname);
8370 break;
8371 case L_STR:
8372 break;
8373 default:
8374 FATAL_ERROR("LogArgument::set_fullname()");
8375 } // switch
8376 }
8377
8378 const string& LogArgument::get_str() const
8379 {
8380 if (logargtype != L_STR) FATAL_ERROR("LogArgument::get_str()");
8381 return *cstr;
8382 }
8383
8384 Value *LogArgument::get_val() const
8385 {
8386 switch (logargtype) {
8387 case L_VAL:
8388 case L_MATCH:
8389 case L_MACRO:
8390 break;
8391 default:
8392 FATAL_ERROR("LogArgument::get_val()");
8393 }
8394 return val;
8395 }
8396
8397 Ref_base *LogArgument::get_ref() const
8398 {
8399 if (logargtype != L_REF) FATAL_ERROR("LogArgument::get_ref()");
8400 return ref;
8401 }
8402
8403 TemplateInstance *LogArgument::get_ti() const
8404 {
8405 if (logargtype != L_TI) FATAL_ERROR("LogArgument::get_ref()");
8406 return ti;
8407 }
8408
8409 void LogArgument::append_str(const string& p_str)
8410 {
8411 if (logargtype != L_STR) FATAL_ERROR("LogArgument::append_str()");
8412 *cstr += p_str;
8413 }
8414
8415 void LogArgument::chk() // determine the proper type of the log argument
8416 {
8417 if (logargtype != L_UNDEF) return;
8418 Template *t_templ = ti->get_Template();
8419 t_templ = t_templ->get_template_refd_last();
8420 t_templ->set_lowerid_to_ref();
8421 if (!ti->get_Type() && !ti->get_DerivedRef() && t_templ->is_Value()) {
8422 // drop the template instance and keep only the embedded value
8423 Value *t_val = t_templ->get_Value();
8424 delete ti;
8425 logargtype = L_VAL;
8426 val = t_val;
8427 chk_val();
8428 } else {
8429 // try to obtain the governor of the template instance
8430 Type *governor = ti->get_expr_governor(Type::EXPECTED_TEMPLATE);
8431 if (!governor) {
8432 // the governor is still unknown: an error occurred
8433 // try to interpret possible enum values as references
8434 t_templ->set_lowerid_to_ref();
8435 governor = t_templ->get_expr_governor(Type::EXPECTED_TEMPLATE);
8436 }
8437 if (governor) {
8438 logargtype = L_TI;
8439 ti->chk(governor);
8440 } else {
8441 t_templ->error("Cannot determine the type of the argument");
8442 delete ti;
8443 logargtype = L_ERROR;
8444 }
8445 }
8446 }
8447
8448 void LogArgument::chk_ref()
8449 {
8450 Common::Assignment *t_ass = ref->get_refd_assignment();
8451 if (!t_ass) return;
8452 Common::Assignment::asstype_t asstype = t_ass->get_asstype();
8453 switch (asstype) {
8454 case Common::Assignment::A_FUNCTION_RVAL:
8455 case Common::Assignment::A_FUNCTION_RTEMP:
8456 case Common::Assignment::A_EXT_FUNCTION_RVAL:
8457 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
8458 ref->get_my_scope()->chk_runs_on_clause(t_ass, *this, "call");
8459 case Common::Assignment::A_CONST:
8460 case Common::Assignment::A_EXT_CONST:
8461 case Common::Assignment::A_MODULEPAR:
8462 case Common::Assignment::A_MODULEPAR_TEMP:
8463 case Common::Assignment::A_TEMPLATE:
8464 case Common::Assignment::A_VAR:
8465 case Common::Assignment::A_VAR_TEMPLATE:
8466 case Common::Assignment::A_PAR_VAL_IN:
8467 case Common::Assignment::A_PAR_VAL_OUT:
8468 case Common::Assignment::A_PAR_VAL_INOUT:
8469 case Common::Assignment::A_PAR_TEMPL_IN:
8470 case Common::Assignment::A_PAR_TEMPL_OUT:
8471 case Common::Assignment::A_PAR_TEMPL_INOUT: {
8472 // the reference points to a value or template-like entity
8473 // checking sub-references
8474 FieldOrArrayRefs *subrefs = ref->get_subrefs();
8475 if (subrefs && t_ass->get_Type()->get_field_type(subrefs,
8476 Type::EXPECTED_DYNAMIC_VALUE)) {
8477 // subrefs seems to be correct
8478 // also checking the presence of referred fields if possible
8479 if (asstype == Common::Assignment::A_CONST) {
8480 ReferenceChain refch(ref, "While searching referenced value");
8481 t_ass->get_Value()->get_refd_sub_value(subrefs, 0, false, &refch);
8482 } else if (asstype == Common::Assignment::A_TEMPLATE) {
8483 ReferenceChain refch(ref, "While searching referenced template");
8484 t_ass->get_Template()
8485 ->get_refd_sub_template(subrefs, false, &refch);
8486 }
8487 }
8488 break; }
8489 case Common::Assignment::A_TIMER:
8490 case Common::Assignment::A_PORT: {
8491 ArrayDimensions *t_dims = t_ass->get_Dimensions();
8492 if (t_dims) t_dims->chk_indices(ref, t_ass->get_assname(), true,
8493 Type::EXPECTED_DYNAMIC_VALUE);
8494 else if (ref->get_subrefs()) ref->error("Reference to single %s "
8495 "cannot have field or array sub-references",
8496 t_ass->get_description().c_str());
8497 break; }
8498 case Common::Assignment::A_PAR_TIMER:
8499 case Common::Assignment::A_PAR_PORT:
8500 if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
8501 "field or array sub-references", t_ass->get_description().c_str());
8502 break;
8503 case Common::Assignment::A_FUNCTION:
8504 case Common::Assignment::A_EXT_FUNCTION:
8505 ref->error("Reference to a value, template, timer or port was expected "
8506 "instead of a call of %s, which does not have return type",
8507 t_ass->get_description().c_str());
8508 break;
8509 default:
8510 ref->error("Reference to a value, template, timer or port was expected "
8511 "instead of %s", t_ass->get_description().c_str());
8512 }
8513 }
8514
8515 void LogArgument::chk_val()
8516 {
8517 // literal enumerated values cannot appear in this context
8518 val->set_lowerid_to_ref();
8519 switch (val->get_valuetype()) {
8520 case Value::V_CSTR: {
8521 string *t_cstr = new string(val->get_val_str());
8522 delete val;
8523 cstr = t_cstr;
8524 logargtype = L_STR;
8525 return; }
8526 case Value::V_REFD: {
8527 Ref_base *t_ref = val->steal_ttcn_ref_base();
8528 delete val;
8529 ref = t_ref;
8530 logargtype = L_REF;
8531 chk_ref();
8532 return; }
8533 case Value::V_EXPR:
8534 if (val->get_optype() == Value::OPTYPE_MATCH) logargtype = L_MATCH;
8535 else logargtype = L_VAL;
8536 break;
8537 case Value::V_MACRO:
8538 logargtype = L_MACRO;
8539 break;
8540 default:
8541 logargtype = L_VAL;
8542 } // switch
8543 Type *governor = val->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
8544 if (governor) {
8545 val->set_my_governor(governor);
8546 (void)governor->chk_this_value(val, 0, Type::EXPECTED_DYNAMIC_VALUE,
8547 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
8548 if (logargtype == L_VAL && val->get_valuetype() == Value::V_CSTR
8549 && !val->is_unfoldable()) { // string value known at compile time
8550 string *t_cstr = new string(val->get_val_str());
8551 delete val;
8552 cstr = t_cstr;
8553 logargtype = L_STR;
8554 return;
8555 }
8556 if (logargtype == L_MACRO) {
8557 switch (val->get_valuetype()) {
8558 case Value::V_CSTR: {
8559 // the macro was evaluated to a charstring value
8560 string *t_cstr = new string(val->get_val_str());
8561 delete val;
8562 cstr = t_cstr;
8563 logargtype = L_STR;
8564 break; }
8565 case Value::V_MACRO:
8566 // the macro could not be evaluated at compile time
8567 // leave logargtype as is
8568 break;
8569 default:
8570 // the macro was evaluated to other value (e.g. integer)
8571 logargtype = L_VAL;
8572 }
8573 }
8574 } else {
8575 val->error("Cannot determine the type of the argument");
8576 delete val;
8577 logargtype = L_ERROR;
8578 }
8579 }
8580
8581 void LogArgument::dump(unsigned int level) const
8582 {
8583 Node::dump(level++);
8584 switch (logargtype) {
8585 case L_ERROR:
8586 DEBUG(level, "*error*");
8587 break;
8588 case L_UNDEF:
8589 DEBUG(level, "*undef*");
8590 break;
8591 case L_TI:
8592 DEBUG(level, "TemplateInstance");
8593 break;
8594 case L_VAL:
8595 val->dump(level);
8596 break;
8597 case L_MATCH:
8598 DEBUG(level, "Match");
8599 break;
8600 case L_MACRO:
8601 DEBUG(level, "Macro");
8602 break;
8603 case L_REF:
8604 DEBUG(level, "Reference");
8605 break;
8606 case L_STR:
8607 DEBUG(level, "String=`%s'", cstr->c_str());
8608 break;
8609 default:
8610 FATAL_ERROR("LogArgument::~LogArgument()");
8611 } // switch
8612 }
8613
8614 void LogArgument::set_code_section(
8615 GovernedSimple::code_section_t p_code_section)
8616 {
8617 switch (logargtype) {
8618 case L_UNDEF:
8619 case L_TI:
8620 ti->set_code_section(p_code_section);
8621 break;
8622 case L_VAL:
8623 case L_MATCH:
8624 case L_MACRO:
8625 val->set_code_section(p_code_section);
8626 break;
8627 case L_REF:
8628 ref->set_code_section(p_code_section);
8629 break;
8630 case L_STR:
8631 case L_ERROR:
8632 break;
8633 default:
8634 FATAL_ERROR("LogArgument::set_code_section()");
8635 } // switch
8636 }
8637
8638 char *LogArgument::generate_code_log(char *str)
8639 {
8640 expression_struct expr;
8641 Code::init_expr(&expr);
8642 generate_code_expr(&expr);
8643 str = Code::merge_free_expr(str, &expr);
8644 return str;
8645 }
8646
8647 void LogArgument::chk_recursions(ReferenceChain& refch)
8648 {
8649 switch (logargtype) {
8650 case L_UNDEF:
8651 case L_TI:
8652 ti->chk_recursions(refch);
8653 break;
8654 case L_VAL:
8655 case L_MATCH:
8656 case L_MACRO:
8657 val->chk_recursions(refch);
8658 break;
8659 case L_REF: {
8660 Common::Assignment *ass = ref->get_refd_assignment();
8661 if (!ass) break;
8662 refch.add(ass->get_fullname());
8663 } break;
8664 case L_STR:
8665 case L_ERROR:
8666 break;
8667 default:
8668 FATAL_ERROR("LogArgument::chk_recursions()");
8669 } // switch
8670 }
8671
8672 bool LogArgument::has_single_expr()
8673 {
8674 switch (logargtype) {
8675 case L_UNDEF:
8676 case L_TI:
8677 return ti->has_single_expr();
8678 case L_VAL:
8679 case L_MATCH:
8680 case L_MACRO:
8681 return ( val->has_single_expr() && !val->explicit_cast_needed() );
8682 case L_REF: {
8683 Common::Assignment *ass = ref->get_refd_assignment();
8684 switch (ass->get_asstype()) {
8685 case Common::Assignment::A_CONST:
8686 case Common::Assignment::A_EXT_CONST:
8687 return ref->has_single_expr();
8688 default:
8689 return false;
8690 }
8691 break; }
8692 case L_STR:
8693 case L_ERROR:
8694 return true;
8695 default:
8696 FATAL_ERROR("LogArgument::has_single_expr()");
8697 } // switch
8698 return true;
8699 }
8700
8701 void LogArgument::generate_code_expr(expression_struct *expr)
8702 {
8703 switch(logargtype) {
8704 case L_TI: {
8705 if (ti->is_only_specific_value()) {
8706 // use the embedded specific value for code generation
8707 ti->get_Template()->get_specific_value()->generate_code_log(expr);
8708 } else {
8709 ti->generate_code(expr);
8710 expr->expr = mputstr(expr->expr, ".log()");
8711 }
8712 break; }
8713 case L_VAL:
8714 val->generate_code_log(expr);
8715 break;
8716 case L_MATCH:
8717 val->generate_code_log_match(expr);
8718 break;
8719 case L_MACRO:
8720 if (val->has_single_expr()) {
8721 expr->expr = mputprintf(expr->expr, "TTCN_Logger::log_event_str(%s)",
8722 val->get_single_expr().c_str());
8723 } else val->generate_code_log(expr);
8724 break;
8725 case L_REF: {
8726 ref->generate_code_const_ref(expr);
8727 expr->expr=mputstr(expr->expr, ".log()");
8728 break;}
8729 case L_STR: {
8730 size_t str_len = cstr->size();
8731 const char *str_ptr = cstr->c_str();
8732 switch (str_len) {
8733 case 0:
8734 // the string is empty: do not generate any code
8735 case 1:
8736 // the string has one character: use log_char member
8737 expr->expr = mputstr(expr->expr, "TTCN_Logger::log_char('");
8738 expr->expr = Code::translate_character(expr->expr, *str_ptr, false);
8739 expr->expr = mputstr(expr->expr, "')");
8740 break;
8741 default:
8742 // the string has more characters: use log_event_str member
8743 expr->expr = mputstr(expr->expr, "TTCN_Logger::log_event_str(\"");
8744 expr->expr = Code::translate_string(expr->expr, str_ptr);
8745 expr->expr = mputstr(expr->expr, "\")");
8746 }
8747 break; }
8748 default:
8749 FATAL_ERROR("LogArgument::generate_code_expr()");
8750 } // switch
8751 }
8752
8753 // =================================
8754 // ===== LogArguments
8755 // =================================
8756
8757 LogArguments::~LogArguments()
8758 {
8759 for(size_t i=0; i<logargs.size(); i++) delete logargs[i];
8760 logargs.clear();
8761 }
8762
8763 LogArguments *LogArguments::clone() const
8764 {
8765 FATAL_ERROR("LogArguments::clone");
8766 }
8767
8768 void LogArguments::add_logarg(LogArgument *p_logarg)
8769 {
8770 if(!p_logarg)
8771 FATAL_ERROR("LogArguments::add_logarg()");
8772 logargs.add(p_logarg);
8773 }
8774
8775 void LogArguments::set_my_scope(Scope *p_scope)
8776 {
8777 for(size_t i=0; i<logargs.size(); i++)
8778 logargs[i]->set_my_scope(p_scope);
8779 }
8780
8781 void LogArguments::set_fullname(const string& p_fullname)
8782 {
8783 Node::set_fullname(p_fullname);
8784 for(size_t i=0; i<logargs.size(); i++)
8785 logargs[i]->set_fullname(p_fullname+".logargs_"+Int2string(i+1));
8786 }
8787
8788 void LogArguments::chk()
8789 {
8790 for(size_t i=0; i<logargs.size(); i++)
8791 logargs[i]->chk();
8792 }
8793
8794 void LogArguments::join_strings()
8795 {
8796 // points to the previous string argument otherwise it is NULL
8797 LogArgument *prev_arg = 0;
8798 for (size_t i = 0; i < logargs.size(); ) {
8799 LogArgument *arg = logargs[i];
8800 if (arg->get_type() == LogArgument::L_STR) {
8801 const string& str = arg->get_str();
8802 if (str.size() > 0) {
8803 // the current argument is a non-empty string
8804 if (prev_arg) {
8805 // append str to prev_arg and drop arg
8806 prev_arg->append_str(str);
8807 delete arg;
8808 logargs.replace(i, 1);
8809 // don't increment i
8810 } else {
8811 // keep it for the next iteration
8812 prev_arg = arg;
8813 i++;
8814 }
8815 } else {
8816 // the current argument is an empty string
8817 // simply drop it unless it is the only argument
8818 // note: we must distinguish between log() and log("")
8819 if (i > 0 || logargs.size() > 1) {
8820 delete arg;
8821 logargs.replace(i, 1);
8822 // don't increment i
8823 } else break;
8824 }
8825 } else {
8826 // the current argument is not a string
8827 // forget the previous arg
8828 prev_arg = 0;
8829 i++;
8830 }
8831 }
8832 }
8833
8834 void LogArguments::set_code_section(
8835 GovernedSimple::code_section_t p_code_section)
8836 {
8837 for (size_t i = 0; i < logargs.size(); i++)
8838 logargs[i]->set_code_section(p_code_section);
8839 }
8840
8841 char *LogArguments::generate_code(char *str)
8842 {
8843 for(size_t i=0; i<logargs.size(); i++)
8844 str=logargs[i]->generate_code_log(str);
8845 return str;
8846 }
8847
8848 void LogArguments::chk_recursions(ReferenceChain& refch)
8849 {
8850 for (size_t i=0; i<logargs.size(); i++) {
8851 refch.mark_state();
8852 logargs[i]->chk_recursions(refch);
8853 refch.prev_state();
8854 }
8855 }
8856
8857 bool LogArguments::has_single_expr()
8858 {
8859 bool i_have_single_expr = true;
8860 for (size_t i=0; i<logargs.size(); i++)
8861 i_have_single_expr = i_have_single_expr && logargs[i]->has_single_expr();
8862 return i_have_single_expr;
8863 }
8864
8865 void LogArguments::generate_code_expr(expression_struct *expr)
8866 {
8867 expr->expr = mputstr(expr->expr, "(TTCN_Logger::begin_event_log2str(),");
8868 for(size_t i=0; i<logargs.size(); i++) {
8869 logargs[i]->generate_code_expr(expr);
8870 expr->expr = mputc(expr->expr, ','); // comma operator
8871 }
8872 expr->expr = mputstr(expr->expr, "TTCN_Logger::end_event_log2str())");
8873 }
8874
8875 // =================================
8876 // ===== IfClause
8877 // =================================
8878
8879 IfClause::IfClause(Value *p_expr, StatementBlock *p_block)
8880 : expr(p_expr), block(p_block)
8881 {
8882 if(!expr || !block)
8883 FATAL_ERROR("IfClause::IfClause()");
8884 }
8885
8886 IfClause::~IfClause()
8887 {
8888 delete expr;
8889 delete block;
8890 }
8891
8892 IfClause *IfClause::clone() const
8893 {
8894 FATAL_ERROR("IfClause::clone");
8895 }
8896
8897 void IfClause::set_my_scope(Scope *p_scope)
8898 {
8899 expr->set_my_scope(p_scope);
8900 block->set_my_scope(p_scope);
8901 }
8902
8903 void IfClause::set_fullname(const string& p_fullname)
8904 {
8905 Node::set_fullname(p_fullname);
8906 expr->set_fullname(p_fullname+".expr");
8907 block->set_fullname(p_fullname+".block");
8908 }
8909
8910 bool IfClause::has_receiving_stmt() const
8911 {
8912 return block->has_receiving_stmt();
8913 }
8914
8915 void IfClause::chk(bool& unreach)
8916 {
8917 Error_Context cntxt(this, "In if statement");
8918 if(unreach) warning("Control never reaches this code because of"
8919 " previous effective condition(s)");
8920 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
8921 if(!expr->is_unfoldable()) {
8922 if(expr->get_val_bool()) unreach=true;
8923 else block->warning("Control never reaches this code because the"
8924 " conditional expression evaluates to false");
8925 }
8926 block->chk();
8927 }
8928
8929 void IfClause::set_code_section(
8930 GovernedSimple::code_section_t p_code_section)
8931 {
8932 expr->set_code_section(p_code_section);
8933 block->set_code_section(p_code_section);
8934 }
8935
8936 char* IfClause::generate_code(char *str, size_t& blockcount,
8937 bool& unreach, bool& eachfalse)
8938 {
8939 if(unreach) return str;
8940 if(!expr->is_unfoldable()) {
8941 if(expr->get_val_bool()) unreach=true;
8942 else return str;
8943 }
8944 if (!eachfalse) str = mputstr(str, "else ");
8945 if (!unreach) {
8946 if (!eachfalse) {
8947 str = mputstr(str, "{\n");
8948 blockcount++;
8949 }
8950 str = expr->update_location_object(str);
8951 str = expr->generate_code_tmp(str, "if (", blockcount);
8952 str = mputstr(str, ") ");
8953 }
8954 eachfalse = false;
8955 str=mputstr(str, "{\n");
8956 str=block->generate_code(str);
8957 str=mputstr(str, "}\n");
8958 return str;
8959 }
8960
8961 void IfClause::ilt_generate_code(ILT *ilt, const char *end_label,
8962 bool& unreach)
8963 {
8964 if(unreach) return;
8965 if(!expr->is_unfoldable()) {
8966 if(expr->get_val_bool()) unreach=true;
8967 else return;
8968 }
8969 char*& str=ilt->get_out_branches();
8970 char *label=0;
8971 if(!unreach) {
8972 size_t blockcount=0;
8973 label=mprintf("%s_l%lu",
8974 ilt->get_my_tmpid().c_str(),
8975 (unsigned long) ilt->get_new_label_num());
8976 str=expr->update_location_object(str);
8977 str=expr->generate_code_tmp(str, "if(!", blockcount);
8978 str=mputprintf(str, ") goto %s;\n", label);
8979 while(blockcount-->0) str=mputstr(str, "}\n");
8980 }
8981 block->ilt_generate_code(ilt);
8982 if(!unreach) {
8983 str=mputprintf(str, "goto %s;\n%s:\n",
8984 end_label, label);
8985 Free(label);
8986 }
8987 }
8988
8989 void IfClause::set_parent_path(WithAttribPath* p_path) {
8990 block->set_parent_path(p_path);
8991 }
8992
8993 void IfClause::dump(unsigned int level) const {
8994 DEBUG(level, "If clause!");
8995 expr->dump(level + 1);
8996 block->dump(level + 1);
8997 }
8998
8999 // =================================
9000 // ===== IfClauses
9001 // =================================
9002
9003 IfClauses::~IfClauses()
9004 {
9005 for(size_t i=0; i<ics.size(); i++) delete ics[i];
9006 ics.clear();
9007 }
9008
9009 IfClauses *IfClauses::clone() const
9010 {
9011 FATAL_ERROR("IfClauses::clone");
9012 }
9013
9014 void IfClauses::add_ic(IfClause *p_ic)
9015 {
9016 if(!p_ic)
9017 FATAL_ERROR("IfClauses::add_ic()");
9018 ics.add(p_ic);
9019 }
9020
9021 void IfClauses::add_front_ic(IfClause *p_ic)
9022 {
9023 if(!p_ic)
9024 FATAL_ERROR("IfClauses::add_front_ic()");
9025 ics.add_front(p_ic);
9026 }
9027
9028 void IfClauses::set_my_scope(Scope *p_scope)
9029 {
9030 for(size_t i=0; i<ics.size(); i++)
9031 ics[i]->set_my_scope(p_scope);
9032 }
9033
9034 void IfClauses::set_fullname(const string& p_fullname)
9035 {
9036 Node::set_fullname(p_fullname);
9037 for(size_t i=0; i<ics.size(); i++)
9038 ics[i]->set_fullname(p_fullname+".ic_"+Int2string(i+1));
9039 }
9040
9041 void IfClauses::set_my_sb(StatementBlock *p_sb, size_t p_index)
9042 {
9043 for(size_t i=0; i<ics.size(); i++)
9044 ics[i]->get_block()->set_my_sb(p_sb, p_index);
9045 }
9046
9047 void IfClauses::set_my_def(Definition *p_def)
9048 {
9049 for(size_t i=0; i<ics.size(); i++)
9050 ics[i]->get_block()->set_my_def(p_def);
9051 }
9052
9053 void IfClauses::set_my_ags(AltGuards *p_ags)
9054 {
9055 for(size_t i=0; i<ics.size(); i++)
9056 ics[i]->get_block()->set_my_ags(p_ags);
9057 }
9058
9059 void IfClauses::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9060 {
9061 for(size_t i=0; i<ics.size(); i++)
9062 ics[i]->get_block()->set_my_laic_stmt(p_ags, p_loop_stmt);
9063 }
9064
9065 StatementBlock::returnstatus_t IfClauses::has_return
9066 (StatementBlock *elseblock) const
9067 {
9068 StatementBlock::returnstatus_t ret_val = StatementBlock::RS_MAYBE;
9069 for (size_t i = 0; i < ics.size(); i++) {
9070 switch (ics[i]->get_block()->has_return()) {
9071 case StatementBlock::RS_NO:
9072 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9073 else ret_val = StatementBlock::RS_NO;
9074 break;
9075 case StatementBlock::RS_YES:
9076 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9077 else ret_val = StatementBlock::RS_YES;
9078 break;
9079 default:
9080 return StatementBlock::RS_MAYBE;
9081 }
9082 }
9083 StatementBlock::returnstatus_t else_status;
9084 if (elseblock) else_status = elseblock->has_return();
9085 else else_status = StatementBlock::RS_NO;
9086 switch (else_status) {
9087 case StatementBlock::RS_NO:
9088 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9089 else ret_val = StatementBlock::RS_NO;
9090 break;
9091 case StatementBlock::RS_YES:
9092 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9093 else ret_val = StatementBlock::RS_YES;
9094 break;
9095 default:
9096 return StatementBlock::RS_MAYBE;
9097 }
9098 return ret_val;
9099 }
9100
9101 bool IfClauses::has_receiving_stmt() const
9102 {
9103 for(size_t i=0; i<ics.size(); i++)
9104 if(ics[i]->has_receiving_stmt()) return true;
9105 return false;
9106 }
9107
9108 void IfClauses::chk(bool& unreach)
9109 {
9110 for(size_t i=0; i<ics.size(); i++)
9111 ics[i]->chk(unreach);
9112 }
9113
9114 void IfClauses::chk_allowed_interleave()
9115 {
9116 for (size_t i = 0; i < ics.size(); i++)
9117 ics[i]->get_block()->chk_allowed_interleave();
9118 }
9119
9120 void IfClauses::set_code_section(
9121 GovernedSimple::code_section_t p_code_section)
9122 {
9123 for (size_t i = 0; i < ics.size(); i++)
9124 ics[i]->set_code_section(p_code_section);
9125 }
9126
9127 char* IfClauses::generate_code(char *str, size_t& blockcount,
9128 bool& unreach, bool& eachfalse)
9129 {
9130 for(size_t i=0; i<ics.size(); i++) {
9131 if(unreach) return str;
9132 str=ics[i]->generate_code(str, blockcount, unreach, eachfalse);
9133 }
9134 return str;
9135 }
9136
9137 void IfClauses::ilt_generate_code(ILT *ilt, const char *end_label,
9138 bool& unreach)
9139 {
9140 for(size_t i=0; i<ics.size(); i++) {
9141 if(unreach) return;
9142 ics[i]->ilt_generate_code(ilt, end_label, unreach);
9143 }
9144 }
9145
9146 void IfClauses::set_parent_path(WithAttribPath* p_path) {
9147 for (size_t i = 0; i < ics.size(); i++)
9148 ics[i]->set_parent_path(p_path);
9149 }
9150
9151 void IfClauses::dump(unsigned int level) const {
9152 DEBUG(level, "%lu if clauses", (unsigned long)ics.size());
9153 for (size_t i = 0; i < ics.size(); i++)
9154 ics[i]->dump(level + 1);
9155 }
9156
9157 // =================================
9158 // ===== SelectCase
9159 // =================================
9160
9161 SelectCase::SelectCase(TemplateInstances *p_tis, StatementBlock *p_block)
9162 : tis(p_tis), block(p_block)
9163 {
9164 if(!block)
9165 FATAL_ERROR("SelectCase::SelectCase()");
9166 }
9167
9168 SelectCase::~SelectCase()
9169 {
9170 delete tis;
9171 delete block;
9172 }
9173
9174 SelectCase *SelectCase::clone() const
9175 {
9176 FATAL_ERROR("SelectCase::clone");
9177 }
9178
9179 void SelectCase::set_my_scope(Scope *p_scope)
9180 {
9181 if(tis) tis->set_my_scope(p_scope);
9182 block->set_my_scope(p_scope);
9183 }
9184
9185 void SelectCase::set_fullname(const string& p_fullname)
9186 {
9187 Node::set_fullname(p_fullname);
9188 if(tis) tis->set_fullname(p_fullname+".tis");
9189 block->set_fullname(p_fullname+".block");
9190 }
9191
9192 /** \todo review */
9193 void SelectCase::chk(Type *p_gov, bool& unreach)
9194 {
9195 Error_Context cntxt(this, "In select case statement");
9196 if(unreach) warning("Control never reaches this code because of"
9197 " previous effective case(s)");
9198 if(tis)
9199 for(size_t i=0; i<tis->get_nof_tis(); i++)
9200 tis->get_ti_byIndex(i)->chk(p_gov);
9201 else unreach=true; // else statement
9202 block->chk();
9203 }
9204
9205 void SelectCase::set_code_section
9206 (GovernedSimple::code_section_t p_code_section)
9207 {
9208 if(tis) tis->set_code_section(p_code_section);
9209 block->set_code_section(p_code_section);
9210 }
9211
9212 /** \todo review */
9213 char* SelectCase::generate_code_if(char *str, const char *tmp_prefix,
9214 const char *expr_name, size_t idx,
9215 bool& unreach)
9216 {
9217 if(unreach) return str;
9218 if(tis) {
9219 for(size_t i=0; i<tis->get_nof_tis(); i++) {
9220 TemplateInstance *ti=tis->get_ti_byIndex(i);
9221 Template *tb=ti->get_Template();
a38c6d4c 9222 bool is_value = NULL == ti->get_DerivedRef() && tb->is_Value();
970ed795
EL
9223 expression_struct exprs;
9224 Code::init_expr(&exprs);
a38c6d4c 9225 if (is_value) {
9226 if (tb->get_templatetype() == Template::SPECIFIC_VALUE) {
9227 tb->get_specific_value()->generate_code_expr_mandatory(&exprs);
9228 }
9229 else {
9230 Value* val = tb->get_Value();
9231 if (NULL == val->get_my_governor()) {
9232 // the value's governor could not be determined, treat it as a non-value template
9233 is_value = false;
9234 }
9235 else {
9236 val->generate_code_expr_mandatory(&exprs);
9237 }
9238 delete val;
9239 }
970ed795 9240 }
a38c6d4c 9241 if (!is_value) {
9242 ti->generate_code(&exprs);
970ed795
EL
9243 }
9244 str=tb->update_location_object(str);
9245 if(!exprs.preamble && !exprs.postamble) {
9246 str=mputstr(str, "if(");
a38c6d4c 9247 if(!is_value)
3abe9331 9248 str=mputprintf(str, "%s.match(%s%s)", exprs.expr, expr_name,
9249 omit_in_value_list ? ", TRUE" : "");
970ed795
EL
9250 else str=mputprintf(str, "%s == %s", expr_name, exprs.expr);
9251 str=mputprintf(str, ") goto %s_%lu;\n", tmp_prefix,
9252 (unsigned long) idx);
9253 Code::free_expr(&exprs);
9254 }
9255 else {
9256 str=mputprintf(str, "{\nboolean %s_%lub;\n", tmp_prefix,
9257 (unsigned long) idx);
9258 char *s=exprs.expr;
9259 exprs.expr=mprintf("%s_%lub = ", tmp_prefix, (unsigned long) idx);
a38c6d4c 9260 if(!is_value)
3abe9331 9261 exprs.expr=mputprintf(exprs.expr, "%s.match(%s%s)", s, expr_name,
9262 omit_in_value_list ? ", TRUE" : "");
970ed795
EL
9263 else exprs.expr=mputprintf(exprs.expr, "(%s == %s)", expr_name, s);
9264 Free(s);
9265 str=Code::merge_free_expr(str, &exprs);
9266 str=mputprintf(str, "if(%s_%lub) goto %s_%lu;\n}\n",
9267 tmp_prefix, (unsigned long) idx, tmp_prefix, (unsigned long) idx);
9268 }
9269 } // for i
9270 } // if tis
9271 else {
9272 unreach=true; // else statement
9273 str=mputprintf(str, "goto %s_%lu;\n", tmp_prefix, (unsigned long) idx);
9274 }
9275 return str;
9276 }
9277
9278 /** \todo review */
9279 char* SelectCase::generate_code_stmt(char *str, const char *tmp_prefix,
9280 size_t idx, bool& unreach)
9281 {
9282 if(unreach) return str;
9283 if(!tis) unreach=true;
9284 str=mputprintf(str, "%s_%lu:\n{\n", tmp_prefix, (unsigned long) idx);
9285 str=block->generate_code(str);
9286 str=mputprintf(str, "goto %s_end;\n}\n", tmp_prefix);
9287 return str;
9288 }
9289
9290 void SelectCase::ilt_generate_code_stmt(ILT *ilt, const char *tmp_prefix,
9291 size_t idx, bool& unreach)
9292 {
9293 if(unreach) return;
9294 if(!tis) unreach=true;
9295 char*& str=ilt->get_out_branches();
9296 str=mputprintf(str, "%s_%lu:\n", tmp_prefix, (unsigned long) idx);
9297 bool has_recv=block->has_receiving_stmt();
9298 if(!has_recv) {
9299 str=mputstr(str, "{\n");
9300 str=block->generate_code(str);
9301 }
9302 else block->ilt_generate_code(ilt);
9303 str=mputprintf(str, "goto %s_end;\n", tmp_prefix);
9304 if(!has_recv)
9305 str=mputstr(str, "}\n");
9306 }
9307
9308 void SelectCase::set_parent_path(WithAttribPath* p_path) {
9309 block->set_parent_path(p_path);
9310 }
9311
9312 // =================================
9313 // ===== SelectCases
9314 // =================================
9315
9316 SelectCases::~SelectCases()
9317 {
9318 for(size_t i=0; i<scs.size(); i++) delete scs[i];
9319 scs.clear();
9320 }
9321
9322 SelectCases *SelectCases::clone() const
9323 {
9324 FATAL_ERROR("SelectCases::clone");
9325 }
9326
9327 void SelectCases::add_sc(SelectCase *p_sc)
9328 {
9329 if(!p_sc)
9330 FATAL_ERROR("SelectCases::add_sc()");
9331 scs.add(p_sc);
9332 }
9333
9334 void SelectCases::set_my_scope(Scope *p_scope)
9335 {
9336 for(size_t i=0; i<scs.size(); i++)
9337 scs[i]->set_my_scope(p_scope);
9338 }
9339
9340 void SelectCases::set_fullname(const string& p_fullname)
9341 {
9342 Node::set_fullname(p_fullname);
9343 for(size_t i=0; i<scs.size(); i++)
9344 scs[i]->set_fullname(p_fullname+".sc_"+Int2string(i+1));
9345 }
9346
9347 void SelectCases::set_my_sb(StatementBlock *p_sb, size_t p_index)
9348 {
9349 for(size_t i=0; i<scs.size(); i++)
9350 scs[i]->get_block()->set_my_sb(p_sb, p_index);
9351 }
9352
9353 void SelectCases::set_my_def(Definition *p_def)
9354 {
9355 for(size_t i=0; i<scs.size(); i++)
9356 scs[i]->get_block()->set_my_def(p_def);
9357 }
9358
9359 void SelectCases::set_my_ags(AltGuards *p_ags)
9360 {
9361 for(size_t i=0; i<scs.size(); i++)
9362 scs[i]->get_block()->set_my_ags(p_ags);
9363 }
9364
9365 void SelectCases::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9366 {
9367 for(size_t i=0; i<scs.size(); i++)
9368 scs[i]->get_block()->set_my_laic_stmt(p_ags, p_loop_stmt);
9369 }
9370
9371 StatementBlock::returnstatus_t SelectCases::has_return() const
9372 {
9373 StatementBlock::returnstatus_t ret_val = StatementBlock::RS_MAYBE;
9374 bool has_else = false;
9375 for (size_t i = 0; i < scs.size(); i++) {
9376 SelectCase *sc = scs[i];
9377 switch (sc->get_block()->has_return()) {
9378 case StatementBlock::RS_NO:
9379 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9380 else ret_val = StatementBlock::RS_NO;
9381 break;
9382 case StatementBlock::RS_YES:
9383 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9384 else ret_val = StatementBlock::RS_YES;
9385 break;
9386 default:
9387 return StatementBlock::RS_MAYBE;
9388 }
9389 if (!sc->get_tis()) {
9390 has_else = true;
9391 break;
9392 }
9393 }
9394 if (!has_else && ret_val == StatementBlock::RS_YES)
9395 return StatementBlock::RS_MAYBE;
9396 else return ret_val;
9397 }
9398
9399 bool SelectCases::has_receiving_stmt() const
9400 {
9401 for(size_t i=0; i<scs.size(); i++)
9402 if(scs[i]->get_block()->has_receiving_stmt()) return true;
9403 return false;
9404 }
9405
9406 /** \todo review */
9407 void SelectCases::chk(Type *p_gov)
9408 {
9409 bool unreach=false;
9410 for(size_t i=0; i<scs.size(); i++)
9411 scs[i]->chk(p_gov, unreach);
9412 }
9413
9414 void SelectCases::chk_allowed_interleave()
9415 {
9416 for (size_t i = 0; i < scs.size(); i++)
9417 scs[i]->get_block()->chk_allowed_interleave();
9418 }
9419
9420 void SelectCases::set_code_section
9421 (GovernedSimple::code_section_t p_code_section)
9422 {
9423 for(size_t i=0; i<scs.size(); i++)
9424 scs[i]->set_code_section(p_code_section);
9425 }
9426
9427 char* SelectCases::generate_code(char *str, const char *tmp_prefix,
9428 const char *expr_name)
9429 {
9430 bool unreach=false;
9431 for(size_t i=0; i<scs.size(); i++) {
9432 str=scs[i]->generate_code_if(str, tmp_prefix, expr_name, i, unreach);
9433 if(unreach) break;
9434 }
9435 if(!unreach) str=mputprintf(str, "goto %s_end;\n", tmp_prefix);
9436 unreach=false;
9437 for(size_t i=0; i<scs.size(); i++) {
9438 str=scs[i]->generate_code_stmt(str, tmp_prefix, i, unreach);
9439 if(unreach) break;
9440 }
9441 str=mputprintf(str, "%s_end: /* empty */;\n", tmp_prefix);
9442 return str;
9443 }
9444
9445 void SelectCases::ilt_generate_code(ILT *ilt, const char *tmp_prefix,
9446 const char *expr_init,
9447 const char *expr_name)
9448 {
9449 char*& str=ilt->get_out_branches();
9450 if(strlen(expr_init)) {
9451 str=mputstr(str, "{\n"); // (1)
9452 str=mputstr(str, expr_init);
9453 }
9454 bool unreach=false;
9455 for(size_t i=0; i<scs.size(); i++) {
9456 if(unreach) break;
9457 str=scs[i]->generate_code_if(str, tmp_prefix, expr_name, i, unreach);
9458 }
9459 if(!unreach) str=mputprintf(str, "goto %s_end;\n", tmp_prefix);
9460 if(strlen(expr_init)) str=mputstr(str, "}\n"); // (1)
9461 unreach=false;
9462 for(size_t i=0; i<scs.size(); i++) {
9463 if(unreach) break;
9464 scs[i]->ilt_generate_code_stmt(ilt, tmp_prefix, i, unreach);
9465 }
9466 str=mputprintf(str, "%s_end:\n", tmp_prefix);
9467 }
9468
9469 void SelectCases::set_parent_path(WithAttribPath* p_path) {
9470 for (size_t i = 0; i < scs.size(); i++)
9471 scs[i]->set_parent_path(p_path);
9472 }
9473
9474 // =================================
9475 // ===== AltGuard
9476 // =================================
9477
9478 AltGuard::AltGuard(Value *p_expr, Statement *p_stmt, StatementBlock *p_block)
9479 : altguardtype(AG_OP), expr(p_expr), stmt(p_stmt), block(p_block)
9480 {
9481 if (!p_stmt || !p_block) FATAL_ERROR("AltGuard::AltGuard()");
9482 }
9483
9484 AltGuard::AltGuard(Value *p_expr, Ref_pard *p_ref, StatementBlock *p_block)
9485 : altguardtype(AG_REF), expr(p_expr), ref(p_ref), block(p_block)
9486 {
9487 if (!p_ref) FATAL_ERROR("AltGuard::AltGuard()");
9488 }
9489
9490 AltGuard::AltGuard(Value *p_expr, Value *p_v,
9491 Ttcn::TemplateInstances *p_t_list, StatementBlock *p_block)
9492 : altguardtype(AG_INVOKE), expr(p_expr)
9493 , block(p_block)
9494 {
9495 if(!p_v || !p_t_list) FATAL_ERROR("AltGuard::AltGuard()");
9496 invoke.v = p_v;
9497 invoke.t_list = p_t_list;
9498 invoke.ap_list = 0;
9499 }
9500
9501 AltGuard::AltGuard(StatementBlock *p_block)
9502 : altguardtype(AG_ELSE), expr(0), dummy(0), block(p_block)
9503 {
9504 if (!p_block) FATAL_ERROR("AltGuard::AltGuard()");
9505 }
9506
9507 AltGuard::~AltGuard()
9508 {
9509 switch(altguardtype) {
9510 case AG_OP:
9511 delete expr;
9512 delete stmt;
9513 delete block;
9514 break;
9515 case AG_REF:
9516 delete expr;
9517 delete ref;
9518 delete block;
9519 break;
9520 case AG_INVOKE:
9521 delete expr;
9522 delete invoke.v;
9523 delete invoke.t_list;
9524 delete invoke.ap_list;
9525 delete block;
9526 break;
9527 case AG_ELSE:
9528 delete block;
9529 break;
9530 default:
9531 FATAL_ERROR("AltGuard::~AltGuard()");
9532 } // switch
9533 }
9534
9535 AltGuard *AltGuard::clone() const
9536 {
9537 FATAL_ERROR("AltGuard::clone");
9538 }
9539
9540 void AltGuard::set_my_scope(Scope *p_scope)
9541 {
9542 switch(altguardtype) {
9543 case AG_OP:
9544 if(expr) expr->set_my_scope(p_scope);
9545 stmt->set_my_scope(p_scope);
9546 block->set_my_scope(p_scope);
9547 break;
9548 case AG_REF:
9549 if(expr) expr->set_my_scope(p_scope);
9550 ref->set_my_scope(p_scope);
9551 if(block) block->set_my_scope(p_scope);
9552 break;
9553 case AG_INVOKE:
9554 if(expr) expr->set_my_scope(p_scope);
9555 invoke.v->set_my_scope(p_scope);
9556 if(invoke.t_list) invoke.t_list->set_my_scope(p_scope);
9557 if(invoke.ap_list) invoke.ap_list->set_my_scope(p_scope);
9558 if(block) block->set_my_scope(p_scope);
9559 break;
9560 case AG_ELSE:
9561 block->set_my_scope(p_scope);
9562 break;
9563 default:
9564 FATAL_ERROR("AltGuard::set_my_scope()");
9565 } // switch
9566 }
9567
9568 void AltGuard::set_my_sb(StatementBlock *p_sb, size_t p_index)
9569 {
9570 switch(altguardtype) {
9571 case AG_OP:
9572 stmt->set_my_sb(p_sb, p_index);
9573 block->set_my_sb(p_sb, p_index);
9574 break;
9575 case AG_REF:
9576 if(block) block->set_my_sb(p_sb, p_index);
9577 break;
9578 case AG_INVOKE:
9579 if(block) block->set_my_sb(p_sb, p_index);
9580 break;
9581 case AG_ELSE:
9582 block->set_my_sb(p_sb, p_index);
9583 break;
9584 default:
9585 FATAL_ERROR("AltGuard::set_my_sb()");
9586 } // switch
9587 }
9588
9589 void AltGuard::set_fullname(const string& p_fullname)
9590 {
9591 Node::set_fullname(p_fullname);
9592 switch(altguardtype) {
9593 case AG_OP:
9594 if(expr) expr->set_fullname(p_fullname+".expr");
9595 stmt->set_fullname(p_fullname+".stmt");
9596 block->set_fullname(p_fullname+".block");
9597 break;
9598 case AG_REF:
9599 if(expr) expr->set_fullname(p_fullname+".expr");
9600 ref->set_fullname(p_fullname+".ref");
9601 if(block) block->set_fullname(p_fullname+".block");
9602 break;
9603 case AG_INVOKE:
9604 if(expr) expr->set_fullname(p_fullname+".expr");
9605 invoke.v->set_fullname(p_fullname+".function");
9606 if(invoke.t_list) invoke.t_list->set_fullname(p_fullname+".argument");
9607 if(invoke.ap_list) invoke.ap_list->set_fullname(p_fullname+".argument");
9608 if(block) block->set_fullname(p_fullname+".block");
9609 break;
9610 case AG_ELSE:
9611 block->set_fullname(p_fullname+".elseblock");
9612 break;
9613 default:
9614 FATAL_ERROR("AltGuard::set_fullname()");
9615 } // switch
9616 }
9617
9618 Value *AltGuard::get_guard_expr() const
9619 {
9620 if (altguardtype == AG_ELSE) FATAL_ERROR("AltGuard::get_guard_expr()");
9621 return expr;
9622 }
9623
9624 Ref_pard *AltGuard::get_guard_ref() const
9625 {
9626 if (altguardtype != AG_REF) FATAL_ERROR("AltGuard::get_guard_ref()");
9627 return ref;
9628 }
9629
9630 Statement *AltGuard::get_guard_stmt() const
9631 {
9632 if (altguardtype != AG_OP) FATAL_ERROR("AltGuard::get_guard_stmt()");
9633 return stmt;
9634 }
9635
9636 void AltGuard::set_my_def(Definition *p_def)
9637 {
9638 switch(altguardtype) {
9639 case AG_OP:
9640 stmt->set_my_def(p_def);
9641 block->set_my_def(p_def);
9642 break;
9643 case AG_REF:
9644 if(block) block->set_my_def(p_def);
9645 break;
9646 case AG_INVOKE:
9647 if(block) block->set_my_def(p_def);
9648 break;
9649 case AG_ELSE:
9650 block->set_my_def(p_def);
9651 break;
9652 default:
9653 FATAL_ERROR("AltGuard::set_my_def()");
9654 } // switch
9655 }
9656
9657 void AltGuard::set_my_ags(AltGuards *p_ags)
9658 {
9659 switch (altguardtype) {
9660 case AG_OP:
9661 block->set_my_ags(p_ags);
9662 break;
9663 case AG_REF:
9664 if (block) block->set_my_ags(p_ags);
9665 break;
9666 case AG_INVOKE:
9667 if (block) block->set_my_ags(p_ags);
9668 break;
9669 case AG_ELSE:
9670 block->set_my_ags(p_ags);
9671 break;
9672 default:
9673 FATAL_ERROR("AltGuard::set_my_ags()");
9674 } // switch
9675 }
9676
9677 void AltGuard::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9678 {
9679 switch (altguardtype) {
9680 case AG_OP:
9681 block->set_my_laic_stmt(p_ags, p_loop_stmt);
9682 break;
9683 case AG_REF:
9684 if (block) block->set_my_laic_stmt(p_ags, p_loop_stmt);
9685 break;
9686 case AG_INVOKE:
9687 if (block) block->set_my_laic_stmt(p_ags, p_loop_stmt);
9688 break;
9689 case AG_ELSE:
9690 block->set_my_laic_stmt(p_ags, p_loop_stmt);
9691 break;
9692 default:
9693 FATAL_ERROR("AltGuard::set_my_laic_stmt()");
9694 } // switch
9695 }
9696
9697 void AltGuard::chk()
9698 {
9699 switch(altguardtype) {
9700 case AG_OP:
9701 if (expr) {
9702 Error_Context cntxt(expr, "In guard expression");
9703 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
9704 }
9705 {
9706 Error_Context cntxt(stmt, "In guard operation");
9707 stmt->chk();
9708 }
9709 block->chk();
9710 break;
9711 case AG_REF:
9712 if (expr) {
9713 Error_Context cntxt(expr, "In guard expression");
9714 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
9715 }
9716 {
9717 Error_Context cntxt(ref, "In guard statement");
9718 Common::Assignment *t_ass = ref->get_refd_assignment();
9719 if (t_ass) {
9720 if (t_ass->get_asstype() == Common::Assignment::A_ALTSTEP) {
9721 ref->get_my_scope()->chk_runs_on_clause(t_ass, *ref, "call");
9722 } else {
9723 ref->error("Reference to an altstep was expected instead of %s",
9724 t_ass->get_description().c_str());
9725 }
9726 }
9727 }
9728 if (block) block->chk();
9729 break;
9730 case AG_INVOKE:
9731 if (expr) {
9732 Error_Context cntxt(expr, "In guard expression");
9733 expr->chk_expr_bool(Type::EXPECTED_DYNAMIC_VALUE);
9734 }
9735 {
9736 if (!invoke.t_list) return; //already_checked
9737 Error_Context cntxt(ref, "In guard statement");
9738 switch(invoke.v->get_valuetype()){
9739 case Value::V_REFER:
9740 invoke.v->error(
9741 "A value of an altstep type was expected "
9742 "in the argument instead of a `refers' statement,"
9743 " which does not specify any function type");
9744 return;
9745 case Value::V_TTCN3_NULL:
9746 invoke.v->error(
9747 "A value of an altstep type was expected "
9748 "in the argument instead of a `null' value,"
9749 " which does not specify any function type");
9750 return;
9751 default:
9752 break;
9753 }
9754 Type *t = invoke.v->get_expr_governor_last();
9755 if (!t) return;
9756 switch (t->get_typetype()) {
9757 case Type::T_ERROR:
9758 return;
9759 case Type::T_ALTSTEP:
9760 break;
9761 default:
9762 invoke.v->error("A value of type altstep was expected instead of "
9763 "`%s'", t->get_typename().c_str());
9764 return;
9765 }
9766 invoke.v->get_my_scope()->chk_runs_on_clause(t, *this, "call");
9767 Ttcn::FormalParList *fp_list = t->get_fat_parameters();
9768 invoke.ap_list = new Ttcn::ActualParList;
9769 bool is_erroneous = fp_list->chk_actual_parlist(invoke.t_list,
9770 invoke.ap_list);
9771 delete invoke.t_list;
9772 invoke.t_list = 0;
9773 if(is_erroneous) {
9774 delete invoke.ap_list;
9775 invoke.ap_list = 0;
9776 } else {
9777 invoke.ap_list->set_fullname(get_fullname());
9778 invoke.ap_list->set_my_scope(invoke.v->get_my_scope());
9779 }
9780 }
9781 if (block) block->chk();
9782 break;
9783 case AG_ELSE:
9784 {
9785 Error_Context cntxt(this, "In else branch");
9786 block->chk();
9787 Statement *first_stmt = block->get_first_stmt();
9788 if (first_stmt && first_stmt->get_statementtype() ==
9789 Statement::S_REPEAT)
9790 first_stmt->warning("The first statement of the [else] branch is a "
9791 "repeat statement. This will result in busy waiting");
9792 }
9793 break;
9794 default:
9795 FATAL_ERROR("AltGuard::chk()");
9796 } // switch
9797 }
9798
9799 void AltGuard::set_code_section(
9800 GovernedSimple::code_section_t p_code_section)
9801 {
9802 switch(altguardtype) {
9803 case AG_OP:
9804 if (expr) expr->set_code_section(p_code_section);
9805 stmt->set_code_section(p_code_section);
9806 block->set_code_section(p_code_section);
9807 break;
9808 case AG_REF:
9809 if (expr) expr->set_code_section(p_code_section);
9810 ref->set_code_section(p_code_section);
9811 if (block) block->set_code_section(p_code_section);
9812 break;
9813 case AG_INVOKE:
9814 if (expr) expr->set_code_section(p_code_section);
9815 invoke.v->set_code_section(p_code_section);
9816 if(invoke.t_list) invoke.t_list->set_code_section(p_code_section);
9817 if(invoke.ap_list)
9818 for(size_t i = 0; i < invoke.ap_list->get_nof_pars(); i++)
9819 invoke.ap_list->get_par(i)->set_code_section(p_code_section);
9820 if (block) block->set_code_section(p_code_section);
9821 break;
9822 case AG_ELSE:
9823 block->set_code_section(p_code_section);
9824 break;
9825 default:
9826 FATAL_ERROR("AltGuard::set_fullname()");
9827 } // switch
9828 }
9829
9830 void AltGuard::generate_code_invoke_instance(expression_struct *p_expr)
9831 {
9832 if (altguardtype != AG_INVOKE)
9833 FATAL_ERROR("AltGuard::generate_code_invoke_instance");
9834 Value *last_v = invoke.v->get_value_refd_last();
9835 if (last_v->get_valuetype() == Value::V_ALTSTEP) {
9836 Common::Assignment *altstep = last_v->get_refd_fat();
9837 p_expr->expr = mputprintf(p_expr->expr, "%s_instance(",
9838 altstep->get_genname_from_scope(invoke.v->get_my_scope()).c_str());
9839 invoke.ap_list->generate_code_alias(p_expr,
9840 altstep->get_FormalParList(), altstep->get_RunsOnType(), false);
9841 } else {
9842 invoke.v->generate_code_expr_mandatory(p_expr);
9843 p_expr->expr = mputstr(p_expr->expr, ".invoke(");
9844 Type* gov_last = invoke.v->get_expr_governor_last();
9845 invoke.ap_list->generate_code_alias(p_expr, 0,
9846 gov_last->get_fat_runs_on_type(), gov_last->get_fat_runs_on_self());
9847 }
9848 p_expr->expr = mputc(p_expr->expr, ')');
9849 }
9850
9851 // =================================
9852 // ===== AltGuards
9853 // =================================
9854
9855 AltGuards::~AltGuards()
9856 {
9857 for(size_t i=0; i<ags.size(); i++) delete ags[i];
9858 ags.clear();
9859 delete label;
9860 delete il_label_end;
9861 }
9862
9863 AltGuards *AltGuards::clone() const
9864 {
9865 FATAL_ERROR("AltGuards::clone");
9866 }
9867
9868 void AltGuards::add_ag(AltGuard *p_ag)
9869 {
9870 if(!p_ag)
9871 FATAL_ERROR("AltGuards::add_ag()");
9872 ags.add(p_ag);
9873 }
9874
9875 void AltGuards::set_my_scope(Scope *p_scope)
9876 {
9877 my_scope = p_scope;
9878 for(size_t i=0; i<ags.size(); i++)
9879 ags[i]->set_my_scope(p_scope);
9880 }
9881
9882 void AltGuards::set_fullname(const string& p_fullname)
9883 {
9884 Node::set_fullname(p_fullname);
9885 for(size_t i=0; i<ags.size(); i++)
9886 ags[i]->set_fullname(p_fullname+".ag_"+Int2string(i+1));
9887 }
9888
9889 void AltGuards::set_my_sb(StatementBlock *p_sb, size_t p_index)
9890 {
9891 for(size_t i=0; i<ags.size(); i++)
9892 ags[i]->set_my_sb(p_sb, p_index);
9893 }
9894
9895 void AltGuards::set_my_def(Definition *p_def)
9896 {
9897 for(size_t i=0; i<ags.size(); i++)
9898 ags[i]->set_my_def(p_def);
9899 }
9900
9901 void AltGuards::set_my_ags(AltGuards *p_ags)
9902 {
9903 for(size_t i=0; i<ags.size(); i++)
9904 ags[i]->set_my_ags(p_ags);
9905 }
9906
9907 void AltGuards::set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt)
9908 {
9909 for(size_t i=0; i<ags.size(); i++)
9910 ags[i]->set_my_laic_stmt(p_ags, p_loop_stmt);
9911 }
9912
9913 bool AltGuards::has_else() const
9914 {
9915 for (size_t i = 0; i < ags.size(); i++)
9916 if (ags[i]->get_type() == AltGuard::AG_ELSE) return true;
9917 return false;
9918 }
9919
9920 StatementBlock::returnstatus_t AltGuards::has_return() const
9921 {
9922 StatementBlock::returnstatus_t ret_val = StatementBlock::RS_MAYBE;
9923 for (size_t i = 0; i < ags.size(); i++) {
9924 AltGuard *ag = ags[i];
9925 StatementBlock *block = ag->get_block();
9926 StatementBlock::returnstatus_t block_status;
9927 if (block) block_status = block->has_return();
9928 else block_status = StatementBlock::RS_NO;
9929 switch (block_status) {
9930 case StatementBlock::RS_NO:
9931 if (ret_val == StatementBlock::RS_YES) return StatementBlock::RS_MAYBE;
9932 else ret_val = StatementBlock::RS_NO;
9933 break;
9934 case StatementBlock::RS_YES:
9935 if (ret_val == StatementBlock::RS_NO) return StatementBlock::RS_MAYBE;
9936 else ret_val = StatementBlock::RS_YES;
9937 break;
9938 default:
9939 return StatementBlock::RS_MAYBE;
9940 }
9941 if (ag->get_type() == AltGuard::AG_ELSE) break;
9942 }
9943 return ret_val;
9944 }
9945
9946 bool AltGuards::has_receiving_stmt() const
9947 {
9948 for(size_t i=0; i<ags.size(); i++)
9949 if(ags[i]->get_block()->has_receiving_stmt()) return true;
9950 return false;
9951 }
9952
9953 void AltGuards::chk()
9954 {
9955 bool unreach_found = false;
9956 size_t nof_ags = ags.size();
9957 AltGuard *prev_ag = 0;
9958 for (size_t i = 0; i < nof_ags; i++) {
9959 AltGuard *ag = ags[i];
9960 ag->chk();
9961 if (!unreach_found && prev_ag &&
9962 prev_ag->get_type() == AltGuard::AG_ELSE) {
9963 ag->warning("Control never reaches this branch of alternative "
9964 "because of the previous [else] branch");
9965 unreach_found = true;
9966 }
9967 prev_ag = ag;
9968 }
9969 }
9970
9971 void AltGuards::chk_allowed_interleave()
9972 {
9973 for (size_t i = 0; i < ags.size(); i++) {
9974 AltGuard *ag = ags[i];
9975 switch (ag->get_type()) {
9976 case AltGuard::AG_OP:
9977 break;
9978 case AltGuard::AG_REF:
9979 case AltGuard::AG_INVOKE:
9980 ag->error("Invocation of an altstep is not allowed within an "
9981 "interleave statement");
9982 break;
9983 case AltGuard::AG_ELSE:
9984 ag->error("Else branch of an alternative is not allowed within an "
9985 "interleave statement");
9986 break;
9987 default:
9988 FATAL_ERROR("AltGuards::chk_allowed_interleave()");
9989 }
9990 ag->get_block()->chk_allowed_interleave();
9991 }
9992 }
9993
9994 void AltGuards::set_code_section(
9995 GovernedSimple::code_section_t p_code_section)
9996 {
9997 for (size_t i = 0; i < ags.size(); i++)
9998 ags[i]->set_code_section(p_code_section);
9999 }
10000
10001 char *AltGuards::generate_code_alt(char *str, const Location& loc)
10002 {
10003 bool label_needed = has_repeat, has_else_branch = false;
10004 for (size_t i = 0; i < ags.size(); i++) {
10005 AltGuard *ag = ags[i];
10006 switch (ag->get_type()) {
10007 case AltGuard::AG_OP:
10008 // trigger may return ALT_REPEAT
10009 if (ag->get_guard_stmt()->can_repeat()) label_needed = true;
10010 break;
10011 case AltGuard::AG_REF:
10012 case AltGuard::AG_INVOKE:
10013 // an altstep may return ALT_REPEAT
10014 label_needed = true;
10015 break;
10016 case AltGuard::AG_ELSE:
10017 has_else_branch = true;
10018 break;
10019 default:
10020 FATAL_ERROR("AltGuards::generate_code_alt()");
10021 }
10022 if (has_else_branch) break;
10023 }
10024 // if there is no [else] branch the defaults may return ALT_REPEAT
10025 if (!has_else_branch) label_needed = true;
10026 // opening bracket of the statement block
10027 str = mputstr(str, "{\n");
10028 // the label name is also used for prefixing local variables
10029 if (!my_scope || label) FATAL_ERROR("AltGuards::generate_code_alt()");
10030 label = new string(my_scope->get_scope_mod_gen()->get_temporary_id());
10031 const char *label_str = label->c_str();
10032 if (label_needed) str = mputprintf(str, "%s:\n", label_str);
10033 // temporary variables used for caching of status codes
10034 for (size_t i = 0; i < ags.size(); i++) {
10035 AltGuard *ag = ags[i];
10036 if (ag->get_type() == AltGuard::AG_ELSE) break;
10037 str = mputprintf(str, "alt_status %s_alt_flag_%lu = %s;\n",
10038 label_str, (unsigned long) i,
10039 ag->get_guard_expr() ? "ALT_UNCHECKED" : "ALT_MAYBE");
10040 }
10041 if (!has_else_branch) {
10042 str = mputprintf(str, "alt_status %s_default_flag = ALT_MAYBE;\n",
10043 label_str);
10044 }
10045 // the first snapshot is taken in non-blocking mode
10046 // and opening infinite for() loop
10047 str = mputstr(str, "TTCN_Snapshot::take_new(FALSE);\n"
10048 "for ( ; ; ) {\n");
10049 for (size_t i = 0; i < ags.size(); i++) {
10050 AltGuard *ag = ags[i];
10051 AltGuard::altguardtype_t agtype = ag->get_type();
10052 if (agtype == AltGuard::AG_ELSE) {
10053 // an else branch was found
10054 str = mputstr(str, "TTCN_Snapshot::else_branch_reached();\n");
10055 StatementBlock *block = ag->get_block();
10056 if (block->get_nof_stmts() > 0) {
10057 str = mputstr(str, "{\n");
10058 str = block->generate_code(str);
10059 str = mputstr(str, "}\n");
10060 }
10061 // jump out of the infinite for() loop
10062 if (block->has_return() != StatementBlock::RS_YES)
10063 str = mputstr(str, "break;\n");
10064 // do not generate code for further branches
10065 break;
10066 } else {
10067 Value *guard_expr = ag->get_guard_expr();
10068 if (guard_expr) {
10069 // the branch has a boolean guard expression
10070 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n",
10071 label_str, (unsigned long) i);
10072 str = guard_expr->update_location_object(str);
10073 expression_struct expr;
10074 Code::init_expr(&expr);
10075 guard_expr->generate_code_expr(&expr);
10076 str = mputstr(str, expr.preamble);
10077 str = mputprintf(str, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10078 "else %s_alt_flag_%lu = ALT_NO;\n", expr.expr, label_str,
10079 (unsigned long) i, label_str, (unsigned long) i);
10080 str = mputstr(str, expr.postamble);
10081 Code::free_expr(&expr);
10082 str = mputstr(str, "}\n");
10083 }
10084 // evaluation of guard operation or altstep
10085 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n",
10086 label_str, (unsigned long) i);
10087 // indicates whether the guard operation might return ALT_REPEAT
10088 bool can_repeat;
10089 expression_struct expr;
10090 Code::init_expr(&expr);
10091 expr.expr = mputprintf(expr.expr, "%s_alt_flag_%lu = ", label_str,
10092 (unsigned long) i);
10093 switch (agtype) {
10094 case AltGuard::AG_OP: {
10095 // the guard operation is a receiving statement
10096 Statement *stmt = ag->get_guard_stmt();
10097 str = stmt->update_location_object(str);
10098 stmt->generate_code_expr(&expr);
10099 can_repeat = stmt->can_repeat();
10100 break; }
10101 case AltGuard::AG_REF: {
10102 // the guard operation is an altstep instance
10103 Ref_pard *ref = ag->get_guard_ref();
10104 str = ref->update_location_object(str);
10105 Common::Assignment *altstep = ref->get_refd_assignment();
10106 expr.expr = mputprintf(expr.expr, "%s_instance(",
10107 altstep->get_genname_from_scope(my_scope).c_str());
10108 ref->get_parlist()->generate_code_alias(&expr,
10109 altstep->get_FormalParList(), altstep->get_RunsOnType(), false);
10110 expr.expr = mputc(expr.expr, ')');
10111 can_repeat = true;
10112 break; }
10113 case AltGuard::AG_INVOKE: {
10114 // the guard operation is an altstep invocation
10115 str = ag->update_location_object(str);
10116 ag->generate_code_invoke_instance(&expr);
10117 can_repeat = true;
10118 break; }
10119 default:
10120 FATAL_ERROR("AltGuards::generate_code_alt()");
10121 }
10122 str = Code::merge_free_expr(str, &expr);
10123 if (can_repeat) {
10124 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_REPEAT) goto %s;\n",
10125 label_str, (unsigned long) i, label_str);
10126 }
10127 if (agtype == AltGuard::AG_REF || agtype == AltGuard::AG_INVOKE) {
10128 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_BREAK) break;\n",
10129 label_str, (unsigned long) i);
10130 }
10131 // execution of statement block if the guard was successful
10132 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_YES) ", label_str,
10133 (unsigned long) i);
10134 StatementBlock *block = ag->get_block();
10135 if (block && block->get_nof_stmts() > 0) {
10136 str = mputstr(str, "{\n");
10137 str = block->generate_code(str);
10138 if (block->has_return() != StatementBlock::RS_YES)
10139 str = mputstr(str, "break;\n");
10140 str = mputstr(str, "}\n");
10141 } else str = mputstr(str, "break;\n");
10142 // closing of if() block
10143 str = mputstr(str, "}\n");
10144 }
10145 }
10146 if (!has_else_branch) {
10147 // calling of defaults
10148 str = mputprintf(str, "if (%s_default_flag == ALT_MAYBE) {\n"
10149 "%s_default_flag = TTCN_Default::try_altsteps();\n"
10150 "if (%s_default_flag == ALT_YES || %s_default_flag == ALT_BREAK)"
10151 " break;\n"
10152 "else if (%s_default_flag == ALT_REPEAT) goto %s;\n"
10153 "}\n",
10154 label_str, label_str, label_str, label_str, label_str, label_str);
10155 str = loc.update_location_object(str);
10156 // error handling and taking the next snapshot in blocking mode
10157 str = mputstr(str, "if (");
10158 for (size_t i = 0; i < ags.size(); i++)
10159 str = mputprintf(str, "%s_alt_flag_%lu == ALT_NO && ", label_str,
10160 (unsigned long) i);
10161 str = mputprintf(str,"%s_default_flag == ALT_NO) "
10162 "TTCN_error(\"None of the branches can be chosen in the alt "
10163 "statement in file ", label_str);
10164 str = Code::translate_string(str, loc.get_filename());
10165 int first_line = loc.get_first_line(), last_line = loc.get_last_line();
10166 if (first_line < last_line) str = mputprintf(str,
10167 " between lines %d and %d", first_line, last_line);
10168 else str = mputprintf(str, ", line %d", first_line);
10169 str = mputstr(str, ".\");\n"
10170 "TTCN_Snapshot::take_new(TRUE);\n");
10171 }
10172 // end of for() statement and the statement block
10173 str = mputstr(str, "}\n"
10174 "}\n");
10175 return str;
10176 }
10177
10178 char *AltGuards::generate_code_altstep(char *str)
10179 {
10180 if (!my_scope) FATAL_ERROR("AltGuards::generate_code_altstep()");
10181 Common::Module *my_mod = my_scope->get_scope_mod_gen();
10182 bool has_else_branch = has_else();
10183 if (!has_else_branch) {
10184 str = mputstr(str, "alt_status ret_val = ALT_NO;\n");
10185 }
10186 for (size_t i = 0; i < ags.size(); i++) {
10187 AltGuard *ag = ags[i];
10188 AltGuard::altguardtype_t agtype = ag->get_type();
10189 if (agtype == AltGuard::AG_ELSE) {
10190 // an else branch was found
10191 str = mputstr(str, "TTCN_Snapshot::else_branch_reached();\n");
10192 StatementBlock *block = ag->get_block();
10193 if (block->get_nof_stmts() > 0) {
10194 str = mputstr(str, "{\n");
10195 str = block->generate_code(str);
10196 str = mputstr(str, "}\n");
10197 }
10198 if (block->has_return() != StatementBlock::RS_YES)
10199 str = mputstr(str, "return ALT_YES;\n");
10200 // do not generate code for further branches
10201 break;
10202 } else {
10203 size_t blockcount = 0;
10204 Value *guard_expr = ag->get_guard_expr();
10205 if (guard_expr) {
10206 // the branch has a boolean guard expression
10207 str = guard_expr->update_location_object(str);
10208 str = guard_expr->generate_code_tmp(str, "if (", blockcount);
10209 str = mputstr(str, ") {\n");
10210 blockcount++;
10211 }
10212 // indicates whether the guard operation might return ALT_REPEAT
10213 bool can_repeat;
10214 expression_struct expr;
10215 Code::init_expr(&expr);
10216 switch (agtype) {
10217 case AltGuard::AG_OP: {
10218 // the guard operation is a receiving statement
10219 Statement *stmt = ag->get_guard_stmt();
10220 str = stmt->update_location_object(str);
10221 stmt->generate_code_expr(&expr);
10222 can_repeat = stmt->can_repeat();
10223 break; }
10224 case AltGuard::AG_REF: {
10225 // the guard operation is an altstep instance
10226 Ref_pard *ref = ag->get_guard_ref();
10227 str = ref->update_location_object(str);
10228 Common::Assignment *altstep = ref->get_refd_assignment();
10229 expr.expr = mputprintf(expr.expr, "%s_instance(",
10230 altstep->get_genname_from_scope(my_scope).c_str());
10231 ref->get_parlist()->generate_code_alias(&expr,
10232 altstep->get_FormalParList(), altstep->get_RunsOnType(), false);
10233 expr.expr = mputc(expr.expr, ')');
10234 can_repeat = true;
10235 break; }
10236 case AltGuard::AG_INVOKE: {
10237 str = ag->update_location_object(str);
10238 ag->generate_code_invoke_instance(&expr);
10239 can_repeat = true;
10240 break; }
10241 default:
10242 FATAL_ERROR("AltGuards::generate_code_altstep()");
10243 }
10244 if (expr.preamble || expr.postamble) {
10245 if (blockcount == 0) {
10246 // open a statement block if it is not done so far
10247 str = mputstr(str, "{\n");
10248 blockcount++;
10249 }
10250 const string& tmp_id = my_mod->get_temporary_id();
10251 const char *tmp_id_str = tmp_id.c_str();
10252 str = mputprintf(str, "alt_status %s;\n"
10253 "{\n", tmp_id_str);
10254 str = mputstr(str, expr.preamble);
10255 str = mputprintf(str, "%s = %s;\n", tmp_id_str, expr.expr);
10256 str = mputstr(str, expr.postamble);
10257 str = mputprintf(str, "}\n"
10258 "switch (%s) {\n", tmp_id_str);
10259 } else {
10260 str = mputprintf(str, "switch (%s) {\n", expr.expr);
10261 }
10262 Code::free_expr(&expr);
10263 str = mputstr(str, "case ALT_YES:\n");
10264 StatementBlock *block = ag->get_block();
10265 if (block && block->get_nof_stmts() > 0) {
10266 str = mputstr(str, "{\n");
10267 str = block->generate_code(str);
10268 str = mputstr(str, "}\n");
10269 }
10270 if (!block || block->has_return() != StatementBlock::RS_YES)
10271 str = mputstr(str, "return ALT_YES;\n");
10272 if (can_repeat)
10273 str = mputstr(str, "case ALT_REPEAT:\n"
10274 "return ALT_REPEAT;\n");
10275 if (agtype == AltGuard::AG_REF || agtype == AltGuard::AG_INVOKE) {
10276 str = mputprintf(str, "case ALT_BREAK:\n"
10277 "return ALT_BREAK;\n");
10278 }
10279 if (!has_else_branch)
10280 str = mputstr(str, "case ALT_MAYBE:\n"
10281 "ret_val = ALT_MAYBE;\n");
10282 str = mputstr(str, "default:\n"
10283 "break;\n"
10284 "}\n");
10285 // closing statement blocks
10286 for ( ; blockcount > 0; blockcount--) str = mputstr(str, "}\n");
10287 }
10288 }
10289 if (!has_else_branch) str = mputstr(str, "return ret_val;\n");
10290 return str;
10291 }
10292
10293 char* AltGuards::generate_code_call_body(char *str, const Location& loc,
10294 const string& temp_id, bool in_interleave)
10295 {
10296 if (label) FATAL_ERROR("AltGuards::generate_code_call_body()");
10297 label = new string(temp_id);
10298 const char *label_str = temp_id.c_str();
10299 // label is needed only if there is a repeat statement in the branches
10300 if (has_repeat) str = mputprintf(str, "%s:\n", label_str);
10301 // temporary variables used for caching of status codes
10302 for (size_t i = 0; i < ags.size(); i++)
10303 str = mputprintf(str, "alt_status %s_alt_flag_%lu = %s;\n",
10304 label_str, (unsigned long) i,
10305 ags[i]->get_guard_expr()?"ALT_UNCHECKED":"ALT_MAYBE");
10306 str = loc.update_location_object(str);
10307 // the first snapshot is taken in non-blocking mode
10308 // and opening infinite for() loop
10309 str = mputstr(str, "TTCN_Snapshot::take_new(FALSE);\n"
10310 "for ( ; ; ) {\n"); // (1)
10311 for (size_t i = 0; i < ags.size(); i++) {
10312 AltGuard *ag = ags[i];
10313 if (ag->get_type() != AltGuard::AG_OP)
10314 FATAL_ERROR("AltGuards::generate_code_call_body()");
10315 Value *guard_expr = ag->get_guard_expr();
10316 if (guard_expr) {
10317 // the branch has a boolean guard expression
10318 str = mputprintf(str,
10319 "if (%s_alt_flag_%lu == ALT_UNCHECKED) {\n", // (2)
10320 label_str, (unsigned long) i);
10321 str = guard_expr->update_location_object(str);
10322 expression_struct expr;
10323 Code::init_expr(&expr);
10324 guard_expr->generate_code_expr(&expr);
10325 str = mputstr(str, expr.preamble);
10326 str = mputprintf(str, "if (%s) %s_alt_flag_%lu = ALT_MAYBE;\n"
10327 "else %s_alt_flag_%lu = ALT_NO;\n",
10328 expr.expr, label_str, (unsigned long) i,
10329 label_str, (unsigned long) i);
10330 str = mputstr(str, expr.postamble);
10331 Code::free_expr(&expr);
10332 str = mputstr(str, "}\n"); // (2)
10333 }
10334 // evaluation of guard operation
10335 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_MAYBE) {\n", // (2)
10336 label_str, (unsigned long) i);
10337 expression_struct expr;
10338 Code::init_expr(&expr);
10339 expr.expr = mputprintf(expr.expr, "%s_alt_flag_%lu = ", label_str,
10340 (unsigned long) i);
10341 Statement *stmt = ag->get_guard_stmt();
10342 str = stmt->update_location_object(str);
10343 stmt->generate_code_expr(&expr);
10344 str = Code::merge_free_expr(str, &expr);
10345 // execution of statement block if the guard was successful
10346 str = mputprintf(str, "if (%s_alt_flag_%lu == ALT_YES) ", label_str,
10347 (unsigned long) i);
10348 StatementBlock *block = ag->get_block();
10349 if(in_interleave) {
10350 if(block && block->get_nof_stmts() > 0) {
10351 if(block->has_receiving_stmt()) {
10352 str = mputprintf(str, "goto %s_branch%lu;\n",
10353 label_str, (unsigned long) i);
10354 }
10355 else {
10356 str = mputstr(str, "{\n"); // (3)
10357 str = block->generate_code(str);
10358 str = mputprintf(str, "goto %s_end;\n"
10359 "}\n", // (3)
10360 label_str);
10361 }
10362 }
10363 else str = mputprintf(str, "goto %s_end;\n", label_str);
10364 }
10365 else {
10366 if (block && block->get_nof_stmts() > 0) {
10367 str = mputstr(str, "{\n"); // (3)
10368 str = block->generate_code(str);
10369 if (block->has_return() != StatementBlock::RS_YES)
10370 str = mputstr(str, "break;\n");
10371 str = mputstr(str, "}\n"); // (3)
10372 }
10373 else str = mputstr(str, "break;\n");
10374 }
10375 // closing of if() block
10376 str = mputstr(str, "}\n"); // (2)
10377 }
10378 str = loc.update_location_object(str);
10379 // error handling and taking the next snapshot in blocking mode
10380 str = mputstr(str, "if (");
10381 for (size_t i = 0; i < ags.size(); i++) {
10382 if (i > 0) str = mputstr(str, " && ");
10383 str = mputprintf(str, "%s_alt_flag_%lu == ALT_NO", label_str,
10384 (unsigned long) i);
10385 }
10386 str = mputstr(str, ") TTCN_error(\"None of the branches can be chosen in "
10387 "the response and exception handling part of call statement in file ");
10388 str = Code::translate_string(str, loc.get_filename());
10389 int first_line = loc.get_first_line(), last_line = loc.get_last_line();
10390 if (first_line < last_line) str = mputprintf(str,
10391 " between lines %d and %d", first_line, last_line);
10392 else str = mputprintf(str, ", line %d", first_line);
10393 str = mputstr(str, ".\");\n"
10394 "TTCN_Snapshot::take_new(TRUE);\n"
10395 "}\n"); // (1) for
10396 return str;
10397 }
10398
10399 void AltGuards::ilt_generate_code_call_body(ILT *ilt, const char *label_str)
10400 {
10401 char*& str=ilt->get_out_branches();
10402 for(size_t i=0; i<ags.size(); i++) {
10403 StatementBlock *block = ags[i]->get_block();
10404 if (block && block->has_receiving_stmt()) {
10405 str = mputprintf(str, "%s_branch%lu:\n", label_str, (unsigned long) i);
10406 block->ilt_generate_code(ilt);
10407 str = mputprintf(str, "goto %s_end;\n", label_str);
10408 }
10409 } // for i
10410 }
10411
10412} // namespace Ttcn
This page took 0.423029 seconds and 5 git commands to generate.