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"
10 #include "../CompilerError.hh"
11 #include "AST_ttcn3.hh"
13 #include "Attributes.hh"
16 // implemented in coding_attrib_p.y
17 extern Ttcn::ExtensionAttributes
* parse_extattributes(
18 Ttcn::WithAttribPath
*w_attrib_path
);
22 // =================================
23 // ===== ErrorBehaviorSetting
24 // =================================
26 ErrorBehaviorSetting
*ErrorBehaviorSetting::clone() const
28 FATAL_ERROR("ErrorBehaviorSetting::clone");
31 void ErrorBehaviorSetting::dump(unsigned level
) const
33 DEBUG(level
, "%s : %s", error_type
.c_str(), error_handling
.c_str());
36 // =================================
37 // ===== ErrorBehaviorList
38 // =================================
40 ErrorBehaviorList::~ErrorBehaviorList()
42 for (size_t i
= 0; i
< ebs_v
.size(); i
++)
48 ErrorBehaviorList
*ErrorBehaviorList::clone() const
50 FATAL_ERROR("ErrorBehaviorList::clone");
53 void ErrorBehaviorList::set_fullname(const string
& p_fullname
)
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) + ">");
61 void ErrorBehaviorList::add_ebs(ErrorBehaviorSetting
*p_ebs
)
63 if (!p_ebs
|| checked
) FATAL_ERROR("ErrorBehaviorList::add_ebs()");
67 void ErrorBehaviorList::steal_ebs(ErrorBehaviorList
*p_eblist
)
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
);
77 bool ErrorBehaviorList::has_setting(const string
& p_error_type
)
80 return ebs_all
!= 0 || ebs_m
.has_key(p_error_type
);
83 string
ErrorBehaviorList::get_handling(const string
& p_error_type
)
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");
92 void ErrorBehaviorList::chk()
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
) {
102 ebs
->warning("Duplicate setting for error type `ALL'");
103 ebs_all
->warning("The previous setting is ignored");
106 if (!ebs_m
.empty()) {
107 ebs
->warning("All settings before `ALL' are ignored");
111 if (ebs_m
.has_key(error_type
)) {
112 ebs
->warning("Duplicate setting for error type `%s'",
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
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
) {
133 ebs
->warning("String `%s' is not a valid error type",
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;
147 if (!handling_found
) {
148 ebs
->warning("String `%s' is not a valid error handling",
149 error_handling
.c_str());
155 char *ErrorBehaviorList::generate_code(char *str
)
157 if (!checked
) FATAL_ERROR("ErrorBehaviorList::generate_code()");
158 const string
all_str("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());
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");
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());
177 void ErrorBehaviorList::dump(unsigned level
) const
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);
184 // =================================
185 // ===== PrintingType
186 // =================================
188 PrintingType
*PrintingType::clone() const
190 FATAL_ERROR("PrintingType::clone");
193 char *PrintingType::generate_code(char *str
)
195 return mputprintf(str
, ", %d", (PT_PRETTY
== printing
) ? 1 : 0);
198 // =================================
199 // ===== TypeMappingTarget
200 // =================================
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)
207 if (p_mapping_type
== TM_SIMPLE
&& p_target_type
!= NULL
) { // acceptable
208 target_type
->set_ownertype(Type::OT_TYPE_MAP_TARGET
, this);
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()");
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)
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);
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)
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);
243 TypeMappingTarget::~TypeMappingTarget()
246 switch (mapping_type
) {
248 delete u
.func
.function_ref
;
252 delete u
.encdec
.coding_options
;
253 delete u
.encdec
.eb_list
;
259 TypeMappingTarget
*TypeMappingTarget::clone() const
261 FATAL_ERROR("TypeMappingTarget::clone");
264 void TypeMappingTarget::set_fullname(const string
& p_fullname
)
266 Node::set_fullname(p_fullname
);
267 if (target_type
) target_type
->set_fullname(p_fullname
+ ".<target_type>");
268 switch (mapping_type
) {
273 u
.func
.function_ref
->set_fullname(p_fullname
+ ".<function_ref>");
277 if (u
.encdec
.eb_list
)
278 u
.encdec
.eb_list
->set_fullname(p_fullname
+ ".<errorbehavior>");
281 FATAL_ERROR("TypeMappingTarget::set_fullname()");
285 void TypeMappingTarget::set_my_scope(Common::Scope
*p_scope
)
287 if (target_type
) target_type
->set_my_scope(p_scope
);
288 switch (mapping_type
) {
295 u
.func
.function_ref
->set_my_scope(p_scope
);
298 FATAL_ERROR("TypeMappingTarget::set_my_scope()");
302 const char *TypeMappingTarget::get_mapping_name() const
304 switch (mapping_type
) {
316 return "<unknown mapping>";
320 Ttcn::Def_Function_Base
*TypeMappingTarget::get_function() const
322 if (mapping_type
!= TM_FUNCTION
|| !checked
)
323 FATAL_ERROR("TypeMappingTarget::get_function()");
324 return u
.func
.function_ptr
;
327 Type::MessageEncodingType_t
TypeMappingTarget::get_coding_type() const
329 if (mapping_type
!= TM_ENCODE
&& mapping_type
!= TM_DECODE
)
330 FATAL_ERROR("TypeMappingTarget::get_coding_type()");
331 return u
.encdec
.coding_type
;
334 bool TypeMappingTarget::has_coding_options() const
336 if (mapping_type
!= TM_ENCODE
&& mapping_type
!= TM_DECODE
)
337 FATAL_ERROR("TypeMappingTarget::has_coding_options()");
338 return u
.encdec
.coding_options
!= 0;
341 const string
& TypeMappingTarget::get_coding_options() const
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
;
349 ErrorBehaviorList
*TypeMappingTarget::get_eb_list() const
351 if (mapping_type
!= TM_ENCODE
&& mapping_type
!= TM_DECODE
)
352 FATAL_ERROR("TypeMappingTarget::get_eb_list()");
353 return u
.encdec
.eb_list
;
356 void TypeMappingTarget::chk_simple(Type
*source_type
)
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());
367 void TypeMappingTarget::chk_function(Type
*source_type
)
369 Error_Context
cntxt(this, "In `function' mapping");
370 Assignment
*t_ass
= u
.func
.function_ref
->get_refd_assignment(false);
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
:
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());
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());
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());
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());
413 void TypeMappingTarget::chk_encode(Type
*source_type
)
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
));
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());
428 if (u
.encdec
.eb_list
) u
.encdec
.eb_list
->chk();
431 void TypeMappingTarget::chk_decode(Type
*source_type
)
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());
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
));
446 if (u
.encdec
.eb_list
) u
.encdec
.eb_list
->chk();
449 void TypeMappingTarget::chk(Type
*source_type
)
454 Error_Context
cntxt(target_type
, "In target type");
457 switch (mapping_type
) {
459 chk_simple(source_type
);
464 chk_function(source_type
);
467 chk_encode(source_type
);
470 chk_decode(source_type
);
473 FATAL_ERROR("TypeMappingTarget::chk()");
477 bool TypeMappingTarget::fill_type_mapping_target(
478 port_msg_type_mapping_target
*target
, Type
*source_type
,
479 Scope
*p_scope
, stringpool
& pool
)
481 bool has_sliding
= false;
483 target
->target_name
= pool
.add(target_type
->get_genname_value(p_scope
));
484 target
->target_dispname
= pool
.add(target_type
->get_typename());
486 target
->target_name
= NULL
;
487 target
->target_dispname
= NULL
;
489 switch (mapping_type
) {
491 target
->mapping_type
= M_SIMPLE
;
494 target
->mapping_type
= M_DISCARD
;
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
;
506 case Ttcn::Def_Function_Base::PROTOTYPE_FAST
:
507 target
->mapping
.function
.prototype
= PT_FAST
;
509 case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK
:
510 target
->mapping
.function
.prototype
= PT_BACKTRACK
;
512 case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING
:
513 target
->mapping
.function
.prototype
= PT_SLIDING
;
517 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
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
));
527 target
->mapping_type
= M_DECODE
;
528 target
->mapping
.encdec
.typedescr_name
=
529 pool
.add(target_type
->get_genname_typedescriptor(p_scope
));
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
));
541 target
->mapping
.encdec
.errorbehavior
=
542 "TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, "
543 "TTCN_EncDec::EB_DEFAULT);\n";
547 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
552 void TypeMappingTarget::dump(unsigned level
) const
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
) {
560 u
.func
.function_ref
->dump(level
+ 1);
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);
574 // =================================
575 // ===== TypeMappingTargets
576 // =================================
578 TypeMappingTargets::~TypeMappingTargets()
580 size_t nof_targets
= targets_v
.size();
581 for (size_t i
= 0; i
< nof_targets
; i
++) delete targets_v
[i
];
585 TypeMappingTargets
*TypeMappingTargets::clone() const
587 FATAL_ERROR("TypeMappingTargets::clone");
590 void TypeMappingTargets::set_fullname(const string
& p_fullname
)
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)
600 void TypeMappingTargets::set_my_scope(Scope
*p_scope
)
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
);
607 void TypeMappingTargets::add_target(TypeMappingTarget
*p_target
)
609 if (!p_target
) FATAL_ERROR("TypeMappingTargets::add_target()");
610 targets_v
.add(p_target
);
613 void TypeMappingTargets::dump(unsigned level
) const
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);
620 // =================================
622 // =================================
624 TypeMapping::TypeMapping(Type
*p_source_type
, TypeMappingTargets
*p_targets
)
625 : Node(), Location(), source_type(p_source_type
), targets(p_targets
)
627 if (!p_source_type
|| !p_targets
)
628 FATAL_ERROR("TypeMapping::TypeMapping()");
629 source_type
->set_ownertype(Type::OT_TYPE_MAP
, this);
632 TypeMapping::~TypeMapping()
638 TypeMapping
*TypeMapping::clone() const
640 FATAL_ERROR("TypeMapping::clone");
643 void TypeMapping::set_fullname(const string
& p_fullname
)
645 Node::set_fullname(p_fullname
);
646 source_type
->set_fullname(p_fullname
+ ".<source_type>");
647 targets
->set_fullname(p_fullname
);
650 void TypeMapping::set_my_scope(Scope
*p_scope
)
652 source_type
->set_my_scope(p_scope
);
653 targets
->set_my_scope(p_scope
);
656 void TypeMapping::chk()
658 Error_Context
cntxt(this, "In type mapping");
660 Error_Context
cntxt2(source_type
, "In source type");
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 "
674 else if (i
< nof_targets
- 1) target
->error("Mapping `discard' must "
675 "be the last target of the source type");
677 case TypeMappingTarget::TM_FUNCTION
: {
678 Ttcn::Def_Function_Base
*t_function
= target
->get_function();
680 switch (t_function
->get_prototype()) {
681 case Ttcn::Def_Function_Base::PROTOTYPE_NONE
:
683 case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK
:
684 has_non_sliding
= true;
686 case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING
:
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());
697 case TypeMappingTarget::TM_DECODE
:
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());
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)'");
713 void TypeMapping::dump(unsigned level
) const
715 DEBUG(level
, "Source type:");
716 source_type
->dump(level
+ 1);
717 targets
->dump(level
);
720 // =================================
721 // ===== TypeMappings
722 // =================================
724 TypeMappings::~TypeMappings()
726 size_t nof_mappings
= mappings_v
.size();
727 for (size_t i
= 0; i
< nof_mappings
; i
++) delete mappings_v
[i
];
732 TypeMappings
*TypeMappings::clone() const
734 FATAL_ERROR("TypeMappings::clone");
737 void TypeMappings::set_fullname(const string
& p_fullname
)
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)
747 void TypeMappings::set_my_scope(Scope
*p_scope
)
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
);
754 void TypeMappings::add_mapping(TypeMapping
*p_mapping
)
756 if (checked
|| !p_mapping
) FATAL_ERROR("TypeMappings::add_mapping()");
757 mappings_v
.add(p_mapping
);
760 void TypeMappings::steal_mappings(TypeMappings
*p_mappings
)
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
);
771 bool TypeMappings::has_mapping_for_type(Type
*p_type
) const
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
)
777 else return mappings_m
.has_key(p_type
->get_typename());
780 TypeMapping
*TypeMappings::get_mapping_byType(Type
*p_type
) const
782 if (!checked
|| !p_type
)
783 FATAL_ERROR("TypeMappings::get_mapping_byType()");
784 return mappings_m
[p_type
->get_typename()];
787 void TypeMappings::chk()
791 size_t nof_mappings
= mappings_v
.size();
792 for (size_t i
= 0; i
< nof_mappings
; i
++) {
793 TypeMapping
*mapping
= mappings_v
[i
];
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
);
809 void TypeMappings::dump(unsigned level
) const
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);
817 // =================================
819 // =================================
823 size_t nof_types
= types
.size();
824 for (size_t i
= 0; i
< nof_types
; i
++) delete types
[i
];
828 Types
*Types::clone() const
830 FATAL_ERROR("Types::clone");
833 void Types::add_type(Type
*p_type
)
835 if (!p_type
) FATAL_ERROR("Types::add_type()");
836 p_type
->set_ownertype(Type::OT_TYPE_LIST
, this);
840 Type
*Types::extract_type_byIndex(size_t n
)
842 Type
*retval
= types
[n
];
847 void Types::steal_types(Types
*p_tl
)
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
]);
853 join_location(*p_tl
);
856 void Types::set_fullname(const string
& p_fullname
)
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) + ">");
864 void Types::set_my_scope(Scope
*p_scope
)
866 size_t nof_types
= types
.size();
867 for (size_t i
= 0; i
< nof_types
; i
++) types
[i
]->set_my_scope(p_scope
);
870 void Types::dump(unsigned level
) const
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);
877 // =================================
879 // =================================
887 TypeSet
*TypeSet::clone() const
889 FATAL_ERROR("TypeSet::clone()");
892 void TypeSet::add_type(Type
*p_type
)
894 if (!p_type
) FATAL_ERROR("TypeSet::add_type()");
896 types_m
.add(p_type
->get_typename(), p_type
);
899 bool TypeSet::has_type(Type
*p_type
) const
901 if (!p_type
) FATAL_ERROR("TypeSet::has_type()");
902 if (p_type
->get_type_refd_last()->get_typetype() == Type::T_ERROR
)
904 else return types_m
.has_key(p_type
->get_typename());
907 size_t TypeSet::get_nof_compatible_types(Type
*p_type
) const
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.
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
++;
924 size_t TypeSet::get_index_byType(Type
*p_type
) const
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);
935 void TypeSet::dump(unsigned level
) const
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);
942 // =================================
943 // ===== PortTypeBody
944 // =================================
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
),
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)
959 PortTypeBody::~PortTypeBody()
973 PortTypeBody
*PortTypeBody::clone() const
975 FATAL_ERROR("PortTypeBody::clone");
978 void PortTypeBody::set_fullname(const string
& p_fullname
)
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>");
989 provider_ref
->set_fullname(p_fullname
+ ".<provider_ref>");
990 if (in_mappings
) in_mappings
->set_fullname(p_fullname
+ ".<in_mappings>");
992 out_mappings
->set_fullname(p_fullname
+ ".<out_mappings>");
995 void PortTypeBody::set_my_scope(Scope
*p_scope
)
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
);
1005 void PortTypeBody::set_my_type(Type
*p_type
)
1007 if (!p_type
|| p_type
->get_typetype() != Type::T_PORT
)
1008 FATAL_ERROR("PortTypeBody::set_my_type()");
1012 TypeSet
*PortTypeBody::get_in_msgs() const
1014 if (!checked
) FATAL_ERROR("PortTypeBody::get_in_msgs()");
1018 TypeSet
*PortTypeBody::get_out_msgs() const
1020 if (!checked
) FATAL_ERROR("PortTypeBody::get_out_msgs()");
1024 TypeSet
*PortTypeBody::get_in_sigs() const
1026 if (!checked
) FATAL_ERROR("PortTypeBody::get_in_sigs()");
1030 TypeSet
*PortTypeBody::get_out_sigs() const
1032 if (!checked
) FATAL_ERROR("PortTypeBody::get_out_sigs()");
1036 bool PortTypeBody::has_queue() const
1038 if (!checked
) FATAL_ERROR("PortTypeBody::has_queue()");
1039 if (in_msgs
|| in_sigs
) return true;
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;
1051 bool PortTypeBody::getreply_allowed() const
1053 if (!checked
) FATAL_ERROR("PortTypeBody::getreply_allowed()");
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;
1064 bool PortTypeBody::catch_allowed() const
1066 if (!checked
) FATAL_ERROR("PortTypeBody::catch_allowed()");
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;
1077 bool PortTypeBody::is_internal() const
1079 if (!checked
) FATAL_ERROR("PortTypeBody::is_internal_port()");
1080 return testport_type
== TP_INTERNAL
;
1083 Type
*PortTypeBody::get_address_type()
1085 if (!checked
) FATAL_ERROR("PortTypeBody::get_address_type()");
1086 if (testport_type
== TP_ADDRESS
) {
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
;
1092 return t
->get_my_scope()->get_scope_mod()->get_address_type();
1094 // the port type does not support SUT addresses
1099 void PortTypeBody::add_provider_attribute()
1101 port_type
= PT_PROVIDER
;
1102 delete provider_ref
;
1107 delete out_mappings
;
1111 void PortTypeBody::add_user_attribute(Ttcn::Reference
*p_provider_ref
,
1112 TypeMappings
*p_in_mappings
, TypeMappings
*p_out_mappings
)
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
);
1125 in_mappings
= p_in_mappings
;
1127 in_mappings
->set_fullname(t_fullname
+ ".<in_mappings>");
1128 in_mappings
->set_my_scope(t_scope
);
1130 delete out_mappings
;
1131 out_mappings
= p_out_mappings
;
1133 out_mappings
->set_fullname(t_fullname
+ ".<out_mappings>");
1134 out_mappings
->set_my_scope(t_scope
);
1138 Type
*PortTypeBody::get_provider_type() const
1140 if (!checked
|| port_type
!= PT_USER
)
1141 FATAL_ERROR("PortTypeBody::get_provider_type()");
1142 return provider_type
;
1145 void PortTypeBody::chk_list(const Types
*list
, bool is_in
, bool is_out
)
1147 const char *err_msg
;
1149 if (is_out
) err_msg
= "sent or received";
1150 else err_msg
= "received";
1151 } else if (is_out
) err_msg
= "sent";
1153 FATAL_ERROR("PortTypeBody::chk_list()");
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
);
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");
1165 Type
*t_last
= t
->get_type_refd_last();
1166 switch (t_last
->get_typetype()) {
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());
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());
1183 in_sigs
= new TypeSet
;
1184 in_sigs
->set_fullname(get_fullname() + ".<incoming_signatures>");
1186 in_sigs
->add_type(t
);
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());
1197 out_sigs
= new TypeSet
;
1198 out_sigs
->set_fullname(get_fullname() + ".<outgoing_signatures>");
1200 out_sigs
->add_type(t
);
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
);
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());
1218 in_msgs
= new TypeSet
;
1219 in_msgs
->set_fullname(get_fullname() + ".<incoming_messages>");
1221 in_msgs
->add_type(t
);
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());
1232 out_msgs
= new TypeSet
;
1233 out_msgs
->set_fullname(get_fullname() + ".<outgoing_messages>");
1235 out_msgs
->add_type(t
);
1242 void PortTypeBody::chk_user_attribute()
1244 Error_Context
cntxt(this, "In extension attribute `user'");
1245 // check the reference that points to the provider type
1247 PortTypeBody
*provider_body
= 0;
1248 Assignment
*t_ass
= provider_ref
->get_refd_assignment(); // provider port
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
) {
1254 provider_body
= t
->get_PortBody();
1256 provider_ref
->error("Type reference `%s' does not refer to a port "
1257 "type", provider_ref
->get_dispname().c_str());
1260 provider_ref
->error("Reference `%s' does not refer to a type",
1261 provider_ref
->get_dispname().c_str());
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());
1271 switch (provider_body
->testport_type
) {
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());
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());
1286 FATAL_ERROR("PortTypeBody::chk_attributes()");
1288 // inherit the test port API type from the provider
1289 testport_type
= provider_body
->testport_type
;
1292 // checking the incoming mappings
1294 Error_Context
cntxt2(in_mappings
, "In `in' mappings");
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
1301 size_t nof_mappings
= in_mappings
->get_nof_mappings();
1302 for (size_t i
= 0; i
< nof_mappings
; i
++) {
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());
1312 // check if all types of the `in' list of the provider are handled by
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());
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());
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
++) {
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());
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());
1351 // checking the outgoing mappings
1353 Error_Context
cntxt2(out_mappings
, "In `out' mappings");
1354 out_mappings
->chk();
1355 // checking source types
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
++) {
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());
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());
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());
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
++) {
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());
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());
1409 // checking the compatibility of signature lists
1410 if (provider_body
) {
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());
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());
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());
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());
1477 void PortTypeBody::chk()
1479 if (checked
) return;
1482 // checking 'all' directives
1485 warning("Redundant `in all' and `inout all' directives");
1489 warning("Redundant `out all' and `inout all' directives");
1492 warning("Unsupported `inout all' directive was ignored");
1494 if (in_all
) warning("Unsupported `in all' directive was ignored");
1495 if (out_all
) warning("Unsupported `out all' directive was ignored");
1498 // checking message/signature lists
1500 Error_Context
cntxt(in_list
, "In `in' list");
1501 chk_list(in_list
, true, false);
1504 Error_Context
cntxt(out_list
, "In `out' list");
1505 chk_list(out_list
, false, true);
1508 Error_Context
cntxt(inout_list
, "In `inout' list");
1509 chk_list(inout_list
, true, true);
1513 void PortTypeBody::chk_attributes(Ttcn::WithAttribPath
*w_attrib_path
)
1515 if (!w_attrib_path
|| !checked
|| !my_type
)
1516 FATAL_ERROR("PortTypeBody::chk_attributes()");
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
:
1530 case PortTypeBody::TP_INTERNAL
: {
1531 ea
.warning("Duplicate attribute `internal'");
1533 case PortTypeBody::TP_ADDRESS
: {
1534 ea
.error("Attributes `address' and `internal' "
1535 "cannot be used at the same time");
1538 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1540 set_testport_type(PortTypeBody::TP_INTERNAL
);
1542 else if (api
== PortTypeBody::TP_ADDRESS
) {
1543 switch (testport_type
) {
1544 case PortTypeBody::TP_REGULAR
:
1546 case PortTypeBody::TP_INTERNAL
: {
1547 ea
.error("Attributes `internal' and `address' "
1548 "cannot be used at the same time");
1550 case PortTypeBody::TP_ADDRESS
: {
1551 ea
.warning("Duplicate attribute `address'");
1554 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1556 set_testport_type(PortTypeBody::TP_ADDRESS
);
1560 case ExtensionAttribute::PORT_TYPE_PROVIDER
:
1561 switch (port_type
) {
1562 case PortTypeBody::PT_REGULAR
:
1564 case PortTypeBody::PT_PROVIDER
: {
1565 ea
.warning("Duplicate attribute `provider'");
1567 case PortTypeBody::PT_USER
: {
1568 ea
.error("Attributes `user' and `provider' "
1569 "cannot be used at the same time");
1572 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1574 add_provider_attribute();
1577 case ExtensionAttribute::PORT_TYPE_USER
:
1578 switch (port_type
) {
1579 case PortTypeBody::PT_REGULAR
:
1581 case PortTypeBody::PT_PROVIDER
: {
1582 ea
.error("Attributes `provider' and `user' "
1583 "cannot be used at the same time");
1585 case PortTypeBody::PT_USER
: {
1586 ea
.error("Duplicate attribute `user'");
1589 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1594 ea
.get_user(ref
, in
, out
);
1595 add_user_attribute(ref
, in
, out
);
1598 case ExtensionAttribute::ANYTYPELIST
:
1601 case ExtensionAttribute::NONE
:
1602 break; // ignore, do not issue "wrong type" error
1605 ea
.error("Port can only have the following extension attributes: "
1606 "'provider', 'user', 'internal' or 'address'");
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());
1623 bool PortTypeBody::is_connectable(PortTypeBody
*p_other
) const
1625 if (!checked
|| !p_other
|| !p_other
->checked
)
1626 FATAL_ERROR("Type::is_connectable()");
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
)))
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
)))
1646 void PortTypeBody::report_connection_errors(PortTypeBody
*p_other
) const
1648 if (!checked
|| !my_type
|| !p_other
|| !p_other
->checked
||
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();
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
);
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
);
1679 bool PortTypeBody::is_mappable(PortTypeBody
*p_other
) const
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
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
)))
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
)))
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
)))
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
)))
1722 void PortTypeBody::report_mapping_errors(PortTypeBody
*p_other
) const
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();
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
);
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
);
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
,
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
,
1780 void PortTypeBody::generate_code(output_struct
*target
)
1782 if (!checked
|| !my_type
) FATAL_ERROR("PortTypeBody::generate_code()");
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
;
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());
1811 pdef
.msg_in
.nElements
= 0;
1812 pdef
.msg_in
.elements
= NULL
;
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);
1835 mapped_type
->nTargets
= 0;
1836 mapped_type
->targets
= NULL
;
1840 pdef
.msg_out
.nElements
= 0;
1841 pdef
.msg_out
.elements
= NULL
;
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
;
1860 pdef
.proc_in
.nElements
= 0;
1861 pdef
.proc_in
.elements
= NULL
;
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
;
1879 pdef
.proc_out
.nElements
= 0;
1880 pdef
.proc_out
.elements
= NULL
;
1883 switch (testport_type
) {
1885 pdef
.testport_type
= NORMAL
;
1888 pdef
.testport_type
= INTERNAL
;
1891 pdef
.testport_type
= ADDRESS
;
1894 FATAL_ERROR("PortTypeBody::generate_code()");
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();
1926 if (!in_msgs
) FATAL_ERROR("PortTypeBody::generate_code()");
1927 mapped_type
->targets
[j
].target_index
=
1928 in_msgs
->get_index_byType(target_type
);
1930 // the message will be discarded: fill in a dummy index
1931 mapped_type
->targets
[j
].target_index
= static_cast<size_t>(-1);
1936 pdef
.provider_msg_in
.nElements
= 0;
1937 pdef
.provider_msg_in
.elements
= NULL
;
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
;
1949 defPortClass(&pdef
, target
);
1950 if (generate_skeleton
&& testport_type
!= TP_INTERNAL
&&
1951 port_type
!= PT_USER
) generateTestPortSkeleton(&pdef
);
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
);
1964 void PortTypeBody::dump(unsigned level
) const
1966 switch (operation_mode
) {
1968 DEBUG(level
, "mode: message");
1971 DEBUG(level
, "mode: procedure");
1974 DEBUG(level
, "mode: mixed");
1977 DEBUG(level
, "mode: <invalid>");
1980 DEBUG(level
, "in list:");
1981 in_list
->dump(level
+ 1);
1983 if (in_all
) DEBUG(level
, "in all");
1985 DEBUG(level
, "out list:");
1986 out_list
->dump(level
+ 1);
1988 if (out_all
) DEBUG(level
, "out all");
1990 DEBUG(level
, "inout list:");
1991 inout_list
->dump(level
+ 1);
1993 if (inout_all
) DEBUG(level
, "inout all");
1995 DEBUG(level
, "incoming messages:");
1996 in_msgs
->dump(level
+ 1);
1999 DEBUG(level
, "outgoing messages:");
2000 out_msgs
->dump(level
+ 1);
2003 DEBUG(level
, "incoming signatures:");
2004 in_sigs
->dump(level
+ 1);
2007 DEBUG(level
, "outgoing signatures:");
2008 out_sigs
->dump(level
+ 1);
2010 switch (testport_type
) {
2014 DEBUG(level
, "attribute: internal");
2017 DEBUG(level
, "attribute: address");
2020 DEBUG(level
, "attribute: <unknown>");
2022 switch (port_type
) {
2026 DEBUG(level
, "attribute: provider");
2029 DEBUG(level
, "attribute: user");
2032 DEBUG(level
, "attribute: <unknown>");
2035 DEBUG(level
, "provider type: %s", provider_ref
->get_dispname().c_str());
2037 DEBUG(level
, "in mappings:");
2038 in_mappings
->dump(level
+ 1);
2041 DEBUG(level
, "out mappings:");
2042 out_mappings
->dump(level
+ 1);
2046 // =================================
2047 // ===== ExtensionAttribute
2048 // =================================
2049 static const string
version_template("RnXnn");
2051 void ExtensionAttribute::check_product_number(const char* ABCClass
, int type_number
, int sequence
) {
2052 if (NULL
== ABCClass
&& 0 == type_number
&& 0 == sequence
) {
2056 int ABCLength
= strlen(ABCClass
);
2057 if (ABCLength
< 3 || ABCLength
> 5) {
2058 // incorrect ABC number
2063 if (type_number
>= 1000) {
2068 if (sequence
>= 10000 ) {
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
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
);
2092 case 3: // all fields scanned
2093 case 2: // 2 scanned, bld remained unmodified
2094 value_
.version_
.release_
= rel
;
2095 value_
.version_
.build_
= bld
;
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';
2101 case 'J': case 'K': case 'L': case 'M': case 'N':
2102 value_
.version_
.patch_
= patch
[0] - 'A' - 1;
2104 case 'S': case 'T': case 'U': case 'V':
2105 value_
.version_
.patch_
= patch
[0] - 'A' - 5;
2107 case 'X': case 'Y': case 'Z':
2108 value_
.version_
.patch_
= patch
[0] - 'A' - 6;
2111 case 'I': case 'W': // forbidden
2112 case 'O': case 'P': case 'Q': case 'R': // forbidden
2113 default: // incorrect
2118 default: // there was an error
2124 ExtensionAttribute::ExtensionAttribute(const char* ABCClass
, int type_number
,
2125 int sequence
, int suffix
, Identifier
*ver
)
2126 : Location(), type_(VERSION
), value_()
2128 if (ver
== NULL
) FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2129 value_
.version_
.module_
= NULL
;
2131 check_product_number(ABCClass
, type_number
, sequence
);
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"
2141 ExtensionAttribute::ExtensionAttribute(Identifier
*mod
, const char* ABCClass
,
2142 int type_number
, int sequence
, int suffix
, Identifier
*ver
)
2143 : Location(), type_(REQUIRES
), value_()
2145 if (mod
== NULL
|| ver
== NULL
)
2146 FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2147 // store the module identifier
2148 value_
.version_
.module_
= mod
;
2150 check_product_number(ABCClass
, type_number
, sequence
);
2152 if (type_
== NONE
) { // parse_version reported an error
2153 value_
.version_
.module_
= NULL
; // disown it; caller will free
2154 value_
.version_
.suffix_
= suffix
;
2156 value_
.version_
.productNumber_
=
2157 NULL
== ABCClass
? NULL
: mprintf("%s %d %d", ABCClass
, type_number
, sequence
);
2158 value_
.version_
.suffix_
= suffix
;
2163 ExtensionAttribute::ExtensionAttribute(const char* ABCClass
, int type_number
,
2164 int sequence
, int suffix
, Identifier
* ver
, extension_t et
)
2165 : Location(), type_(et
), value_()
2167 if (ver
== NULL
) FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2171 check_product_number(ABCClass
, type_number
, sequence
);
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"
2179 value_
.version_
.suffix_
= suffix
;
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
;
2197 FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2204 ExtensionAttribute::~ExtensionAttribute()
2208 break; // nothing to do, data has been extracted
2209 // TODO perhaps NONE should be the only acceptable option?
2210 // (no unprocessed attribute allowed)
2213 case ENCODE
: case DECODE
:
2214 delete value_
.encdec_
.s_
;
2218 case PORT_TYPE_USER
:
2219 delete value_
.user_
.ref_
;
2220 delete value_
.user_
.inmaps_
;
2221 delete value_
.user_
.outmaps_
;
2223 case PORT_TYPE_PROVIDER
:
2229 delete value_
.anytypes_
;
2232 delete value_
.encdecvalue_
.inmaps_
;
2233 delete value_
.encdecvalue_
.outmaps_
;
2236 case VERSION_TEMPLATE
:
2237 Free(value_
.version_
.productNumber_
);
2238 Free(value_
.version_
.extra_
);
2241 Free(value_
.version_
.productNumber_
);
2242 Free(value_
.version_
.extra_
);
2243 delete value_
.version_
.module_
;
2246 Free(value_
.version_
.productNumber_
);
2247 Free(value_
.version_
.extra_
);
2254 default: // can't happen
2255 FATAL_ERROR("ExtensionAttribute::~ExtensionAttribute(%X)", type_
);
2259 Types
*ExtensionAttribute::get_types()
2261 if (type_
!= ANYTYPELIST
) FATAL_ERROR("ExtensionAttribute::get_types()");
2263 return value_
.anytypes_
;
2266 Ttcn::Def_Function_Base::prototype_t
ExtensionAttribute::get_proto()
2268 if (type_
!= PROTOTYPE
) FATAL_ERROR("ExtensionAttribute::get_proto()");
2270 return value_
.proto_
;
2273 void ExtensionAttribute::get_encdec_parameters(
2274 Type::MessageEncodingType_t
&p_encoding_type
, string
*&p_encoding_options
)
2276 if (type_
!= ENCODE
&& type_
!= DECODE
)
2277 FATAL_ERROR("ExtensionAttribute::get_encdec_parameters()");
2279 p_encoding_type
= value_
.encdec_
.mess_
;
2280 p_encoding_options
= value_
.encdec_
.s_
;
2281 const_cast<ExtensionAttribute
*>(this)->value_
.encdec_
.s_
= 0;
2284 ErrorBehaviorList
*ExtensionAttribute::get_eb_list()
2286 if (type_
!= ERRORBEHAVIOR
)
2287 FATAL_ERROR("ExtensionAttribute::get_eb_list()");
2289 ErrorBehaviorList
*retval
= value_
.ebl_
;
2290 const_cast<ExtensionAttribute
*>(this)->value_
.ebl_
= 0;
2294 PrintingType
*ExtensionAttribute::get_printing()
2296 if (type_
!= PRINTING
)
2297 FATAL_ERROR("ExtensionAttribute::get_printing()");
2299 PrintingType
*retval
= value_
.pt_
;
2300 const_cast<ExtensionAttribute
*>(this)->value_
.pt_
= 0;
2304 PortTypeBody::TestPortAPI_t
ExtensionAttribute::get_api()
2306 if (type_
!= PORT_API
)
2307 FATAL_ERROR("ExtensionAttribute::get_api()");
2312 void ExtensionAttribute::get_user(Reference
*&ref
,
2313 TypeMappings
*&in
, TypeMappings
*&out
)
2315 if (type_
!= PORT_TYPE_USER
)
2316 FATAL_ERROR("ExtensionAttribute::get_user()");
2319 ref
= value_
.user_
.ref_
;
2320 in
= value_
.user_
.inmaps_
;
2321 out
= value_
.user_
.outmaps_
;
2323 value_
.user_
.ref_
= 0;
2324 value_
.user_
.inmaps_
= 0;
2325 value_
.user_
.outmaps_
= 0;
2328 void ExtensionAttribute::get_encdecvalue_mappings(
2329 TypeMappings
*&in
, TypeMappings
*&out
)
2331 if (type_
!= ENCDECVALUE
)
2332 FATAL_ERROR("ExtensionAttribute::get_encdecvalue_mappings()");
2334 in
= value_
.encdecvalue_
.inmaps_
;
2335 out
= value_
.encdecvalue_
.outmaps_
;
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
)
2343 if ( type_
!= REQUIRES
&& type_
!= REQ_TITAN
2344 && type_
!= VERSION
&& type_
!= VERSION_TEMPLATE
) {
2345 FATAL_ERROR("ExtensionAttribute::get_id()");
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_
;
2356 // =================================
2357 // ===== ExtensionAttributes
2358 // =================================
2359 void ExtensionAttributes::add(ExtensionAttribute
*a
)
2361 vector
<ExtensionAttribute
>::add(a
);
2364 ExtensionAttributes::~ExtensionAttributes()
2366 for (int i
= size()-1; i
>= 0; --i
)
2367 delete operator [](i
);
2371 void ExtensionAttributes::import(ExtensionAttributes
*other
)
2373 size_t n
= other
->size();
2374 for (size_t i
= 0; i
< n
; ++i
) {
2375 vector
<ExtensionAttribute
>::add((*other
)[i
]);