Sync with 5.1.0
[deliverable/titan.core.git] / compiler2 / ttcn3 / Ttcnstuff.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "Ttcnstuff.hh"
9 #include "../Int.hh"
10 #include "../CompilerError.hh"
11 #include "AST_ttcn3.hh"
12 #include "../main.hh"
13 #include "Attributes.hh"
14 #include <errno.h>
15
16 // implemented in coding_attrib_p.y
17 extern Ttcn::ExtensionAttributes * parse_extattributes(
18 Ttcn::WithAttribPath *w_attrib_path);
19
20 namespace Ttcn {
21
22 // =================================
23 // ===== ErrorBehaviorSetting
24 // =================================
25
26 ErrorBehaviorSetting *ErrorBehaviorSetting::clone() const
27 {
28 FATAL_ERROR("ErrorBehaviorSetting::clone");
29 }
30
31 void ErrorBehaviorSetting::dump(unsigned level) const
32 {
33 DEBUG(level, "%s : %s", error_type.c_str(), error_handling.c_str());
34 }
35
36 // =================================
37 // ===== ErrorBehaviorList
38 // =================================
39
40 ErrorBehaviorList::~ErrorBehaviorList()
41 {
42 for (size_t i = 0; i < ebs_v.size(); i++)
43 delete ebs_v[i];
44 ebs_v.clear();
45 ebs_m.clear();
46 }
47
48 ErrorBehaviorList *ErrorBehaviorList::clone() const
49 {
50 FATAL_ERROR("ErrorBehaviorList::clone");
51 }
52
53 void ErrorBehaviorList::set_fullname(const string& p_fullname)
54 {
55 Node::set_fullname(p_fullname);
56 for (size_t i = 0; i < ebs_v.size(); i++)
57 ebs_v[i]->set_fullname(p_fullname
58 + ".<setting" + Common::Int2string(i + 1) + ">");
59 }
60
61 void ErrorBehaviorList::add_ebs(ErrorBehaviorSetting *p_ebs)
62 {
63 if (!p_ebs || checked) FATAL_ERROR("ErrorBehaviorList::add_ebs()");
64 ebs_v.add(p_ebs);
65 }
66
67 void ErrorBehaviorList::steal_ebs(ErrorBehaviorList *p_eblist)
68 {
69 if (!p_eblist || checked || p_eblist->checked)
70 FATAL_ERROR("ErrorBehaviorList::steal_ebs()");
71 for (size_t i = 0; i < p_eblist->ebs_v.size(); i++)
72 ebs_v.add(p_eblist->ebs_v[i]);
73 p_eblist->ebs_v.clear();
74 join_location(*p_eblist);
75 }
76
77 bool ErrorBehaviorList::has_setting(const string& p_error_type)
78 {
79 if (!checked) chk();
80 return ebs_all != 0 || ebs_m.has_key(p_error_type);
81 }
82
83 string ErrorBehaviorList::get_handling(const string& p_error_type)
84 {
85 if (!checked) chk();
86 if (ebs_m.has_key(p_error_type))
87 return ebs_m[p_error_type]->get_error_handling();
88 else if (ebs_all) return ebs_all->get_error_handling();
89 else return string("DEFAULT");
90 }
91
92 void ErrorBehaviorList::chk()
93 {
94 if (checked) return;
95 const string all_str("ALL");
96 Common::Error_Context cntxt(this, "In error behavior list");
97 for (size_t i = 0; i < ebs_v.size(); i++) {
98 ErrorBehaviorSetting *ebs = ebs_v[i];
99 const string& error_type = ebs->get_error_type();
100 if (error_type == all_str) {
101 if (ebs_all) {
102 ebs->warning("Duplicate setting for error type `ALL'");
103 ebs_all->warning("The previous setting is ignored");
104 }
105 ebs_all = ebs;
106 if (!ebs_m.empty()) {
107 ebs->warning("All settings before `ALL' are ignored");
108 ebs_m.clear();
109 }
110 } else {
111 if (ebs_m.has_key(error_type)) {
112 ebs->warning("Duplicate setting for error type `%s'",
113 error_type.c_str());
114 ErrorBehaviorSetting*& ebs_ref = ebs_m[error_type];
115 ebs_ref->warning("The previous setting is ignored");
116 // replace the previous setting in the map
117 ebs_ref = ebs;
118 } else ebs_m.add(error_type, ebs);
119 static const char * const valid_types[] = {
120 "UNBOUND", "INCOMPL_ANY", "ENC_ENUM", "INCOMPL_MSG", "LEN_FORM",
121 "INVAL_MSG", "REPR", "CONSTRAINT", "TAG", "SUPERFL", "EXTENSION",
122 "DEC_ENUM", "DEC_DUPFLD", "DEC_MISSFLD", "DEC_OPENTYPE", "DEC_UCSTR",
123 "LEN_ERR", "SIGN_ERR", "INCOMP_ORDER", "TOKEN_ERR", "LOG_MATCHING",
124 "FLOAT_TR", "FLOAT_NAN", "OMITTED_TAG", "NEGTEST_CONFL", NULL };
125 bool type_found = false;
126 for (const char * const *str = valid_types; *str; str++) {
127 if (error_type == *str) {
128 type_found = true;
129 break;
130 }
131 }
132 if (!type_found) {
133 ebs->warning("String `%s' is not a valid error type",
134 error_type.c_str());
135 }
136 }
137 const string& error_handling = ebs->get_error_handling();
138 static const char * const valid_handlings[] = {
139 "DEFAULT", "ERROR", "WARNING", "IGNORE", NULL };
140 bool handling_found = false;
141 for (const char * const *str = valid_handlings; *str; str++) {
142 if (error_handling == *str) {
143 handling_found = true;
144 break;
145 }
146 }
147 if (!handling_found) {
148 ebs->warning("String `%s' is not a valid error handling",
149 error_handling.c_str());
150 }
151 }
152 checked = true;
153 }
154
155 char *ErrorBehaviorList::generate_code(char *str)
156 {
157 if (!checked) FATAL_ERROR("ErrorBehaviorList::generate_code()");
158 const string all_str("ALL");
159 if (ebs_all) {
160 str = mputprintf(str, "TTCN_EncDec::set_error_behavior("
161 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_%s);\n",
162 ebs_all->get_error_handling().c_str());
163 } else {
164 // reset all error behavior to default
165 str = mputstr(str, "TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, "
166 "TTCN_EncDec::EB_DEFAULT);\n");
167 }
168 for (size_t i = 0; i < ebs_m.size(); i++) {
169 ErrorBehaviorSetting *ebs = ebs_m.get_nth_elem(i);
170 str = mputprintf(str, "TTCN_EncDec::set_error_behavior("
171 "TTCN_EncDec::ET_%s, TTCN_EncDec::EB_%s);\n",
172 ebs->get_error_type().c_str(), ebs->get_error_handling().c_str());
173 }
174 return str;
175 }
176
177 void ErrorBehaviorList::dump(unsigned level) const
178 {
179 DEBUG(level, "Error behavior: (%lu pcs.)", (unsigned long) ebs_v.size());
180 for (size_t i = 0; i < ebs_v.size(); i++)
181 ebs_v[i]->dump(level + 1);
182 }
183
184 // =================================
185 // ===== PrintingType
186 // =================================
187
188 PrintingType *PrintingType::clone() const
189 {
190 FATAL_ERROR("PrintingType::clone");
191 }
192
193 char *PrintingType::generate_code(char *str)
194 {
195 return mputprintf(str, ", %d", (PT_PRETTY == printing) ? 1 : 0);
196 }
197
198 // =================================
199 // ===== TypeMappingTarget
200 // =================================
201
202 TypeMappingTarget::TypeMappingTarget(Common::Type *p_target_type,
203 TypeMappingType_t p_mapping_type)
204 : Node(), Location(), target_type(p_target_type),
205 mapping_type(p_mapping_type), checked(false)
206 {
207 if (p_mapping_type == TM_SIMPLE && p_target_type != NULL) { // acceptable
208 target_type->set_ownertype(Type::OT_TYPE_MAP_TARGET, this);
209 }
210 else if (p_mapping_type == TM_DISCARD && p_target_type == NULL)
211 {} // also acceptable but nothing to do
212 else FATAL_ERROR("TypeMappingTarget::TypeMappingTarget()");
213 }
214
215 TypeMappingTarget::TypeMappingTarget(Common::Type *p_target_type,
216 TypeMappingType_t p_mapping_type, Ttcn::Reference *p_function_ref)
217 : Node(), Location(), target_type(p_target_type),
218 mapping_type(p_mapping_type), checked(false)
219 {
220 if (!p_target_type || p_mapping_type != TM_FUNCTION || !p_function_ref)
221 FATAL_ERROR("TypeMappingTarget::TypeMappingTarget()");
222 u.func.function_ref = p_function_ref;
223 u.func.function_ptr = 0;
224 target_type->set_ownertype(Type::OT_TYPE_MAP_TARGET, this);
225 }
226
227 TypeMappingTarget::TypeMappingTarget(Common::Type *p_target_type,
228 TypeMappingType_t p_mapping_type,
229 Common::Type::MessageEncodingType_t p_coding_type, string *p_coding_options,
230 ErrorBehaviorList *p_eb_list)
231 : Node(), Location(), target_type(p_target_type),
232 mapping_type(p_mapping_type), checked(false)
233 {
234 if (!p_target_type || (p_mapping_type != TM_ENCODE &&
235 p_mapping_type != TM_DECODE))
236 FATAL_ERROR("TypeMappingTarget::TypeMappingTarget()");
237 u.encdec.coding_type = p_coding_type;
238 u.encdec.coding_options = p_coding_options;
239 u.encdec.eb_list = p_eb_list;
240 target_type->set_ownertype(Type::OT_TYPE_MAP_TARGET, this);
241 }
242
243 TypeMappingTarget::~TypeMappingTarget()
244 {
245 delete target_type;
246 switch (mapping_type) {
247 case TM_FUNCTION:
248 delete u.func.function_ref;
249 break;
250 case TM_ENCODE:
251 case TM_DECODE:
252 delete u.encdec.coding_options;
253 delete u.encdec.eb_list;
254 default:
255 break;
256 }
257 }
258
259 TypeMappingTarget *TypeMappingTarget::clone() const
260 {
261 FATAL_ERROR("TypeMappingTarget::clone");
262 }
263
264 void TypeMappingTarget::set_fullname(const string& p_fullname)
265 {
266 Node::set_fullname(p_fullname);
267 if (target_type) target_type->set_fullname(p_fullname + ".<target_type>");
268 switch (mapping_type) {
269 case TM_SIMPLE:
270 case TM_DISCARD:
271 break;
272 case TM_FUNCTION:
273 u.func.function_ref->set_fullname(p_fullname + ".<function_ref>");
274 break;
275 case TM_ENCODE:
276 case TM_DECODE:
277 if (u.encdec.eb_list)
278 u.encdec.eb_list->set_fullname(p_fullname + ".<errorbehavior>");
279 break;
280 default:
281 FATAL_ERROR("TypeMappingTarget::set_fullname()");
282 }
283 }
284
285 void TypeMappingTarget::set_my_scope(Common::Scope *p_scope)
286 {
287 if (target_type) target_type->set_my_scope(p_scope);
288 switch (mapping_type) {
289 case TM_SIMPLE:
290 case TM_DISCARD:
291 case TM_ENCODE:
292 case TM_DECODE:
293 break;
294 case TM_FUNCTION:
295 u.func.function_ref->set_my_scope(p_scope);
296 break;
297 default:
298 FATAL_ERROR("TypeMappingTarget::set_my_scope()");
299 }
300 }
301
302 const char *TypeMappingTarget::get_mapping_name() const
303 {
304 switch (mapping_type) {
305 case TM_SIMPLE:
306 return "simple";
307 case TM_DISCARD:
308 return "discard";
309 case TM_FUNCTION:
310 return "function";
311 case TM_ENCODE:
312 return "encode";
313 case TM_DECODE:
314 return "decode";
315 default:
316 return "<unknown mapping>";
317 }
318 }
319
320 Ttcn::Def_Function_Base *TypeMappingTarget::get_function() const
321 {
322 if (mapping_type != TM_FUNCTION || !checked)
323 FATAL_ERROR("TypeMappingTarget::get_function()");
324 return u.func.function_ptr;
325 }
326
327 Type::MessageEncodingType_t TypeMappingTarget::get_coding_type() const
328 {
329 if (mapping_type != TM_ENCODE && mapping_type != TM_DECODE)
330 FATAL_ERROR("TypeMappingTarget::get_coding_type()");
331 return u.encdec.coding_type;
332 }
333
334 bool TypeMappingTarget::has_coding_options() const
335 {
336 if (mapping_type != TM_ENCODE && mapping_type != TM_DECODE)
337 FATAL_ERROR("TypeMappingTarget::has_coding_options()");
338 return u.encdec.coding_options != 0;
339 }
340
341 const string& TypeMappingTarget::get_coding_options() const
342 {
343 if ((mapping_type != TM_ENCODE && mapping_type != TM_DECODE) ||
344 !u.encdec.coding_options)
345 FATAL_ERROR("TypeMappingTarget::get_coding_options()");
346 return *u.encdec.coding_options;
347 }
348
349 ErrorBehaviorList *TypeMappingTarget::get_eb_list() const
350 {
351 if (mapping_type != TM_ENCODE && mapping_type != TM_DECODE)
352 FATAL_ERROR("TypeMappingTarget::get_eb_list()");
353 return u.encdec.eb_list;
354 }
355
356 void TypeMappingTarget::chk_simple(Type *source_type)
357 {
358 Error_Context cntxt(this, "In `simple' mapping");
359 if (!source_type->is_identical(target_type)) {
360 target_type->error("The source and target types must be the same: "
361 "`%s' was expected instead of `%s'",
362 source_type->get_typename().c_str(),
363 target_type->get_typename().c_str());
364 }
365 }
366
367 void TypeMappingTarget::chk_function(Type *source_type)
368 {
369 Error_Context cntxt(this, "In `function' mapping");
370 Assignment *t_ass = u.func.function_ref->get_refd_assignment(false);
371 if (!t_ass) return;
372 t_ass->chk();
373 switch (t_ass->get_asstype()) {
374 case Assignment::A_FUNCTION:
375 case Assignment::A_FUNCTION_RVAL:
376 case Assignment::A_FUNCTION_RTEMP:
377 case Assignment::A_EXT_FUNCTION:
378 case Assignment::A_EXT_FUNCTION_RVAL:
379 case Assignment::A_EXT_FUNCTION_RTEMP:
380 break;
381 default:
382 u.func.function_ref->error("Reference to a function or external "
383 "function was expected instead of %s",
384 t_ass->get_description().c_str());
385 return;
386 }
387 u.func.function_ptr = dynamic_cast<Ttcn::Def_Function_Base*>(t_ass);
388 if (!u.func.function_ptr) FATAL_ERROR("TypeMappingTarget::chk_function()");
389 if (u.func.function_ptr->get_prototype() ==
390 Ttcn::Def_Function_Base::PROTOTYPE_NONE) {
391 u.func.function_ref->error("The referenced %s does not have `prototype' "
392 "attribute", u.func.function_ptr->get_description().c_str());
393 return;
394 }
395 Type *input_type = u.func.function_ptr->get_input_type();
396 if (input_type && !source_type->is_identical(input_type)) {
397 source_type->error("The input type of %s must be the same as the source "
398 "type of the mapping: `%s' was expected instead of `%s'",
399 u.func.function_ptr->get_description().c_str(),
400 source_type->get_typename().c_str(),
401 input_type->get_typename().c_str());
402 }
403 Type *output_type = u.func.function_ptr->get_output_type();
404 if (output_type && !target_type->is_identical(output_type)) {
405 target_type->error("The output type of %s must be the same as the "
406 "target type of the mapping: `%s' was expected instead of `%s'",
407 u.func.function_ptr->get_description().c_str(),
408 target_type->get_typename().c_str(),
409 output_type->get_typename().c_str());
410 }
411 }
412
413 void TypeMappingTarget::chk_encode(Type *source_type)
414 {
415 Error_Context cntxt(this, "In `encode' mapping");
416 if (!source_type->has_encoding(u.encdec.coding_type)) {
417 source_type->error("Source type `%s' does not support %s encoding",
418 source_type->get_typename().c_str(),
419 Type::get_encoding_name(u.encdec.coding_type));
420 }
421 Type *stream_type = Type::get_stream_type(u.encdec.coding_type);
422 if (!stream_type->is_identical(target_type)) {
423 target_type->error("Target type of %s encoding should be `%s' instead "
424 "of `%s'", Type::get_encoding_name(u.encdec.coding_type),
425 stream_type->get_typename().c_str(),
426 target_type->get_typename().c_str());
427 }
428 if (u.encdec.eb_list) u.encdec.eb_list->chk();
429 }
430
431 void TypeMappingTarget::chk_decode(Type *source_type)
432 {
433 Error_Context cntxt(this, "In `decode' mapping");
434 Type *stream_type = Type::get_stream_type(u.encdec.coding_type);
435 if (!stream_type->is_identical(source_type)) {
436 source_type->error("Source type of %s encoding should be `%s' instead "
437 "of `%s'", Type::get_encoding_name(u.encdec.coding_type),
438 stream_type->get_typename().c_str(),
439 source_type->get_typename().c_str());
440 }
441 if (!target_type->has_encoding(u.encdec.coding_type)) {
442 target_type->error("Target type `%s' does not support %s encoding",
443 target_type->get_typename().c_str(),
444 Type::get_encoding_name(u.encdec.coding_type));
445 }
446 if (u.encdec.eb_list) u.encdec.eb_list->chk();
447 }
448
449 void TypeMappingTarget::chk(Type *source_type)
450 {
451 if (checked) return;
452 checked = true;
453 if (target_type) {
454 Error_Context cntxt(target_type, "In target type");
455 target_type->chk();
456 }
457 switch (mapping_type) {
458 case TM_SIMPLE:
459 chk_simple(source_type);
460 break;
461 case TM_DISCARD:
462 break;
463 case TM_FUNCTION:
464 chk_function(source_type);
465 break;
466 case TM_ENCODE:
467 chk_encode(source_type);
468 break;
469 case TM_DECODE:
470 chk_decode(source_type);
471 break;
472 default:
473 FATAL_ERROR("TypeMappingTarget::chk()");
474 }
475 }
476
477 bool TypeMappingTarget::fill_type_mapping_target(
478 port_msg_type_mapping_target *target, Type *source_type,
479 Scope *p_scope, stringpool& pool)
480 {
481 bool has_sliding = false;
482 if (target_type) {
483 target->target_name = pool.add(target_type->get_genname_value(p_scope));
484 target->target_dispname = pool.add(target_type->get_typename());
485 } else {
486 target->target_name = NULL;
487 target->target_dispname = NULL;
488 }
489 switch (mapping_type) {
490 case TM_SIMPLE:
491 target->mapping_type = M_SIMPLE;
492 break;
493 case TM_DISCARD:
494 target->mapping_type = M_DISCARD;
495 break;
496 case TM_FUNCTION:
497 target->mapping_type = M_FUNCTION;
498 if (!u.func.function_ptr)
499 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
500 target->mapping.function.name =
501 pool.add(u.func.function_ptr->get_genname_from_scope(p_scope));
502 switch (u.func.function_ptr->get_prototype()) {
503 case Ttcn::Def_Function_Base::PROTOTYPE_CONVERT:
504 target->mapping.function.prototype = PT_CONVERT;
505 break;
506 case Ttcn::Def_Function_Base::PROTOTYPE_FAST:
507 target->mapping.function.prototype = PT_FAST;
508 break;
509 case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK:
510 target->mapping.function.prototype = PT_BACKTRACK;
511 break;
512 case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING:
513 target->mapping.function.prototype = PT_SLIDING;
514 has_sliding = true;
515 break;
516 default:
517 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
518 }
519 break;
520 case TM_ENCODE:
521 case TM_DECODE:
522 if (mapping_type == TM_ENCODE) {
523 target->mapping_type = M_ENCODE;
524 target->mapping.encdec.typedescr_name =
525 pool.add(source_type->get_genname_typedescriptor(p_scope));
526 } else {
527 target->mapping_type = M_DECODE;
528 target->mapping.encdec.typedescr_name =
529 pool.add(target_type->get_genname_typedescriptor(p_scope));
530 }
531 target->mapping.encdec.encoding_type =
532 Type::get_encoding_name(u.encdec.coding_type);
533 if (u.encdec.coding_options) target->mapping.encdec.encoding_options =
534 u.encdec.coding_options->c_str();
535 else target->mapping.encdec.encoding_options = NULL;
536 if (u.encdec.eb_list) {
537 char *str = u.encdec.eb_list->generate_code(memptystr());
538 target->mapping.encdec.errorbehavior = pool.add(string(str));
539 Free(str);
540 } else {
541 target->mapping.encdec.errorbehavior =
542 "TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, "
543 "TTCN_EncDec::EB_DEFAULT);\n";
544 }
545 break;
546 default:
547 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
548 }
549 return has_sliding;
550 }
551
552 void TypeMappingTarget::dump(unsigned level) const
553 {
554 DEBUG(level, "target:");
555 if (target_type) target_type->dump(level + 1);
556 else DEBUG(level + 1, "<none>");
557 DEBUG(level, "mapping type: %s", get_mapping_name());
558 switch (mapping_type) {
559 case TM_FUNCTION:
560 u.func.function_ref->dump(level + 1);
561 break;
562 case TM_ENCODE:
563 case TM_DECODE:
564 DEBUG(level + 1, "encoding: %s",
565 Type::get_encoding_name(u.encdec.coding_type));
566 if (u.encdec.coding_options)
567 DEBUG(level + 1, "options: %s", u.encdec.coding_options->c_str());
568 if (u.encdec.eb_list) u.encdec.eb_list->dump(level + 1);
569 default:
570 break;
571 }
572 }
573
574 // =================================
575 // ===== TypeMappingTargets
576 // =================================
577
578 TypeMappingTargets::~TypeMappingTargets()
579 {
580 size_t nof_targets = targets_v.size();
581 for (size_t i = 0; i < nof_targets; i++) delete targets_v[i];
582 targets_v.clear();
583 }
584
585 TypeMappingTargets *TypeMappingTargets::clone() const
586 {
587 FATAL_ERROR("TypeMappingTargets::clone");
588 }
589
590 void TypeMappingTargets::set_fullname(const string& p_fullname)
591 {
592 Node::set_fullname(p_fullname);
593 size_t nof_targets = targets_v.size();
594 for (size_t i = 0; i < nof_targets; i++) {
595 targets_v[i]->set_fullname(p_fullname + ".<target" + Int2string(i + 1)
596 + ">");
597 }
598 }
599
600 void TypeMappingTargets::set_my_scope(Scope *p_scope)
601 {
602 size_t nof_targets = targets_v.size();
603 for (size_t i = 0; i < nof_targets; i++)
604 targets_v[i]->set_my_scope(p_scope);
605 }
606
607 void TypeMappingTargets::add_target(TypeMappingTarget *p_target)
608 {
609 if (!p_target) FATAL_ERROR("TypeMappingTargets::add_target()");
610 targets_v.add(p_target);
611 }
612
613 void TypeMappingTargets::dump(unsigned level) const
614 {
615 size_t nof_targets = targets_v.size();
616 DEBUG(level, "Targets: (%lu pcs.)", (unsigned long) nof_targets);
617 for (size_t i = 0; i < nof_targets; i++) targets_v[i]->dump(level + 1);
618 }
619
620 // =================================
621 // ===== TypeMapping
622 // =================================
623
624 TypeMapping::TypeMapping(Type *p_source_type, TypeMappingTargets *p_targets)
625 : Node(), Location(), source_type(p_source_type), targets(p_targets)
626 {
627 if (!p_source_type || !p_targets)
628 FATAL_ERROR("TypeMapping::TypeMapping()");
629 source_type->set_ownertype(Type::OT_TYPE_MAP, this);
630 }
631
632 TypeMapping::~TypeMapping()
633 {
634 delete source_type;
635 delete targets;
636 }
637
638 TypeMapping *TypeMapping::clone() const
639 {
640 FATAL_ERROR("TypeMapping::clone");
641 }
642
643 void TypeMapping::set_fullname(const string& p_fullname)
644 {
645 Node::set_fullname(p_fullname);
646 source_type->set_fullname(p_fullname + ".<source_type>");
647 targets->set_fullname(p_fullname);
648 }
649
650 void TypeMapping::set_my_scope(Scope *p_scope)
651 {
652 source_type->set_my_scope(p_scope);
653 targets->set_my_scope(p_scope);
654 }
655
656 void TypeMapping::chk()
657 {
658 Error_Context cntxt(this, "In type mapping");
659 {
660 Error_Context cntxt2(source_type, "In source type");
661 source_type->chk();
662 }
663 size_t nof_targets = targets->get_nof_targets();
664 bool has_sliding = false, has_non_sliding = false;
665 for (size_t i = 0; i < nof_targets; i++) {
666 TypeMappingTarget *target = targets->get_target_byIndex(i);
667 target->chk(source_type);
668 if (nof_targets > 1) {
669 switch (target->get_mapping_type()) {
670 case TypeMappingTarget::TM_DISCARD:
671 if (has_sliding) target->error("Mapping `discard' cannot be used "
672 "if functions with `prototype(sliding)' are referred from the same "
673 "source type");
674 else if (i < nof_targets - 1) target->error("Mapping `discard' must "
675 "be the last target of the source type");
676 break;
677 case TypeMappingTarget::TM_FUNCTION: {
678 Ttcn::Def_Function_Base *t_function = target->get_function();
679 if (t_function) {
680 switch (t_function->get_prototype()) {
681 case Ttcn::Def_Function_Base::PROTOTYPE_NONE:
682 break;
683 case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK:
684 has_non_sliding = true;
685 break;
686 case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING:
687 has_sliding = true;
688 break;
689 default:
690 target->error("The referenced %s must have the attribute "
691 "`prototype(backtrack)' or `prototype(sliding)' when more "
692 "than one targets are present",
693 t_function->get_description().c_str());
694 }
695 }
696 break; }
697 case TypeMappingTarget::TM_DECODE:
698 break;
699 default:
700 target->error("The type of the mapping must be `function', `decode' "
701 "or `discard' instead of `%s' when more than one targets are "
702 "present", target->get_mapping_name());
703 }
704 }
705 }
706 if (has_sliding && has_non_sliding) {
707 error("If one of the mappings refers to a function with attribute "
708 "`prototype(sliding)' then mappings of this source type cannot refer "
709 "to functions with attribute `prototype(backtrack)'");
710 }
711 }
712
713 void TypeMapping::dump(unsigned level) const
714 {
715 DEBUG(level, "Source type:");
716 source_type->dump(level + 1);
717 targets->dump(level);
718 }
719
720 // =================================
721 // ===== TypeMappings
722 // =================================
723
724 TypeMappings::~TypeMappings()
725 {
726 size_t nof_mappings = mappings_v.size();
727 for (size_t i = 0; i < nof_mappings; i++) delete mappings_v[i];
728 mappings_v.clear();
729 mappings_m.clear();
730 }
731
732 TypeMappings *TypeMappings::clone() const
733 {
734 FATAL_ERROR("TypeMappings::clone");
735 }
736
737 void TypeMappings::set_fullname(const string& p_fullname)
738 {
739 Node::set_fullname(p_fullname);
740 size_t nof_mappings = mappings_v.size();
741 for (size_t i = 0; i < nof_mappings; i++) {
742 mappings_v[i]->set_fullname(p_fullname + ".<mapping" + Int2string(i + 1)
743 + ">");
744 }
745 }
746
747 void TypeMappings::set_my_scope(Scope *p_scope)
748 {
749 size_t nof_mappings = mappings_v.size();
750 for (size_t i = 0; i < nof_mappings; i++)
751 mappings_v[i]->set_my_scope(p_scope);
752 }
753
754 void TypeMappings::add_mapping(TypeMapping *p_mapping)
755 {
756 if (checked || !p_mapping) FATAL_ERROR("TypeMappings::add_mapping()");
757 mappings_v.add(p_mapping);
758 }
759
760 void TypeMappings::steal_mappings(TypeMappings *p_mappings)
761 {
762 if (checked || !p_mappings || p_mappings->checked)
763 FATAL_ERROR("TypeMappings::steal_mappings()");
764 size_t nof_mappings = p_mappings->mappings_v.size();
765 for (size_t i = 0; i < nof_mappings; i++)
766 mappings_v.add(p_mappings->mappings_v[i]);
767 p_mappings->mappings_v.clear();
768 join_location(*p_mappings);
769 }
770
771 bool TypeMappings::has_mapping_for_type(Type *p_type) const
772 {
773 if (!checked || !p_type)
774 FATAL_ERROR("TypeMappings::has_mapping_for_type()");
775 if (p_type->get_type_refd_last()->get_typetype() == Type::T_ERROR)
776 return true;
777 else return mappings_m.has_key(p_type->get_typename());
778 }
779
780 TypeMapping *TypeMappings::get_mapping_byType(Type *p_type) const
781 {
782 if (!checked || !p_type)
783 FATAL_ERROR("TypeMappings::get_mapping_byType()");
784 return mappings_m[p_type->get_typename()];
785 }
786
787 void TypeMappings::chk()
788 {
789 if (checked) return;
790 checked = true;
791 size_t nof_mappings = mappings_v.size();
792 for (size_t i = 0; i < nof_mappings; i++) {
793 TypeMapping *mapping = mappings_v[i];
794 mapping->chk();
795 Type *source_type = mapping->get_source_type();
796 if (source_type->get_type_refd_last()->get_typetype() != Type::T_ERROR) {
797 const string& source_type_name = source_type->get_typename();
798 if (mappings_m.has_key(source_type_name)) {
799 const char *source_type_name_str = source_type_name.c_str();
800 source_type->error("Duplicate mapping for type `%s'",
801 source_type_name_str);
802 mappings_m[source_type_name]->note("The mapping of type `%s' is "
803 "already given here", source_type_name_str);
804 } else mappings_m.add(source_type_name, mapping);
805 }
806 }
807 }
808
809 void TypeMappings::dump(unsigned level) const
810 {
811 size_t nof_mappings = mappings_v.size();
812 DEBUG(level, "type mappings: (%lu pcs.)", (unsigned long) nof_mappings);
813 for (size_t i = 0; i < nof_mappings; i++)
814 mappings_v[i]->dump(level + 1);
815 }
816
817 // =================================
818 // ===== Types
819 // =================================
820
821 Types::~Types()
822 {
823 size_t nof_types = types.size();
824 for (size_t i = 0; i < nof_types; i++) delete types[i];
825 types.clear();
826 }
827
828 Types *Types::clone() const
829 {
830 FATAL_ERROR("Types::clone");
831 }
832
833 void Types::add_type(Type *p_type)
834 {
835 if (!p_type) FATAL_ERROR("Types::add_type()");
836 p_type->set_ownertype(Type::OT_TYPE_LIST, this);
837 types.add(p_type);
838 }
839
840 Type *Types::extract_type_byIndex(size_t n)
841 {
842 Type *retval = types[n];
843 types[n] = 0;
844 return retval;
845 }
846
847 void Types::steal_types(Types *p_tl)
848 {
849 if (!p_tl) FATAL_ERROR("Types::steal_types()");
850 size_t nof_types = p_tl->types.size();
851 for (size_t i = 0; i < nof_types; i++) types.add(p_tl->types[i]);
852 p_tl->types.clear();
853 join_location(*p_tl);
854 }
855
856 void Types::set_fullname(const string& p_fullname)
857 {
858 Node::set_fullname(p_fullname);
859 size_t nof_types = types.size();
860 for (size_t i = 0; i < nof_types; i++)
861 types[i]->set_fullname(p_fullname + ".<type" + Int2string(i + 1) + ">");
862 }
863
864 void Types::set_my_scope(Scope *p_scope)
865 {
866 size_t nof_types = types.size();
867 for (size_t i = 0; i < nof_types; i++) types[i]->set_my_scope(p_scope);
868 }
869
870 void Types::dump(unsigned level) const
871 {
872 size_t nof_types = types.size();
873 DEBUG(level, "Types: (%lu pcs.)", (unsigned long) nof_types);
874 for (size_t i = 0; i < nof_types; i++) types[i]->dump(level + 1);
875 }
876
877 // =================================
878 // ===== TypeSet
879 // =================================
880
881 TypeSet::~TypeSet()
882 {
883 types_v.clear();
884 types_m.clear();
885 }
886
887 TypeSet *TypeSet::clone() const
888 {
889 FATAL_ERROR("TypeSet::clone()");
890 }
891
892 void TypeSet::add_type(Type *p_type)
893 {
894 if (!p_type) FATAL_ERROR("TypeSet::add_type()");
895 types_v.add(p_type);
896 types_m.add(p_type->get_typename(), p_type);
897 }
898
899 bool TypeSet::has_type(Type *p_type) const
900 {
901 if (!p_type) FATAL_ERROR("TypeSet::has_type()");
902 if (p_type->get_type_refd_last()->get_typetype() == Type::T_ERROR)
903 return true;
904 else return types_m.has_key(p_type->get_typename());
905 }
906
907 size_t TypeSet::get_nof_compatible_types(Type *p_type) const
908 {
909 if (!p_type) FATAL_ERROR("TypeSet::get_nof_compatible_types()");
910 if (p_type->get_type_refd_last()->get_typetype() == Type::T_ERROR) {
911 // Return a positive answer for erroneous types.
912 return 1;
913 } else {
914 size_t ret_val = 0;
915 size_t nof_types = types_v.size();
916 for (size_t i = 0; i < nof_types; i++) {
917 // Don't allow type compatibility.
918 if (types_v[i]->is_compatible(p_type, NULL)) ret_val++;
919 }
920 return ret_val;
921 }
922 }
923
924 size_t TypeSet::get_index_byType(Type *p_type) const
925 {
926 if (!p_type) FATAL_ERROR("TypeSet::get_index_byType()");
927 const string& name = p_type->get_typename();
928 size_t nof_types = types_v.size();
929 for (size_t i = 0; i < nof_types; i++)
930 if (types_v[i]->get_typename() == name) return i;
931 FATAL_ERROR("TypeSet::get_index_byType()");
932 return static_cast<size_t>(-1);
933 }
934
935 void TypeSet::dump(unsigned level) const
936 {
937 size_t nof_types = types_v.size();
938 DEBUG(level, "Types: (%lu pcs.)", (unsigned long) nof_types);
939 for (size_t i = 0; i < nof_types; i++) types_v[i]->dump(level + 1);
940 }
941
942 // =================================
943 // ===== PortTypeBody
944 // =================================
945
946 PortTypeBody::PortTypeBody(PortOperationMode_t p_operation_mode,
947 Types *p_in_list, Types *p_out_list, Types *p_inout_list,
948 bool p_in_all, bool p_out_all, bool p_inout_all)
949 : Node(), Location(), my_type(0), operation_mode(p_operation_mode),
950 in_list(p_in_list), out_list(p_out_list), inout_list(p_inout_list),
951 in_all(p_in_all), out_all(p_out_all), inout_all(p_inout_all),
952 checked(false),
953 in_msgs(0), out_msgs(0), in_sigs(0), out_sigs(0),
954 testport_type(TP_REGULAR), port_type(PT_REGULAR),
955 provider_ref(0), provider_type(0), in_mappings(0), out_mappings(0)
956 {
957 }
958
959 PortTypeBody::~PortTypeBody()
960 {
961 delete in_list;
962 delete out_list;
963 delete inout_list;
964 delete in_msgs;
965 delete out_msgs;
966 delete in_sigs;
967 delete out_sigs;
968 delete provider_ref;
969 delete in_mappings;
970 delete out_mappings;
971 }
972
973 PortTypeBody *PortTypeBody::clone() const
974 {
975 FATAL_ERROR("PortTypeBody::clone");
976 }
977
978 void PortTypeBody::set_fullname(const string& p_fullname)
979 {
980 Node::set_fullname(p_fullname);
981 if (in_list) in_list->set_fullname(p_fullname + ".<in_list>");
982 if (out_list) out_list->set_fullname(p_fullname + ".<out_list>");
983 if (inout_list) inout_list->set_fullname(p_fullname + ".<inout_list>");
984 if (in_msgs) in_msgs->set_fullname(p_fullname + ".<incoming_messages>");
985 if (out_msgs) out_msgs->set_fullname(p_fullname + ".<outgoing_messages>");
986 if (in_sigs) in_sigs->set_fullname(p_fullname + ".<incoming_signatures>");
987 if (out_sigs) out_sigs->set_fullname(p_fullname + ".<outgoing_signatures>");
988 if (provider_ref)
989 provider_ref->set_fullname(p_fullname + ".<provider_ref>");
990 if (in_mappings) in_mappings->set_fullname(p_fullname + ".<in_mappings>");
991 if (out_mappings)
992 out_mappings->set_fullname(p_fullname + ".<out_mappings>");
993 }
994
995 void PortTypeBody::set_my_scope(Scope *p_scope)
996 {
997 if (in_list) in_list->set_my_scope(p_scope);
998 if (out_list) out_list->set_my_scope(p_scope);
999 if (inout_list) inout_list->set_my_scope(p_scope);
1000 if (provider_ref) provider_ref->set_my_scope(p_scope);
1001 if (in_mappings) in_mappings->set_my_scope(p_scope);
1002 if (out_mappings) out_mappings->set_my_scope(p_scope);
1003 }
1004
1005 void PortTypeBody::set_my_type(Type *p_type)
1006 {
1007 if (!p_type || p_type->get_typetype() != Type::T_PORT)
1008 FATAL_ERROR("PortTypeBody::set_my_type()");
1009 my_type = p_type;
1010 }
1011
1012 TypeSet *PortTypeBody::get_in_msgs() const
1013 {
1014 if (!checked) FATAL_ERROR("PortTypeBody::get_in_msgs()");
1015 return in_msgs;
1016 }
1017
1018 TypeSet *PortTypeBody::get_out_msgs() const
1019 {
1020 if (!checked) FATAL_ERROR("PortTypeBody::get_out_msgs()");
1021 return out_msgs;
1022 }
1023
1024 TypeSet *PortTypeBody::get_in_sigs() const
1025 {
1026 if (!checked) FATAL_ERROR("PortTypeBody::get_in_sigs()");
1027 return in_sigs;
1028 }
1029
1030 TypeSet *PortTypeBody::get_out_sigs() const
1031 {
1032 if (!checked) FATAL_ERROR("PortTypeBody::get_out_sigs()");
1033 return out_sigs;
1034 }
1035
1036 bool PortTypeBody::has_queue() const
1037 {
1038 if (!checked) FATAL_ERROR("PortTypeBody::has_queue()");
1039 if (in_msgs || in_sigs) return true;
1040 if (out_sigs) {
1041 size_t nof_sigs = out_sigs->get_nof_types();
1042 for (size_t i = 0; i < nof_sigs; i++) {
1043 Type *t_sig = out_sigs->get_type_byIndex(i)->get_type_refd_last();
1044 if (!t_sig->is_nonblocking_signature() ||
1045 t_sig->get_signature_exceptions()) return true;
1046 }
1047 }
1048 return false;
1049 }
1050
1051 bool PortTypeBody::getreply_allowed() const
1052 {
1053 if (!checked) FATAL_ERROR("PortTypeBody::getreply_allowed()");
1054 if (out_sigs) {
1055 size_t nof_sigs = out_sigs->get_nof_types();
1056 for (size_t i = 0; i < nof_sigs; i++) {
1057 if (!out_sigs->get_type_byIndex(i)->get_type_refd_last()
1058 ->is_nonblocking_signature()) return true;
1059 }
1060 }
1061 return false;
1062 }
1063
1064 bool PortTypeBody::catch_allowed() const
1065 {
1066 if (!checked) FATAL_ERROR("PortTypeBody::catch_allowed()");
1067 if (out_sigs) {
1068 size_t nof_sigs = out_sigs->get_nof_types();
1069 for (size_t i = 0; i < nof_sigs; i++) {
1070 if (out_sigs->get_type_byIndex(i)->get_type_refd_last()
1071 ->get_signature_exceptions()) return true;
1072 }
1073 }
1074 return false;
1075 }
1076
1077 bool PortTypeBody::is_internal() const
1078 {
1079 if (!checked) FATAL_ERROR("PortTypeBody::is_internal_port()");
1080 return testport_type == TP_INTERNAL;
1081 }
1082
1083 Type *PortTypeBody::get_address_type()
1084 {
1085 if (!checked) FATAL_ERROR("PortTypeBody::get_address_type()");
1086 if (testport_type == TP_ADDRESS) {
1087 Type *t;
1088 // in case of 'user' port types the address visible and supported by the
1089 // 'provider' port type is relevant
1090 if (port_type == PT_USER && provider_type) t = provider_type;
1091 else t = my_type;
1092 return t->get_my_scope()->get_scope_mod()->get_address_type();
1093 } else {
1094 // the port type does not support SUT addresses
1095 return 0;
1096 }
1097 }
1098
1099 void PortTypeBody::add_provider_attribute()
1100 {
1101 port_type = PT_PROVIDER;
1102 delete provider_ref;
1103 provider_ref = 0;
1104 provider_type = 0;
1105 delete in_mappings;
1106 in_mappings = 0;
1107 delete out_mappings;
1108 out_mappings = 0;
1109 }
1110
1111 void PortTypeBody::add_user_attribute(Ttcn::Reference *p_provider_ref,
1112 TypeMappings *p_in_mappings, TypeMappings *p_out_mappings)
1113 {
1114 if (!p_provider_ref || !my_type)
1115 FATAL_ERROR("PortTypeBody::add_user_attribute()");
1116 Scope *t_scope = my_type->get_my_scope();
1117 const string& t_fullname = get_fullname();
1118 port_type = PT_USER;
1119 delete provider_ref;
1120 provider_ref = p_provider_ref;
1121 provider_ref->set_fullname(t_fullname + ".<provider_ref>");
1122 provider_ref->set_my_scope(t_scope);
1123 provider_type = 0;
1124 delete in_mappings;
1125 in_mappings = p_in_mappings;
1126 if (in_mappings) {
1127 in_mappings->set_fullname(t_fullname + ".<in_mappings>");
1128 in_mappings->set_my_scope(t_scope);
1129 }
1130 delete out_mappings;
1131 out_mappings = p_out_mappings;
1132 if (out_mappings) {
1133 out_mappings->set_fullname(t_fullname + ".<out_mappings>");
1134 out_mappings->set_my_scope(t_scope);
1135 }
1136 }
1137
1138 Type *PortTypeBody::get_provider_type() const
1139 {
1140 if (!checked || port_type != PT_USER)
1141 FATAL_ERROR("PortTypeBody::get_provider_type()");
1142 return provider_type;
1143 }
1144
1145 void PortTypeBody::chk_list(const Types *list, bool is_in, bool is_out)
1146 {
1147 const char *err_msg;
1148 if (is_in) {
1149 if (is_out) err_msg = "sent or received";
1150 else err_msg = "received";
1151 } else if (is_out) err_msg = "sent";
1152 else {
1153 FATAL_ERROR("PortTypeBody::chk_list()");
1154 err_msg = 0;
1155 }
1156 size_t nof_types = list->get_nof_types();
1157 for (size_t i = 0; i < nof_types; i++) {
1158 Type *t = list->get_type_byIndex(i);
1159 t->chk();
1160 // check if a value/template of this type can leave the component
1161 if (t->is_component_internal()) {
1162 map<Type*,void> type_chain;
1163 t->chk_component_internal(type_chain, "sent or received on a port");
1164 }
1165 Type *t_last = t->get_type_refd_last();
1166 switch (t_last->get_typetype()) {
1167 case Type::T_ERROR:
1168 // silently ignore
1169 break;
1170 case Type::T_SIGNATURE:
1171 if (operation_mode == PO_MESSAGE) {
1172 t->error("Signature `%s' cannot be used on a message based port",
1173 t_last->get_typename().c_str());
1174 }
1175 if (is_in) {
1176 if (in_sigs && in_sigs->has_type(t_last)) {
1177 const string& type_name = t_last->get_typename();
1178 t->error("Duplicate incoming signature `%s'", type_name.c_str());
1179 in_sigs->get_type_byName(type_name)->note("Signature `%s' is "
1180 "already listed here", type_name.c_str());
1181 } else {
1182 if (!in_sigs) {
1183 in_sigs = new TypeSet;
1184 in_sigs->set_fullname(get_fullname() + ".<incoming_signatures>");
1185 }
1186 in_sigs->add_type(t);
1187 }
1188 }
1189 if (is_out) {
1190 if (out_sigs && out_sigs->has_type(t_last)) {
1191 const string& type_name = t_last->get_typename();
1192 t->error("Duplicate outgoing signature `%s'", type_name.c_str());
1193 out_sigs->get_type_byName(type_name)->note("Signature `%s' is "
1194 "already listed here", type_name.c_str());
1195 } else {
1196 if (!out_sigs) {
1197 out_sigs = new TypeSet;
1198 out_sigs->set_fullname(get_fullname() + ".<outgoing_signatures>");
1199 }
1200 out_sigs->add_type(t);
1201 }
1202 }
1203 break;
1204 default:
1205 // t is a normal data type
1206 if (operation_mode == PO_PROCEDURE) {
1207 t->error("Data type `%s' cannot be %s on a procedure based port",
1208 t_last->get_typename().c_str(), err_msg);
1209 }
1210 if (is_in) {
1211 if (in_msgs && in_msgs->has_type(t_last)) {
1212 const string& type_name = t_last->get_typename();
1213 t->error("Duplicate incoming message type `%s'", type_name.c_str());
1214 in_msgs->get_type_byName(type_name)->note("Type `%s' is already "
1215 "listed here", type_name.c_str());
1216 } else {
1217 if (!in_msgs) {
1218 in_msgs = new TypeSet;
1219 in_msgs->set_fullname(get_fullname() + ".<incoming_messages>");
1220 }
1221 in_msgs->add_type(t);
1222 }
1223 }
1224 if (is_out) {
1225 if (out_msgs && out_msgs->has_type(t_last)) {
1226 const string& type_name = t_last->get_typename();
1227 t->error("Duplicate outgoing message type `%s'", type_name.c_str());
1228 out_msgs->get_type_byName(type_name)->note("Type `%s' is already "
1229 "listed here", type_name.c_str());
1230 } else {
1231 if (!out_msgs) {
1232 out_msgs = new TypeSet;
1233 out_msgs->set_fullname(get_fullname() + ".<outgoing_messages>");
1234 }
1235 out_msgs->add_type(t);
1236 }
1237 }
1238 }
1239 }
1240 }
1241
1242 void PortTypeBody::chk_user_attribute()
1243 {
1244 Error_Context cntxt(this, "In extension attribute `user'");
1245 // check the reference that points to the provider type
1246 provider_type = 0;
1247 PortTypeBody *provider_body = 0;
1248 Assignment *t_ass = provider_ref->get_refd_assignment(); // provider port
1249 if (t_ass) {
1250 if (t_ass->get_asstype() == Assignment::A_TYPE) {
1251 Type *t = t_ass->get_Type()->get_type_refd_last();
1252 if (t->get_typetype() == Type::T_PORT) {
1253 provider_type = t;
1254 provider_body = t->get_PortBody();
1255 } else {
1256 provider_ref->error("Type reference `%s' does not refer to a port "
1257 "type", provider_ref->get_dispname().c_str());
1258 }
1259 } else {
1260 provider_ref->error("Reference `%s' does not refer to a type",
1261 provider_ref->get_dispname().c_str());
1262 }
1263 }
1264
1265 // checking the consistency of attributes in this and provider_body
1266 if (provider_body && testport_type != TP_INTERNAL) {
1267 if (provider_body->port_type != PT_PROVIDER) {
1268 provider_ref->error("The referenced port type `%s' must have the "
1269 "`provider' attribute", provider_type->get_typename().c_str());
1270 }
1271 switch (provider_body->testport_type) {
1272 case TP_REGULAR:
1273 if (testport_type == TP_ADDRESS) {
1274 provider_ref->error("Attribute `address' cannot be used because the "
1275 "provider port type `%s' does not have attribute `address'",
1276 provider_type->get_typename().c_str());
1277 }
1278 break;
1279 case TP_INTERNAL:
1280 provider_ref->error("Missing attribute `internal'. Provider port "
1281 "type `%s' has attribute `internal', which must be also present here",
1282 provider_type->get_typename().c_str());
1283 case TP_ADDRESS:
1284 break;
1285 default:
1286 FATAL_ERROR("PortTypeBody::chk_attributes()");
1287 }
1288 // inherit the test port API type from the provider
1289 testport_type = provider_body->testport_type;
1290 }
1291
1292 // checking the incoming mappings
1293 if (in_mappings) {
1294 Error_Context cntxt2(in_mappings, "In `in' mappings");
1295 in_mappings->chk();
1296 // checking source types
1297 if (provider_body) {
1298 if (provider_body->in_msgs) {
1299 // check if all source types are present on the `in' list of the
1300 // provider
1301 size_t nof_mappings = in_mappings->get_nof_mappings();
1302 for (size_t i = 0; i < nof_mappings; i++) {
1303 Type *source_type =
1304 in_mappings->get_mapping_byIndex(i)->get_source_type();
1305 if (!provider_body->in_msgs->has_type(source_type)) {
1306 source_type->error("Source type `%s' of the `in' mapping is not "
1307 "present on the list of incoming messages in provider port "
1308 "type `%s'", source_type->get_typename().c_str(),
1309 provider_type->get_typename().c_str());
1310 }
1311 }
1312 // check if all types of the `in' list of the provider are handled by
1313 // the mappings
1314 size_t nof_msgs = provider_body->in_msgs->get_nof_types();
1315 for (size_t i = 0; i < nof_msgs; i++) {
1316 Type *msg_type = provider_body->in_msgs->get_type_byIndex(i);
1317 if (!in_mappings->has_mapping_for_type(msg_type)) {
1318 in_mappings->error("Incoming message type `%s' of provider "
1319 "port type `%s' is not handled by the incoming mappings",
1320 msg_type->get_typename().c_str(),
1321 provider_type->get_typename().c_str());
1322 }
1323 }
1324 } else {
1325 in_mappings->error("Invalid incoming mappings. Provider port type "
1326 "`%s' does not have incoming message types",
1327 provider_type->get_typename().c_str());
1328 }
1329 }
1330 // checking target types
1331 size_t nof_mappings = in_mappings->get_nof_mappings();
1332 for (size_t i = 0; i < nof_mappings; i++) {
1333 TypeMapping *mapping = in_mappings->get_mapping_byIndex(i);
1334 size_t nof_targets = mapping->get_nof_targets();
1335 for (size_t j = 0; j < nof_targets; j++) {
1336 Type *target_type =
1337 mapping->get_target_byIndex(j)->get_target_type();
1338 if (target_type && (!in_msgs || !in_msgs->has_type(target_type))) {
1339 target_type->error("Target type `%s' of the `in' mapping is not "
1340 "present on the list of incoming messages in user port type "
1341 "`%s'", target_type->get_typename().c_str(),
1342 my_type->get_typename().c_str());
1343 }
1344 }
1345 }
1346 } else if (provider_body && provider_body->in_msgs) {
1347 error("Missing `in' mappings to handle the incoming message types of "
1348 "provider port type `%s'", provider_type->get_typename().c_str());
1349 }
1350
1351 // checking the outgoing mappings
1352 if (out_mappings) {
1353 Error_Context cntxt2(out_mappings, "In `out' mappings");
1354 out_mappings->chk();
1355 // checking source types
1356 if (out_msgs) {
1357 // check if all source types are present on the `out' list
1358 size_t nof_mappings = out_mappings->get_nof_mappings();
1359 for (size_t i = 0; i < nof_mappings; i++) {
1360 Type *source_type =
1361 out_mappings->get_mapping_byIndex(i)->get_source_type();
1362 if (!out_msgs->has_type(source_type)) {
1363 source_type->error("Source type `%s' of the `out' mapping is not "
1364 "present on the list of outgoing messages in user port type `%s'",
1365 source_type->get_typename().c_str(),
1366 my_type->get_typename().c_str());
1367 }
1368 }
1369 // check if all types of the `out' list are handled by the mappings
1370 size_t nof_msgs = out_msgs->get_nof_types();
1371 for (size_t i = 0; i < nof_msgs; i++) {
1372 Type *msg_type = out_msgs->get_type_byIndex(i);
1373 if (!out_mappings->has_mapping_for_type(msg_type)) {
1374 out_mappings->error("Outgoing message type `%s' of user port type "
1375 "`%s' is not handled by the outgoing mappings",
1376 msg_type->get_typename().c_str(),
1377 my_type->get_typename().c_str());
1378 }
1379 }
1380 } else {
1381 out_mappings->error("Invalid outgoing mappings. User port type "
1382 "`%s' does not have outgoing message types",
1383 my_type->get_typename().c_str());
1384 }
1385 // checking target types
1386 if (provider_body) {
1387 size_t nof_mappings = out_mappings->get_nof_mappings();
1388 for (size_t i = 0; i < nof_mappings; i++) {
1389 TypeMapping *mapping = out_mappings->get_mapping_byIndex(i);
1390 size_t nof_targets = mapping->get_nof_targets();
1391 for (size_t j = 0; j < nof_targets; j++) {
1392 Type *target_type =
1393 mapping->get_target_byIndex(j)->get_target_type();
1394 if (target_type && (!provider_body->out_msgs ||
1395 !provider_body->out_msgs->has_type(target_type))) {
1396 target_type->error("Target type `%s' of the `out' mapping is "
1397 "not present on the list of outgoing messages in provider "
1398 "port type `%s'", target_type->get_typename().c_str(),
1399 provider_type->get_typename().c_str());
1400 }
1401 }
1402 }
1403 }
1404 } else if (out_msgs) {
1405 error("Missing `out' mappings to handle the outgoing message types of "
1406 "user port type `%s'", my_type->get_typename().c_str());
1407 }
1408
1409 // checking the compatibility of signature lists
1410 if (provider_body) {
1411 if (in_sigs) {
1412 size_t nof_sigs = in_sigs->get_nof_types();
1413 for (size_t i = 0; i < nof_sigs; i++) {
1414 Type *t_sig = in_sigs->get_type_byIndex(i);
1415 if (!provider_body->in_sigs ||
1416 !provider_body->in_sigs->has_type(t_sig)) {
1417 Type *t_sig_last = t_sig->get_type_refd_last();
1418 if (!t_sig_last->is_nonblocking_signature() ||
1419 t_sig_last->get_signature_exceptions())
1420 t_sig->error("Incoming signature `%s' of user port type `%s' is "
1421 "not present on the list of incoming signatures in provider "
1422 "port type `%s'", t_sig->get_typename().c_str(),
1423 my_type->get_typename().c_str(),
1424 provider_type->get_typename().c_str());
1425 }
1426 }
1427 }
1428
1429 if (provider_body->in_sigs) {
1430 size_t nof_sigs = provider_body->in_sigs->get_nof_types();
1431 for (size_t i = 0; i < nof_sigs; i++) {
1432 Type *t_sig = provider_body->in_sigs->get_type_byIndex(i);
1433 if (!in_sigs || !in_sigs->has_type(t_sig)) {
1434 error("Incoming signature `%s' of provider port type `%s' is not "
1435 "present on the list of incoming signatures in user port type "
1436 "`%s'", t_sig->get_typename().c_str(),
1437 provider_type->get_typename().c_str(),
1438 my_type->get_typename().c_str());
1439 }
1440 }
1441 }
1442
1443 if (out_sigs) {
1444 size_t nof_sigs = out_sigs->get_nof_types();
1445 for (size_t i = 0; i < nof_sigs; i++) {
1446 Type *t_sig = out_sigs->get_type_byIndex(i);
1447 if (!provider_body->out_sigs ||
1448 !provider_body->out_sigs->has_type(t_sig)) {
1449 t_sig->error("Outgoing signature `%s' of user port type `%s' is "
1450 "not present on the list of outgoing signatures in provider port "
1451 "type `%s'", t_sig->get_typename().c_str(),
1452 my_type->get_typename().c_str(),
1453 provider_type->get_typename().c_str());
1454 }
1455 }
1456 }
1457
1458 if (provider_body->out_sigs) {
1459 size_t nof_sigs = provider_body->out_sigs->get_nof_types();
1460 for (size_t i = 0; i < nof_sigs; i++) {
1461 Type *t_sig = provider_body->out_sigs->get_type_byIndex(i);
1462 if (!out_sigs || !out_sigs->has_type(t_sig)) {
1463 Type *t_sig_last = t_sig->get_type_refd_last();
1464 if (!t_sig_last->is_nonblocking_signature() ||
1465 t_sig_last->get_signature_exceptions())
1466 error("Outgoing signature `%s' of provider port type `%s' is not "
1467 "present on the list of outgoing signatures in user port type "
1468 "`%s'", t_sig->get_typename().c_str(),
1469 provider_type->get_typename().c_str(),
1470 my_type->get_typename().c_str());
1471 }
1472 }
1473 }
1474 }
1475 }
1476
1477 void PortTypeBody::chk()
1478 {
1479 if (checked) return;
1480 checked = true;
1481
1482 // checking 'all' directives
1483 if (inout_all) {
1484 if (in_all) {
1485 warning("Redundant `in all' and `inout all' directives");
1486 in_all = false;
1487 }
1488 if (out_all) {
1489 warning("Redundant `out all' and `inout all' directives");
1490 out_all = false;
1491 }
1492 warning("Unsupported `inout all' directive was ignored");
1493 } else {
1494 if (in_all) warning("Unsupported `in all' directive was ignored");
1495 if (out_all) warning("Unsupported `out all' directive was ignored");
1496 }
1497
1498 // checking message/signature lists
1499 if (in_list) {
1500 Error_Context cntxt(in_list, "In `in' list");
1501 chk_list(in_list, true, false);
1502 }
1503 if (out_list) {
1504 Error_Context cntxt(out_list, "In `out' list");
1505 chk_list(out_list, false, true);
1506 }
1507 if (inout_list) {
1508 Error_Context cntxt(inout_list, "In `inout' list");
1509 chk_list(inout_list, true, true);
1510 }
1511 }
1512
1513 void PortTypeBody::chk_attributes(Ttcn::WithAttribPath *w_attrib_path)
1514 {
1515 if (!w_attrib_path || !checked || !my_type)
1516 FATAL_ERROR("PortTypeBody::chk_attributes()");
1517
1518 Ttcn::ExtensionAttributes * extarts = parse_extattributes(w_attrib_path);
1519 if (extarts != 0) { // NULL means parsing error
1520 size_t num_atrs = extarts->size();
1521 for (size_t k = 0; k < num_atrs; ++k) {
1522 ExtensionAttribute &ea = extarts->get(k);
1523 switch (ea.get_type()) {
1524 case ExtensionAttribute::PORT_API: { // internal or address
1525 const PortTypeBody::TestPortAPI_t api = ea.get_api();
1526 if (api == PortTypeBody::TP_INTERNAL) {
1527 switch (testport_type) {
1528 case PortTypeBody::TP_REGULAR:
1529 break;
1530 case PortTypeBody::TP_INTERNAL: {
1531 ea.warning("Duplicate attribute `internal'");
1532 break; }
1533 case PortTypeBody::TP_ADDRESS: {
1534 ea.error("Attributes `address' and `internal' "
1535 "cannot be used at the same time");
1536 break; }
1537 default:
1538 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1539 }
1540 set_testport_type(PortTypeBody::TP_INTERNAL);
1541 }
1542 else if (api == PortTypeBody::TP_ADDRESS) {
1543 switch (testport_type) {
1544 case PortTypeBody::TP_REGULAR:
1545 break;
1546 case PortTypeBody::TP_INTERNAL: {
1547 ea.error("Attributes `internal' and `address' "
1548 "cannot be used at the same time");
1549 break; }
1550 case PortTypeBody::TP_ADDRESS: {
1551 ea.warning("Duplicate attribute `address'");
1552 break; }
1553 default:
1554 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1555 }
1556 set_testport_type(PortTypeBody::TP_ADDRESS);
1557 }
1558 break; }
1559
1560 case ExtensionAttribute::PORT_TYPE_PROVIDER:
1561 switch (port_type) {
1562 case PortTypeBody::PT_REGULAR:
1563 break;
1564 case PortTypeBody::PT_PROVIDER: {
1565 ea.warning("Duplicate attribute `provider'");
1566 break; }
1567 case PortTypeBody::PT_USER: {
1568 ea.error("Attributes `user' and `provider' "
1569 "cannot be used at the same time");
1570 break; }
1571 default:
1572 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1573 }
1574 add_provider_attribute();
1575 break;
1576
1577 case ExtensionAttribute::PORT_TYPE_USER:
1578 switch (port_type) {
1579 case PortTypeBody::PT_REGULAR:
1580 break;
1581 case PortTypeBody::PT_PROVIDER: {
1582 ea.error("Attributes `provider' and `user' "
1583 "cannot be used at the same time");
1584 break; }
1585 case PortTypeBody::PT_USER: {
1586 ea.error("Duplicate attribute `user'");
1587 break; }
1588 default:
1589 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1590 }
1591 Reference *ref;
1592 TypeMappings *in;
1593 TypeMappings *out;
1594 ea.get_user(ref, in, out);
1595 add_user_attribute(ref, in, out);
1596 break;
1597
1598 case ExtensionAttribute::ANYTYPELIST:
1599 break; // ignore it
1600
1601 case ExtensionAttribute::NONE:
1602 break; // ignore, do not issue "wrong type" error
1603
1604 default:
1605 ea.error("Port can only have the following extension attributes: "
1606 "'provider', 'user', 'internal' or 'address'");
1607 break;
1608 } // switch
1609 } // next attribute
1610 delete extarts;
1611 } // if not null
1612
1613 if (port_type == PT_USER) chk_user_attribute();
1614 else if (testport_type == TP_ADDRESS) {
1615 Error_Context cntxt(this, "In extension attribute `address'");
1616 Common::Module *my_mod = my_type->get_my_scope()->get_scope_mod();
1617 if (!my_mod->get_address_type())
1618 error("Type `address' is not defined in module `%s'",
1619 my_mod->get_modid().get_dispname().c_str());
1620 }
1621 }
1622
1623 bool PortTypeBody::is_connectable(PortTypeBody *p_other) const
1624 {
1625 if (!checked || !p_other || !p_other->checked)
1626 FATAL_ERROR("Type::is_connectable()");
1627 if (out_msgs) {
1628 if (!p_other->in_msgs) return false;
1629 size_t nof_msgs = out_msgs->get_nof_types();
1630 for (size_t i = 0; i < nof_msgs; i++) {
1631 if (!p_other->in_msgs->has_type(out_msgs->get_type_byIndex(i)))
1632 return false;
1633 }
1634 }
1635 if (out_sigs) {
1636 if (!p_other->in_sigs) return false;
1637 size_t nof_sigs = out_sigs->get_nof_types();
1638 for (size_t i = 0; i < nof_sigs; i++) {
1639 if (!p_other->in_sigs->has_type(out_sigs->get_type_byIndex(i)))
1640 return false;
1641 }
1642 }
1643 return true;
1644 }
1645
1646 void PortTypeBody::report_connection_errors(PortTypeBody *p_other) const
1647 {
1648 if (!checked || !my_type || !p_other || !p_other->checked ||
1649 !p_other->my_type)
1650 FATAL_ERROR("PortTypeBody::report_connection_errors()");
1651 const string& my_typename = my_type->get_typename();
1652 const char *my_typename_str = my_typename.c_str();
1653 const string& other_typename = p_other->my_type->get_typename();
1654 const char *other_typename_str = other_typename.c_str();
1655 if (out_msgs) {
1656 size_t nof_msgs = out_msgs->get_nof_types();
1657 for (size_t i = 0; i < nof_msgs; i++) {
1658 Type *t_msg = out_msgs->get_type_byIndex(i);
1659 if (!p_other->in_msgs || !p_other->in_msgs->has_type(t_msg)) {
1660 t_msg->note("Outgoing message type `%s' of port type `%s' is not "
1661 "present on the incoming list of port type `%s'",
1662 t_msg->get_typename().c_str(), my_typename_str, other_typename_str);
1663 }
1664 }
1665 }
1666 if (out_sigs) {
1667 size_t nof_sigs = out_sigs->get_nof_types();
1668 for (size_t i = 0; i < nof_sigs; i++) {
1669 Type *t_sig = out_sigs->get_type_byIndex(i);
1670 if (!p_other->in_sigs || !p_other->in_sigs->has_type(t_sig)) {
1671 t_sig->note("Outgoing signature `%s' of port type `%s' is not "
1672 "present on the incoming list of port type `%s'",
1673 t_sig->get_typename().c_str(), my_typename_str, other_typename_str);
1674 }
1675 }
1676 }
1677 }
1678
1679 bool PortTypeBody::is_mappable(PortTypeBody *p_other) const
1680 {
1681 if (!checked || !p_other || !p_other->checked)
1682 FATAL_ERROR("PortTypeBody::is_mappable()");
1683 // shortcut: every port type can be mapped to itself
1684 if (this == p_other) return true;
1685 // outgoing lists of this should be covered by outgoing lists of p_other
1686 if (out_msgs) {
1687 if (!p_other->out_msgs) return false;
1688 size_t nof_msgs = out_msgs->get_nof_types();
1689 for (size_t i = 0; i < nof_msgs; i++) {
1690 if (!p_other->out_msgs->has_type(out_msgs->get_type_byIndex(i)))
1691 return false;
1692 }
1693 }
1694 if (out_sigs) {
1695 if (!p_other->out_sigs) return false;
1696 size_t nof_sigs = out_sigs->get_nof_types();
1697 for (size_t i = 0; i < nof_sigs; i++) {
1698 if (!p_other->out_sigs->has_type(out_sigs->get_type_byIndex(i)))
1699 return false;
1700 }
1701 }
1702 // incoming lists of p_other should be covered by incoming lists of this
1703 if (p_other->in_msgs) {
1704 if (!in_msgs) return false;
1705 size_t nof_msgs = p_other->in_msgs->get_nof_types();
1706 for (size_t i = 0; i < nof_msgs; i++) {
1707 if (!in_msgs->has_type(p_other->in_msgs->get_type_byIndex(i)))
1708 return false;
1709 }
1710 }
1711 if (p_other->in_sigs) {
1712 if (!in_sigs) return false;
1713 size_t nof_sigs = p_other->in_sigs->get_nof_types();
1714 for (size_t i = 0; i < nof_sigs; i++) {
1715 if (!in_sigs->has_type(p_other->in_sigs->get_type_byIndex(i)))
1716 return false;
1717 }
1718 }
1719 return true;
1720 }
1721
1722 void PortTypeBody::report_mapping_errors(PortTypeBody *p_other) const
1723 {
1724 if (!checked || !my_type || !p_other || !p_other->checked ||
1725 !p_other->my_type) FATAL_ERROR("PortTypeBody::report_mapping_errors()");
1726 const string& my_typename = my_type->get_typename();
1727 const char *my_typename_str = my_typename.c_str();
1728 const string& other_typename = p_other->my_type->get_typename();
1729 const char *other_typename_str = other_typename.c_str();
1730 if (out_msgs) {
1731 size_t nof_msgs = out_msgs->get_nof_types();
1732 for (size_t i = 0; i < nof_msgs; i++) {
1733 Type *t_msg = out_msgs->get_type_byIndex(i);
1734 if (!p_other->out_msgs || !p_other->out_msgs->has_type(t_msg)) {
1735 t_msg->note("Outgoing message type `%s' of test component "
1736 "port type `%s' is not present on the outgoing list of "
1737 "system port type `%s'", t_msg->get_typename().c_str(),
1738 my_typename_str, other_typename_str);
1739 }
1740 }
1741 }
1742 if (out_sigs) {
1743 size_t nof_sigs = out_sigs->get_nof_types();
1744 for (size_t i = 0; i < nof_sigs; i++) {
1745 Type *t_sig = out_sigs->get_type_byIndex(i);
1746 if (!p_other->out_sigs || !p_other->out_sigs->has_type(t_sig)) {
1747 t_sig->note("Outgoing signature `%s' of test component port type "
1748 "`%s' is not present on the outgoing list of system port type "
1749 "`%s'", t_sig->get_typename().c_str(), my_typename_str,
1750 other_typename_str);
1751 }
1752 }
1753 }
1754 if (p_other->in_msgs) {
1755 size_t nof_msgs = p_other->in_msgs->get_nof_types();
1756 for (size_t i = 0; i < nof_msgs; i++) {
1757 Type *t_msg = p_other->in_msgs->get_type_byIndex(i);
1758 if (!in_msgs || !in_msgs->has_type(t_msg)) {
1759 t_msg->note("Incoming message type `%s' of system port type `%s' "
1760 "is not present on the incoming list of test component port type "
1761 "`%s'", t_msg->get_typename().c_str(), other_typename_str,
1762 my_typename_str);
1763 }
1764 }
1765 }
1766 if (p_other->in_sigs) {
1767 size_t nof_sigs = p_other->in_sigs->get_nof_types();
1768 for (size_t i = 0; i < nof_sigs; i++) {
1769 Type *t_sig = p_other->in_sigs->get_type_byIndex(i);
1770 if (!in_sigs || !in_sigs->has_type(t_sig)) {
1771 t_sig->note("Incoming signature `%s' of system port type `%s' is "
1772 "not present on the incoming list of test component port type "
1773 "`%s'", t_sig->get_typename().c_str(), other_typename_str,
1774 my_typename_str);
1775 }
1776 }
1777 }
1778 }
1779
1780 void PortTypeBody::generate_code(output_struct *target)
1781 {
1782 if (!checked || !my_type) FATAL_ERROR("PortTypeBody::generate_code()");
1783 stringpool pool;
1784 port_def pdef;
1785 memset(&pdef, 0, sizeof(pdef));
1786 const string& t_genname = my_type->get_genname_own();
1787 pdef.name = t_genname.c_str();
1788 pdef.dispname = my_type->get_fullname().c_str();
1789 pdef.filename = pool.add(Identifier::name_2_ttcn(t_genname));
1790 Scope *my_scope = my_type->get_my_scope();
1791 const Identifier& modid = my_scope->get_scope_mod_gen()->get_modid();
1792 pdef.module_name = modid.get_name().c_str();
1793 pdef.module_dispname = modid.get_ttcnname().c_str();
1794 if (testport_type == TP_ADDRESS) {
1795 Type *t_address = get_address_type();
1796 if (!t_address) FATAL_ERROR("PortTypeBody::generate_code()");
1797 pdef.address_name = pool.add(t_address->get_genname_value(my_scope));
1798 } else pdef.address_name = NULL;
1799
1800 if (in_msgs) {
1801 pdef.msg_in.nElements = in_msgs->get_nof_types();
1802 pdef.msg_in.elements = (port_msg_type*)
1803 Malloc(pdef.msg_in.nElements * sizeof(*pdef.msg_in.elements));
1804 for (size_t i = 0; i < pdef.msg_in.nElements; i++) {
1805 Type *type = in_msgs->get_type_byIndex(i);
1806 pdef.msg_in.elements[i].name =
1807 pool.add(type->get_genname_value(my_scope));
1808 pdef.msg_in.elements[i].dispname = pool.add(type->get_typename());
1809 }
1810 } else {
1811 pdef.msg_in.nElements = 0;
1812 pdef.msg_in.elements = NULL;
1813 }
1814 if (out_msgs) {
1815 pdef.msg_out.nElements = out_msgs->get_nof_types();
1816 pdef.msg_out.elements = (port_msg_mapped_type*)
1817 Malloc(pdef.msg_out.nElements * sizeof(*pdef.msg_out.elements));
1818 for (size_t i = 0; i < pdef.msg_out.nElements; i++) {
1819 Type *type = out_msgs->get_type_byIndex(i);
1820 port_msg_mapped_type *mapped_type = pdef.msg_out.elements + i;
1821 mapped_type->name = pool.add(type->get_genname_value(my_scope));
1822 mapped_type->dispname = pool.add(type->get_typename());
1823 if (port_type == PT_USER) {
1824 if (!out_mappings) FATAL_ERROR("PortTypeBody::generate_code()");
1825 TypeMapping *mapping = out_mappings->get_mapping_byType(type);
1826 mapped_type->nTargets = mapping->get_nof_targets();
1827 mapped_type->targets = (port_msg_type_mapping_target*)
1828 Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets));
1829 for (size_t j = 0; j < mapped_type->nTargets; j++) {
1830 mapping->get_target_byIndex(j)->fill_type_mapping_target(
1831 mapped_type->targets + j, type, my_scope, pool);
1832 mapped_type->targets[j].target_index = static_cast<size_t>(-1);
1833 }
1834 } else {
1835 mapped_type->nTargets = 0;
1836 mapped_type->targets = NULL;
1837 }
1838 }
1839 } else {
1840 pdef.msg_out.nElements = 0;
1841 pdef.msg_out.elements = NULL;
1842 }
1843
1844 if (in_sigs) {
1845 pdef.proc_in.nElements = in_sigs->get_nof_types();
1846 pdef.proc_in.elements = (port_proc_signature*)
1847 Malloc(pdef.proc_in.nElements * sizeof(*pdef.proc_in.elements));
1848 for (size_t i = 0; i < pdef.proc_in.nElements; i++) {
1849 Type *signature = in_sigs->get_type_byIndex(i)->get_type_refd_last();
1850 pdef.proc_in.elements[i].name =
1851 pool.add(signature->get_genname_value(my_scope));
1852 pdef.proc_in.elements[i].dispname =
1853 pool.add(signature->get_typename());
1854 pdef.proc_in.elements[i].is_noblock =
1855 signature->is_nonblocking_signature();
1856 pdef.proc_in.elements[i].has_exceptions =
1857 signature->get_signature_exceptions() ? TRUE : FALSE;
1858 }
1859 } else {
1860 pdef.proc_in.nElements = 0;
1861 pdef.proc_in.elements = NULL;
1862 }
1863 if (out_sigs) {
1864 pdef.proc_out.nElements = out_sigs->get_nof_types();
1865 pdef.proc_out.elements = (port_proc_signature*)
1866 Malloc(pdef.proc_out.nElements * sizeof(*pdef.proc_out.elements));
1867 for (size_t i = 0; i < pdef.proc_out.nElements; i++) {
1868 Type *signature = out_sigs->get_type_byIndex(i)->get_type_refd_last();
1869 pdef.proc_out.elements[i].name =
1870 pool.add(signature->get_genname_value(my_scope));
1871 pdef.proc_out.elements[i].dispname =
1872 pool.add(signature->get_typename());
1873 pdef.proc_out.elements[i].is_noblock =
1874 signature->is_nonblocking_signature();
1875 pdef.proc_out.elements[i].has_exceptions =
1876 signature->get_signature_exceptions() ? TRUE : FALSE;
1877 }
1878 } else {
1879 pdef.proc_out.nElements = 0;
1880 pdef.proc_out.elements = NULL;
1881 }
1882
1883 switch (testport_type) {
1884 case TP_REGULAR:
1885 pdef.testport_type = NORMAL;
1886 break;
1887 case TP_INTERNAL:
1888 pdef.testport_type = INTERNAL;
1889 break;
1890 case TP_ADDRESS:
1891 pdef.testport_type = ADDRESS;
1892 break;
1893 default:
1894 FATAL_ERROR("PortTypeBody::generate_code()");
1895 }
1896
1897 if (port_type == PT_USER) {
1898 pdef.port_type = USER;
1899 if (!provider_type) FATAL_ERROR("PortTypeBody::generate_code()");
1900 pdef.provider_name =
1901 pool.add(provider_type->get_genname_value(my_scope));
1902 PortTypeBody *provider_body = provider_type->get_PortBody();
1903 if (provider_body->in_msgs) {
1904 if (!in_mappings) // !this->in_msgs OK for an all-discard mapping
1905 FATAL_ERROR("PortTypeBody::generate_code()");
1906 pdef.provider_msg_in.nElements =
1907 provider_body->in_msgs->get_nof_types();
1908 pdef.provider_msg_in.elements = (port_msg_mapped_type*)
1909 Malloc(pdef.provider_msg_in.nElements *
1910 sizeof(*pdef.provider_msg_in.elements));
1911 for (size_t i = 0; i < pdef.provider_msg_in.nElements; i++) {
1912 Type *type = provider_body->in_msgs->get_type_byIndex(i);
1913 port_msg_mapped_type *mapped_type = pdef.provider_msg_in.elements + i;
1914 mapped_type->name = pool.add(type->get_genname_value(my_scope));
1915 mapped_type->dispname = pool.add(type->get_typename());
1916 TypeMapping *mapping = in_mappings->get_mapping_byType(type);
1917 mapped_type->nTargets = mapping->get_nof_targets();
1918 mapped_type->targets = (port_msg_type_mapping_target*)
1919 Malloc(mapped_type->nTargets * sizeof(*mapped_type->targets));
1920 for (size_t j = 0; j < mapped_type->nTargets; j++) {
1921 TypeMappingTarget *t_target = mapping->get_target_byIndex(j);
1922 pdef.has_sliding |= t_target->fill_type_mapping_target(
1923 mapped_type->targets + j, type, my_scope, pool);
1924 Type *target_type = t_target->get_target_type();
1925 if (target_type) {
1926 if (!in_msgs) FATAL_ERROR("PortTypeBody::generate_code()");
1927 mapped_type->targets[j].target_index =
1928 in_msgs->get_index_byType(target_type);
1929 } else {
1930 // the message will be discarded: fill in a dummy index
1931 mapped_type->targets[j].target_index = static_cast<size_t>(-1);
1932 }
1933 }
1934 }
1935 } else {
1936 pdef.provider_msg_in.nElements = 0;
1937 pdef.provider_msg_in.elements = NULL;
1938 }
1939 } else {
1940 // "internal provider" is the same as "internal"
1941 if (port_type == PT_PROVIDER && testport_type != TP_INTERNAL)
1942 pdef.port_type = PROVIDER;
1943 else pdef.port_type = REGULAR;
1944 pdef.provider_name = NULL;
1945 pdef.provider_msg_in.nElements = 0;
1946 pdef.provider_msg_in.elements = NULL;
1947 }
1948
1949 defPortClass(&pdef, target);
1950 if (generate_skeleton && testport_type != TP_INTERNAL &&
1951 port_type != PT_USER) generateTestPortSkeleton(&pdef);
1952
1953 Free(pdef.msg_in.elements);
1954 for (size_t i = 0; i < pdef.msg_out.nElements; i++)
1955 Free(pdef.msg_out.elements[i].targets);
1956 Free(pdef.msg_out.elements);
1957 Free(pdef.proc_in.elements);
1958 Free(pdef.proc_out.elements);
1959 for (size_t i = 0; i < pdef.provider_msg_in.nElements; i++)
1960 Free(pdef.provider_msg_in.elements[i].targets);
1961 Free(pdef.provider_msg_in.elements);
1962 }
1963
1964 void PortTypeBody::dump(unsigned level) const
1965 {
1966 switch (operation_mode) {
1967 case PO_MESSAGE:
1968 DEBUG(level, "mode: message");
1969 break;
1970 case PO_PROCEDURE:
1971 DEBUG(level, "mode: procedure");
1972 break;
1973 case PO_MIXED:
1974 DEBUG(level, "mode: mixed");
1975 break;
1976 default:
1977 DEBUG(level, "mode: <invalid>");
1978 }
1979 if (in_list) {
1980 DEBUG(level, "in list:");
1981 in_list->dump(level + 1);
1982 }
1983 if (in_all) DEBUG(level, "in all");
1984 if (out_list) {
1985 DEBUG(level, "out list:");
1986 out_list->dump(level + 1);
1987 }
1988 if (out_all) DEBUG(level, "out all");
1989 if (inout_list) {
1990 DEBUG(level, "inout list:");
1991 inout_list->dump(level + 1);
1992 }
1993 if (inout_all) DEBUG(level, "inout all");
1994 if (in_msgs) {
1995 DEBUG(level, "incoming messages:");
1996 in_msgs->dump(level + 1);
1997 }
1998 if (out_msgs) {
1999 DEBUG(level, "outgoing messages:");
2000 out_msgs->dump(level + 1);
2001 }
2002 if (in_sigs) {
2003 DEBUG(level, "incoming signatures:");
2004 in_sigs->dump(level + 1);
2005 }
2006 if (out_sigs) {
2007 DEBUG(level, "outgoing signatures:");
2008 out_sigs->dump(level + 1);
2009 }
2010 switch (testport_type) {
2011 case TP_REGULAR:
2012 break;
2013 case TP_INTERNAL:
2014 DEBUG(level, "attribute: internal");
2015 break;
2016 case TP_ADDRESS:
2017 DEBUG(level, "attribute: address");
2018 break;
2019 default:
2020 DEBUG(level, "attribute: <unknown>");
2021 }
2022 switch (port_type) {
2023 case PT_REGULAR:
2024 break;
2025 case PT_PROVIDER:
2026 DEBUG(level, "attribute: provider");
2027 break;
2028 case PT_USER:
2029 DEBUG(level, "attribute: user");
2030 break;
2031 default:
2032 DEBUG(level, "attribute: <unknown>");
2033 }
2034 if (provider_ref)
2035 DEBUG(level, "provider type: %s", provider_ref->get_dispname().c_str());
2036 if (in_mappings) {
2037 DEBUG(level, "in mappings:");
2038 in_mappings->dump(level + 1);
2039 }
2040 if (out_mappings) {
2041 DEBUG(level, "out mappings:");
2042 out_mappings->dump(level + 1);
2043 }
2044 }
2045
2046 // =================================
2047 // ===== ExtensionAttribute
2048 // =================================
2049 static const string version_template("RnXnn");
2050
2051 void ExtensionAttribute::check_product_number(const char* ABCClass, int type_number, int sequence) {
2052 if (NULL == ABCClass && 0 == type_number && 0 == sequence) {
2053 return;
2054 }
2055
2056 int ABCLength = strlen(ABCClass);
2057 if (ABCLength < 3 || ABCLength > 5) {
2058 // incorrect ABC number
2059 type_ = NONE;
2060 return;
2061 }
2062
2063 if (type_number >= 1000) {
2064 type_ = NONE;
2065 return;
2066 }
2067
2068 if (sequence >= 10000 ) {
2069 type_ = NONE;
2070 }
2071 }
2072
2073 void ExtensionAttribute::parse_version(Identifier *ver) {
2074 unsigned int rel, bld = 99;
2075 char patch[4] = {0,0,0,0};
2076 // The limit of max three characters is an optimization: any more than two
2077 // is already an error and we can quit scanning. We can't limit the field
2078 // to two by using "%2[...] because then we can't distinguish between R1AA
2079 // and R1AAA. The switch below makes the distinction between one character
2080 // like R1A (valid), two characters like R1AA (also valid), and
2081 // R1AAA (invalid).
2082 // in addition after the RmXnn part some characters may come (needed by TitanSim)
2083 char extra_junk[64];
2084 int scanned = sscanf(ver->get_dispname().c_str(), "R%u%3[A-HJ-NS-VX-Z]%u%63s",
2085 &rel, patch, &bld, extra_junk);
2086 value_.version_.extra_ = NULL;
2087 switch (scanned * (patch[2]==0)) {
2088 case 4: // all fields + titansim's extra stuff scanned
2089 if (strlen(extra_junk)>0) {
2090 value_.version_.extra_ = mprintf("%s", extra_junk);
2091 }
2092 case 3: // all fields scanned
2093 case 2: // 2 scanned, bld remained unmodified
2094 value_.version_.release_ = rel;
2095 value_.version_.build_ = bld;
2096 switch (patch[0]) {
2097 case 'A': case 'B': case 'C': case 'D':
2098 case 'E': case 'F': case 'G': case 'H':
2099 value_.version_.patch_ = patch[0] - 'A';
2100 break;
2101 case 'J': case 'K': case 'L': case 'M': case 'N':
2102 value_.version_.patch_ = patch[0] - 'A' - 1;
2103 break;
2104 case 'S': case 'T': case 'U': case 'V':
2105 value_.version_.patch_ = patch[0] - 'A' - 5;
2106 break;
2107 case 'X': case 'Y': case 'Z':
2108 value_.version_.patch_ = patch[0] - 'A' - 6;
2109 break;
2110
2111 case 'I': case 'W': // forbidden
2112 case 'O': case 'P': case 'Q': case 'R': // forbidden
2113 default: // incorrect
2114 type_ = NONE;
2115 break;
2116 }
2117 break;
2118 default: // there was an error
2119 type_ = NONE;
2120 break;
2121 }
2122 }
2123
2124 ExtensionAttribute::ExtensionAttribute(const char* ABCClass, int type_number,
2125 int sequence, int suffix, Identifier *ver)
2126 : Location(), type_(VERSION), value_()
2127 {
2128 if (ver == NULL) FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2129 value_.version_.module_ = NULL;
2130
2131 check_product_number(ABCClass, type_number, sequence);
2132 parse_version(ver);
2133 if (type_ != NONE) {
2134 value_.version_.productNumber_ =
2135 NULL == ABCClass ? NULL : mprintf("%s %d %d", ABCClass, type_number, sequence);
2136 value_.version_.suffix_ = suffix;
2137 delete ver; // "took care of it"
2138 }
2139 }
2140
2141 ExtensionAttribute::ExtensionAttribute(Identifier *mod, const char* ABCClass,
2142 int type_number, int sequence, int suffix, Identifier *ver)
2143 : Location(), type_(REQUIRES), value_()
2144 {
2145 if (mod == NULL || ver == NULL)
2146 FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2147 // store the module identifier
2148 value_.version_.module_ = mod;
2149
2150 check_product_number(ABCClass, type_number, sequence);
2151 parse_version(ver);
2152 if (type_ == NONE) { // parse_version reported an error
2153 value_.version_.module_ = NULL; // disown it; caller will free
2154 value_.version_.suffix_ = suffix;
2155 } else {
2156 value_.version_.productNumber_ =
2157 NULL == ABCClass ? NULL : mprintf("%s %d %d", ABCClass, type_number, sequence);
2158 value_.version_.suffix_ = suffix;
2159 delete ver;
2160 }
2161 }
2162
2163 ExtensionAttribute::ExtensionAttribute(const char* ABCClass, int type_number,
2164 int sequence, int suffix, Identifier* ver, extension_t et)
2165 : Location(), type_(et), value_()
2166 {
2167 if (ver == NULL) FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2168
2169 switch (et) {
2170 case REQ_TITAN:
2171 check_product_number(ABCClass, type_number, sequence);
2172 parse_version(ver);
2173 if (type_ != NONE) {
2174 value_.version_.productNumber_ =
2175 NULL == ABCClass ? NULL : mprintf("%s %d %d", ABCClass, type_number, sequence);
2176 value_.version_.suffix_ = suffix;
2177 delete ver; // "took care of it"
2178 } else {
2179 value_.version_.suffix_ = suffix;
2180 }
2181 break;
2182
2183 case VERSION_TEMPLATE: // RnXnn without the <>, must match exactly
2184 if (ver->get_name() == version_template) {
2185 value_.version_.productNumber_ = NULL;
2186 value_.version_.suffix_ = UINT_MAX;
2187 value_.version_.release_ = UINT_MAX;
2188 value_.version_.patch_ = UINT_MAX;
2189 value_.version_.build_ = UINT_MAX;
2190 delete ver;
2191 return;
2192 }
2193 else type_ = NONE;
2194 break;
2195
2196 default:
2197 FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2198 break;
2199 }
2200
2201 }
2202
2203
2204 ExtensionAttribute::~ExtensionAttribute()
2205 {
2206 switch (type_) {
2207 case NONE:
2208 break; // nothing to do, data has been extracted
2209 // TODO perhaps NONE should be the only acceptable option?
2210 // (no unprocessed attribute allowed)
2211 case PROTOTYPE:
2212 break;
2213 case ENCODE: case DECODE:
2214 delete value_.encdec_.s_;
2215 break;
2216 case PORT_API:
2217 break;
2218 case PORT_TYPE_USER:
2219 delete value_.user_.ref_;
2220 delete value_.user_.inmaps_;
2221 delete value_.user_.outmaps_;
2222 break;
2223 case PORT_TYPE_PROVIDER:
2224 break;
2225 case ERRORBEHAVIOR:
2226 delete value_.ebl_;
2227 break;
2228 case ANYTYPELIST:
2229 delete value_.anytypes_;
2230 break;
2231 case ENCDECVALUE:
2232 delete value_.encdecvalue_.inmaps_;
2233 delete value_.encdecvalue_.outmaps_;
2234 break;
2235 case VERSION:
2236 case VERSION_TEMPLATE:
2237 Free(value_.version_.productNumber_);
2238 Free(value_.version_.extra_);
2239 break;
2240 case REQUIRES:
2241 Free(value_.version_.productNumber_);
2242 Free(value_.version_.extra_);
2243 delete value_.version_.module_;
2244 break;
2245 case REQ_TITAN:
2246 Free(value_.version_.productNumber_);
2247 Free(value_.version_.extra_);
2248 break;
2249 case TRANSPARENT:
2250 break;
2251 case PRINTING:
2252 delete value_.pt_;
2253 break;
2254 default: // can't happen
2255 FATAL_ERROR("ExtensionAttribute::~ExtensionAttribute(%X)", type_);
2256 }
2257 }
2258
2259 Types *ExtensionAttribute::get_types()
2260 {
2261 if (type_ != ANYTYPELIST) FATAL_ERROR("ExtensionAttribute::get_types()");
2262 type_ = NONE;
2263 return value_.anytypes_;
2264 }
2265
2266 Ttcn::Def_Function_Base::prototype_t ExtensionAttribute::get_proto()
2267 {
2268 if (type_ != PROTOTYPE) FATAL_ERROR("ExtensionAttribute::get_proto()");
2269 type_ = NONE;
2270 return value_.proto_;
2271 }
2272
2273 void ExtensionAttribute::get_encdec_parameters(
2274 Type::MessageEncodingType_t &p_encoding_type, string *&p_encoding_options)
2275 {
2276 if (type_ != ENCODE && type_ != DECODE)
2277 FATAL_ERROR("ExtensionAttribute::get_encdec_parameters()");
2278 type_ = NONE;
2279 p_encoding_type = value_.encdec_.mess_;
2280 p_encoding_options = value_.encdec_.s_;
2281 const_cast<ExtensionAttribute*>(this)->value_.encdec_.s_ = 0;
2282 }
2283
2284 ErrorBehaviorList *ExtensionAttribute::get_eb_list()
2285 {
2286 if (type_ != ERRORBEHAVIOR)
2287 FATAL_ERROR("ExtensionAttribute::get_eb_list()");
2288 type_ = NONE;
2289 ErrorBehaviorList *retval = value_.ebl_;
2290 const_cast<ExtensionAttribute*>(this)->value_.ebl_ = 0;
2291 return retval;
2292 }
2293
2294 PrintingType *ExtensionAttribute::get_printing()
2295 {
2296 if (type_ != PRINTING)
2297 FATAL_ERROR("ExtensionAttribute::get_printing()");
2298 type_ = NONE;
2299 PrintingType *retval = value_.pt_;
2300 const_cast<ExtensionAttribute*>(this)->value_.pt_ = 0;
2301 return retval;
2302 }
2303
2304 PortTypeBody::TestPortAPI_t ExtensionAttribute::get_api()
2305 {
2306 if (type_ != PORT_API)
2307 FATAL_ERROR("ExtensionAttribute::get_api()");
2308 type_ = NONE;
2309 return value_.api_;
2310 }
2311
2312 void ExtensionAttribute::get_user(Reference *&ref,
2313 TypeMappings *&in, TypeMappings *&out)
2314 {
2315 if (type_ != PORT_TYPE_USER)
2316 FATAL_ERROR("ExtensionAttribute::get_user()");
2317 type_ = NONE;
2318
2319 ref = value_.user_.ref_;
2320 in = value_.user_.inmaps_;
2321 out = value_.user_.outmaps_;
2322
2323 value_.user_.ref_ = 0;
2324 value_.user_.inmaps_ = 0;
2325 value_.user_.outmaps_ = 0;
2326 }
2327
2328 void ExtensionAttribute::get_encdecvalue_mappings(
2329 TypeMappings *&in, TypeMappings *&out)
2330 {
2331 if (type_ != ENCDECVALUE)
2332 FATAL_ERROR("ExtensionAttribute::get_encdecvalue_mappings()");
2333
2334 in = value_.encdecvalue_.inmaps_;
2335 out = value_.encdecvalue_.outmaps_;
2336 }
2337
2338 //FIXME ot is update -elni kell.
2339 Common::Identifier *ExtensionAttribute::get_id(
2340 char*& product_number, unsigned int& suffix,
2341 unsigned int& rel, unsigned int& patch, unsigned int& bld, char*& extra)
2342 {
2343 if ( type_ != REQUIRES && type_ != REQ_TITAN
2344 && type_ != VERSION && type_ != VERSION_TEMPLATE) {
2345 FATAL_ERROR("ExtensionAttribute::get_id()");
2346 }
2347 product_number = value_.version_.productNumber_;
2348 suffix = value_.version_.suffix_;
2349 rel = value_.version_.release_;
2350 patch = value_.version_.patch_;
2351 bld = value_.version_.build_;
2352 extra = value_.version_.extra_;
2353 return value_.version_.module_;
2354 }
2355
2356 // =================================
2357 // ===== ExtensionAttributes
2358 // =================================
2359 void ExtensionAttributes::add(ExtensionAttribute *a)
2360 {
2361 vector<ExtensionAttribute>::add(a);
2362 }
2363
2364 ExtensionAttributes::~ExtensionAttributes()
2365 {
2366 for (int i = size()-1; i >= 0; --i)
2367 delete operator [](i);
2368 clear();
2369 }
2370
2371 void ExtensionAttributes::import(ExtensionAttributes *other)
2372 {
2373 size_t n = other->size();
2374 for (size_t i = 0; i < n; ++i) {
2375 vector<ExtensionAttribute>::add((*other)[i]);
2376 }
2377 other->clear();
2378 }
2379
2380 } // namespace Ttcn
This page took 0.080116 seconds and 5 git commands to generate.