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
15 * Zalanyi, Balazs Andor
17 ******************************************************************************/
18 #include "Ttcnstuff.hh"
20 #include "../CompilerError.hh"
21 #include "AST_ttcn3.hh"
23 #include "Attributes.hh"
26 // implemented in coding_attrib_p.y
27 extern Ttcn::ExtensionAttributes
* parse_extattributes(
28 Ttcn::WithAttribPath
*w_attrib_path
);
32 // =================================
33 // ===== ErrorBehaviorSetting
34 // =================================
36 ErrorBehaviorSetting
*ErrorBehaviorSetting::clone() const
38 FATAL_ERROR("ErrorBehaviorSetting::clone");
41 void ErrorBehaviorSetting::dump(unsigned level
) const
43 DEBUG(level
, "%s : %s", error_type
.c_str(), error_handling
.c_str());
46 // =================================
47 // ===== ErrorBehaviorList
48 // =================================
50 ErrorBehaviorList::~ErrorBehaviorList()
52 for (size_t i
= 0; i
< ebs_v
.size(); i
++)
58 ErrorBehaviorList
*ErrorBehaviorList::clone() const
60 FATAL_ERROR("ErrorBehaviorList::clone");
63 void ErrorBehaviorList::set_fullname(const string
& p_fullname
)
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) + ">");
71 void ErrorBehaviorList::add_ebs(ErrorBehaviorSetting
*p_ebs
)
73 if (!p_ebs
|| checked
) FATAL_ERROR("ErrorBehaviorList::add_ebs()");
77 void ErrorBehaviorList::steal_ebs(ErrorBehaviorList
*p_eblist
)
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
);
87 bool ErrorBehaviorList::has_setting(const string
& p_error_type
)
90 return ebs_all
!= 0 || ebs_m
.has_key(p_error_type
);
93 string
ErrorBehaviorList::get_handling(const string
& p_error_type
)
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");
102 void ErrorBehaviorList::chk()
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
) {
112 ebs
->warning("Duplicate setting for error type `ALL'");
113 ebs_all
->warning("The previous setting is ignored");
116 if (!ebs_m
.empty()) {
117 ebs
->warning("All settings before `ALL' are ignored");
121 if (ebs_m
.has_key(error_type
)) {
122 ebs
->warning("Duplicate setting for error type `%s'",
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
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
) {
143 ebs
->warning("String `%s' is not a valid error type",
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;
157 if (!handling_found
) {
158 ebs
->warning("String `%s' is not a valid error handling",
159 error_handling
.c_str());
165 char *ErrorBehaviorList::generate_code(char *str
)
167 if (!checked
) FATAL_ERROR("ErrorBehaviorList::generate_code()");
168 const string
all_str("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());
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");
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());
187 void ErrorBehaviorList::dump(unsigned level
) const
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);
194 // =================================
195 // ===== PrintingType
196 // =================================
198 PrintingType
*PrintingType::clone() const
200 FATAL_ERROR("PrintingType::clone");
203 char *PrintingType::generate_code(char *str
)
205 return mputprintf(str
, ", %d", (PT_PRETTY
== printing
) ? 1 : 0);
208 // =================================
209 // ===== TypeMappingTarget
210 // =================================
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)
217 if (p_mapping_type
== TM_SIMPLE
&& p_target_type
!= NULL
) { // acceptable
218 target_type
->set_ownertype(Type::OT_TYPE_MAP_TARGET
, this);
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()");
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)
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);
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)
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);
253 TypeMappingTarget::~TypeMappingTarget()
256 switch (mapping_type
) {
258 delete u
.func
.function_ref
;
262 delete u
.encdec
.coding_options
;
263 delete u
.encdec
.eb_list
;
269 TypeMappingTarget
*TypeMappingTarget::clone() const
271 FATAL_ERROR("TypeMappingTarget::clone");
274 void TypeMappingTarget::set_fullname(const string
& p_fullname
)
276 Node::set_fullname(p_fullname
);
277 if (target_type
) target_type
->set_fullname(p_fullname
+ ".<target_type>");
278 switch (mapping_type
) {
283 u
.func
.function_ref
->set_fullname(p_fullname
+ ".<function_ref>");
287 if (u
.encdec
.eb_list
)
288 u
.encdec
.eb_list
->set_fullname(p_fullname
+ ".<errorbehavior>");
291 FATAL_ERROR("TypeMappingTarget::set_fullname()");
295 void TypeMappingTarget::set_my_scope(Common::Scope
*p_scope
)
297 if (target_type
) target_type
->set_my_scope(p_scope
);
298 switch (mapping_type
) {
305 u
.func
.function_ref
->set_my_scope(p_scope
);
308 FATAL_ERROR("TypeMappingTarget::set_my_scope()");
312 const char *TypeMappingTarget::get_mapping_name() const
314 switch (mapping_type
) {
326 return "<unknown mapping>";
330 Ttcn::Def_Function_Base
*TypeMappingTarget::get_function() const
332 if (mapping_type
!= TM_FUNCTION
|| !checked
)
333 FATAL_ERROR("TypeMappingTarget::get_function()");
334 return u
.func
.function_ptr
;
337 Type::MessageEncodingType_t
TypeMappingTarget::get_coding_type() const
339 if (mapping_type
!= TM_ENCODE
&& mapping_type
!= TM_DECODE
)
340 FATAL_ERROR("TypeMappingTarget::get_coding_type()");
341 return u
.encdec
.coding_type
;
344 bool TypeMappingTarget::has_coding_options() const
346 if (mapping_type
!= TM_ENCODE
&& mapping_type
!= TM_DECODE
)
347 FATAL_ERROR("TypeMappingTarget::has_coding_options()");
348 return u
.encdec
.coding_options
!= 0;
351 const string
& TypeMappingTarget::get_coding_options() const
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
;
359 ErrorBehaviorList
*TypeMappingTarget::get_eb_list() const
361 if (mapping_type
!= TM_ENCODE
&& mapping_type
!= TM_DECODE
)
362 FATAL_ERROR("TypeMappingTarget::get_eb_list()");
363 return u
.encdec
.eb_list
;
366 void TypeMappingTarget::chk_simple(Type
*source_type
)
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());
377 void TypeMappingTarget::chk_function(Type
*source_type
)
379 Error_Context
cntxt(this, "In `function' mapping");
380 Assignment
*t_ass
= u
.func
.function_ref
->get_refd_assignment(false);
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
:
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());
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());
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());
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());
423 void TypeMappingTarget::chk_encode(Type
*source_type
)
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
));
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());
438 if (u
.encdec
.eb_list
) u
.encdec
.eb_list
->chk();
441 void TypeMappingTarget::chk_decode(Type
*source_type
)
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());
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
));
456 if (u
.encdec
.eb_list
) u
.encdec
.eb_list
->chk();
459 void TypeMappingTarget::chk(Type
*source_type
)
464 Error_Context
cntxt(target_type
, "In target type");
467 switch (mapping_type
) {
469 chk_simple(source_type
);
474 chk_function(source_type
);
477 chk_encode(source_type
);
480 chk_decode(source_type
);
483 FATAL_ERROR("TypeMappingTarget::chk()");
487 bool TypeMappingTarget::fill_type_mapping_target(
488 port_msg_type_mapping_target
*target
, Type
*source_type
,
489 Scope
*p_scope
, stringpool
& pool
)
491 bool has_sliding
= false;
493 target
->target_name
= pool
.add(target_type
->get_genname_value(p_scope
));
494 target
->target_dispname
= pool
.add(target_type
->get_typename());
496 target
->target_name
= NULL
;
497 target
->target_dispname
= NULL
;
499 switch (mapping_type
) {
501 target
->mapping_type
= M_SIMPLE
;
504 target
->mapping_type
= M_DISCARD
;
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
;
516 case Ttcn::Def_Function_Base::PROTOTYPE_FAST
:
517 target
->mapping
.function
.prototype
= PT_FAST
;
519 case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK
:
520 target
->mapping
.function
.prototype
= PT_BACKTRACK
;
522 case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING
:
523 target
->mapping
.function
.prototype
= PT_SLIDING
;
527 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
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
));
537 target
->mapping_type
= M_DECODE
;
538 target
->mapping
.encdec
.typedescr_name
=
539 pool
.add(target_type
->get_genname_typedescriptor(p_scope
));
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
));
551 target
->mapping
.encdec
.errorbehavior
=
552 "TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, "
553 "TTCN_EncDec::EB_DEFAULT);\n";
557 FATAL_ERROR("TypeMappingTarget::fill_type_mapping_target()");
562 void TypeMappingTarget::dump(unsigned level
) const
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
) {
570 u
.func
.function_ref
->dump(level
+ 1);
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);
584 // =================================
585 // ===== TypeMappingTargets
586 // =================================
588 TypeMappingTargets::~TypeMappingTargets()
590 size_t nof_targets
= targets_v
.size();
591 for (size_t i
= 0; i
< nof_targets
; i
++) delete targets_v
[i
];
595 TypeMappingTargets
*TypeMappingTargets::clone() const
597 FATAL_ERROR("TypeMappingTargets::clone");
600 void TypeMappingTargets::set_fullname(const string
& p_fullname
)
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)
610 void TypeMappingTargets::set_my_scope(Scope
*p_scope
)
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
);
617 void TypeMappingTargets::add_target(TypeMappingTarget
*p_target
)
619 if (!p_target
) FATAL_ERROR("TypeMappingTargets::add_target()");
620 targets_v
.add(p_target
);
623 void TypeMappingTargets::dump(unsigned level
) const
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);
630 // =================================
632 // =================================
634 TypeMapping::TypeMapping(Type
*p_source_type
, TypeMappingTargets
*p_targets
)
635 : Node(), Location(), source_type(p_source_type
), targets(p_targets
)
637 if (!p_source_type
|| !p_targets
)
638 FATAL_ERROR("TypeMapping::TypeMapping()");
639 source_type
->set_ownertype(Type::OT_TYPE_MAP
, this);
642 TypeMapping::~TypeMapping()
648 TypeMapping
*TypeMapping::clone() const
650 FATAL_ERROR("TypeMapping::clone");
653 void TypeMapping::set_fullname(const string
& p_fullname
)
655 Node::set_fullname(p_fullname
);
656 source_type
->set_fullname(p_fullname
+ ".<source_type>");
657 targets
->set_fullname(p_fullname
);
660 void TypeMapping::set_my_scope(Scope
*p_scope
)
662 source_type
->set_my_scope(p_scope
);
663 targets
->set_my_scope(p_scope
);
666 void TypeMapping::chk()
668 Error_Context
cntxt(this, "In type mapping");
670 Error_Context
cntxt2(source_type
, "In source type");
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 "
684 else if (i
< nof_targets
- 1) target
->error("Mapping `discard' must "
685 "be the last target of the source type");
687 case TypeMappingTarget::TM_FUNCTION
: {
688 Ttcn::Def_Function_Base
*t_function
= target
->get_function();
690 switch (t_function
->get_prototype()) {
691 case Ttcn::Def_Function_Base::PROTOTYPE_NONE
:
693 case Ttcn::Def_Function_Base::PROTOTYPE_BACKTRACK
:
694 has_non_sliding
= true;
696 case Ttcn::Def_Function_Base::PROTOTYPE_SLIDING
:
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());
707 case TypeMappingTarget::TM_DECODE
:
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());
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)'");
723 void TypeMapping::dump(unsigned level
) const
725 DEBUG(level
, "Source type:");
726 source_type
->dump(level
+ 1);
727 targets
->dump(level
);
730 // =================================
731 // ===== TypeMappings
732 // =================================
734 TypeMappings::~TypeMappings()
736 size_t nof_mappings
= mappings_v
.size();
737 for (size_t i
= 0; i
< nof_mappings
; i
++) delete mappings_v
[i
];
742 TypeMappings
*TypeMappings::clone() const
744 FATAL_ERROR("TypeMappings::clone");
747 void TypeMappings::set_fullname(const string
& p_fullname
)
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)
757 void TypeMappings::set_my_scope(Scope
*p_scope
)
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
);
764 void TypeMappings::add_mapping(TypeMapping
*p_mapping
)
766 if (checked
|| !p_mapping
) FATAL_ERROR("TypeMappings::add_mapping()");
767 mappings_v
.add(p_mapping
);
770 void TypeMappings::steal_mappings(TypeMappings
*p_mappings
)
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
);
781 bool TypeMappings::has_mapping_for_type(Type
*p_type
) const
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
)
787 else return mappings_m
.has_key(p_type
->get_typename());
790 TypeMapping
*TypeMappings::get_mapping_byType(Type
*p_type
) const
792 if (!checked
|| !p_type
)
793 FATAL_ERROR("TypeMappings::get_mapping_byType()");
794 return mappings_m
[p_type
->get_typename()];
797 void TypeMappings::chk()
801 size_t nof_mappings
= mappings_v
.size();
802 for (size_t i
= 0; i
< nof_mappings
; i
++) {
803 TypeMapping
*mapping
= mappings_v
[i
];
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
);
819 void TypeMappings::dump(unsigned level
) const
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);
827 // =================================
829 // =================================
833 size_t nof_types
= types
.size();
834 for (size_t i
= 0; i
< nof_types
; i
++) delete types
[i
];
838 Types
*Types::clone() const
840 FATAL_ERROR("Types::clone");
843 void Types::add_type(Type
*p_type
)
845 if (!p_type
) FATAL_ERROR("Types::add_type()");
846 p_type
->set_ownertype(Type::OT_TYPE_LIST
, this);
850 Type
*Types::extract_type_byIndex(size_t n
)
852 Type
*retval
= types
[n
];
857 void Types::steal_types(Types
*p_tl
)
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
]);
863 join_location(*p_tl
);
866 void Types::set_fullname(const string
& p_fullname
)
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) + ">");
874 void Types::set_my_scope(Scope
*p_scope
)
876 size_t nof_types
= types
.size();
877 for (size_t i
= 0; i
< nof_types
; i
++) types
[i
]->set_my_scope(p_scope
);
880 void Types::dump(unsigned level
) const
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);
887 // =================================
889 // =================================
897 TypeSet
*TypeSet::clone() const
899 FATAL_ERROR("TypeSet::clone()");
902 void TypeSet::add_type(Type
*p_type
)
904 if (!p_type
) FATAL_ERROR("TypeSet::add_type()");
906 types_m
.add(p_type
->get_typename(), p_type
);
909 bool TypeSet::has_type(Type
*p_type
) const
911 if (!p_type
) FATAL_ERROR("TypeSet::has_type()");
912 if (p_type
->get_type_refd_last()->get_typetype() == Type::T_ERROR
)
914 else return types_m
.has_key(p_type
->get_typename());
917 size_t TypeSet::get_nof_compatible_types(Type
*p_type
) const
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.
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
++;
934 size_t TypeSet::get_index_byType(Type
*p_type
) const
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);
945 void TypeSet::dump(unsigned level
) const
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);
952 // =================================
953 // ===== PortTypeBody
954 // =================================
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
),
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)
969 PortTypeBody::~PortTypeBody()
983 PortTypeBody
*PortTypeBody::clone() const
985 FATAL_ERROR("PortTypeBody::clone");
988 void PortTypeBody::set_fullname(const string
& p_fullname
)
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>");
999 provider_ref
->set_fullname(p_fullname
+ ".<provider_ref>");
1000 if (in_mappings
) in_mappings
->set_fullname(p_fullname
+ ".<in_mappings>");
1002 out_mappings
->set_fullname(p_fullname
+ ".<out_mappings>");
1005 void PortTypeBody::set_my_scope(Scope
*p_scope
)
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
);
1015 void PortTypeBody::set_my_type(Type
*p_type
)
1017 if (!p_type
|| p_type
->get_typetype() != Type::T_PORT
)
1018 FATAL_ERROR("PortTypeBody::set_my_type()");
1022 TypeSet
*PortTypeBody::get_in_msgs() const
1024 if (!checked
) FATAL_ERROR("PortTypeBody::get_in_msgs()");
1028 TypeSet
*PortTypeBody::get_out_msgs() const
1030 if (!checked
) FATAL_ERROR("PortTypeBody::get_out_msgs()");
1034 TypeSet
*PortTypeBody::get_in_sigs() const
1036 if (!checked
) FATAL_ERROR("PortTypeBody::get_in_sigs()");
1040 TypeSet
*PortTypeBody::get_out_sigs() const
1042 if (!checked
) FATAL_ERROR("PortTypeBody::get_out_sigs()");
1046 bool PortTypeBody::has_queue() const
1048 if (!checked
) FATAL_ERROR("PortTypeBody::has_queue()");
1049 if (in_msgs
|| in_sigs
) return true;
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;
1061 bool PortTypeBody::getreply_allowed() const
1063 if (!checked
) FATAL_ERROR("PortTypeBody::getreply_allowed()");
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;
1074 bool PortTypeBody::catch_allowed() const
1076 if (!checked
) FATAL_ERROR("PortTypeBody::catch_allowed()");
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;
1087 bool PortTypeBody::is_internal() const
1089 if (!checked
) FATAL_ERROR("PortTypeBody::is_internal_port()");
1090 return testport_type
== TP_INTERNAL
;
1093 Type
*PortTypeBody::get_address_type()
1095 if (!checked
) FATAL_ERROR("PortTypeBody::get_address_type()");
1096 if (testport_type
== TP_ADDRESS
) {
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
;
1102 return t
->get_my_scope()->get_scope_mod()->get_address_type();
1104 // the port type does not support SUT addresses
1109 void PortTypeBody::add_provider_attribute()
1111 port_type
= PT_PROVIDER
;
1112 delete provider_ref
;
1117 delete out_mappings
;
1121 void PortTypeBody::add_user_attribute(Ttcn::Reference
*p_provider_ref
,
1122 TypeMappings
*p_in_mappings
, TypeMappings
*p_out_mappings
)
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
);
1135 in_mappings
= p_in_mappings
;
1137 in_mappings
->set_fullname(t_fullname
+ ".<in_mappings>");
1138 in_mappings
->set_my_scope(t_scope
);
1140 delete out_mappings
;
1141 out_mappings
= p_out_mappings
;
1143 out_mappings
->set_fullname(t_fullname
+ ".<out_mappings>");
1144 out_mappings
->set_my_scope(t_scope
);
1148 Type
*PortTypeBody::get_provider_type() const
1150 if (!checked
|| port_type
!= PT_USER
)
1151 FATAL_ERROR("PortTypeBody::get_provider_type()");
1152 return provider_type
;
1155 void PortTypeBody::chk_list(const Types
*list
, bool is_in
, bool is_out
)
1157 const char *err_msg
;
1159 if (is_out
) err_msg
= "sent or received";
1160 else err_msg
= "received";
1161 } else if (is_out
) err_msg
= "sent";
1163 FATAL_ERROR("PortTypeBody::chk_list()");
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
);
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");
1175 Type
*t_last
= t
->get_type_refd_last();
1176 switch (t_last
->get_typetype()) {
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());
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());
1193 in_sigs
= new TypeSet
;
1194 in_sigs
->set_fullname(get_fullname() + ".<incoming_signatures>");
1196 in_sigs
->add_type(t
);
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());
1207 out_sigs
= new TypeSet
;
1208 out_sigs
->set_fullname(get_fullname() + ".<outgoing_signatures>");
1210 out_sigs
->add_type(t
);
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
);
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());
1228 in_msgs
= new TypeSet
;
1229 in_msgs
->set_fullname(get_fullname() + ".<incoming_messages>");
1231 in_msgs
->add_type(t
);
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());
1242 out_msgs
= new TypeSet
;
1243 out_msgs
->set_fullname(get_fullname() + ".<outgoing_messages>");
1245 out_msgs
->add_type(t
);
1252 void PortTypeBody::chk_user_attribute()
1254 Error_Context
cntxt(this, "In extension attribute `user'");
1255 // check the reference that points to the provider type
1257 PortTypeBody
*provider_body
= 0;
1258 Assignment
*t_ass
= provider_ref
->get_refd_assignment(); // provider port
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
) {
1264 provider_body
= t
->get_PortBody();
1266 provider_ref
->error("Type reference `%s' does not refer to a port "
1267 "type", provider_ref
->get_dispname().c_str());
1270 provider_ref
->error("Reference `%s' does not refer to a type",
1271 provider_ref
->get_dispname().c_str());
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());
1281 switch (provider_body
->testport_type
) {
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());
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());
1296 FATAL_ERROR("PortTypeBody::chk_attributes()");
1298 // inherit the test port API type from the provider
1299 testport_type
= provider_body
->testport_type
;
1302 // checking the incoming mappings
1304 Error_Context
cntxt2(in_mappings
, "In `in' mappings");
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
1311 size_t nof_mappings
= in_mappings
->get_nof_mappings();
1312 for (size_t i
= 0; i
< nof_mappings
; i
++) {
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());
1322 // check if all types of the `in' list of the provider are handled by
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());
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());
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
++) {
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());
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());
1361 // checking the outgoing mappings
1363 Error_Context
cntxt2(out_mappings
, "In `out' mappings");
1364 out_mappings
->chk();
1365 // checking source types
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
++) {
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());
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());
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());
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
++) {
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());
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());
1419 // checking the compatibility of signature lists
1420 if (provider_body
) {
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());
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());
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());
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());
1487 void PortTypeBody::chk()
1489 if (checked
) return;
1492 // checking 'all' directives
1495 warning("Redundant `in all' and `inout all' directives");
1499 warning("Redundant `out all' and `inout all' directives");
1502 warning("Unsupported `inout all' directive was ignored");
1504 if (in_all
) warning("Unsupported `in all' directive was ignored");
1505 if (out_all
) warning("Unsupported `out all' directive was ignored");
1508 // checking message/signature lists
1510 Error_Context
cntxt(in_list
, "In `in' list");
1511 chk_list(in_list
, true, false);
1514 Error_Context
cntxt(out_list
, "In `out' list");
1515 chk_list(out_list
, false, true);
1518 Error_Context
cntxt(inout_list
, "In `inout' list");
1519 chk_list(inout_list
, true, true);
1523 void PortTypeBody::chk_attributes(Ttcn::WithAttribPath
*w_attrib_path
)
1525 if (!w_attrib_path
|| !checked
|| !my_type
)
1526 FATAL_ERROR("PortTypeBody::chk_attributes()");
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
:
1540 case PortTypeBody::TP_INTERNAL
: {
1541 ea
.warning("Duplicate attribute `internal'");
1543 case PortTypeBody::TP_ADDRESS
: {
1544 ea
.error("Attributes `address' and `internal' "
1545 "cannot be used at the same time");
1548 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1550 set_testport_type(PortTypeBody::TP_INTERNAL
);
1552 else if (api
== PortTypeBody::TP_ADDRESS
) {
1553 switch (testport_type
) {
1554 case PortTypeBody::TP_REGULAR
:
1556 case PortTypeBody::TP_INTERNAL
: {
1557 ea
.error("Attributes `internal' and `address' "
1558 "cannot be used at the same time");
1560 case PortTypeBody::TP_ADDRESS
: {
1561 ea
.warning("Duplicate attribute `address'");
1564 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1566 set_testport_type(PortTypeBody::TP_ADDRESS
);
1570 case ExtensionAttribute::PORT_TYPE_PROVIDER
:
1571 switch (port_type
) {
1572 case PortTypeBody::PT_REGULAR
:
1574 case PortTypeBody::PT_PROVIDER
: {
1575 ea
.warning("Duplicate attribute `provider'");
1577 case PortTypeBody::PT_USER
: {
1578 ea
.error("Attributes `user' and `provider' "
1579 "cannot be used at the same time");
1582 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1584 add_provider_attribute();
1587 case ExtensionAttribute::PORT_TYPE_USER
:
1588 switch (port_type
) {
1589 case PortTypeBody::PT_REGULAR
:
1591 case PortTypeBody::PT_PROVIDER
: {
1592 ea
.error("Attributes `provider' and `user' "
1593 "cannot be used at the same time");
1595 case PortTypeBody::PT_USER
: {
1596 ea
.error("Duplicate attribute `user'");
1599 FATAL_ERROR("coding_attrib_parse(): invalid testport type");
1604 ea
.get_user(ref
, in
, out
);
1605 add_user_attribute(ref
, in
, out
);
1608 case ExtensionAttribute::ANYTYPELIST
:
1611 case ExtensionAttribute::NONE
:
1612 break; // ignore, do not issue "wrong type" error
1615 ea
.error("Port can only have the following extension attributes: "
1616 "'provider', 'user', 'internal' or 'address'");
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());
1633 bool PortTypeBody::is_connectable(PortTypeBody
*p_other
) const
1635 if (!checked
|| !p_other
|| !p_other
->checked
)
1636 FATAL_ERROR("Type::is_connectable()");
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
)))
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
)))
1656 void PortTypeBody::report_connection_errors(PortTypeBody
*p_other
) const
1658 if (!checked
|| !my_type
|| !p_other
|| !p_other
->checked
||
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();
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
);
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
);
1689 bool PortTypeBody::is_mappable(PortTypeBody
*p_other
) const
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
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
)))
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
)))
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
)))
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
)))
1732 void PortTypeBody::report_mapping_errors(PortTypeBody
*p_other
) const
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();
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
);
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
);
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
,
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
,
1790 void PortTypeBody::generate_code(output_struct
*target
)
1792 if (!checked
|| !my_type
) FATAL_ERROR("PortTypeBody::generate_code()");
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
;
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());
1821 pdef
.msg_in
.nElements
= 0;
1822 pdef
.msg_in
.elements
= NULL
;
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);
1845 mapped_type
->nTargets
= 0;
1846 mapped_type
->targets
= NULL
;
1850 pdef
.msg_out
.nElements
= 0;
1851 pdef
.msg_out
.elements
= NULL
;
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
;
1870 pdef
.proc_in
.nElements
= 0;
1871 pdef
.proc_in
.elements
= NULL
;
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
;
1889 pdef
.proc_out
.nElements
= 0;
1890 pdef
.proc_out
.elements
= NULL
;
1893 switch (testport_type
) {
1895 pdef
.testport_type
= NORMAL
;
1898 pdef
.testport_type
= INTERNAL
;
1901 pdef
.testport_type
= ADDRESS
;
1904 FATAL_ERROR("PortTypeBody::generate_code()");
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();
1936 if (!in_msgs
) FATAL_ERROR("PortTypeBody::generate_code()");
1937 mapped_type
->targets
[j
].target_index
=
1938 in_msgs
->get_index_byType(target_type
);
1940 // the message will be discarded: fill in a dummy index
1941 mapped_type
->targets
[j
].target_index
= static_cast<size_t>(-1);
1946 pdef
.provider_msg_in
.nElements
= 0;
1947 pdef
.provider_msg_in
.elements
= NULL
;
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
;
1959 defPortClass(&pdef
, target
);
1960 if (generate_skeleton
&& testport_type
!= TP_INTERNAL
&&
1961 port_type
!= PT_USER
) generateTestPortSkeleton(&pdef
);
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
);
1974 void PortTypeBody::dump(unsigned level
) const
1976 switch (operation_mode
) {
1978 DEBUG(level
, "mode: message");
1981 DEBUG(level
, "mode: procedure");
1984 DEBUG(level
, "mode: mixed");
1987 DEBUG(level
, "mode: <invalid>");
1990 DEBUG(level
, "in list:");
1991 in_list
->dump(level
+ 1);
1993 if (in_all
) DEBUG(level
, "in all");
1995 DEBUG(level
, "out list:");
1996 out_list
->dump(level
+ 1);
1998 if (out_all
) DEBUG(level
, "out all");
2000 DEBUG(level
, "inout list:");
2001 inout_list
->dump(level
+ 1);
2003 if (inout_all
) DEBUG(level
, "inout all");
2005 DEBUG(level
, "incoming messages:");
2006 in_msgs
->dump(level
+ 1);
2009 DEBUG(level
, "outgoing messages:");
2010 out_msgs
->dump(level
+ 1);
2013 DEBUG(level
, "incoming signatures:");
2014 in_sigs
->dump(level
+ 1);
2017 DEBUG(level
, "outgoing signatures:");
2018 out_sigs
->dump(level
+ 1);
2020 switch (testport_type
) {
2024 DEBUG(level
, "attribute: internal");
2027 DEBUG(level
, "attribute: address");
2030 DEBUG(level
, "attribute: <unknown>");
2032 switch (port_type
) {
2036 DEBUG(level
, "attribute: provider");
2039 DEBUG(level
, "attribute: user");
2042 DEBUG(level
, "attribute: <unknown>");
2045 DEBUG(level
, "provider type: %s", provider_ref
->get_dispname().c_str());
2047 DEBUG(level
, "in mappings:");
2048 in_mappings
->dump(level
+ 1);
2051 DEBUG(level
, "out mappings:");
2052 out_mappings
->dump(level
+ 1);
2056 // =================================
2057 // ===== ExtensionAttribute
2058 // =================================
2059 static const string
version_template("RnXnn");
2061 void ExtensionAttribute::check_product_number(const char* ABCClass
, int type_number
, int sequence
) {
2062 if (NULL
== ABCClass
&& 0 == type_number
&& 0 == sequence
) {
2066 int ABCLength
= strlen(ABCClass
);
2067 if (ABCLength
< 3 || ABCLength
> 5) {
2068 // incorrect ABC number
2073 if (type_number
>= 1000) {
2078 if (sequence
>= 10000 ) {
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
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
);
2102 case 3: // all fields scanned
2103 case 2: // 2 scanned, bld remained unmodified
2104 value_
.version_
.release_
= rel
;
2105 value_
.version_
.build_
= bld
;
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';
2111 case 'J': case 'K': case 'L': case 'M': case 'N':
2112 value_
.version_
.patch_
= patch
[0] - 'A' - 1;
2114 case 'S': case 'T': case 'U': case 'V':
2115 value_
.version_
.patch_
= patch
[0] - 'A' - 5;
2117 case 'X': case 'Y': case 'Z':
2118 value_
.version_
.patch_
= patch
[0] - 'A' - 6;
2121 case 'I': case 'W': // forbidden
2122 case 'O': case 'P': case 'Q': case 'R': // forbidden
2123 default: // incorrect
2128 default: // there was an error
2134 ExtensionAttribute::ExtensionAttribute(const char* ABCClass
, int type_number
,
2135 int sequence
, int suffix
, Identifier
*ver
)
2136 : Location(), type_(VERSION
), value_()
2138 if (ver
== NULL
) FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2139 value_
.version_
.module_
= NULL
;
2141 check_product_number(ABCClass
, type_number
, sequence
);
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"
2151 ExtensionAttribute::ExtensionAttribute(Identifier
*mod
, const char* ABCClass
,
2152 int type_number
, int sequence
, int suffix
, Identifier
*ver
)
2153 : Location(), type_(REQUIRES
), value_()
2155 if (mod
== NULL
|| ver
== NULL
)
2156 FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2157 // store the module identifier
2158 value_
.version_
.module_
= mod
;
2160 check_product_number(ABCClass
, type_number
, sequence
);
2162 if (type_
== NONE
) { // parse_version reported an error
2163 value_
.version_
.module_
= NULL
; // disown it; caller will free
2164 value_
.version_
.suffix_
= suffix
;
2166 value_
.version_
.productNumber_
=
2167 NULL
== ABCClass
? NULL
: mprintf("%s %d %d", ABCClass
, type_number
, sequence
);
2168 value_
.version_
.suffix_
= suffix
;
2173 ExtensionAttribute::ExtensionAttribute(const char* ABCClass
, int type_number
,
2174 int sequence
, int suffix
, Identifier
* ver
, extension_t et
)
2175 : Location(), type_(et
), value_()
2177 if (ver
== NULL
) FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2181 check_product_number(ABCClass
, type_number
, sequence
);
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"
2189 value_
.version_
.suffix_
= suffix
;
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
;
2207 FATAL_ERROR("ExtensionAttribute::ExtensionAttribute()");
2214 ExtensionAttribute::~ExtensionAttribute()
2218 break; // nothing to do, data has been extracted
2219 // TODO perhaps NONE should be the only acceptable option?
2220 // (no unprocessed attribute allowed)
2223 case ENCODE
: case DECODE
:
2224 delete value_
.encdec_
.s_
;
2228 case PORT_TYPE_USER
:
2229 delete value_
.user_
.ref_
;
2230 delete value_
.user_
.inmaps_
;
2231 delete value_
.user_
.outmaps_
;
2233 case PORT_TYPE_PROVIDER
:
2239 delete value_
.anytypes_
;
2242 delete value_
.encdecvalue_
.inmaps_
;
2243 delete value_
.encdecvalue_
.outmaps_
;
2246 case VERSION_TEMPLATE
:
2247 Free(value_
.version_
.productNumber_
);
2248 Free(value_
.version_
.extra_
);
2251 Free(value_
.version_
.productNumber_
);
2252 Free(value_
.version_
.extra_
);
2253 delete value_
.version_
.module_
;
2256 Free(value_
.version_
.productNumber_
);
2257 Free(value_
.version_
.extra_
);
2264 default: // can't happen
2265 FATAL_ERROR("ExtensionAttribute::~ExtensionAttribute(%X)", type_
);
2269 Types
*ExtensionAttribute::get_types()
2271 if (type_
!= ANYTYPELIST
) FATAL_ERROR("ExtensionAttribute::get_types()");
2273 return value_
.anytypes_
;
2276 Ttcn::Def_Function_Base::prototype_t
ExtensionAttribute::get_proto()
2278 if (type_
!= PROTOTYPE
) FATAL_ERROR("ExtensionAttribute::get_proto()");
2280 return value_
.proto_
;
2283 void ExtensionAttribute::get_encdec_parameters(
2284 Type::MessageEncodingType_t
&p_encoding_type
, string
*&p_encoding_options
)
2286 if (type_
!= ENCODE
&& type_
!= DECODE
)
2287 FATAL_ERROR("ExtensionAttribute::get_encdec_parameters()");
2289 p_encoding_type
= value_
.encdec_
.mess_
;
2290 p_encoding_options
= value_
.encdec_
.s_
;
2291 const_cast<ExtensionAttribute
*>(this)->value_
.encdec_
.s_
= 0;
2294 ErrorBehaviorList
*ExtensionAttribute::get_eb_list()
2296 if (type_
!= ERRORBEHAVIOR
)
2297 FATAL_ERROR("ExtensionAttribute::get_eb_list()");
2299 ErrorBehaviorList
*retval
= value_
.ebl_
;
2300 const_cast<ExtensionAttribute
*>(this)->value_
.ebl_
= 0;
2304 PrintingType
*ExtensionAttribute::get_printing()
2306 if (type_
!= PRINTING
)
2307 FATAL_ERROR("ExtensionAttribute::get_printing()");
2309 PrintingType
*retval
= value_
.pt_
;
2310 const_cast<ExtensionAttribute
*>(this)->value_
.pt_
= 0;
2314 PortTypeBody::TestPortAPI_t
ExtensionAttribute::get_api()
2316 if (type_
!= PORT_API
)
2317 FATAL_ERROR("ExtensionAttribute::get_api()");
2322 void ExtensionAttribute::get_user(Reference
*&ref
,
2323 TypeMappings
*&in
, TypeMappings
*&out
)
2325 if (type_
!= PORT_TYPE_USER
)
2326 FATAL_ERROR("ExtensionAttribute::get_user()");
2329 ref
= value_
.user_
.ref_
;
2330 in
= value_
.user_
.inmaps_
;
2331 out
= value_
.user_
.outmaps_
;
2333 value_
.user_
.ref_
= 0;
2334 value_
.user_
.inmaps_
= 0;
2335 value_
.user_
.outmaps_
= 0;
2338 void ExtensionAttribute::get_encdecvalue_mappings(
2339 TypeMappings
*&in
, TypeMappings
*&out
)
2341 if (type_
!= ENCDECVALUE
)
2342 FATAL_ERROR("ExtensionAttribute::get_encdecvalue_mappings()");
2344 in
= value_
.encdecvalue_
.inmaps_
;
2345 out
= value_
.encdecvalue_
.outmaps_
;
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
)
2353 if ( type_
!= REQUIRES
&& type_
!= REQ_TITAN
2354 && type_
!= VERSION
&& type_
!= VERSION_TEMPLATE
) {
2355 FATAL_ERROR("ExtensionAttribute::get_id()");
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_
;
2366 // =================================
2367 // ===== ExtensionAttributes
2368 // =================================
2369 void ExtensionAttributes::add(ExtensionAttribute
*a
)
2371 vector
<ExtensionAttribute
>::add(a
);
2374 ExtensionAttributes::~ExtensionAttributes()
2376 for (int i
= size()-1; i
>= 0; --i
)
2377 delete operator [](i
);
2381 void ExtensionAttributes::import(ExtensionAttributes
*other
)
2383 size_t n
= other
->size();
2384 for (size_t i
= 0; i
< n
; ++i
) {
2385 vector
<ExtensionAttribute
>::add((*other
)[i
]);