1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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
) {
150 return "<unknown encoding>";
154 Type
*Type::get_stream_type(MessageEncodingType_t encoding_type
, int stream_variant
)
156 switch (encoding_type
) {
160 case CT_XER
: // UTF-8 doesn't fit into charstring and universal is wasteful
162 return get_pooltype(T_OSTR
);
164 if(stream_variant
==0){
165 return get_pooltype(T_CSTR
);
167 return get_pooltype(T_OSTR
);
170 return get_pooltype(T_BSTR
);
172 FATAL_ERROR("Type::get_stream_type()");
177 map
<Type::typetype_t
, Type
> *Type::pooltypes
= 0;
179 Type
* Type::get_pooltype(typetype_t p_typetype
)
181 p_typetype
=get_typetype_ttcn3(p_typetype
);
197 break; // we have a pool type
199 return 0; // no pool type for you!
201 if (!pooltypes
) pooltypes
= new map
<typetype_t
, Type
>; // lazy init
202 else if (pooltypes
->has_key(p_typetype
)) return (*pooltypes
)[p_typetype
];
204 if (p_typetype
== T_COMPONENT
)
205 t
= new Type(T_COMPONENT
, new ComponentTypeBody());
206 else t
= new Type(p_typetype
);
207 t
->ownertype
= OT_POOL
;
208 pooltypes
->add(p_typetype
, t
);
212 void Type::destroy_pooltypes()
215 for(size_t i
=0; i
<pooltypes
->size(); i
++)
216 delete pooltypes
->get_nth_elem(i
);
223 Tag
*Type::get_default_tag()
225 typetype_t t_typetype
;
228 t_typetype
= T_INT_A
;
231 t_typetype
= T_BSTR_A
;
234 t_typetype
= T_ENUM_A
;
238 t_typetype
= T_SEQ_A
;
242 t_typetype
= T_SET_A
;
251 return get_type_refd()->get_tag();
253 t_typetype
= typetype
;
256 if (!default_tags
) default_tags
= new map
<typetype_t
, Tag
>;
257 else if (default_tags
->has_key(t_typetype
))
258 return (*default_tags
)[t_typetype
];
260 switch (t_typetype
) {
262 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_ALL
, (Int
)0);
265 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_ERROR
, (Int
)0);
268 int tagnumber
= get_default_tagnumber(t_typetype
);
269 if (tagnumber
< 0) FATAL_ERROR ("Type::get_default_tag():type `%s' "
270 "does not have default tag", get_typename().c_str());
271 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_UNIVERSAL
, Int(tagnumber
));
274 default_tags
->add(t_typetype
, tag
);
278 int Type::get_default_tagnumber(typetype_t p_tt
)
281 // note: tag number 0 is reserved for internal use
294 case T_OBJECTDESCRIPTOR
:
308 // note: tag numbers 14 and 15 are reserved for future use
313 case T_NUMERICSTRING
:
315 case T_PRINTABLESTRING
:
317 case T_TELETEXSTRING
:
319 case T_VIDEOTEXSTRING
:
325 case T_GENERALIZEDTIME
:
327 case T_GRAPHICSTRING
:
329 case T_VISIBLESTRING
:
331 case T_GENERALSTRING
:
333 case T_UNIVERSALSTRING
:
335 case T_UNRESTRICTEDSTRING
:
344 map
<Type::typetype_t
, Tag
> *Type::default_tags
= 0;
346 void Type::destroy_default_tags()
349 size_t nof_tags
= default_tags
->size();
350 for (size_t i
= 0; i
< nof_tags
; i
++)
351 delete default_tags
->get_nth_elem(i
);
352 default_tags
->clear();
358 Type::Type(const Type
& p
)
359 : Governor(p
), typetype(p
.typetype
)
362 if (p
.w_attrib_path
!= NULL
) FATAL_ERROR("Type::Type()");
363 tags
=p
.tags
?p
.tags
->clone():0;
365 constraints
=p
.constraints
->clone();
366 constraints
->set_my_type(this);
369 if(p
.parsed_restr
!=NULL
) {
370 parsed_restr
=new vector
<SubTypeParse
>;
371 for(size_t i
=0;i
<p
.parsed_restr
->size();i
++) {
372 SubTypeParse
*stp
= 0;
373 switch((*p
.parsed_restr
)[i
]->get_selection()) {
374 case SubTypeParse::STP_SINGLE
:
375 stp
=new SubTypeParse((*p
.parsed_restr
)[i
]->Single());
377 case SubTypeParse::STP_RANGE
:
378 stp
=new SubTypeParse((*p
.parsed_restr
)[i
]->Min(),
379 (*p
.parsed_restr
)[i
]->MinExclusive(),
380 (*p
.parsed_restr
)[i
]->Max(),
381 (*p
.parsed_restr
)[i
]->MaxExclusive());
383 case SubTypeParse::STP_LENGTH
:
384 FATAL_ERROR("Type::Type(Type&): STP_LENGTH");
386 default: FATAL_ERROR("Type::Type()");
388 parsed_restr
->add(stp
);
404 case T_NUMERICSTRING
:
405 case T_PRINTABLESTRING
:
406 case T_TELETEXSTRING
:
407 case T_VIDEOTEXSTRING
:
409 case T_GRAPHICSTRING
:
410 case T_VISIBLESTRING
:
411 case T_GENERALSTRING
:
412 case T_UNIVERSALSTRING
:
415 case T_GENERALIZEDTIME
:
416 case T_OBJECTDESCRIPTOR
:
422 case T_UNRESTRICTEDSTRING
:
428 u
.namednums
.block
=p
.u
.namednums
.block
?p
.u
.namednums
.block
->clone():0;
429 u
.namednums
.nvs
=p
.u
.namednums
.nvs
?p
.u
.namednums
.nvs
->clone():0;
432 u
.enums
.block
=p
.u
.enums
.block
?p
.u
.enums
.block
->clone():0;
433 u
.enums
.eis1
=p
.u
.enums
.eis1
?p
.u
.enums
.eis1
->clone():0;
434 u
.enums
.ellipsis
=p
.u
.enums
.ellipsis
;
435 u
.enums
.excSpec
=p
.u
.enums
.excSpec
?p
.u
.enums
.excSpec
->clone():0;
436 u
.enums
.eis2
=p
.u
.enums
.eis2
?p
.u
.enums
.eis2
->clone():0;
439 u
.enums
.eis
=p
.u
.enums
.eis
->clone();
440 u
.enums
.eis_by_name
=0;
446 u
.secho
.cfm
=p
.u
.secho
.cfm
->clone();
447 u
.secho
.field_by_name
= 0;
448 u
.secho
.component_internal
= false;
449 u
.secho
.has_single_charenc
= false;
453 u
.secho
.tr_compsof_ready
=p
.u
.secho
.tr_compsof_ready
;
457 u
.secho
.block
=p
.u
.secho
.block
?p
.u
.secho
.block
->clone():0;
458 u
.secho
.ctss
=p
.u
.secho
.ctss
?p
.u
.secho
.ctss
->clone():0;
459 u
.secho
.field_by_name
= 0;
460 u
.secho
.component_internal
= false;
461 u
.secho
.has_single_charenc
= false;
465 u
.seof
.ofType
=p
.u
.seof
.ofType
->clone();
466 u
.seof
.component_internal
= false;
469 u
.ref
.ref
=p
.u
.ref
.ref
->clone();
471 u
.ref
.component_internal
= false;
474 u
.ref
.oc_defn
=p
.u
.ref
.oc_defn
;
475 u
.ref
.oc_fieldname
=p
.u
.ref
.oc_fieldname
;
478 u
.ref
.type_refd
=p
.u
.ref
.type_refd
;
479 u
.ref
.component_internal
= false;
482 u
.seltype
.id
=p
.u
.seltype
.id
->clone();
483 u
.seltype
.type
=p
.u
.seltype
.type
->clone();
484 u
.seltype
.type_refd
=0;
487 u
.secho
.cfm
=new CompFieldMap();
488 u
.secho
.cfm
->set_my_type(this);
489 u
.secho
.oc_defn
=p
.u
.secho
.oc_defn
;
490 u
.secho
.oc_fieldname
=p
.u
.secho
.oc_fieldname
;
491 u
.secho
.my_tableconstraint
=0;
492 u
.secho
.field_by_name
= 0;
493 u
.secho
.component_internal
= false;
494 u
.secho
.has_single_charenc
= false;
497 u
.array
.element_type
=p
.u
.array
.element_type
->clone();
498 u
.array
.dimension
= p
.u
.array
.dimension
->clone();
499 u
.array
.in_typedef
= p
.u
.array
.in_typedef
;
500 u
.array
.component_internal
= false;
503 u
.port
= p
.u
.port
->clone();
506 u
.component
= p
.u
.component
->clone();
512 u
.signature
.parameters
= p
.u
.signature
.parameters
?
513 p
.u
.signature
.parameters
->clone() : 0;
514 u
.signature
.return_type
= p
.u
.signature
.return_type
?
515 p
.u
.signature
.return_type
->clone() : 0;
516 u
.signature
.no_block
= p
.u
.signature
.no_block
;
517 u
.signature
.exceptions
= p
.u
.signature
.exceptions
?
518 p
.u
.signature
.exceptions
->clone() : 0;
519 u
.signature
.component_internal
= false;
523 u
.fatref
.fp_list
= p
.u
.fatref
.fp_list
->clone();
524 u
.fatref
.runs_on
.ref
= p
.u
.fatref
.runs_on
.ref
?
525 p
.u
.fatref
.runs_on
.ref
->clone() : 0;
526 u
.fatref
.runs_on
.self
= p
.u
.fatref
.runs_on
.self
;
527 u
.fatref
.runs_on
.type
= 0;
528 u
.fatref
.return_type
= p
.u
.fatref
.return_type
?
529 p
.u
.fatref
.return_type
->clone() : 0;
530 u
.fatref
.is_startable
= false;
531 u
.fatref
.returns_template
= p
.u
.fatref
.returns_template
;
532 u
.fatref
.template_restriction
= p
.u
.fatref
.template_restriction
;
535 u
.fatref
.fp_list
= p
.u
.fatref
.fp_list
->clone();
536 u
.fatref
.runs_on
.ref
= p
.u
.fatref
.runs_on
.ref
?
537 p
.u
.fatref
.runs_on
.ref
->clone() : 0;
538 u
.fatref
.runs_on
.self
= false;
539 u
.fatref
.runs_on
.type
= 0;
540 u
.fatref
.system
.ref
= p
.u
.fatref
.system
.ref
?
541 p
.u
.fatref
.system
.ref
->clone() : 0;
542 u
.fatref
.system
.type
= 0;
543 u
.fatref
.is_startable
= false;
544 u
.fatref
.returns_template
= false;
545 u
.fatref
.template_restriction
= TR_NONE
;
548 FATAL_ERROR("Type::Type()");
554 tags_checked
= false;
555 tbl_cons_checked
= false;
556 text_checked
= false;
557 json_checked
= false;
561 raw_length_calculated
= false;
562 has_opentypes
= false;
563 opentype_outermost
= false;
564 code_generated
= false;
565 embed_values_possible
= false;
566 use_nil_possible
= false;
567 use_order_possible
= false;
573 encode_attrib_path
= 0;
581 ownertype
= OT_UNKNOWN
;
583 chk_finished
= false;
584 pard_type_instance
= false;
587 void Type::clean_up()
601 case T_NUMERICSTRING
:
602 case T_PRINTABLESTRING
:
603 case T_TELETEXSTRING
:
604 case T_VIDEOTEXSTRING
:
606 case T_GRAPHICSTRING
:
607 case T_VISIBLESTRING
:
608 case T_GENERALSTRING
:
609 case T_UNIVERSALSTRING
:
612 case T_GENERALIZEDTIME
:
613 case T_OBJECTDESCRIPTOR
:
619 case T_UNRESTRICTEDSTRING
:
628 delete u
.namednums
.block
;
629 delete u
.namednums
.nvs
;
632 delete u
.enums
.block
;
634 u
.enums
.eis1
->release_eis();
638 u
.enums
.eis2
->release_eis();
644 if (u
.enums
.eis_by_name
) {
645 for (size_t a
= 0; a
< u
.enums
.eis_by_name
->size(); a
++) {
646 delete u
.enums
.eis_by_name
->get_nth_elem(a
);
648 u
.enums
.eis_by_name
->clear();
649 delete u
.enums
.eis_by_name
;
655 delete u
.secho
.block
;
664 if (u
.secho
.field_by_name
) {
665 for(size_t a
= 0; a
< u
.secho
.field_by_name
->size(); a
++) {
666 delete u
.secho
.field_by_name
->get_nth_elem(a
);
668 u
.secho
.field_by_name
->clear();
669 delete u
.secho
.field_by_name
;
674 delete u
.seof
.ofType
;
681 delete u
.seltype
.type
;
684 delete u
.array
.element_type
;
685 delete u
.array
.dimension
;
694 delete u
.signature
.parameters
;
695 delete u
.signature
.return_type
;
696 delete u
.signature
.exceptions
;
700 delete u
.fatref
.fp_list
;
701 delete u
.fatref
.runs_on
.ref
;
702 delete u
.fatref
.return_type
;
705 delete u
.fatref
.fp_list
;
706 delete u
.fatref
.runs_on
.ref
;
707 delete u
.fatref
.system
.ref
;
710 FATAL_ERROR("Type::clean_up()");
730 for (size_t i
= 0; i
< parsed_restr
->size(); i
++)
731 delete (*parsed_restr
)[i
];
732 parsed_restr
->clear();
736 delete w_attrib_path
;
738 delete encode_attrib_path
;
739 encode_attrib_path
= 0;
742 Type::Type(typetype_t p_tt
)
743 : Governor(S_T
), typetype(p_tt
)
758 case T_NUMERICSTRING
:
759 case T_PRINTABLESTRING
:
760 case T_TELETEXSTRING
:
761 case T_VIDEOTEXSTRING
:
763 case T_GRAPHICSTRING
:
764 case T_VISIBLESTRING
:
765 case T_GENERALSTRING
:
766 case T_UNIVERSALSTRING
:
769 case T_GENERALIZEDTIME
:
770 case T_OBJECTDESCRIPTOR
:
776 case T_UNRESTRICTEDSTRING
:
781 u
.secho
.cfm
= new CompFieldMap
;
782 u
.secho
.cfm
->set_my_type(this);
785 u
.secho
.field_by_name
= 0;
786 u
.secho
.component_internal
= false;
787 u
.secho
.has_single_charenc
= false;
798 FATAL_ERROR("Type::Type()");
802 Type::Type(typetype_t p_tt
, EnumItems
*p_eis
)
803 : Governor(S_T
), typetype(p_tt
)
805 if (p_tt
!= T_ENUM_T
|| !p_eis
) FATAL_ERROR("Type::Type()");
808 u
.enums
.eis_by_name
=0;
811 Type::Type(typetype_t p_tt
, Block
*p_block
)
812 : Governor(S_T
), typetype(p_tt
)
814 if (!p_block
) FATAL_ERROR("NULL parameter");
819 u
.namednums
.block
=p_block
;
823 u
.enums
.eis
=new EnumItems();
824 u
.enums
.block
=p_block
;
826 u
.enums
.ellipsis
=false;
829 u
.enums
.eis_by_name
=0;
833 u
.secho
.tr_compsof_ready
=false;
837 u
.secho
.block
=p_block
;
839 u
.secho
.field_by_name
= 0;
840 u
.secho
.component_internal
= false;
841 u
.secho
.has_single_charenc
= false;
844 FATAL_ERROR("Type::Type()");
848 Type::Type(typetype_t p_tt
,
849 EnumItems
*p_eis1
, bool p_ellipsis
, EnumItems
*p_eis2
)
850 : Governor(S_T
), typetype(p_tt
)
852 if (p_tt
!= T_ENUM_A
|| !p_eis1
) FATAL_ERROR("Type::Type()");
854 u
.enums
.eis
=new EnumItems();
857 u
.enums
.ellipsis
=p_ellipsis
;
859 u
.enums
.eis_by_name
=0;
862 Type::Type(typetype_t p_tt
, CompFieldMap
*p_cfm
)
863 : Governor(S_T
), typetype(p_tt
)
865 if (!p_cfm
) FATAL_ERROR("NULL parameter");
872 u
.secho
.field_by_name
= 0;
873 u
.secho
.component_internal
= false;
874 u
.secho
.has_single_charenc
= false;
877 FATAL_ERROR("Type::Type()");
881 Type::Type(typetype_t p_tt
, Type
*p_type
)
882 : Governor(S_T
), typetype(p_tt
)
884 if (!p_type
) FATAL_ERROR("NULL parameter");
889 u
.seof
.ofType
=p_type
;
890 u
.seof
.ofType
->set_ownertype(OT_RECORD_OF
, this);
891 u
.seof
.component_internal
= false;
894 u
.ref
.type_refd
=p_type
;
895 u
.ref
.type_refd
->set_ownertype(OT_REF_SPEC
, this);
896 u
.ref
.component_internal
= false;
899 FATAL_ERROR("Type::Type()");
903 Type::Type(typetype_t p_tt
, Identifier
*p_id
, Type
*p_type
)
904 : Governor(S_T
), typetype(p_tt
)
906 if (p_tt
!= T_SELTYPE
|| !p_id
|| !p_type
) FATAL_ERROR("Type::Type()");
909 u
.seltype
.type
=p_type
;
910 u
.seltype
.type
->set_ownertype(OT_SELTYPE
, this);
911 u
.seltype
.type_refd
=0;
914 Type::Type(typetype_t p_tt
, Type
*p_type
, Ttcn::ArrayDimension
*p_dim
,
916 : Governor(S_T
), typetype(p_tt
)
918 if (p_tt
!= T_ARRAY
|| !p_type
|| !p_dim
) FATAL_ERROR("Type::Type()");
920 u
.array
.element_type
= p_type
;
921 u
.array
.element_type
->set_ownertype(OT_ARRAY
, this);
922 u
.array
.dimension
= p_dim
;
923 u
.array
.in_typedef
= p_in_typedef
;
924 u
.array
.component_internal
= false;
927 Type::Type(typetype_t p_tt
, Type
*p_type
, OC_defn
*p_oc_defn
,
928 const Identifier
*p_id
)
929 : Governor(S_T
), typetype(p_tt
)
931 if (p_tt
!= T_OCFT
|| !p_type
||!p_oc_defn
|| !p_id
)
932 FATAL_ERROR("Type::Type()");
934 u
.ref
.type_refd
=p_type
;
935 u
.ref
.type_refd
->set_ownertype(OT_OCFT
, this);
936 u
.ref
.oc_defn
=p_oc_defn
;
937 u
.ref
.oc_fieldname
=p_id
;
938 u
.ref
.component_internal
= false;
941 Type::Type(typetype_t p_tt
, OC_defn
*p_oc_defn
,
942 const Identifier
*p_id
)
943 : Governor(S_T
), typetype(p_tt
)
945 if (p_tt
!= T_OPENTYPE
|| !p_oc_defn
|| !p_id
) FATAL_ERROR("Type::Type()");
948 u
.secho
.cfm
=new CompFieldMap();
949 u
.secho
.cfm
->set_my_type(this);
950 u
.secho
.oc_defn
=p_oc_defn
;
951 u
.secho
.oc_fieldname
=p_id
;
952 u
.secho
.my_tableconstraint
=0;
953 u
.secho
.field_by_name
= 0;
954 u
.secho
.component_internal
= false;
955 u
.secho
.has_single_charenc
= false;
958 Type::Type(typetype_t p_tt
, Reference
*p_ref
)
959 : Governor(S_T
), typetype(p_tt
)
961 if (p_tt
!= T_REFD
|| !p_ref
) FATAL_ERROR("Type::Type()");
965 u
.ref
.component_internal
= false;
968 Type::Type(typetype_t p_tt
, Ttcn::PortTypeBody
*p_pb
)
969 : Governor(S_T
), typetype(p_tt
)
971 if (p_tt
!= T_PORT
|| !p_pb
) FATAL_ERROR("Type::Type()");
974 p_pb
->set_my_type(this);
977 Type::Type(typetype_t p_tt
, ComponentTypeBody
*p_cb
)
978 : Governor(S_T
), typetype(p_tt
)
980 if (p_tt
!= T_COMPONENT
|| !p_cb
) FATAL_ERROR("Type::Type()");
983 p_cb
->set_my_type(this);
986 Type::Type(typetype_t p_tt
, SignatureParamList
*p_params
, Type
*p_returntype
,
987 bool p_noblock
, SignatureExceptions
*p_exceptions
)
988 : Governor(S_T
), typetype(p_tt
)
990 if (p_tt
!= T_SIGNATURE
|| (p_returntype
&& p_noblock
))
991 FATAL_ERROR("Type::Type()");
993 u
.signature
.parameters
= p_params
;
994 if ((u
.signature
.return_type
= p_returntype
)) { // check assignment for 0
995 u
.signature
.return_type
->set_ownertype(OT_SIGNATURE
, this);
997 u
.signature
.no_block
= p_noblock
;
998 u
.signature
.exceptions
= p_exceptions
;
999 u
.signature
.component_internal
= false;
1002 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1003 Ttcn::Reference
* p_runs_on_ref
, bool p_runs_on_self
,
1004 Type
*p_returntype
, bool p_returns_template
,
1005 template_restriction_t p_template_restriction
)
1006 : Governor(S_T
), typetype(p_tt
)
1008 if (p_tt
!= T_FUNCTION
|| !p_params
|| (!p_returntype
&& p_returns_template
)
1009 || (p_runs_on_ref
&& p_runs_on_self
)) FATAL_ERROR("Type::Type()");
1011 u
.fatref
.fp_list
= p_params
;
1012 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1013 u
.fatref
.runs_on
.self
= p_runs_on_self
;
1014 u
.fatref
.runs_on
.type
= 0;
1015 if ((u
.fatref
.return_type
= p_returntype
)) { // check assignment for 0
1016 u
.fatref
.return_type
->set_ownertype(OT_FUNCTION
, this);
1018 u
.fatref
.is_startable
= false;
1019 u
.fatref
.returns_template
= p_returns_template
;
1020 u
.fatref
.template_restriction
= p_template_restriction
;
1023 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1024 Ttcn::Reference
* p_runs_on_ref
, bool p_runs_on_self
)
1025 : Governor(S_T
), typetype(p_tt
)
1027 if(p_tt
!= T_ALTSTEP
|| !p_params
|| (p_runs_on_ref
&& p_runs_on_self
))
1028 FATAL_ERROR("Type::Type()");
1030 u
.fatref
.fp_list
= p_params
;
1031 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1032 u
.fatref
.runs_on
.self
= p_runs_on_self
;
1033 u
.fatref
.runs_on
.type
= 0;
1034 u
.fatref
.return_type
= 0;
1035 u
.fatref
.is_startable
= false;
1036 u
.fatref
.returns_template
= false;
1037 u
.fatref
.template_restriction
= TR_NONE
;
1040 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1041 Ttcn::Reference
* p_runs_on_ref
, Ttcn::Reference
*p_system_ref
)
1042 : Governor(S_T
), typetype(p_tt
)
1044 if(p_tt
!= T_TESTCASE
|| !p_params
|| !p_runs_on_ref
)
1045 FATAL_ERROR("Type::Type()");
1047 u
.fatref
.fp_list
= p_params
;
1048 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1049 u
.fatref
.runs_on
.self
= false;
1050 u
.fatref
.runs_on
.type
= 0;
1051 u
.fatref
.system
.ref
= p_system_ref
;
1052 u
.fatref
.system
.type
= 0;
1053 u
.fatref
.is_startable
= false;
1054 u
.fatref
.returns_template
= false;
1055 u
.fatref
.template_restriction
= TR_NONE
;
1063 void Type::free_pools()
1065 destroy_default_tags();// Additionally: R&S license warning
1066 destroy_pooltypes();// Additionally: R&S license checkin/disconnect/shutdown
1069 Type
*Type::clone() const
1071 return new Type(*this);
1074 Type::typetype_t
Type::get_typetype_ttcn3(typetype_t p_tt
)
1085 case T_UNIVERSALSTRING
:
1087 case T_TELETEXSTRING
:
1088 case T_VIDEOTEXSTRING
:
1089 case T_GRAPHICSTRING
:
1090 case T_OBJECTDESCRIPTOR
:
1091 case T_GENERALSTRING
:
1093 case T_NUMERICSTRING
:
1094 case T_PRINTABLESTRING
:
1096 case T_VISIBLESTRING
:
1098 case T_GENERALIZEDTIME
:
1109 case T_EMBEDDED_PDV
:
1110 case T_UNRESTRICTEDSTRING
:
1116 } // switch typetype
1119 bool Type::is_asn1() const
1121 if (my_scope
) return Setting::is_asn1();
1122 // the type might be a pool type, which is considered to be a TTCN-3 type
1123 typetype_t t_typetype
= get_typetype_ttcn3(typetype
);
1124 if (pooltypes
&& pooltypes
->has_key(t_typetype
) &&
1125 (*pooltypes
)[t_typetype
] == this) return false;
1126 else FATAL_ERROR("Type::is_asn1()");
1129 bool Type::is_ref() const
1132 case T_UNRESTRICTEDSTRING
:
1135 case T_EMBEDDED_PDV
:
1146 bool Type::is_secho() const
1163 Type::truth
Type::is_charenc()
1169 bool possible
= true;
1170 size_t ncomp
= u
.secho
.cfm
->get_nof_comps();
1171 for (size_t i
=0; i
<ncomp
; ++i
) {
1172 CompField
* cf
= u
.secho
.cfm
->get_comp_byIndex(i
);
1173 if (cf
->get_type()->is_charenc() == No
) {
1174 possible
= false; break;
1178 return (xerattrib
&& (xerattrib
->useUnion_
|| xerattrib
->useType_
)) ? Yes
: No
;
1187 // UNTAGGED cannot be used to make a type character-encodable!
1188 // But USE-QNAME can!
1189 return (xerattrib
&& xerattrib
->useQName_
) ? Yes
: No
;
1191 case T_SEQOF
: // A record-of is character-encodable if it has the "list"
1192 case T_SETOF
: // attribute and its element is character-encodable.
1193 return (xerattrib
&& xerattrib
->list_
&& (u
.seof
.ofType
->is_charenc()==Yes
))
1203 truth retval
= get_type_refd_last()->is_charenc();
1204 if (retval
== Yes
) return Yes
;
1205 else if (retval
== Maybe
) {
1206 if (xerattrib
&& xerattrib
->useUnion_
) return Yes
;
1208 // else fall through to No
1218 // TODO ASN.1 restricted character string types when (if) ASN.1 gets XER
1219 // TODO check subtype; strings must be restricted to not contain
1220 // control characters (0..0x1F except 9,0x0A,0x0D)
1226 /* FIXME : this kind of check should be applied to elements of secho,
1227 * not to the type of the element ! */
1232 bool Type::has_empty_xml() {
1233 bool answer
= false;
1235 case T_SEQ_A
: case T_SEQ_T
:
1236 case T_SET_A
: case T_SET_T
: {
1237 answer
= true; // If all components are optional.
1238 size_t n_comps
= get_nof_comps();
1239 for (size_t i
= 0; i
< n_comps
; ++i
) {
1240 CompField
* cf
= get_comp_byIndex(i
);
1241 if (!cf
->get_is_optional()) {
1247 case T_SEQOF
: case T_SETOF
:
1248 // _If_ there is a length restriction, 0 length must be allowed.
1249 // By this time parsed_restr has been absorbed into sub_type.
1250 answer
= (sub_type
==0) || sub_type
->zero_length_allowed();
1258 void Type::set_fullname(const string
& p_fullname
)
1260 Governor::set_fullname(p_fullname
);
1264 if(u
.namednums
.block
) u
.namednums
.block
->set_fullname(p_fullname
);
1266 u
.namednums
.nvs
->set_fullname(p_fullname
+".<namedvalues>");
1269 if(u
.enums
.eis1
) u
.enums
.eis1
->set_fullname(p_fullname
);
1270 if(u
.enums
.eis2
) u
.enums
.eis2
->set_fullname(p_fullname
);
1273 u
.enums
.eis
->set_fullname(p_fullname
);
1280 u
.secho
.cfm
->set_fullname(p_fullname
);
1285 if (u
.secho
.ctss
) u
.secho
.ctss
->set_fullname(p_fullname
);
1289 string
subtypename(".<oftype>");
1290 Type
* t
= u
.seof
.ofType
;
1291 /* Do NOT call get_type_refd_last() or else fatal_error !
1292 * The AST is not fully set up. */
1294 /* XER will use these strings */
1295 switch (t
->typetype
)
1297 case T_EMBEDDED_PDV
: case T_EXTERNAL
:
1298 case T_SEQ_A
: case T_SEQ_T
:
1299 subtypename
= ".SEQUENCE";
1302 case T_SET_A
: case T_SET_T
:
1303 subtypename
= ".SET";
1307 subtypename
= ".SEQUENCE_OF";
1311 subtypename
= ".SET_OF";
1315 subtypename
= ".BITSTRING";
1319 subtypename
= ".BOOLEAN";
1322 case T_CHOICE_A
: case T_CHOICE_T
:
1323 subtypename
= ".CHOICE";
1326 case T_ENUM_A
: case T_ENUM_T
:
1327 subtypename
= ".ENUMERATED";
1330 case T_INT_A
: case T_INT
:
1331 subtypename
= ".INTEGER";
1337 u
.seof
.ofType
->set_fullname(p_fullname
+subtypename
);
1340 u
.ref
.ref
->set_fullname(p_fullname
);
1343 u
.seltype
.type
->set_fullname(p_fullname
+".<selection>");
1346 u
.port
->set_fullname(p_fullname
);
1349 u
.component
->set_fullname(p_fullname
);
1352 u
.array
.element_type
->set_fullname(p_fullname
+ ".<element_type>");
1353 u
.array
.dimension
->set_fullname(p_fullname
+ ".<dimension>");
1356 if (u
.signature
.parameters
)
1357 u
.signature
.parameters
->set_fullname(p_fullname
);
1358 if (u
.signature
.return_type
)
1359 u
.signature
.return_type
->set_fullname(p_fullname
+ ".<return_type>");
1360 if (u
.signature
.exceptions
)
1361 u
.signature
.exceptions
->set_fullname(p_fullname
+ ".<exception_list>");
1365 u
.fatref
.fp_list
->set_fullname(p_fullname
+ "<formal_par_list>");
1366 if (u
.fatref
.runs_on
.ref
)
1367 u
.fatref
.runs_on
.ref
->set_fullname(p_fullname
+ "<runs_on_type>");
1368 if (u
.fatref
.return_type
)
1369 u
.fatref
.return_type
->set_fullname(p_fullname
+ "<return type>");
1372 u
.fatref
.fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
1373 if (u
.fatref
.runs_on
.ref
)
1374 u
.fatref
.runs_on
.ref
->set_fullname(p_fullname
+".<runs_on_type>");
1375 if (u
.fatref
.system
.ref
)
1376 u
.fatref
.system
.ref
->set_fullname(p_fullname
+ ".<system_type>");
1383 void Type::set_my_scope(Scope
*p_scope
)
1385 Governor::set_my_scope(p_scope
);
1386 if(tags
) tags
->set_my_scope(p_scope
);
1390 if(u
.namednums
.nvs
) u
.namednums
.nvs
->set_my_scope(p_scope
);
1393 if(u
.enums
.eis1
) u
.enums
.eis1
->set_my_scope(p_scope
);
1394 if(u
.enums
.eis2
) u
.enums
.eis2
->set_my_scope(p_scope
);
1397 u
.enums
.eis
->set_my_scope(p_scope
);
1404 u
.secho
.cfm
->set_my_scope(p_scope
);
1409 if(u
.secho
.ctss
) u
.secho
.ctss
->set_my_scope(p_scope
);
1413 u
.seof
.ofType
->set_my_scope(p_scope
);
1416 u
.ref
.ref
->set_my_scope(p_scope
);
1419 u
.seltype
.type
->set_my_scope(p_scope
);
1422 u
.array
.element_type
->set_my_scope(p_scope
);
1423 u
.array
.dimension
->set_my_scope(p_scope
);
1426 u
.port
->set_my_scope(p_scope
);
1429 if (u
.signature
.parameters
)
1430 u
.signature
.parameters
->set_my_scope(p_scope
);
1431 if (u
.signature
.return_type
)
1432 u
.signature
.return_type
->set_my_scope(p_scope
);
1433 if (u
.signature
.exceptions
)
1434 u
.signature
.exceptions
->set_my_scope(p_scope
);
1437 u
.component
->set_my_scope(p_scope
);
1441 // the scope of parameter list is set later in chk_Fat()
1442 if (u
.fatref
.runs_on
.ref
)
1443 u
.fatref
.runs_on
.ref
->set_my_scope(p_scope
);
1444 if (u
.fatref
.return_type
)
1445 u
.fatref
.return_type
->set_my_scope(p_scope
);
1448 // the scope of parameter list is set later in chk_Fat()
1449 if (u
.fatref
.runs_on
.ref
)
1450 u
.fatref
.runs_on
.ref
->set_my_scope(p_scope
);
1451 if (u
.fatref
.system
.ref
)
1452 u
.fatref
.system
.ref
->set_my_scope(p_scope
);
1459 Type
* Type::get_type_refd(ReferenceChain
*refch
)
1463 if(refch
&& !refch
->add(get_fullname())) goto error
;
1464 if(!u
.ref
.type_refd
) {
1465 Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1466 if (!ass
) goto error
; // The referenced assignment is not found
1467 switch (ass
->get_asstype()) {
1468 case Assignment::A_ERROR
:
1470 case Assignment::A_TYPE
:
1471 case Assignment::A_VS
:
1472 u
.ref
.type_refd
= ass
->get_Type()->get_field_type(
1473 u
.ref
.ref
->get_subrefs(), EXPECTED_DYNAMIC_VALUE
, refch
);
1474 if (!u
.ref
.type_refd
) goto error
;
1476 //case Assignment::A_VS:
1477 //u.ref.type_refd = ass->get_Type();
1478 // if(!u.ref.type_refd) goto error;
1480 case Assignment::A_OC
:
1481 case Assignment::A_OBJECT
:
1482 case Assignment::A_OS
: {
1483 Setting
*setting
= u
.ref
.ref
->get_refd_setting();
1484 if (!setting
|| setting
->get_st() == Setting::S_ERROR
) goto error
;
1486 u
.ref
.type_refd
= dynamic_cast<Type
*>(setting
);
1487 if(!u
.ref
.type_refd
) {
1488 error("`%s' is not a reference to a type",
1489 u
.ref
.ref
->get_dispname().c_str());
1493 if (u
.ref
.type_refd
->ownertype
== OT_UNKNOWN
) {
1494 u
.ref
.type_refd
->set_ownertype(OT_REF
, this);
1499 error("`%s' is not a reference to a type",
1500 u
.ref
.ref
->get_dispname().c_str());
1503 if(!u
.ref
.type_refd
->get_my_scope()) {
1505 u
.ref
.type_refd
->set_my_scope(get_my_scope());
1506 u
.ref
.type_refd
->set_parent_type(get_parent_type());
1507 u
.ref
.type_refd
->set_genname(get_genname_own(), string("type"));
1508 u
.ref
.type_refd
->set_fullname(get_fullname()+".type");
1510 if (u
.ref
.type_refd
->typetype
== T_OPENTYPE
&& !constraints
)
1511 warning("An open type without table constraint is useless in TTCN-3");
1513 return u
.ref
.type_refd
;
1516 if(refch
&& !refch
->add(get_fullname())) goto error
;
1517 if(!u
.seltype
.type_refd
) {
1518 Type
*t
=u
.seltype
.type
->get_type_refd_last(refch
);
1519 if(t
->typetype
==T_ERROR
) goto error
;
1520 if(t
->typetype
!=T_CHOICE_A
) {
1521 error("(Reference to) a CHOICE type was expected"
1522 " in selection type.");
1525 if(!t
->has_comp_withName(*u
.seltype
.id
)) {
1526 error("No alternative with name `%s' in the given type `%s'.",
1527 u
.seltype
.id
->get_dispname().c_str(),
1528 t
->get_fullname().c_str());
1531 u
.seltype
.type_refd
=t
->get_comp_byName(*u
.seltype
.id
)->get_type();
1533 return u
.seltype
.type_refd
;
1537 if(refch
&& !refch
->add(get_fullname())) goto error
;
1538 return u
.ref
.type_refd
;
1541 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1542 Identifier
t_id(Identifier::ID_ASN
, string("EXTERNAL"));
1543 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1544 case T_EMBEDDED_PDV
: {
1545 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1546 Identifier
t_id(Identifier::ID_ASN
, string("EMBEDDED PDV"));
1547 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1548 case T_UNRESTRICTEDSTRING
: {
1549 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1550 Identifier
t_id(Identifier::ID_ASN
, string("CHARACTER STRING"));
1551 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1553 if (refch
&& !refch
->add(get_fullname())) goto error
;
1554 if (u
.address
) return u
.address
;
1555 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1556 u
.address
= my_scope
->get_scope_mod()->get_address_type();
1558 error("Type `address' is not defined in this module");
1563 FATAL_ERROR("Type::get_type_refd()");
1571 Type
* Type::get_type_refd_last(ReferenceChain
*refch
)
1574 while(t
->is_ref()) t
=t
->get_type_refd(refch
);
1578 Type
*Type::get_field_type(Ttcn::FieldOrArrayRefs
*subrefs
,
1579 expected_value_t expected_index
, ReferenceChain
*refch
,
1580 bool interrupt_if_optional
)
1582 if (!subrefs
) return this;
1584 if (expected_index
== EXPECTED_TEMPLATE
)
1585 expected_index
= EXPECTED_DYNAMIC_VALUE
;
1586 size_t nof_refs
= subrefs
->get_nof_refs();
1587 subrefs
->clear_string_element_ref();
1588 for (size_t i
= 0; i
< nof_refs
; i
++) {
1589 if (refch
) refch
->mark_state();
1590 t
= t
->get_type_refd_last(refch
);
1591 if (refch
) refch
->prev_state();
1592 // stop immediately if current type t is erroneous
1593 // (e.g. because of circular reference)
1594 if (t
->typetype
== T_ERROR
) return 0;
1595 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1596 switch (ref
->get_type()) {
1597 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
1598 if (t
->typetype
== T_OPENTYPE
) {
1599 // allow the alternatives of open types as both lower and upper identifiers
1600 ref
->set_field_name_to_lowercase();
1602 const Identifier
& id
= *ref
->get_id();
1603 switch (t
->typetype
) {
1614 ref
->error("Invalid field reference `%s': type `%s' "
1615 "does not have fields", id
.get_dispname().c_str(),
1616 t
->get_typename().c_str());
1619 if (!t
->has_comp_withName(id
)) {
1620 ref
->error("Reference to non-existent field `%s' in type `%s'",
1621 id
.get_dispname().c_str(),
1622 t
->get_typename().c_str());
1625 CompField
* cf
= t
->get_comp_byName(id
);
1626 if (interrupt_if_optional
&& cf
->get_is_optional()) return 0;
1629 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
1630 Type
*embedded_type
= 0;
1631 switch (t
->typetype
) {
1634 embedded_type
= t
->u
.seof
.ofType
;
1637 embedded_type
= t
->u
.array
.element_type
;
1646 case T_NUMERICSTRING
:
1647 case T_PRINTABLESTRING
:
1648 case T_TELETEXSTRING
:
1649 case T_VIDEOTEXSTRING
:
1651 case T_GRAPHICSTRING
:
1652 case T_VISIBLESTRING
:
1653 case T_GENERALSTRING
:
1654 case T_UNIVERSALSTRING
:
1657 case T_GENERALIZEDTIME
:
1658 case T_OBJECTDESCRIPTOR
:
1659 if (subrefs
->refers_to_string_element()) {
1660 ref
->error("A string element of type `%s' cannot be indexed",
1661 t
->get_typename().c_str());
1664 subrefs
->set_string_element_ref();
1665 // string elements have the same type as the string itself
1670 ref
->error("Type `%s' cannot be indexed",
1671 t
->get_typename().c_str());
1674 // check the index value
1675 Value
*index_value
= ref
->get_val();
1676 if (t
->typetype
== T_ARRAY
) {
1677 // checking of array index is performed by the array dimension
1678 t
->u
.array
.dimension
->chk_index(index_value
, expected_index
);
1680 // perform a generic index check for other types
1681 if (refch
== 0 // variable assignment
1682 || index_value
->get_valuetype() != Value::V_NOTUSED
) {
1683 Error_Context
cntxt(index_value
, "In index value");
1684 index_value
->chk_expr_int(expected_index
);
1686 Value
*v_last
= index_value
->get_value_refd_last();
1687 if (v_last
->get_valuetype() == Value::V_INT
) {
1688 const int_val_t
*index_int
= v_last
->get_val_Int();
1689 if (*index_int
> INT_MAX
) {
1690 index_value
->error("Integer value `%s' is too big for indexing "
1691 "type `%s'", (index_int
->t_str()).c_str(),
1692 (t
->get_typename()).c_str());
1693 index_value
->set_valuetype(Value::V_ERROR
);
1695 if (*index_int
< 0) {
1696 index_value
->error("A non-negative integer value was "
1697 "expected for indexing type `%s' instead of `%s'",
1698 t
->get_typename().c_str(), (index_int
->t_str()).c_str());
1699 index_value
->set_valuetype(Value::V_ERROR
);
1704 // change t to the embedded type
1708 FATAL_ERROR("Type::get_field_type(): invalid reference type");
1714 bool Type::get_subrefs_as_array(const Ttcn::FieldOrArrayRefs
*subrefs
, dynamic_array
<size_t>& subrefs_array
, dynamic_array
<Type
*>& type_array
)
1716 if (!subrefs
) FATAL_ERROR("Type::get_subrefs_as_array()");
1718 size_t nof_refs
= subrefs
->get_nof_refs();
1719 for (size_t i
= 0; i
< nof_refs
; i
++) {
1720 t
= t
->get_type_refd_last();
1722 if (t
->typetype
== T_ERROR
) FATAL_ERROR("Type::get_subrefs_as_array()");
1723 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1724 size_t field_index
=0;
1725 switch (ref
->get_type()) {
1726 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
1727 const Identifier
& id
= *ref
->get_id();
1728 if (!t
->has_comp_withName(id
)) FATAL_ERROR("Type::get_subrefs_as_array()");
1729 CompField
* cf
= t
->get_comp_byName(id
);
1730 field_index
= t
->get_comp_index_byName(id
);
1731 field_index
= t
->get_codegen_index(field_index
);
1734 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
1735 Value
*index_value
= ref
->get_val();
1736 Value
*v_last
= index_value
->get_value_refd_last();
1737 if (v_last
->get_valuetype()!=Value::V_INT
) {
1738 // workaround: get_field_type() does not return NULL if the index
1739 // value is invalid, this function returns false in this case
1742 const int_val_t
*index_int
= v_last
->get_val_Int();
1743 if (!index_int
->is_native() || index_int
->is_negative()) {
1746 field_index
= (size_t)index_int
->get_val();
1747 Type
*embedded_type
= 0;
1748 switch (t
->typetype
) {
1751 embedded_type
= t
->u
.seof
.ofType
;
1754 embedded_type
= t
->u
.array
.element_type
;
1760 // change t to the embedded type
1764 FATAL_ERROR("Type::get_subrefs_as_array()");
1766 subrefs_array
.add(field_index
);
1771 bool Type::is_optional_field() const {
1772 if (ownertype
== OT_COMP_FIELD
) {
1773 const CompField
* const myOwner
= (CompField
*) owner
;
1774 return myOwner
&& myOwner
->get_is_optional();
1779 bool Type::field_is_optional(Ttcn::FieldOrArrayRefs
*subrefs
)
1781 // handling trivial cases
1782 if (!subrefs
) return false;
1783 size_t nof_subrefs
= subrefs
->get_nof_refs();
1784 if (nof_subrefs
< 1) return false;
1785 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
->get_ref(nof_subrefs
- 1);
1786 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) return false;
1787 // following the embedded types
1788 Type
*t
=get_type_refd_last();
1789 for (size_t i
= 0; i
< nof_subrefs
- 1; i
++) {
1790 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1791 if (ref
->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF
)
1792 t
= t
->get_comp_byName(*ref
->get_id())->get_type();
1793 else t
= t
->get_ofType();
1794 t
=t
->get_type_refd_last();
1796 // now last_ref refers to a field of t
1797 return t
->get_comp_byName(*last_ref
->get_id())->get_is_optional();
1800 bool Type::is_root_basic(){
1801 Type
*t
=get_type_refd_last();
1802 switch(t
->typetype
){
1817 int Type::get_raw_length(){
1818 if(!raw_checked
) FATAL_ERROR("Type::get_raw_length()");
1819 if(raw_length_calculated
) return raw_length
;
1820 raw_length_calculated
=true;
1823 raw_length
=get_type_refd()->get_raw_length();
1826 if(rawattrib
) raw_length
=rawattrib
->fieldlength
;
1830 if(rawattrib
) raw_length
=rawattrib
->fieldlength
;
1837 if(rawattrib
&& rawattrib
->fieldlength
) raw_length
=rawattrib
->fieldlength
;
1841 if(rawattrib
&& rawattrib
->fieldlength
) raw_length
=rawattrib
->fieldlength
;
1844 int max_val
=u
.enums
.first_unused
;
1845 for(size_t a
=0;a
<u
.enums
.eis
->get_nof_eis();a
++){
1846 int val
=u
.enums
.eis
->get_ei_byIndex(a
)->get_value()->get_val_Int()
1848 if((max_val
<0?-max_val
:max_val
)<(val
<0?-val
:val
)) max_val
=val
;
1850 if(max_val
<0){ min_bits
=1;max_val
=-max_val
;}
1851 while(max_val
){ min_bits
++; max_val
/=2;}
1852 raw_length
=min_bits
;
1858 for(size_t i
= 0; i
< get_nof_comps(); i
++){
1860 CompField
* cf
=get_comp_byIndex(i
);
1861 if(cf
->get_is_optional()){
1865 l
=cf
->get_type()->get_raw_length();
1870 if(cf
->get_type()->rawattrib
1871 && (cf
->get_type()->rawattrib
->pointerto
1872 || cf
->get_type()->rawattrib
->lengthto_num
)){
1879 // TODO: case T_ANYTYPE: for get_raw_length needed ?
1881 for(size_t i
= 0; i
< get_nof_comps(); i
++){
1882 CompField
*cf
=get_comp_byIndex(i
);
1884 l
=cf
->get_type()->get_raw_length();
1905 /** \todo: add extra checks and warnings for unsupported attributes
1906 * e.g. when TAG refers to a record/set field which has union type */
1907 void Type::chk_raw()
1909 bool self_ref
= false;
1910 if (raw_checked
) return;
1912 if (!enable_raw()) return;
1915 restrlength
=(int)sub_type
->get_length_restriction();
1916 if(restrlength
!=-1){
1918 Type
*t
=get_type_refd_last();
1919 typetype_t basic_type
=t
->typetype
;
1920 rawattrib
=new RawAST(basic_type
==T_INT
);
1921 if(basic_type
==T_REAL
) rawattrib
->fieldlength
=64;
1923 rawattrib
->length_restrition
=restrlength
;
1925 if(!rawattrib
) return;
1928 get_type_refd()->force_raw();
1929 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
1930 typetype_t basic_type
=get_type_refd_last()->typetype
;
1933 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
1934 rawattrib
->length_restrition
=-1;
1937 rawattrib
->fieldlength
=rawattrib
->length_restrition
*4;
1938 rawattrib
->length_restrition
=-1;
1941 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
1942 rawattrib
->length_restrition
=-1;
1945 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
1946 rawattrib
->length_restrition
=-1;
1950 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
1951 rawattrib
->length_restrition
=-1;
1960 size_t nof_comps
= get_nof_comps();
1961 for (size_t i
= 0; i
< nof_comps
; i
++)
1962 get_comp_byIndex(i
)->get_type()->force_raw();
1963 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++){
1964 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1965 if(!has_comp_withName(*idf
)){
1966 error("Invalid field name `%s' in RAW parameter TAG for type `%s'",
1967 idf
->get_dispname().c_str(), get_typename().c_str());
1970 size_t fieldnum
= get_comp_index_byName(*idf
);
1971 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1973 CompField
*cf
=get_comp_byIndex(fieldnum
);
1974 Type
*t
=cf
->get_type()->get_type_refd_last();
1975 for(int b
=0;b
<rawattrib
->taglist
.tag
[c
].keyList
[a
].
1976 keyField
->nElements
;b
++){
1978 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
1980 error("Invalid fieldmember type in RAW parameter TAG"
1982 ,cf
->get_name().get_dispname().c_str());
1986 if(!t
->has_comp_withName(*idf2
)){
1987 error("Invalid field member name `%s' in RAW parameter TAG "
1988 "for field `%s'", idf2
->get_dispname().c_str(),
1989 cf
->get_name().get_dispname().c_str());
1993 size_t comp_index
=t
->get_comp_index_byName(*idf2
);
1994 CompField
*cf2
=t
->get_comp_byIndex(comp_index
);
1995 t
=cf2
->get_type()->get_type_refd_last();
1998 Error_Context
cntx(this, "In Raw parmeter TAG");
1999 Value
*v
= rawattrib
->taglist
.tag
[c
].keyList
[a
].v_value
;
2000 v
->set_my_scope(get_my_scope());
2001 v
->set_my_governor(t
);
2002 t
->chk_this_value_ref(v
);
2003 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2004 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2005 Value::valuetype_t vt
= v
->get_valuetype();
2006 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2007 Free(rawattrib
->taglist
.tag
[c
].keyList
[a
].value
);
2008 rawattrib
->taglist
.tag
[c
].keyList
[a
].value
=
2009 mcopystr(v
->get_single_expr().c_str());
2020 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++) { // check TAG
2021 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
2022 if(!has_comp_withName(*idf
)){
2023 error("Invalid field name `%s' in RAW parameter TAG "
2024 "for type `%s'", idf
->get_dispname().c_str(),
2025 get_typename().c_str());
2028 fieldnum
=get_comp_index_byName(*idf
);
2029 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
2031 CompField
*cf
=get_comp_byIndex(fieldnum
);
2032 Type
*t
=cf
->get_type()->get_type_refd_last();
2033 for(int b
=0;b
<rawattrib
->taglist
.tag
[c
].keyList
[a
].
2034 keyField
->nElements
;b
++){
2036 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2038 error("Invalid fieldmember type in RAW parameter TAG"
2040 ,cf
->get_name().get_dispname().c_str());
2044 if(!t
->has_comp_withName(*idf2
)){
2045 error("Invalid field member name `%s' in RAW parameter TAG "
2046 "for field `%s'", idf2
->get_dispname().c_str(),
2047 cf
->get_name().get_dispname().c_str());
2051 size_t comp_index
=t
->get_comp_index_byName(*idf2
);
2052 CompField
*cf2
=t
->get_comp_byIndex(comp_index
);
2053 t
=cf2
->get_type()->get_type_refd_last();
2056 Error_Context
cntx(this, "In Raw parmeter TAG");
2057 Value
*v
= rawattrib
->taglist
.tag
[c
].keyList
[a
].v_value
;
2058 v
->set_my_scope(get_my_scope());
2059 v
->set_my_governor(t
);
2060 t
->chk_this_value_ref(v
);
2061 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2062 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2063 Value::valuetype_t vt
= v
->get_valuetype();
2064 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2065 Free(rawattrib
->taglist
.tag
[c
].keyList
[a
].value
);
2066 rawattrib
->taglist
.tag
[c
].keyList
[a
].value
=
2067 mcopystr(v
->get_single_expr().c_str());
2072 for(int a
=0; a
<rawattrib
->ext_bit_goup_num
;a
++){ // EXTENSION_BIT_GROUP
2073 Identifier
*idf
=rawattrib
->ext_bit_groups
[a
].from
;
2074 Identifier
*idf2
=rawattrib
->ext_bit_groups
[a
].to
;
2076 if(!has_comp_withName(*idf
)){
2077 error("Invalid field name `%s' in RAW parameter "
2078 "EXTENSION_BIT_GROUP for type `%s'",
2079 idf
->get_dispname().c_str(), get_typename().c_str());
2082 if(!has_comp_withName(*idf2
)){
2083 error("Invalid field name `%s' in RAW parameter "
2084 "EXTENSION_BIT_GROUP for type `%s'",
2085 idf2
->get_dispname().c_str(), get_typename().c_str());
2089 size_t kezd
=get_comp_index_byName(*idf
);
2090 size_t veg
=get_comp_index_byName(*idf2
);
2092 error("Invalid field order in RAW parameter "
2093 "EXTENSION_BIT_GROUP for type `%s': `%s', `%s'",
2094 get_typename().c_str(), idf
->get_dispname().c_str(),
2095 idf2
->get_dispname().c_str());
2100 if(rawattrib
->paddall
!=XDEFDEFAULT
){ // PADDALL
2101 for(size_t i
= 0; i
< get_nof_comps(); i
++) {
2102 CompField
*cfield
=get_comp_byIndex(i
);
2103 RawAST
*field_rawattr
=cfield
->get_type()->rawattrib
;
2104 if(field_rawattr
==NULL
){
2105 Type
*t
=cfield
->get_type()->get_type_refd_last();
2106 typetype_t basic_type
=t
->typetype
;
2107 t
=cfield
->get_type();
2108 if(t
->is_ref()) t
=t
->get_type_refd();
2109 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd();
2110 field_rawattr
= new RawAST(t
->rawattrib
,basic_type
==T_INT
);
2111 if(!t
->rawattrib
&& basic_type
==T_REAL
) field_rawattr
->fieldlength
=64;
2112 cfield
->get_type()->rawattrib
=field_rawattr
;
2114 if(field_rawattr
->padding
==0)
2115 field_rawattr
->padding
=rawattrib
->padding
;
2116 if(field_rawattr
->prepadding
==0)
2117 field_rawattr
->prepadding
=rawattrib
->prepadding
;
2118 if (field_rawattr
->padding_pattern_length
== 0 &&
2119 rawattrib
->padding_pattern_length
> 0) {
2120 Free(field_rawattr
->padding_pattern
);
2121 field_rawattr
->padding_pattern
=
2122 mcopystr(rawattrib
->padding_pattern
);
2123 field_rawattr
->padding_pattern_length
=
2124 rawattrib
->padding_pattern_length
;
2128 if(rawattrib
->fieldorder
!=XDEFDEFAULT
){ // FIELDORDER
2129 for(size_t i
= 0; i
< get_nof_comps(); i
++) {
2130 CompField
*cfield
=get_comp_byIndex(i
);
2131 RawAST
*field_rawattr
=cfield
->get_type()->rawattrib
;
2132 if(field_rawattr
==NULL
){
2133 Type
*t
=cfield
->get_type()->get_type_refd_last();
2134 typetype_t basic_type
=t
->typetype
;
2135 t
=cfield
->get_type();
2136 if(t
->is_ref()) t
=t
->get_type_refd();
2137 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd();
2138 field_rawattr
= new RawAST(t
->rawattrib
,basic_type
==T_INT
);
2139 if(!t
->rawattrib
&& basic_type
==T_REAL
) field_rawattr
->fieldlength
=64;
2140 cfield
->get_type()->rawattrib
=field_rawattr
;
2142 if(field_rawattr
->fieldorder
==XDEFDEFAULT
)
2143 field_rawattr
->fieldorder
=rawattrib
->fieldorder
;
2147 for(int a
=0;a
<rawattrib
->presence
.nElements
;a
++){ //PRESENCE
2150 for(int b
=0;b
<rawattrib
->presence
.keyList
[a
].keyField
->nElements
;b
++){
2151 Identifier
*idf
=rawattrib
->presence
.keyList
[a
].keyField
->names
[b
];
2153 error("Invalid fieldmember type in RAW parameter PRESENCE"
2154 " for the record %s."
2155 ,get_typename().c_str());
2159 if(!t
->has_comp_withName(*idf
)){
2160 error("Invalid fieldname in RAW parameter"
2161 " PRESENCE for the record %s: %s"
2162 ,get_typename().c_str()
2163 ,rawattrib
->presence
.keyList
[a
].keyField
->names
[b
]
2164 ->get_dispname().c_str());
2168 t
=t
->get_comp_byName(*idf
)->get_type()->get_type_refd_last();
2171 Error_Context
cntx(this, "In Raw parameter PRESENCE");
2172 Value
*v
= rawattrib
->presence
.keyList
[a
].v_value
;
2173 v
->set_my_scope(get_my_scope());
2174 v
->set_my_governor(t
);
2175 t
->chk_this_value_ref(v
);
2176 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2177 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2178 Value::valuetype_t vt
= v
->get_valuetype();
2179 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2180 Free(rawattrib
->presence
.keyList
[a
].value
);
2181 rawattrib
->presence
.keyList
[a
].value
=
2182 mcopystr(v
->get_single_expr().c_str());
2186 int used_bits
= 0; // number of bits used to store all previous fields
2187 for(size_t i
= 0; i
< get_nof_comps(); i
++) { // field attributes
2188 CompField
*cf
= get_comp_byIndex(i
);
2189 const Identifier
& field_id
= cf
->get_name();
2190 Type
*field_type
= cf
->get_type();
2191 Type
*field_type_last
= field_type
->get_type_refd_last();
2192 field_type
->force_raw();
2193 RawAST
*rawpar
= field_type
->rawattrib
;
2195 if (rawpar
->prepadding
!= 0) {
2196 used_bits
= (used_bits
+ rawpar
->prepadding
- 1) / rawpar
->prepadding
*
2199 if (rawpar
->intx
&& field_type_last
->get_typetype() == T_INT
) { // IntX
2200 if (used_bits
% 8 != 0 &&
2201 (!rawattrib
|| rawattrib
->fieldorder
!= XDEFMSB
)) {
2202 error("Using RAW parameter IntX in a record/set with FIELDORDER "
2203 "set to 'lsb' is only supported if the IntX field starts at "
2204 "the beginning of a new octet. There are %d unused bits in the "
2205 "last octet before field %s.", 8 - (used_bits
% 8),
2206 field_id
.get_dispname().c_str());
2210 used_bits
+= rawpar
->fieldlength
;
2212 if (rawpar
->padding
!= 0) {
2213 used_bits
= (used_bits
+ rawpar
->padding
- 1) / rawpar
->padding
*
2216 for (int j
= 0; j
< rawpar
->lengthto_num
; j
++) { // LENGTHTO
2217 Identifier
*idf
= rawpar
->lengthto
[j
];
2218 if (!has_comp_withName(*idf
)) {
2219 error("Invalid fieldname in RAW parameter "
2220 "LENGTHTO for field %s: %s",
2221 field_id
.get_dispname().c_str(),
2222 rawpar
->lengthto
[j
]->get_dispname().c_str());
2225 if (rawpar
->lengthto_num
) {
2226 Type
*ft
= field_type
;
2227 if (ft
->get_typetype() == T_REFD
) ft
= ft
->get_type_refd_last();
2228 typetype_t ftt
= ft
->get_typetype();
2235 for (size_t fi
= 0; fi
< ft
->get_nof_comps(); fi
++) {
2236 typetype_t uftt
= ft
->get_comp_byIndex(fi
)->get_type()
2238 if (uftt
!= T_INT
&& uftt
!= T_INT_A
)
2239 error("The union type LENGTHTO field must contain only "
2249 if (rawpar
->lengthindex
) break; // Will be checked in the next step.
2250 // Else continue with default.
2252 error("The LENGTHTO field must be an integer or union type "
2253 "instead of `%s'", ft
->get_typename().c_str());
2257 if(rawpar
->lengthto_num
&& rawpar
->lengthindex
){ // LENGTHINDEX
2258 Identifier
*idf
=rawpar
->lengthindex
->names
[0];
2259 if(!field_type_last
->is_secho()){
2260 error("Invalid fieldmember type in RAW parameter LENGTHINDEX"
2262 ,field_id
.get_dispname().c_str());
2265 if(!field_type_last
->has_comp_withName(*idf
))
2266 error("Invalid fieldname in RAW parameter"
2267 " LENGTHINDEX for field %s: %s"
2268 ,field_id
.get_dispname().c_str()
2269 ,rawpar
->lengthindex
->names
[0]->get_dispname().c_str());
2271 if(rawpar
->pointerto
){ // POINTERTO
2272 Identifier
*idf
=rawpar
->pointerto
;
2275 if(!has_comp_withName(*idf
)){
2276 error("Invalid fieldname in RAW"
2277 " parameter POINTERTO for field %s: %s"
2278 ,field_id
.get_dispname().c_str()
2279 ,rawpar
->pointerto
->get_dispname().c_str());
2282 if(!hiba
&& (pointed
=get_comp_index_byName(*idf
))<=i
){
2283 error("Pointer must precede the pointed field. Incorrect field "
2284 "name `%s' in RAW parameter POINTERTO for field `%s'",
2285 rawpar
->pointerto
->get_dispname().c_str(),
2286 field_id
.get_dispname().c_str());
2289 if(!hiba
&& rawpar
->ptrbase
){ // POINTERTO
2290 Identifier
*idf2
=rawpar
->ptrbase
;
2291 if(!has_comp_withName(*idf2
)){
2292 error("Invalid field name `%s' in RAW parameter PTROFFSET for "
2293 "field `%s'", rawpar
->ptrbase
->get_dispname().c_str(),
2294 field_id
.get_dispname().c_str());
2297 if(!hiba
&& get_comp_index_byName(*idf2
)>pointed
){
2298 error("Pointer base must precede the pointed field. Incorrect "
2299 "field name `%s' in RAW parameter PTROFFSET for field "
2300 "`%s'", rawpar
->ptrbase
->get_dispname().c_str(),
2301 field_id
.get_dispname().c_str());
2305 for(int a
=0;a
<rawpar
->presence
.nElements
;a
++){ //PRESENCE
2308 for(int b
=0;b
<rawpar
->presence
.keyList
[a
].keyField
->nElements
;b
++){
2309 Identifier
*idf
=rawpar
->presence
.keyList
[a
].keyField
->names
[b
];
2311 error("Invalid fieldmember type in RAW parameter PRESENCE"
2313 ,field_id
.get_dispname().c_str());
2317 if(!t
->has_comp_withName(*idf
)){
2318 error("Invalid fieldname `%s' in RAW parameter PRESENCE for "
2319 "field `%s'", rawpar
->presence
.keyList
[a
].keyField
2320 ->names
[b
]->get_dispname().c_str(),
2321 field_id
.get_dispname().c_str());
2325 if(b
==0 && !(get_comp_index_byName(*rawpar
->presence
.keyList
[a
]
2326 .keyField
->names
[0])<i
)){
2327 error("The PRESENCE field `%s' must precede the optional field "
2328 "in RAW parameter PRESENCE for field `%s'"
2329 ,rawpar
->presence
.keyList
[a
].keyField
->names
[0]
2330 ->get_dispname().c_str()
2331 ,field_id
.get_dispname().c_str());
2335 t
=t
->get_comp_byName(*idf
)->get_type()->get_type_refd_last();
2338 Error_Context
cntx(this, "In Raw parmeter PRESENCE");
2339 Value
*v
= rawpar
->presence
.keyList
[a
].v_value
;
2340 v
->set_my_scope(get_my_scope());
2341 v
->set_my_governor(t
);
2342 t
->chk_this_value_ref(v
);
2343 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2344 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2345 Value::valuetype_t vt
= v
->get_valuetype();
2346 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2347 Free(rawpar
->presence
.keyList
[a
].value
);
2348 rawpar
->presence
.keyList
[a
].value
=
2349 mcopystr(v
->get_single_expr().c_str());
2353 for(int c
=0;c
<rawpar
->crosstaglist
.nElements
;c
++) { // CROSSTAG
2354 Identifier
*idf
=rawpar
->crosstaglist
.tag
[c
].fieldName
;
2355 if(!field_type_last
->is_secho()){
2356 error("Invalid fieldmember type in RAW parameter CROSSTAG"
2358 ,field_id
.get_dispname().c_str());
2361 if(!field_type_last
->has_comp_withName(*idf
)){
2362 error("Invalid fieldmember name in RAW parameter CROSSTAG"
2364 ,field_id
.get_dispname().c_str()
2365 ,rawpar
->crosstaglist
.tag
[c
].fieldName
2366 ->get_dispname().c_str());
2369 for(int a
=0;a
<rawpar
->crosstaglist
.tag
[c
].nElements
;a
++){
2372 bool allow_omit
= false;
2374 b
<rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->nElements
;b
++){
2376 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2377 if(!t2
->is_secho()){
2378 error("Invalid fieldmember type in RAW parameter CROSSTAG"
2380 ,field_id
.get_dispname().c_str());
2384 if(!t2
->has_comp_withName(*idf2
)){
2385 error("Invalid fieldname in RAW parameter CROSSTAG"
2387 ,field_id
.get_dispname().c_str()
2388 ,idf2
->get_dispname().c_str());
2393 size_t field_idx
= get_comp_index_byName(*idf2
);
2394 if (field_idx
== i
) {
2395 error("RAW parameter CROSSTAG for field `%s' cannot refer "
2396 "to the field itself", idf2
->get_dispname().c_str());
2397 } else if (field_idx
> i
) {
2398 if (cf
->get_is_optional() ||
2399 field_type
->get_raw_length() < 0)
2400 error("Field `%s' that CROSSTAG refers to must precede "
2401 "field `%s' or field `%s' must be mandatory with "
2402 "fixed length", idf2
->get_dispname().c_str(),
2403 field_id
.get_dispname().c_str(),
2404 field_id
.get_dispname().c_str());
2407 CompField
*cf2
=t2
->get_comp_byName(*idf2
);
2408 t2
=cf2
->get_type()->get_type_refd_last();
2409 if (b
== rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
2410 ->nElements
- 1 && cf2
->get_is_optional())
2414 Error_Context
cntx(this, "In Raw parmeter CROSSTAG");
2415 Value
*v
= rawpar
->crosstaglist
.tag
[c
].keyList
[a
].v_value
;
2416 v
->set_my_scope(get_my_scope());
2417 v
->set_my_governor(t2
);
2418 t2
->chk_this_value_ref(v
);
2419 self_ref
= t2
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2420 INCOMPLETE_NOT_ALLOWED
,
2421 (allow_omit
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
), SUB_CHK
);
2422 Value::valuetype_t vt
= v
->get_valuetype();
2423 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2424 Free(rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
);
2425 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
=
2426 mcopystr(v
->get_single_expr().c_str());
2435 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2436 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
2437 rawattrib
->length_restrition
=-1;
2441 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2442 rawattrib
->fieldlength
=rawattrib
->length_restrition
*4;
2443 rawattrib
->length_restrition
=-1;
2447 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2448 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
2449 rawattrib
->length_restrition
=-1;
2453 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2454 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
2455 rawattrib
->length_restrition
=-1;
2460 get_ofType()->force_raw();
2461 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2462 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
2463 rawattrib
->length_restrition
=-1;
2465 if(rawattrib
->length_restrition
!=-1 &&
2466 rawattrib
->length_restrition
!=rawattrib
->fieldlength
){
2467 error("Invalid length specified in parameter FIELDLENGTH for %s of "
2468 "type `%s'. The FIELDLENGTH must be equal to specified length "
2469 "restriction", typetype
== T_SEQOF
? "record" : "set",
2470 get_fullname().c_str());
2474 if(rawattrib
->fieldlength
!=64 && rawattrib
->fieldlength
!=32){
2475 error("Invalid length (%d) specified in parameter FIELDLENGTH for "
2476 "float type `%s'. The FIELDLENGTH must be single (32) or double "
2477 "(64)", rawattrib
->fieldlength
, get_fullname().c_str());
2481 if (rawattrib
->intx
) {
2482 rawattrib
->bitorderinfield
= XDEFMSB
;
2483 rawattrib
->bitorderinoctet
= XDEFMSB
;
2484 rawattrib
->byteorder
= XDEFMSB
;
2490 // nothing to do, ASN1 types or types without defined raw attribute
2497 void Type::force_raw()
2505 // TODO case T_ANYTYPE: for force_raw ?
2509 rawattrib
= new RawAST(false);
2512 if (is_ref()) get_type_refd()->force_raw();
2517 // Don't run chk_raw() on unchecked types
2522 void Type::chk_text()
2524 if (text_checked
) return;
2525 text_checked
= true;
2526 if (!textattrib
|| !enable_text()) return;
2527 //textattrib->print_TextAST();
2529 chk_text_matching_values(textattrib
->begin_val
, "BEGIN");
2530 chk_text_matching_values(textattrib
->end_val
, "END");
2531 chk_text_matching_values(textattrib
->separator_val
, "SEPARATOR");
2538 size_t nof_comps
= get_nof_comps();
2539 for (size_t i
= 0; i
< nof_comps
; i
++)
2540 get_comp_byIndex(i
)->get_type()->force_text();
2544 get_ofType()->force_text();
2547 if (is_ref()) get_type_refd()->force_text();
2551 switch (get_type_refd_last()->typetype
) {
2553 chk_text_matching_values(textattrib
->true_params
, "true value");
2554 chk_text_matching_values(textattrib
->false_params
, "false value");
2557 if(textattrib
->nof_field_params
){
2558 Type
*t
=get_type_refd_last();
2559 size_t nof_comps
= t
->u
.enums
.eis
->get_nof_eis();
2560 textAST_enum_def
**params
=(textAST_enum_def
**)
2561 Malloc(nof_comps
*sizeof(textAST_enum_def
*));
2562 memset(params
,0,nof_comps
*sizeof(textAST_enum_def
*));
2563 for (int a
= 0; a
< textattrib
->nof_field_params
; a
++) {
2564 const Identifier
& id
= *textattrib
->field_params
[a
]->name
;
2565 if (t
->u
.enums
.eis
->has_ei_withName(id
)) {
2566 int index
= t
->get_eis_index_byName(id
);
2567 if (params
[index
]) FATAL_ERROR("Type::chk_text(): duplicate " \
2568 "attribute for enum `%s'", id
.get_dispname().c_str());
2569 params
[index
] = textattrib
->field_params
[a
];
2570 char *attrib_name
= mprintf("enumerated value `%s'",
2571 id
.get_dispname().c_str());
2572 chk_text_matching_values(¶ms
[index
]->value
, attrib_name
);
2575 error("Coding attribute refers to non-existent enumerated value "
2576 "`%s'", id
.get_dispname().c_str());
2577 Free(textattrib
->field_params
[a
]->value
.encode_token
);
2578 Free(textattrib
->field_params
[a
]->value
.decode_token
);
2579 delete textattrib
->field_params
[a
]->name
;
2580 Free(textattrib
->field_params
[a
]);
2583 Free(textattrib
->field_params
);
2584 textattrib
->field_params
=params
;
2585 textattrib
->nof_field_params
=nof_comps
;
2591 if (textattrib
->decode_token
) {
2592 char *tmp
= textattrib
->decode_token
;
2593 textattrib
->decode_token
= process_decode_token(tmp
, *this);
2595 tmp
= TTCN_pattern_to_regexp(textattrib
->decode_token
);
2598 error("Incorrect select token expression: `%s'",
2599 textattrib
->decode_token
);
2606 //textattrib->print_TextAST();
2609 void Type::chk_text_matching_values(textAST_matching_values
*matching_values
,
2610 const char *attrib_name
)
2612 if (!matching_values
) return;
2613 if (matching_values
->decode_token
) {
2614 // check whether decode token is a correct TTCN-3 pattern
2615 char *tmp
= matching_values
->decode_token
;
2616 matching_values
->decode_token
= process_decode_token(tmp
, *this);
2618 tmp
= TTCN_pattern_to_regexp(matching_values
->decode_token
);
2621 error("Incorrect matching expression for %s: `%s'", attrib_name
,
2622 matching_values
->decode_token
);
2624 } else if (matching_values
->encode_token
) {
2625 // the decode token is not present, but there is an encode token
2626 // derive the decode token from the encode token
2627 matching_values
->generated_decode_token
= true;
2628 matching_values
->decode_token
=
2629 convert_charstring_to_pattern(matching_values
->encode_token
);
2633 void Type::force_text()
2641 // TODO case T_ANYTYPE: for force_text ?
2645 textattrib
= new TextAST
;
2648 if (is_ref()) get_type_refd()->force_text();
2656 static const char* JSON_SCHEMA_KEYWORDS
[] = {
2657 // built-in JSON schema keywords
2658 "$ref", "type", "properties", "items", "anyOf", "enum", "pattern",
2659 "default", "minItems", "maxItems", "additionalProperties", "fieldOrder",
2660 "required", "$schema", "minLength", "maxLength", "minimum", "maximum",
2661 "excludeMinimum", "excludeMaximum", "allOf"
2662 // TITAN-specific keywords
2663 "originalName", "unusedAlias", "subType", "numericValues", "omitAsNull",
2664 "encoding", "decoding", "valueList"
2667 void Type::chk_json()
2669 if (json_checked
) return;
2670 json_checked
= true;
2671 if ((NULL
== jsonattrib
&& !hasEncodeAttr(get_encoding_name(CT_JSON
))) || !enable_json()) return;
2681 size_t nof_comps
= get_nof_comps();
2682 for (size_t i
= 0; i
< nof_comps
; i
++)
2683 get_comp_byIndex(i
)->get_type()->force_json();
2688 get_ofType()->force_json();
2691 if (is_ref()) get_type_refd()->force_json();
2695 if (NULL
!= jsonattrib
) {
2696 if (jsonattrib
->omit_as_null
&& !is_optional_field()) {
2697 error("Invalid attribute, 'omit as null' requires optional "
2698 "field of a record or set.");
2701 if (jsonattrib
->as_value
&& T_CHOICE_T
!= get_type_refd_last()->typetype
) {
2702 error("Invalid attribute, 'as value' is only allowed for unions");
2705 if (NULL
!= jsonattrib
->alias
) {
2706 Type
* parent
= get_parent_type();
2707 if (NULL
== parent
|| (T_SEQ_T
!= parent
->typetype
&&
2708 T_SET_T
!= parent
->typetype
&& T_CHOICE_T
!= parent
->typetype
)) {
2709 error("Invalid attribute, 'name as ...' requires field of a "
2710 "record, set or union.");
2712 if (NULL
!= parent
&& NULL
!= parent
->jsonattrib
&&
2713 T_CHOICE_T
== parent
->typetype
&& parent
->jsonattrib
->as_value
) {
2714 warning("Attribute 'name as ...' will be ignored, because parent union "
2715 "is encoded without field names.");
2719 if (NULL
!= jsonattrib
->default_value
) {
2723 const size_t nof_extensions
= jsonattrib
->schema_extensions
.size();
2724 if (0 != nof_extensions
) {
2725 const size_t nof_keywords
= sizeof(JSON_SCHEMA_KEYWORDS
) / sizeof(char*);
2727 // these keep track of erroneous extensions so each warning is only
2729 char* checked_extensions
= new char[nof_extensions
];
2730 char* checked_keywords
= new char[nof_keywords
];
2731 memset(checked_extensions
, 0, nof_extensions
);
2732 memset(checked_keywords
, 0, nof_keywords
);
2734 for (size_t i
= 0; i
< nof_extensions
; ++i
) {
2735 for (size_t j
= 0; j
< nof_keywords
; ++j
) {
2736 if (0 == checked_extensions
[i
] && 0 == checked_keywords
[j
] &&
2737 0 == strcmp(jsonattrib
->schema_extensions
[i
]->key
,
2738 JSON_SCHEMA_KEYWORDS
[j
])) {
2739 // only report the warning once for each keyword
2740 warning("JSON schema keyword '%s' should not be used as the key of "
2741 "attribute 'extend'", JSON_SCHEMA_KEYWORDS
[j
]);
2742 checked_keywords
[j
] = 1;
2743 checked_extensions
[i
] = 1;
2747 if (0 == checked_extensions
[i
]) {
2748 for (size_t k
= i
+ 1; k
< nof_extensions
; ++k
) {
2749 if (0 == strcmp(jsonattrib
->schema_extensions
[i
]->key
,
2750 jsonattrib
->schema_extensions
[k
]->key
)) {
2751 if (0 == checked_extensions
[i
]) {
2752 // only report the warning once for each unique key
2753 warning("Key '%s' is used multiple times in 'extend' attributes "
2754 "of type '%s'", jsonattrib
->schema_extensions
[i
]->key
,
2755 get_typename().c_str());
2756 checked_extensions
[i
] = 1;
2758 checked_extensions
[k
] = 1;
2763 delete[] checked_extensions
;
2764 delete[] checked_keywords
;
2766 if (jsonattrib
->metainfo_unbound
) {
2767 Type
* parent
= get_parent_type();
2768 if (T_SEQ_T
== get_type_refd_last()->typetype
||
2769 T_SET_T
== get_type_refd_last()->typetype
) {
2770 // if it's set for the record/set, pass it onto its fields
2771 size_t nof_comps
= get_nof_comps();
2772 for (size_t i
= 0; i
< nof_comps
; i
++) {
2773 Type
* comp_type
= get_comp_byIndex(i
)->get_type();
2774 if (NULL
== comp_type
->jsonattrib
) {
2775 comp_type
->jsonattrib
= new JsonAST
;
2777 comp_type
->jsonattrib
->metainfo_unbound
= true;
2780 else if (NULL
== parent
|| (T_SEQ_T
!= parent
->typetype
&&
2781 T_SET_T
!= parent
->typetype
)) {
2782 // only allowed if it's a field of a record/set
2783 error("Invalid attribute 'metainfo for unbound', requires record, set, "
2784 "or field of a record or set");
2790 void Type::chk_json_default()
2792 const char* dval
= jsonattrib
->default_value
;
2793 const size_t dval_len
= strlen(dval
);
2794 Type
*last
= get_type_refd_last();
2796 switch (last
->typetype
) {
2798 if (strcmp(dval
, "true") != 0 && strcmp(dval
, "false") != 0) {
2803 for (size_t i
= (dval
[0] == '-') ? 1 : 0; i
< dval_len
; ++i
) {
2804 if (dval
[i
] < '0' || dval
[i
] > '9') {
2806 break; // from the loop
2811 if (strcmp(dval
, "infinity") == 0 || strcmp(dval
, "-infinity") == 0 ||
2812 strcmp(dval
, "not_a_number") == 0) {
2813 // special float values => skip the rest of the check
2817 boolean first_digit
= false; // first non-zero digit reached
2818 boolean zero
= false; // first zero digit reached
2819 boolean decimal_point
= false; // decimal point (.) reached
2820 boolean exponent_mark
= false; // exponential mark (e or E) reached
2821 boolean exponent_sign
= false; // sign of the exponential (- or +) reached
2823 size_t i
= (dval
[0] == '-') ? 1 : 0;
2824 while(!err
&& i
< dval_len
) {
2827 if (decimal_point
|| exponent_mark
|| (!first_digit
&& !zero
)) {
2830 decimal_point
= true;
2831 first_digit
= false;
2836 if (exponent_mark
|| (!first_digit
&& !zero
)) {
2839 exponent_mark
= true;
2840 first_digit
= false;
2844 if (!first_digit
&& (exponent_mark
|| (!decimal_point
&& zero
))) {
2858 if (!first_digit
&& zero
&& (!decimal_point
|| exponent_mark
)) {
2865 if (exponent_sign
|| !exponent_mark
|| zero
|| first_digit
) {
2868 exponent_sign
= true;
2875 err
= !first_digit
&& !zero
;
2878 for (size_t i
= 0; i
< dval_len
; ++i
) {
2879 if (dval
[i
] < '0' || dval
[i
] > '1') {
2881 break; // from the loop
2886 if (dval_len
% 2 != 0) {
2892 for (size_t i
= 0; i
< dval_len
; ++i
) {
2893 if ((dval
[i
] < '0' || dval
[i
] > '9') && (dval
[i
] < 'a' || dval
[i
] > 'f') &&
2894 (dval
[i
] < 'A' || dval
[i
] > 'F')) {
2896 break; // from the loop
2903 while(!err
&& i
< dval_len
) {
2904 if (dval
[i
] < 0 && last
->typetype
== T_CSTR
) {
2907 else if (dval
[i
] == '\\') {
2908 if (i
== dval_len
- 1) {
2921 break; // these are OK
2923 if (i
+ 4 >= dval_len
) {
2925 } else if (last
->typetype
== T_CSTR
&&
2926 (dval
[i
+ 1] != '0' || dval
[i
+ 2] != '0' ||
2927 dval
[i
+ 3] < '0' || dval
[i
+ 3] > '7')) {
2930 for (size_t j
= (last
->typetype
== T_CSTR
) ? 4 : 1; j
<= 4; ++j
) {
2931 if ((dval
[i
+ j
] < '0' || dval
[i
+ j
] > '9') &&
2932 (dval
[i
+ j
] < 'a' || dval
[i
+ j
] > 'f') &&
2933 (dval
[i
+ j
] < 'A' || dval
[i
+ j
] > 'F')) {
2935 break; // from the loop
2951 Common::Identifier
id(Identifier::ID_TTCN
, string(dval
));
2952 if (!last
->has_ei_withName(id
)) {
2957 if (strcmp(dval
, "none") != 0 && strcmp(dval
, "pass") != 0 &&
2958 strcmp(dval
, "inconc") != 0 && strcmp(dval
, "fail") != 0 &&
2959 strcmp(dval
, "error") != 0) {
2964 error("JSON default values are not available for type `%s'",
2965 last
->get_stringRepr().c_str());
2970 if (last
->typetype
== T_ENUM_T
) {
2971 error("Invalid JSON default value for enumerated type `%s'",
2972 last
->get_stringRepr().c_str());
2974 error("Invalid %s JSON default value", get_typename_builtin(last
->typetype
));
2979 void Type::force_json()
2994 jsonattrib
= new JsonAST
;
2997 if (is_ref()) get_type_refd()->force_json();
3006 int Type::get_length_multiplier()
3010 return get_type_refd()->get_length_multiplier();
3025 /** \todo review, especially the string types... */
3026 bool Type::is_compatible_tt_tt(typetype_t p_tt1
, typetype_t p_tt2
,
3027 bool p_is_asn11
, bool p_is_asn12
)
3029 if (p_tt2
== T_ERROR
) return true;
3031 // error type is compatible with everything
3034 // unambiguous built-in types
3050 return p_tt1
== p_tt2
;
3052 return p_tt2
==T_OSTR
|| (!p_is_asn11
&& p_tt2
==T_ANY
);
3058 case T_UNIVERSALSTRING
:
3059 case T_TELETEXSTRING
:
3060 case T_VIDEOTEXSTRING
:
3061 case T_GRAPHICSTRING
:
3062 case T_OBJECTDESCRIPTOR
:
3063 case T_GENERALSTRING
:
3065 case T_NUMERICSTRING
:
3066 case T_PRINTABLESTRING
:
3068 case T_VISIBLESTRING
:
3070 case T_GENERALIZEDTIME
:
3075 // character string group 1
3078 case T_UNIVERSALSTRING
:
3083 case T_UNIVERSALSTRING
:
3085 case T_NUMERICSTRING
:
3086 case T_PRINTABLESTRING
:
3088 case T_VISIBLESTRING
:
3090 case T_GENERALIZEDTIME
:
3095 // character string group 2
3096 case T_TELETEXSTRING
:
3097 case T_VIDEOTEXSTRING
:
3098 case T_GRAPHICSTRING
:
3099 case T_OBJECTDESCRIPTOR
:
3100 case T_GENERALSTRING
:
3102 case T_TELETEXSTRING
:
3103 case T_VIDEOTEXSTRING
:
3104 case T_GRAPHICSTRING
:
3105 case T_OBJECTDESCRIPTOR
:
3106 case T_GENERALSTRING
:
3108 case T_NUMERICSTRING
:
3109 case T_PRINTABLESTRING
:
3111 case T_VISIBLESTRING
:
3113 case T_GENERALIZEDTIME
:
3116 // maybe :) is ustr.is_cstr()
3121 // character string group 3
3123 case T_NUMERICSTRING
:
3124 case T_PRINTABLESTRING
:
3126 case T_VISIBLESTRING
:
3128 case T_GENERALIZEDTIME
:
3131 case T_NUMERICSTRING
:
3132 case T_PRINTABLESTRING
:
3134 case T_VISIBLESTRING
:
3136 case T_GENERALIZEDTIME
:
3141 // polymorphic built-in types
3144 return p_tt2
== T_BSTR
|| p_tt2
== T_BSTR_A
;
3147 return p_tt2
== T_INT
|| p_tt2
== T_INT_A
;
3148 // ROID is visible as OID from TTCN-3
3150 return p_tt2
== T_OID
||
3151 (!p_is_asn11
&& p_tt2
== T_ROID
);
3153 return p_tt2
== T_ROID
||
3154 (!p_is_asn12
&& p_tt2
== T_OID
);
3157 return p_tt2
==T_ENUM_A
|| p_tt2
==T_ENUM_T
;
3161 return p_tt2
==T_CHOICE_T
|| p_tt2
==T_CHOICE_A
|| p_tt2
==T_OPENTYPE
;
3164 return p_tt2
==T_SEQ_A
|| p_tt2
==T_SEQ_T
;
3167 return p_tt2
==T_SET_A
|| p_tt2
==T_SET_T
;
3169 return p_tt2
== T_ANY
|| p_tt2
== T_OSTR
;
3170 // these should never appear?
3177 FATAL_ERROR("Type::is_compatible_tt_tt()");
3182 bool Type::is_compatible_tt(typetype_t p_tt
, bool p_is_asn1
)
3185 Type
*t1
=get_type_refd_last();
3186 if (p_tt
== T_ERROR
) return true;
3187 switch (t1
->typetype
) {
3188 // these should never appear
3193 FATAL_ERROR("Type::is_compatible_tt()");
3196 return is_compatible_tt_tt(t1
->typetype
, p_tt
, is_asn1(), p_is_asn1
);
3200 bool Type::is_compatible(Type
*p_type
, TypeCompatInfo
*p_info
,
3201 TypeChain
*p_left_chain
, TypeChain
*p_right_chain
,
3202 bool p_is_inline_template
)
3206 Type
*t1
= get_type_refd_last();
3207 Type
*t2
= p_type
->get_type_refd_last();
3208 // Error type is compatible with everything.
3209 if (t1
->typetype
== T_ERROR
|| t2
->typetype
== T_ERROR
) return true;
3211 switch (t1
->typetype
) {
3212 // Unambiguous built-in types.
3219 is_type_comp
= (t1
->typetype
== t2
->typetype
);
3222 is_type_comp
= ( t2
->typetype
==T_OSTR
|| (!is_asn1() && t2
->typetype
==T_ANY
) );
3225 switch (t2
->typetype
) {
3229 case T_UNIVERSALSTRING
:
3230 case T_TELETEXSTRING
:
3231 case T_VIDEOTEXSTRING
:
3232 case T_GRAPHICSTRING
:
3233 case T_OBJECTDESCRIPTOR
:
3234 case T_GENERALSTRING
:
3236 case T_NUMERICSTRING
:
3237 case T_PRINTABLESTRING
:
3239 case T_VISIBLESTRING
:
3241 case T_GENERALIZEDTIME
:
3242 is_type_comp
= true;
3245 is_type_comp
= false;
3249 // Character string group 1.
3252 case T_UNIVERSALSTRING
:
3253 switch (t2
->typetype
) {
3257 case T_UNIVERSALSTRING
:
3259 case T_NUMERICSTRING
:
3260 case T_PRINTABLESTRING
:
3262 case T_VISIBLESTRING
:
3264 case T_GENERALIZEDTIME
:
3265 is_type_comp
= true;
3268 is_type_comp
= false;
3272 // Character string group 2.
3273 case T_TELETEXSTRING
:
3274 case T_VIDEOTEXSTRING
:
3275 case T_GRAPHICSTRING
:
3276 case T_OBJECTDESCRIPTOR
:
3277 case T_GENERALSTRING
:
3278 switch (t2
->typetype
) {
3279 case T_TELETEXSTRING
:
3280 case T_VIDEOTEXSTRING
:
3281 case T_GRAPHICSTRING
:
3282 case T_OBJECTDESCRIPTOR
:
3283 case T_GENERALSTRING
:
3285 case T_NUMERICSTRING
:
3286 case T_PRINTABLESTRING
:
3288 case T_VISIBLESTRING
:
3290 case T_GENERALIZEDTIME
:
3291 is_type_comp
= true;
3294 // Maybe :) is ustr.is_cstr().
3295 is_type_comp
= true;
3298 is_type_comp
= false;
3302 // Character string group 3.
3304 case T_NUMERICSTRING
:
3305 case T_PRINTABLESTRING
:
3307 case T_VISIBLESTRING
:
3309 case T_GENERALIZEDTIME
:
3310 switch (t2
->typetype
) {
3312 case T_NUMERICSTRING
:
3313 case T_PRINTABLESTRING
:
3315 case T_VISIBLESTRING
:
3317 case T_GENERALIZEDTIME
:
3318 is_type_comp
= true;
3321 is_type_comp
= false;
3325 // Polymorphic built-in types.
3328 is_type_comp
= ( t2
->typetype
== T_BSTR
|| t2
->typetype
== T_BSTR_A
);
3332 is_type_comp
= ( t2
->typetype
== T_INT
|| t2
->typetype
== T_INT_A
);
3334 // ROID is visible as OID from TTCN-3.
3336 is_type_comp
= ( t2
->typetype
== T_OID
|| (!is_asn1() && t2
->typetype
== T_ROID
) );
3339 is_type_comp
= ( t2
->typetype
== T_ROID
|| (!p_type
->is_asn1() && t2
->typetype
== T_OID
) );
3342 is_type_comp
= ( t2
->typetype
== T_COMPONENT
&& t1
->u
.component
->is_compatible(t2
->u
.component
) );
3346 is_type_comp
= t1
->is_compatible_record(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3349 is_type_comp
= t1
->is_compatible_record_of(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3353 is_type_comp
= t1
->is_compatible_set(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3356 is_type_comp
= t1
->is_compatible_set_of(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3359 is_type_comp
= t1
->is_compatible_array(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3364 is_type_comp
= t1
->is_compatible_choice_anytype(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3371 is_type_comp
= ( t1
== t2
);
3376 // TODO: Compatibility.
3377 is_type_comp
= ( t1
== t2
);
3380 is_type_comp
= ( t2
->typetype
== T_ANY
|| t2
->typetype
== T_OSTR
);
3383 FATAL_ERROR("Type::is_compatible()");
3385 // if types are compatible then check subtype compatibility
3386 // skip check if p_info is NULL
3387 if ((p_info
!=NULL
) && is_type_comp
&& (sub_type
!=NULL
) && (p_type
->sub_type
!=NULL
) &&
3388 (sub_type
->get_subtypetype()==p_type
->sub_type
->get_subtypetype()))
3390 if (p_info
->get_str1_elem()) {
3391 if (p_info
->get_str2_elem()) {
3392 // both are string elements -> nothing to do
3395 if (!p_type
->sub_type
->is_compatible_with_elem()) {
3396 is_type_comp
= false;
3397 p_info
->set_subtype_error(
3398 string("Subtype mismatch: string element has no common value with subtype ")+
3399 p_type
->sub_type
->to_string());
3403 if (p_info
->get_str2_elem()) {
3405 if (!sub_type
->is_compatible_with_elem()) {
3406 is_type_comp
= false;
3407 p_info
->set_subtype_error(string("Subtype mismatch: subtype ")+
3408 sub_type
->to_string()+string(" has no common value with a string element"));
3411 // string <-> string
3412 if (!sub_type
->is_compatible(p_type
->sub_type
)) {
3413 is_type_comp
= false;
3414 p_info
->set_subtype_error(string("Subtype mismatch: subtype ")+
3415 sub_type
->to_string()+string(" has no common value with subtype ")+
3416 p_type
->sub_type
->to_string());
3421 return is_type_comp
;
3424 bool Type::is_structured_type() const
3443 bool Type::is_subtype_length_compatible(Type
*p_type
)
3445 if (typetype
!= T_SEQOF
&& typetype
!= T_SETOF
)
3446 FATAL_ERROR("Type::is_subtype_length_compatible()");
3447 if (!sub_type
) return true;
3448 SubtypeConstraint::subtype_t st_t
= typetype
== T_SEQOF
?
3449 SubtypeConstraint::ST_RECORDOF
: SubtypeConstraint::ST_SETOF
;
3450 switch (p_type
->typetype
) {
3455 vector
<SubTypeParse
> p_stp_v
;
3456 Value
*p_nof_comps
= new Value(Value::V_INT
,
3457 new int_val_t(p_type
->get_nof_comps()));
3458 p_stp_v
.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps
)));
3459 SubType
p_st(st_t
, this, NULL
, &p_stp_v
, NULL
);
3463 return sub_type
->is_length_compatible(&p_st
); }
3466 if (!p_type
->sub_type
) return true;
3467 else return sub_type
->is_length_compatible(p_type
->sub_type
);
3469 if (p_type
->u
.array
.dimension
->get_has_error()) return false;
3470 vector
<SubTypeParse
> p_stp_v
;
3472 = new Value(Value::V_INT
,
3473 new int_val_t(p_type
->u
.array
.dimension
->get_size()));
3474 p_stp_v
.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps
)));
3475 SubType
p_st(st_t
, this, NULL
, &p_stp_v
, NULL
);
3476 p_st
.chk(); // Convert SubTypeParse to SubType.
3479 return sub_type
->is_length_compatible(&p_st
); }
3481 FATAL_ERROR("Type::is_subtype_length_compatible()");
3485 // Errors and warnings are reported in an upper level. We just make a
3486 // simple decision here.
3487 bool Type::is_compatible_record(Type
*p_type
, TypeCompatInfo
*p_info
,
3488 TypeChain
*p_left_chain
,
3489 TypeChain
*p_right_chain
,
3490 bool p_is_inline_template
)
3492 if (typetype
!= T_SEQ_A
&& typetype
!= T_SEQ_T
)
3493 FATAL_ERROR("Type::is_compatible_record()");
3494 // The get_type_refd_last() was called for both Types at this point. All
3495 // this code runs in both run-times.
3496 if (this == p_type
) return true;
3497 else if (!use_runtime_2
|| !p_info
3498 || (p_info
&& p_info
->is_strict())) return false;
3499 size_t nof_comps
= get_nof_comps();
3500 switch (p_type
->typetype
) {
3503 // According to 6.3.2.2 the # of fields and the optionality must be
3504 // the same for record types. It's good news for compile-time checks.
3505 // Conversion is always from "p_type -> this".
3506 size_t p_nof_comps
= p_type
->get_nof_comps();
3507 if (nof_comps
!= p_nof_comps
) {
3508 p_info
->set_is_erroneous(this, p_type
, string("The number of fields in "
3509 "record/SEQUENCE types must be the same"));
3512 // If p_info is present we have the chains as well.
3513 if (p_left_chain
->empty()) p_left_chain
->add(this);
3514 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3515 for (size_t i
= 0; i
< nof_comps
; i
++) {
3516 CompField
*cf
= get_comp_byIndex(i
);
3517 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3518 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
3519 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3520 string cf_name
= cf
->get_name().get_dispname();
3521 string p_cf_name
= p_cf
->get_name().get_dispname();
3522 if (cf
->get_is_optional() != p_cf
->get_is_optional()) {
3523 p_info
->append_ref_str(0, "." + cf_name
);
3524 p_info
->append_ref_str(1, "." + p_cf_name
);
3525 p_info
->set_is_erroneous(cf_type
, p_cf_type
, string("The optionality of "
3526 "fields in record/SEQUENCE types must be "
3530 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
3532 p_left_chain
->mark_state();
3533 p_right_chain
->mark_state();
3534 p_left_chain
->add(cf_type
);
3535 p_right_chain
->add(p_cf_type
);
3536 if (cf_type
!= p_cf_type
3537 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3538 && !cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3539 p_right_chain
, p_is_inline_template
)) {
3540 p_info
->append_ref_str(0, "." + cf_name
+ info_tmp
.get_ref_str(0));
3541 p_info
->append_ref_str(1, "." + p_cf_name
+ info_tmp
.get_ref_str(1));
3542 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3543 info_tmp
.get_error_str());
3544 p_left_chain
->previous_state();
3545 p_right_chain
->previous_state();
3548 p_left_chain
->previous_state();
3549 p_right_chain
->previous_state();
3551 if (!p_is_inline_template
) {
3552 p_info
->set_needs_conversion(true);
3553 p_info
->add_type_conversion(p_type
, this);
3557 if (!p_type
->is_subtype_length_compatible(this)) {
3558 p_info
->set_is_erroneous(this, p_type
, string("Incompatible record of/SEQUENCE "
3564 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3565 if (p_type
->typetype
== T_ARRAY
) {
3566 if (p_of_type
->get_typetype() == T_ARRAY
) {
3567 p_info
->set_is_erroneous(this, p_type
, string("record/SEQUENCE types are "
3568 "compatible only with single-dimension "
3572 size_t nof_opt_fields
= 0;
3573 for (size_t i
= 0; i
< nof_comps
; i
++)
3574 if (get_comp_byIndex(i
)->get_is_optional()) nof_opt_fields
++;
3575 if (p_type
->u
.array
.dimension
->get_size()
3576 < nof_comps
- nof_opt_fields
) {
3577 p_info
->set_is_erroneous(this, p_type
, string("The dimension of the array "
3578 "must be >= than the number of mandatory "
3579 "fields in the record/SEQUENCE type"));
3583 if (p_left_chain
->empty()) p_left_chain
->add(this);
3584 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3585 for (size_t i
= 0; i
< nof_comps
; i
++) {
3586 Type
*cf_type
= get_comp_byIndex(i
)->get_type()->get_type_refd_last();
3587 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_of_type
,
3589 p_left_chain
->mark_state();
3590 p_right_chain
->mark_state();
3591 p_left_chain
->add(cf_type
);
3592 p_right_chain
->add(p_of_type
);
3593 if (cf_type
!= p_of_type
3594 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3595 && !cf_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3596 p_right_chain
, p_is_inline_template
)) {
3597 p_info
->append_ref_str(0, "." + get_comp_byIndex(i
)
3598 ->get_name().get_dispname() + info_tmp
.get_ref_str(0));
3599 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
3600 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3601 info_tmp
.get_error_str());
3602 p_left_chain
->previous_state();
3603 p_right_chain
->previous_state();
3606 p_left_chain
->previous_state();
3607 p_right_chain
->previous_state();
3609 if (!p_is_inline_template
) {
3610 p_info
->set_needs_conversion(true);
3611 p_info
->add_type_conversion(p_type
, this);
3617 // 6.3.2.4 makes our job very easy...
3618 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3619 "compatible only with other "
3620 "union/CHOICE/anytype types"));
3625 // Only set/set of types are compatible with other set/set of types.
3626 // 6.3.2.3 is a little bit unclear about set of types, but we treat them
3627 // this way. Otherwise, it would be possible to use compatibility with
3628 // a "middle-man" set of variable between record/set types:
3629 // type set S { integer f1, integer f2 }
3630 // type record { integer f1, integer f2 }
3631 // type set of integer SO
3632 // var S s := { 1, 2 }
3633 // var R r := { 1, 2 }
3636 // if (r == s) { ... } // Not allowed.
3637 // if (r == so) { ... } // Not allowed. (?)
3638 // Seems to be a fair decision. If we would want compatibility between
3639 // variables of record/set types, we should allow it directly.
3640 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3641 "types are compatible only with other set/SET "
3642 "set of/SET OF types"));
3649 bool Type::is_compatible_record_of(Type
*p_type
, TypeCompatInfo
*p_info
,
3650 TypeChain
*p_left_chain
,
3651 TypeChain
*p_right_chain
,
3652 bool p_is_inline_template
)
3654 if (typetype
!= T_SEQOF
) FATAL_ERROR("Type::is_compatible_record_of()");
3655 if (this == p_type
) return true;
3656 else if (T_SEQOF
== p_type
->get_type_refd_last()->typetype
&&
3657 is_pregenerated() && p_type
->is_pregenerated() &&
3658 get_ofType()->get_type_refd_last()->typetype
==
3659 p_type
->get_ofType()->get_type_refd_last()->typetype
&&
3660 (use_runtime_2
|| get_optimize_attribute() == p_type
->get_optimize_attribute())) {
3661 // Pre-generated record-ofs of the same element type are compatible with
3662 // each other (in RT1 optimized record-ofs are not compatible with non-optimized ones)
3663 if (!is_subtype_length_compatible(p_type
)) {
3664 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3665 "record of/SEQUENCE OF subtypes"));
3670 else if (!use_runtime_2
|| !p_info
3671 || (p_info
&& p_info
->is_strict())) return false;
3672 switch (p_type
->typetype
) {
3675 if (!is_subtype_length_compatible(p_type
)) {
3676 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3677 "record of/SEQUENCE OF subtypes"));
3680 Type
*of_type
= get_ofType()->get_type_refd_last();
3681 if (p_left_chain
->empty()) p_left_chain
->add(this);
3682 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3683 for (size_t i
= 0; i
< p_type
->get_nof_comps(); i
++) {
3684 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3685 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3686 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3688 p_left_chain
->mark_state();
3689 p_right_chain
->mark_state();
3690 p_left_chain
->add(of_type
);
3691 p_right_chain
->add(p_cf_type
);
3692 if (of_type
!= p_cf_type
3693 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3694 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3695 p_right_chain
, p_is_inline_template
)) {
3696 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3697 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3698 info_tmp
.get_ref_str(1));
3699 p_info
->set_is_erroneous(info_tmp
.get_type(0),
3700 info_tmp
.get_type(1),
3701 info_tmp
.get_error_str());
3702 p_left_chain
->previous_state();
3703 p_right_chain
->previous_state();
3706 p_left_chain
->previous_state();
3707 p_right_chain
->previous_state();
3709 if (!p_is_inline_template
) {
3710 p_info
->set_needs_conversion(true);
3711 p_info
->add_type_conversion(p_type
, this);
3716 if (!is_subtype_length_compatible(p_type
)) {
3717 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3718 "record of/SEQUENCE OF subtypes"));
3721 Type
*of_type
= get_ofType()->get_type_refd_last();
3722 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3723 if (p_left_chain
->empty()) p_left_chain
->add(this);
3724 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3725 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3727 p_left_chain
->mark_state();
3728 p_right_chain
->mark_state();
3729 p_left_chain
->add(of_type
);
3730 p_right_chain
->add(p_of_type
);
3731 if (of_type
== p_of_type
3732 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3733 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3734 p_right_chain
, p_is_inline_template
)) {
3735 if (!p_is_inline_template
) {
3736 p_info
->set_needs_conversion(true);
3737 p_info
->add_type_conversion(p_type
, this);
3739 p_left_chain
->previous_state();
3740 p_right_chain
->previous_state();
3743 p_left_chain
->previous_state();
3744 p_right_chain
->previous_state();
3745 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3746 // Arrays already have the "[]" in their names.
3747 if (p_type
->get_typetype() != T_ARRAY
) p_info
->append_ref_str(1, string("[]"));
3748 p_info
->append_ref_str(1, info_tmp
.get_ref_str(1));
3749 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3750 info_tmp
.get_error_str());
3755 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3756 "compatible only with other "
3757 "union/CHOICE/anytype types"));
3762 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3763 "types are compatible only with other set/SET "
3764 "set of/SET OF types"));
3771 bool Type::is_compatible_array(Type
*p_type
, TypeCompatInfo
*p_info
,
3772 TypeChain
*p_left_chain
,
3773 TypeChain
*p_right_chain
,
3774 bool p_is_inline_template
)
3776 if (typetype
!= T_ARRAY
) FATAL_ERROR("Type::is_compatible_array()");
3777 // Copied from the original checker code. The type of the elements and
3778 // the dimension of the array must be the same.
3779 if (this == p_type
) return true;
3780 if (p_type
->typetype
== T_ARRAY
&& u
.array
.element_type
3781 ->is_compatible(p_type
->u
.array
.element_type
, NULL
, NULL
, NULL
, p_is_inline_template
)
3782 && u
.array
.dimension
->is_identical(p_type
->u
.array
.dimension
))
3784 else if (!use_runtime_2
|| !p_info
3785 || (p_info
&& p_info
->is_strict())) return false;
3786 Type
*of_type
= get_ofType()->get_type_refd_last();
3787 switch (p_type
->get_typetype()) {
3790 if (of_type
->get_typetype() == T_ARRAY
) {
3791 p_info
->set_is_erroneous(this, p_type
, string("record/SEQUENCE types are "
3792 "compatible only with single-dimension "
3796 size_t p_nof_comps
= p_type
->get_nof_comps();
3797 size_t p_nof_opt_fields
= 0;
3798 for (size_t i
= 0; i
< p_nof_comps
; i
++)
3799 if (p_type
->get_comp_byIndex(i
)->get_is_optional())
3801 if (u
.array
.dimension
->get_size() < p_nof_comps
- p_nof_opt_fields
) {
3802 p_info
->set_is_erroneous(this, p_type
, string("The dimension of the array "
3803 "must be >= than the number of mandatory "
3804 "fields in the record/SEQUENCE type"));
3807 if (p_left_chain
->empty()) p_left_chain
->add(this);
3808 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3809 for (size_t i
= 0; i
< p_nof_comps
; ++i
) {
3810 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3811 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3812 string p_cf_name
= p_cf
->get_name().get_dispname();
3813 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3815 p_left_chain
->mark_state();
3816 p_right_chain
->mark_state();
3817 p_left_chain
->add(of_type
);
3818 p_right_chain
->add(p_cf_type
);
3819 if (of_type
!= p_cf_type
3820 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3821 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3822 p_right_chain
, p_is_inline_template
)) {
3823 p_info
->append_ref_str(0, info_tmp
.get_ref_str(0));
3824 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3825 info_tmp
.get_ref_str(1));
3826 p_info
->set_is_erroneous(info_tmp
.get_type(0),
3827 info_tmp
.get_type(1),
3828 info_tmp
.get_error_str());
3829 p_left_chain
->previous_state();
3830 p_right_chain
->previous_state();
3833 p_left_chain
->previous_state();
3834 p_right_chain
->previous_state();
3836 if (!p_is_inline_template
) {
3837 p_info
->set_needs_conversion(true);
3838 p_info
->add_type_conversion(p_type
, this);
3842 if (!p_type
->is_subtype_length_compatible(this)) {
3843 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3844 "record of/SEQUENCE OF subtypes"));
3848 if (p_type
->get_typetype() == T_ARRAY
3849 && !u
.array
.dimension
->is_identical(p_type
->u
.array
.dimension
)) {
3850 p_info
->set_is_erroneous(this, p_type
, string("Array types should have "
3851 "the same dimension"));
3854 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3855 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3857 if (p_left_chain
->empty()) p_left_chain
->add(this);
3858 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3859 p_left_chain
->mark_state();
3860 p_right_chain
->mark_state();
3861 p_left_chain
->add(of_type
);
3862 p_right_chain
->add(p_of_type
);
3863 if (of_type
== p_of_type
3864 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3865 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3866 p_right_chain
, p_is_inline_template
)) {
3867 if (!p_is_inline_template
) {
3868 p_info
->set_needs_conversion(true);
3869 p_info
->add_type_conversion(p_type
, this);
3871 p_left_chain
->previous_state();
3872 p_right_chain
->previous_state();
3875 p_left_chain
->previous_state();
3876 p_right_chain
->previous_state();
3877 p_info
->append_ref_str(0, info_tmp
.get_ref_str(0));
3878 if (p_type
->get_typetype() != T_ARRAY
) p_info
->append_ref_str(1, string("[]"));
3879 p_info
->append_ref_str(1, info_tmp
.get_ref_str(1));
3880 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3881 info_tmp
.get_error_str());
3886 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3887 "compatible only with other "
3888 "union/CHOICE/anytype types"));
3893 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3894 "types are compatible only with other set/SET "
3895 "set of/SET OF types"));
3902 bool Type::is_compatible_set(Type
*p_type
, TypeCompatInfo
*p_info
,
3903 TypeChain
*p_left_chain
,
3904 TypeChain
*p_right_chain
,
3905 bool p_is_inline_template
)
3907 if (typetype
!= T_SET_A
&& typetype
!= T_SET_T
)
3908 FATAL_ERROR("Type::is_compatible_set()");
3909 if (this == p_type
) return true;
3910 else if (!use_runtime_2
|| !p_info
3911 || (p_info
&& p_info
->is_strict())) return false;
3912 size_t nof_comps
= get_nof_comps();
3913 switch (p_type
->typetype
) {
3916 // The standard is very generous. We don't need to check for a possible
3917 // combination of compatible fields. According to 6.3.2.3, simply do
3918 // the same thing as for T_SEQ_{A,T} types. The fields are in their
3920 size_t p_nof_comps
= p_type
->get_nof_comps();
3921 if (nof_comps
!= p_nof_comps
) {
3922 p_info
->set_is_erroneous(this, p_type
, string("The number of fields in "
3923 "set/SET types must be the same"));
3926 if (p_left_chain
->empty()) p_left_chain
->add(this);
3927 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3928 for (size_t i
= 0; i
< nof_comps
; i
++) {
3929 CompField
*cf
= get_comp_byIndex(i
);
3930 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3931 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
3932 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3933 string cf_name
= cf
->get_name().get_dispname();
3934 string p_cf_name
= p_cf
->get_name().get_dispname();
3935 if (cf
->get_is_optional() != p_cf
->get_is_optional()) {
3936 p_info
->append_ref_str(0, "." + cf_name
);
3937 p_info
->append_ref_str(1, "." + p_cf_name
);
3938 p_info
->set_is_erroneous(cf_type
, p_cf_type
, string("The optionality of "
3939 "fields in set/SET types must be the "
3943 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
3945 p_left_chain
->mark_state();
3946 p_right_chain
->mark_state();
3947 p_left_chain
->add(cf_type
);
3948 p_right_chain
->add(p_cf_type
);
3949 if (cf_type
!= p_cf_type
3950 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3951 && !cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3952 p_right_chain
, p_is_inline_template
)) {
3953 p_info
->append_ref_str(0, "." + cf_name
+ info_tmp
.get_ref_str(0));
3954 p_info
->append_ref_str(1, "." + p_cf_name
+ info_tmp
.get_ref_str(1));
3955 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3956 info_tmp
.get_error_str());
3957 p_left_chain
->previous_state();
3958 p_right_chain
->previous_state();
3961 p_left_chain
->previous_state();
3962 p_right_chain
->previous_state();
3964 if (!p_is_inline_template
) {
3965 p_info
->set_needs_conversion(true);
3966 p_info
->add_type_conversion(p_type
, this);
3970 if (!p_type
->is_subtype_length_compatible(this)) {
3971 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
3975 if (p_left_chain
->empty()) p_left_chain
->add(this);
3976 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3977 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3978 for (size_t i
= 0; i
< nof_comps
; i
++) {
3979 Type
*cf_type
= get_comp_byIndex(i
)->get_type()->get_type_refd_last();
3980 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_of_type
,
3982 p_left_chain
->mark_state();
3983 p_right_chain
->mark_state();
3984 p_left_chain
->add(cf_type
);
3985 p_right_chain
->add(p_of_type
);
3986 if (cf_type
!= p_of_type
3987 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3988 && !cf_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3989 p_right_chain
, p_is_inline_template
)) {
3990 p_info
->append_ref_str(0, "." + get_comp_byIndex(i
)
3991 ->get_name().get_dispname() + info_tmp
.get_ref_str(0));
3992 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
3993 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3994 info_tmp
.get_error_str());
3995 p_left_chain
->previous_state();
3996 p_right_chain
->previous_state();
3999 p_left_chain
->previous_state();
4000 p_right_chain
->previous_state();
4002 if (!p_is_inline_template
) {
4003 p_info
->set_needs_conversion(true);
4004 p_info
->add_type_conversion(p_type
, this);
4010 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
4011 "compatible only with other "
4012 "union/CHOICE/anytype types"));
4018 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
4019 "types are compatible only with other set/SET "
4020 "set of/SET OF types"));
4027 bool Type::is_compatible_set_of(Type
*p_type
, TypeCompatInfo
*p_info
,
4028 TypeChain
*p_left_chain
,
4029 TypeChain
*p_right_chain
,
4030 bool p_is_inline_template
)
4032 if (typetype
!= T_SETOF
) FATAL_ERROR("Type::is_compatible_set_of()");
4033 if (this == p_type
) return true;
4034 else if (T_SETOF
== p_type
->get_type_refd_last()->typetype
&&
4035 is_pregenerated() && p_type
->is_pregenerated() &&
4036 get_ofType()->get_type_refd_last()->typetype
==
4037 p_type
->get_ofType()->get_type_refd_last()->typetype
&&
4038 (use_runtime_2
|| get_optimize_attribute() == p_type
->get_optimize_attribute())) {
4039 // Pre-generated set-ofs of the same element type are compatible with
4040 // each other (in RT1 optimized set-ofs are not compatible with non-optimized ones)
4041 if (!is_subtype_length_compatible(p_type
)) {
4042 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
4043 "set of/SET OF subtypes"));
4048 else if (!use_runtime_2
|| !p_info
4049 || (p_info
&& p_info
->is_strict())) return false;
4050 Type
*of_type
= get_ofType();
4051 switch (p_type
->get_typetype()) {
4054 if (!is_subtype_length_compatible(p_type
)) {
4055 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
4059 if (p_left_chain
->empty()) p_left_chain
->add(this);
4060 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4061 for (size_t i
= 0; i
< p_type
->get_nof_comps(); i
++) {
4062 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
4063 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
4064 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
4066 p_left_chain
->mark_state();
4067 p_right_chain
->mark_state();
4068 p_left_chain
->add(of_type
);
4069 p_right_chain
->add(p_cf_type
);
4070 if (of_type
!= p_cf_type
4071 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4072 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
4073 p_right_chain
, p_is_inline_template
)) {
4074 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
4075 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
4076 info_tmp
.get_ref_str(1));
4077 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
4078 info_tmp
.get_error_str());
4079 p_left_chain
->previous_state();
4080 p_right_chain
->previous_state();
4083 p_left_chain
->previous_state();
4084 p_right_chain
->previous_state();
4086 if (!p_is_inline_template
) {
4087 p_info
->set_needs_conversion(true);
4088 p_info
->add_type_conversion(p_type
, this);
4092 if (!is_subtype_length_compatible(p_type
)) {
4093 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
4097 if (p_left_chain
->empty()) p_left_chain
->add(this);
4098 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4099 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
4100 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
4102 p_left_chain
->mark_state();
4103 p_right_chain
->mark_state();
4104 p_left_chain
->add(of_type
);
4105 p_right_chain
->add(p_of_type
);
4106 if (of_type
== p_of_type
4107 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4108 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
4109 p_right_chain
, p_is_inline_template
)) {
4110 if (!p_is_inline_template
) {
4111 p_info
->set_needs_conversion(true);
4112 p_info
->add_type_conversion(p_type
, this);
4114 p_left_chain
->previous_state();
4115 p_right_chain
->previous_state();
4118 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
4119 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
4120 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
4121 info_tmp
.get_error_str());
4122 p_left_chain
->previous_state();
4123 p_right_chain
->previous_state();
4128 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype "
4129 "types are compatible only with other "
4130 "union/CHOICE/anytype types"));
4136 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
4137 "types are compatible only with other set/SET "
4138 "set of/SET OF types"));
4145 bool Type::is_compatible_choice_anytype(Type
*p_type
,
4146 TypeCompatInfo
*p_info
,
4147 TypeChain
*p_left_chain
,
4148 TypeChain
*p_right_chain
,
4149 bool p_is_inline_template
)
4151 if (typetype
!= T_ANYTYPE
&& typetype
!= T_CHOICE_A
4152 && typetype
!= T_CHOICE_T
)
4153 FATAL_ERROR("Type::is_compatible_choice_anytype()");
4154 if (this == p_type
) return true; // Original "true" leaf...
4155 else if (!use_runtime_2
|| !p_info
4156 || (p_info
&& p_info
->is_strict())) return false; // ...and "false".
4157 if ((typetype
== T_ANYTYPE
&& p_type
->get_typetype() != T_ANYTYPE
)
4158 || (p_type
->get_typetype() == T_ANYTYPE
&& typetype
!= T_ANYTYPE
)) {
4159 p_info
->set_is_erroneous(this, p_type
, string("Type anytype is compatible only "
4160 "with other anytype types"));
4163 switch (p_type
->get_typetype()) {
4171 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
4172 "compatible only with other union/CHOICE/anytype "
4177 if (typetype
!= T_CHOICE_A
&& typetype
!= T_CHOICE_T
) {
4178 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE types are "
4179 "compatible only with other union/CHOICE "
4185 if (p_left_chain
->empty()) p_left_chain
->add(this);
4186 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4187 // Find a field with the same name and with compatible type. There can
4188 // be more alternatives, we need to generate all conversion functions.
4189 // The same field types must be avoided. (For anytypes the "field
4190 // name = module name + field name".)
4191 bool alles_okay
= false;
4192 for (size_t i
= 0; i
< get_nof_comps(); i
++) {
4193 CompField
*cf
= get_comp_byIndex(i
);
4194 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
4195 for (size_t j
= 0; j
< p_type
->get_nof_comps(); ++j
) {
4196 CompField
*p_cf
= p_type
->get_comp_byIndex(j
);
4197 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
4198 if (cf
->get_name().get_name() != p_cf
->get_name().get_name())
4200 // Don't report errors for each incompatible field, it would be a
4201 // complete mess. Use this temporary for all fields. And forget
4203 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
4205 p_left_chain
->mark_state();
4206 p_right_chain
->mark_state();
4207 p_left_chain
->add(cf_type
);
4208 p_right_chain
->add(p_cf_type
);
4209 if (cf_type
== p_cf_type
4210 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4211 || cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
4212 p_right_chain
, p_is_inline_template
)) {
4213 if (cf_type
!= p_cf_type
&& cf_type
->is_structured_type()
4214 && p_cf_type
->is_structured_type()) {
4215 if (typetype
== T_ANYTYPE
&& cf_type
->get_my_scope()
4216 ->get_scope_mod() != p_cf_type
->get_my_scope()
4217 ->get_scope_mod()) {
4218 p_left_chain
->previous_state();
4219 p_right_chain
->previous_state();
4222 p_info
->add_type_conversion(p_cf_type
, cf_type
);
4226 p_left_chain
->previous_state();
4227 p_right_chain
->previous_state();
4230 if (alles_okay
&& !p_is_inline_template
) {
4231 p_info
->set_needs_conversion(true);
4232 p_info
->add_type_conversion(p_type
, this);
4235 p_info
->set_is_erroneous(this, p_type
, string("No compatible "
4236 "union/CHOICE/anytype field found"));
4244 /** \todo consider subtype constraints */
4245 bool Type::is_identical(Type
*p_type
)
4249 Type
*t1
= get_type_refd_last();
4250 Type
*t2
= p_type
->get_type_refd_last();
4251 if (t2
->typetype
== T_ERROR
) return true;
4252 switch (t1
->typetype
) {
4254 // error type is identical to everything
4274 // user-defined structured types must be identical
4277 // the embedded type and the dimension must be identical in case of arrays
4278 return t2
->typetype
== T_ARRAY
&&
4279 t1
->u
.array
.element_type
->is_identical(t2
->u
.array
.element_type
) &&
4280 t1
->u
.array
.dimension
->is_identical(t2
->u
.array
.dimension
);
4282 // in case of built-in types the TTCN-3 view of typetype must be the same
4283 return get_typetype_ttcn3(t1
->typetype
) ==
4284 get_typetype_ttcn3(t2
->typetype
);
4288 void Type::tr_compsof(ReferenceChain
*refch
)
4290 if (typetype
!=T_SEQ_A
&& typetype
!=T_SET_A
)
4291 FATAL_ERROR("Type::tr_compsof()");
4292 if (u
.secho
.tr_compsof_ready
) return;
4293 if (u
.secho
.block
) parse_block_Se();
4294 bool auto_tagging
=u
.secho
.ctss
->needs_auto_tags();
4296 refch
->mark_state();
4297 if (refch
->add(get_fullname())) u
.secho
.ctss
->tr_compsof(refch
, false);
4298 refch
->prev_state();
4299 u
.secho
.tr_compsof_ready
= true;
4300 u
.secho
.ctss
->tr_compsof(0, true);
4302 ReferenceChain
refch2(this, "While resolving COMPONENTS OF");
4303 refch2
.add(get_fullname());
4304 Error_Context
cntxt(this, "While resolving COMPONENTS OF");
4305 u
.secho
.ctss
->tr_compsof(&refch2
, false);
4306 u
.secho
.tr_compsof_ready
= true;
4307 u
.secho
.ctss
->tr_compsof(0, true);
4309 if(auto_tagging
) u
.secho
.ctss
->add_auto_tags();
4312 bool Type::is_startable()
4314 if(typetype
!= T_FUNCTION
)
4315 FATAL_ERROR("Type::is_startable()");
4317 return u
.fatref
.is_startable
;
4320 bool Type::is_list_type(bool allow_array
)
4322 switch (get_type_refd_last()->get_typetype_ttcn3()) {
4338 void Type::set_coding_function(bool encode
, const string
& function_name
)
4340 string
& coding_str
= encode
? encoding_str
: decoding_str
;
4341 if (!coding_str
.empty()) {
4342 error("Multiple custom %s functions declared for type '%s' (function `%s' "
4343 "is already set)", encode
? "encoding" : "decoding",
4344 get_typename().c_str(), coding_str
.c_str());
4347 coding_str
= function_name
;
4348 coding_by_function
= true;
4351 void Type::chk_coding(bool encode
, bool delayed
/* = false */) {
4352 string
& coding_str
= encode
? encoding_str
: decoding_str
;
4353 if (!coding_str
.empty())
4355 coding_by_function
= false;
4357 if (!w_attrib_path
) {
4358 error("No coding rule specified for type '%s'", get_typename().c_str());
4361 Type::MessageEncodingType_t coding
= CT_UNDEF
;
4363 // Checking extension attributes
4364 Ttcn::ExtensionAttributes
* extatrs
= parse_extattributes(w_attrib_path
);
4365 if (extatrs
!= 0) { // NULL means parsing error
4366 for (size_t k
= 0; k
< extatrs
->size(); ++k
) {
4367 Ttcn::ExtensionAttribute
&ea
= extatrs
->get(k
);
4368 Ttcn::TypeMappings
*inmaps
= 0, *maps
= 0;
4369 Ttcn::TypeMapping
* mapping
= 0;
4370 Ttcn::TypeMappingTarget
* target
= 0;
4372 switch (ea
.get_type()) {
4373 case Ttcn::ExtensionAttribute::ENCDECVALUE
:
4374 ea
.get_encdecvalue_mappings(inmaps
, maps
);
4375 maps
= encode
? maps
: inmaps
;
4376 maps
->set_my_scope(this->get_my_scope());
4378 // look for coding settings
4379 t
= encode
? this : Type::get_pooltype(T_BSTR
);
4380 mapping
= maps
->get_mapping_byType(t
);
4381 if (mapping
->get_nof_targets() == 0)
4384 for (size_t ind
= 0; ind
< mapping
->get_nof_targets(); ind
++) {
4385 target
= mapping
->get_target_byIndex(ind
);
4386 t
= target
->get_target_type();
4387 if ((encode
&& (t
->get_typetype() == T_BSTR
)) ||
4388 (!encode
&& (t
->get_typename() == this->get_typename())))
4390 if (target
->get_mapping_type() ==
4391 Ttcn::TypeMappingTarget::TM_FUNCTION
) {
4392 if (!coding_str
.empty())
4393 target
->error("Multiple definition of this target");
4394 coding_str
= target
->get_function()->
4395 get_genname_from_scope(my_scope
);
4396 coding_by_function
= true;
4398 target
->error("Only function is supported to do this mapping");
4402 if (coding_str
.empty()) {
4403 ea
.warning("Extension attribute is found for %s but without "
4404 "typemappings", encode
? "encvalue" : "decvalue");
4409 case Ttcn::ExtensionAttribute::ANYTYPELIST
:
4410 break; // ignore (may be inherited from the module)
4412 case Ttcn::ExtensionAttribute::NONE
:
4413 break; // ignore erroneous attribute
4416 ea
.error("A type can only have type mapping extension attribute: "
4417 "in(...) or out(...)");
4424 if (!coding_str
.empty())
4428 const vector
<SingleWithAttrib
>& real_attribs
4429 = w_attrib_path
->get_real_attrib();
4431 for (size_t i
= real_attribs
.size(); i
> 0 && !found
; i
--) {
4432 if (real_attribs
[i
-1]->get_attribKeyword()
4433 == SingleWithAttrib::AT_ENCODE
) {
4435 coding
= get_enc_type(*real_attribs
[i
-1]);
4438 if (coding
== CT_UNDEF
) {
4439 // no "encode" attribute found
4440 error("No coding rule specified for type '%s'", get_typename().c_str());
4443 if (coding
!= CT_CUSTOM
&& !has_encoding(coding
)) {
4444 error("Type '%s' cannot be coded with the selected method '%s'",
4445 get_typename().c_str(),
4446 get_encoding_name(coding
));
4454 coding_str
= "TEXT";
4460 coding_str
= "XER, XER_EXTENDED"; // TODO: fine tuning this parameter
4463 coding_str
= "JSON";
4466 coding_str
= "BER, ";
4467 BerAST
* ber
= berattrib
;
4468 if (!ber
) // use default settings if attributes are not specified
4471 coding_str
+= ber
->get_encode_str();
4473 coding_str
+= ber
->get_decode_str();
4479 // coding_str is set by the coding function's checker in this case;
4480 // it's possible, that the function exists, but has not been reached yet;
4481 // delay this function until everything else has been checked
4482 Modules::delay_type_encode_check(this, encode
);
4484 else if (coding_str
.empty()) {
4485 // this is the delayed call, and the custom coding function has still
4487 error("No custom %s function found for type `%s'",
4488 encode
? "encoding" : "decoding", get_typename().c_str());
4492 error("Unknown coding selected for type '%s'", get_typename().c_str());
4495 coding_by_function
= false;
4498 bool Type::is_coding_by_function() const {
4499 return coding_by_function
;
4502 const string
& Type::get_coding(bool encode
) const {
4504 return encoding_str
;
4506 return decoding_str
;
4509 namespace { // unnamed
4510 const string
ex_emm_ell("XML"), ex_ee_arr("XER");
4513 Type::MessageEncodingType_t
Type::get_enc_type(const SingleWithAttrib
& atr
) {
4514 const string
& enc
= atr
.get_attribSpec().get_spec();
4517 else if (enc
== "TEXT")
4519 else if (enc
== "JSON")
4521 else if (enc
== "BER:2002" || enc
== "CER:2002" || enc
== "DER:2002")
4523 else if (enc
== ex_emm_ell
)
4525 else if (enc
== ex_ee_arr
) {
4526 atr
.warning("The correct name of the encoding is ''XML''");
4529 else if (enc
== "PER")
4534 bool Type::has_ei_withName(const Identifier
& p_id
) const
4542 FATAL_ERROR("Type::has_ei_withName()");
4544 return u
.enums
.eis
->has_ei_withName(p_id
);
4547 EnumItem
*Type::get_ei_byName(const Identifier
& p_id
) const
4555 FATAL_ERROR("Type::get_ei_byName()");
4557 return u
.enums
.eis
->get_ei_byName(p_id
);
4560 EnumItem
*Type::get_ei_byIndex(size_t n
) const
4568 FATAL_ERROR("Type::get_ei_byIndex()");
4570 return u
.enums
.eis
->get_ei_byIndex(n
);
4573 size_t Type::get_nof_comps()
4581 return u
.secho
.cfm
->get_nof_comps();
4584 if(u
.secho
.block
) parse_block_Se();
4585 return u
.secho
.ctss
->get_nof_comps();
4587 if(u
.secho
.block
) parse_block_Choice();
4588 return u
.secho
.ctss
->get_nof_comps();
4590 return u
.array
.dimension
->get_size();
4592 if (u
.signature
.parameters
)
4593 return u
.signature
.parameters
->get_nof_params();
4596 FATAL_ERROR("Type::get_nof_comps(%d)", typetype
);
4601 const Identifier
& Type::get_comp_id_byIndex(size_t n
)
4609 return u
.secho
.cfm
->get_comp_byIndex(n
)->get_name();
4612 if(u
.secho
.block
) parse_block_Se();
4613 return u
.secho
.ctss
->get_comp_byIndex(n
)->get_name();
4615 if(u
.secho
.block
) parse_block_Choice();
4616 return u
.secho
.ctss
->get_comp_byIndex(n
)->get_name();
4618 return u
.signature
.parameters
->get_param_byIndex(n
)->get_id();
4620 FATAL_ERROR("Type::get_comp_id_byIndex()");
4622 // to avoid warnings
4623 const Identifier
*fake
= 0;
4627 CompField
* Type::get_comp_byIndex(size_t n
)
4635 return u
.secho
.cfm
->get_comp_byIndex(n
);
4638 if(u
.secho
.block
) parse_block_Se();
4639 return u
.secho
.ctss
->get_comp_byIndex(n
);
4641 if(u
.secho
.block
) parse_block_Choice();
4642 return u
.secho
.ctss
->get_comp_byIndex(n
);
4644 FATAL_ERROR("Type::get_comp_byIndex()");
4649 size_t Type::get_comp_index_byName(const Identifier
& p_name
)
4651 Type
*t
= get_type_refd_last();
4653 FATAL_ERROR("Type::get_comp_index_byName()");
4654 if (!t
->u
.secho
.field_by_name
) {
4655 t
->u
.secho
.field_by_name
= new map
<string
, size_t>;
4656 size_t nof_comps
= t
->get_nof_comps();
4657 for (size_t i
= 0; i
< nof_comps
; i
++) {
4658 const string
& field_name
=
4659 t
->get_comp_byIndex(i
)->get_name().get_name();
4660 if (!t
->u
.secho
.field_by_name
->has_key(field_name
))
4661 t
->u
.secho
.field_by_name
->add(field_name
, new size_t(i
));
4664 return *(*t
->u
.secho
.field_by_name
)[p_name
.get_name()];
4667 size_t Type::get_eis_index_byName(const Identifier
& p_name
)
4669 Type
*t
= get_type_refd_last();
4670 switch (t
->typetype
) {
4675 FATAL_ERROR("Type::get_eis_index_byName()");
4677 if (!t
->u
.enums
.eis_by_name
) {
4678 t
->u
.enums
.eis_by_name
= new map
<string
, size_t>;
4679 size_t nof_eis
= t
->u
.enums
.eis
->get_nof_eis();
4680 for (size_t i
= 0; i
< nof_eis
; i
++) {
4681 const string
& enum_name
=
4682 t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name().get_name();
4683 if (!t
->u
.enums
.eis_by_name
->has_key(enum_name
))
4684 t
->u
.enums
.eis_by_name
->add(enum_name
, new size_t(i
));
4687 return *(*t
->u
.enums
.eis_by_name
)[p_name
.get_name()];
4690 const Int
& Type::get_enum_val_byId(const Identifier
& p_name
)
4692 if(!checked
) FATAL_ERROR("Type::get_enum_val_byId(): Not checked.");
4698 FATAL_ERROR("Type::get_enum_val_byId()");
4700 return u
.enums
.eis
->get_ei_byName(p_name
)->get_value()
4701 ->get_value_refd_last()->get_val_Int()->get_val();
4704 size_t Type::get_nof_root_comps()
4709 if(u
.secho
.block
) parse_block_Se();
4710 return u
.secho
.ctss
->get_nof_root_comps();
4713 FATAL_ERROR("Type::get_nof_root_comps()");
4718 CompField
* Type::get_root_comp_byIndex(size_t n
)
4723 if(u
.secho
.block
) parse_block_Se();
4724 return u
.secho
.ctss
->get_root_comp_byIndex(n
);
4727 FATAL_ERROR("Type::get_root_comp_byIndex()");
4732 bool Type::has_comp_withName(const Identifier
& p_name
)
4734 Type
*t
= get_type_refd_last();
4735 switch (t
->typetype
) {
4741 return t
->u
.secho
.cfm
->has_comp_withName(p_name
);
4744 if (t
->u
.secho
.block
) t
->parse_block_Se();
4745 return t
->u
.secho
.ctss
->has_comp_withName(p_name
);
4747 if (t
->u
.secho
.block
) t
->parse_block_Choice();
4748 return t
->u
.secho
.ctss
->has_comp_withName(p_name
);
4750 if (t
->u
.signature
.parameters
)
4751 return t
->u
.signature
.parameters
->has_param_withName(p_name
);
4754 FATAL_ERROR("Type::has_comp_withName()");
4759 CompField
* Type::get_comp_byName(const Identifier
& p_name
)
4761 Type
*t
= get_type_refd_last();
4762 switch (t
->typetype
) {
4768 return t
->u
.secho
.cfm
->get_comp_byName(p_name
);
4771 if (t
->u
.secho
.block
) t
->parse_block_Se();
4772 return t
->u
.secho
.ctss
->get_comp_byName(p_name
);
4774 if(t
->u
.secho
.block
) t
->parse_block_Choice();
4775 return t
->u
.secho
.ctss
->get_comp_byName(p_name
);
4777 FATAL_ERROR("Type::get_comp_byName()");
4782 void Type::add_comp(CompField
*p_cf
)
4790 u
.secho
.cfm
->add_comp(p_cf
);
4793 FATAL_ERROR("Type::add_comp()");
4797 Type
*Type::get_ofType()
4799 Type
*t
=get_type_refd_last();
4800 switch (t
->typetype
) {
4803 return t
->u
.seof
.ofType
;
4805 return t
->u
.array
.element_type
;
4807 FATAL_ERROR("Type::get_ofType()");
4812 OC_defn
* Type::get_my_oc()
4816 return u
.ref
.oc_defn
;
4819 return u
.secho
.oc_defn
;
4822 FATAL_ERROR("Type::get_my_oc()");
4827 const Identifier
& Type::get_oc_fieldname()
4831 return *u
.ref
.oc_fieldname
;
4834 return *u
.secho
.oc_fieldname
;
4837 FATAL_ERROR("Type::get_oc_fieldname()");
4838 // to avoid warning...
4839 return *u
.secho
.oc_fieldname
;
4843 void Type::set_my_tableconstraint(const TableConstraint
*p_tc
)
4847 u
.secho
.my_tableconstraint
=p_tc
;
4850 FATAL_ERROR("Type::set_my_tableconstraint()");
4854 const TableConstraint
* Type::get_my_tableconstraint()
4858 return u
.secho
.my_tableconstraint
;
4861 FATAL_ERROR("Type::get_my_tableconstraint()");
4866 Ttcn::ArrayDimension
*Type::get_dimension() const
4868 if (typetype
!= T_ARRAY
) FATAL_ERROR("Type::get_dimension()");
4869 return u
.array
.dimension
;
4872 Ttcn::PortTypeBody
*Type::get_PortBody() const
4874 if (typetype
!= T_PORT
) FATAL_ERROR("Type::get_PortBody()");
4878 ComponentTypeBody
*Type::get_CompBody() const
4880 if (typetype
!= T_COMPONENT
) FATAL_ERROR("Type::get_CompBody()");
4884 SignatureParamList
*Type::get_signature_parameters() const
4886 if (typetype
!= T_SIGNATURE
|| !checked
)
4887 FATAL_ERROR("Type::get_signature_parameters()");
4888 return u
.signature
.parameters
;
4891 SignatureExceptions
*Type::get_signature_exceptions() const
4893 if (typetype
!= T_SIGNATURE
|| !checked
)
4894 FATAL_ERROR("Type::get_signature_exceptions()");
4895 return u
.signature
.exceptions
;
4898 Type
*Type::get_signature_return_type() const
4900 if (typetype
!= T_SIGNATURE
|| !checked
)
4901 FATAL_ERROR("Type::get_signature_return_type()");
4902 return u
.signature
.return_type
;
4905 bool Type::is_nonblocking_signature() const
4907 if (typetype
!= T_SIGNATURE
|| !checked
)
4908 FATAL_ERROR("Type::is_nonblocking_signature()");
4909 return u
.signature
.no_block
;
4912 Ttcn::FormalParList
*Type::get_fat_parameters()
4914 if(!checked
) FATAL_ERROR("Type::get_fat_parameteres()");
4919 return u
.fatref
.fp_list
;
4921 FATAL_ERROR("Type::get_fat_parameteres()");
4926 Type
*Type::get_function_return_type()
4928 if(!checked
) FATAL_ERROR("Type::get_function_return_type()");
4931 return u
.fatref
.return_type
;
4933 FATAL_ERROR("Type::get_function_return_type()");
4938 Type
*Type::get_fat_runs_on_type()
4940 if(!checked
) FATAL_ERROR("Type::get_fat_runs_on_type()");
4945 return u
.fatref
.runs_on
.type
;
4947 FATAL_ERROR("Type::get_fat_runs_on_type()");
4952 bool Type::get_fat_runs_on_self()
4954 if(!checked
) FATAL_ERROR("Type::get_fat_runs_on_self()");
4959 return u
.fatref
.runs_on
.self
;
4961 FATAL_ERROR("Type::get_fat_runs_on_self()");
4966 bool Type::get_returns_template()
4968 if (!checked
|| typetype
!= T_FUNCTION
)
4969 FATAL_ERROR("Type::Returns_template()");
4970 return u
.fatref
.returns_template
;
4973 void Type::add_tag(Tag
*p_tag
)
4975 if(!tags
) tags
=new Tags();
4976 tags
->add_tag(p_tag
);
4979 void Type::add_constraints(Constraints
*p_constraints
)
4981 if(!p_constraints
) return;
4983 FATAL_ERROR("This type already has its constraints");
4984 constraints
=p_constraints
;
4985 constraints
->set_my_type(this);
4988 Reference
* Type::get_Reference()
4993 void Type::chk_table_constraints()
4995 if(!tbl_cons_checked
) {
4996 tbl_cons_checked
=true;
4997 if (constraints
) constraints
->chk_table();
5006 for(size_t i
=0; i
<get_nof_comps(); i
++)
5007 get_comp_byIndex(i
)->get_type()->chk_table_constraints();
5011 u
.seof
.ofType
->chk_table_constraints();
5019 void Type::check_subtype_constraints()
5021 if (sub_type
!=NULL
) FATAL_ERROR("Type::check_subtype_constraints()");
5023 // get parent subtype or NULL if it doesn't exist
5024 SubType
* parent_subtype
= NULL
;
5025 if (is_ref()) parent_subtype
= get_type_refd()->sub_type
;
5027 // if the parent subtype is erroneous then ignore it, the error was already
5029 if ( (parent_subtype
!=NULL
) &&
5030 (parent_subtype
->get_subtypetype()==SubtypeConstraint::ST_ERROR
) )
5031 parent_subtype
= NULL
;
5033 // return if there are neither inherited nor own constraints
5034 if ( (parent_subtype
==NULL
) && (parsed_restr
==NULL
) && (constraints
==NULL
)
5035 && (SubtypeConstraint::get_asn_type_constraint(this)==NULL
) ) return;
5037 // the subtype type is determined by the type of this type
5038 if (get_type_refd_last()->get_typetype()==T_ERROR
) return;
5039 SubtypeConstraint::subtype_t s_t
= get_subtype_type();
5040 if (s_t
==SubtypeConstraint::ST_ERROR
) {
5041 error("Subtype constraints are not applicable to type `%s'",
5042 get_typename().c_str());
5046 // create the aggregate subtype for this type
5047 sub_type
= new SubType(s_t
, this, parent_subtype
, parsed_restr
, constraints
);
5051 bool Type::has_multiple_tags()
5053 if (tags
) return false;
5062 return get_type_refd()->has_multiple_tags();
5068 Tag
*Type::get_tag()
5071 Tag
*tag
=tags
->get_tag_byIndex(tags
->get_nof_tags()-1);
5075 else return get_default_tag();
5078 void Type::get_tags(TagCollection
& coll
, map
<Type
*, void>& chain
)
5080 if(typetype
!=T_CHOICE_A
)
5081 FATAL_ERROR("Type::get_tags()");
5082 if (chain
.has_key(this)) return;
5084 if(u
.secho
.block
) parse_block_Choice();
5085 size_t n_alts
= u
.secho
.ctss
->get_nof_comps();
5086 for(size_t i
=0; i
<n_alts
; i
++) {
5087 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
5088 Type
*type
= cf
->get_type();
5089 if(type
->has_multiple_tags()) {
5090 type
=type
->get_type_refd_last();
5091 type
->get_tags(coll
, chain
);
5094 const Tag
*tag
=type
->get_tag();
5095 if(coll
.hasTag(tag
))
5096 error("Alternative `%s' in CHOICE has non-distinct tag",
5097 cf
->get_name().get_dispname().c_str());
5098 else coll
.addTag(tag
);
5101 if(u
.secho
.ctss
->has_ellipsis()) coll
.setExtensible();
5104 Tag
*Type::get_smallest_tag()
5106 if(!has_multiple_tags()) return get_tag()->clone();
5107 Type
*t
=get_type_refd_last();
5108 TagCollection tagcoll
;
5109 map
<Type
*, void> chain
;
5110 t
->get_tags(tagcoll
, chain
);
5112 return tagcoll
.getSmallestTag()->clone();
5115 bool Type::needs_explicit_tag()
5124 if(!dynamic_cast<Asn::Ref_pard
*>(u
.ref
.ref
)) {
5125 Scope
*s
=u
.ref
.ref
->get_refd_assignment()->get_my_scope();
5126 if(s
->get_parent_scope()!=s
->get_scope_mod()) {
5127 // Not in the module scope, so it is a dummyreference (X.680
5130 WARNING("%s is a dummyreference, i give him an explicit tag :)",
5131 get_fullname().c_str());
5132 WARNING("0: %s", s->get_scope_name().c_str());
5133 WARNING("1: %s", s->get_parent_scope()->get_scope_name().c_str());
5134 WARNING("2: %s", s->get_scope_mod()->get_scope_name().c_str());
5144 Type
*t
= get_type_refd();
5145 if(t
->is_tagged()) return false;
5146 else return t
->needs_explicit_tag();
5149 // T_ANYTYPE probably does not need explicit tagging
5154 void Type::cut_auto_tags()
5157 tags
->cut_auto_tags();
5158 if (tags
->get_nof_tags() == 0) {
5166 * I suppose in this function that tags->chk() and
5167 * tags->set_plicit() are already done.
5169 Tags
* Type::build_tags_joined(Tags
*p_tags
)
5171 if(!p_tags
) p_tags
=new Tags();
5178 get_type_refd()->build_tags_joined(p_tags
);
5182 //TODO case T_ANYTYPE: for build_tags_joined ?
5187 p_tags
->add_tag(get_default_tag()->clone());
5191 for(size_t i
=0; i
<tags
->get_nof_tags(); i
++) {
5192 Tag
*tag
=tags
->get_tag_byIndex(i
);
5193 switch(tag
->get_plicit()) {
5194 case Tag::TAG_EXPLICIT
:
5195 p_tags
->add_tag(tag
->clone());
5197 case Tag::TAG_IMPLICIT
: {
5198 Tag
*t_p_tag
=p_tags
->get_tag_byIndex(p_tags
->get_nof_tags()-1);
5199 t_p_tag
->set_tagclass(tag
->get_tagclass());
5200 t_p_tag
->set_tagvalue(tag
->get_tagvalue());
5203 FATAL_ERROR("Type::build_tags_joined()");
5210 void Type::set_with_attr(Ttcn::MultiWithAttrib
* p_attrib
)
5214 w_attrib_path
= new WithAttribPath();
5217 w_attrib_path
->set_with_attr(p_attrib
);
5220 void Type::set_parent_path(WithAttribPath
* p_path
)
5224 w_attrib_path
= new WithAttribPath();
5226 w_attrib_path
->set_parent(p_path
);
5227 if (typetype
== T_COMPONENT
)
5228 u
.component
->set_parent_path(w_attrib_path
);
5231 WithAttribPath
* Type::get_attrib_path() const
5233 return w_attrib_path
;
5236 bool Type::hasRawAttrs()
5238 if(rawattrib
) return true;
5242 if(w_attrib_path
->get_had_global_variants()) return true;
5244 vector
<SingleWithAttrib
> const &real_attribs
5245 = w_attrib_path
->get_real_attrib();
5247 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
5248 if (real_attribs
[i
]->get_attribKeyword()
5249 == SingleWithAttrib::AT_VARIANT
)
5254 MultiWithAttrib
* temp_attrib
= w_attrib_path
->get_with_attr();
5256 for(size_t i
= 0; i
< temp_attrib
->get_nof_elements(); i
++)
5257 if(temp_attrib
->get_element(i
)->get_attribKeyword()
5258 == SingleWithAttrib::AT_VARIANT
5259 && (!temp_attrib
->get_element(i
)->get_attribQualifiers()
5260 || temp_attrib
->get_element(i
)->get_attribQualifiers()
5261 ->get_nof_qualifiers() == 0))
5263 w_attrib_path
->set_had_global_variants( true );
5271 bool Type::hasNeedofRawAttrs()
5273 if(rawattrib
) return true;
5280 nof_comps
= get_nof_comps();
5281 for(size_t i
=0; i
< nof_comps
; i
++)
5283 if(get_comp_byIndex(i
)->get_type()->hasNeedofRawAttrs())
5295 bool Type::hasNeedofTextAttrs()
5297 if(textattrib
) return true;
5304 nof_comps
= get_nof_comps();
5305 for(size_t i
=0; i
< nof_comps
; i
++)
5307 if(get_comp_byIndex(i
)->get_type()->hasNeedofTextAttrs())
5319 bool Type::hasNeedofJsonAttrs()
5321 if(jsonattrib
) return true;
5328 nof_comps
= get_nof_comps();
5329 for (size_t i
= 0; i
< nof_comps
; ++i
)
5331 if (get_comp_byIndex(i
)->get_type()->hasNeedofJsonAttrs())
5343 bool Type::hasNeedofXerAttrs()
5345 if(xerattrib
&& !xerattrib
->empty()) return true;
5352 nof_comps
= get_nof_comps();
5353 for(size_t i
=0; i
< nof_comps
; i
++)
5355 if(get_comp_byIndex(i
)->get_type()->hasNeedofXerAttrs())
5367 bool Type::hasVariantAttrs()
5371 if(w_attrib_path
->get_had_global_variants()) return true;
5373 vector
<SingleWithAttrib
> const &real_attribs
5374 = w_attrib_path
->get_real_attrib();
5376 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
5377 if (real_attribs
[i
]->get_attribKeyword()
5378 == SingleWithAttrib::AT_VARIANT
)
5383 MultiWithAttrib
* temp_attrib
= w_attrib_path
->get_with_attr();
5385 for(size_t i
= 0; i
< temp_attrib
->get_nof_elements(); i
++)
5386 if(temp_attrib
->get_element(i
)->get_attribKeyword()
5387 == SingleWithAttrib::AT_VARIANT
5388 && (!temp_attrib
->get_element(i
)->get_attribQualifiers()
5389 || temp_attrib
->get_element(i
)->get_attribQualifiers()
5390 ->get_nof_qualifiers() != 0))
5392 w_attrib_path
->set_had_global_variants( true );
5400 bool Type::hasEncodeAttr(const char* encoding_name
)
5402 if (0 == strcmp(encoding_name
, "JSON") && (implicit_json_encoding
5403 || is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) {
5404 // ASN.1 types automatically support JSON encoding
5407 // Check the type itself first, then the root type
5408 WithAttribPath
*aps
[2] = { 0, 0 };
5409 size_t num_aps
= ((aps
[0] = get_attrib_path()) != 0);
5410 // assign, compare, then add 0 or 1
5412 num_aps
+= ((aps
[num_aps
] = get_type_refd()->get_attrib_path()) != 0);
5414 for (size_t a
= 0; a
< num_aps
; ++a
) {
5415 const vector
<SingleWithAttrib
>& real
= aps
[a
]->get_real_attrib();
5416 const size_t num_atr
= real
.size();
5417 for (size_t i
= 0; i
< num_atr
; ++i
) {
5418 const SingleWithAttrib
& s
= *real
[i
];
5419 if (s
.get_attribKeyword() == SingleWithAttrib::AT_ENCODE
) {
5420 const string
& spec
= s
.get_attribSpec().get_spec();
5421 if (spec
== encoding_name
) {
5430 namespace { // unnamed
5432 enum state
{ PROCESSING
= -1, ANSWER_NO
, ANSWER_YES
};
5434 struct memoizer
: private map
<Type
*, state
> {
5435 memoizer() : map
<Type
*, state
>() {}
5438 for (int i
= size()-1; i
>= 0; --i
) {
5439 delete get_nth_elem(i
);
5444 bool remember (Type
*t
, state s
) {
5449 add(t
, new state(s
));
5451 return s
== ANSWER_YES
;
5454 bool has_key(Type
*t
) {
5455 return map
<Type
*, state
>::has_key(t
);
5458 state
* get(Type
*t
) {
5459 return operator [](t
);
5465 bool Type::has_encoding(MessageEncodingType_t encoding_type
, const string
* custom_encoding
/* = NULL */)
5467 static memoizer memory
;
5468 static memoizer json_mem
;
5470 switch (encoding_type
) {
5474 if (t
->is_asn1()) return true;
5475 else if (t
->is_ref()) t
= t
->get_type_refd();
5477 switch (t
->typetype
) {
5485 // these basic TTCN-3 types have ASN.1 equivalents
5494 if (memory
.has_key(this)) {
5495 state
*s
= memory
.get(this);
5507 // For ASN.1 types, the answer depends solely on the -a switch.
5508 // They are all considered to have Basic (i.e. useless) XER,
5509 // unless the -a switch says removes XER from all ASN.1 types.
5510 if (t
->is_asn1()) return memory
.remember(t
,
5511 asn1_xer
? ANSWER_YES
: ANSWER_NO
);
5512 else if (t
->is_ref()) t
= t
->get_type_refd();
5513 else { // at the end of the ref. chain
5514 switch (t
->typetype
) {
5520 // The octetstring type can always be encoded in XER.
5521 // XSD:base64Binary is only needed for Type::is_charenc()
5523 case T_HSTR
: // TTCN-3 hexstring
5524 case T_VERDICT
: // TTCN-3 verdict
5525 case T_CSTR
: // TTCN3 charstring
5526 case T_USTR
: // TTCN3 universal charstring
5527 return memory
.remember(t
, ANSWER_YES
);
5530 break; // the switch; skip to checking if it has encode "XML";
5532 case T_PORT
: // TTCN-3 port (the list of in's, out's, inout's)
5533 case T_COMPONENT
: // TTCN-3 comp. type (extends, and { ... })
5534 case T_DEFAULT
: // TTCN-3
5535 case T_SIGNATURE
: // TTCN-3
5536 case T_FUNCTION
: // TTCN-3
5537 case T_ALTSTEP
: // TTCN-3
5538 case T_TESTCASE
: // TTCN-3
5539 case T_ANYTYPE
: // TTCN-3 anytype
5540 return memory
.remember(t
, ANSWER_NO
);
5545 return false; // why don't we remember these ?
5550 // No field may reject XER
5551 size_t ncomp
= t
->get_nof_comps();
5552 for (size_t i
= 0; i
< ncomp
; ++i
) {
5553 Type
*t2
= t
->get_comp_byIndex(i
)->get_type();
5554 bool subresult
= false;
5555 if (memory
.has_key(t2
)) {
5556 switch (*memory
.get(t2
)) {
5558 // This type contains itself and is in the process
5559 // of being checked. Pretend it doesn't exist.
5560 // The answer will be determined by the other fields,
5561 // and it will propagate back up.
5562 // Avoids infinite recursion for self-referencing types.
5573 memory
.remember(t2
, PROCESSING
);
5574 subresult
= t2
->has_encoding(CT_XER
);
5577 if (subresult
) memory
.remember(t2
, ANSWER_YES
);
5578 else return memory
.remember(t2
, ANSWER_NO
);
5579 // Note: return only if the answer (false) is known.
5580 // If the answer is true, keep checking.
5582 // Empty record, or all fields supported XER: answer maybe yes.
5587 bool subresult
= false;
5588 Type
*t2
= t
->u
.seof
.ofType
;
5589 if (memory
.has_key(t2
)) {
5590 switch (*memory
.get(t2
)) {
5592 // Recursive record-of. This is OK because the recursion
5593 // can always be broken with an empty record-of.
5605 memory
.remember(t2
, PROCESSING
);
5606 // Check the contained type
5607 subresult
= t2
->has_encoding(CT_XER
);
5609 if (subresult
) break; // continue checking
5610 else return memory
.remember(t
, ANSWER_NO
); // No means no.
5613 case T_NULL
: // ASN.1 null
5614 case T_INT_A
: // ASN.1 integer
5615 case T_ENUM_A
:// ASN.1 enum
5616 case T_BSTR_A
:// ASN.1 bitstring
5617 case T_UTF8STRING
: // ASN.1
5618 case T_NUMERICSTRING
:
5619 case T_PRINTABLESTRING
:
5620 case T_TELETEXSTRING
:
5621 case T_VIDEOTEXSTRING
:
5623 case T_GRAPHICSTRING
:
5624 case T_VISIBLESTRING
:
5625 case T_GENERALSTRING
:
5626 case T_UNIVERSALSTRING
:
5628 case T_UNRESTRICTEDSTRING
: // still ASN.1
5629 case T_UTCTIME
: // ASN.1 string
5630 case T_GENERALIZEDTIME
: // ASN.1 string
5631 case T_OBJECTDESCRIPTOR
: // ASN.1 string
5632 case T_ROID
: // relative OID (ASN.1)
5635 case T_SEQ_A
: // ASN.1 versions of choice,sequence,set
5638 case T_OCFT
: // ObjectClassFieldType (ASN.1)
5639 case T_OPENTYPE
: // ASN.1 open type
5640 case T_ANY
: // deprecated ASN.1 ANY
5642 case T_EXTERNAL
: // ASN.1 external
5643 case T_EMBEDDED_PDV
: // ASN.1 embedded pdv
5644 case T_SELTYPE
: // selection type (ASN.1)
5645 FATAL_ERROR("Type::has_encoding(): typetype %d should be asn1",
5647 break; // not reached
5649 case T_REFD
: // reference to another type
5650 case T_ADDRESS
: // TTCN-3 address type
5651 case T_ARRAY
: // TTCN-3 array
5652 default: // FIXME: if compiling with -Wswitch, the default should be removed
5653 return memory
.remember(t
, ANSWER_NO
);
5654 } // switch t->typetype
5656 // Check to see if it has an encode "XML"; first the type itself,
5657 // then the root type.
5658 WithAttribPath
*aps
[2] = {0,0};
5659 size_t num_aps
= ((aps
[0] = this->get_attrib_path()) != 0);
5660 // assign, compare, then add 0 or 1
5662 num_aps
+= ((aps
[num_aps
] = t
->get_attrib_path()) != 0);
5664 for (size_t a
= 0; a
< num_aps
; ++a
) {
5665 const vector
<SingleWithAttrib
>& real
= aps
[a
]->get_real_attrib();
5666 const size_t num_atr
= real
.size();
5667 for (size_t i
= 0; i
< num_atr
; ++i
) {
5668 const SingleWithAttrib
& s
= *real
[i
];
5669 if (s
.get_attribKeyword() == SingleWithAttrib::AT_ENCODE
) {
5670 const string
& spec
= s
.get_attribSpec().get_spec();
5671 if (spec
== ex_emm_ell
// the right answer
5672 ||spec
== ex_ee_arr
) // the acceptable answer
5673 return memory
.remember(t
, ANSWER_YES
);
5677 return memory
.remember(t
, ANSWER_NO
); // no encode XER
5680 return memory
.remember(t
, ANSWER_NO
); }
5684 if (t
->rawattrib
) return true;
5685 else if (t
->is_ref()) t
= t
->get_type_refd();
5687 switch (t
->typetype
) {
5696 // these basic types support RAW encoding by default
5706 if (t
->textattrib
) return true;
5707 else if (t
->is_ref()) t
= t
->get_type_refd();
5709 switch (t
->typetype
) {
5715 case T_USTR
: // TTCN3 universal charstring
5716 // these basic types support TEXT encoding by default
5726 if (json_mem
.has_key(t
)) {
5727 switch (*json_mem
.get(t
)) {
5736 if (t
->jsonattrib
) {
5737 return json_mem
.remember(t
, ANSWER_YES
);
5740 t
= t
->get_type_refd();
5743 switch (t
->typetype
) {
5756 case T_NUMERICSTRING
:
5757 case T_PRINTABLESTRING
:
5758 case T_TELETEXSTRING
:
5759 case T_VIDEOTEXSTRING
:
5761 case T_GRAPHICSTRING
:
5762 case T_VISIBLESTRING
:
5763 case T_GENERALSTRING
:
5764 case T_UNIVERSALSTRING
:
5771 // these basic types support JSON encoding by default
5772 return json_mem
.remember(t
, ANSWER_YES
);
5781 // all fields must also support JSON encoding
5782 size_t ncomp
= t
->get_nof_comps();
5783 for (size_t i
= 0; i
< ncomp
; ++i
) {
5784 Type
*t2
= t
->get_comp_byIndex(i
)->get_type();
5785 if (json_mem
.has_key(t2
)) {
5786 switch (*json_mem
.get(t2
)) {
5788 // This field is OK, but we still need to check the others
5790 // This type contains itself and is in the process
5791 // of being checked. Pretend it doesn't exist.
5792 // The answer will be determined by the other fields,
5793 // and it will propagate back up.
5794 // Avoids infinite recursion for self-referencing types.
5797 // One field is not OK => the structure is not OK
5798 return json_mem
.remember(t
, ANSWER_NO
);
5802 json_mem
.remember(t2
, PROCESSING
);
5803 bool enabled
= t2
->has_encoding(CT_JSON
);
5804 json_mem
.remember(t2
, enabled
? ANSWER_YES
: ANSWER_NO
);
5806 // One field is not OK => the structure is not OK
5807 return json_mem
.remember(t
, ANSWER_NO
);
5811 break; // check for an encode attribute
5816 Type
*t2
= t
->u
.seof
.ofType
;
5817 if (json_mem
.has_key(t2
)) {
5818 switch (*json_mem
.get(t2
)) {
5820 // Continue checking
5822 // Recursive record-of. This is OK because the recursion
5823 // can always be broken with an empty record-of.
5826 return json_mem
.remember(t
, ANSWER_NO
);
5831 json_mem
.remember(t2
, PROCESSING
);
5832 bool enabled
= t2
->has_encoding(CT_JSON
);
5833 json_mem
.remember(t2
, enabled
? ANSWER_YES
: ANSWER_NO
);
5835 // One field is not OK => the structure is not OK
5836 return json_mem
.remember(t
, ANSWER_NO
);
5839 break; // check for an encode attribute
5843 break; // check for an encode attribute
5845 return json_mem
.remember(t
, ANSWER_NO
);
5847 return json_mem
.remember(t
, hasEncodeAttr(get_encoding_name(CT_JSON
)) ? ANSWER_YES
: ANSWER_NO
);
5852 // the encoding name parameter has to be the same as the encoding name
5853 // specified for the type
5854 return custom_encoding
? hasEncodeAttr(custom_encoding
->c_str()) : false;
5857 FATAL_ERROR("Type::has_encoding()");
5863 bool Type::is_pure_refd()
5867 // ASN.1 parameterized references are not pure :)
5868 if(dynamic_cast<Asn::Ref_pard
*>(u
.ref
.ref
)) return false;
5873 if (sub_type
|| constraints
) return false;
5874 else if (tags
&& enable_ber()) return false;
5875 else if (rawattrib
&& enable_raw()) return false;
5876 else if (textattrib
&& enable_text()) return false;
5877 else if (enable_xer()) return false;
5878 else if (jsonattrib
&& enable_json()) return false;
5885 string
Type::create_stringRepr()
5887 if(is_tagged() || hasRawAttrs())
5888 return get_genname_own();
5891 return string("NULL");
5893 return string("BOOLEAN");
5896 return string("INTEGER");
5898 return string("REAL");
5901 return string("BIT__STRING");
5903 return string("HEX__STRING");
5905 return string("OCTET__STRING");
5907 return string("CHAR__STRING");
5909 return string("UNIVERSAL__CHARSTRING");
5911 return string("UTF8String");
5912 case T_NUMERICSTRING
:
5913 return string("NumericString");
5914 case T_PRINTABLESTRING
:
5915 return string("PrintableString");
5916 case T_TELETEXSTRING
:
5917 return string("TeletexString");
5918 case T_VIDEOTEXSTRING
:
5919 return string("VideotexString");
5921 return string("IA5String");
5922 case T_GRAPHICSTRING
:
5923 return string("GraphicString");
5924 case T_VISIBLESTRING
:
5925 return string("VisibleString");
5926 case T_GENERALSTRING
:
5927 return string("GeneralString");
5928 case T_UNIVERSALSTRING
:
5929 return string("UniversalString");
5931 return string("BMPString");
5932 case T_UNRESTRICTEDSTRING
:
5933 return string("CHARACTER__STRING");
5935 return string("UTCTime");
5936 case T_GENERALIZEDTIME
:
5937 return string("GeneralizedTime");
5938 case T_OBJECTDESCRIPTOR
:
5939 return string("ObjectDescriptor");
5941 return string("OBJECT__IDENTIFIER");
5943 return string("RELATIVE__OID");
5945 return string("ANY");
5950 if (tags
|| constraints
||
5951 (w_attrib_path
&& w_attrib_path
->has_attribs()))
5952 return get_genname_own();
5953 else return get_type_refd()->get_stringRepr();
5955 return string("<Error_type>");
5957 return get_genname_own();
5961 Identifier
Type::get_otaltname(bool& is_strange
)
5964 if (is_tagged() || is_constrained() || hasRawAttrs()) {
5965 s
= get_genname_own();
5967 } else if (typetype
== T_REFD
) {
5968 Ref_simple
* t_ref
=dynamic_cast<Ref_simple
*>(u
.ref
.ref
);
5970 const Identifier
*id
= t_ref
->get_id();
5971 const string
& dispname
= id
->get_dispname();
5972 if (dispname
.find('.') < dispname
.size()) {
5973 // id is not regular because t_ref is a parameterized reference
5974 // use that id anyway
5975 s
+= id
->get_name();
5978 Scope
*ass_scope
= t_ref
->get_refd_assignment()->get_my_scope();
5979 if (ass_scope
->get_parent_scope() == ass_scope
->get_scope_mod()) {
5980 // t_ref points to an assignment at module scope
5981 // use the simple id of the reference (in lowercase)
5985 // t_ref is a dummy reference in a parameterized assignment
5986 // (i.e. it points to a parameter assignment of an instantiation)
5987 // perform the same examination recursively on the referenced type
5988 // (which is the actual parameter)
5989 return get_type_refd()->get_otaltname(is_strange
);
5993 // the type comes from an information object [class]
5994 // examine the referenced type recursively
5995 return get_type_refd()->get_otaltname(is_strange
);
5998 s
= get_stringRepr();
5999 // throw away the leading @ if this is an instantiated type
6000 // (e.g. an in-line SEQUENCE from a parameterized reference)
6001 if (!strncmp(s
.c_str(), "_root_", 6)) s
.replace(0, 6, "");
6002 // the name is strange if it contains a single underscore
6004 // transform "__" -> "-"
6005 for (size_t pos
= 0; ; ) {
6006 pos
= s2
.find("__", pos
);
6007 if (pos
< s2
.size()) {
6008 s2
.replace(pos
, 2, "-");
6012 is_strange
= s2
.find('_') < s2
.size();
6015 size_t pos=s.find_if(0, s.size(), isupper);
6016 if(pos==s.size()) FATAL_ERROR("Type::get_otaltname() (`%s')", s.c_str());
6017 s[pos]=tolower(s[pos]);
6020 Identifier
tmp_id(Identifier::ID_NAME
, s
, true);
6021 /* This is because the origin of the returned ID must be ASN. */
6022 return Identifier(Identifier::ID_ASN
, tmp_id
.get_asnname());
6025 string
Type::get_genname_value(Scope
*p_scope
)
6027 Type
*t
= get_type_refd_last();
6028 switch (t
->typetype
) {
6031 case T_UNRESTRICTEDSTRING
:
6034 case T_EMBEDDED_PDV
:
6038 FATAL_ERROR("Type::get_genname_value()");
6040 return string("ASN_NULL");
6042 return string("BOOLEAN");
6045 return string("INTEGER");
6047 return string("FLOAT");
6050 return string("BITSTRING");
6052 return string("HEXSTRING");
6054 return string("OCTETSTRING");
6056 case T_NUMERICSTRING
:
6057 case T_PRINTABLESTRING
:
6059 case T_VISIBLESTRING
:
6061 case T_GENERALIZEDTIME
:
6062 return string("CHARSTRING");
6063 case T_USTR
: // ttcn3 universal charstring
6065 case T_TELETEXSTRING
:
6066 case T_VIDEOTEXSTRING
:
6067 case T_GRAPHICSTRING
:
6068 case T_GENERALSTRING
:
6069 case T_UNIVERSALSTRING
:
6071 case T_OBJECTDESCRIPTOR
:
6072 return string("UNIVERSAL_CHARSTRING");
6075 return string("OBJID");
6077 return string("ASN_ANY");
6079 return string("VERDICTTYPE");
6081 return string("COMPONENT");
6083 return string("DEFAULT");
6085 if (!t
->u
.array
.in_typedef
)
6086 return t
->u
.array
.dimension
->get_value_type(t
->u
.array
.element_type
,
6090 return t
->get_genname_own(p_scope
);
6094 string
Type::get_genname_template(Scope
*p_scope
)
6096 Type
*t
= get_type_refd_last();
6098 switch (t
->typetype
) {
6101 // template classes do not exist for these types
6102 FATAL_ERROR("Type::get_genname_template()");
6104 // a template class has to be instantiated in case of arrays
6105 // outside type definitions
6106 if (!t
->u
.array
.in_typedef
) {
6107 ret_val
= t
->u
.array
.dimension
->get_template_type(
6108 t
->u
.array
.element_type
, p_scope
);
6113 // in case of other types the name of the template class is derived
6114 // from the value class by appending a suffix
6115 ret_val
= t
->get_genname_value(p_scope
);
6116 ret_val
+= "_template";
6122 string
Type::get_genname_altname()
6124 Type
*t_last
= get_type_refd_last();
6125 Scope
*t_scope
= t_last
->get_my_scope();
6126 switch (t_last
->typetype
) {
6129 case T_UNRESTRICTEDSTRING
:
6132 case T_EMBEDDED_PDV
:
6136 FATAL_ERROR("Type::get_genname_altname()");
6148 case T_ANYTYPE
: // FIXME this does not yet work
6156 // user-defined types
6157 // always use the qualified name (including module identifier)
6158 string
ret_val(t_scope
->get_scope_mod_gen()->get_modid().get_name());
6160 ret_val
+= t_last
->get_genname_own();
6164 // use the simple class name from the base library
6165 return t_last
->get_genname_value(t_scope
);
6169 string
Type::get_typename()
6171 Type
*t
= get_type_refd_last();
6172 const char* tn
= get_typename_builtin(t
->typetype
);
6173 if (tn
!= 0) return string(tn
);
6174 switch (t
->typetype
) {
6192 return t
->get_fullname();
6194 string
dimensions(t
->u
.array
.dimension
->get_stringRepr());
6195 t
= t
->u
.array
.element_type
;
6196 while (t
->typetype
== T_ARRAY
) {
6197 dimensions
+= t
->u
.array
.dimension
->get_stringRepr();
6198 t
= t
->u
.array
.element_type
;
6200 return t
->get_typename() + dimensions
; }
6202 FATAL_ERROR("Type::get_typename()");
6208 const char* Type::get_typename_builtin(typetype_t tt
)
6212 return "Erroneous type";
6228 return "octetstring";
6230 return "charstring";
6232 return "universal charstring";
6234 return "UTF8String";
6235 case T_NUMERICSTRING
:
6236 return "NumericString";
6237 case T_PRINTABLESTRING
:
6238 return "PrintableString";
6239 case T_TELETEXSTRING
:
6240 return "TeletexString";
6241 case T_VIDEOTEXSTRING
:
6242 return "VideotexString";
6245 case T_GRAPHICSTRING
:
6246 return "GraphicString";
6247 case T_VISIBLESTRING
:
6248 return "VisibleString";
6249 case T_GENERALSTRING
:
6250 return "GeneralString";
6251 case T_UNIVERSALSTRING
:
6252 return "UniversalString";
6257 case T_GENERALIZEDTIME
:
6258 return "GeneralizedTime";
6259 case T_OBJECTDESCRIPTOR
:
6260 return "ObjectDescriptor";
6267 return "verdicttype";
6272 case T_EMBEDDED_PDV
:
6273 return "EMBEDDED PDV";
6274 case T_UNRESTRICTEDSTRING
:
6275 return "CHARACTER STRING";
6285 string
Type::get_genname_typedescriptor(Scope
*p_scope
)
6289 /* If it has tags or encoding attributes, then its encoding may be
6290 * different from the other "equivalent" types and needs to have its own
6293 if (t
->is_tagged() || t
->rawattrib
|| t
->textattrib
|| t
->jsonattrib
||
6294 (t
->xerattrib
&& !t
->xerattrib
->empty() ))
6296 return t
->get_genname_own(p_scope
);
6298 else if (t
->is_ref()) {
6299 if (t
->has_encoding(CT_XER
)) {
6300 // just fetch the referenced type and return
6301 return t
->get_type_refd()->get_genname_own(p_scope
);
6304 { // follow the white rabbit
6305 t
= t
->get_type_refd();
6310 return t
->get_genname_typename(p_scope
);
6313 string
Type::get_genname_typename(Scope
*p_scope
)
6315 Type
*t
= get_type_refd_last();
6316 switch (t
->typetype
) {
6318 return string("UTF8String");
6319 case T_NUMERICSTRING
:
6320 return string("NumericString");
6321 case T_PRINTABLESTRING
:
6322 return string("PrintableString");
6323 case T_TELETEXSTRING
:
6324 return string("TeletexString");
6325 case T_VIDEOTEXSTRING
:
6326 return string("VideotexString");
6328 return string("IA5String");
6329 case T_GRAPHICSTRING
:
6330 return string("GraphicString");
6331 case T_VISIBLESTRING
:
6332 return string("VisibleString");
6333 case T_GENERALSTRING
:
6334 return string("GeneralString");
6335 case T_UNIVERSALSTRING
:
6336 return string("UniversalString");
6338 return string("BMPString");
6340 return string("ASN_UTCTime");
6341 case T_GENERALIZEDTIME
:
6342 return string("ASN_GeneralizedTime");
6343 case T_OBJECTDESCRIPTOR
:
6344 return string("ObjectDescriptor");
6346 return string("ASN_ROID");
6348 return t
->get_genname_value(p_scope
);
6352 string
Type::get_genname_berdescriptor()
6356 if (t
->is_tagged()) return t
->get_genname_own(my_scope
);
6357 else if (t
->is_ref()) t
= t
->get_type_refd();
6360 switch (t
->typetype
) {
6363 return string("ENUMERATED");
6367 return string("CHOICE");
6371 return string("SEQUENCE");
6375 return string("SET");
6377 return t
->get_genname_typename(my_scope
);
6381 string
Type::get_genname_rawdescriptor()
6385 if (t
->rawattrib
) return t
->get_genname_own(my_scope
);
6386 else if (t
->is_ref()) t
= t
->get_type_refd();
6389 return t
->get_genname_typename(my_scope
);
6392 string
Type::get_genname_textdescriptor()
6396 if (t
->textattrib
) return t
->get_genname_own(my_scope
);
6397 else if (t
->is_ref()) t
= t
->get_type_refd();
6400 return t
->get_genname_typename(my_scope
);
6403 string
Type::get_genname_xerdescriptor()
6405 if (T_REFDSPEC
== typetype
) {
6406 return get_genname_typedescriptor(my_scope
);
6408 else return genname
;
6411 string
Type::get_genname_jsondescriptor()
6415 if (t
->jsonattrib
) return t
->get_genname_own(my_scope
);
6416 else if (t
->is_ref()) t
= t
->get_type_refd();
6419 return t
->get_genname_typename(my_scope
);
6422 const char* Type::get_genname_typedescr_asnbasetype()
6424 switch (get_type_refd_last()->typetype
) {
6427 case T_UNIVERSALSTRING
:
6428 return "UNIVERSALSTRING";
6430 return "UTF8STRING";
6431 case T_TELETEXSTRING
:
6432 return "TELETEXSTRING";
6433 case T_VIDEOTEXSTRING
:
6434 return "VIDEOTEXSTRING";
6435 case T_OBJECTDESCRIPTOR
:
6436 case T_GRAPHICSTRING
:
6437 return "GRAPHICSTRING";
6438 case T_GENERALSTRING
:
6439 return "GENERALSTRING";
6449 void Type::dump(unsigned level
) const
6451 DEBUG(level
, "Type @ %p, '%s'", (const void*)this, get_fullname().c_str());
6454 DEBUG(level
, "Type: <erroneous>");
6457 DEBUG(level
, "Type: NULL");
6460 DEBUG(level
, "Type: boolean");
6463 DEBUG(level
, "Type: integer");
6466 DEBUG(level
, "Type: INTEGER");
6467 if(u
.namednums
.block
)
6468 DEBUG(level
, "with unparsed block");
6469 if(u
.namednums
.nvs
) {
6470 DEBUG(level
, "with named numbers (%lu pcs.)",
6471 (unsigned long) u
.namednums
.nvs
->get_nof_nvs());
6472 u
.namednums
.nvs
->dump(level
+1);
6476 DEBUG(level
, "Type: float/REAL");
6480 DEBUG(level
, "Type: enumerated");
6481 u
.enums
.eis
->dump(level
+1);
6484 DEBUG(level
, "Type: bitstring");
6487 DEBUG(level
, "Type: BIT STRING");
6488 if(u
.namednums
.block
)
6489 DEBUG(level
, "with unparsed block");
6490 if(u
.namednums
.nvs
) {
6491 DEBUG(level
, "with named numbers (%lu pcs.)",
6492 (unsigned long) u
.namednums
.nvs
->get_nof_nvs());
6493 u
.namednums
.nvs
->dump(level
+1);
6497 DEBUG(level
, "Type: hexstring");
6500 DEBUG(level
, "Type: octetstring");
6503 DEBUG(level
, "Type: charstring");
6506 DEBUG(level
, "Type: universal charstring");
6509 DEBUG(level
, "Type: UTF8String");
6511 case T_NUMERICSTRING
:
6512 DEBUG(level
, "Type: NumericString");
6514 case T_PRINTABLESTRING
:
6515 DEBUG(level
, "Type: PrintableString");
6517 case T_TELETEXSTRING
:
6518 DEBUG(level
, "Type: TeletexString");
6520 case T_VIDEOTEXSTRING
:
6521 DEBUG(level
, "Type: VideotexString");
6524 DEBUG(level
, "Type: IA5String");
6526 case T_GRAPHICSTRING
:
6527 DEBUG(level
, "Type: GraphicString");
6529 case T_VISIBLESTRING
:
6530 DEBUG(level
, "Type: VisibleString");
6532 case T_GENERALSTRING
:
6533 DEBUG(level
, "Type: GeneralString");
6535 case T_UNIVERSALSTRING
:
6536 DEBUG(level
, "Type: UniversalString");
6539 DEBUG(level
, "Type: BMPString");
6541 case T_UNRESTRICTEDSTRING
:
6542 DEBUG(level
, "Type: CHARACTER STRING");
6545 DEBUG(level
, "Type: UTCTime");
6547 case T_GENERALIZEDTIME
:
6548 DEBUG(level
, "Type: GeneralizedTime");
6550 case T_OBJECTDESCRIPTOR
:
6551 DEBUG(level
, "Type: OBJECT DESCRIPTOR");
6554 DEBUG(level
, "Type: objid/OBJECT IDENTIFIER");
6557 DEBUG(level
, "Type: RELATIVE-OID");
6560 DEBUG(level
, "Type: anytype!!!");
6561 u
.secho
.cfm
->dump(level
+1);
6564 DEBUG(level
, "Type: union");
6565 u
.secho
.cfm
->dump(level
+1);
6568 DEBUG(level
, "Type: CHOICE");
6570 DEBUG(level
, "with unparsed block");
6572 DEBUG(level
, "with alternatives (%lu pcs.)",
6573 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6574 u
.secho
.ctss
->dump(level
+1);
6578 DEBUG(level
, "Type: record of/SEQUENCE OF");
6579 DEBUG(level
+1, "of type:");
6580 u
.seof
.ofType
->dump(level
+2);
6583 DEBUG(level
, "Type: set of/SET OF");
6584 DEBUG(level
+1, "of type:");
6585 u
.seof
.ofType
->dump(level
+2);
6588 DEBUG(level
, "Type: record");
6589 u
.secho
.cfm
->dump(level
+1);
6592 DEBUG(level
, "Type: set");
6593 u
.secho
.cfm
->dump(level
+1);
6596 DEBUG(level
, "Type: SEQUENCE");
6598 DEBUG(level
, "with unparsed block");
6600 DEBUG(level
, "with components (%lu pcs.)",
6601 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6602 u
.secho
.ctss
->dump(level
+1);
6606 DEBUG(level
, "Type: SET");
6608 DEBUG(level
, "with unparsed block");
6610 DEBUG(level
, "with components (%lu pcs.)",
6611 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6612 u
.secho
.ctss
->dump(level
+1);
6616 DEBUG(level
, "Type: ObjectClassFieldType (%s)",
6617 const_cast<Type
*>(this)->get_type_refd()->get_stringRepr().c_str());
6620 DEBUG(level
, "Type: opentype (mapped to CHOICE)");
6621 u
.secho
.cfm
->dump(level
+1);
6624 DEBUG(level
, "Type: ANY");
6627 DEBUG(level
, "Type: EXTERNAL");
6629 case T_EMBEDDED_PDV
:
6630 DEBUG(level
, "Type: EMBEDDED PDV");
6633 DEBUG(level
, "Type: reference");
6634 u
.ref
.ref
->dump(level
+1);
6635 if(u
.ref
.type_refd
&& u
.ref
.type_refd
->typetype
==T_OPENTYPE
)
6636 u
.ref
.type_refd
->dump(level
+1);
6639 DEBUG(level
, "Type: reference (spec) to %s:",
6640 u
.ref
.type_refd
->get_fullname().c_str());
6641 u
.ref
.type_refd
->dump(level
+ 1);
6644 DEBUG(level
, "Type: selection type");
6645 DEBUG(level
+1, "`%s' <", u
.seltype
.id
->get_dispname().c_str());
6646 u
.seltype
.type
->dump(level
+1);
6649 DEBUG(level
, "Type: verdicttype");
6652 DEBUG(level
, "Type: port");
6653 u
.port
->dump(level
+ 1);
6656 DEBUG(level
, "Type: component");
6657 u
.component
->dump(level
+ 1);
6660 DEBUG(level
, "Type: address");
6663 DEBUG(level
, "Type: default");
6666 DEBUG(level
, "Type: array");
6667 DEBUG(level
+ 1, "element type:");
6668 u
.array
.element_type
->dump(level
+ 2);
6669 DEBUG(level
+ 1, "dimension:");
6670 u
.array
.dimension
->dump(level
+ 2);
6673 DEBUG(level
, "Type: signature");
6674 if (u
.signature
.parameters
) {
6675 DEBUG(level
+1,"parameter(s):");
6676 u
.signature
.parameters
->dump(level
+2);
6678 if (u
.signature
.return_type
) {
6679 DEBUG(level
+1,"return type");
6680 u
.signature
.return_type
->dump(level
+2);
6682 if (u
.signature
.no_block
) DEBUG(level
+1,"no block");
6683 if (u
.signature
.exceptions
) {
6684 DEBUG(level
+1,"exception(s):");
6685 u
.signature
.exceptions
->dump(level
+2);
6689 DEBUG(level
, "Type: function");
6690 DEBUG(level
+1, "Parameters:");
6691 u
.fatref
.fp_list
->dump(level
+2);
6692 if (u
.fatref
.return_type
) {
6693 if (!u
.fatref
.returns_template
) {
6694 DEBUG(level
+1, "Return type:");
6696 if (u
.fatref
.template_restriction
==TR_OMIT
)
6697 DEBUG(level
+1, "Returns template of type:");
6699 DEBUG(level
+1, "Returns template(%s) of type:",
6700 Template::get_restriction_name(u
.fatref
.template_restriction
));
6702 u
.fatref
.return_type
->dump(level
+2);
6704 if(u
.fatref
.runs_on
.ref
) {
6705 DEBUG(level
+1, "Runs on clause:");
6706 u
.fatref
.runs_on
.ref
->dump(level
+2);
6708 if (u
.fatref
.runs_on
.self
) DEBUG(level
+1, "Runs on self");
6712 DEBUG(level
, "Type: altstep");
6713 DEBUG(level
+1, "Parameters:");
6714 u
.fatref
.fp_list
->dump(level
+2);
6715 if(u
.fatref
.runs_on
.ref
) {
6716 DEBUG(level
+1, "Runs on clause:");
6717 u
.fatref
.runs_on
.ref
->dump(level
+2);
6719 if (u
.fatref
.runs_on
.self
) DEBUG(level
+1, "Runs on self");
6723 DEBUG(level
, "Type: testcase");
6724 DEBUG(level
+1, "Parameters:");
6725 u
.fatref
.fp_list
->dump(level
+2);
6726 if(u
.fatref
.runs_on
.ref
) {
6727 DEBUG(level
+1, "Runs on clause:");
6728 u
.fatref
.runs_on
.ref
->dump(level
+2);
6730 if(u
.fatref
.system
.ref
) {
6731 DEBUG(level
+1, "System clause:");
6732 u
.fatref
.system
.ref
->dump(level
+2);
6736 DEBUG(level
, "type (%d - %s)", typetype
, const_cast<Type
*>(this)->get_stringRepr().c_str());
6738 DEBUG(level
, "ownertype %2d", ownertype
);
6739 if(sub_type
!=NULL
) {
6740 DEBUG(level
, "with subtype");
6741 sub_type
->dump(level
+1);
6744 DEBUG(level
, "with tags");
6745 tags
->dump(level
+1);
6748 if(w_attrib_path
&& w_attrib_path
->get_with_attr())
6750 DEBUG(level
, "Attributes");
6751 w_attrib_path
->dump(level
);
6752 //w_attrib_path->get_with_attr()->dump(level);
6756 xerattrib
->print(get_fullname().c_str());
6760 SubtypeConstraint::subtype_t
Type::get_subtype_type()
6762 Type
* t
= get_type_refd_last();
6763 switch (t
->get_typetype()) {
6766 return SubtypeConstraint::ST_INTEGER
;
6768 return SubtypeConstraint::ST_FLOAT
;
6770 return SubtypeConstraint::ST_BOOLEAN
;
6772 return SubtypeConstraint::ST_VERDICTTYPE
;
6775 return SubtypeConstraint::ST_OBJID
;
6778 return SubtypeConstraint::ST_BITSTRING
;
6780 return SubtypeConstraint::ST_HEXSTRING
;
6782 return SubtypeConstraint::ST_OCTETSTRING
;
6783 case T_TELETEXSTRING
:
6784 case T_VIDEOTEXSTRING
:
6785 case T_GRAPHICSTRING
:
6786 case T_GENERALSTRING
:
6787 case T_OBJECTDESCRIPTOR
:
6790 case T_NUMERICSTRING
:
6791 case T_PRINTABLESTRING
:
6793 case T_VISIBLESTRING
:
6795 case T_GENERALIZEDTIME
:
6796 return SubtypeConstraint::ST_CHARSTRING
;
6799 case T_UNIVERSALSTRING
:
6801 return SubtypeConstraint::ST_UNIVERSAL_CHARSTRING
;
6804 case T_NULL
: // FIXME: this should have it's own ST_NULL case
6805 return SubtypeConstraint::ST_ENUM
;
6808 case T_ANYTYPE
: // (titan's hacked anytype is a choice)
6810 return SubtypeConstraint::ST_UNION
;
6812 return SubtypeConstraint::ST_RECORDOF
;
6814 return SubtypeConstraint::ST_SETOF
;
6817 case T_EXTERNAL
: // associated ASN.1 type is a SEQUENCE
6818 case T_EMBEDDED_PDV
: // associated ASN.1 type is a SEQUENCE
6819 case T_UNRESTRICTEDSTRING
: // associated ASN.1 type is a SEQUENCE
6820 return SubtypeConstraint::ST_RECORD
;
6823 return SubtypeConstraint::ST_SET
;
6825 return SubtypeConstraint::ST_FUNCTION
;
6827 return SubtypeConstraint::ST_ALTSTEP
;
6829 return SubtypeConstraint::ST_TESTCASE
;
6831 return SubtypeConstraint::ST_ERROR
;
6835 void Type::set_parsed_restrictions(vector
<SubTypeParse
> *stp
)
6837 if(!parsed_restr
)parsed_restr
=stp
;
6838 else FATAL_ERROR("Type::set_parsed_restrictions(): restrictions "
6839 "are already set.");
6842 bool Type::is_component_internal()
6844 if (!checked
) chk();
6851 return u
.fatref
.runs_on
.self
;
6855 return u
.secho
.component_internal
;
6858 return u
.seof
.component_internal
;
6860 return u
.array
.component_internal
;
6862 return u
.signature
.component_internal
;
6865 return u
.ref
.component_internal
;
6871 void Type::chk_component_internal(map
<Type
*,void>& type_chain
,
6874 Type
* t_last
= get_type_refd_last();
6875 switch (t_last
->typetype
) {
6876 // types that cannot be sent
6878 error("Default type cannot be %s", p_what
);
6881 error("Port type `%s' cannot be %s", t_last
->get_typename().c_str(),
6885 if (t_last
->u
.fatref
.runs_on
.self
) {
6886 error("Function type `%s' with 'runs on self' clause cannot be %s",
6887 t_last
->get_typename().c_str(), p_what
);
6891 if (t_last
->u
.fatref
.runs_on
.self
) {
6892 error("Altstep type `%s' with 'runs on self' clause cannot be %s",
6893 t_last
->get_typename().c_str(), p_what
);
6896 // structured types that may contain types that cannot be sent
6904 if (type_chain
.has_key(t_last
)) break;
6905 type_chain
.add(t_last
, 0);
6906 Error_Context
cntxt(this, "In type `%s'", get_typename().c_str());
6907 switch (t_last
->typetype
) {
6911 size_t nof_comps
= t_last
->get_nof_comps();
6912 for (size_t i
=0; i
<nof_comps
; i
++) {
6913 Type
* t
= t_last
->get_comp_byIndex(i
)->get_type();
6914 if (t
->is_component_internal())
6915 t
->chk_component_internal(type_chain
, p_what
);
6920 if (t_last
->u
.seof
.ofType
->is_component_internal())
6921 t_last
->u
.seof
.ofType
->chk_component_internal(type_chain
, p_what
);
6924 if (t_last
->u
.array
.element_type
->is_component_internal())
6925 t_last
->u
.array
.element_type
->chk_component_internal(type_chain
,
6929 if (t_last
->u
.signature
.parameters
) {
6930 size_t nof_params
= t_last
->u
.signature
.parameters
->get_nof_params();
6931 for (size_t i
=0; i
<nof_params
; i
++) {
6932 Type
* t
= t_last
->u
.signature
.parameters
->
6933 get_param_byIndex(i
)->get_type();
6934 if (t
->is_component_internal())
6935 t
->chk_component_internal(type_chain
, p_what
);
6938 if (t_last
->u
.signature
.return_type
&&
6939 t_last
->u
.signature
.return_type
->is_component_internal()) {
6940 t_last
->u
.signature
.return_type
->chk_component_internal(type_chain
,
6943 if (t_last
->u
.signature
.exceptions
) {
6944 size_t nof_types
= t_last
->u
.signature
.exceptions
->get_nof_types();
6945 for (size_t i
=0; i
<nof_types
; i
++) {
6946 Type
* t
= t_last
->u
.signature
.exceptions
->get_type_byIndex(i
);
6947 if (t
->is_component_internal())
6948 t
->chk_component_internal(type_chain
, p_what
);
6953 FATAL_ERROR("Type::chk_component_internal()");
6955 type_chain
.erase(t_last
);
6957 default: //all other types are Ok.
6962 Type::typetype_t
Type::search_for_not_allowed_type(map
<Type
*,void>& type_chain
,
6963 map
<typetype_t
, void>& not_allowed
)
6965 if (!checked
) chk();
6966 Type
* t_last
= get_type_refd_last();
6967 Type::typetype_t ret
= t_last
->typetype
;
6969 if (not_allowed
.has_key(t_last
->typetype
)) {
6973 switch (t_last
->typetype
) {
6980 if (type_chain
.has_key(t_last
)) {
6983 type_chain
.add(t_last
, 0);
6984 switch (t_last
->typetype
) {
6988 size_t nof_comps
= t_last
->get_nof_comps();
6989 for (size_t i
= 0; i
< nof_comps
; ++i
) {
6990 Type
* t
= t_last
->get_comp_byIndex(i
)->get_type();
6991 ret
= t
->search_for_not_allowed_type(type_chain
, not_allowed
);
6992 if (not_allowed
.has_key(ret
)) {
7000 ret
= t_last
->get_ofType()->search_for_not_allowed_type(type_chain
, not_allowed
);
7001 if (not_allowed
.has_key(ret
)) {
7008 type_chain
.erase(t_last
);
7014 return t_last
->typetype
;
7017 string
Type::get_dispname() const
7019 string dispname
= genname
;
7021 while(pos
< dispname
.size()) {
7022 pos
= dispname
.find("__", pos
);
7023 if (pos
== dispname
.size()) {
7026 dispname
.replace(pos
, 1, "");
7032 bool Type::is_pregenerated()
7034 // records/sets of base types are already pre-generated, only a type alias will be generated
7035 // exception: record of universal charstring with the XER coding instruction "anyElement"
7036 if (!force_gen_seof
&& (T_SEQOF
== get_type_refd_last()->typetype
||
7037 T_SETOF
== get_type_refd_last()->typetype
) &&
7038 (NULL
== xerattrib
|| /* check for "anyElement" at the record of type */
7039 NamespaceRestriction::UNUSED
== xerattrib
->anyElement_
.type_
) &&
7040 (NULL
== u
.seof
.ofType
->xerattrib
|| /* check for "anyElement" at the element type */
7041 NamespaceRestriction::UNUSED
== u
.seof
.ofType
->xerattrib
->anyElement_
.type_
)) {
7042 switch(u
.seof
.ofType
->get_type_refd_last()->typetype
) {
7052 case T_NUMERICSTRING
:
7053 case T_PRINTABLESTRING
:
7055 case T_VISIBLESTRING
:
7056 case T_UNRESTRICTEDSTRING
:
7058 case T_GENERALIZEDTIME
:
7061 case T_TELETEXSTRING
:
7062 case T_VIDEOTEXSTRING
:
7063 case T_GRAPHICSTRING
:
7064 case T_GENERALSTRING
:
7065 case T_UNIVERSALSTRING
:
7067 case T_OBJECTDESCRIPTOR
:
7076 bool Type::has_as_value_union()
7078 if (jsonattrib
!= NULL
&& jsonattrib
->as_value
) {
7081 Type
* t
= get_type_refd_last();
7082 switch (t
->get_typetype_ttcn3()) {
7084 if (t
->jsonattrib
!= NULL
&& t
->jsonattrib
->as_value
) {
7087 // no break, check alternatives
7090 for (size_t i
= 0; i
< t
->get_nof_comps(); ++i
) {
7091 if (t
->get_comp_byIndex(i
)->get_type()->has_as_value_union()) {
7098 return t
->get_ofType()->has_as_value_union();
7104 } // namespace Common