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 "../common/dbgnew.hh"
11 #include "Typestuff.hh" // FIXME CTs
12 #include "CompType.hh"
13 #include "TypeCompat.hh"
14 #include "CompField.hh"
15 #include "SigParam.hh"
16 #include "EnumItem.hh"
18 #include "Valuestuff.hh"
19 #include "ttcn3/ArrayDimensions.hh"
20 #include "asn1/Tag.hh"
21 #include "asn1/Block.hh"
22 #include "asn1/Ref.hh"
23 #include "Constraint.hh"
25 #include "../common/pattern.hh"
26 #include "ttcn3/Attributes.hh"
27 #include "XerAttributes.hh"
28 #include "ttcn3/Ttcnstuff.hh"
29 #include "ttcn3/TtcnTemplate.hh"
30 #include "ttcn3/Templatestuff.hh"
32 #include "../common/static_check.h"
33 #include "PredefFunc.hh"
35 // implemented in coding_attrib_p.y
36 extern Ttcn::ExtensionAttributes
* parse_extattributes(
37 Ttcn::WithAttribPath
*w_attrib_path
);
41 using Ttcn::MultiWithAttrib
;
42 using Ttcn::SingleWithAttrib
;
43 using Ttcn::WithAttribPath
;
45 const char* Type::type_as_string
[] = {
46 "undefined", // T_UNDEF
47 "erroneous", // T_ERROR
48 "null(ASN)", // T_NULL
51 "integer(ASN.1)", // T_INT_A
52 "real/float", // T_REAL
53 "enumerated(ASN.1)", // T_ENUM_A
54 "enumerated(TTCN-3)", // T_ENUM_T
55 "bitstring", // T_BSTR
56 "bitstring(ASN)", // T_BSTR_A
57 "hexstring(TTCN-3)", // T_HSTR
58 "octetstring", // T_OSTR
59 "charstring (TTCN-3)", // T_CSTR
60 "universal charstring(TTCN-3)", // T_USTR
61 "UTF8String(ASN.1)", // T_UTF8STRING
62 "NumericString(ASN.1)", // T_NUMERICSTRING
63 "PrintableString(ASN.1)", // T_PRINTABLESTRING
64 "TeletexString(ASN.1)", //T_TELETEXSTRING
65 "VideotexString(ASN.1)", // T_VIDEOTEXSTRING
66 "IA5String(ASN.1)", // T_IA5STRING
67 "GraphicString(ASN.1)", // T_GRAPHICSTRING,
68 "VisibleString(ASN.1)", // T_VISIBLESTRING
69 "GeneralString (ASN.1)", // T_GENERALSTRING
70 "UniversalString (ASN.1)", // T_UNIVERSALSTRING
71 "BMPString (ASN.1)", // T_BMPSTRING
72 "UnrestrictedCharacterString(ASN.1)", // T_UNRESTRICTEDSTRING
73 "UTCTime(ASN.1)", // T_UTCTIME
74 "GeneralizedTime(ASN.1)", // T_GENERALIZEDTIME
75 "Object descriptor, a kind of string (ASN.1)", // T_OBJECTDESCRIPTOR
76 "object identifier", // T_OID
77 "relative OID(ASN.1)", // T_ROID
78 "choice(ASN-1)", // T_CHOICE_A
79 "union(TTCN-3)", // T_CHOICE_T
80 "sequence (record) of", // T_SEQOF
82 "sequence(ASN-1)", // T_SEQ_A
83 "record(TTCN-3)", // T_SEQ_T
84 "set(ASN.1)", // T_SET_A
85 "set(TTCN-3)", // T_SET_T
86 "ObjectClassFieldType(ASN.1)", // T_OCFT
87 "open type(ASN.1)", // T_OPENTYPE
88 "ANY(deprecated ASN.1)", // T_ANY
89 "external(ASN.1)", // T_EXTERNAL
90 "embedded PDV(ASN.1)", // T_EMBEDDED_PDV
91 "referenced", // T_REFD
92 "special referenced(by pointer, not by name)", // T_REFDSPEC
93 "selection type(ASN.1)", // T_SELTYPE
94 "verdict type(TTCN-3)", // T_VERDICT
95 "port type(TTCN-3)", // T_PORT
96 "component type(TTCN-3)", // T_COMPONENT
97 "address type(TTCN-3)", // T_ADDRESS
98 "default type (TTCN-3)", // T_DEFAULT
99 "array(TTCN-3)", // T_ARRAY
100 "signature(TTCN-3)", // T_SIGNATURE
101 "function reference(TTCN-3)", // T_FUNCTION
102 "altstep reference(TTCN-3)", // T_ALTSTEP
103 "testcase reference(TTCN-3)", // T_TESTCASE
104 "anytype(TTCN-3)", // T_ANYTYPE
107 // =================================
109 // =================================
110 const char* Type::asString() const {
111 if (this->get_typetype() < Type::T_LAST
&& Type::T_UNDEF
< this->get_typetype()) {
112 return type_as_string
[this->get_typetype()];
115 return type_as_string
[Type::T_UNDEF
];
119 const char* Type::asString(Type::typetype_t type
) {
120 if (type
< Type::T_LAST
&& Type::T_UNDEF
< type
) {
121 return type_as_string
[type
];
124 return type_as_string
[Type::T_UNDEF
];
128 // Used by dump() for user-readable messages, by Def_ExtFunction::generate_*
129 // The text returned must match the case label without the "CT_" !
130 const char *Type::get_encoding_name(MessageEncodingType_t encoding_type
)
132 ENSURE_EQUAL(Type::T_UNDEF
, 0);
133 ENSURE_EQUAL(Type::OT_UNKNOWN
, 0);
134 switch (encoding_type
) {
148 return "<unknown encoding>";
152 Type
*Type::get_stream_type(MessageEncodingType_t encoding_type
)
154 switch (encoding_type
) {
158 case CT_XER
: // UTF-8 doesn't fit into charstring and universal is wasteful
160 return get_pooltype(T_OSTR
);
162 return get_pooltype(T_CSTR
);
164 FATAL_ERROR("Type::get_stream_type()");
169 map
<Type::typetype_t
, Type
> *Type::pooltypes
= 0;
171 Type
* Type::get_pooltype(typetype_t p_typetype
)
173 p_typetype
=get_typetype_ttcn3(p_typetype
);
189 break; // we have a pool type
191 return 0; // no pool type for you!
193 if (!pooltypes
) pooltypes
= new map
<typetype_t
, Type
>; // lazy init
194 else if (pooltypes
->has_key(p_typetype
)) return (*pooltypes
)[p_typetype
];
196 if (p_typetype
== T_COMPONENT
)
197 t
= new Type(T_COMPONENT
, new ComponentTypeBody());
198 else t
= new Type(p_typetype
);
199 t
->ownertype
= OT_POOL
;
200 pooltypes
->add(p_typetype
, t
);
204 void Type::destroy_pooltypes()
207 for(size_t i
=0; i
<pooltypes
->size(); i
++)
208 delete pooltypes
->get_nth_elem(i
);
215 Tag
*Type::get_default_tag()
217 typetype_t t_typetype
;
220 t_typetype
= T_INT_A
;
223 t_typetype
= T_BSTR_A
;
226 t_typetype
= T_ENUM_A
;
230 t_typetype
= T_SEQ_A
;
234 t_typetype
= T_SET_A
;
243 return get_type_refd()->get_tag();
245 t_typetype
= typetype
;
248 if (!default_tags
) default_tags
= new map
<typetype_t
, Tag
>;
249 else if (default_tags
->has_key(t_typetype
))
250 return (*default_tags
)[t_typetype
];
252 switch (t_typetype
) {
254 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_ALL
, (Int
)0);
257 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_ERROR
, (Int
)0);
260 int tagnumber
= get_default_tagnumber(t_typetype
);
261 if (tagnumber
< 0) FATAL_ERROR ("Type::get_default_tag():type `%s' "
262 "does not have default tag", get_typename().c_str());
263 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_UNIVERSAL
, Int(tagnumber
));
266 default_tags
->add(t_typetype
, tag
);
270 int Type::get_default_tagnumber(typetype_t p_tt
)
273 // note: tag number 0 is reserved for internal use
286 case T_OBJECTDESCRIPTOR
:
300 // note: tag numbers 14 and 15 are reserved for future use
305 case T_NUMERICSTRING
:
307 case T_PRINTABLESTRING
:
309 case T_TELETEXSTRING
:
311 case T_VIDEOTEXSTRING
:
317 case T_GENERALIZEDTIME
:
319 case T_GRAPHICSTRING
:
321 case T_VISIBLESTRING
:
323 case T_GENERALSTRING
:
325 case T_UNIVERSALSTRING
:
327 case T_UNRESTRICTEDSTRING
:
336 map
<Type::typetype_t
, Tag
> *Type::default_tags
= 0;
338 void Type::destroy_default_tags()
341 size_t nof_tags
= default_tags
->size();
342 for (size_t i
= 0; i
< nof_tags
; i
++)
343 delete default_tags
->get_nth_elem(i
);
344 default_tags
->clear();
350 Type::Type(const Type
& p
)
351 : Governor(p
), typetype(p
.typetype
)
354 if (p
.w_attrib_path
!= NULL
) FATAL_ERROR("Type::Type()");
355 tags
=p
.tags
?p
.tags
->clone():0;
357 constraints
=p
.constraints
->clone();
358 constraints
->set_my_type(this);
361 if(p
.parsed_restr
!=NULL
) {
362 parsed_restr
=new vector
<SubTypeParse
>;
363 for(size_t i
=0;i
<p
.parsed_restr
->size();i
++) {
364 SubTypeParse
*stp
= 0;
365 switch((*p
.parsed_restr
)[i
]->get_selection()) {
366 case SubTypeParse::STP_SINGLE
:
367 stp
=new SubTypeParse((*p
.parsed_restr
)[i
]->Single());
369 case SubTypeParse::STP_RANGE
:
370 stp
=new SubTypeParse((*p
.parsed_restr
)[i
]->Min(),
371 (*p
.parsed_restr
)[i
]->MinExclusive(),
372 (*p
.parsed_restr
)[i
]->Max(),
373 (*p
.parsed_restr
)[i
]->MaxExclusive());
375 case SubTypeParse::STP_LENGTH
:
376 FATAL_ERROR("Type::Type(Type&): STP_LENGTH");
378 default: FATAL_ERROR("Type::Type()");
380 parsed_restr
->add(stp
);
396 case T_NUMERICSTRING
:
397 case T_PRINTABLESTRING
:
398 case T_TELETEXSTRING
:
399 case T_VIDEOTEXSTRING
:
401 case T_GRAPHICSTRING
:
402 case T_VISIBLESTRING
:
403 case T_GENERALSTRING
:
404 case T_UNIVERSALSTRING
:
407 case T_GENERALIZEDTIME
:
408 case T_OBJECTDESCRIPTOR
:
414 case T_UNRESTRICTEDSTRING
:
420 u
.namednums
.block
=p
.u
.namednums
.block
?p
.u
.namednums
.block
->clone():0;
421 u
.namednums
.nvs
=p
.u
.namednums
.nvs
?p
.u
.namednums
.nvs
->clone():0;
424 u
.enums
.block
=p
.u
.enums
.block
?p
.u
.enums
.block
->clone():0;
425 u
.enums
.eis1
=p
.u
.enums
.eis1
?p
.u
.enums
.eis1
->clone():0;
426 u
.enums
.ellipsis
=p
.u
.enums
.ellipsis
;
427 u
.enums
.excSpec
=p
.u
.enums
.excSpec
?p
.u
.enums
.excSpec
->clone():0;
428 u
.enums
.eis2
=p
.u
.enums
.eis2
?p
.u
.enums
.eis2
->clone():0;
431 u
.enums
.eis
=p
.u
.enums
.eis
->clone();
432 u
.enums
.eis_by_name
=0;
438 u
.secho
.cfm
=p
.u
.secho
.cfm
->clone();
439 u
.secho
.field_by_name
= 0;
440 u
.secho
.component_internal
= false;
441 u
.secho
.has_single_charenc
= false;
445 u
.secho
.tr_compsof_ready
=p
.u
.secho
.tr_compsof_ready
;
449 u
.secho
.block
=p
.u
.secho
.block
?p
.u
.secho
.block
->clone():0;
450 u
.secho
.ctss
=p
.u
.secho
.ctss
?p
.u
.secho
.ctss
->clone():0;
451 u
.secho
.field_by_name
= 0;
452 u
.secho
.component_internal
= false;
453 u
.secho
.has_single_charenc
= false;
457 u
.seof
.ofType
=p
.u
.seof
.ofType
->clone();
458 u
.seof
.component_internal
= false;
461 u
.ref
.ref
=p
.u
.ref
.ref
->clone();
463 u
.ref
.component_internal
= false;
466 u
.ref
.oc_defn
=p
.u
.ref
.oc_defn
;
467 u
.ref
.oc_fieldname
=p
.u
.ref
.oc_fieldname
;
470 u
.ref
.type_refd
=p
.u
.ref
.type_refd
;
471 u
.ref
.component_internal
= false;
474 u
.seltype
.id
=p
.u
.seltype
.id
->clone();
475 u
.seltype
.type
=p
.u
.seltype
.type
->clone();
476 u
.seltype
.type_refd
=0;
479 u
.secho
.cfm
=new CompFieldMap();
480 u
.secho
.cfm
->set_my_type(this);
481 u
.secho
.oc_defn
=p
.u
.secho
.oc_defn
;
482 u
.secho
.oc_fieldname
=p
.u
.secho
.oc_fieldname
;
483 u
.secho
.my_tableconstraint
=0;
484 u
.secho
.field_by_name
= 0;
485 u
.secho
.component_internal
= false;
486 u
.secho
.has_single_charenc
= false;
489 u
.array
.element_type
=p
.u
.array
.element_type
->clone();
490 u
.array
.dimension
= p
.u
.array
.dimension
->clone();
491 u
.array
.in_typedef
= p
.u
.array
.in_typedef
;
492 u
.array
.component_internal
= false;
495 u
.port
= p
.u
.port
->clone();
498 u
.component
= p
.u
.component
->clone();
504 u
.signature
.parameters
= p
.u
.signature
.parameters
?
505 p
.u
.signature
.parameters
->clone() : 0;
506 u
.signature
.return_type
= p
.u
.signature
.return_type
?
507 p
.u
.signature
.return_type
->clone() : 0;
508 u
.signature
.no_block
= p
.u
.signature
.no_block
;
509 u
.signature
.exceptions
= p
.u
.signature
.exceptions
?
510 p
.u
.signature
.exceptions
->clone() : 0;
511 u
.signature
.component_internal
= false;
515 u
.fatref
.fp_list
= p
.u
.fatref
.fp_list
->clone();
516 u
.fatref
.runs_on
.ref
= p
.u
.fatref
.runs_on
.ref
?
517 p
.u
.fatref
.runs_on
.ref
->clone() : 0;
518 u
.fatref
.runs_on
.self
= p
.u
.fatref
.runs_on
.self
;
519 u
.fatref
.runs_on
.type
= 0;
520 u
.fatref
.return_type
= p
.u
.fatref
.return_type
?
521 p
.u
.fatref
.return_type
->clone() : 0;
522 u
.fatref
.is_startable
= false;
523 u
.fatref
.returns_template
= p
.u
.fatref
.returns_template
;
524 u
.fatref
.template_restriction
= p
.u
.fatref
.template_restriction
;
527 u
.fatref
.fp_list
= p
.u
.fatref
.fp_list
->clone();
528 u
.fatref
.runs_on
.ref
= p
.u
.fatref
.runs_on
.ref
?
529 p
.u
.fatref
.runs_on
.ref
->clone() : 0;
530 u
.fatref
.runs_on
.self
= false;
531 u
.fatref
.runs_on
.type
= 0;
532 u
.fatref
.system
.ref
= p
.u
.fatref
.system
.ref
?
533 p
.u
.fatref
.system
.ref
->clone() : 0;
534 u
.fatref
.system
.type
= 0;
535 u
.fatref
.is_startable
= false;
536 u
.fatref
.returns_template
= false;
537 u
.fatref
.template_restriction
= TR_NONE
;
540 FATAL_ERROR("Type::Type()");
546 tags_checked
= false;
547 tbl_cons_checked
= false;
548 text_checked
= false;
549 json_checked
= false;
553 raw_length_calculated
= false;
554 has_opentypes
= false;
555 opentype_outermost
= false;
556 code_generated
= false;
557 embed_values_possible
= false;
558 use_nil_possible
= false;
559 use_order_possible
= false;
565 encode_attrib_path
= 0;
573 ownertype
= OT_UNKNOWN
;
575 chk_finished
= false;
576 pard_type_instance
= false;
579 void Type::clean_up()
593 case T_NUMERICSTRING
:
594 case T_PRINTABLESTRING
:
595 case T_TELETEXSTRING
:
596 case T_VIDEOTEXSTRING
:
598 case T_GRAPHICSTRING
:
599 case T_VISIBLESTRING
:
600 case T_GENERALSTRING
:
601 case T_UNIVERSALSTRING
:
604 case T_GENERALIZEDTIME
:
605 case T_OBJECTDESCRIPTOR
:
611 case T_UNRESTRICTEDSTRING
:
620 delete u
.namednums
.block
;
621 delete u
.namednums
.nvs
;
624 delete u
.enums
.block
;
626 u
.enums
.eis1
->release_eis();
630 u
.enums
.eis2
->release_eis();
636 if (u
.enums
.eis_by_name
) {
637 for (size_t a
= 0; a
< u
.enums
.eis_by_name
->size(); a
++) {
638 delete u
.enums
.eis_by_name
->get_nth_elem(a
);
640 u
.enums
.eis_by_name
->clear();
641 delete u
.enums
.eis_by_name
;
647 delete u
.secho
.block
;
656 if (u
.secho
.field_by_name
) {
657 for(size_t a
= 0; a
< u
.secho
.field_by_name
->size(); a
++) {
658 delete u
.secho
.field_by_name
->get_nth_elem(a
);
660 u
.secho
.field_by_name
->clear();
661 delete u
.secho
.field_by_name
;
666 delete u
.seof
.ofType
;
673 delete u
.seltype
.type
;
676 delete u
.array
.element_type
;
677 delete u
.array
.dimension
;
686 delete u
.signature
.parameters
;
687 delete u
.signature
.return_type
;
688 delete u
.signature
.exceptions
;
692 delete u
.fatref
.fp_list
;
693 delete u
.fatref
.runs_on
.ref
;
694 delete u
.fatref
.return_type
;
697 delete u
.fatref
.fp_list
;
698 delete u
.fatref
.runs_on
.ref
;
699 delete u
.fatref
.system
.ref
;
702 FATAL_ERROR("Type::clean_up()");
722 for (size_t i
= 0; i
< parsed_restr
->size(); i
++)
723 delete (*parsed_restr
)[i
];
724 parsed_restr
->clear();
728 delete w_attrib_path
;
730 delete encode_attrib_path
;
731 encode_attrib_path
= 0;
734 Type::Type(typetype_t p_tt
)
735 : Governor(S_T
), typetype(p_tt
)
750 case T_NUMERICSTRING
:
751 case T_PRINTABLESTRING
:
752 case T_TELETEXSTRING
:
753 case T_VIDEOTEXSTRING
:
755 case T_GRAPHICSTRING
:
756 case T_VISIBLESTRING
:
757 case T_GENERALSTRING
:
758 case T_UNIVERSALSTRING
:
761 case T_GENERALIZEDTIME
:
762 case T_OBJECTDESCRIPTOR
:
768 case T_UNRESTRICTEDSTRING
:
773 u
.secho
.cfm
= new CompFieldMap
;
774 u
.secho
.cfm
->set_my_type(this);
777 u
.secho
.field_by_name
= 0;
778 u
.secho
.component_internal
= false;
779 u
.secho
.has_single_charenc
= false;
790 FATAL_ERROR("Type::Type()");
794 Type::Type(typetype_t p_tt
, EnumItems
*p_eis
)
795 : Governor(S_T
), typetype(p_tt
)
797 if (p_tt
!= T_ENUM_T
|| !p_eis
) FATAL_ERROR("Type::Type()");
800 u
.enums
.eis_by_name
=0;
803 Type::Type(typetype_t p_tt
, Block
*p_block
)
804 : Governor(S_T
), typetype(p_tt
)
806 if (!p_block
) FATAL_ERROR("NULL parameter");
811 u
.namednums
.block
=p_block
;
815 u
.enums
.eis
=new EnumItems();
816 u
.enums
.block
=p_block
;
818 u
.enums
.ellipsis
=false;
821 u
.enums
.eis_by_name
=0;
825 u
.secho
.tr_compsof_ready
=false;
829 u
.secho
.block
=p_block
;
831 u
.secho
.field_by_name
= 0;
832 u
.secho
.component_internal
= false;
833 u
.secho
.has_single_charenc
= false;
836 FATAL_ERROR("Type::Type()");
840 Type::Type(typetype_t p_tt
,
841 EnumItems
*p_eis1
, bool p_ellipsis
, EnumItems
*p_eis2
)
842 : Governor(S_T
), typetype(p_tt
)
844 if (p_tt
!= T_ENUM_A
|| !p_eis1
) FATAL_ERROR("Type::Type()");
846 u
.enums
.eis
=new EnumItems();
849 u
.enums
.ellipsis
=p_ellipsis
;
851 u
.enums
.eis_by_name
=0;
854 Type::Type(typetype_t p_tt
, CompFieldMap
*p_cfm
)
855 : Governor(S_T
), typetype(p_tt
)
857 if (!p_cfm
) FATAL_ERROR("NULL parameter");
864 u
.secho
.field_by_name
= 0;
865 u
.secho
.component_internal
= false;
866 u
.secho
.has_single_charenc
= false;
869 FATAL_ERROR("Type::Type()");
873 Type::Type(typetype_t p_tt
, Type
*p_type
)
874 : Governor(S_T
), typetype(p_tt
)
876 if (!p_type
) FATAL_ERROR("NULL parameter");
881 u
.seof
.ofType
=p_type
;
882 u
.seof
.ofType
->set_ownertype(OT_RECORD_OF
, this);
883 u
.seof
.component_internal
= false;
886 u
.ref
.type_refd
=p_type
;
887 u
.ref
.type_refd
->set_ownertype(OT_REF_SPEC
, this);
888 u
.ref
.component_internal
= false;
891 FATAL_ERROR("Type::Type()");
895 Type::Type(typetype_t p_tt
, Identifier
*p_id
, Type
*p_type
)
896 : Governor(S_T
), typetype(p_tt
)
898 if (p_tt
!= T_SELTYPE
|| !p_id
|| !p_type
) FATAL_ERROR("Type::Type()");
901 u
.seltype
.type
=p_type
;
902 u
.seltype
.type
->set_ownertype(OT_SELTYPE
, this);
903 u
.seltype
.type_refd
=0;
906 Type::Type(typetype_t p_tt
, Type
*p_type
, Ttcn::ArrayDimension
*p_dim
,
908 : Governor(S_T
), typetype(p_tt
)
910 if (p_tt
!= T_ARRAY
|| !p_type
|| !p_dim
) FATAL_ERROR("Type::Type()");
912 u
.array
.element_type
= p_type
;
913 u
.array
.element_type
->set_ownertype(OT_ARRAY
, this);
914 u
.array
.dimension
= p_dim
;
915 u
.array
.in_typedef
= p_in_typedef
;
916 u
.array
.component_internal
= false;
919 Type::Type(typetype_t p_tt
, Type
*p_type
, OC_defn
*p_oc_defn
,
920 const Identifier
*p_id
)
921 : Governor(S_T
), typetype(p_tt
)
923 if (p_tt
!= T_OCFT
|| !p_type
||!p_oc_defn
|| !p_id
)
924 FATAL_ERROR("Type::Type()");
926 u
.ref
.type_refd
=p_type
;
927 u
.ref
.type_refd
->set_ownertype(OT_OCFT
, this);
928 u
.ref
.oc_defn
=p_oc_defn
;
929 u
.ref
.oc_fieldname
=p_id
;
930 u
.ref
.component_internal
= false;
933 Type::Type(typetype_t p_tt
, OC_defn
*p_oc_defn
,
934 const Identifier
*p_id
)
935 : Governor(S_T
), typetype(p_tt
)
937 if (p_tt
!= T_OPENTYPE
|| !p_oc_defn
|| !p_id
) FATAL_ERROR("Type::Type()");
940 u
.secho
.cfm
=new CompFieldMap();
941 u
.secho
.cfm
->set_my_type(this);
942 u
.secho
.oc_defn
=p_oc_defn
;
943 u
.secho
.oc_fieldname
=p_id
;
944 u
.secho
.my_tableconstraint
=0;
945 u
.secho
.field_by_name
= 0;
946 u
.secho
.component_internal
= false;
947 u
.secho
.has_single_charenc
= false;
950 Type::Type(typetype_t p_tt
, Reference
*p_ref
)
951 : Governor(S_T
), typetype(p_tt
)
953 if (p_tt
!= T_REFD
|| !p_ref
) FATAL_ERROR("Type::Type()");
957 u
.ref
.component_internal
= false;
960 Type::Type(typetype_t p_tt
, Ttcn::PortTypeBody
*p_pb
)
961 : Governor(S_T
), typetype(p_tt
)
963 if (p_tt
!= T_PORT
|| !p_pb
) FATAL_ERROR("Type::Type()");
966 p_pb
->set_my_type(this);
969 Type::Type(typetype_t p_tt
, ComponentTypeBody
*p_cb
)
970 : Governor(S_T
), typetype(p_tt
)
972 if (p_tt
!= T_COMPONENT
|| !p_cb
) FATAL_ERROR("Type::Type()");
975 p_cb
->set_my_type(this);
978 Type::Type(typetype_t p_tt
, SignatureParamList
*p_params
, Type
*p_returntype
,
979 bool p_noblock
, SignatureExceptions
*p_exceptions
)
980 : Governor(S_T
), typetype(p_tt
)
982 if (p_tt
!= T_SIGNATURE
|| (p_returntype
&& p_noblock
))
983 FATAL_ERROR("Type::Type()");
985 u
.signature
.parameters
= p_params
;
986 if ((u
.signature
.return_type
= p_returntype
)) { // check assignment for 0
987 u
.signature
.return_type
->set_ownertype(OT_SIGNATURE
, this);
989 u
.signature
.no_block
= p_noblock
;
990 u
.signature
.exceptions
= p_exceptions
;
991 u
.signature
.component_internal
= false;
994 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
995 Ttcn::Reference
* p_runs_on_ref
, bool p_runs_on_self
,
996 Type
*p_returntype
, bool p_returns_template
,
997 template_restriction_t p_template_restriction
)
998 : Governor(S_T
), typetype(p_tt
)
1000 if (p_tt
!= T_FUNCTION
|| !p_params
|| (!p_returntype
&& p_returns_template
)
1001 || (p_runs_on_ref
&& p_runs_on_self
)) FATAL_ERROR("Type::Type()");
1003 u
.fatref
.fp_list
= p_params
;
1004 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1005 u
.fatref
.runs_on
.self
= p_runs_on_self
;
1006 u
.fatref
.runs_on
.type
= 0;
1007 if ((u
.fatref
.return_type
= p_returntype
)) { // check assignment for 0
1008 u
.fatref
.return_type
->set_ownertype(OT_FUNCTION
, this);
1010 u
.fatref
.is_startable
= false;
1011 u
.fatref
.returns_template
= p_returns_template
;
1012 u
.fatref
.template_restriction
= p_template_restriction
;
1015 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1016 Ttcn::Reference
* p_runs_on_ref
, bool p_runs_on_self
)
1017 : Governor(S_T
), typetype(p_tt
)
1019 if(p_tt
!= T_ALTSTEP
|| !p_params
|| (p_runs_on_ref
&& p_runs_on_self
))
1020 FATAL_ERROR("Type::Type()");
1022 u
.fatref
.fp_list
= p_params
;
1023 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1024 u
.fatref
.runs_on
.self
= p_runs_on_self
;
1025 u
.fatref
.runs_on
.type
= 0;
1026 u
.fatref
.return_type
= 0;
1027 u
.fatref
.is_startable
= false;
1028 u
.fatref
.returns_template
= false;
1029 u
.fatref
.template_restriction
= TR_NONE
;
1032 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1033 Ttcn::Reference
* p_runs_on_ref
, Ttcn::Reference
*p_system_ref
)
1034 : Governor(S_T
), typetype(p_tt
)
1036 if(p_tt
!= T_TESTCASE
|| !p_params
|| !p_runs_on_ref
)
1037 FATAL_ERROR("Type::Type()");
1039 u
.fatref
.fp_list
= p_params
;
1040 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1041 u
.fatref
.runs_on
.self
= false;
1042 u
.fatref
.runs_on
.type
= 0;
1043 u
.fatref
.system
.ref
= p_system_ref
;
1044 u
.fatref
.system
.type
= 0;
1045 u
.fatref
.is_startable
= false;
1046 u
.fatref
.returns_template
= false;
1047 u
.fatref
.template_restriction
= TR_NONE
;
1055 void Type::free_pools()
1057 destroy_default_tags();// Additionally: R&S license warning
1058 destroy_pooltypes();// Additionally: R&S license checkin/disconnect/shutdown
1061 Type
*Type::clone() const
1063 return new Type(*this);
1066 Type::typetype_t
Type::get_typetype_ttcn3(typetype_t p_tt
)
1077 case T_UNIVERSALSTRING
:
1079 case T_TELETEXSTRING
:
1080 case T_VIDEOTEXSTRING
:
1081 case T_GRAPHICSTRING
:
1082 case T_OBJECTDESCRIPTOR
:
1083 case T_GENERALSTRING
:
1085 case T_NUMERICSTRING
:
1086 case T_PRINTABLESTRING
:
1088 case T_VISIBLESTRING
:
1090 case T_GENERALIZEDTIME
:
1101 case T_EMBEDDED_PDV
:
1102 case T_UNRESTRICTEDSTRING
:
1108 } // switch typetype
1111 bool Type::is_asn1() const
1113 if (my_scope
) return Setting::is_asn1();
1114 // the type might be a pool type, which is considered to be a TTCN-3 type
1115 typetype_t t_typetype
= get_typetype_ttcn3(typetype
);
1116 if (pooltypes
&& pooltypes
->has_key(t_typetype
) &&
1117 (*pooltypes
)[t_typetype
] == this) return false;
1118 else FATAL_ERROR("Type::is_asn1()");
1121 bool Type::is_ref() const
1124 case T_UNRESTRICTEDSTRING
:
1127 case T_EMBEDDED_PDV
:
1138 bool Type::is_secho() const
1155 Type::truth
Type::is_charenc()
1161 bool possible
= true;
1162 size_t ncomp
= u
.secho
.cfm
->get_nof_comps();
1163 for (size_t i
=0; i
<ncomp
; ++i
) {
1164 CompField
* cf
= u
.secho
.cfm
->get_comp_byIndex(i
);
1165 if (cf
->get_type()->is_charenc() == No
) {
1166 possible
= false; break;
1170 return (xerattrib
&& (xerattrib
->useUnion_
|| xerattrib
->useType_
)) ? Yes
: No
;
1179 // UNTAGGED cannot be used to make a type character-encodable!
1180 // But USE-QNAME can!
1181 return (xerattrib
&& xerattrib
->useQName_
) ? Yes
: No
;
1183 case T_SEQOF
: // A record-of is character-encodable if it has the "list"
1184 case T_SETOF
: // attribute and its element is character-encodable.
1185 return (xerattrib
&& xerattrib
->list_
&& (u
.seof
.ofType
->is_charenc()==Yes
))
1195 truth retval
= get_type_refd_last()->is_charenc();
1196 if (retval
== Yes
) return Yes
;
1197 else if (retval
== Maybe
) {
1198 if (xerattrib
&& xerattrib
->useUnion_
) return Yes
;
1200 // else fall through to No
1210 // TODO ASN.1 restricted character string types when (if) ASN.1 gets XER
1211 // TODO check subtype; strings must be restricted to not contain
1212 // control characters (0..0x1F except 9,0x0A,0x0D)
1218 /* FIXME : this kind of check should be applied to elements of secho,
1219 * not to the type of the element ! */
1224 bool Type::has_empty_xml() {
1225 bool answer
= false;
1227 case T_SEQ_A
: case T_SEQ_T
:
1228 case T_SET_A
: case T_SET_T
: {
1229 answer
= true; // If all components are optional.
1230 size_t n_comps
= get_nof_comps();
1231 for (size_t i
= 0; i
< n_comps
; ++i
) {
1232 CompField
* cf
= get_comp_byIndex(i
);
1233 if (!cf
->get_is_optional()) {
1239 case T_SEQOF
: case T_SETOF
:
1240 // _If_ there is a length restriction, 0 length must be allowed.
1241 // By this time parsed_restr has been absorbed into sub_type.
1242 answer
= (sub_type
==0) || sub_type
->zero_length_allowed();
1250 void Type::set_fullname(const string
& p_fullname
)
1252 Governor::set_fullname(p_fullname
);
1256 if(u
.namednums
.block
) u
.namednums
.block
->set_fullname(p_fullname
);
1258 u
.namednums
.nvs
->set_fullname(p_fullname
+".<namedvalues>");
1261 if(u
.enums
.eis1
) u
.enums
.eis1
->set_fullname(p_fullname
);
1262 if(u
.enums
.eis2
) u
.enums
.eis2
->set_fullname(p_fullname
);
1265 u
.enums
.eis
->set_fullname(p_fullname
);
1272 u
.secho
.cfm
->set_fullname(p_fullname
);
1277 if (u
.secho
.ctss
) u
.secho
.ctss
->set_fullname(p_fullname
);
1281 string
subtypename(".<oftype>");
1282 Type
* t
= u
.seof
.ofType
;
1283 /* Do NOT call get_type_refd_last() or else fatal_error !
1284 * The AST is not fully set up. */
1286 /* XER will use these strings */
1287 switch (t
->typetype
)
1289 case T_EMBEDDED_PDV
: case T_EXTERNAL
:
1290 case T_SEQ_A
: case T_SEQ_T
:
1291 subtypename
= ".SEQUENCE";
1294 case T_SET_A
: case T_SET_T
:
1295 subtypename
= ".SET";
1299 subtypename
= ".SEQUENCE_OF";
1303 subtypename
= ".SET_OF";
1307 subtypename
= ".BITSTRING";
1311 subtypename
= ".BOOLEAN";
1314 case T_CHOICE_A
: case T_CHOICE_T
:
1315 subtypename
= ".CHOICE";
1318 case T_ENUM_A
: case T_ENUM_T
:
1319 subtypename
= ".ENUMERATED";
1322 case T_INT_A
: case T_INT
:
1323 subtypename
= ".INTEGER";
1329 u
.seof
.ofType
->set_fullname(p_fullname
+subtypename
);
1332 u
.ref
.ref
->set_fullname(p_fullname
);
1335 u
.seltype
.type
->set_fullname(p_fullname
+".<selection>");
1338 u
.port
->set_fullname(p_fullname
);
1341 u
.component
->set_fullname(p_fullname
);
1344 u
.array
.element_type
->set_fullname(p_fullname
+ ".<element_type>");
1345 u
.array
.dimension
->set_fullname(p_fullname
+ ".<dimension>");
1348 if (u
.signature
.parameters
)
1349 u
.signature
.parameters
->set_fullname(p_fullname
);
1350 if (u
.signature
.return_type
)
1351 u
.signature
.return_type
->set_fullname(p_fullname
+ ".<return_type>");
1352 if (u
.signature
.exceptions
)
1353 u
.signature
.exceptions
->set_fullname(p_fullname
+ ".<exception_list>");
1357 u
.fatref
.fp_list
->set_fullname(p_fullname
+ "<formal_par_list>");
1358 if (u
.fatref
.runs_on
.ref
)
1359 u
.fatref
.runs_on
.ref
->set_fullname(p_fullname
+ "<runs_on_type>");
1360 if (u
.fatref
.return_type
)
1361 u
.fatref
.return_type
->set_fullname(p_fullname
+ "<return type>");
1364 u
.fatref
.fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
1365 if (u
.fatref
.runs_on
.ref
)
1366 u
.fatref
.runs_on
.ref
->set_fullname(p_fullname
+".<runs_on_type>");
1367 if (u
.fatref
.system
.ref
)
1368 u
.fatref
.system
.ref
->set_fullname(p_fullname
+ ".<system_type>");
1375 void Type::set_my_scope(Scope
*p_scope
)
1377 Governor::set_my_scope(p_scope
);
1378 if(tags
) tags
->set_my_scope(p_scope
);
1382 if(u
.namednums
.nvs
) u
.namednums
.nvs
->set_my_scope(p_scope
);
1385 if(u
.enums
.eis1
) u
.enums
.eis1
->set_my_scope(p_scope
);
1386 if(u
.enums
.eis2
) u
.enums
.eis2
->set_my_scope(p_scope
);
1389 u
.enums
.eis
->set_my_scope(p_scope
);
1396 u
.secho
.cfm
->set_my_scope(p_scope
);
1401 if(u
.secho
.ctss
) u
.secho
.ctss
->set_my_scope(p_scope
);
1405 u
.seof
.ofType
->set_my_scope(p_scope
);
1408 u
.ref
.ref
->set_my_scope(p_scope
);
1411 u
.seltype
.type
->set_my_scope(p_scope
);
1414 u
.array
.element_type
->set_my_scope(p_scope
);
1415 u
.array
.dimension
->set_my_scope(p_scope
);
1418 u
.port
->set_my_scope(p_scope
);
1421 if (u
.signature
.parameters
)
1422 u
.signature
.parameters
->set_my_scope(p_scope
);
1423 if (u
.signature
.return_type
)
1424 u
.signature
.return_type
->set_my_scope(p_scope
);
1425 if (u
.signature
.exceptions
)
1426 u
.signature
.exceptions
->set_my_scope(p_scope
);
1429 u
.component
->set_my_scope(p_scope
);
1433 // the scope of parameter list is set later in chk_Fat()
1434 if (u
.fatref
.runs_on
.ref
)
1435 u
.fatref
.runs_on
.ref
->set_my_scope(p_scope
);
1436 if (u
.fatref
.return_type
)
1437 u
.fatref
.return_type
->set_my_scope(p_scope
);
1440 // the scope of parameter list is set later in chk_Fat()
1441 if (u
.fatref
.runs_on
.ref
)
1442 u
.fatref
.runs_on
.ref
->set_my_scope(p_scope
);
1443 if (u
.fatref
.system
.ref
)
1444 u
.fatref
.system
.ref
->set_my_scope(p_scope
);
1451 Type
* Type::get_type_refd(ReferenceChain
*refch
)
1455 if(refch
&& !refch
->add(get_fullname())) goto error
;
1456 if(!u
.ref
.type_refd
) {
1457 Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1458 if (!ass
) goto error
; // The referenced assignment is not found
1459 switch (ass
->get_asstype()) {
1460 case Assignment::A_ERROR
:
1462 case Assignment::A_TYPE
:
1463 case Assignment::A_VS
:
1464 u
.ref
.type_refd
= ass
->get_Type()->get_field_type(
1465 u
.ref
.ref
->get_subrefs(), EXPECTED_DYNAMIC_VALUE
, refch
);
1466 if (!u
.ref
.type_refd
) goto error
;
1468 //case Assignment::A_VS:
1469 //u.ref.type_refd = ass->get_Type();
1470 // if(!u.ref.type_refd) goto error;
1472 case Assignment::A_OC
:
1473 case Assignment::A_OBJECT
:
1474 case Assignment::A_OS
: {
1475 Setting
*setting
= u
.ref
.ref
->get_refd_setting();
1476 if (!setting
|| setting
->get_st() == Setting::S_ERROR
) goto error
;
1478 u
.ref
.type_refd
= dynamic_cast<Type
*>(setting
);
1479 if(!u
.ref
.type_refd
) {
1480 error("`%s' is not a reference to a type",
1481 u
.ref
.ref
->get_dispname().c_str());
1485 if (u
.ref
.type_refd
->ownertype
== OT_UNKNOWN
) {
1486 u
.ref
.type_refd
->set_ownertype(OT_REF
, this);
1491 error("`%s' is not a reference to a type",
1492 u
.ref
.ref
->get_dispname().c_str());
1495 if(!u
.ref
.type_refd
->get_my_scope()) {
1497 u
.ref
.type_refd
->set_my_scope(get_my_scope());
1498 u
.ref
.type_refd
->set_parent_type(get_parent_type());
1499 u
.ref
.type_refd
->set_genname(get_genname_own(), string("type"));
1500 u
.ref
.type_refd
->set_fullname(get_fullname()+".type");
1502 if (u
.ref
.type_refd
->typetype
== T_OPENTYPE
&& !constraints
)
1503 warning("An open type without table constraint is useless in TTCN-3");
1505 return u
.ref
.type_refd
;
1508 if(refch
&& !refch
->add(get_fullname())) goto error
;
1509 if(!u
.seltype
.type_refd
) {
1510 Type
*t
=u
.seltype
.type
->get_type_refd_last(refch
);
1511 if(t
->typetype
==T_ERROR
) goto error
;
1512 if(t
->typetype
!=T_CHOICE_A
) {
1513 error("(Reference to) a CHOICE type was expected"
1514 " in selection type.");
1517 if(!t
->has_comp_withName(*u
.seltype
.id
)) {
1518 error("No alternative with name `%s' in the given type `%s'.",
1519 u
.seltype
.id
->get_dispname().c_str(),
1520 t
->get_fullname().c_str());
1523 u
.seltype
.type_refd
=t
->get_comp_byName(*u
.seltype
.id
)->get_type();
1525 return u
.seltype
.type_refd
;
1529 if(refch
&& !refch
->add(get_fullname())) goto error
;
1530 return u
.ref
.type_refd
;
1533 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1534 Identifier
t_id(Identifier::ID_ASN
, string("EXTERNAL"));
1535 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1536 case T_EMBEDDED_PDV
: {
1537 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1538 Identifier
t_id(Identifier::ID_ASN
, string("EMBEDDED PDV"));
1539 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1540 case T_UNRESTRICTEDSTRING
: {
1541 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1542 Identifier
t_id(Identifier::ID_ASN
, string("CHARACTER STRING"));
1543 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1545 if (refch
&& !refch
->add(get_fullname())) goto error
;
1546 if (u
.address
) return u
.address
;
1547 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1548 u
.address
= my_scope
->get_scope_mod()->get_address_type();
1550 error("Type `address' is not defined in this module");
1555 FATAL_ERROR("Type::get_type_refd()");
1563 Type
* Type::get_type_refd_last(ReferenceChain
*refch
)
1566 while(t
->is_ref()) t
=t
->get_type_refd(refch
);
1570 Type
*Type::get_field_type(Ttcn::FieldOrArrayRefs
*subrefs
,
1571 expected_value_t expected_index
, ReferenceChain
*refch
,
1572 bool interrupt_if_optional
)
1574 if (!subrefs
) return this;
1576 if (expected_index
== EXPECTED_TEMPLATE
)
1577 expected_index
= EXPECTED_DYNAMIC_VALUE
;
1578 size_t nof_refs
= subrefs
->get_nof_refs();
1579 subrefs
->clear_string_element_ref();
1580 for (size_t i
= 0; i
< nof_refs
; i
++) {
1581 if (refch
) refch
->mark_state();
1582 t
= t
->get_type_refd_last(refch
);
1583 if (refch
) refch
->prev_state();
1584 // stop immediately if current type t is erroneous
1585 // (e.g. because of circular reference)
1586 if (t
->typetype
== T_ERROR
) return 0;
1587 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1588 switch (ref
->get_type()) {
1589 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
1590 const Identifier
& id
= *ref
->get_id();
1591 switch (t
->typetype
) {
1602 ref
->error("Invalid field reference `%s': type `%s' "
1603 "does not have fields", id
.get_dispname().c_str(),
1604 t
->get_typename().c_str());
1607 if (!t
->has_comp_withName(id
)) {
1608 ref
->error("Reference to non-existent field `%s' in type `%s'",
1609 id
.get_dispname().c_str(),
1610 t
->get_typename().c_str());
1613 CompField
* cf
= t
->get_comp_byName(id
);
1614 if (interrupt_if_optional
&& cf
->get_is_optional()) return 0;
1617 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
1618 Type
*embedded_type
= 0;
1619 switch (t
->typetype
) {
1622 embedded_type
= t
->u
.seof
.ofType
;
1625 embedded_type
= t
->u
.array
.element_type
;
1634 case T_NUMERICSTRING
:
1635 case T_PRINTABLESTRING
:
1636 case T_TELETEXSTRING
:
1637 case T_VIDEOTEXSTRING
:
1639 case T_GRAPHICSTRING
:
1640 case T_VISIBLESTRING
:
1641 case T_GENERALSTRING
:
1642 case T_UNIVERSALSTRING
:
1645 case T_GENERALIZEDTIME
:
1646 case T_OBJECTDESCRIPTOR
:
1647 if (subrefs
->refers_to_string_element()) {
1648 ref
->error("A string element of type `%s' cannot be indexed",
1649 t
->get_typename().c_str());
1652 subrefs
->set_string_element_ref();
1653 // string elements have the same type as the string itself
1658 ref
->error("Type `%s' cannot be indexed",
1659 t
->get_typename().c_str());
1662 // check the index value
1663 Value
*index_value
= ref
->get_val();
1664 if (t
->typetype
== T_ARRAY
) {
1665 // checking of array index is performed by the array dimension
1666 t
->u
.array
.dimension
->chk_index(index_value
, expected_index
);
1668 // perform a generic index check for other types
1669 if (refch
== 0 // variable assignment
1670 || index_value
->get_valuetype() != Value::V_NOTUSED
) {
1671 Error_Context
cntxt(index_value
, "In index value");
1672 index_value
->chk_expr_int(expected_index
);
1674 Value
*v_last
= index_value
->get_value_refd_last();
1675 if (v_last
->get_valuetype() == Value::V_INT
) {
1676 const int_val_t
*index_int
= v_last
->get_val_Int();
1677 if (*index_int
> INT_MAX
) {
1678 index_value
->error("Integer value `%s' is too big for indexing "
1679 "type `%s'", (index_int
->t_str()).c_str(),
1680 (t
->get_typename()).c_str());
1681 index_value
->set_valuetype(Value::V_ERROR
);
1683 if (*index_int
< 0) {
1684 index_value
->error("A non-negative integer value was "
1685 "expected for indexing type `%s' instead of `%s'",
1686 t
->get_typename().c_str(), (index_int
->t_str()).c_str());
1687 index_value
->set_valuetype(Value::V_ERROR
);
1692 // change t to the embedded type
1696 FATAL_ERROR("Type::get_field_type(): invalid reference type");
1702 bool Type::get_subrefs_as_array(const Ttcn::FieldOrArrayRefs
*subrefs
, dynamic_array
<size_t>& subrefs_array
, dynamic_array
<Type
*>& type_array
)
1704 if (!subrefs
) FATAL_ERROR("Type::get_subrefs_as_array()");
1706 size_t nof_refs
= subrefs
->get_nof_refs();
1707 for (size_t i
= 0; i
< nof_refs
; i
++) {
1708 t
= t
->get_type_refd_last();
1710 if (t
->typetype
== T_ERROR
) FATAL_ERROR("Type::get_subrefs_as_array()");
1711 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1712 size_t field_index
=0;
1713 switch (ref
->get_type()) {
1714 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
1715 const Identifier
& id
= *ref
->get_id();
1716 if (!t
->has_comp_withName(id
)) FATAL_ERROR("Type::get_subrefs_as_array()");
1717 CompField
* cf
= t
->get_comp_byName(id
);
1718 field_index
= t
->get_comp_index_byName(id
);
1719 field_index
= t
->get_codegen_index(field_index
);
1722 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
1723 Value
*index_value
= ref
->get_val();
1724 Value
*v_last
= index_value
->get_value_refd_last();
1725 if (v_last
->get_valuetype()!=Value::V_INT
) {
1726 // workaround: get_field_type() does not return NULL if the index
1727 // value is invalid, this function returns false in this case
1730 const int_val_t
*index_int
= v_last
->get_val_Int();
1731 if (!index_int
->is_native() || index_int
->is_negative()) {
1734 field_index
= (size_t)index_int
->get_val();
1735 Type
*embedded_type
= 0;
1736 switch (t
->typetype
) {
1739 embedded_type
= t
->u
.seof
.ofType
;
1742 embedded_type
= t
->u
.array
.element_type
;
1748 // change t to the embedded type
1752 FATAL_ERROR("Type::get_subrefs_as_array()");
1754 subrefs_array
.add(field_index
);
1759 bool Type::is_optional_field() const {
1760 if (ownertype
== OT_COMP_FIELD
) {
1761 const CompField
* const myOwner
= (CompField
*) owner
;
1762 return myOwner
&& myOwner
->get_is_optional();
1767 bool Type::field_is_optional(Ttcn::FieldOrArrayRefs
*subrefs
)
1769 // handling trivial cases
1770 if (!subrefs
) return false;
1771 size_t nof_subrefs
= subrefs
->get_nof_refs();
1772 if (nof_subrefs
< 1) return false;
1773 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
->get_ref(nof_subrefs
- 1);
1774 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) return false;
1775 // following the embedded types
1776 Type
*t
=get_type_refd_last();
1777 for (size_t i
= 0; i
< nof_subrefs
- 1; i
++) {
1778 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1779 if (ref
->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF
)
1780 t
= t
->get_comp_byName(*ref
->get_id())->get_type();
1781 else t
= t
->get_ofType();
1782 t
=t
->get_type_refd_last();
1784 // now last_ref refers to a field of t
1785 return t
->get_comp_byName(*last_ref
->get_id())->get_is_optional();
1788 bool Type::is_root_basic(){
1789 Type
*t
=get_type_refd_last();
1790 switch(t
->typetype
){
1805 int Type::get_raw_length(){
1806 if(!raw_checked
) FATAL_ERROR("Type::get_raw_length()");
1807 if(raw_length_calculated
) return raw_length
;
1808 raw_length_calculated
=true;
1811 raw_length
=get_type_refd()->get_raw_length();
1814 if(rawattrib
) raw_length
=rawattrib
->fieldlength
;
1818 if(rawattrib
) raw_length
=rawattrib
->fieldlength
;
1825 if(rawattrib
&& rawattrib
->fieldlength
) raw_length
=rawattrib
->fieldlength
;
1829 if(rawattrib
&& rawattrib
->fieldlength
) raw_length
=rawattrib
->fieldlength
;
1832 int max_val
=u
.enums
.first_unused
;
1833 for(size_t a
=0;a
<u
.enums
.eis
->get_nof_eis();a
++){
1834 int val
=u
.enums
.eis
->get_ei_byIndex(a
)->get_value()->get_val_Int()
1836 if((max_val
<0?-max_val
:max_val
)<(val
<0?-val
:val
)) max_val
=val
;
1838 if(max_val
<0){ min_bits
=1;max_val
=-max_val
;}
1839 while(max_val
){ min_bits
++; max_val
/=2;}
1840 raw_length
=min_bits
;
1846 for(size_t i
= 0; i
< get_nof_comps(); i
++){
1848 CompField
* cf
=get_comp_byIndex(i
);
1849 if(cf
->get_is_optional()){
1853 l
=cf
->get_type()->get_raw_length();
1858 if(cf
->get_type()->rawattrib
1859 && (cf
->get_type()->rawattrib
->pointerto
1860 || cf
->get_type()->rawattrib
->lengthto_num
)){
1867 // TODO: case T_ANYTYPE: for get_raw_length needed ?
1869 for(size_t i
= 0; i
< get_nof_comps(); i
++){
1870 CompField
*cf
=get_comp_byIndex(i
);
1872 l
=cf
->get_type()->get_raw_length();
1893 /** \todo: add extra checks and warnings for unsupported attributes
1894 * e.g. when TAG refers to a record/set field which has union type */
1895 void Type::chk_raw()
1897 bool self_ref
= false;
1898 if (raw_checked
) return;
1900 if (!enable_raw()) return;
1903 restrlength
=(int)sub_type
->get_length_restriction();
1904 if(restrlength
!=-1){
1906 Type
*t
=get_type_refd_last();
1907 typetype_t basic_type
=t
->typetype
;
1908 rawattrib
=new RawAST(basic_type
==T_INT
);
1909 if(basic_type
==T_REAL
) rawattrib
->fieldlength
=64;
1911 rawattrib
->length_restrition
=restrlength
;
1913 if(!rawattrib
) return;
1916 get_type_refd()->force_raw();
1917 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
1918 typetype_t basic_type
=get_type_refd_last()->typetype
;
1921 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
1922 rawattrib
->length_restrition
=-1;
1925 rawattrib
->fieldlength
=rawattrib
->length_restrition
*4;
1926 rawattrib
->length_restrition
=-1;
1929 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
1930 rawattrib
->length_restrition
=-1;
1933 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
1934 rawattrib
->length_restrition
=-1;
1938 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
1939 rawattrib
->length_restrition
=-1;
1948 size_t nof_comps
= get_nof_comps();
1949 for (size_t i
= 0; i
< nof_comps
; i
++)
1950 get_comp_byIndex(i
)->get_type()->force_raw();
1951 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++){
1952 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1953 if(!has_comp_withName(*idf
)){
1954 error("Invalid field name `%s' in RAW parameter TAG for type `%s'",
1955 idf
->get_dispname().c_str(), get_typename().c_str());
1958 size_t fieldnum
= get_comp_index_byName(*idf
);
1959 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1961 CompField
*cf
=get_comp_byIndex(fieldnum
);
1962 Type
*t
=cf
->get_type()->get_type_refd_last();
1963 for(int b
=0;b
<rawattrib
->taglist
.tag
[c
].keyList
[a
].
1964 keyField
->nElements
;b
++){
1966 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
1968 error("Invalid fieldmember type in RAW parameter TAG"
1970 ,cf
->get_name().get_dispname().c_str());
1974 if(!t
->has_comp_withName(*idf2
)){
1975 error("Invalid field member name `%s' in RAW parameter TAG "
1976 "for field `%s'", idf2
->get_dispname().c_str(),
1977 cf
->get_name().get_dispname().c_str());
1981 size_t comp_index
=t
->get_comp_index_byName(*idf2
);
1982 CompField
*cf2
=t
->get_comp_byIndex(comp_index
);
1983 t
=cf2
->get_type()->get_type_refd_last();
1986 Error_Context
cntx(this, "In Raw parmeter TAG");
1987 Value
*v
= rawattrib
->taglist
.tag
[c
].keyList
[a
].v_value
;
1988 v
->set_my_scope(get_my_scope());
1989 v
->set_my_governor(t
);
1990 t
->chk_this_value_ref(v
);
1991 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
1992 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
1993 Value::valuetype_t vt
= v
->get_valuetype();
1994 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
1995 Free(rawattrib
->taglist
.tag
[c
].keyList
[a
].value
);
1996 rawattrib
->taglist
.tag
[c
].keyList
[a
].value
=
1997 mcopystr(v
->get_single_expr().c_str());
2008 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++) { // check TAG
2009 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
2010 if(!has_comp_withName(*idf
)){
2011 error("Invalid field name `%s' in RAW parameter TAG "
2012 "for type `%s'", idf
->get_dispname().c_str(),
2013 get_typename().c_str());
2016 fieldnum
=get_comp_index_byName(*idf
);
2017 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
2019 CompField
*cf
=get_comp_byIndex(fieldnum
);
2020 Type
*t
=cf
->get_type()->get_type_refd_last();
2021 for(int b
=0;b
<rawattrib
->taglist
.tag
[c
].keyList
[a
].
2022 keyField
->nElements
;b
++){
2024 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2026 error("Invalid fieldmember type in RAW parameter TAG"
2028 ,cf
->get_name().get_dispname().c_str());
2032 if(!t
->has_comp_withName(*idf2
)){
2033 error("Invalid field member name `%s' in RAW parameter TAG "
2034 "for field `%s'", idf2
->get_dispname().c_str(),
2035 cf
->get_name().get_dispname().c_str());
2039 size_t comp_index
=t
->get_comp_index_byName(*idf2
);
2040 CompField
*cf2
=t
->get_comp_byIndex(comp_index
);
2041 t
=cf2
->get_type()->get_type_refd_last();
2044 Error_Context
cntx(this, "In Raw parmeter TAG");
2045 Value
*v
= rawattrib
->taglist
.tag
[c
].keyList
[a
].v_value
;
2046 v
->set_my_scope(get_my_scope());
2047 v
->set_my_governor(t
);
2048 t
->chk_this_value_ref(v
);
2049 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2050 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2051 Value::valuetype_t vt
= v
->get_valuetype();
2052 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2053 Free(rawattrib
->taglist
.tag
[c
].keyList
[a
].value
);
2054 rawattrib
->taglist
.tag
[c
].keyList
[a
].value
=
2055 mcopystr(v
->get_single_expr().c_str());
2060 for(int a
=0; a
<rawattrib
->ext_bit_goup_num
;a
++){ // EXTENSION_BIT_GROUP
2061 Identifier
*idf
=rawattrib
->ext_bit_groups
[a
].from
;
2062 Identifier
*idf2
=rawattrib
->ext_bit_groups
[a
].to
;
2064 if(!has_comp_withName(*idf
)){
2065 error("Invalid field name `%s' in RAW parameter "
2066 "EXTENSION_BIT_GROUP for type `%s'",
2067 idf
->get_dispname().c_str(), get_typename().c_str());
2070 if(!has_comp_withName(*idf2
)){
2071 error("Invalid field name `%s' in RAW parameter "
2072 "EXTENSION_BIT_GROUP for type `%s'",
2073 idf2
->get_dispname().c_str(), get_typename().c_str());
2077 size_t kezd
=get_comp_index_byName(*idf
);
2078 size_t veg
=get_comp_index_byName(*idf2
);
2080 error("Invalid field order in RAW parameter "
2081 "EXTENSION_BIT_GROUP for type `%s': `%s', `%s'",
2082 get_typename().c_str(), idf
->get_dispname().c_str(),
2083 idf2
->get_dispname().c_str());
2088 if(rawattrib
->paddall
!=XDEFDEFAULT
){ // PADDALL
2089 for(size_t i
= 0; i
< get_nof_comps(); i
++) {
2090 CompField
*cfield
=get_comp_byIndex(i
);
2091 RawAST
*field_rawattr
=cfield
->get_type()->rawattrib
;
2092 if(field_rawattr
==NULL
){
2093 Type
*t
=cfield
->get_type()->get_type_refd_last();
2094 typetype_t basic_type
=t
->typetype
;
2095 t
=cfield
->get_type();
2096 if(t
->is_ref()) t
=t
->get_type_refd();
2097 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd();
2098 field_rawattr
= new RawAST(t
->rawattrib
,basic_type
==T_INT
);
2099 if(!t
->rawattrib
&& basic_type
==T_REAL
) field_rawattr
->fieldlength
=64;
2100 cfield
->get_type()->rawattrib
=field_rawattr
;
2102 if(field_rawattr
->padding
==0)
2103 field_rawattr
->padding
=rawattrib
->padding
;
2104 if(field_rawattr
->prepadding
==0)
2105 field_rawattr
->prepadding
=rawattrib
->prepadding
;
2106 if (field_rawattr
->padding_pattern_length
== 0 &&
2107 rawattrib
->padding_pattern_length
> 0) {
2108 Free(field_rawattr
->padding_pattern
);
2109 field_rawattr
->padding_pattern
=
2110 mcopystr(rawattrib
->padding_pattern
);
2111 field_rawattr
->padding_pattern_length
=
2112 rawattrib
->padding_pattern_length
;
2116 if(rawattrib
->fieldorder
!=XDEFDEFAULT
){ // FIELDORDER
2117 for(size_t i
= 0; i
< get_nof_comps(); i
++) {
2118 CompField
*cfield
=get_comp_byIndex(i
);
2119 RawAST
*field_rawattr
=cfield
->get_type()->rawattrib
;
2120 if(field_rawattr
==NULL
){
2121 Type
*t
=cfield
->get_type()->get_type_refd_last();
2122 typetype_t basic_type
=t
->typetype
;
2123 t
=cfield
->get_type();
2124 if(t
->is_ref()) t
=t
->get_type_refd();
2125 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd();
2126 field_rawattr
= new RawAST(t
->rawattrib
,basic_type
==T_INT
);
2127 if(!t
->rawattrib
&& basic_type
==T_REAL
) field_rawattr
->fieldlength
=64;
2128 cfield
->get_type()->rawattrib
=field_rawattr
;
2130 if(field_rawattr
->fieldorder
==XDEFDEFAULT
)
2131 field_rawattr
->fieldorder
=rawattrib
->fieldorder
;
2135 for(int a
=0;a
<rawattrib
->presence
.nElements
;a
++){ //PRESENCE
2138 for(int b
=0;b
<rawattrib
->presence
.keyList
[a
].keyField
->nElements
;b
++){
2139 Identifier
*idf
=rawattrib
->presence
.keyList
[a
].keyField
->names
[b
];
2141 error("Invalid fieldmember type in RAW parameter PRESENCE"
2142 " for the record %s."
2143 ,get_typename().c_str());
2147 if(!t
->has_comp_withName(*idf
)){
2148 error("Invalid fieldname in RAW parameter"
2149 " PRESENCE for the record %s: %s"
2150 ,get_typename().c_str()
2151 ,rawattrib
->presence
.keyList
[a
].keyField
->names
[b
]
2152 ->get_dispname().c_str());
2156 t
=t
->get_comp_byName(*idf
)->get_type()->get_type_refd_last();
2159 Error_Context
cntx(this, "In Raw parameter PRESENCE");
2160 Value
*v
= rawattrib
->presence
.keyList
[a
].v_value
;
2161 v
->set_my_scope(get_my_scope());
2162 v
->set_my_governor(t
);
2163 t
->chk_this_value_ref(v
);
2164 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2165 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2166 Value::valuetype_t vt
= v
->get_valuetype();
2167 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2168 Free(rawattrib
->presence
.keyList
[a
].value
);
2169 rawattrib
->presence
.keyList
[a
].value
=
2170 mcopystr(v
->get_single_expr().c_str());
2174 for(size_t i
= 0; i
< get_nof_comps(); i
++) { // field attributes
2175 CompField
*cf
= get_comp_byIndex(i
);
2176 const Identifier
& field_id
= cf
->get_name();
2177 Type
*field_type
= cf
->get_type();
2178 Type
*field_type_last
= field_type
->get_type_refd_last();
2179 field_type
->force_raw();
2180 RawAST
*rawpar
= field_type
->rawattrib
;
2182 for (int j
= 0; j
< rawpar
->lengthto_num
; j
++) { // LENGTHTO
2183 Identifier
*idf
= rawpar
->lengthto
[j
];
2184 if (!has_comp_withName(*idf
)) {
2185 error("Invalid fieldname in RAW parameter "
2186 "LENGTHTO for field %s: %s",
2187 field_id
.get_dispname().c_str(),
2188 rawpar
->lengthto
[j
]->get_dispname().c_str());
2191 if (rawpar
->lengthto_num
) {
2192 Type
*ft
= field_type
;
2193 if (ft
->get_typetype() == T_REFD
) ft
= ft
->get_type_refd_last();
2194 typetype_t ftt
= ft
->get_typetype();
2201 for (size_t fi
= 0; fi
< ft
->get_nof_comps(); fi
++) {
2202 typetype_t uftt
= ft
->get_comp_byIndex(fi
)->get_type()
2204 if (uftt
!= T_INT
&& uftt
!= T_INT_A
)
2205 error("The union type LENGTHTO field must contain only "
2215 if (rawpar
->lengthindex
) break; // Will be checked in the next step.
2216 // Else continue with default.
2218 error("The LENGTHTO field must be an integer or union type "
2219 "instead of `%s'", ft
->get_typename().c_str());
2223 if(rawpar
->lengthto_num
&& rawpar
->lengthindex
){ // LENGTHINDEX
2224 Identifier
*idf
=rawpar
->lengthindex
->names
[0];
2225 if(!field_type_last
->is_secho()){
2226 error("Invalid fieldmember type in RAW parameter LENGTHINDEX"
2228 ,field_id
.get_dispname().c_str());
2231 if(!field_type_last
->has_comp_withName(*idf
))
2232 error("Invalid fieldname in RAW parameter"
2233 " LENGTHINDEX for field %s: %s"
2234 ,field_id
.get_dispname().c_str()
2235 ,rawpar
->lengthindex
->names
[0]->get_dispname().c_str());
2237 if(rawpar
->pointerto
){ // POINTERTO
2238 Identifier
*idf
=rawpar
->pointerto
;
2241 if(!has_comp_withName(*idf
)){
2242 error("Invalid fieldname in RAW"
2243 " parameter POINTERTO for field %s: %s"
2244 ,field_id
.get_dispname().c_str()
2245 ,rawpar
->pointerto
->get_dispname().c_str());
2248 if(!hiba
&& (pointed
=get_comp_index_byName(*idf
))<=i
){
2249 error("Pointer must precede the pointed field. Incorrect field "
2250 "name `%s' in RAW parameter POINTERTO for field `%s'",
2251 rawpar
->pointerto
->get_dispname().c_str(),
2252 field_id
.get_dispname().c_str());
2255 if(!hiba
&& rawpar
->ptrbase
){ // POINTERTO
2256 Identifier
*idf2
=rawpar
->ptrbase
;
2257 if(!has_comp_withName(*idf2
)){
2258 error("Invalid field name `%s' in RAW parameter PTROFFSET for "
2259 "field `%s'", rawpar
->ptrbase
->get_dispname().c_str(),
2260 field_id
.get_dispname().c_str());
2263 if(!hiba
&& get_comp_index_byName(*idf2
)>pointed
){
2264 error("Pointer base must precede the pointed field. Incorrect "
2265 "field name `%s' in RAW parameter PTROFFSET for field "
2266 "`%s'", rawpar
->ptrbase
->get_dispname().c_str(),
2267 field_id
.get_dispname().c_str());
2271 for(int a
=0;a
<rawpar
->presence
.nElements
;a
++){ //PRESENCE
2274 for(int b
=0;b
<rawpar
->presence
.keyList
[a
].keyField
->nElements
;b
++){
2275 Identifier
*idf
=rawpar
->presence
.keyList
[a
].keyField
->names
[b
];
2277 error("Invalid fieldmember type in RAW parameter PRESENCE"
2279 ,field_id
.get_dispname().c_str());
2283 if(!t
->has_comp_withName(*idf
)){
2284 error("Invalid fieldname `%s' in RAW parameter PRESENCE for "
2285 "field `%s'", rawpar
->presence
.keyList
[a
].keyField
2286 ->names
[b
]->get_dispname().c_str(),
2287 field_id
.get_dispname().c_str());
2291 if(b
==0 && !(get_comp_index_byName(*rawpar
->presence
.keyList
[a
]
2292 .keyField
->names
[0])<i
)){
2293 error("The PRESENCE field `%s' must precede the optional field "
2294 "in RAW parameter PRESENCE for field `%s'"
2295 ,rawpar
->presence
.keyList
[a
].keyField
->names
[0]
2296 ->get_dispname().c_str()
2297 ,field_id
.get_dispname().c_str());
2301 t
=t
->get_comp_byName(*idf
)->get_type()->get_type_refd_last();
2304 Error_Context
cntx(this, "In Raw parmeter PRESENCE");
2305 Value
*v
= rawpar
->presence
.keyList
[a
].v_value
;
2306 v
->set_my_scope(get_my_scope());
2307 v
->set_my_governor(t
);
2308 t
->chk_this_value_ref(v
);
2309 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2310 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2311 Value::valuetype_t vt
= v
->get_valuetype();
2312 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2313 Free(rawpar
->presence
.keyList
[a
].value
);
2314 rawpar
->presence
.keyList
[a
].value
=
2315 mcopystr(v
->get_single_expr().c_str());
2319 for(int c
=0;c
<rawpar
->crosstaglist
.nElements
;c
++) { // CROSSTAG
2320 Identifier
*idf
=rawpar
->crosstaglist
.tag
[c
].fieldName
;
2321 if(!field_type_last
->is_secho()){
2322 error("Invalid fieldmember type in RAW parameter CROSSTAG"
2324 ,field_id
.get_dispname().c_str());
2327 if(!field_type_last
->has_comp_withName(*idf
)){
2328 error("Invalid fieldmember name in RAW parameter CROSSTAG"
2330 ,field_id
.get_dispname().c_str()
2331 ,rawpar
->crosstaglist
.tag
[c
].fieldName
2332 ->get_dispname().c_str());
2335 for(int a
=0;a
<rawpar
->crosstaglist
.tag
[c
].nElements
;a
++){
2338 bool allow_omit
= false;
2340 b
<rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->nElements
;b
++){
2342 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2343 if(!t2
->is_secho()){
2344 error("Invalid fieldmember type in RAW parameter CROSSTAG"
2346 ,field_id
.get_dispname().c_str());
2350 if(!t2
->has_comp_withName(*idf2
)){
2351 error("Invalid fieldname in RAW parameter CROSSTAG"
2353 ,field_id
.get_dispname().c_str()
2354 ,idf2
->get_dispname().c_str());
2359 size_t field_idx
= get_comp_index_byName(*idf2
);
2360 if (field_idx
== i
) {
2361 error("RAW parameter CROSSTAG for field `%s' cannot refer "
2362 "to the field itself", idf2
->get_dispname().c_str());
2363 } else if (field_idx
> i
) {
2364 if (cf
->get_is_optional() ||
2365 field_type
->get_raw_length() < 0)
2366 error("Field `%s' that CROSSTAG refers to must precede "
2367 "field `%s' or field `%s' must be mandatory with "
2368 "fixed length", idf2
->get_dispname().c_str(),
2369 field_id
.get_dispname().c_str(),
2370 field_id
.get_dispname().c_str());
2373 CompField
*cf2
=t2
->get_comp_byName(*idf2
);
2374 t2
=cf2
->get_type()->get_type_refd_last();
2375 if (b
== rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
2376 ->nElements
- 1 && cf2
->get_is_optional())
2380 Error_Context
cntx(this, "In Raw parmeter CROSSTAG");
2381 Value
*v
= rawpar
->crosstaglist
.tag
[c
].keyList
[a
].v_value
;
2382 v
->set_my_scope(get_my_scope());
2383 v
->set_my_governor(t2
);
2384 t2
->chk_this_value_ref(v
);
2385 self_ref
= t2
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2386 INCOMPLETE_NOT_ALLOWED
,
2387 (allow_omit
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
), SUB_CHK
);
2388 Value::valuetype_t vt
= v
->get_valuetype();
2389 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2390 Free(rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
);
2391 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
=
2392 mcopystr(v
->get_single_expr().c_str());
2401 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2402 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
2403 rawattrib
->length_restrition
=-1;
2407 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2408 rawattrib
->fieldlength
=rawattrib
->length_restrition
*4;
2409 rawattrib
->length_restrition
=-1;
2413 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2414 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
2415 rawattrib
->length_restrition
=-1;
2419 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2420 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
2421 rawattrib
->length_restrition
=-1;
2426 get_ofType()->force_raw();
2427 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2428 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
2429 rawattrib
->length_restrition
=-1;
2431 if(rawattrib
->length_restrition
!=-1 &&
2432 rawattrib
->length_restrition
!=rawattrib
->fieldlength
){
2433 error("Invalid length specified in parameter FIELDLENGTH for %s of "
2434 "type `%s'. The FIELDLENGTH must be equal to specified length "
2435 "restriction", typetype
== T_SEQOF
? "record" : "set",
2436 get_fullname().c_str());
2440 if(rawattrib
->fieldlength
!=64 && rawattrib
->fieldlength
!=32){
2441 error("Invalid length (%d) specified in parameter FIELDLENGTH for "
2442 "float type `%s'. The FIELDLENGTH must be single (32) or double "
2443 "(64)", rawattrib
->fieldlength
, get_fullname().c_str());
2450 // nothing to do, ASN1 types or types without defined raw attribute
2457 void Type::force_raw()
2465 // TODO case T_ANYTYPE: for force_raw ?
2469 rawattrib
= new RawAST(false);
2472 if (is_ref()) get_type_refd()->force_raw();
2477 // Don't run chk_raw() on unchecked types
2482 void Type::chk_text()
2484 if (text_checked
) return;
2485 text_checked
= true;
2486 if (!textattrib
|| !enable_text()) return;
2487 //textattrib->print_TextAST();
2489 chk_text_matching_values(textattrib
->begin_val
, "BEGIN");
2490 chk_text_matching_values(textattrib
->end_val
, "END");
2491 chk_text_matching_values(textattrib
->separator_val
, "SEPARATOR");
2498 size_t nof_comps
= get_nof_comps();
2499 for (size_t i
= 0; i
< nof_comps
; i
++)
2500 get_comp_byIndex(i
)->get_type()->force_text();
2504 get_ofType()->force_text();
2507 if (is_ref()) get_type_refd()->force_text();
2511 switch (get_type_refd_last()->typetype
) {
2513 chk_text_matching_values(textattrib
->true_params
, "true value");
2514 chk_text_matching_values(textattrib
->false_params
, "false value");
2517 if(textattrib
->nof_field_params
){
2518 Type
*t
=get_type_refd_last();
2519 size_t nof_comps
= t
->u
.enums
.eis
->get_nof_eis();
2520 textAST_enum_def
**params
=(textAST_enum_def
**)
2521 Malloc(nof_comps
*sizeof(textAST_enum_def
*));
2522 memset(params
,0,nof_comps
*sizeof(textAST_enum_def
*));
2523 for (int a
= 0; a
< textattrib
->nof_field_params
; a
++) {
2524 const Identifier
& id
= *textattrib
->field_params
[a
]->name
;
2525 if (t
->u
.enums
.eis
->has_ei_withName(id
)) {
2526 int index
= t
->get_eis_index_byName(id
);
2527 if (params
[index
]) FATAL_ERROR("Type::chk_text(): duplicate " \
2528 "attribute for enum `%s'", id
.get_dispname().c_str());
2529 params
[index
] = textattrib
->field_params
[a
];
2530 char *attrib_name
= mprintf("enumerated value `%s'",
2531 id
.get_dispname().c_str());
2532 chk_text_matching_values(¶ms
[index
]->value
, attrib_name
);
2535 error("Coding attribute refers to non-existent enumerated value "
2536 "`%s'", id
.get_dispname().c_str());
2537 Free(textattrib
->field_params
[a
]->value
.encode_token
);
2538 Free(textattrib
->field_params
[a
]->value
.decode_token
);
2539 delete textattrib
->field_params
[a
]->name
;
2540 Free(textattrib
->field_params
[a
]);
2543 Free(textattrib
->field_params
);
2544 textattrib
->field_params
=params
;
2545 textattrib
->nof_field_params
=nof_comps
;
2551 if (textattrib
->decode_token
) {
2552 char *tmp
= textattrib
->decode_token
;
2553 textattrib
->decode_token
= process_decode_token(tmp
, *this);
2555 tmp
= TTCN_pattern_to_regexp(textattrib
->decode_token
);
2558 error("Incorrect select token expression: `%s'",
2559 textattrib
->decode_token
);
2566 //textattrib->print_TextAST();
2569 void Type::chk_text_matching_values(textAST_matching_values
*matching_values
,
2570 const char *attrib_name
)
2572 if (!matching_values
) return;
2573 if (matching_values
->decode_token
) {
2574 // check whether decode token is a correct TTCN-3 pattern
2575 char *tmp
= matching_values
->decode_token
;
2576 matching_values
->decode_token
= process_decode_token(tmp
, *this);
2578 tmp
= TTCN_pattern_to_regexp(matching_values
->decode_token
);
2581 error("Incorrect matching expression for %s: `%s'", attrib_name
,
2582 matching_values
->decode_token
);
2584 } else if (matching_values
->encode_token
) {
2585 // the decode token is not present, but there is an encode token
2586 // derive the decode token from the encode token
2587 matching_values
->generated_decode_token
= true;
2588 matching_values
->decode_token
=
2589 convert_charstring_to_pattern(matching_values
->encode_token
);
2593 void Type::force_text()
2601 // TODO case T_ANYTYPE: for force_text ?
2605 textattrib
= new TextAST
;
2608 if (is_ref()) get_type_refd()->force_text();
2616 void Type::chk_json()
2618 if (json_checked
) return;
2619 json_checked
= true;
2620 if ((NULL
== jsonattrib
&& !hasEncodeAttr(CT_JSON
)) || !enable_json()) return;
2630 size_t nof_comps
= get_nof_comps();
2631 for (size_t i
= 0; i
< nof_comps
; i
++)
2632 get_comp_byIndex(i
)->get_type()->force_json();
2636 get_ofType()->force_json();
2639 if (is_ref()) get_type_refd()->force_json();
2643 if (NULL
!= jsonattrib
) {
2644 if (jsonattrib
->omit_as_null
&& !is_optional_field()) {
2645 error("Invalid attribute, 'omit as null' requires optional "
2646 "field of a record or set.");
2649 if (jsonattrib
->as_value
&& T_CHOICE_T
!= get_type_refd_last()->typetype
) {
2650 error("Invalid attribute, 'as value' is only allowed for unions");
2653 if (NULL
!= jsonattrib
->alias
) {
2654 Type
* parent
= get_parent_type();
2655 if (NULL
== parent
|| (T_SEQ_T
!= parent
->typetype
&&
2656 T_SET_T
!= parent
->typetype
&& T_CHOICE_T
!= parent
->typetype
)) {
2657 error("Invalid attribute, 'name as ...' requires field of a "
2658 "record, set or union.");
2660 if (NULL
!= parent
&& NULL
!= parent
->jsonattrib
&&
2661 T_CHOICE_T
== parent
->typetype
&& parent
->jsonattrib
->as_value
) {
2662 warning("Attribute 'name as ...' will be ignored, because parent union "
2663 "is encoded without field names.");
2667 if (NULL
!= jsonattrib
->default_value
) {
2673 void Type::chk_json_default()
2675 const char* dval
= jsonattrib
->default_value
;
2676 const size_t dval_len
= strlen(dval
);
2677 Type
*last
= get_type_refd_last();
2679 switch (last
->typetype
) {
2681 if (strcmp(dval
, "true") != 0 && strcmp(dval
, "false") != 0) {
2686 for (size_t i
= (dval
[0] == '-') ? 1 : 0; i
< dval_len
; ++i
) {
2687 if (dval
[i
] < '0' || dval
[i
] > '9') {
2689 break; // from the loop
2694 if (strcmp(dval
, "infinity") == 0 || strcmp(dval
, "-infinity") == 0 ||
2695 strcmp(dval
, "not_a_number") == 0) {
2696 // special float values => skip the rest of the check
2700 boolean first_digit
= false; // first non-zero digit reached
2701 boolean zero
= false; // first zero digit reached
2702 boolean decimal_point
= false; // decimal point (.) reached
2703 boolean exponent_mark
= false; // exponential mark (e or E) reached
2704 boolean exponent_sign
= false; // sign of the exponential (- or +) reached
2706 size_t i
= (dval
[0] == '-') ? 1 : 0;
2707 while(!err
&& i
< dval_len
) {
2710 if (decimal_point
|| exponent_mark
|| (!first_digit
&& !zero
)) {
2713 decimal_point
= true;
2714 first_digit
= false;
2719 if (exponent_mark
|| (!first_digit
&& !zero
)) {
2722 exponent_mark
= true;
2723 first_digit
= false;
2727 if (!first_digit
&& (exponent_mark
|| (!decimal_point
&& zero
))) {
2741 if (!first_digit
&& zero
&& (!decimal_point
|| exponent_mark
)) {
2748 if (exponent_sign
|| !exponent_mark
|| zero
|| first_digit
) {
2751 exponent_sign
= true;
2758 err
= !first_digit
&& !zero
;
2761 for (size_t i
= 0; i
< dval_len
; ++i
) {
2762 if (dval
[i
] < '0' || dval
[i
] > '1') {
2764 break; // from the loop
2769 if (dval_len
% 2 != 0) {
2775 for (size_t i
= 0; i
< dval_len
; ++i
) {
2776 if ((dval
[i
] < '0' || dval
[i
] > '9') && (dval
[i
] < 'a' || dval
[i
] > 'f') &&
2777 (dval
[i
] < 'A' || dval
[i
] > 'F')) {
2779 break; // from the loop
2786 while(!err
&& i
< dval_len
) {
2787 if (dval
[i
] < 0 && last
->typetype
== T_CSTR
) {
2790 else if (dval
[i
] == '\\') {
2791 if (i
== dval_len
- 1) {
2804 break; // these are OK
2806 if (i
+ 4 >= dval_len
) {
2808 } else if (last
->typetype
== T_CSTR
&&
2809 (dval
[i
+ 1] != '0' || dval
[i
+ 2] != '0' ||
2810 dval
[i
+ 3] < '0' || dval
[i
+ 3] > '7')) {
2813 for (size_t j
= (last
->typetype
== T_CSTR
) ? 4 : 1; j
<= 4; ++j
) {
2814 if ((dval
[i
+ j
] < '0' || dval
[i
+ j
] > '9') &&
2815 (dval
[i
+ j
] < 'a' || dval
[i
+ j
] > 'f') &&
2816 (dval
[i
+ j
] < 'A' || dval
[i
+ j
] > 'F')) {
2818 break; // from the loop
2834 Common::Identifier
id(Identifier::ID_TTCN
, string(dval
));
2835 if (!last
->has_ei_withName(id
)) {
2840 if (strcmp(dval
, "none") != 0 && strcmp(dval
, "pass") != 0 &&
2841 strcmp(dval
, "inconc") != 0 && strcmp(dval
, "fail") != 0 &&
2842 strcmp(dval
, "error") != 0) {
2847 error("JSON default values are not available for type `%s'",
2848 last
->get_stringRepr().c_str());
2853 if (last
->typetype
== T_ENUM_T
) {
2854 error("Invalid JSON default value for enumerated type `%s'",
2855 last
->get_stringRepr().c_str());
2857 error("Invalid %s JSON default value", get_typename_builtin(last
->typetype
));
2862 void Type::force_json()
2877 jsonattrib
= new JsonAST
;
2880 if (is_ref()) get_type_refd()->force_json();
2889 int Type::get_length_multiplier()
2893 return get_type_refd()->get_length_multiplier();
2908 /** \todo review, especially the string types... */
2909 bool Type::is_compatible_tt_tt(typetype_t p_tt1
, typetype_t p_tt2
,
2910 bool p_is_asn11
, bool p_is_asn12
)
2912 if (p_tt2
== T_ERROR
) return true;
2914 // error type is compatible with everything
2917 // unambiguous built-in types
2933 return p_tt1
== p_tt2
;
2935 return p_tt2
==T_OSTR
|| (!p_is_asn11
&& p_tt2
==T_ANY
);
2941 case T_UNIVERSALSTRING
:
2942 case T_TELETEXSTRING
:
2943 case T_VIDEOTEXSTRING
:
2944 case T_GRAPHICSTRING
:
2945 case T_OBJECTDESCRIPTOR
:
2946 case T_GENERALSTRING
:
2948 case T_NUMERICSTRING
:
2949 case T_PRINTABLESTRING
:
2951 case T_VISIBLESTRING
:
2953 case T_GENERALIZEDTIME
:
2958 // character string group 1
2961 case T_UNIVERSALSTRING
:
2966 case T_UNIVERSALSTRING
:
2968 case T_NUMERICSTRING
:
2969 case T_PRINTABLESTRING
:
2971 case T_VISIBLESTRING
:
2973 case T_GENERALIZEDTIME
:
2978 // character string group 2
2979 case T_TELETEXSTRING
:
2980 case T_VIDEOTEXSTRING
:
2981 case T_GRAPHICSTRING
:
2982 case T_OBJECTDESCRIPTOR
:
2983 case T_GENERALSTRING
:
2985 case T_TELETEXSTRING
:
2986 case T_VIDEOTEXSTRING
:
2987 case T_GRAPHICSTRING
:
2988 case T_OBJECTDESCRIPTOR
:
2989 case T_GENERALSTRING
:
2991 case T_NUMERICSTRING
:
2992 case T_PRINTABLESTRING
:
2994 case T_VISIBLESTRING
:
2996 case T_GENERALIZEDTIME
:
2999 // maybe :) is ustr.is_cstr()
3004 // character string group 3
3006 case T_NUMERICSTRING
:
3007 case T_PRINTABLESTRING
:
3009 case T_VISIBLESTRING
:
3011 case T_GENERALIZEDTIME
:
3014 case T_NUMERICSTRING
:
3015 case T_PRINTABLESTRING
:
3017 case T_VISIBLESTRING
:
3019 case T_GENERALIZEDTIME
:
3024 // polymorphic built-in types
3027 return p_tt2
== T_BSTR
|| p_tt2
== T_BSTR_A
;
3030 return p_tt2
== T_INT
|| p_tt2
== T_INT_A
;
3031 // ROID is visible as OID from TTCN-3
3033 return p_tt2
== T_OID
||
3034 (!p_is_asn11
&& p_tt2
== T_ROID
);
3036 return p_tt2
== T_ROID
||
3037 (!p_is_asn12
&& p_tt2
== T_OID
);
3040 return p_tt2
==T_ENUM_A
|| p_tt2
==T_ENUM_T
;
3044 return p_tt2
==T_CHOICE_T
|| p_tt2
==T_CHOICE_A
|| p_tt2
==T_OPENTYPE
;
3047 return p_tt2
==T_SEQ_A
|| p_tt2
==T_SEQ_T
;
3050 return p_tt2
==T_SET_A
|| p_tt2
==T_SET_T
;
3052 return p_tt2
== T_ANY
|| p_tt2
== T_OSTR
;
3053 // these should never appear?
3060 FATAL_ERROR("Type::is_compatible_tt_tt()");
3065 bool Type::is_compatible_tt(typetype_t p_tt
, bool p_is_asn1
)
3068 Type
*t1
=get_type_refd_last();
3069 if (p_tt
== T_ERROR
) return true;
3070 switch (t1
->typetype
) {
3071 // these should never appear
3076 FATAL_ERROR("Type::is_compatible_tt()");
3079 return is_compatible_tt_tt(t1
->typetype
, p_tt
, is_asn1(), p_is_asn1
);
3083 bool Type::is_compatible(Type
*p_type
, TypeCompatInfo
*p_info
,
3084 TypeChain
*p_left_chain
, TypeChain
*p_right_chain
)
3088 Type
*t1
= get_type_refd_last();
3089 Type
*t2
= p_type
->get_type_refd_last();
3090 // Error type is compatible with everything.
3091 if (t1
->typetype
== T_ERROR
|| t2
->typetype
== T_ERROR
) return true;
3093 switch (t1
->typetype
) {
3094 // Unambiguous built-in types.
3101 is_type_comp
= (t1
->typetype
== t2
->typetype
);
3104 is_type_comp
= ( t2
->typetype
==T_OSTR
|| (!is_asn1() && t2
->typetype
==T_ANY
) );
3107 switch (t2
->typetype
) {
3111 case T_UNIVERSALSTRING
:
3112 case T_TELETEXSTRING
:
3113 case T_VIDEOTEXSTRING
:
3114 case T_GRAPHICSTRING
:
3115 case T_OBJECTDESCRIPTOR
:
3116 case T_GENERALSTRING
:
3118 case T_NUMERICSTRING
:
3119 case T_PRINTABLESTRING
:
3121 case T_VISIBLESTRING
:
3123 case T_GENERALIZEDTIME
:
3124 is_type_comp
= true;
3127 is_type_comp
= false;
3131 // Character string group 1.
3134 case T_UNIVERSALSTRING
:
3135 switch (t2
->typetype
) {
3139 case T_UNIVERSALSTRING
:
3141 case T_NUMERICSTRING
:
3142 case T_PRINTABLESTRING
:
3144 case T_VISIBLESTRING
:
3146 case T_GENERALIZEDTIME
:
3147 is_type_comp
= true;
3150 is_type_comp
= false;
3154 // Character string group 2.
3155 case T_TELETEXSTRING
:
3156 case T_VIDEOTEXSTRING
:
3157 case T_GRAPHICSTRING
:
3158 case T_OBJECTDESCRIPTOR
:
3159 case T_GENERALSTRING
:
3160 switch (t2
->typetype
) {
3161 case T_TELETEXSTRING
:
3162 case T_VIDEOTEXSTRING
:
3163 case T_GRAPHICSTRING
:
3164 case T_OBJECTDESCRIPTOR
:
3165 case T_GENERALSTRING
:
3167 case T_NUMERICSTRING
:
3168 case T_PRINTABLESTRING
:
3170 case T_VISIBLESTRING
:
3172 case T_GENERALIZEDTIME
:
3173 is_type_comp
= true;
3176 // Maybe :) is ustr.is_cstr().
3177 is_type_comp
= true;
3180 is_type_comp
= false;
3184 // Character string group 3.
3186 case T_NUMERICSTRING
:
3187 case T_PRINTABLESTRING
:
3189 case T_VISIBLESTRING
:
3191 case T_GENERALIZEDTIME
:
3192 switch (t2
->typetype
) {
3194 case T_NUMERICSTRING
:
3195 case T_PRINTABLESTRING
:
3197 case T_VISIBLESTRING
:
3199 case T_GENERALIZEDTIME
:
3200 is_type_comp
= true;
3203 is_type_comp
= false;
3207 // Polymorphic built-in types.
3210 is_type_comp
= ( t2
->typetype
== T_BSTR
|| t2
->typetype
== T_BSTR_A
);
3214 is_type_comp
= ( t2
->typetype
== T_INT
|| t2
->typetype
== T_INT_A
);
3216 // ROID is visible as OID from TTCN-3.
3218 is_type_comp
= ( t2
->typetype
== T_OID
|| (!is_asn1() && t2
->typetype
== T_ROID
) );
3221 is_type_comp
= ( t2
->typetype
== T_ROID
|| (!p_type
->is_asn1() && t2
->typetype
== T_OID
) );
3224 is_type_comp
= ( t2
->typetype
== T_COMPONENT
&& t1
->u
.component
->is_compatible(t2
->u
.component
) );
3228 is_type_comp
= t1
->is_compatible_record(t2
, p_info
, p_left_chain
, p_right_chain
);
3231 is_type_comp
= t1
->is_compatible_record_of(t2
, p_info
, p_left_chain
, p_right_chain
);
3235 is_type_comp
= t1
->is_compatible_set(t2
, p_info
, p_left_chain
, p_right_chain
);
3238 is_type_comp
= t1
->is_compatible_set_of(t2
, p_info
, p_left_chain
, p_right_chain
);
3241 is_type_comp
= t1
->is_compatible_array(t2
, p_info
, p_left_chain
, p_right_chain
);
3246 is_type_comp
= t1
->is_compatible_choice_anytype(t2
, p_info
, p_left_chain
, p_right_chain
);
3253 is_type_comp
= ( t1
== t2
);
3258 // TODO: Compatibility.
3259 is_type_comp
= ( t1
== t2
);
3262 is_type_comp
= ( t2
->typetype
== T_ANY
|| t2
->typetype
== T_OSTR
);
3265 FATAL_ERROR("Type::is_compatible()");
3267 // if types are compatible then check subtype compatibility
3268 // skip check if p_info is NULL
3269 if ((p_info
!=NULL
) && is_type_comp
&& (sub_type
!=NULL
) && (p_type
->sub_type
!=NULL
) &&
3270 (sub_type
->get_subtypetype()==p_type
->sub_type
->get_subtypetype()))
3272 if (p_info
->get_str1_elem()) {
3273 if (p_info
->get_str2_elem()) {
3274 // both are string elements -> nothing to do
3277 if (!p_type
->sub_type
->is_compatible_with_elem()) {
3278 is_type_comp
= false;
3279 p_info
->set_subtype_error(
3280 string("Subtype mismatch: string element has no common value with subtype ")+
3281 p_type
->sub_type
->to_string());
3285 if (p_info
->get_str2_elem()) {
3287 if (!sub_type
->is_compatible_with_elem()) {
3288 is_type_comp
= false;
3289 p_info
->set_subtype_error(string("Subtype mismatch: subtype ")+
3290 sub_type
->to_string()+string(" has no common value with a string element"));
3293 // string <-> string
3294 if (!sub_type
->is_compatible(p_type
->sub_type
)) {
3295 is_type_comp
= false;
3296 p_info
->set_subtype_error(string("Subtype mismatch: subtype ")+
3297 sub_type
->to_string()+string(" has no common value with subtype ")+
3298 p_type
->sub_type
->to_string());
3303 return is_type_comp
;
3306 bool Type::is_structured_type() const
3325 bool Type::is_subtype_length_compatible(Type
*p_type
)
3327 if (typetype
!= T_SEQOF
&& typetype
!= T_SETOF
)
3328 FATAL_ERROR("Type::is_subtype_length_compatible()");
3329 if (!sub_type
) return true;
3330 SubtypeConstraint::subtype_t st_t
= typetype
== T_SEQOF
?
3331 SubtypeConstraint::ST_RECORDOF
: SubtypeConstraint::ST_SETOF
;
3332 switch (p_type
->typetype
) {
3337 vector
<SubTypeParse
> p_stp_v
;
3338 Value
*p_nof_comps
= new Value(Value::V_INT
,
3339 new int_val_t(p_type
->get_nof_comps()));
3340 p_stp_v
.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps
)));
3341 SubType
p_st(st_t
, this, NULL
, &p_stp_v
, NULL
);
3345 return sub_type
->is_length_compatible(&p_st
); }
3348 if (!p_type
->sub_type
) return true;
3349 else return sub_type
->is_length_compatible(p_type
->sub_type
);
3351 if (p_type
->u
.array
.dimension
->get_has_error()) return false;
3352 vector
<SubTypeParse
> p_stp_v
;
3354 = new Value(Value::V_INT
,
3355 new int_val_t(p_type
->u
.array
.dimension
->get_size()));
3356 p_stp_v
.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps
)));
3357 SubType
p_st(st_t
, this, NULL
, &p_stp_v
, NULL
);
3358 p_st
.chk(); // Convert SubTypeParse to SubType.
3361 return sub_type
->is_length_compatible(&p_st
); }
3363 FATAL_ERROR("Type::is_subtype_length_compatible()");
3367 // Errors and warnings are reported in an upper level. We just make a
3368 // simple decision here.
3369 bool Type::is_compatible_record(Type
*p_type
, TypeCompatInfo
*p_info
,
3370 TypeChain
*p_left_chain
,
3371 TypeChain
*p_right_chain
)
3373 if (typetype
!= T_SEQ_A
&& typetype
!= T_SEQ_T
)
3374 FATAL_ERROR("Type::is_compatible_record()");
3375 // The get_type_refd_last() was called for both Types at this point. All
3376 // this code runs in both run-times.
3377 if (this == p_type
) return true;
3378 else if (!use_runtime_2
|| !p_info
3379 || (p_info
&& p_info
->is_strict())) return false;
3380 size_t nof_comps
= get_nof_comps();
3381 switch (p_type
->typetype
) {
3384 // According to 6.3.2.2 the # of fields and the optionality must be
3385 // the same for record types. It's good news for compile-time checks.
3386 // Conversion is always from "p_type -> this".
3387 size_t p_nof_comps
= p_type
->get_nof_comps();
3388 if (nof_comps
!= p_nof_comps
) {
3389 p_info
->set_is_erroneous(this, p_type
, string("The number of fields in "
3390 "record/SEQUENCE types must be the same"));
3393 // If p_info is present we have the chains as well.
3394 if (p_left_chain
->empty()) p_left_chain
->add(this);
3395 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3396 for (size_t i
= 0; i
< nof_comps
; i
++) {
3397 CompField
*cf
= get_comp_byIndex(i
);
3398 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3399 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
3400 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3401 string cf_name
= cf
->get_name().get_dispname();
3402 string p_cf_name
= p_cf
->get_name().get_dispname();
3403 if (cf
->get_is_optional() != p_cf
->get_is_optional()) {
3404 p_info
->append_ref_str(0, "." + cf_name
);
3405 p_info
->append_ref_str(1, "." + p_cf_name
);
3406 p_info
->set_is_erroneous(cf_type
, p_cf_type
, string("The optionality of "
3407 "fields in record/SEQUENCE types must be "
3411 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
3413 p_left_chain
->mark_state();
3414 p_right_chain
->mark_state();
3415 p_left_chain
->add(cf_type
);
3416 p_right_chain
->add(p_cf_type
);
3417 if (cf_type
!= p_cf_type
3418 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3419 && !cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3421 p_info
->append_ref_str(0, "." + cf_name
+ info_tmp
.get_ref_str(0));
3422 p_info
->append_ref_str(1, "." + p_cf_name
+ info_tmp
.get_ref_str(1));
3423 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3424 info_tmp
.get_error_str());
3425 p_left_chain
->previous_state();
3426 p_right_chain
->previous_state();
3429 p_left_chain
->previous_state();
3430 p_right_chain
->previous_state();
3432 p_info
->set_needs_conversion(true);
3433 p_info
->add_type_conversion(p_type
, this);
3436 if (!p_type
->is_subtype_length_compatible(this)) {
3437 p_info
->set_is_erroneous(this, p_type
, string("Incompatible record of/SEQUENCE "
3443 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3444 if (p_type
->typetype
== T_ARRAY
) {
3445 if (p_of_type
->get_typetype() == T_ARRAY
) {
3446 p_info
->set_is_erroneous(this, p_type
, string("record/SEQUENCE types are "
3447 "compatible only with single-dimension "
3451 size_t nof_opt_fields
= 0;
3452 for (size_t i
= 0; i
< nof_comps
; i
++)
3453 if (get_comp_byIndex(i
)->get_is_optional()) nof_opt_fields
++;
3454 if (p_type
->u
.array
.dimension
->get_size()
3455 < nof_comps
- nof_opt_fields
) {
3456 p_info
->set_is_erroneous(this, p_type
, string("The dimension of the array "
3457 "must be >= than the number of mandatory "
3458 "fields in the record/SEQUENCE type"));
3462 if (p_left_chain
->empty()) p_left_chain
->add(this);
3463 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3464 for (size_t i
= 0; i
< nof_comps
; i
++) {
3465 Type
*cf_type
= get_comp_byIndex(i
)->get_type()->get_type_refd_last();
3466 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_of_type
,
3468 p_left_chain
->mark_state();
3469 p_right_chain
->mark_state();
3470 p_left_chain
->add(cf_type
);
3471 p_right_chain
->add(p_of_type
);
3472 if (cf_type
!= p_of_type
3473 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3474 && !cf_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3476 p_info
->append_ref_str(0, "." + get_comp_byIndex(i
)
3477 ->get_name().get_dispname() + info_tmp
.get_ref_str(0));
3478 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
3479 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3480 info_tmp
.get_error_str());
3481 p_left_chain
->previous_state();
3482 p_right_chain
->previous_state();
3485 p_left_chain
->previous_state();
3486 p_right_chain
->previous_state();
3488 p_info
->set_needs_conversion(true);
3489 p_info
->add_type_conversion(p_type
, this);
3494 // 6.3.2.4 makes our job very easy...
3495 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3496 "compatible only with other "
3497 "union/CHOICE/anytype types"));
3502 // Only set/set of types are compatible with other set/set of types.
3503 // 6.3.2.3 is a little bit unclear about set of types, but we treat them
3504 // this way. Otherwise, it would be possible to use compatibility with
3505 // a "middle-man" set of variable between record/set types:
3506 // type set S { integer f1, integer f2 }
3507 // type record { integer f1, integer f2 }
3508 // type set of integer SO
3509 // var S s := { 1, 2 }
3510 // var R r := { 1, 2 }
3513 // if (r == s) { ... } // Not allowed.
3514 // if (r == so) { ... } // Not allowed. (?)
3515 // Seems to be a fair decision. If we would want compatibility between
3516 // variables of record/set types, we should allow it directly.
3517 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3518 "types are compatible only with other set/SET "
3519 "set of/SET OF types"));
3526 bool Type::is_compatible_record_of(Type
*p_type
, TypeCompatInfo
*p_info
,
3527 TypeChain
*p_left_chain
,
3528 TypeChain
*p_right_chain
)
3530 if (typetype
!= T_SEQOF
) FATAL_ERROR("Type::is_compatible_record_of()");
3531 if (this == p_type
) return true;
3532 else if (!use_runtime_2
|| !p_info
3533 || (p_info
&& p_info
->is_strict())) return false;
3534 switch (p_type
->typetype
) {
3537 if (!is_subtype_length_compatible(p_type
)) {
3538 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3539 "record of/SEQUENCE OF subtypes"));
3542 Type
*of_type
= get_ofType()->get_type_refd_last();
3543 if (p_left_chain
->empty()) p_left_chain
->add(this);
3544 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3545 for (size_t i
= 0; i
< p_type
->get_nof_comps(); i
++) {
3546 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3547 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3548 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3550 p_left_chain
->mark_state();
3551 p_right_chain
->mark_state();
3552 p_left_chain
->add(of_type
);
3553 p_right_chain
->add(p_cf_type
);
3554 if (of_type
!= p_cf_type
3555 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3556 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3558 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3559 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3560 info_tmp
.get_ref_str(1));
3561 p_info
->set_is_erroneous(info_tmp
.get_type(0),
3562 info_tmp
.get_type(1),
3563 info_tmp
.get_error_str());
3564 p_left_chain
->previous_state();
3565 p_right_chain
->previous_state();
3568 p_left_chain
->previous_state();
3569 p_right_chain
->previous_state();
3571 p_info
->set_needs_conversion(true);
3572 p_info
->add_type_conversion(p_type
, this);
3576 if (!is_subtype_length_compatible(p_type
)) {
3577 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3578 "record of/SEQUENCE OF subtypes"));
3581 Type
*of_type
= get_ofType()->get_type_refd_last();
3582 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3583 if (p_left_chain
->empty()) p_left_chain
->add(this);
3584 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3585 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3587 p_left_chain
->mark_state();
3588 p_right_chain
->mark_state();
3589 p_left_chain
->add(of_type
);
3590 p_right_chain
->add(p_of_type
);
3591 if (of_type
== p_of_type
3592 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3593 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3595 p_info
->set_needs_conversion(true);
3596 p_info
->add_type_conversion(p_type
, this);
3597 p_left_chain
->previous_state();
3598 p_right_chain
->previous_state();
3601 p_left_chain
->previous_state();
3602 p_right_chain
->previous_state();
3603 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3604 // Arrays already have the "[]" in their names.
3605 if (p_type
->get_typetype() != T_ARRAY
) p_info
->append_ref_str(1, string("[]"));
3606 p_info
->append_ref_str(1, info_tmp
.get_ref_str(1));
3607 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3608 info_tmp
.get_error_str());
3613 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3614 "compatible only with other "
3615 "union/CHOICE/anytype types"));
3620 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3621 "types are compatible only with other set/SET "
3622 "set of/SET OF types"));
3629 bool Type::is_compatible_array(Type
*p_type
, TypeCompatInfo
*p_info
,
3630 TypeChain
*p_left_chain
,
3631 TypeChain
*p_right_chain
)
3633 if (typetype
!= T_ARRAY
) FATAL_ERROR("Type::is_compatible_array()");
3634 // Copied from the original checker code. The type of the elements and
3635 // the dimension of the array must be the same.
3636 if (this == p_type
) return true;
3637 if (p_type
->typetype
== T_ARRAY
&& u
.array
.element_type
3638 ->is_compatible(p_type
->u
.array
.element_type
, NULL
)
3639 && u
.array
.dimension
->is_identical(p_type
->u
.array
.dimension
))
3641 else if (!use_runtime_2
|| !p_info
3642 || (p_info
&& p_info
->is_strict())) return false;
3643 Type
*of_type
= get_ofType()->get_type_refd_last();
3644 switch (p_type
->get_typetype()) {
3647 if (of_type
->get_typetype() == T_ARRAY
) {
3648 p_info
->set_is_erroneous(this, p_type
, string("record/SEQUENCE types are "
3649 "compatible only with single-dimension "
3653 size_t p_nof_comps
= p_type
->get_nof_comps();
3654 size_t p_nof_opt_fields
= 0;
3655 for (size_t i
= 0; i
< p_nof_comps
; i
++)
3656 if (p_type
->get_comp_byIndex(i
)->get_is_optional())
3658 if (u
.array
.dimension
->get_size() < p_nof_comps
- p_nof_opt_fields
) {
3659 p_info
->set_is_erroneous(this, p_type
, string("The dimension of the array "
3660 "must be >= than the number of mandatory "
3661 "fields in the record/SEQUENCE type"));
3664 if (p_left_chain
->empty()) p_left_chain
->add(this);
3665 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3666 for (size_t i
= 0; i
< p_nof_comps
; ++i
) {
3667 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3668 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3669 string p_cf_name
= p_cf
->get_name().get_dispname();
3670 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3672 p_left_chain
->mark_state();
3673 p_right_chain
->mark_state();
3674 p_left_chain
->add(of_type
);
3675 p_right_chain
->add(p_cf_type
);
3676 if (of_type
!= p_cf_type
3677 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3678 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3680 p_info
->append_ref_str(0, info_tmp
.get_ref_str(0));
3681 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3682 info_tmp
.get_ref_str(1));
3683 p_info
->set_is_erroneous(info_tmp
.get_type(0),
3684 info_tmp
.get_type(1),
3685 info_tmp
.get_error_str());
3686 p_left_chain
->previous_state();
3687 p_right_chain
->previous_state();
3690 p_left_chain
->previous_state();
3691 p_right_chain
->previous_state();
3693 p_info
->set_needs_conversion(true);
3694 p_info
->add_type_conversion(p_type
, this);
3697 if (!p_type
->is_subtype_length_compatible(this)) {
3698 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3699 "record of/SEQUENCE OF subtypes"));
3703 if (p_type
->get_typetype() == T_ARRAY
3704 && !u
.array
.dimension
->is_identical(p_type
->u
.array
.dimension
)) {
3705 p_info
->set_is_erroneous(this, p_type
, string("Array types should have "
3706 "the same dimension"));
3709 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3710 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3712 if (p_left_chain
->empty()) p_left_chain
->add(this);
3713 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3714 p_left_chain
->mark_state();
3715 p_right_chain
->mark_state();
3716 p_left_chain
->add(of_type
);
3717 p_right_chain
->add(p_of_type
);
3718 if (of_type
== p_of_type
3719 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3720 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3722 p_info
->set_needs_conversion(true);
3723 p_info
->add_type_conversion(p_type
, this);
3724 p_left_chain
->previous_state();
3725 p_right_chain
->previous_state();
3728 p_left_chain
->previous_state();
3729 p_right_chain
->previous_state();
3730 p_info
->append_ref_str(0, info_tmp
.get_ref_str(0));
3731 if (p_type
->get_typetype() != T_ARRAY
) p_info
->append_ref_str(1, string("[]"));
3732 p_info
->append_ref_str(1, info_tmp
.get_ref_str(1));
3733 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3734 info_tmp
.get_error_str());
3739 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3740 "compatible only with other "
3741 "union/CHOICE/anytype types"));
3746 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3747 "types are compatible only with other set/SET "
3748 "set of/SET OF types"));
3755 bool Type::is_compatible_set(Type
*p_type
, TypeCompatInfo
*p_info
,
3756 TypeChain
*p_left_chain
,
3757 TypeChain
*p_right_chain
)
3759 if (typetype
!= T_SET_A
&& typetype
!= T_SET_T
)
3760 FATAL_ERROR("Type::is_compatible_set()");
3761 if (this == p_type
) return true;
3762 else if (!use_runtime_2
|| !p_info
3763 || (p_info
&& p_info
->is_strict())) return false;
3764 size_t nof_comps
= get_nof_comps();
3765 switch (p_type
->typetype
) {
3768 // The standard is very generous. We don't need to check for a possible
3769 // combination of compatible fields. According to 6.3.2.3, simply do
3770 // the same thing as for T_SEQ_{A,T} types. The fields are in their
3772 size_t p_nof_comps
= p_type
->get_nof_comps();
3773 if (nof_comps
!= p_nof_comps
) {
3774 p_info
->set_is_erroneous(this, p_type
, string("The number of fields in "
3775 "set/SET types must be the same"));
3778 if (p_left_chain
->empty()) p_left_chain
->add(this);
3779 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3780 for (size_t i
= 0; i
< nof_comps
; i
++) {
3781 CompField
*cf
= get_comp_byIndex(i
);
3782 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3783 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
3784 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3785 string cf_name
= cf
->get_name().get_dispname();
3786 string p_cf_name
= p_cf
->get_name().get_dispname();
3787 if (cf
->get_is_optional() != p_cf
->get_is_optional()) {
3788 p_info
->append_ref_str(0, "." + cf_name
);
3789 p_info
->append_ref_str(1, "." + p_cf_name
);
3790 p_info
->set_is_erroneous(cf_type
, p_cf_type
, string("The optionality of "
3791 "fields in set/SET types must be the "
3795 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
3797 p_left_chain
->mark_state();
3798 p_right_chain
->mark_state();
3799 p_left_chain
->add(cf_type
);
3800 p_right_chain
->add(p_cf_type
);
3801 if (cf_type
!= p_cf_type
3802 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3803 && !cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3805 p_info
->append_ref_str(0, "." + cf_name
+ info_tmp
.get_ref_str(0));
3806 p_info
->append_ref_str(1, "." + p_cf_name
+ info_tmp
.get_ref_str(1));
3807 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3808 info_tmp
.get_error_str());
3809 p_left_chain
->previous_state();
3810 p_right_chain
->previous_state();
3813 p_left_chain
->previous_state();
3814 p_right_chain
->previous_state();
3816 p_info
->set_needs_conversion(true);
3817 p_info
->add_type_conversion(p_type
, this);
3820 if (!p_type
->is_subtype_length_compatible(this)) {
3821 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
3825 if (p_left_chain
->empty()) p_left_chain
->add(this);
3826 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3827 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3828 for (size_t i
= 0; i
< nof_comps
; i
++) {
3829 Type
*cf_type
= get_comp_byIndex(i
)->get_type()->get_type_refd_last();
3830 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_of_type
,
3832 p_left_chain
->mark_state();
3833 p_right_chain
->mark_state();
3834 p_left_chain
->add(cf_type
);
3835 p_right_chain
->add(p_of_type
);
3836 if (cf_type
!= p_of_type
3837 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3838 && !cf_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3840 p_info
->append_ref_str(0, "." + get_comp_byIndex(i
)
3841 ->get_name().get_dispname() + info_tmp
.get_ref_str(0));
3842 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
3843 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3844 info_tmp
.get_error_str());
3845 p_left_chain
->previous_state();
3846 p_right_chain
->previous_state();
3849 p_left_chain
->previous_state();
3850 p_right_chain
->previous_state();
3852 p_info
->set_needs_conversion(true);
3853 p_info
->add_type_conversion(p_type
, this);
3858 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3859 "compatible only with other "
3860 "union/CHOICE/anytype types"));
3866 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3867 "types are compatible only with other set/SET "
3868 "set of/SET OF types"));
3875 bool Type::is_compatible_set_of(Type
*p_type
, TypeCompatInfo
*p_info
,
3876 TypeChain
*p_left_chain
,
3877 TypeChain
*p_right_chain
)
3879 if (typetype
!= T_SETOF
) FATAL_ERROR("Type::is_compatible_set_of()");
3880 if (this == p_type
) return true;
3881 else if (!use_runtime_2
|| !p_info
3882 || (p_info
&& p_info
->is_strict())) return false;
3883 Type
*of_type
= get_ofType();
3884 switch (p_type
->get_typetype()) {
3887 if (!is_subtype_length_compatible(p_type
)) {
3888 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
3892 if (p_left_chain
->empty()) p_left_chain
->add(this);
3893 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3894 for (size_t i
= 0; i
< p_type
->get_nof_comps(); i
++) {
3895 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3896 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3897 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3899 p_left_chain
->mark_state();
3900 p_right_chain
->mark_state();
3901 p_left_chain
->add(of_type
);
3902 p_right_chain
->add(p_cf_type
);
3903 if (of_type
!= p_cf_type
3904 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3905 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3907 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3908 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3909 info_tmp
.get_ref_str(1));
3910 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3911 info_tmp
.get_error_str());
3912 p_left_chain
->previous_state();
3913 p_right_chain
->previous_state();
3916 p_left_chain
->previous_state();
3917 p_right_chain
->previous_state();
3919 p_info
->set_needs_conversion(true);
3920 p_info
->add_type_conversion(p_type
, this);
3923 if (!is_subtype_length_compatible(p_type
)) {
3924 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
3928 if (p_left_chain
->empty()) p_left_chain
->add(this);
3929 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3930 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3931 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3933 p_left_chain
->mark_state();
3934 p_right_chain
->mark_state();
3935 p_left_chain
->add(of_type
);
3936 p_right_chain
->add(p_of_type
);
3937 if (of_type
== p_of_type
3938 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3939 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3941 p_info
->set_needs_conversion(true);
3942 p_info
->add_type_conversion(p_type
, this);
3943 p_left_chain
->previous_state();
3944 p_right_chain
->previous_state();
3947 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3948 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
3949 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3950 info_tmp
.get_error_str());
3951 p_left_chain
->previous_state();
3952 p_right_chain
->previous_state();
3957 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype "
3958 "types are compatible only with other "
3959 "union/CHOICE/anytype types"));
3965 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3966 "types are compatible only with other set/SET "
3967 "set of/SET OF types"));
3974 bool Type::is_compatible_choice_anytype(Type
*p_type
,
3975 TypeCompatInfo
*p_info
,
3976 TypeChain
*p_left_chain
,
3977 TypeChain
*p_right_chain
)
3979 if (typetype
!= T_ANYTYPE
&& typetype
!= T_CHOICE_A
3980 && typetype
!= T_CHOICE_T
)
3981 FATAL_ERROR("Type::is_compatible_choice_anytype()");
3982 if (this == p_type
) return true; // Original "true" leaf...
3983 else if (!use_runtime_2
|| !p_info
3984 || (p_info
&& p_info
->is_strict())) return false; // ...and "false".
3985 if ((typetype
== T_ANYTYPE
&& p_type
->get_typetype() != T_ANYTYPE
)
3986 || (p_type
->get_typetype() == T_ANYTYPE
&& typetype
!= T_ANYTYPE
)) {
3987 p_info
->set_is_erroneous(this, p_type
, string("Type anytype is compatible only "
3988 "with other anytype types"));
3991 switch (p_type
->get_typetype()) {
3999 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
4000 "compatible only with other union/CHOICE/anytype "
4005 if (typetype
!= T_CHOICE_A
&& typetype
!= T_CHOICE_T
) {
4006 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE types are "
4007 "compatible only with other union/CHOICE "
4013 if (p_left_chain
->empty()) p_left_chain
->add(this);
4014 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4015 // Find a field with the same name and with compatible type. There can
4016 // be more alternatives, we need to generate all conversion functions.
4017 // The same field types must be avoided. (For anytypes the "field
4018 // name = module name + field name".)
4019 bool alles_okay
= false;
4020 for (size_t i
= 0; i
< get_nof_comps(); i
++) {
4021 CompField
*cf
= get_comp_byIndex(i
);
4022 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
4023 for (size_t j
= 0; j
< p_type
->get_nof_comps(); ++j
) {
4024 CompField
*p_cf
= p_type
->get_comp_byIndex(j
);
4025 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
4026 if (cf
->get_name().get_name() != p_cf
->get_name().get_name())
4028 // Don't report errors for each incompatible field, it would be a
4029 // complete mess. Use this temporary for all fields. And forget
4031 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
4033 p_left_chain
->mark_state();
4034 p_right_chain
->mark_state();
4035 p_left_chain
->add(cf_type
);
4036 p_right_chain
->add(p_cf_type
);
4037 if (cf_type
== p_cf_type
4038 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4039 || cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
4041 if (cf_type
!= p_cf_type
&& cf_type
->is_structured_type()
4042 && p_cf_type
->is_structured_type()) {
4043 if (typetype
== T_ANYTYPE
&& cf_type
->get_my_scope()
4044 ->get_scope_mod() != p_cf_type
->get_my_scope()
4045 ->get_scope_mod()) {
4046 p_left_chain
->previous_state();
4047 p_right_chain
->previous_state();
4050 p_info
->add_type_conversion(p_cf_type
, cf_type
);
4054 p_left_chain
->previous_state();
4055 p_right_chain
->previous_state();
4059 p_info
->set_needs_conversion(true);
4060 p_info
->add_type_conversion(p_type
, this);
4063 p_info
->set_is_erroneous(this, p_type
, string("No compatible "
4064 "union/CHOICE/anytype field found"));
4072 /** \todo consider subtype constraints */
4073 bool Type::is_identical(Type
*p_type
)
4077 Type
*t1
= get_type_refd_last();
4078 Type
*t2
= p_type
->get_type_refd_last();
4079 if (t2
->typetype
== T_ERROR
) return true;
4080 switch (t1
->typetype
) {
4082 // error type is identical to everything
4102 // user-defined structured types must be identical
4105 // the embedded type and the dimension must be identical in case of arrays
4106 return t2
->typetype
== T_ARRAY
&&
4107 t1
->u
.array
.element_type
->is_identical(t2
->u
.array
.element_type
) &&
4108 t1
->u
.array
.dimension
->is_identical(t2
->u
.array
.dimension
);
4110 // in case of built-in types the TTCN-3 view of typetype must be the same
4111 return get_typetype_ttcn3(t1
->typetype
) ==
4112 get_typetype_ttcn3(t2
->typetype
);
4116 void Type::tr_compsof(ReferenceChain
*refch
)
4118 if (typetype
!=T_SEQ_A
&& typetype
!=T_SET_A
)
4119 FATAL_ERROR("Type::tr_compsof()");
4120 if (u
.secho
.tr_compsof_ready
) return;
4121 if (u
.secho
.block
) parse_block_Se();
4122 bool auto_tagging
=u
.secho
.ctss
->needs_auto_tags();
4124 refch
->mark_state();
4125 if (refch
->add(get_fullname())) u
.secho
.ctss
->tr_compsof(refch
, false);
4126 refch
->prev_state();
4127 u
.secho
.tr_compsof_ready
= true;
4128 u
.secho
.ctss
->tr_compsof(0, true);
4130 ReferenceChain
refch2(this, "While resolving COMPONENTS OF");
4131 refch2
.add(get_fullname());
4132 Error_Context
cntxt(this, "While resolving COMPONENTS OF");
4133 u
.secho
.ctss
->tr_compsof(&refch2
, false);
4134 u
.secho
.tr_compsof_ready
= true;
4135 u
.secho
.ctss
->tr_compsof(0, true);
4137 if(auto_tagging
) u
.secho
.ctss
->add_auto_tags();
4140 bool Type::is_startable()
4142 if(typetype
!= T_FUNCTION
)
4143 FATAL_ERROR("Type::is_startable()");
4145 return u
.fatref
.is_startable
;
4148 bool Type::is_list_type(bool allow_array
)
4150 switch (get_type_refd_last()->get_typetype_ttcn3()) {
4166 void Type::chk_coding(bool encode
) {
4167 string
& coding_str
= encode
? encoding_str
: decoding_str
;
4168 if (!coding_str
.empty())
4170 coding_by_function
= false;
4172 if (!w_attrib_path
) {
4173 error("No coding rule specified for type '%s'", get_typename().c_str());
4176 Type::MessageEncodingType_t coding
= CT_UNDEF
;
4178 // Checking extension attributes
4179 Ttcn::ExtensionAttributes
* extatrs
= parse_extattributes(w_attrib_path
);
4180 if (extatrs
!= 0) { // NULL means parsing error
4181 for (size_t k
= 0; k
< extatrs
->size(); ++k
) {
4182 Ttcn::ExtensionAttribute
&ea
= extatrs
->get(k
);
4183 Ttcn::TypeMappings
*inmaps
= 0, *maps
= 0;
4184 Ttcn::TypeMapping
* mapping
= 0;
4185 Ttcn::TypeMappingTarget
* target
= 0;
4187 switch (ea
.get_type()) {
4188 case Ttcn::ExtensionAttribute::ENCDECVALUE
:
4189 ea
.get_encdecvalue_mappings(inmaps
, maps
);
4190 maps
= encode
? maps
: inmaps
;
4191 maps
->set_my_scope(this->get_my_scope());
4193 // look for coding settings
4194 t
= encode
? this : Type::get_pooltype(T_BSTR
);
4195 mapping
= maps
->get_mapping_byType(t
);
4196 if (mapping
->get_nof_targets() == 0)
4199 for (size_t ind
= 0; ind
< mapping
->get_nof_targets(); ind
++) {
4200 target
= mapping
->get_target_byIndex(ind
);
4201 t
= target
->get_target_type();
4202 if ((encode
&& (t
->get_typetype() == T_BSTR
)) ||
4203 (!encode
&& (t
->get_typename() == this->get_typename())))
4205 if (target
->get_mapping_type() ==
4206 Ttcn::TypeMappingTarget::TM_FUNCTION
) {
4207 if (!coding_str
.empty())
4208 target
->error("Multiple definition of this target");
4209 coding_str
= target
->get_function()->
4210 get_genname_from_scope(my_scope
);
4211 coding_by_function
= true;
4213 target
->error("Only function is supported to do this mapping");
4217 if (coding_str
.empty()) {
4218 ea
.warning("Extension attribute is found for %s but without "
4219 "typemappings", encode
? "encvalue" : "decvalue");
4224 case Ttcn::ExtensionAttribute::ANYTYPELIST
:
4225 break; // ignore (may be inherited from the module)
4227 case Ttcn::ExtensionAttribute::NONE
:
4228 break; // ignore erroneous attribute
4231 ea
.error("A type can only have type mapping extension attribute: "
4232 "in(...) or out(...)");
4239 if (!coding_str
.empty())
4243 const vector
<SingleWithAttrib
>& real_attribs
4244 = w_attrib_path
->get_real_attrib();
4246 for (size_t i
= real_attribs
.size(); i
> 0 && !found
; i
--) {
4247 if (real_attribs
[i
-1]->get_attribKeyword()
4248 == SingleWithAttrib::AT_ENCODE
) {
4250 coding
= get_enc_type(*real_attribs
[i
-1]);
4251 if (coding
== CT_UNDEF
) {
4252 // "encode" attribute found, but the spec didn't match any known encodings
4253 error("Unknown encoding '%s'", real_attribs
[i
-1]->get_attribSpec().get_spec().c_str());
4258 if (coding
== CT_UNDEF
) {
4259 // no "encode" attribute found
4260 error("No coding rule specified for type '%s'", get_typename().c_str());
4263 if (!has_encoding(coding
)) {
4264 error("Type '%s' cannot be coded with the selected method '%s'",
4265 get_typename().c_str(),
4266 get_encoding_name(coding
));
4274 coding_str
= "TEXT";
4280 coding_str
= "XER, XER_EXTENDED"; // TODO: fine tuning this parameter
4283 coding_str
= "JSON";
4286 coding_str
= "BER, ";
4287 BerAST
* ber
= berattrib
;
4288 if (!ber
) // use default settings if attributes are not specified
4291 coding_str
+= ber
->get_encode_str();
4293 coding_str
+= ber
->get_decode_str();
4298 error("Unknown coding selected for type '%s'", get_typename().c_str());
4301 coding_by_function
= false;
4304 bool Type::is_coding_by_function() const {
4305 return coding_by_function
;
4308 const string
& Type::get_coding(bool encode
) const {
4310 return encoding_str
;
4312 return decoding_str
;
4315 namespace { // unnamed
4316 const string
ex_emm_ell("XML"), ex_ee_arr("XER");
4319 Type::MessageEncodingType_t
Type::get_enc_type(const SingleWithAttrib
& atr
) {
4320 const string
& enc
= atr
.get_attribSpec().get_spec();
4323 else if (enc
== "TEXT")
4325 else if (enc
== "JSON")
4327 else if (enc
== "BER:2002" || enc
== "CER:2002" || enc
== "DER:2002")
4329 else if (enc
== ex_emm_ell
)
4331 else if (enc
== ex_ee_arr
) {
4332 atr
.warning("The correct name of the encoding is ''XML''");
4335 else if (enc
== "PER")
4340 bool Type::has_ei_withName(const Identifier
& p_id
) const
4348 FATAL_ERROR("Type::has_ei_withName()");
4350 return u
.enums
.eis
->has_ei_withName(p_id
);
4353 EnumItem
*Type::get_ei_byName(const Identifier
& p_id
) const
4361 FATAL_ERROR("Type::get_ei_byName()");
4363 return u
.enums
.eis
->get_ei_byName(p_id
);
4366 EnumItem
*Type::get_ei_byIndex(size_t n
) const
4374 FATAL_ERROR("Type::get_ei_byIndex()");
4376 return u
.enums
.eis
->get_ei_byIndex(n
);
4379 size_t Type::get_nof_comps()
4387 return u
.secho
.cfm
->get_nof_comps();
4390 if(u
.secho
.block
) parse_block_Se();
4391 return u
.secho
.ctss
->get_nof_comps();
4393 if(u
.secho
.block
) parse_block_Choice();
4394 return u
.secho
.ctss
->get_nof_comps();
4396 return u
.array
.dimension
->get_size();
4398 if (u
.signature
.parameters
)
4399 return u
.signature
.parameters
->get_nof_params();
4402 FATAL_ERROR("Type::get_nof_comps(%d)", typetype
);
4407 const Identifier
& Type::get_comp_id_byIndex(size_t n
)
4415 return u
.secho
.cfm
->get_comp_byIndex(n
)->get_name();
4418 if(u
.secho
.block
) parse_block_Se();
4419 return u
.secho
.ctss
->get_comp_byIndex(n
)->get_name();
4421 if(u
.secho
.block
) parse_block_Choice();
4422 return u
.secho
.ctss
->get_comp_byIndex(n
)->get_name();
4424 return u
.signature
.parameters
->get_param_byIndex(n
)->get_id();
4426 FATAL_ERROR("Type::get_comp_id_byIndex()");
4428 // to avoid warnings
4429 const Identifier
*fake
= 0;
4433 CompField
* Type::get_comp_byIndex(size_t n
)
4441 return u
.secho
.cfm
->get_comp_byIndex(n
);
4444 if(u
.secho
.block
) parse_block_Se();
4445 return u
.secho
.ctss
->get_comp_byIndex(n
);
4447 if(u
.secho
.block
) parse_block_Choice();
4448 return u
.secho
.ctss
->get_comp_byIndex(n
);
4450 FATAL_ERROR("Type::get_comp_byIndex()");
4455 size_t Type::get_comp_index_byName(const Identifier
& p_name
)
4457 Type
*t
= get_type_refd_last();
4459 FATAL_ERROR("Type::get_comp_index_byName()");
4460 if (!t
->u
.secho
.field_by_name
) {
4461 t
->u
.secho
.field_by_name
= new map
<string
, size_t>;
4462 size_t nof_comps
= t
->get_nof_comps();
4463 for (size_t i
= 0; i
< nof_comps
; i
++) {
4464 const string
& field_name
=
4465 t
->get_comp_byIndex(i
)->get_name().get_name();
4466 if (!t
->u
.secho
.field_by_name
->has_key(field_name
))
4467 t
->u
.secho
.field_by_name
->add(field_name
, new size_t(i
));
4470 return *(*t
->u
.secho
.field_by_name
)[p_name
.get_name()];
4473 size_t Type::get_eis_index_byName(const Identifier
& p_name
)
4475 Type
*t
= get_type_refd_last();
4476 switch (t
->typetype
) {
4481 FATAL_ERROR("Type::get_eis_index_byName()");
4483 if (!t
->u
.enums
.eis_by_name
) {
4484 t
->u
.enums
.eis_by_name
= new map
<string
, size_t>;
4485 size_t nof_eis
= t
->u
.enums
.eis
->get_nof_eis();
4486 for (size_t i
= 0; i
< nof_eis
; i
++) {
4487 const string
& enum_name
=
4488 t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name().get_name();
4489 if (!t
->u
.enums
.eis_by_name
->has_key(enum_name
))
4490 t
->u
.enums
.eis_by_name
->add(enum_name
, new size_t(i
));
4493 return *(*t
->u
.enums
.eis_by_name
)[p_name
.get_name()];
4496 const Int
& Type::get_enum_val_byId(const Identifier
& p_name
)
4498 if(!checked
) FATAL_ERROR("Type::get_enum_val_byId(): Not checked.");
4504 FATAL_ERROR("Type::get_enum_val_byId()");
4506 return u
.enums
.eis
->get_ei_byName(p_name
)->get_value()
4507 ->get_value_refd_last()->get_val_Int()->get_val();
4510 size_t Type::get_nof_root_comps()
4515 if(u
.secho
.block
) parse_block_Se();
4516 return u
.secho
.ctss
->get_nof_root_comps();
4519 FATAL_ERROR("Type::get_nof_root_comps()");
4524 CompField
* Type::get_root_comp_byIndex(size_t n
)
4529 if(u
.secho
.block
) parse_block_Se();
4530 return u
.secho
.ctss
->get_root_comp_byIndex(n
);
4533 FATAL_ERROR("Type::get_root_comp_byIndex()");
4538 bool Type::has_comp_withName(const Identifier
& p_name
)
4540 Type
*t
= get_type_refd_last();
4541 switch (t
->typetype
) {
4547 return t
->u
.secho
.cfm
->has_comp_withName(p_name
);
4550 if (t
->u
.secho
.block
) t
->parse_block_Se();
4551 return t
->u
.secho
.ctss
->has_comp_withName(p_name
);
4553 if (t
->u
.secho
.block
) t
->parse_block_Choice();
4554 return t
->u
.secho
.ctss
->has_comp_withName(p_name
);
4556 if (t
->u
.signature
.parameters
)
4557 return t
->u
.signature
.parameters
->has_param_withName(p_name
);
4560 FATAL_ERROR("Type::has_comp_withName()");
4565 CompField
* Type::get_comp_byName(const Identifier
& p_name
)
4567 Type
*t
= get_type_refd_last();
4568 switch (t
->typetype
) {
4574 return t
->u
.secho
.cfm
->get_comp_byName(p_name
);
4577 if (t
->u
.secho
.block
) t
->parse_block_Se();
4578 return t
->u
.secho
.ctss
->get_comp_byName(p_name
);
4580 if(t
->u
.secho
.block
) t
->parse_block_Choice();
4581 return t
->u
.secho
.ctss
->get_comp_byName(p_name
);
4583 FATAL_ERROR("Type::get_comp_byName()");
4588 void Type::add_comp(CompField
*p_cf
)
4596 u
.secho
.cfm
->add_comp(p_cf
);
4599 FATAL_ERROR("Type::add_comp()");
4603 Type
*Type::get_ofType()
4605 Type
*t
=get_type_refd_last();
4606 switch (t
->typetype
) {
4609 return t
->u
.seof
.ofType
;
4611 return t
->u
.array
.element_type
;
4613 FATAL_ERROR("Type::get_ofType()");
4618 OC_defn
* Type::get_my_oc()
4622 return u
.ref
.oc_defn
;
4625 return u
.secho
.oc_defn
;
4628 FATAL_ERROR("Type::get_my_oc()");
4633 const Identifier
& Type::get_oc_fieldname()
4637 return *u
.ref
.oc_fieldname
;
4640 return *u
.secho
.oc_fieldname
;
4643 FATAL_ERROR("Type::get_oc_fieldname()");
4644 // to avoid warning...
4645 return *u
.secho
.oc_fieldname
;
4649 void Type::set_my_tableconstraint(const TableConstraint
*p_tc
)
4653 u
.secho
.my_tableconstraint
=p_tc
;
4656 FATAL_ERROR("Type::set_my_tableconstraint()");
4660 const TableConstraint
* Type::get_my_tableconstraint()
4664 return u
.secho
.my_tableconstraint
;
4667 FATAL_ERROR("Type::get_my_tableconstraint()");
4672 Ttcn::ArrayDimension
*Type::get_dimension() const
4674 if (typetype
!= T_ARRAY
) FATAL_ERROR("Type::get_dimension()");
4675 return u
.array
.dimension
;
4678 Ttcn::PortTypeBody
*Type::get_PortBody() const
4680 if (typetype
!= T_PORT
) FATAL_ERROR("Type::get_PortBody()");
4684 ComponentTypeBody
*Type::get_CompBody() const
4686 if (typetype
!= T_COMPONENT
) FATAL_ERROR("Type::get_CompBody()");
4690 SignatureParamList
*Type::get_signature_parameters() const
4692 if (typetype
!= T_SIGNATURE
|| !checked
)
4693 FATAL_ERROR("Type::get_signature_parameters()");
4694 return u
.signature
.parameters
;
4697 SignatureExceptions
*Type::get_signature_exceptions() const
4699 if (typetype
!= T_SIGNATURE
|| !checked
)
4700 FATAL_ERROR("Type::get_signature_exceptions()");
4701 return u
.signature
.exceptions
;
4704 Type
*Type::get_signature_return_type() const
4706 if (typetype
!= T_SIGNATURE
|| !checked
)
4707 FATAL_ERROR("Type::get_signature_return_type()");
4708 return u
.signature
.return_type
;
4711 bool Type::is_nonblocking_signature() const
4713 if (typetype
!= T_SIGNATURE
|| !checked
)
4714 FATAL_ERROR("Type::is_nonblocking_signature()");
4715 return u
.signature
.no_block
;
4718 Ttcn::FormalParList
*Type::get_fat_parameters()
4720 if(!checked
) FATAL_ERROR("Type::get_fat_parameteres()");
4725 return u
.fatref
.fp_list
;
4727 FATAL_ERROR("Type::get_fat_parameteres()");
4732 Type
*Type::get_function_return_type()
4734 if(!checked
) FATAL_ERROR("Type::get_function_return_type()");
4737 return u
.fatref
.return_type
;
4739 FATAL_ERROR("Type::get_function_return_type()");
4744 Type
*Type::get_fat_runs_on_type()
4746 if(!checked
) FATAL_ERROR("Type::get_fat_runs_on_type()");
4751 return u
.fatref
.runs_on
.type
;
4753 FATAL_ERROR("Type::get_fat_runs_on_type()");
4758 bool Type::get_fat_runs_on_self()
4760 if(!checked
) FATAL_ERROR("Type::get_fat_runs_on_self()");
4765 return u
.fatref
.runs_on
.self
;
4767 FATAL_ERROR("Type::get_fat_runs_on_self()");
4772 bool Type::get_returns_template()
4774 if (!checked
|| typetype
!= T_FUNCTION
)
4775 FATAL_ERROR("Type::Returns_template()");
4776 return u
.fatref
.returns_template
;
4779 void Type::add_tag(Tag
*p_tag
)
4781 if(!tags
) tags
=new Tags();
4782 tags
->add_tag(p_tag
);
4785 void Type::add_constraints(Constraints
*p_constraints
)
4787 if(!p_constraints
) return;
4789 FATAL_ERROR("This type already has its constraints");
4790 constraints
=p_constraints
;
4791 constraints
->set_my_type(this);
4794 Reference
* Type::get_Reference()
4799 void Type::chk_table_constraints()
4801 if(!tbl_cons_checked
) {
4802 tbl_cons_checked
=true;
4803 if (constraints
) constraints
->chk_table();
4812 for(size_t i
=0; i
<get_nof_comps(); i
++)
4813 get_comp_byIndex(i
)->get_type()->chk_table_constraints();
4817 u
.seof
.ofType
->chk_table_constraints();
4825 void Type::check_subtype_constraints()
4827 if (sub_type
!=NULL
) FATAL_ERROR("Type::check_subtype_constraints()");
4829 // get parent subtype or NULL if it doesn't exist
4830 SubType
* parent_subtype
= NULL
;
4831 if (is_ref()) parent_subtype
= get_type_refd()->sub_type
;
4833 // if the parent subtype is erroneous then ignore it, the error was already
4835 if ( (parent_subtype
!=NULL
) &&
4836 (parent_subtype
->get_subtypetype()==SubtypeConstraint::ST_ERROR
) )
4837 parent_subtype
= NULL
;
4839 // return if there are neither inherited nor own constraints
4840 if ( (parent_subtype
==NULL
) && (parsed_restr
==NULL
) && (constraints
==NULL
)
4841 && (SubtypeConstraint::get_asn_type_constraint(this)==NULL
) ) return;
4843 // the subtype type is determined by the type of this type
4844 if (get_type_refd_last()->get_typetype()==T_ERROR
) return;
4845 SubtypeConstraint::subtype_t s_t
= get_subtype_type();
4846 if (s_t
==SubtypeConstraint::ST_ERROR
) {
4847 error("Subtype constraints are not applicable to type `%s'",
4848 get_typename().c_str());
4852 // create the aggregate subtype for this type
4853 sub_type
= new SubType(s_t
, this, parent_subtype
, parsed_restr
, constraints
);
4857 bool Type::has_multiple_tags()
4859 if (tags
) return false;
4868 return get_type_refd()->has_multiple_tags();
4874 Tag
*Type::get_tag()
4877 Tag
*tag
=tags
->get_tag_byIndex(tags
->get_nof_tags()-1);
4881 else return get_default_tag();
4884 void Type::get_tags(TagCollection
& coll
, map
<Type
*, void>& chain
)
4886 if(typetype
!=T_CHOICE_A
)
4887 FATAL_ERROR("Type::get_tags()");
4888 if (chain
.has_key(this)) return;
4890 if(u
.secho
.block
) parse_block_Choice();
4891 size_t n_alts
= u
.secho
.ctss
->get_nof_comps();
4892 for(size_t i
=0; i
<n_alts
; i
++) {
4893 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4894 Type
*type
= cf
->get_type();
4895 if(type
->has_multiple_tags()) {
4896 type
=type
->get_type_refd_last();
4897 type
->get_tags(coll
, chain
);
4900 const Tag
*tag
=type
->get_tag();
4901 if(coll
.hasTag(tag
))
4902 error("Alternative `%s' in CHOICE has non-distinct tag",
4903 cf
->get_name().get_dispname().c_str());
4904 else coll
.addTag(tag
);
4907 if(u
.secho
.ctss
->has_ellipsis()) coll
.setExtensible();
4910 Tag
*Type::get_smallest_tag()
4912 if(!has_multiple_tags()) return get_tag()->clone();
4913 Type
*t
=get_type_refd_last();
4914 TagCollection tagcoll
;
4915 map
<Type
*, void> chain
;
4916 t
->get_tags(tagcoll
, chain
);
4918 return tagcoll
.getSmallestTag()->clone();
4921 bool Type::needs_explicit_tag()
4930 if(!dynamic_cast<Asn::Ref_pard
*>(u
.ref
.ref
)) {
4931 Scope
*s
=u
.ref
.ref
->get_refd_assignment()->get_my_scope();
4932 if(s
->get_parent_scope()!=s
->get_scope_mod()) {
4933 // Not in the module scope, so it is a dummyreference (X.680
4936 WARNING("%s is a dummyreference, i give him an explicit tag :)",
4937 get_fullname().c_str());
4938 WARNING("0: %s", s->get_scope_name().c_str());
4939 WARNING("1: %s", s->get_parent_scope()->get_scope_name().c_str());
4940 WARNING("2: %s", s->get_scope_mod()->get_scope_name().c_str());
4950 Type
*t
= get_type_refd();
4951 if(t
->is_tagged()) return false;
4952 else return t
->needs_explicit_tag();
4955 // T_ANYTYPE probably does not need explicit tagging
4960 void Type::cut_auto_tags()
4963 tags
->cut_auto_tags();
4964 if (tags
->get_nof_tags() == 0) {
4972 * I suppose in this function that tags->chk() and
4973 * tags->set_plicit() are already done.
4975 Tags
* Type::build_tags_joined(Tags
*p_tags
)
4977 if(!p_tags
) p_tags
=new Tags();
4984 get_type_refd()->build_tags_joined(p_tags
);
4988 //TODO case T_ANYTYPE: for build_tags_joined ?
4993 p_tags
->add_tag(get_default_tag()->clone());
4997 for(size_t i
=0; i
<tags
->get_nof_tags(); i
++) {
4998 Tag
*tag
=tags
->get_tag_byIndex(i
);
4999 switch(tag
->get_plicit()) {
5000 case Tag::TAG_EXPLICIT
:
5001 p_tags
->add_tag(tag
->clone());
5003 case Tag::TAG_IMPLICIT
: {
5004 Tag
*t_p_tag
=p_tags
->get_tag_byIndex(p_tags
->get_nof_tags()-1);
5005 t_p_tag
->set_tagclass(tag
->get_tagclass());
5006 t_p_tag
->set_tagvalue(tag
->get_tagvalue());
5009 FATAL_ERROR("Type::build_tags_joined()");
5016 void Type::set_with_attr(Ttcn::MultiWithAttrib
* p_attrib
)
5020 w_attrib_path
= new WithAttribPath();
5023 w_attrib_path
->set_with_attr(p_attrib
);
5026 void Type::set_parent_path(WithAttribPath
* p_path
)
5030 w_attrib_path
= new WithAttribPath();
5032 w_attrib_path
->set_parent(p_path
);
5033 if (typetype
== T_COMPONENT
)
5034 u
.component
->set_parent_path(w_attrib_path
);
5037 WithAttribPath
* Type::get_attrib_path() const
5039 return w_attrib_path
;
5042 bool Type::hasRawAttrs()
5044 if(rawattrib
) return true;
5048 if(w_attrib_path
->get_had_global_variants()) return true;
5050 vector
<SingleWithAttrib
> const &real_attribs
5051 = w_attrib_path
->get_real_attrib();
5053 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
5054 if (real_attribs
[i
]->get_attribKeyword()
5055 == SingleWithAttrib::AT_VARIANT
)
5060 MultiWithAttrib
* temp_attrib
= w_attrib_path
->get_with_attr();
5062 for(size_t i
= 0; i
< temp_attrib
->get_nof_elements(); i
++)
5063 if(temp_attrib
->get_element(i
)->get_attribKeyword()
5064 == SingleWithAttrib::AT_VARIANT
5065 && (!temp_attrib
->get_element(i
)->get_attribQualifiers()
5066 || temp_attrib
->get_element(i
)->get_attribQualifiers()
5067 ->get_nof_qualifiers() == 0))
5069 w_attrib_path
->set_had_global_variants( true );
5077 bool Type::hasNeedofRawAttrs()
5079 if(rawattrib
) return true;
5086 nof_comps
= get_nof_comps();
5087 for(size_t i
=0; i
< nof_comps
; i
++)
5089 if(get_comp_byIndex(i
)->get_type()->hasNeedofRawAttrs())
5101 bool Type::hasNeedofTextAttrs()
5103 if(textattrib
) return true;
5110 nof_comps
= get_nof_comps();
5111 for(size_t i
=0; i
< nof_comps
; i
++)
5113 if(get_comp_byIndex(i
)->get_type()->hasNeedofTextAttrs())
5125 bool Type::hasNeedofJsonAttrs()
5127 if(jsonattrib
) return true;
5134 nof_comps
= get_nof_comps();
5135 for (size_t i
= 0; i
< nof_comps
; ++i
)
5137 if (get_comp_byIndex(i
)->get_type()->hasNeedofJsonAttrs())
5149 bool Type::hasNeedofXerAttrs()
5151 if(xerattrib
&& !xerattrib
->empty()) return true;
5158 nof_comps
= get_nof_comps();
5159 for(size_t i
=0; i
< nof_comps
; i
++)
5161 if(get_comp_byIndex(i
)->get_type()->hasNeedofXerAttrs())
5173 bool Type::hasVariantAttrs()
5177 if(w_attrib_path
->get_had_global_variants()) return true;
5179 vector
<SingleWithAttrib
> const &real_attribs
5180 = w_attrib_path
->get_real_attrib();
5182 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
5183 if (real_attribs
[i
]->get_attribKeyword()
5184 == SingleWithAttrib::AT_VARIANT
)
5189 MultiWithAttrib
* temp_attrib
= w_attrib_path
->get_with_attr();
5191 for(size_t i
= 0; i
< temp_attrib
->get_nof_elements(); i
++)
5192 if(temp_attrib
->get_element(i
)->get_attribKeyword()
5193 == SingleWithAttrib::AT_VARIANT
5194 && (!temp_attrib
->get_element(i
)->get_attribQualifiers()
5195 || temp_attrib
->get_element(i
)->get_attribQualifiers()
5196 ->get_nof_qualifiers() != 0))
5198 w_attrib_path
->set_had_global_variants( true );
5206 bool Type::hasEncodeAttr(const MessageEncodingType_t encoding_type
)
5208 if (CT_JSON
== encoding_type
&& (implicit_json_encoding
5209 || is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) {
5210 // ASN.1 types automatically support JSON encoding
5213 // Check the type itself first, then the root type
5214 WithAttribPath
*aps
[2] = { 0, 0 };
5215 size_t num_aps
= ((aps
[0] = get_attrib_path()) != 0);
5216 // assign, compare, then add 0 or 1
5218 num_aps
+= ((aps
[num_aps
] = get_type_refd()->get_attrib_path()) != 0);
5220 for (size_t a
= 0; a
< num_aps
; ++a
) {
5221 const vector
<SingleWithAttrib
>& real
= aps
[a
]->get_real_attrib();
5222 const size_t num_atr
= real
.size();
5223 for (size_t i
= 0; i
< num_atr
; ++i
) {
5224 const SingleWithAttrib
& s
= *real
[i
];
5225 if (s
.get_attribKeyword() == SingleWithAttrib::AT_ENCODE
) {
5226 const string
& spec
= s
.get_attribSpec().get_spec();
5227 if (spec
== get_encoding_name(encoding_type
)) {
5230 // if it has an encode other than the one we're looking for, quit now
5239 namespace { // unnamed
5241 enum state
{ PROCESSING
= -1, ANSWER_NO
, ANSWER_YES
};
5243 struct memoizer
: private map
<Type
*, state
> {
5244 memoizer() : map
<Type
*, state
>() {}
5247 for (int i
= size()-1; i
>= 0; --i
) {
5248 delete get_nth_elem(i
);
5253 bool remember (Type
*t
, state s
) {
5258 add(t
, new state(s
));
5260 return s
== ANSWER_YES
;
5263 bool has_key(Type
*t
) {
5264 return map
<Type
*, state
>::has_key(t
);
5267 state
* get(Type
*t
) {
5268 return operator [](t
);
5274 bool Type::has_encoding(MessageEncodingType_t encoding_type
)
5276 static memoizer memory
;
5277 static memoizer json_mem
;
5279 switch (encoding_type
) {
5283 if (t
->is_asn1()) return true;
5284 else if (t
->is_ref()) t
= t
->get_type_refd();
5286 switch (t
->typetype
) {
5294 // these basic TTCN-3 types have ASN.1 equivalents
5303 if (memory
.has_key(this)) {
5304 state
*s
= memory
.get(this);
5316 // For ASN.1 types, the answer depends solely on the -a switch.
5317 // They are all considered to have Basic (i.e. useless) XER,
5318 // unless the -a switch says removes XER from all ASN.1 types.
5319 if (t
->is_asn1()) return memory
.remember(t
,
5320 asn1_xer
? ANSWER_YES
: ANSWER_NO
);
5321 else if (t
->is_ref()) t
= t
->get_type_refd();
5322 else { // at the end of the ref. chain
5323 switch (t
->typetype
) {
5329 // The octetstring type can always be encoded in XER.
5330 // XSD:base64Binary is only needed for Type::is_charenc()
5332 case T_HSTR
: // TTCN-3 hexstring
5333 case T_VERDICT
: // TTCN-3 verdict
5334 case T_CSTR
: // TTCN3 charstring
5335 case T_USTR
: // TTCN3 universal charstring
5336 return memory
.remember(t
, ANSWER_YES
);
5339 break; // the switch; skip to checking if it has encode "XML";
5341 case T_PORT
: // TTCN-3 port (the list of in's, out's, inout's)
5342 case T_COMPONENT
: // TTCN-3 comp. type (extends, and { ... })
5343 case T_DEFAULT
: // TTCN-3
5344 case T_SIGNATURE
: // TTCN-3
5345 case T_FUNCTION
: // TTCN-3
5346 case T_ALTSTEP
: // TTCN-3
5347 case T_TESTCASE
: // TTCN-3
5348 case T_ANYTYPE
: // TTCN-3 anytype
5349 return memory
.remember(t
, ANSWER_NO
);
5354 return false; // why don't we remember these ?
5359 // No field may reject XER
5360 size_t ncomp
= t
->get_nof_comps();
5361 for (size_t i
= 0; i
< ncomp
; ++i
) {
5362 Type
*t2
= t
->get_comp_byIndex(i
)->get_type();
5363 bool subresult
= false;
5364 if (memory
.has_key(t2
)) {
5365 switch (*memory
.get(t2
)) {
5367 // This type contains itself and is in the process
5368 // of being checked. Pretend it doesn't exist.
5369 // The answer will be determined by the other fields,
5370 // and it will propagate back up.
5371 // Avoids infinite recursion for self-referencing types.
5382 memory
.remember(t2
, PROCESSING
);
5383 subresult
= t2
->has_encoding(CT_XER
);
5386 if (subresult
) memory
.remember(t2
, ANSWER_YES
);
5387 else return memory
.remember(t2
, ANSWER_NO
);
5388 // Note: return only if the answer (false) is known.
5389 // If the answer is true, keep checking.
5391 // Empty record, or all fields supported XER: answer maybe yes.
5396 bool subresult
= false;
5397 Type
*t2
= t
->u
.seof
.ofType
;
5398 if (memory
.has_key(t2
)) {
5399 switch (*memory
.get(t2
)) {
5401 // Recursive record-of. This is OK because the recursion
5402 // can always be broken with an empty record-of.
5414 memory
.remember(t2
, PROCESSING
);
5415 // Check the contained type
5416 subresult
= t2
->has_encoding(CT_XER
);
5418 if (subresult
) break; // continue checking
5419 else return memory
.remember(t
, ANSWER_NO
); // No means no.
5422 case T_NULL
: // ASN.1 null
5423 case T_INT_A
: // ASN.1 integer
5424 case T_ENUM_A
:// ASN.1 enum
5425 case T_BSTR_A
:// ASN.1 bitstring
5426 case T_UTF8STRING
: // ASN.1
5427 case T_NUMERICSTRING
:
5428 case T_PRINTABLESTRING
:
5429 case T_TELETEXSTRING
:
5430 case T_VIDEOTEXSTRING
:
5432 case T_GRAPHICSTRING
:
5433 case T_VISIBLESTRING
:
5434 case T_GENERALSTRING
:
5435 case T_UNIVERSALSTRING
:
5437 case T_UNRESTRICTEDSTRING
: // still ASN.1
5438 case T_UTCTIME
: // ASN.1 string
5439 case T_GENERALIZEDTIME
: // ASN.1 string
5440 case T_OBJECTDESCRIPTOR
: // ASN.1 string
5441 case T_ROID
: // relative OID (ASN.1)
5444 case T_SEQ_A
: // ASN.1 versions of choice,sequence,set
5447 case T_OCFT
: // ObjectClassFieldType (ASN.1)
5448 case T_OPENTYPE
: // ASN.1 open type
5449 case T_ANY
: // deprecated ASN.1 ANY
5451 case T_EXTERNAL
: // ASN.1 external
5452 case T_EMBEDDED_PDV
: // ASN.1 embedded pdv
5453 case T_SELTYPE
: // selection type (ASN.1)
5454 FATAL_ERROR("Type::has_encoding(): typetype %d should be asn1",
5456 break; // not reached
5458 case T_REFD
: // reference to another type
5459 case T_ADDRESS
: // TTCN-3 address type
5460 case T_ARRAY
: // TTCN-3 array
5461 default: // FIXME: if compiling with -Wswitch, the default should be removed
5462 return memory
.remember(t
, ANSWER_NO
);
5463 } // switch t->typetype
5465 // Check to see if it has an encode "XML"; first the type itself,
5466 // then the root type.
5467 WithAttribPath
*aps
[2] = {0,0};
5468 size_t num_aps
= ((aps
[0] = this->get_attrib_path()) != 0);
5469 // assign, compare, then add 0 or 1
5471 num_aps
+= ((aps
[num_aps
] = t
->get_attrib_path()) != 0);
5473 for (size_t a
= 0; a
< num_aps
; ++a
) {
5474 const vector
<SingleWithAttrib
>& real
= aps
[a
]->get_real_attrib();
5475 const size_t num_atr
= real
.size();
5476 for (size_t i
= 0; i
< num_atr
; ++i
) {
5477 const SingleWithAttrib
& s
= *real
[i
];
5478 if (s
.get_attribKeyword() == SingleWithAttrib::AT_ENCODE
) {
5479 const string
& spec
= s
.get_attribSpec().get_spec();
5480 if (spec
== ex_emm_ell
// the right answer
5481 ||spec
== ex_ee_arr
) // the acceptable answer
5482 return memory
.remember(t
, ANSWER_YES
);
5483 else // if it has an encode other than XER, quit now
5484 return memory
.remember(t
, ANSWER_NO
);
5488 return memory
.remember(t
, ANSWER_NO
); // no encode XER
5491 return memory
.remember(t
, ANSWER_NO
); }
5495 if (t
->rawattrib
) return true;
5496 else if (t
->is_ref()) t
= t
->get_type_refd();
5498 switch (t
->typetype
) {
5507 // these basic types support RAW encoding by default
5517 if (t
->textattrib
) return true;
5518 else if (t
->is_ref()) t
= t
->get_type_refd();
5520 switch (t
->typetype
) {
5526 // these basic types support TEXT encoding by default
5536 if (json_mem
.has_key(t
)) {
5537 switch (*json_mem
.get(t
)) {
5546 if (t
->jsonattrib
) {
5547 return json_mem
.remember(t
, ANSWER_YES
);
5550 t
= t
->get_type_refd();
5553 switch (t
->typetype
) {
5566 case T_NUMERICSTRING
:
5567 case T_PRINTABLESTRING
:
5568 case T_TELETEXSTRING
:
5569 case T_VIDEOTEXSTRING
:
5571 case T_GRAPHICSTRING
:
5572 case T_VISIBLESTRING
:
5573 case T_GENERALSTRING
:
5574 case T_UNIVERSALSTRING
:
5581 // these basic types support JSON encoding by default
5582 return json_mem
.remember(t
, ANSWER_YES
);
5591 // all fields must also support JSON encoding
5592 size_t ncomp
= t
->get_nof_comps();
5593 for (size_t i
= 0; i
< ncomp
; ++i
) {
5594 Type
*t2
= t
->get_comp_byIndex(i
)->get_type();
5595 if (json_mem
.has_key(t2
)) {
5596 switch (*json_mem
.get(t2
)) {
5598 // This field is OK, but we still need to check the others
5600 // This type contains itself and is in the process
5601 // of being checked. Pretend it doesn't exist.
5602 // The answer will be determined by the other fields,
5603 // and it will propagate back up.
5604 // Avoids infinite recursion for self-referencing types.
5607 // One field is not OK => the structure is not OK
5608 return json_mem
.remember(t
, ANSWER_NO
);
5612 json_mem
.remember(t2
, PROCESSING
);
5613 bool enabled
= t2
->has_encoding(CT_JSON
);
5614 json_mem
.remember(t2
, enabled
? ANSWER_YES
: ANSWER_NO
);
5616 // One field is not OK => the structure is not OK
5617 return json_mem
.remember(t
, ANSWER_NO
);
5621 break; // check for an encode attribute
5626 Type
*t2
= t
->u
.seof
.ofType
;
5627 if (json_mem
.has_key(t2
)) {
5628 switch (*json_mem
.get(t2
)) {
5630 // Continue checking
5632 // Recursive record-of. This is OK because the recursion
5633 // can always be broken with an empty record-of.
5636 return json_mem
.remember(t
, ANSWER_NO
);
5641 json_mem
.remember(t2
, PROCESSING
);
5642 bool enabled
= t2
->has_encoding(CT_JSON
);
5643 json_mem
.remember(t2
, enabled
? ANSWER_YES
: ANSWER_NO
);
5645 // One field is not OK => the structure is not OK
5646 return json_mem
.remember(t
, ANSWER_NO
);
5649 break; // check for an encode attribute
5653 break; // check for an encode attribute
5655 return json_mem
.remember(t
, ANSWER_NO
);
5657 return json_mem
.remember(t
, hasEncodeAttr(CT_JSON
) ? ANSWER_YES
: ANSWER_NO
);
5662 FATAL_ERROR("Type::has_encoding()");
5668 bool Type::is_pure_refd()
5672 // ASN.1 parameterized references are not pure :)
5673 if(dynamic_cast<Asn::Ref_pard
*>(u
.ref
.ref
)) return false;
5678 if (sub_type
|| constraints
) return false;
5679 else if (tags
&& enable_ber()) return false;
5680 else if (rawattrib
&& enable_raw()) return false;
5681 else if (textattrib
&& enable_text()) return false;
5682 else if (enable_xer()) return false;
5683 else if (jsonattrib
&& enable_json()) return false;
5690 string
Type::create_stringRepr()
5692 if(is_tagged() || hasRawAttrs())
5693 return get_genname_own();
5696 return string("NULL");
5698 return string("BOOLEAN");
5701 return string("INTEGER");
5703 return string("REAL");
5706 return string("BIT__STRING");
5708 return string("HEX__STRING");
5710 return string("OCTET__STRING");
5712 return string("CHAR__STRING");
5714 return string("UNIVERSAL__CHARSTRING");
5716 return string("UTF8String");
5717 case T_NUMERICSTRING
:
5718 return string("NumericString");
5719 case T_PRINTABLESTRING
:
5720 return string("PrintableString");
5721 case T_TELETEXSTRING
:
5722 return string("TeletexString");
5723 case T_VIDEOTEXSTRING
:
5724 return string("VideotexString");
5726 return string("IA5String");
5727 case T_GRAPHICSTRING
:
5728 return string("GraphicString");
5729 case T_VISIBLESTRING
:
5730 return string("VisibleString");
5731 case T_GENERALSTRING
:
5732 return string("GeneralString");
5733 case T_UNIVERSALSTRING
:
5734 return string("UniversalString");
5736 return string("BMPString");
5737 case T_UNRESTRICTEDSTRING
:
5738 return string("CHARACTER__STRING");
5740 return string("UTCTime");
5741 case T_GENERALIZEDTIME
:
5742 return string("GeneralizedTime");
5743 case T_OBJECTDESCRIPTOR
:
5744 return string("ObjectDescriptor");
5746 return string("OBJECT__IDENTIFIER");
5748 return string("RELATIVE__OID");
5750 return string("ANY");
5755 if (tags
|| constraints
||
5756 (w_attrib_path
&& w_attrib_path
->has_attribs()))
5757 return get_genname_own();
5758 else return get_type_refd()->get_stringRepr();
5760 return string("<Error_type>");
5762 return get_genname_own();
5766 Identifier
Type::get_otaltname(bool& is_strange
)
5769 if (is_tagged() || is_constrained() || hasRawAttrs()) {
5770 s
= get_genname_own();
5772 } else if (typetype
== T_REFD
) {
5773 Ref_simple
* t_ref
=dynamic_cast<Ref_simple
*>(u
.ref
.ref
);
5775 const Identifier
*id
= t_ref
->get_id();
5776 const string
& dispname
= id
->get_dispname();
5777 if (dispname
.find('.') < dispname
.size()) {
5778 // id is not regular because t_ref is a parameterized reference
5779 // use that id anyway
5780 s
+= id
->get_name();
5783 Scope
*ass_scope
= t_ref
->get_refd_assignment()->get_my_scope();
5784 if (ass_scope
->get_parent_scope() == ass_scope
->get_scope_mod()) {
5785 // t_ref points to an assignment at module scope
5786 // use the simple id of the reference (in lowercase)
5790 // t_ref is a dummy reference in a parameterized assignment
5791 // (i.e. it points to a parameter assignment of an instantiation)
5792 // perform the same examination recursively on the referenced type
5793 // (which is the actual parameter)
5794 return get_type_refd()->get_otaltname(is_strange
);
5798 // the type comes from an information object [class]
5799 // examine the referenced type recursively
5800 return get_type_refd()->get_otaltname(is_strange
);
5803 s
= get_stringRepr();
5804 // throw away the leading @ if this is an instantiated type
5805 // (e.g. an in-line SEQUENCE from a parameterized reference)
5806 if (!strncmp(s
.c_str(), "_root_", 6)) s
.replace(0, 6, "");
5807 // the name is strange if it contains a single underscore
5809 // transform "__" -> "-"
5810 for (size_t pos
= 0; ; ) {
5811 pos
= s2
.find("__", pos
);
5812 if (pos
< s2
.size()) {
5813 s2
.replace(pos
, 2, "-");
5817 is_strange
= s2
.find('_') < s2
.size();
5820 size_t pos=s.find_if(0, s.size(), isupper);
5821 if(pos==s.size()) FATAL_ERROR("Type::get_otaltname() (`%s')", s.c_str());
5822 s[pos]=tolower(s[pos]);
5825 Identifier
tmp_id(Identifier::ID_NAME
, s
, true);
5826 /* This is because the origin of the returned ID must be ASN. */
5827 return Identifier(Identifier::ID_ASN
, tmp_id
.get_asnname());
5830 string
Type::get_genname_value(Scope
*p_scope
)
5832 Type
*t
= get_type_refd_last();
5833 switch (t
->typetype
) {
5836 case T_UNRESTRICTEDSTRING
:
5839 case T_EMBEDDED_PDV
:
5843 FATAL_ERROR("Type::get_genname_value()");
5845 return string("ASN_NULL");
5847 return string("BOOLEAN");
5850 return string("INTEGER");
5852 return string("FLOAT");
5855 return string("BITSTRING");
5857 return string("HEXSTRING");
5859 return string("OCTETSTRING");
5861 case T_NUMERICSTRING
:
5862 case T_PRINTABLESTRING
:
5864 case T_VISIBLESTRING
:
5866 case T_GENERALIZEDTIME
:
5867 return string("CHARSTRING");
5868 case T_USTR
: // ttcn3 universal charstring
5870 case T_TELETEXSTRING
:
5871 case T_VIDEOTEXSTRING
:
5872 case T_GRAPHICSTRING
:
5873 case T_GENERALSTRING
:
5874 case T_UNIVERSALSTRING
:
5876 case T_OBJECTDESCRIPTOR
:
5877 return string("UNIVERSAL_CHARSTRING");
5880 return string("OBJID");
5882 return string("ASN_ANY");
5884 return string("VERDICTTYPE");
5886 return string("COMPONENT");
5888 return string("DEFAULT");
5890 if (!t
->u
.array
.in_typedef
)
5891 return t
->u
.array
.dimension
->get_value_type(t
->u
.array
.element_type
,
5895 return t
->get_genname_own(p_scope
);
5899 string
Type::get_genname_template(Scope
*p_scope
)
5901 Type
*t
= get_type_refd_last();
5903 switch (t
->typetype
) {
5906 // template classes do not exist for these types
5907 FATAL_ERROR("Type::get_genname_template()");
5909 // a template class has to be instantiated in case of arrays
5910 // outside type definitions
5911 if (!t
->u
.array
.in_typedef
) {
5912 ret_val
= t
->u
.array
.dimension
->get_template_type(
5913 t
->u
.array
.element_type
, p_scope
);
5918 // in case of other types the name of the template class is derived
5919 // from the value class by appending a suffix
5920 ret_val
= t
->get_genname_value(p_scope
);
5921 ret_val
+= "_template";
5927 string
Type::get_genname_altname()
5929 Type
*t_last
= get_type_refd_last();
5930 Scope
*t_scope
= t_last
->get_my_scope();
5931 switch (t_last
->typetype
) {
5934 case T_UNRESTRICTEDSTRING
:
5937 case T_EMBEDDED_PDV
:
5941 FATAL_ERROR("Type::get_genname_altname()");
5953 case T_ANYTYPE
: // FIXME this does not yet work
5961 // user-defined types
5962 // always use the qualified name (including module identifier)
5963 string
ret_val(t_scope
->get_scope_mod_gen()->get_modid().get_name());
5965 ret_val
+= t_last
->get_genname_own();
5969 // use the simple class name from the base library
5970 return t_last
->get_genname_value(t_scope
);
5974 string
Type::get_typename()
5976 Type
*t
= get_type_refd_last();
5977 const char* tn
= get_typename_builtin(t
->typetype
);
5978 if (tn
!= 0) return string(tn
);
5979 switch (t
->typetype
) {
5997 return t
->get_fullname();
5999 string
dimensions(t
->u
.array
.dimension
->get_stringRepr());
6000 t
= t
->u
.array
.element_type
;
6001 while (t
->typetype
== T_ARRAY
) {
6002 dimensions
+= t
->u
.array
.dimension
->get_stringRepr();
6003 t
= t
->u
.array
.element_type
;
6005 return t
->get_typename() + dimensions
; }
6007 FATAL_ERROR("Type::get_typename()");
6013 const char* Type::get_typename_builtin(typetype_t tt
)
6017 return "Erroneous type";
6033 return "octetstring";
6035 return "charstring";
6037 return "universal charstring";
6039 return "UTF8String";
6040 case T_NUMERICSTRING
:
6041 return "NumericString";
6042 case T_PRINTABLESTRING
:
6043 return "PrintableString";
6044 case T_TELETEXSTRING
:
6045 return "TeletexString";
6046 case T_VIDEOTEXSTRING
:
6047 return "VideotexString";
6050 case T_GRAPHICSTRING
:
6051 return "GraphicString";
6052 case T_VISIBLESTRING
:
6053 return "VisibleString";
6054 case T_GENERALSTRING
:
6055 return "GeneralString";
6056 case T_UNIVERSALSTRING
:
6057 return "UniversalString";
6062 case T_GENERALIZEDTIME
:
6063 return "GeneralizedTime";
6064 case T_OBJECTDESCRIPTOR
:
6065 return "ObjectDescriptor";
6072 return "verdicttype";
6077 case T_EMBEDDED_PDV
:
6078 return "EMBEDDED PDV";
6079 case T_UNRESTRICTEDSTRING
:
6080 return "CHARACTER STRING";
6090 string
Type::get_genname_typedescriptor(Scope
*p_scope
)
6094 /* If it has tags or encoding attributes, then its encoding may be
6095 * different from the other "equivalent" types and needs to have its own
6098 if (t
->is_tagged() || t
->rawattrib
|| t
->textattrib
|| t
->jsonattrib
||
6099 (t
->xerattrib
&& !t
->xerattrib
->empty() ))
6101 return t
->get_genname_own(p_scope
);
6103 else if (t
->is_ref()) {
6104 if (t
->has_encoding(CT_XER
)) {
6105 // just fetch the referenced type and return
6106 return t
->get_type_refd()->get_genname_own(p_scope
);
6109 { // follow the white rabbit
6110 t
= t
->get_type_refd();
6115 return t
->get_genname_typename(p_scope
);
6118 string
Type::get_genname_typename(Scope
*p_scope
)
6120 Type
*t
= get_type_refd_last();
6121 switch (t
->typetype
) {
6123 return string("UTF8String");
6124 case T_NUMERICSTRING
:
6125 return string("NumericString");
6126 case T_PRINTABLESTRING
:
6127 return string("PrintableString");
6128 case T_TELETEXSTRING
:
6129 return string("TeletexString");
6130 case T_VIDEOTEXSTRING
:
6131 return string("VideotexString");
6133 return string("IA5String");
6134 case T_GRAPHICSTRING
:
6135 return string("GraphicString");
6136 case T_VISIBLESTRING
:
6137 return string("VisibleString");
6138 case T_GENERALSTRING
:
6139 return string("GeneralString");
6140 case T_UNIVERSALSTRING
:
6141 return string("UniversalString");
6143 return string("BMPString");
6145 return string("ASN_UTCTime");
6146 case T_GENERALIZEDTIME
:
6147 return string("ASN_GeneralizedTime");
6148 case T_OBJECTDESCRIPTOR
:
6149 return string("ObjectDescriptor");
6151 return string("ASN_ROID");
6153 return t
->get_genname_value(p_scope
);
6157 string
Type::get_genname_berdescriptor()
6161 if (t
->is_tagged()) return t
->get_genname_own(my_scope
);
6162 else if (t
->is_ref()) t
= t
->get_type_refd();
6165 switch (t
->typetype
) {
6168 return string("ENUMERATED");
6172 return string("CHOICE");
6176 return string("SEQUENCE");
6180 return string("SET");
6182 return t
->get_genname_typename(my_scope
);
6186 string
Type::get_genname_rawdescriptor()
6190 if (t
->rawattrib
) return t
->get_genname_own(my_scope
);
6191 else if (t
->is_ref()) t
= t
->get_type_refd();
6194 return t
->get_genname_typename(my_scope
);
6197 string
Type::get_genname_textdescriptor()
6201 if (t
->textattrib
) return t
->get_genname_own(my_scope
);
6202 else if (t
->is_ref()) t
= t
->get_type_refd();
6205 return t
->get_genname_typename(my_scope
);
6208 string
Type::get_genname_xerdescriptor()
6210 if (T_REFDSPEC
== typetype
) {
6211 return get_genname_typedescriptor(my_scope
);
6213 else return genname
;
6216 string
Type::get_genname_jsondescriptor()
6220 if (t
->jsonattrib
) return t
->get_genname_own(my_scope
);
6221 else if (t
->is_ref()) t
= t
->get_type_refd();
6224 return t
->get_genname_typename(my_scope
);
6227 const char* Type::get_genname_typedescr_asnbasetype()
6229 switch (get_type_refd_last()->typetype
) {
6232 case T_UNIVERSALSTRING
:
6233 return "UNIVERSALSTRING";
6235 return "UTF8STRING";
6236 case T_TELETEXSTRING
:
6237 return "TELETEXSTRING";
6238 case T_VIDEOTEXSTRING
:
6239 return "VIDEOTEXSTRING";
6240 case T_OBJECTDESCRIPTOR
:
6241 case T_GRAPHICSTRING
:
6242 return "GRAPHICSTRING";
6243 case T_GENERALSTRING
:
6244 return "GENERALSTRING";
6254 void Type::dump(unsigned level
) const
6256 DEBUG(level
, "Type @ %p, '%s'", (const void*)this, get_fullname().c_str());
6259 DEBUG(level
, "Type: <erroneous>");
6262 DEBUG(level
, "Type: NULL");
6265 DEBUG(level
, "Type: boolean");
6268 DEBUG(level
, "Type: integer");
6271 DEBUG(level
, "Type: INTEGER");
6272 if(u
.namednums
.block
)
6273 DEBUG(level
, "with unparsed block");
6274 if(u
.namednums
.nvs
) {
6275 DEBUG(level
, "with named numbers (%lu pcs.)",
6276 (unsigned long) u
.namednums
.nvs
->get_nof_nvs());
6277 u
.namednums
.nvs
->dump(level
+1);
6281 DEBUG(level
, "Type: float/REAL");
6285 DEBUG(level
, "Type: enumerated");
6286 u
.enums
.eis
->dump(level
+1);
6289 DEBUG(level
, "Type: bitstring");
6292 DEBUG(level
, "Type: BIT STRING");
6293 if(u
.namednums
.block
)
6294 DEBUG(level
, "with unparsed block");
6295 if(u
.namednums
.nvs
) {
6296 DEBUG(level
, "with named numbers (%lu pcs.)",
6297 (unsigned long) u
.namednums
.nvs
->get_nof_nvs());
6298 u
.namednums
.nvs
->dump(level
+1);
6302 DEBUG(level
, "Type: hexstring");
6305 DEBUG(level
, "Type: octetstring");
6308 DEBUG(level
, "Type: charstring");
6311 DEBUG(level
, "Type: universal charstring");
6314 DEBUG(level
, "Type: UTF8String");
6316 case T_NUMERICSTRING
:
6317 DEBUG(level
, "Type: NumericString");
6319 case T_PRINTABLESTRING
:
6320 DEBUG(level
, "Type: PrintableString");
6322 case T_TELETEXSTRING
:
6323 DEBUG(level
, "Type: TeletexString");
6325 case T_VIDEOTEXSTRING
:
6326 DEBUG(level
, "Type: VideotexString");
6329 DEBUG(level
, "Type: IA5String");
6331 case T_GRAPHICSTRING
:
6332 DEBUG(level
, "Type: GraphicString");
6334 case T_VISIBLESTRING
:
6335 DEBUG(level
, "Type: VisibleString");
6337 case T_GENERALSTRING
:
6338 DEBUG(level
, "Type: GeneralString");
6340 case T_UNIVERSALSTRING
:
6341 DEBUG(level
, "Type: UniversalString");
6344 DEBUG(level
, "Type: BMPString");
6346 case T_UNRESTRICTEDSTRING
:
6347 DEBUG(level
, "Type: CHARACTER STRING");
6350 DEBUG(level
, "Type: UTCTime");
6352 case T_GENERALIZEDTIME
:
6353 DEBUG(level
, "Type: GeneralizedTime");
6355 case T_OBJECTDESCRIPTOR
:
6356 DEBUG(level
, "Type: OBJECT DESCRIPTOR");
6359 DEBUG(level
, "Type: objid/OBJECT IDENTIFIER");
6362 DEBUG(level
, "Type: RELATIVE-OID");
6365 DEBUG(level
, "Type: anytype!!!");
6366 u
.secho
.cfm
->dump(level
+1);
6369 DEBUG(level
, "Type: union");
6370 u
.secho
.cfm
->dump(level
+1);
6373 DEBUG(level
, "Type: CHOICE");
6375 DEBUG(level
, "with unparsed block");
6377 DEBUG(level
, "with alternatives (%lu pcs.)",
6378 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6379 u
.secho
.ctss
->dump(level
+1);
6383 DEBUG(level
, "Type: record of/SEQUENCE OF");
6384 DEBUG(level
+1, "of type:");
6385 u
.seof
.ofType
->dump(level
+2);
6388 DEBUG(level
, "Type: set of/SET OF");
6389 DEBUG(level
+1, "of type:");
6390 u
.seof
.ofType
->dump(level
+2);
6393 DEBUG(level
, "Type: record");
6394 u
.secho
.cfm
->dump(level
+1);
6397 DEBUG(level
, "Type: set");
6398 u
.secho
.cfm
->dump(level
+1);
6401 DEBUG(level
, "Type: SEQUENCE");
6403 DEBUG(level
, "with unparsed block");
6405 DEBUG(level
, "with components (%lu pcs.)",
6406 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6407 u
.secho
.ctss
->dump(level
+1);
6411 DEBUG(level
, "Type: SET");
6413 DEBUG(level
, "with unparsed block");
6415 DEBUG(level
, "with components (%lu pcs.)",
6416 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6417 u
.secho
.ctss
->dump(level
+1);
6421 DEBUG(level
, "Type: ObjectClassFieldType (%s)",
6422 const_cast<Type
*>(this)->get_type_refd()->get_stringRepr().c_str());
6425 DEBUG(level
, "Type: opentype (mapped to CHOICE)");
6426 u
.secho
.cfm
->dump(level
+1);
6429 DEBUG(level
, "Type: ANY");
6432 DEBUG(level
, "Type: EXTERNAL");
6434 case T_EMBEDDED_PDV
:
6435 DEBUG(level
, "Type: EMBEDDED PDV");
6438 DEBUG(level
, "Type: reference");
6439 u
.ref
.ref
->dump(level
+1);
6440 if(u
.ref
.type_refd
&& u
.ref
.type_refd
->typetype
==T_OPENTYPE
)
6441 u
.ref
.type_refd
->dump(level
+1);
6444 DEBUG(level
, "Type: reference (spec) to %s:",
6445 u
.ref
.type_refd
->get_fullname().c_str());
6446 u
.ref
.type_refd
->dump(level
+ 1);
6449 DEBUG(level
, "Type: selection type");
6450 DEBUG(level
+1, "`%s' <", u
.seltype
.id
->get_dispname().c_str());
6451 u
.seltype
.type
->dump(level
+1);
6454 DEBUG(level
, "Type: verdicttype");
6457 DEBUG(level
, "Type: port");
6458 u
.port
->dump(level
+ 1);
6461 DEBUG(level
, "Type: component");
6462 u
.component
->dump(level
+ 1);
6465 DEBUG(level
, "Type: address");
6468 DEBUG(level
, "Type: default");
6471 DEBUG(level
, "Type: array");
6472 DEBUG(level
+ 1, "element type:");
6473 u
.array
.element_type
->dump(level
+ 2);
6474 DEBUG(level
+ 1, "dimension:");
6475 u
.array
.dimension
->dump(level
+ 2);
6478 DEBUG(level
, "Type: signature");
6479 if (u
.signature
.parameters
) {
6480 DEBUG(level
+1,"parameter(s):");
6481 u
.signature
.parameters
->dump(level
+2);
6483 if (u
.signature
.return_type
) {
6484 DEBUG(level
+1,"return type");
6485 u
.signature
.return_type
->dump(level
+2);
6487 if (u
.signature
.no_block
) DEBUG(level
+1,"no block");
6488 if (u
.signature
.exceptions
) {
6489 DEBUG(level
+1,"exception(s):");
6490 u
.signature
.exceptions
->dump(level
+2);
6494 DEBUG(level
, "Type: function");
6495 DEBUG(level
+1, "Parameters:");
6496 u
.fatref
.fp_list
->dump(level
+2);
6497 if (u
.fatref
.return_type
) {
6498 if (!u
.fatref
.returns_template
) {
6499 DEBUG(level
+1, "Return type:");
6501 if (u
.fatref
.template_restriction
==TR_OMIT
)
6502 DEBUG(level
+1, "Returns template of type:");
6504 DEBUG(level
+1, "Returns template(%s) of type:",
6505 Template::get_restriction_name(u
.fatref
.template_restriction
));
6507 u
.fatref
.return_type
->dump(level
+2);
6509 if(u
.fatref
.runs_on
.ref
) {
6510 DEBUG(level
+1, "Runs on clause:");
6511 u
.fatref
.runs_on
.ref
->dump(level
+2);
6513 if (u
.fatref
.runs_on
.self
) DEBUG(level
+1, "Runs on self");
6517 DEBUG(level
, "Type: altstep");
6518 DEBUG(level
+1, "Parameters:");
6519 u
.fatref
.fp_list
->dump(level
+2);
6520 if(u
.fatref
.runs_on
.ref
) {
6521 DEBUG(level
+1, "Runs on clause:");
6522 u
.fatref
.runs_on
.ref
->dump(level
+2);
6524 if (u
.fatref
.runs_on
.self
) DEBUG(level
+1, "Runs on self");
6528 DEBUG(level
, "Type: testcase");
6529 DEBUG(level
+1, "Parameters:");
6530 u
.fatref
.fp_list
->dump(level
+2);
6531 if(u
.fatref
.runs_on
.ref
) {
6532 DEBUG(level
+1, "Runs on clause:");
6533 u
.fatref
.runs_on
.ref
->dump(level
+2);
6535 if(u
.fatref
.system
.ref
) {
6536 DEBUG(level
+1, "System clause:");
6537 u
.fatref
.system
.ref
->dump(level
+2);
6541 DEBUG(level
, "type (%d - %s)", typetype
, const_cast<Type
*>(this)->get_stringRepr().c_str());
6543 DEBUG(level
, "ownertype %2d", ownertype
);
6544 if(sub_type
!=NULL
) {
6545 DEBUG(level
, "with subtype");
6546 sub_type
->dump(level
+1);
6549 DEBUG(level
, "with tags");
6550 tags
->dump(level
+1);
6553 if(w_attrib_path
&& w_attrib_path
->get_with_attr())
6555 DEBUG(level
, "Attributes");
6556 w_attrib_path
->dump(level
);
6557 //w_attrib_path->get_with_attr()->dump(level);
6561 xerattrib
->print(get_fullname().c_str());
6565 SubtypeConstraint::subtype_t
Type::get_subtype_type()
6567 Type
* t
= get_type_refd_last();
6568 switch (t
->get_typetype()) {
6571 return SubtypeConstraint::ST_INTEGER
;
6573 return SubtypeConstraint::ST_FLOAT
;
6575 return SubtypeConstraint::ST_BOOLEAN
;
6577 return SubtypeConstraint::ST_VERDICTTYPE
;
6580 return SubtypeConstraint::ST_OBJID
;
6583 return SubtypeConstraint::ST_BITSTRING
;
6585 return SubtypeConstraint::ST_HEXSTRING
;
6587 return SubtypeConstraint::ST_OCTETSTRING
;
6588 case T_TELETEXSTRING
:
6589 case T_VIDEOTEXSTRING
:
6590 case T_GRAPHICSTRING
:
6591 case T_GENERALSTRING
:
6592 case T_OBJECTDESCRIPTOR
:
6595 case T_NUMERICSTRING
:
6596 case T_PRINTABLESTRING
:
6598 case T_VISIBLESTRING
:
6600 case T_GENERALIZEDTIME
:
6601 return SubtypeConstraint::ST_CHARSTRING
;
6604 case T_UNIVERSALSTRING
:
6606 return SubtypeConstraint::ST_UNIVERSAL_CHARSTRING
;
6609 case T_NULL
: // FIXME: this should have it's own ST_NULL case
6610 return SubtypeConstraint::ST_ENUM
;
6613 case T_ANYTYPE
: // (titan's hacked anytype is a choice)
6615 return SubtypeConstraint::ST_UNION
;
6617 return SubtypeConstraint::ST_RECORDOF
;
6619 return SubtypeConstraint::ST_SETOF
;
6622 case T_EXTERNAL
: // associated ASN.1 type is a SEQUENCE
6623 case T_EMBEDDED_PDV
: // associated ASN.1 type is a SEQUENCE
6624 case T_UNRESTRICTEDSTRING
: // associated ASN.1 type is a SEQUENCE
6625 return SubtypeConstraint::ST_RECORD
;
6628 return SubtypeConstraint::ST_SET
;
6630 return SubtypeConstraint::ST_FUNCTION
;
6632 return SubtypeConstraint::ST_ALTSTEP
;
6634 return SubtypeConstraint::ST_TESTCASE
;
6636 return SubtypeConstraint::ST_ERROR
;
6640 void Type::set_parsed_restrictions(vector
<SubTypeParse
> *stp
)
6642 if(!parsed_restr
)parsed_restr
=stp
;
6643 else FATAL_ERROR("Type::set_parsed_restrictions(): restrictions "
6644 "are already set.");
6647 bool Type::is_component_internal()
6649 if (!checked
) chk();
6656 return u
.fatref
.runs_on
.self
;
6660 return u
.secho
.component_internal
;
6663 return u
.seof
.component_internal
;
6665 return u
.array
.component_internal
;
6667 return u
.signature
.component_internal
;
6670 return u
.ref
.component_internal
;
6676 void Type::chk_component_internal(map
<Type
*,void>& type_chain
,
6679 Type
* t_last
= get_type_refd_last();
6680 switch (t_last
->typetype
) {
6681 // types that cannot be sent
6683 error("Default type cannot be %s", p_what
);
6686 error("Port type `%s' cannot be %s", t_last
->get_typename().c_str(),
6690 if (t_last
->u
.fatref
.runs_on
.self
) {
6691 error("Function type `%s' with 'runs on self' clause cannot be %s",
6692 t_last
->get_typename().c_str(), p_what
);
6696 if (t_last
->u
.fatref
.runs_on
.self
) {
6697 error("Altstep type `%s' with 'runs on self' clause cannot be %s",
6698 t_last
->get_typename().c_str(), p_what
);
6701 // structured types that may contain types that cannot be sent
6709 if (type_chain
.has_key(t_last
)) break;
6710 type_chain
.add(t_last
, 0);
6711 Error_Context
cntxt(this, "In type `%s'", get_typename().c_str());
6712 switch (t_last
->typetype
) {
6716 size_t nof_comps
= t_last
->get_nof_comps();
6717 for (size_t i
=0; i
<nof_comps
; i
++) {
6718 Type
* t
= t_last
->get_comp_byIndex(i
)->get_type();
6719 if (t
->is_component_internal())
6720 t
->chk_component_internal(type_chain
, p_what
);
6725 if (t_last
->u
.seof
.ofType
->is_component_internal())
6726 t_last
->u
.seof
.ofType
->chk_component_internal(type_chain
, p_what
);
6729 if (t_last
->u
.array
.element_type
->is_component_internal())
6730 t_last
->u
.array
.element_type
->chk_component_internal(type_chain
,
6734 if (t_last
->u
.signature
.parameters
) {
6735 size_t nof_params
= t_last
->u
.signature
.parameters
->get_nof_params();
6736 for (size_t i
=0; i
<nof_params
; i
++) {
6737 Type
* t
= t_last
->u
.signature
.parameters
->
6738 get_param_byIndex(i
)->get_type();
6739 if (t
->is_component_internal())
6740 t
->chk_component_internal(type_chain
, p_what
);
6743 if (t_last
->u
.signature
.return_type
&&
6744 t_last
->u
.signature
.return_type
->is_component_internal()) {
6745 t_last
->u
.signature
.return_type
->chk_component_internal(type_chain
,
6748 if (t_last
->u
.signature
.exceptions
) {
6749 size_t nof_types
= t_last
->u
.signature
.exceptions
->get_nof_types();
6750 for (size_t i
=0; i
<nof_types
; i
++) {
6751 Type
* t
= t_last
->u
.signature
.exceptions
->get_type_byIndex(i
);
6752 if (t
->is_component_internal())
6753 t
->chk_component_internal(type_chain
, p_what
);
6758 FATAL_ERROR("Type::chk_component_internal()");
6760 type_chain
.erase(t_last
);
6762 default: //all other types are Ok.
6767 Type::typetype_t
Type::search_for_not_allowed_type(map
<Type
*,void>& type_chain
,
6768 map
<typetype_t
, void>& not_allowed
)
6770 if (!checked
) chk();
6771 Type
* t_last
= get_type_refd_last();
6772 Type::typetype_t ret
= t_last
->typetype
;
6774 if (not_allowed
.has_key(t_last
->typetype
)) {
6778 switch (t_last
->typetype
) {
6785 if (type_chain
.has_key(t_last
)) {
6788 type_chain
.add(t_last
, 0);
6789 switch (t_last
->typetype
) {
6793 size_t nof_comps
= t_last
->get_nof_comps();
6794 for (size_t i
= 0; i
< nof_comps
; ++i
) {
6795 Type
* t
= t_last
->get_comp_byIndex(i
)->get_type();
6796 ret
= t
->search_for_not_allowed_type(type_chain
, not_allowed
);
6797 if (not_allowed
.has_key(ret
)) {
6805 ret
= t_last
->get_ofType()->search_for_not_allowed_type(type_chain
, not_allowed
);
6806 if (not_allowed
.has_key(ret
)) {
6813 type_chain
.erase(t_last
);
6819 return t_last
->typetype
;
6822 string
Type::get_dispname() const
6824 string dispname
= genname
;
6826 while(pos
< dispname
.size()) {
6827 pos
= dispname
.find("__", pos
);
6828 if (pos
== dispname
.size()) {
6831 dispname
.replace(pos
, 1, "");
6837 } // namespace Common