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