1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
24 * Szabo, Janos Zoltan – initial implementation
27 * Zalanyi, Balazs Andor
29 ******************************************************************************/
30 #include "../common/dbgnew.hh"
33 #include "Typestuff.hh" // FIXME CTs
34 #include "CompType.hh"
35 #include "TypeCompat.hh"
36 #include "CompField.hh"
37 #include "SigParam.hh"
38 #include "EnumItem.hh"
40 #include "Valuestuff.hh"
41 #include "ttcn3/ArrayDimensions.hh"
42 #include "asn1/Tag.hh"
43 #include "asn1/Block.hh"
44 #include "asn1/Ref.hh"
45 #include "Constraint.hh"
47 #include "../common/pattern.hh"
48 #include "ttcn3/Attributes.hh"
49 #include "XerAttributes.hh"
50 #include "ttcn3/Ttcnstuff.hh"
51 #include "ttcn3/TtcnTemplate.hh"
52 #include "ttcn3/Templatestuff.hh"
54 #include "../common/static_check.h"
55 #include "PredefFunc.hh"
57 // implemented in coding_attrib_p.y
58 extern Ttcn::ExtensionAttributes
* parse_extattributes(
59 Ttcn::WithAttribPath
*w_attrib_path
);
63 using Ttcn::MultiWithAttrib
;
64 using Ttcn::SingleWithAttrib
;
65 using Ttcn::WithAttribPath
;
67 const char* Type::type_as_string
[] = {
68 "undefined", // T_UNDEF
69 "erroneous", // T_ERROR
70 "null(ASN)", // T_NULL
73 "integer(ASN.1)", // T_INT_A
74 "real/float", // T_REAL
75 "enumerated(ASN.1)", // T_ENUM_A
76 "enumerated(TTCN-3)", // T_ENUM_T
77 "bitstring", // T_BSTR
78 "bitstring(ASN)", // T_BSTR_A
79 "hexstring(TTCN-3)", // T_HSTR
80 "octetstring", // T_OSTR
81 "charstring (TTCN-3)", // T_CSTR
82 "universal charstring(TTCN-3)", // T_USTR
83 "UTF8String(ASN.1)", // T_UTF8STRING
84 "NumericString(ASN.1)", // T_NUMERICSTRING
85 "PrintableString(ASN.1)", // T_PRINTABLESTRING
86 "TeletexString(ASN.1)", //T_TELETEXSTRING
87 "VideotexString(ASN.1)", // T_VIDEOTEXSTRING
88 "IA5String(ASN.1)", // T_IA5STRING
89 "GraphicString(ASN.1)", // T_GRAPHICSTRING,
90 "VisibleString(ASN.1)", // T_VISIBLESTRING
91 "GeneralString (ASN.1)", // T_GENERALSTRING
92 "UniversalString (ASN.1)", // T_UNIVERSALSTRING
93 "BMPString (ASN.1)", // T_BMPSTRING
94 "UnrestrictedCharacterString(ASN.1)", // T_UNRESTRICTEDSTRING
95 "UTCTime(ASN.1)", // T_UTCTIME
96 "GeneralizedTime(ASN.1)", // T_GENERALIZEDTIME
97 "Object descriptor, a kind of string (ASN.1)", // T_OBJECTDESCRIPTOR
98 "object identifier", // T_OID
99 "relative OID(ASN.1)", // T_ROID
100 "choice(ASN-1)", // T_CHOICE_A
101 "union(TTCN-3)", // T_CHOICE_T
102 "sequence (record) of", // T_SEQOF
104 "sequence(ASN-1)", // T_SEQ_A
105 "record(TTCN-3)", // T_SEQ_T
106 "set(ASN.1)", // T_SET_A
107 "set(TTCN-3)", // T_SET_T
108 "ObjectClassFieldType(ASN.1)", // T_OCFT
109 "open type(ASN.1)", // T_OPENTYPE
110 "ANY(deprecated ASN.1)", // T_ANY
111 "external(ASN.1)", // T_EXTERNAL
112 "embedded PDV(ASN.1)", // T_EMBEDDED_PDV
113 "referenced", // T_REFD
114 "special referenced(by pointer, not by name)", // T_REFDSPEC
115 "selection type(ASN.1)", // T_SELTYPE
116 "verdict type(TTCN-3)", // T_VERDICT
117 "port type(TTCN-3)", // T_PORT
118 "component type(TTCN-3)", // T_COMPONENT
119 "address type(TTCN-3)", // T_ADDRESS
120 "default type (TTCN-3)", // T_DEFAULT
121 "array(TTCN-3)", // T_ARRAY
122 "signature(TTCN-3)", // T_SIGNATURE
123 "function reference(TTCN-3)", // T_FUNCTION
124 "altstep reference(TTCN-3)", // T_ALTSTEP
125 "testcase reference(TTCN-3)", // T_TESTCASE
126 "anytype(TTCN-3)", // T_ANYTYPE
129 // =================================
131 // =================================
132 const char* Type::asString() const {
133 if (this->get_typetype() < Type::T_LAST
&& Type::T_UNDEF
< this->get_typetype()) {
134 return type_as_string
[this->get_typetype()];
137 return type_as_string
[Type::T_UNDEF
];
141 const char* Type::asString(Type::typetype_t type
) {
142 if (type
< Type::T_LAST
&& Type::T_UNDEF
< type
) {
143 return type_as_string
[type
];
146 return type_as_string
[Type::T_UNDEF
];
150 // Used by dump() for user-readable messages, by Def_ExtFunction::generate_*
151 // The text returned must match the case label without the "CT_" !
152 const char *Type::get_encoding_name(MessageEncodingType_t encoding_type
)
154 ENSURE_EQUAL(Type::T_UNDEF
, 0);
155 ENSURE_EQUAL(Type::OT_UNKNOWN
, 0);
156 switch (encoding_type
) {
172 return "<unknown encoding>";
176 Type
*Type::get_stream_type(MessageEncodingType_t encoding_type
, int stream_variant
)
178 switch (encoding_type
) {
182 case CT_XER
: // UTF-8 doesn't fit into charstring and universal is wasteful
184 return get_pooltype(T_OSTR
);
186 if(stream_variant
==0){
187 return get_pooltype(T_CSTR
);
189 return get_pooltype(T_OSTR
);
192 return get_pooltype(T_BSTR
);
194 FATAL_ERROR("Type::get_stream_type()");
199 map
<Type::typetype_t
, Type
> *Type::pooltypes
= 0;
201 Type
* Type::get_pooltype(typetype_t p_typetype
)
203 p_typetype
=get_typetype_ttcn3(p_typetype
);
219 break; // we have a pool type
221 return 0; // no pool type for you!
223 if (!pooltypes
) pooltypes
= new map
<typetype_t
, Type
>; // lazy init
224 else if (pooltypes
->has_key(p_typetype
)) return (*pooltypes
)[p_typetype
];
226 if (p_typetype
== T_COMPONENT
)
227 t
= new Type(T_COMPONENT
, new ComponentTypeBody());
228 else t
= new Type(p_typetype
);
229 t
->ownertype
= OT_POOL
;
230 pooltypes
->add(p_typetype
, t
);
234 void Type::destroy_pooltypes()
237 for(size_t i
=0; i
<pooltypes
->size(); i
++)
238 delete pooltypes
->get_nth_elem(i
);
245 Tag
*Type::get_default_tag()
247 typetype_t t_typetype
;
250 t_typetype
= T_INT_A
;
253 t_typetype
= T_BSTR_A
;
256 t_typetype
= T_ENUM_A
;
260 t_typetype
= T_SEQ_A
;
264 t_typetype
= T_SET_A
;
273 return get_type_refd()->get_tag();
275 t_typetype
= typetype
;
278 if (!default_tags
) default_tags
= new map
<typetype_t
, Tag
>;
279 else if (default_tags
->has_key(t_typetype
))
280 return (*default_tags
)[t_typetype
];
282 switch (t_typetype
) {
284 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_ALL
, (Int
)0);
287 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_ERROR
, (Int
)0);
290 int tagnumber
= get_default_tagnumber(t_typetype
);
291 if (tagnumber
< 0) FATAL_ERROR ("Type::get_default_tag():type `%s' "
292 "does not have default tag", get_typename().c_str());
293 tag
= new Tag(Tag::TAG_EXPLICIT
, Tag::TAG_UNIVERSAL
, Int(tagnumber
));
296 default_tags
->add(t_typetype
, tag
);
300 int Type::get_default_tagnumber(typetype_t p_tt
)
303 // note: tag number 0 is reserved for internal use
316 case T_OBJECTDESCRIPTOR
:
330 // note: tag numbers 14 and 15 are reserved for future use
335 case T_NUMERICSTRING
:
337 case T_PRINTABLESTRING
:
339 case T_TELETEXSTRING
:
341 case T_VIDEOTEXSTRING
:
347 case T_GENERALIZEDTIME
:
349 case T_GRAPHICSTRING
:
351 case T_VISIBLESTRING
:
353 case T_GENERALSTRING
:
355 case T_UNIVERSALSTRING
:
357 case T_UNRESTRICTEDSTRING
:
366 map
<Type::typetype_t
, Tag
> *Type::default_tags
= 0;
368 void Type::destroy_default_tags()
371 size_t nof_tags
= default_tags
->size();
372 for (size_t i
= 0; i
< nof_tags
; i
++)
373 delete default_tags
->get_nth_elem(i
);
374 default_tags
->clear();
380 Type::Type(const Type
& p
)
381 : Governor(p
), typetype(p
.typetype
)
384 if (p
.w_attrib_path
!= NULL
) FATAL_ERROR("Type::Type()");
385 tags
=p
.tags
?p
.tags
->clone():0;
387 constraints
=p
.constraints
->clone();
388 constraints
->set_my_type(this);
391 if(p
.parsed_restr
!=NULL
) {
392 parsed_restr
=new vector
<SubTypeParse
>;
393 for(size_t i
=0;i
<p
.parsed_restr
->size();i
++) {
394 SubTypeParse
*stp
= 0;
395 switch((*p
.parsed_restr
)[i
]->get_selection()) {
396 case SubTypeParse::STP_SINGLE
:
397 stp
=new SubTypeParse((*p
.parsed_restr
)[i
]->Single());
399 case SubTypeParse::STP_RANGE
:
400 stp
=new SubTypeParse((*p
.parsed_restr
)[i
]->Min(),
401 (*p
.parsed_restr
)[i
]->MinExclusive(),
402 (*p
.parsed_restr
)[i
]->Max(),
403 (*p
.parsed_restr
)[i
]->MaxExclusive());
405 case SubTypeParse::STP_LENGTH
:
406 FATAL_ERROR("Type::Type(Type&): STP_LENGTH");
408 default: FATAL_ERROR("Type::Type()");
410 parsed_restr
->add(stp
);
426 case T_NUMERICSTRING
:
427 case T_PRINTABLESTRING
:
428 case T_TELETEXSTRING
:
429 case T_VIDEOTEXSTRING
:
431 case T_GRAPHICSTRING
:
432 case T_VISIBLESTRING
:
433 case T_GENERALSTRING
:
434 case T_UNIVERSALSTRING
:
437 case T_GENERALIZEDTIME
:
438 case T_OBJECTDESCRIPTOR
:
444 case T_UNRESTRICTEDSTRING
:
450 u
.namednums
.block
=p
.u
.namednums
.block
?p
.u
.namednums
.block
->clone():0;
451 u
.namednums
.nvs
=p
.u
.namednums
.nvs
?p
.u
.namednums
.nvs
->clone():0;
454 u
.enums
.block
=p
.u
.enums
.block
?p
.u
.enums
.block
->clone():0;
455 u
.enums
.eis1
=p
.u
.enums
.eis1
?p
.u
.enums
.eis1
->clone():0;
456 u
.enums
.ellipsis
=p
.u
.enums
.ellipsis
;
457 u
.enums
.excSpec
=p
.u
.enums
.excSpec
?p
.u
.enums
.excSpec
->clone():0;
458 u
.enums
.eis2
=p
.u
.enums
.eis2
?p
.u
.enums
.eis2
->clone():0;
461 u
.enums
.eis
=p
.u
.enums
.eis
->clone();
462 u
.enums
.eis_by_name
=0;
468 u
.secho
.cfm
=p
.u
.secho
.cfm
->clone();
469 u
.secho
.field_by_name
= 0;
470 u
.secho
.component_internal
= false;
471 u
.secho
.has_single_charenc
= false;
475 u
.secho
.tr_compsof_ready
=p
.u
.secho
.tr_compsof_ready
;
479 u
.secho
.block
=p
.u
.secho
.block
?p
.u
.secho
.block
->clone():0;
480 u
.secho
.ctss
=p
.u
.secho
.ctss
?p
.u
.secho
.ctss
->clone():0;
481 u
.secho
.field_by_name
= 0;
482 u
.secho
.component_internal
= false;
483 u
.secho
.has_single_charenc
= false;
487 u
.seof
.ofType
=p
.u
.seof
.ofType
->clone();
488 u
.seof
.component_internal
= false;
491 u
.ref
.ref
=p
.u
.ref
.ref
->clone();
493 u
.ref
.component_internal
= false;
496 u
.ref
.oc_defn
=p
.u
.ref
.oc_defn
;
497 u
.ref
.oc_fieldname
=p
.u
.ref
.oc_fieldname
;
500 u
.ref
.type_refd
=p
.u
.ref
.type_refd
;
501 u
.ref
.component_internal
= false;
504 u
.seltype
.id
=p
.u
.seltype
.id
->clone();
505 u
.seltype
.type
=p
.u
.seltype
.type
->clone();
506 u
.seltype
.type_refd
=0;
509 u
.secho
.cfm
=new CompFieldMap();
510 u
.secho
.cfm
->set_my_type(this);
511 u
.secho
.oc_defn
=p
.u
.secho
.oc_defn
;
512 u
.secho
.oc_fieldname
=p
.u
.secho
.oc_fieldname
;
513 u
.secho
.my_tableconstraint
=0;
514 u
.secho
.field_by_name
= 0;
515 u
.secho
.component_internal
= false;
516 u
.secho
.has_single_charenc
= false;
519 u
.array
.element_type
=p
.u
.array
.element_type
->clone();
520 u
.array
.dimension
= p
.u
.array
.dimension
->clone();
521 u
.array
.in_typedef
= p
.u
.array
.in_typedef
;
522 u
.array
.component_internal
= false;
525 u
.port
= p
.u
.port
->clone();
528 u
.component
= p
.u
.component
->clone();
534 u
.signature
.parameters
= p
.u
.signature
.parameters
?
535 p
.u
.signature
.parameters
->clone() : 0;
536 u
.signature
.return_type
= p
.u
.signature
.return_type
?
537 p
.u
.signature
.return_type
->clone() : 0;
538 u
.signature
.no_block
= p
.u
.signature
.no_block
;
539 u
.signature
.exceptions
= p
.u
.signature
.exceptions
?
540 p
.u
.signature
.exceptions
->clone() : 0;
541 u
.signature
.component_internal
= false;
545 u
.fatref
.fp_list
= p
.u
.fatref
.fp_list
->clone();
546 u
.fatref
.runs_on
.ref
= p
.u
.fatref
.runs_on
.ref
?
547 p
.u
.fatref
.runs_on
.ref
->clone() : 0;
548 u
.fatref
.runs_on
.self
= p
.u
.fatref
.runs_on
.self
;
549 u
.fatref
.runs_on
.type
= 0;
550 u
.fatref
.return_type
= p
.u
.fatref
.return_type
?
551 p
.u
.fatref
.return_type
->clone() : 0;
552 u
.fatref
.is_startable
= false;
553 u
.fatref
.returns_template
= p
.u
.fatref
.returns_template
;
554 u
.fatref
.template_restriction
= p
.u
.fatref
.template_restriction
;
557 u
.fatref
.fp_list
= p
.u
.fatref
.fp_list
->clone();
558 u
.fatref
.runs_on
.ref
= p
.u
.fatref
.runs_on
.ref
?
559 p
.u
.fatref
.runs_on
.ref
->clone() : 0;
560 u
.fatref
.runs_on
.self
= false;
561 u
.fatref
.runs_on
.type
= 0;
562 u
.fatref
.system
.ref
= p
.u
.fatref
.system
.ref
?
563 p
.u
.fatref
.system
.ref
->clone() : 0;
564 u
.fatref
.system
.type
= 0;
565 u
.fatref
.is_startable
= false;
566 u
.fatref
.returns_template
= false;
567 u
.fatref
.template_restriction
= TR_NONE
;
570 FATAL_ERROR("Type::Type()");
576 tags_checked
= false;
577 tbl_cons_checked
= false;
578 text_checked
= false;
579 json_checked
= false;
583 raw_length_calculated
= false;
584 has_opentypes
= false;
585 opentype_outermost
= false;
586 code_generated
= false;
587 embed_values_possible
= false;
588 use_nil_possible
= false;
589 use_order_possible
= false;
595 encode_attrib_path
= 0;
603 ownertype
= OT_UNKNOWN
;
605 chk_finished
= false;
606 pard_type_instance
= false;
609 void Type::clean_up()
623 case T_NUMERICSTRING
:
624 case T_PRINTABLESTRING
:
625 case T_TELETEXSTRING
:
626 case T_VIDEOTEXSTRING
:
628 case T_GRAPHICSTRING
:
629 case T_VISIBLESTRING
:
630 case T_GENERALSTRING
:
631 case T_UNIVERSALSTRING
:
634 case T_GENERALIZEDTIME
:
635 case T_OBJECTDESCRIPTOR
:
641 case T_UNRESTRICTEDSTRING
:
650 delete u
.namednums
.block
;
651 delete u
.namednums
.nvs
;
654 delete u
.enums
.block
;
656 u
.enums
.eis1
->release_eis();
660 u
.enums
.eis2
->release_eis();
666 if (u
.enums
.eis_by_name
) {
667 for (size_t a
= 0; a
< u
.enums
.eis_by_name
->size(); a
++) {
668 delete u
.enums
.eis_by_name
->get_nth_elem(a
);
670 u
.enums
.eis_by_name
->clear();
671 delete u
.enums
.eis_by_name
;
677 delete u
.secho
.block
;
686 if (u
.secho
.field_by_name
) {
687 for(size_t a
= 0; a
< u
.secho
.field_by_name
->size(); a
++) {
688 delete u
.secho
.field_by_name
->get_nth_elem(a
);
690 u
.secho
.field_by_name
->clear();
691 delete u
.secho
.field_by_name
;
696 delete u
.seof
.ofType
;
703 delete u
.seltype
.type
;
706 delete u
.array
.element_type
;
707 delete u
.array
.dimension
;
716 delete u
.signature
.parameters
;
717 delete u
.signature
.return_type
;
718 delete u
.signature
.exceptions
;
722 delete u
.fatref
.fp_list
;
723 delete u
.fatref
.runs_on
.ref
;
724 delete u
.fatref
.return_type
;
727 delete u
.fatref
.fp_list
;
728 delete u
.fatref
.runs_on
.ref
;
729 delete u
.fatref
.system
.ref
;
732 FATAL_ERROR("Type::clean_up()");
752 for (size_t i
= 0; i
< parsed_restr
->size(); i
++)
753 delete (*parsed_restr
)[i
];
754 parsed_restr
->clear();
758 delete w_attrib_path
;
760 delete encode_attrib_path
;
761 encode_attrib_path
= 0;
764 Type::Type(typetype_t p_tt
)
765 : Governor(S_T
), typetype(p_tt
)
780 case T_NUMERICSTRING
:
781 case T_PRINTABLESTRING
:
782 case T_TELETEXSTRING
:
783 case T_VIDEOTEXSTRING
:
785 case T_GRAPHICSTRING
:
786 case T_VISIBLESTRING
:
787 case T_GENERALSTRING
:
788 case T_UNIVERSALSTRING
:
791 case T_GENERALIZEDTIME
:
792 case T_OBJECTDESCRIPTOR
:
798 case T_UNRESTRICTEDSTRING
:
803 u
.secho
.cfm
= new CompFieldMap
;
804 u
.secho
.cfm
->set_my_type(this);
807 u
.secho
.field_by_name
= 0;
808 u
.secho
.component_internal
= false;
809 u
.secho
.has_single_charenc
= false;
820 FATAL_ERROR("Type::Type()");
824 Type::Type(typetype_t p_tt
, EnumItems
*p_eis
)
825 : Governor(S_T
), typetype(p_tt
)
827 if (p_tt
!= T_ENUM_T
|| !p_eis
) FATAL_ERROR("Type::Type()");
830 u
.enums
.eis_by_name
=0;
833 Type::Type(typetype_t p_tt
, Block
*p_block
)
834 : Governor(S_T
), typetype(p_tt
)
836 if (!p_block
) FATAL_ERROR("NULL parameter");
841 u
.namednums
.block
=p_block
;
845 u
.enums
.eis
=new EnumItems();
846 u
.enums
.block
=p_block
;
848 u
.enums
.ellipsis
=false;
851 u
.enums
.eis_by_name
=0;
855 u
.secho
.tr_compsof_ready
=false;
859 u
.secho
.block
=p_block
;
861 u
.secho
.field_by_name
= 0;
862 u
.secho
.component_internal
= false;
863 u
.secho
.has_single_charenc
= false;
866 FATAL_ERROR("Type::Type()");
870 Type::Type(typetype_t p_tt
,
871 EnumItems
*p_eis1
, bool p_ellipsis
, EnumItems
*p_eis2
)
872 : Governor(S_T
), typetype(p_tt
)
874 if (p_tt
!= T_ENUM_A
|| !p_eis1
) FATAL_ERROR("Type::Type()");
876 u
.enums
.eis
=new EnumItems();
879 u
.enums
.ellipsis
=p_ellipsis
;
881 u
.enums
.eis_by_name
=0;
884 Type::Type(typetype_t p_tt
, CompFieldMap
*p_cfm
)
885 : Governor(S_T
), typetype(p_tt
)
887 if (!p_cfm
) FATAL_ERROR("NULL parameter");
894 u
.secho
.field_by_name
= 0;
895 u
.secho
.component_internal
= false;
896 u
.secho
.has_single_charenc
= false;
899 FATAL_ERROR("Type::Type()");
903 Type::Type(typetype_t p_tt
, Type
*p_type
)
904 : Governor(S_T
), typetype(p_tt
)
906 if (!p_type
) FATAL_ERROR("NULL parameter");
911 u
.seof
.ofType
=p_type
;
912 u
.seof
.ofType
->set_ownertype(OT_RECORD_OF
, this);
913 u
.seof
.component_internal
= false;
916 u
.ref
.type_refd
=p_type
;
917 u
.ref
.type_refd
->set_ownertype(OT_REF_SPEC
, this);
918 u
.ref
.component_internal
= false;
921 FATAL_ERROR("Type::Type()");
925 Type::Type(typetype_t p_tt
, Identifier
*p_id
, Type
*p_type
)
926 : Governor(S_T
), typetype(p_tt
)
928 if (p_tt
!= T_SELTYPE
|| !p_id
|| !p_type
) FATAL_ERROR("Type::Type()");
931 u
.seltype
.type
=p_type
;
932 u
.seltype
.type
->set_ownertype(OT_SELTYPE
, this);
933 u
.seltype
.type_refd
=0;
936 Type::Type(typetype_t p_tt
, Type
*p_type
, Ttcn::ArrayDimension
*p_dim
,
938 : Governor(S_T
), typetype(p_tt
)
940 if (p_tt
!= T_ARRAY
|| !p_type
|| !p_dim
) FATAL_ERROR("Type::Type()");
942 u
.array
.element_type
= p_type
;
943 u
.array
.element_type
->set_ownertype(OT_ARRAY
, this);
944 u
.array
.dimension
= p_dim
;
945 u
.array
.in_typedef
= p_in_typedef
;
946 u
.array
.component_internal
= false;
949 Type::Type(typetype_t p_tt
, Type
*p_type
, OC_defn
*p_oc_defn
,
950 const Identifier
*p_id
)
951 : Governor(S_T
), typetype(p_tt
)
953 if (p_tt
!= T_OCFT
|| !p_type
||!p_oc_defn
|| !p_id
)
954 FATAL_ERROR("Type::Type()");
956 u
.ref
.type_refd
=p_type
;
957 u
.ref
.type_refd
->set_ownertype(OT_OCFT
, this);
958 u
.ref
.oc_defn
=p_oc_defn
;
959 u
.ref
.oc_fieldname
=p_id
;
960 u
.ref
.component_internal
= false;
963 Type::Type(typetype_t p_tt
, OC_defn
*p_oc_defn
,
964 const Identifier
*p_id
)
965 : Governor(S_T
), typetype(p_tt
)
967 if (p_tt
!= T_OPENTYPE
|| !p_oc_defn
|| !p_id
) FATAL_ERROR("Type::Type()");
970 u
.secho
.cfm
=new CompFieldMap();
971 u
.secho
.cfm
->set_my_type(this);
972 u
.secho
.oc_defn
=p_oc_defn
;
973 u
.secho
.oc_fieldname
=p_id
;
974 u
.secho
.my_tableconstraint
=0;
975 u
.secho
.field_by_name
= 0;
976 u
.secho
.component_internal
= false;
977 u
.secho
.has_single_charenc
= false;
980 Type::Type(typetype_t p_tt
, Reference
*p_ref
)
981 : Governor(S_T
), typetype(p_tt
)
983 if (p_tt
!= T_REFD
|| !p_ref
) FATAL_ERROR("Type::Type()");
987 u
.ref
.component_internal
= false;
990 Type::Type(typetype_t p_tt
, Ttcn::PortTypeBody
*p_pb
)
991 : Governor(S_T
), typetype(p_tt
)
993 if (p_tt
!= T_PORT
|| !p_pb
) FATAL_ERROR("Type::Type()");
996 p_pb
->set_my_type(this);
999 Type::Type(typetype_t p_tt
, ComponentTypeBody
*p_cb
)
1000 : Governor(S_T
), typetype(p_tt
)
1002 if (p_tt
!= T_COMPONENT
|| !p_cb
) FATAL_ERROR("Type::Type()");
1005 p_cb
->set_my_type(this);
1008 Type::Type(typetype_t p_tt
, SignatureParamList
*p_params
, Type
*p_returntype
,
1009 bool p_noblock
, SignatureExceptions
*p_exceptions
)
1010 : Governor(S_T
), typetype(p_tt
)
1012 if (p_tt
!= T_SIGNATURE
|| (p_returntype
&& p_noblock
))
1013 FATAL_ERROR("Type::Type()");
1015 u
.signature
.parameters
= p_params
;
1016 if ((u
.signature
.return_type
= p_returntype
)) { // check assignment for 0
1017 u
.signature
.return_type
->set_ownertype(OT_SIGNATURE
, this);
1019 u
.signature
.no_block
= p_noblock
;
1020 u
.signature
.exceptions
= p_exceptions
;
1021 u
.signature
.component_internal
= false;
1024 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1025 Ttcn::Reference
* p_runs_on_ref
, bool p_runs_on_self
,
1026 Type
*p_returntype
, bool p_returns_template
,
1027 template_restriction_t p_template_restriction
)
1028 : Governor(S_T
), typetype(p_tt
)
1030 if (p_tt
!= T_FUNCTION
|| !p_params
|| (!p_returntype
&& p_returns_template
)
1031 || (p_runs_on_ref
&& p_runs_on_self
)) FATAL_ERROR("Type::Type()");
1033 u
.fatref
.fp_list
= p_params
;
1034 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1035 u
.fatref
.runs_on
.self
= p_runs_on_self
;
1036 u
.fatref
.runs_on
.type
= 0;
1037 if ((u
.fatref
.return_type
= p_returntype
)) { // check assignment for 0
1038 u
.fatref
.return_type
->set_ownertype(OT_FUNCTION
, this);
1040 u
.fatref
.is_startable
= false;
1041 u
.fatref
.returns_template
= p_returns_template
;
1042 u
.fatref
.template_restriction
= p_template_restriction
;
1045 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1046 Ttcn::Reference
* p_runs_on_ref
, bool p_runs_on_self
)
1047 : Governor(S_T
), typetype(p_tt
)
1049 if(p_tt
!= T_ALTSTEP
|| !p_params
|| (p_runs_on_ref
&& p_runs_on_self
))
1050 FATAL_ERROR("Type::Type()");
1052 u
.fatref
.fp_list
= p_params
;
1053 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1054 u
.fatref
.runs_on
.self
= p_runs_on_self
;
1055 u
.fatref
.runs_on
.type
= 0;
1056 u
.fatref
.return_type
= 0;
1057 u
.fatref
.is_startable
= false;
1058 u
.fatref
.returns_template
= false;
1059 u
.fatref
.template_restriction
= TR_NONE
;
1062 Type::Type(typetype_t p_tt
,Ttcn::FormalParList
*p_params
,
1063 Ttcn::Reference
* p_runs_on_ref
, Ttcn::Reference
*p_system_ref
)
1064 : Governor(S_T
), typetype(p_tt
)
1066 if(p_tt
!= T_TESTCASE
|| !p_params
|| !p_runs_on_ref
)
1067 FATAL_ERROR("Type::Type()");
1069 u
.fatref
.fp_list
= p_params
;
1070 u
.fatref
.runs_on
.ref
= p_runs_on_ref
;
1071 u
.fatref
.runs_on
.self
= false;
1072 u
.fatref
.runs_on
.type
= 0;
1073 u
.fatref
.system
.ref
= p_system_ref
;
1074 u
.fatref
.system
.type
= 0;
1075 u
.fatref
.is_startable
= false;
1076 u
.fatref
.returns_template
= false;
1077 u
.fatref
.template_restriction
= TR_NONE
;
1085 void Type::free_pools()
1087 destroy_default_tags();// Additionally: R&S license warning
1088 destroy_pooltypes();// Additionally: R&S license checkin/disconnect/shutdown
1091 Type
*Type::clone() const
1093 return new Type(*this);
1096 Type::typetype_t
Type::get_typetype_ttcn3(typetype_t p_tt
)
1107 case T_UNIVERSALSTRING
:
1109 case T_TELETEXSTRING
:
1110 case T_VIDEOTEXSTRING
:
1111 case T_GRAPHICSTRING
:
1112 case T_OBJECTDESCRIPTOR
:
1113 case T_GENERALSTRING
:
1115 case T_NUMERICSTRING
:
1116 case T_PRINTABLESTRING
:
1118 case T_VISIBLESTRING
:
1120 case T_GENERALIZEDTIME
:
1131 case T_EMBEDDED_PDV
:
1132 case T_UNRESTRICTEDSTRING
:
1138 } // switch typetype
1141 bool Type::is_asn1() const
1143 if (my_scope
) return Setting::is_asn1();
1144 // the type might be a pool type, which is considered to be a TTCN-3 type
1145 typetype_t t_typetype
= get_typetype_ttcn3(typetype
);
1146 if (pooltypes
&& pooltypes
->has_key(t_typetype
) &&
1147 (*pooltypes
)[t_typetype
] == this) return false;
1148 else FATAL_ERROR("Type::is_asn1()");
1151 bool Type::is_ref() const
1154 case T_UNRESTRICTEDSTRING
:
1157 case T_EMBEDDED_PDV
:
1168 bool Type::is_secho() const
1185 Type::truth
Type::is_charenc()
1191 bool possible
= true;
1192 size_t ncomp
= u
.secho
.cfm
->get_nof_comps();
1193 for (size_t i
=0; i
<ncomp
; ++i
) {
1194 CompField
* cf
= u
.secho
.cfm
->get_comp_byIndex(i
);
1195 if (cf
->get_type()->is_charenc() == No
) {
1196 possible
= false; break;
1200 return (xerattrib
&& (xerattrib
->useUnion_
|| xerattrib
->useType_
)) ? Yes
: No
;
1209 // UNTAGGED cannot be used to make a type character-encodable!
1210 // But USE-QNAME can!
1211 return (xerattrib
&& xerattrib
->useQName_
) ? Yes
: No
;
1213 case T_SEQOF
: // A record-of is character-encodable if it has the "list"
1214 case T_SETOF
: // attribute and its element is character-encodable.
1215 return (xerattrib
&& xerattrib
->list_
&& (u
.seof
.ofType
->is_charenc()==Yes
))
1225 truth retval
= get_type_refd_last()->is_charenc();
1226 if (retval
== Yes
) return Yes
;
1227 else if (retval
== Maybe
) {
1228 if (xerattrib
&& xerattrib
->useUnion_
) return Yes
;
1230 // else fall through to No
1240 // TODO ASN.1 restricted character string types when (if) ASN.1 gets XER
1241 // TODO check subtype; strings must be restricted to not contain
1242 // control characters (0..0x1F except 9,0x0A,0x0D)
1248 /* FIXME : this kind of check should be applied to elements of secho,
1249 * not to the type of the element ! */
1254 bool Type::has_empty_xml() {
1255 bool answer
= false;
1257 case T_SEQ_A
: case T_SEQ_T
:
1258 case T_SET_A
: case T_SET_T
: {
1259 answer
= true; // If all components are optional.
1260 size_t n_comps
= get_nof_comps();
1261 for (size_t i
= 0; i
< n_comps
; ++i
) {
1262 CompField
* cf
= get_comp_byIndex(i
);
1263 if (!cf
->get_is_optional()) {
1269 case T_SEQOF
: case T_SETOF
:
1270 // _If_ there is a length restriction, 0 length must be allowed.
1271 // By this time parsed_restr has been absorbed into sub_type.
1272 answer
= (sub_type
==0) || sub_type
->zero_length_allowed();
1280 void Type::set_fullname(const string
& p_fullname
)
1282 Governor::set_fullname(p_fullname
);
1286 if(u
.namednums
.block
) u
.namednums
.block
->set_fullname(p_fullname
);
1288 u
.namednums
.nvs
->set_fullname(p_fullname
+".<namedvalues>");
1291 if(u
.enums
.eis1
) u
.enums
.eis1
->set_fullname(p_fullname
);
1292 if(u
.enums
.eis2
) u
.enums
.eis2
->set_fullname(p_fullname
);
1295 u
.enums
.eis
->set_fullname(p_fullname
);
1302 u
.secho
.cfm
->set_fullname(p_fullname
);
1307 if (u
.secho
.ctss
) u
.secho
.ctss
->set_fullname(p_fullname
);
1311 string
subtypename(".<oftype>");
1312 Type
* t
= u
.seof
.ofType
;
1313 /* Do NOT call get_type_refd_last() or else fatal_error !
1314 * The AST is not fully set up. */
1316 /* XER will use these strings */
1317 switch (t
->typetype
)
1319 case T_EMBEDDED_PDV
: case T_EXTERNAL
:
1320 case T_SEQ_A
: case T_SEQ_T
:
1321 subtypename
= ".SEQUENCE";
1324 case T_SET_A
: case T_SET_T
:
1325 subtypename
= ".SET";
1329 subtypename
= ".SEQUENCE_OF";
1333 subtypename
= ".SET_OF";
1337 subtypename
= ".BITSTRING";
1341 subtypename
= ".BOOLEAN";
1344 case T_CHOICE_A
: case T_CHOICE_T
:
1345 subtypename
= ".CHOICE";
1348 case T_ENUM_A
: case T_ENUM_T
:
1349 subtypename
= ".ENUMERATED";
1352 case T_INT_A
: case T_INT
:
1353 subtypename
= ".INTEGER";
1359 u
.seof
.ofType
->set_fullname(p_fullname
+subtypename
);
1362 u
.ref
.ref
->set_fullname(p_fullname
);
1365 u
.seltype
.type
->set_fullname(p_fullname
+".<selection>");
1368 u
.port
->set_fullname(p_fullname
);
1371 u
.component
->set_fullname(p_fullname
);
1374 u
.array
.element_type
->set_fullname(p_fullname
+ ".<element_type>");
1375 u
.array
.dimension
->set_fullname(p_fullname
+ ".<dimension>");
1378 if (u
.signature
.parameters
)
1379 u
.signature
.parameters
->set_fullname(p_fullname
);
1380 if (u
.signature
.return_type
)
1381 u
.signature
.return_type
->set_fullname(p_fullname
+ ".<return_type>");
1382 if (u
.signature
.exceptions
)
1383 u
.signature
.exceptions
->set_fullname(p_fullname
+ ".<exception_list>");
1387 u
.fatref
.fp_list
->set_fullname(p_fullname
+ "<formal_par_list>");
1388 if (u
.fatref
.runs_on
.ref
)
1389 u
.fatref
.runs_on
.ref
->set_fullname(p_fullname
+ "<runs_on_type>");
1390 if (u
.fatref
.return_type
)
1391 u
.fatref
.return_type
->set_fullname(p_fullname
+ "<return type>");
1394 u
.fatref
.fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
1395 if (u
.fatref
.runs_on
.ref
)
1396 u
.fatref
.runs_on
.ref
->set_fullname(p_fullname
+".<runs_on_type>");
1397 if (u
.fatref
.system
.ref
)
1398 u
.fatref
.system
.ref
->set_fullname(p_fullname
+ ".<system_type>");
1405 void Type::set_my_scope(Scope
*p_scope
)
1407 Governor::set_my_scope(p_scope
);
1408 if(tags
) tags
->set_my_scope(p_scope
);
1412 if(u
.namednums
.nvs
) u
.namednums
.nvs
->set_my_scope(p_scope
);
1415 if(u
.enums
.eis1
) u
.enums
.eis1
->set_my_scope(p_scope
);
1416 if(u
.enums
.eis2
) u
.enums
.eis2
->set_my_scope(p_scope
);
1419 u
.enums
.eis
->set_my_scope(p_scope
);
1426 u
.secho
.cfm
->set_my_scope(p_scope
);
1431 if(u
.secho
.ctss
) u
.secho
.ctss
->set_my_scope(p_scope
);
1435 u
.seof
.ofType
->set_my_scope(p_scope
);
1438 u
.ref
.ref
->set_my_scope(p_scope
);
1441 u
.seltype
.type
->set_my_scope(p_scope
);
1444 u
.array
.element_type
->set_my_scope(p_scope
);
1445 u
.array
.dimension
->set_my_scope(p_scope
);
1448 u
.port
->set_my_scope(p_scope
);
1451 if (u
.signature
.parameters
)
1452 u
.signature
.parameters
->set_my_scope(p_scope
);
1453 if (u
.signature
.return_type
)
1454 u
.signature
.return_type
->set_my_scope(p_scope
);
1455 if (u
.signature
.exceptions
)
1456 u
.signature
.exceptions
->set_my_scope(p_scope
);
1459 u
.component
->set_my_scope(p_scope
);
1463 // the scope of parameter list is set later in chk_Fat()
1464 if (u
.fatref
.runs_on
.ref
)
1465 u
.fatref
.runs_on
.ref
->set_my_scope(p_scope
);
1466 if (u
.fatref
.return_type
)
1467 u
.fatref
.return_type
->set_my_scope(p_scope
);
1470 // the scope of parameter list is set later in chk_Fat()
1471 if (u
.fatref
.runs_on
.ref
)
1472 u
.fatref
.runs_on
.ref
->set_my_scope(p_scope
);
1473 if (u
.fatref
.system
.ref
)
1474 u
.fatref
.system
.ref
->set_my_scope(p_scope
);
1481 Type
* Type::get_type_refd(ReferenceChain
*refch
)
1485 if(refch
&& !refch
->add(get_fullname())) goto error
;
1486 if(!u
.ref
.type_refd
) {
1487 Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1488 if (!ass
) goto error
; // The referenced assignment is not found
1489 switch (ass
->get_asstype()) {
1490 case Assignment::A_ERROR
:
1492 case Assignment::A_TYPE
:
1493 case Assignment::A_VS
:
1494 u
.ref
.type_refd
= ass
->get_Type()->get_field_type(
1495 u
.ref
.ref
->get_subrefs(), EXPECTED_DYNAMIC_VALUE
, refch
);
1496 if (!u
.ref
.type_refd
) goto error
;
1498 //case Assignment::A_VS:
1499 //u.ref.type_refd = ass->get_Type();
1500 // if(!u.ref.type_refd) goto error;
1502 case Assignment::A_OC
:
1503 case Assignment::A_OBJECT
:
1504 case Assignment::A_OS
: {
1505 Setting
*setting
= u
.ref
.ref
->get_refd_setting();
1506 if (!setting
|| setting
->get_st() == Setting::S_ERROR
) goto error
;
1508 u
.ref
.type_refd
= dynamic_cast<Type
*>(setting
);
1509 if(!u
.ref
.type_refd
) {
1510 error("`%s' is not a reference to a type",
1511 u
.ref
.ref
->get_dispname().c_str());
1515 if (u
.ref
.type_refd
->ownertype
== OT_UNKNOWN
) {
1516 u
.ref
.type_refd
->set_ownertype(OT_REF
, this);
1521 error("`%s' is not a reference to a type",
1522 u
.ref
.ref
->get_dispname().c_str());
1525 if(!u
.ref
.type_refd
->get_my_scope()) {
1527 u
.ref
.type_refd
->set_my_scope(get_my_scope());
1528 u
.ref
.type_refd
->set_parent_type(get_parent_type());
1529 u
.ref
.type_refd
->set_genname(get_genname_own(), string("type"));
1530 u
.ref
.type_refd
->set_fullname(get_fullname()+".type");
1532 if (u
.ref
.type_refd
->typetype
== T_OPENTYPE
&& !constraints
)
1533 warning("An open type without table constraint is useless in TTCN-3");
1535 return u
.ref
.type_refd
;
1538 if(refch
&& !refch
->add(get_fullname())) goto error
;
1539 if(!u
.seltype
.type_refd
) {
1540 Type
*t
=u
.seltype
.type
->get_type_refd_last(refch
);
1541 if(t
->typetype
==T_ERROR
) goto error
;
1542 if(t
->typetype
!=T_CHOICE_A
) {
1543 error("(Reference to) a CHOICE type was expected"
1544 " in selection type.");
1547 if(!t
->has_comp_withName(*u
.seltype
.id
)) {
1548 error("No alternative with name `%s' in the given type `%s'.",
1549 u
.seltype
.id
->get_dispname().c_str(),
1550 t
->get_fullname().c_str());
1553 u
.seltype
.type_refd
=t
->get_comp_byName(*u
.seltype
.id
)->get_type();
1555 return u
.seltype
.type_refd
;
1559 if(refch
&& !refch
->add(get_fullname())) goto error
;
1560 return u
.ref
.type_refd
;
1563 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1564 Identifier
t_id(Identifier::ID_ASN
, string("EXTERNAL"));
1565 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1566 case T_EMBEDDED_PDV
: {
1567 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1568 Identifier
t_id(Identifier::ID_ASN
, string("EMBEDDED PDV"));
1569 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1570 case T_UNRESTRICTEDSTRING
: {
1571 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1572 Identifier
t_id(Identifier::ID_ASN
, string("CHARACTER STRING"));
1573 return my_scope
->get_scope_asss()->get_local_ass_byId(t_id
)->get_Type(); }
1575 if (refch
&& !refch
->add(get_fullname())) goto error
;
1576 if (u
.address
) return u
.address
;
1577 if (!my_scope
) FATAL_ERROR("Type::get_type_refd()");
1578 u
.address
= my_scope
->get_scope_mod()->get_address_type();
1580 error("Type `address' is not defined in this module");
1585 FATAL_ERROR("Type::get_type_refd()");
1593 Type
* Type::get_type_refd_last(ReferenceChain
*refch
)
1596 while(t
->is_ref()) t
=t
->get_type_refd(refch
);
1600 Type
*Type::get_field_type(Ttcn::FieldOrArrayRefs
*subrefs
,
1601 expected_value_t expected_index
, ReferenceChain
*refch
,
1602 bool interrupt_if_optional
)
1604 if (!subrefs
) return this;
1606 if (expected_index
== EXPECTED_TEMPLATE
)
1607 expected_index
= EXPECTED_DYNAMIC_VALUE
;
1608 size_t nof_refs
= subrefs
->get_nof_refs();
1609 subrefs
->clear_string_element_ref();
1610 for (size_t i
= 0; i
< nof_refs
; i
++) {
1611 if (refch
) refch
->mark_state();
1612 t
= t
->get_type_refd_last(refch
);
1613 if (refch
) refch
->prev_state();
1614 // stop immediately if current type t is erroneous
1615 // (e.g. because of circular reference)
1616 if (t
->typetype
== T_ERROR
) return 0;
1617 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1618 switch (ref
->get_type()) {
1619 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
1620 if (t
->typetype
== T_OPENTYPE
) {
1621 // allow the alternatives of open types as both lower and upper identifiers
1622 ref
->set_field_name_to_lowercase();
1624 const Identifier
& id
= *ref
->get_id();
1625 switch (t
->typetype
) {
1636 ref
->error("Referencing fields of a component is not allowed");
1639 ref
->error("Invalid field reference `%s': type `%s' "
1640 "does not have fields", id
.get_dispname().c_str(),
1641 t
->get_typename().c_str());
1644 if (!t
->has_comp_withName(id
)) {
1645 ref
->error("Reference to non-existent field `%s' in type `%s'",
1646 id
.get_dispname().c_str(),
1647 t
->get_typename().c_str());
1650 CompField
* cf
= t
->get_comp_byName(id
);
1651 if (interrupt_if_optional
&& cf
->get_is_optional()) return 0;
1654 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
1655 Type
*embedded_type
= 0;
1656 switch (t
->typetype
) {
1659 embedded_type
= t
->u
.seof
.ofType
;
1662 embedded_type
= t
->u
.array
.element_type
;
1671 case T_NUMERICSTRING
:
1672 case T_PRINTABLESTRING
:
1673 case T_TELETEXSTRING
:
1674 case T_VIDEOTEXSTRING
:
1676 case T_GRAPHICSTRING
:
1677 case T_VISIBLESTRING
:
1678 case T_GENERALSTRING
:
1679 case T_UNIVERSALSTRING
:
1682 case T_GENERALIZEDTIME
:
1683 case T_OBJECTDESCRIPTOR
:
1684 if (subrefs
->refers_to_string_element()) {
1685 ref
->error("A string element of type `%s' cannot be indexed",
1686 t
->get_typename().c_str());
1689 subrefs
->set_string_element_ref();
1690 // string elements have the same type as the string itself
1695 ref
->error("Type `%s' cannot be indexed",
1696 t
->get_typename().c_str());
1699 // check the index value
1700 Value
*index_value
= ref
->get_val();
1701 if (t
->typetype
== T_ARRAY
) {
1702 // checking of array index is performed by the array dimension
1703 t
->u
.array
.dimension
->chk_index(index_value
, expected_index
);
1705 // perform a generic index check for other types
1706 if (refch
== 0 // variable assignment
1707 || index_value
->get_valuetype() != Value::V_NOTUSED
) {
1708 Error_Context
cntxt(index_value
, "In index value");
1709 index_value
->chk_expr_int(expected_index
);
1711 Value
*v_last
= index_value
->get_value_refd_last();
1712 if (v_last
->get_valuetype() == Value::V_INT
) {
1713 const int_val_t
*index_int
= v_last
->get_val_Int();
1714 if (*index_int
> INT_MAX
) {
1715 index_value
->error("Integer value `%s' is too big for indexing "
1716 "type `%s'", (index_int
->t_str()).c_str(),
1717 (t
->get_typename()).c_str());
1718 index_value
->set_valuetype(Value::V_ERROR
);
1720 if (*index_int
< 0) {
1721 index_value
->error("A non-negative integer value was "
1722 "expected for indexing type `%s' instead of `%s'",
1723 t
->get_typename().c_str(), (index_int
->t_str()).c_str());
1724 index_value
->set_valuetype(Value::V_ERROR
);
1729 // change t to the embedded type
1733 FATAL_ERROR("Type::get_field_type(): invalid reference type");
1739 bool Type::get_subrefs_as_array(const Ttcn::FieldOrArrayRefs
*subrefs
, dynamic_array
<size_t>& subrefs_array
, dynamic_array
<Type
*>& type_array
)
1741 if (!subrefs
) FATAL_ERROR("Type::get_subrefs_as_array()");
1743 size_t nof_refs
= subrefs
->get_nof_refs();
1744 for (size_t i
= 0; i
< nof_refs
; i
++) {
1745 t
= t
->get_type_refd_last();
1747 if (t
->typetype
== T_ERROR
) FATAL_ERROR("Type::get_subrefs_as_array()");
1748 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1749 size_t field_index
=0;
1750 switch (ref
->get_type()) {
1751 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
1752 const Identifier
& id
= *ref
->get_id();
1753 if (!t
->has_comp_withName(id
)) FATAL_ERROR("Type::get_subrefs_as_array()");
1754 CompField
* cf
= t
->get_comp_byName(id
);
1755 field_index
= t
->get_comp_index_byName(id
);
1756 field_index
= t
->get_codegen_index(field_index
);
1759 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
1760 Value
*index_value
= ref
->get_val();
1761 Value
*v_last
= index_value
->get_value_refd_last();
1762 if (v_last
->get_valuetype()!=Value::V_INT
) {
1763 // workaround: get_field_type() does not return NULL if the index
1764 // value is invalid, this function returns false in this case
1767 const int_val_t
*index_int
= v_last
->get_val_Int();
1768 if (!index_int
->is_native() || index_int
->is_negative()) {
1771 field_index
= (size_t)index_int
->get_val();
1772 Type
*embedded_type
= 0;
1773 switch (t
->typetype
) {
1776 embedded_type
= t
->u
.seof
.ofType
;
1779 embedded_type
= t
->u
.array
.element_type
;
1785 // change t to the embedded type
1789 FATAL_ERROR("Type::get_subrefs_as_array()");
1791 subrefs_array
.add(field_index
);
1796 bool Type::is_optional_field() const {
1797 if (ownertype
== OT_COMP_FIELD
) {
1798 const CompField
* const myOwner
= (CompField
*) owner
;
1799 return myOwner
&& myOwner
->get_is_optional();
1804 bool Type::field_is_optional(Ttcn::FieldOrArrayRefs
*subrefs
)
1806 // handling trivial cases
1807 if (!subrefs
) return false;
1808 size_t nof_subrefs
= subrefs
->get_nof_refs();
1809 if (nof_subrefs
< 1) return false;
1810 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
->get_ref(nof_subrefs
- 1);
1811 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) return false;
1812 // following the embedded types
1813 Type
*t
=get_type_refd_last();
1814 for (size_t i
= 0; i
< nof_subrefs
- 1; i
++) {
1815 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
1816 if (ref
->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF
)
1817 t
= t
->get_comp_byName(*ref
->get_id())->get_type();
1818 else t
= t
->get_ofType();
1819 t
=t
->get_type_refd_last();
1821 // now last_ref refers to a field of t
1822 return t
->get_comp_byName(*last_ref
->get_id())->get_is_optional();
1825 bool Type::is_root_basic(){
1826 Type
*t
=get_type_refd_last();
1827 switch(t
->typetype
){
1842 int Type::get_raw_length(){
1843 if(!raw_checked
) FATAL_ERROR("Type::get_raw_length()");
1844 if(raw_length_calculated
) return raw_length
;
1845 raw_length_calculated
=true;
1848 raw_length
=get_type_refd()->get_raw_length();
1851 if(rawattrib
) raw_length
=rawattrib
->fieldlength
;
1855 if(rawattrib
) raw_length
=rawattrib
->fieldlength
;
1862 if(rawattrib
&& rawattrib
->fieldlength
) raw_length
=rawattrib
->fieldlength
;
1866 if(rawattrib
&& rawattrib
->fieldlength
) raw_length
=rawattrib
->fieldlength
;
1869 int max_val
=u
.enums
.first_unused
;
1870 for(size_t a
=0;a
<u
.enums
.eis
->get_nof_eis();a
++){
1871 int val
=u
.enums
.eis
->get_ei_byIndex(a
)->get_value()->get_val_Int()
1873 if((max_val
<0?-max_val
:max_val
)<(val
<0?-val
:val
)) max_val
=val
;
1875 if(max_val
<0){ min_bits
=1;max_val
=-max_val
;}
1876 while(max_val
){ min_bits
++; max_val
/=2;}
1877 raw_length
=min_bits
;
1883 for(size_t i
= 0; i
< get_nof_comps(); i
++){
1885 CompField
* cf
=get_comp_byIndex(i
);
1886 if(cf
->get_is_optional()){
1890 l
=cf
->get_type()->get_raw_length();
1895 if(cf
->get_type()->rawattrib
1896 && (cf
->get_type()->rawattrib
->pointerto
1897 || cf
->get_type()->rawattrib
->lengthto_num
)){
1904 // TODO: case T_ANYTYPE: for get_raw_length needed ?
1906 for(size_t i
= 0; i
< get_nof_comps(); i
++){
1907 CompField
*cf
=get_comp_byIndex(i
);
1909 l
=cf
->get_type()->get_raw_length();
1930 /** \todo: add extra checks and warnings for unsupported attributes
1931 * e.g. when TAG refers to a record/set field which has union type */
1932 void Type::chk_raw()
1934 bool self_ref
= false;
1935 if (raw_checked
) return;
1937 if (!enable_raw()) return;
1940 restrlength
=(int)sub_type
->get_length_restriction();
1941 if(restrlength
!=-1){
1943 Type
*t
=get_type_refd_last();
1944 typetype_t basic_type
=t
->typetype
;
1945 rawattrib
=new RawAST(basic_type
==T_INT
);
1946 if(basic_type
==T_REAL
) rawattrib
->fieldlength
=64;
1948 rawattrib
->length_restrition
=restrlength
;
1950 if(!rawattrib
) return;
1953 get_type_refd()->force_raw();
1954 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
1955 typetype_t basic_type
=get_type_refd_last()->typetype
;
1958 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
1959 rawattrib
->length_restrition
=-1;
1962 rawattrib
->fieldlength
=rawattrib
->length_restrition
*4;
1963 rawattrib
->length_restrition
=-1;
1966 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
1967 rawattrib
->length_restrition
=-1;
1971 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
1972 rawattrib
->length_restrition
=-1;
1976 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
1977 rawattrib
->length_restrition
=-1;
1986 size_t nof_comps
= get_nof_comps();
1987 for (size_t i
= 0; i
< nof_comps
; i
++)
1988 get_comp_byIndex(i
)->get_type()->force_raw();
1989 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++){
1990 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1991 if(!has_comp_withName(*idf
)){
1992 error("Invalid field name `%s' in RAW parameter TAG for type `%s'",
1993 idf
->get_dispname().c_str(), get_typename().c_str());
1996 size_t fieldnum
= get_comp_index_byName(*idf
);
1997 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1999 CompField
*cf
=get_comp_byIndex(fieldnum
);
2000 Type
*t
=cf
->get_type()->get_type_refd_last();
2001 for(int b
=0;b
<rawattrib
->taglist
.tag
[c
].keyList
[a
].
2002 keyField
->nElements
;b
++){
2004 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2006 error("Invalid fieldmember type in RAW parameter TAG"
2008 ,cf
->get_name().get_dispname().c_str());
2012 if(!t
->has_comp_withName(*idf2
)){
2013 error("Invalid field member name `%s' in RAW parameter TAG "
2014 "for field `%s'", idf2
->get_dispname().c_str(),
2015 cf
->get_name().get_dispname().c_str());
2019 size_t comp_index
=t
->get_comp_index_byName(*idf2
);
2020 CompField
*cf2
=t
->get_comp_byIndex(comp_index
);
2021 t
=cf2
->get_type()->get_type_refd_last();
2024 Error_Context
cntx(this, "In Raw parmeter TAG");
2025 Value
*v
= rawattrib
->taglist
.tag
[c
].keyList
[a
].v_value
;
2026 v
->set_my_scope(get_my_scope());
2027 v
->set_my_governor(t
);
2028 t
->chk_this_value_ref(v
);
2029 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2030 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2031 Value::valuetype_t vt
= v
->get_valuetype();
2032 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2033 Free(rawattrib
->taglist
.tag
[c
].keyList
[a
].value
);
2034 rawattrib
->taglist
.tag
[c
].keyList
[a
].value
=
2035 mcopystr(v
->get_single_expr().c_str());
2046 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++) { // check TAG
2047 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
2048 if(!has_comp_withName(*idf
)){
2049 error("Invalid field name `%s' in RAW parameter TAG "
2050 "for type `%s'", idf
->get_dispname().c_str(),
2051 get_typename().c_str());
2054 fieldnum
=get_comp_index_byName(*idf
);
2055 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
2057 CompField
*cf
=get_comp_byIndex(fieldnum
);
2058 Type
*t
=cf
->get_type()->get_type_refd_last();
2059 for(int b
=0;b
<rawattrib
->taglist
.tag
[c
].keyList
[a
].
2060 keyField
->nElements
;b
++){
2062 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2064 error("Invalid fieldmember type in RAW parameter TAG"
2066 ,cf
->get_name().get_dispname().c_str());
2070 if(!t
->has_comp_withName(*idf2
)){
2071 error("Invalid field member name `%s' in RAW parameter TAG "
2072 "for field `%s'", idf2
->get_dispname().c_str(),
2073 cf
->get_name().get_dispname().c_str());
2077 size_t comp_index
=t
->get_comp_index_byName(*idf2
);
2078 CompField
*cf2
=t
->get_comp_byIndex(comp_index
);
2079 t
=cf2
->get_type()->get_type_refd_last();
2082 Error_Context
cntx(this, "In Raw parmeter TAG");
2083 Value
*v
= rawattrib
->taglist
.tag
[c
].keyList
[a
].v_value
;
2084 v
->set_my_scope(get_my_scope());
2085 v
->set_my_governor(t
);
2086 t
->chk_this_value_ref(v
);
2087 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2088 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2089 Value::valuetype_t vt
= v
->get_valuetype();
2090 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2091 Free(rawattrib
->taglist
.tag
[c
].keyList
[a
].value
);
2092 rawattrib
->taglist
.tag
[c
].keyList
[a
].value
=
2093 mcopystr(v
->get_single_expr().c_str());
2098 for(int a
=0; a
<rawattrib
->ext_bit_goup_num
;a
++){ // EXTENSION_BIT_GROUP
2099 Identifier
*idf
=rawattrib
->ext_bit_groups
[a
].from
;
2100 Identifier
*idf2
=rawattrib
->ext_bit_groups
[a
].to
;
2102 if(!has_comp_withName(*idf
)){
2103 error("Invalid field name `%s' in RAW parameter "
2104 "EXTENSION_BIT_GROUP for type `%s'",
2105 idf
->get_dispname().c_str(), get_typename().c_str());
2108 if(!has_comp_withName(*idf2
)){
2109 error("Invalid field name `%s' in RAW parameter "
2110 "EXTENSION_BIT_GROUP for type `%s'",
2111 idf2
->get_dispname().c_str(), get_typename().c_str());
2115 size_t kezd
=get_comp_index_byName(*idf
);
2116 size_t veg
=get_comp_index_byName(*idf2
);
2118 error("Invalid field order in RAW parameter "
2119 "EXTENSION_BIT_GROUP for type `%s': `%s', `%s'",
2120 get_typename().c_str(), idf
->get_dispname().c_str(),
2121 idf2
->get_dispname().c_str());
2126 if(rawattrib
->paddall
!=XDEFDEFAULT
){ // PADDALL
2127 for(size_t i
= 0; i
< get_nof_comps(); i
++) {
2128 CompField
*cfield
=get_comp_byIndex(i
);
2129 RawAST
*field_rawattr
=cfield
->get_type()->rawattrib
;
2130 if(field_rawattr
==NULL
){
2131 Type
*t
=cfield
->get_type()->get_type_refd_last();
2132 typetype_t basic_type
=t
->typetype
;
2133 t
=cfield
->get_type();
2134 if(t
->is_ref()) t
=t
->get_type_refd();
2135 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd();
2136 field_rawattr
= new RawAST(t
->rawattrib
,basic_type
==T_INT
);
2137 if(!t
->rawattrib
&& basic_type
==T_REAL
) field_rawattr
->fieldlength
=64;
2138 cfield
->get_type()->rawattrib
=field_rawattr
;
2140 if(field_rawattr
->padding
==0)
2141 field_rawattr
->padding
=rawattrib
->padding
;
2142 if(field_rawattr
->prepadding
==0)
2143 field_rawattr
->prepadding
=rawattrib
->prepadding
;
2144 if (field_rawattr
->padding_pattern_length
== 0 &&
2145 rawattrib
->padding_pattern_length
> 0) {
2146 Free(field_rawattr
->padding_pattern
);
2147 field_rawattr
->padding_pattern
=
2148 mcopystr(rawattrib
->padding_pattern
);
2149 field_rawattr
->padding_pattern_length
=
2150 rawattrib
->padding_pattern_length
;
2154 if(rawattrib
->fieldorder
!=XDEFDEFAULT
){ // FIELDORDER
2155 for(size_t i
= 0; i
< get_nof_comps(); i
++) {
2156 CompField
*cfield
=get_comp_byIndex(i
);
2157 RawAST
*field_rawattr
=cfield
->get_type()->rawattrib
;
2158 if(field_rawattr
==NULL
){
2159 Type
*t
=cfield
->get_type()->get_type_refd_last();
2160 typetype_t basic_type
=t
->typetype
;
2161 t
=cfield
->get_type();
2162 if(t
->is_ref()) t
=t
->get_type_refd();
2163 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd();
2164 field_rawattr
= new RawAST(t
->rawattrib
,basic_type
==T_INT
);
2165 if(!t
->rawattrib
&& basic_type
==T_REAL
) field_rawattr
->fieldlength
=64;
2166 cfield
->get_type()->rawattrib
=field_rawattr
;
2168 if(field_rawattr
->fieldorder
==XDEFDEFAULT
)
2169 field_rawattr
->fieldorder
=rawattrib
->fieldorder
;
2173 for(int a
=0;a
<rawattrib
->presence
.nElements
;a
++){ //PRESENCE
2176 for(int b
=0;b
<rawattrib
->presence
.keyList
[a
].keyField
->nElements
;b
++){
2177 Identifier
*idf
=rawattrib
->presence
.keyList
[a
].keyField
->names
[b
];
2179 error("Invalid fieldmember type in RAW parameter PRESENCE"
2180 " for the record %s."
2181 ,get_typename().c_str());
2185 if(!t
->has_comp_withName(*idf
)){
2186 error("Invalid fieldname in RAW parameter"
2187 " PRESENCE for the record %s: %s"
2188 ,get_typename().c_str()
2189 ,rawattrib
->presence
.keyList
[a
].keyField
->names
[b
]
2190 ->get_dispname().c_str());
2194 t
=t
->get_comp_byName(*idf
)->get_type()->get_type_refd_last();
2197 Error_Context
cntx(this, "In Raw parameter PRESENCE");
2198 Value
*v
= rawattrib
->presence
.keyList
[a
].v_value
;
2199 v
->set_my_scope(get_my_scope());
2200 v
->set_my_governor(t
);
2201 t
->chk_this_value_ref(v
);
2202 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2203 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2204 Value::valuetype_t vt
= v
->get_valuetype();
2205 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2206 Free(rawattrib
->presence
.keyList
[a
].value
);
2207 rawattrib
->presence
.keyList
[a
].value
=
2208 mcopystr(v
->get_single_expr().c_str());
2212 int used_bits
= 0; // number of bits used to store all previous fields
2213 for(size_t i
= 0; i
< get_nof_comps(); i
++) { // field attributes
2214 CompField
*cf
= get_comp_byIndex(i
);
2215 const Identifier
& field_id
= cf
->get_name();
2216 Type
*field_type
= cf
->get_type();
2217 Type
*field_type_last
= field_type
->get_type_refd_last();
2218 field_type
->force_raw();
2219 RawAST
*rawpar
= field_type
->rawattrib
;
2221 if (rawpar
->prepadding
!= 0) {
2222 used_bits
= (used_bits
+ rawpar
->prepadding
- 1) / rawpar
->prepadding
*
2225 if (rawpar
->intx
&& field_type_last
->get_typetype() == T_INT
) { // IntX
2226 if (used_bits
% 8 != 0 &&
2227 (!rawattrib
|| rawattrib
->fieldorder
!= XDEFMSB
)) {
2228 error("Using RAW parameter IntX in a record/set with FIELDORDER "
2229 "set to 'lsb' is only supported if the IntX field starts at "
2230 "the beginning of a new octet. There are %d unused bits in the "
2231 "last octet before field %s.", 8 - (used_bits
% 8),
2232 field_id
.get_dispname().c_str());
2236 used_bits
+= rawpar
->fieldlength
;
2238 if (rawpar
->padding
!= 0) {
2239 used_bits
= (used_bits
+ rawpar
->padding
- 1) / rawpar
->padding
*
2242 for (int j
= 0; j
< rawpar
->lengthto_num
; j
++) { // LENGTHTO
2243 Identifier
*idf
= rawpar
->lengthto
[j
];
2244 if (!has_comp_withName(*idf
)) {
2245 error("Invalid fieldname in RAW parameter "
2246 "LENGTHTO for field %s: %s",
2247 field_id
.get_dispname().c_str(),
2248 rawpar
->lengthto
[j
]->get_dispname().c_str());
2251 if (rawpar
->lengthto_num
) {
2252 Type
*ft
= field_type
;
2253 if (ft
->get_typetype() == T_REFD
) ft
= ft
->get_type_refd_last();
2254 typetype_t ftt
= ft
->get_typetype();
2261 for (size_t fi
= 0; fi
< ft
->get_nof_comps(); fi
++) {
2262 typetype_t uftt
= ft
->get_comp_byIndex(fi
)->get_type()
2264 if (uftt
!= T_INT
&& uftt
!= T_INT_A
)
2265 error("The union type LENGTHTO field must contain only "
2275 if (rawpar
->lengthindex
) break; // Will be checked in the next step.
2276 // Else continue with default.
2278 error("The LENGTHTO field must be an integer or union type "
2279 "instead of `%s'", ft
->get_typename().c_str());
2283 if(rawpar
->lengthto_num
&& rawpar
->lengthindex
){ // LENGTHINDEX
2284 Identifier
*idf
=rawpar
->lengthindex
->names
[0];
2285 if(!field_type_last
->is_secho()){
2286 error("Invalid fieldmember type in RAW parameter LENGTHINDEX"
2288 ,field_id
.get_dispname().c_str());
2291 if(!field_type_last
->has_comp_withName(*idf
))
2292 error("Invalid fieldname in RAW parameter"
2293 " LENGTHINDEX for field %s: %s"
2294 ,field_id
.get_dispname().c_str()
2295 ,rawpar
->lengthindex
->names
[0]->get_dispname().c_str());
2297 if(rawpar
->pointerto
){ // POINTERTO
2298 Identifier
*idf
=rawpar
->pointerto
;
2301 if(!has_comp_withName(*idf
)){
2302 error("Invalid fieldname in RAW"
2303 " parameter POINTERTO for field %s: %s"
2304 ,field_id
.get_dispname().c_str()
2305 ,rawpar
->pointerto
->get_dispname().c_str());
2308 if(!hiba
&& (pointed
=get_comp_index_byName(*idf
))<=i
){
2309 error("Pointer must precede the pointed field. Incorrect field "
2310 "name `%s' in RAW parameter POINTERTO for field `%s'",
2311 rawpar
->pointerto
->get_dispname().c_str(),
2312 field_id
.get_dispname().c_str());
2315 if(!hiba
&& rawpar
->ptrbase
){ // POINTERTO
2316 Identifier
*idf2
=rawpar
->ptrbase
;
2317 if(!has_comp_withName(*idf2
)){
2318 error("Invalid field name `%s' in RAW parameter PTROFFSET for "
2319 "field `%s'", rawpar
->ptrbase
->get_dispname().c_str(),
2320 field_id
.get_dispname().c_str());
2323 if(!hiba
&& get_comp_index_byName(*idf2
)>pointed
){
2324 error("Pointer base must precede the pointed field. Incorrect "
2325 "field name `%s' in RAW parameter PTROFFSET for field "
2326 "`%s'", rawpar
->ptrbase
->get_dispname().c_str(),
2327 field_id
.get_dispname().c_str());
2331 for(int a
=0;a
<rawpar
->presence
.nElements
;a
++){ //PRESENCE
2334 for(int b
=0;b
<rawpar
->presence
.keyList
[a
].keyField
->nElements
;b
++){
2335 Identifier
*idf
=rawpar
->presence
.keyList
[a
].keyField
->names
[b
];
2337 error("Invalid fieldmember type in RAW parameter PRESENCE"
2339 ,field_id
.get_dispname().c_str());
2343 if(!t
->has_comp_withName(*idf
)){
2344 error("Invalid fieldname `%s' in RAW parameter PRESENCE for "
2345 "field `%s'", rawpar
->presence
.keyList
[a
].keyField
2346 ->names
[b
]->get_dispname().c_str(),
2347 field_id
.get_dispname().c_str());
2351 if(b
==0 && !(get_comp_index_byName(*rawpar
->presence
.keyList
[a
]
2352 .keyField
->names
[0])<i
)){
2353 error("The PRESENCE field `%s' must precede the optional field "
2354 "in RAW parameter PRESENCE for field `%s'"
2355 ,rawpar
->presence
.keyList
[a
].keyField
->names
[0]
2356 ->get_dispname().c_str()
2357 ,field_id
.get_dispname().c_str());
2361 t
=t
->get_comp_byName(*idf
)->get_type()->get_type_refd_last();
2364 Error_Context
cntx(this, "In Raw parmeter PRESENCE");
2365 Value
*v
= rawpar
->presence
.keyList
[a
].v_value
;
2366 v
->set_my_scope(get_my_scope());
2367 v
->set_my_governor(t
);
2368 t
->chk_this_value_ref(v
);
2369 self_ref
= t
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2370 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
2371 Value::valuetype_t vt
= v
->get_valuetype();
2372 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2373 Free(rawpar
->presence
.keyList
[a
].value
);
2374 rawpar
->presence
.keyList
[a
].value
=
2375 mcopystr(v
->get_single_expr().c_str());
2379 for(int c
=0;c
<rawpar
->crosstaglist
.nElements
;c
++) { // CROSSTAG
2380 Identifier
*idf
=rawpar
->crosstaglist
.tag
[c
].fieldName
;
2381 if(!field_type_last
->is_secho()){
2382 error("Invalid fieldmember type in RAW parameter CROSSTAG"
2384 ,field_id
.get_dispname().c_str());
2387 if(!field_type_last
->has_comp_withName(*idf
)){
2388 error("Invalid fieldmember name in RAW parameter CROSSTAG"
2390 ,field_id
.get_dispname().c_str()
2391 ,rawpar
->crosstaglist
.tag
[c
].fieldName
2392 ->get_dispname().c_str());
2395 for(int a
=0;a
<rawpar
->crosstaglist
.tag
[c
].nElements
;a
++){
2398 bool allow_omit
= false;
2400 b
<rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->nElements
;b
++){
2402 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
2403 if(!t2
->is_secho()){
2404 error("Invalid fieldmember type in RAW parameter CROSSTAG"
2406 ,field_id
.get_dispname().c_str());
2410 if(!t2
->has_comp_withName(*idf2
)){
2411 error("Invalid fieldname in RAW parameter CROSSTAG"
2413 ,field_id
.get_dispname().c_str()
2414 ,idf2
->get_dispname().c_str());
2419 size_t field_idx
= get_comp_index_byName(*idf2
);
2420 if (field_idx
== i
) {
2421 error("RAW parameter CROSSTAG for field `%s' cannot refer "
2422 "to the field itself", idf2
->get_dispname().c_str());
2423 } else if (field_idx
> i
) {
2424 if (cf
->get_is_optional() ||
2425 field_type
->get_raw_length() < 0)
2426 error("Field `%s' that CROSSTAG refers to must precede "
2427 "field `%s' or field `%s' must be mandatory with "
2428 "fixed length", idf2
->get_dispname().c_str(),
2429 field_id
.get_dispname().c_str(),
2430 field_id
.get_dispname().c_str());
2433 CompField
*cf2
=t2
->get_comp_byName(*idf2
);
2434 t2
=cf2
->get_type()->get_type_refd_last();
2435 if (b
== rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
2436 ->nElements
- 1 && cf2
->get_is_optional())
2440 Error_Context
cntx(this, "In Raw parmeter CROSSTAG");
2441 Value
*v
= rawpar
->crosstaglist
.tag
[c
].keyList
[a
].v_value
;
2442 v
->set_my_scope(get_my_scope());
2443 v
->set_my_governor(t2
);
2444 t2
->chk_this_value_ref(v
);
2445 self_ref
= t2
->chk_this_value(v
, 0, EXPECTED_CONSTANT
,
2446 INCOMPLETE_NOT_ALLOWED
,
2447 (allow_omit
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
), SUB_CHK
);
2448 Value::valuetype_t vt
= v
->get_valuetype();
2449 if (vt
== Value::V_ENUM
|| vt
== Value::V_REFD
) {
2450 Free(rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
);
2451 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
=
2452 mcopystr(v
->get_single_expr().c_str());
2461 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2462 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
2463 rawattrib
->length_restrition
=-1;
2467 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2468 rawattrib
->fieldlength
=rawattrib
->length_restrition
*4;
2469 rawattrib
->length_restrition
=-1;
2473 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2474 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
2475 rawattrib
->length_restrition
=-1;
2480 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2481 rawattrib
->fieldlength
=rawattrib
->length_restrition
*8;
2482 rawattrib
->length_restrition
=-1;
2487 get_ofType()->force_raw();
2488 if(rawattrib
->fieldlength
==0 && rawattrib
->length_restrition
!=-1){
2489 rawattrib
->fieldlength
=rawattrib
->length_restrition
;
2490 rawattrib
->length_restrition
=-1;
2492 if(rawattrib
->length_restrition
!=-1 &&
2493 rawattrib
->length_restrition
!=rawattrib
->fieldlength
){
2494 error("Invalid length specified in parameter FIELDLENGTH for %s of "
2495 "type `%s'. The FIELDLENGTH must be equal to specified length "
2496 "restriction", typetype
== T_SEQOF
? "record" : "set",
2497 get_fullname().c_str());
2501 if(rawattrib
->fieldlength
!=64 && rawattrib
->fieldlength
!=32){
2502 error("Invalid length (%d) specified in parameter FIELDLENGTH for "
2503 "float type `%s'. The FIELDLENGTH must be single (32) or double "
2504 "(64)", rawattrib
->fieldlength
, get_fullname().c_str());
2508 if (rawattrib
->intx
) {
2509 rawattrib
->bitorderinfield
= XDEFMSB
;
2510 rawattrib
->bitorderinoctet
= XDEFMSB
;
2511 rawattrib
->byteorder
= XDEFMSB
;
2517 // nothing to do, ASN1 types or types without defined raw attribute
2524 void Type::force_raw()
2532 // TODO case T_ANYTYPE: for force_raw ?
2536 rawattrib
= new RawAST(false);
2539 if (is_ref()) get_type_refd()->force_raw();
2544 // Don't run chk_raw() on unchecked types
2549 void Type::chk_text()
2551 if (text_checked
) return;
2552 text_checked
= true;
2553 if (!textattrib
|| !enable_text()) return;
2554 //textattrib->print_TextAST();
2556 chk_text_matching_values(textattrib
->begin_val
, "BEGIN");
2557 chk_text_matching_values(textattrib
->end_val
, "END");
2558 chk_text_matching_values(textattrib
->separator_val
, "SEPARATOR");
2565 size_t nof_comps
= get_nof_comps();
2566 for (size_t i
= 0; i
< nof_comps
; i
++)
2567 get_comp_byIndex(i
)->get_type()->force_text();
2571 get_ofType()->force_text();
2574 if (is_ref()) get_type_refd()->force_text();
2578 switch (get_type_refd_last()->typetype
) {
2580 chk_text_matching_values(textattrib
->true_params
, "true value");
2581 chk_text_matching_values(textattrib
->false_params
, "false value");
2584 if(textattrib
->nof_field_params
){
2585 Type
*t
=get_type_refd_last();
2586 size_t nof_comps
= t
->u
.enums
.eis
->get_nof_eis();
2587 textAST_enum_def
**params
=(textAST_enum_def
**)
2588 Malloc(nof_comps
*sizeof(textAST_enum_def
*));
2589 memset(params
,0,nof_comps
*sizeof(textAST_enum_def
*));
2590 for (int a
= 0; a
< textattrib
->nof_field_params
; a
++) {
2591 const Identifier
& id
= *textattrib
->field_params
[a
]->name
;
2592 if (t
->u
.enums
.eis
->has_ei_withName(id
)) {
2593 int index
= t
->get_eis_index_byName(id
);
2594 if (params
[index
]) FATAL_ERROR("Type::chk_text(): duplicate " \
2595 "attribute for enum `%s'", id
.get_dispname().c_str());
2596 params
[index
] = textattrib
->field_params
[a
];
2597 char *attrib_name
= mprintf("enumerated value `%s'",
2598 id
.get_dispname().c_str());
2599 chk_text_matching_values(¶ms
[index
]->value
, attrib_name
);
2602 error("Coding attribute refers to non-existent enumerated value "
2603 "`%s'", id
.get_dispname().c_str());
2604 Free(textattrib
->field_params
[a
]->value
.encode_token
);
2605 Free(textattrib
->field_params
[a
]->value
.decode_token
);
2606 delete textattrib
->field_params
[a
]->name
;
2607 Free(textattrib
->field_params
[a
]);
2610 Free(textattrib
->field_params
);
2611 textattrib
->field_params
=params
;
2612 textattrib
->nof_field_params
=nof_comps
;
2618 if (textattrib
->decode_token
) {
2619 char *tmp
= textattrib
->decode_token
;
2620 textattrib
->decode_token
= process_decode_token(tmp
, *this);
2622 tmp
= TTCN_pattern_to_regexp(textattrib
->decode_token
);
2625 error("Incorrect select token expression: `%s'",
2626 textattrib
->decode_token
);
2633 //textattrib->print_TextAST();
2636 void Type::chk_text_matching_values(textAST_matching_values
*matching_values
,
2637 const char *attrib_name
)
2639 if (!matching_values
) return;
2640 if (matching_values
->decode_token
) {
2641 // check whether decode token is a correct TTCN-3 pattern
2642 char *tmp
= matching_values
->decode_token
;
2643 matching_values
->decode_token
= process_decode_token(tmp
, *this);
2645 tmp
= TTCN_pattern_to_regexp(matching_values
->decode_token
);
2648 error("Incorrect matching expression for %s: `%s'", attrib_name
,
2649 matching_values
->decode_token
);
2651 } else if (matching_values
->encode_token
) {
2652 // the decode token is not present, but there is an encode token
2653 // derive the decode token from the encode token
2654 matching_values
->generated_decode_token
= true;
2655 matching_values
->decode_token
=
2656 convert_charstring_to_pattern(matching_values
->encode_token
);
2660 void Type::force_text()
2668 // TODO case T_ANYTYPE: for force_text ?
2672 textattrib
= new TextAST
;
2675 if (is_ref()) get_type_refd()->force_text();
2683 static const char* JSON_SCHEMA_KEYWORDS
[] = {
2684 // built-in JSON schema keywords
2685 "$ref", "type", "properties", "items", "anyOf", "enum", "pattern",
2686 "default", "minItems", "maxItems", "additionalProperties", "fieldOrder",
2687 "required", "$schema", "minLength", "maxLength", "minimum", "maximum",
2688 "excludeMinimum", "excludeMaximum", "allOf"
2689 // TITAN-specific keywords
2690 "originalName", "unusedAlias", "subType", "numericValues", "omitAsNull",
2691 "encoding", "decoding", "valueList"
2694 void Type::chk_json()
2696 if (json_checked
) return;
2697 json_checked
= true;
2698 if ((NULL
== jsonattrib
&& !hasEncodeAttr(get_encoding_name(CT_JSON
))) || !enable_json()) return;
2708 size_t nof_comps
= get_nof_comps();
2709 for (size_t i
= 0; i
< nof_comps
; i
++)
2710 get_comp_byIndex(i
)->get_type()->force_json();
2715 get_ofType()->force_json();
2718 if (is_ref()) get_type_refd()->force_json();
2722 if (NULL
!= jsonattrib
) {
2723 if (jsonattrib
->omit_as_null
&& !is_optional_field()) {
2724 error("Invalid attribute, 'omit as null' requires optional "
2725 "field of a record or set.");
2728 if (jsonattrib
->as_value
&& T_CHOICE_T
!= get_type_refd_last()->typetype
) {
2729 error("Invalid attribute, 'as value' is only allowed for unions");
2732 if (NULL
!= jsonattrib
->alias
) {
2733 Type
* parent
= get_parent_type();
2734 if (NULL
== parent
|| (T_SEQ_T
!= parent
->typetype
&&
2735 T_SET_T
!= parent
->typetype
&& T_CHOICE_T
!= parent
->typetype
)) {
2736 error("Invalid attribute, 'name as ...' requires field of a "
2737 "record, set or union.");
2739 if (NULL
!= parent
&& NULL
!= parent
->jsonattrib
&&
2740 T_CHOICE_T
== parent
->typetype
&& parent
->jsonattrib
->as_value
) {
2741 warning("Attribute 'name as ...' will be ignored, because parent union "
2742 "is encoded without field names.");
2746 if (NULL
!= jsonattrib
->default_value
) {
2750 const size_t nof_extensions
= jsonattrib
->schema_extensions
.size();
2751 if (0 != nof_extensions
) {
2752 const size_t nof_keywords
= sizeof(JSON_SCHEMA_KEYWORDS
) / sizeof(char*);
2754 // these keep track of erroneous extensions so each warning is only
2756 char* checked_extensions
= new char[nof_extensions
];
2757 char* checked_keywords
= new char[nof_keywords
];
2758 memset(checked_extensions
, 0, nof_extensions
);
2759 memset(checked_keywords
, 0, nof_keywords
);
2761 for (size_t i
= 0; i
< nof_extensions
; ++i
) {
2762 for (size_t j
= 0; j
< nof_keywords
; ++j
) {
2763 if (0 == checked_extensions
[i
] && 0 == checked_keywords
[j
] &&
2764 0 == strcmp(jsonattrib
->schema_extensions
[i
]->key
,
2765 JSON_SCHEMA_KEYWORDS
[j
])) {
2766 // only report the warning once for each keyword
2767 warning("JSON schema keyword '%s' should not be used as the key of "
2768 "attribute 'extend'", JSON_SCHEMA_KEYWORDS
[j
]);
2769 checked_keywords
[j
] = 1;
2770 checked_extensions
[i
] = 1;
2774 if (0 == checked_extensions
[i
]) {
2775 for (size_t k
= i
+ 1; k
< nof_extensions
; ++k
) {
2776 if (0 == strcmp(jsonattrib
->schema_extensions
[i
]->key
,
2777 jsonattrib
->schema_extensions
[k
]->key
)) {
2778 if (0 == checked_extensions
[i
]) {
2779 // only report the warning once for each unique key
2780 warning("Key '%s' is used multiple times in 'extend' attributes "
2781 "of type '%s'", jsonattrib
->schema_extensions
[i
]->key
,
2782 get_typename().c_str());
2783 checked_extensions
[i
] = 1;
2785 checked_extensions
[k
] = 1;
2790 delete[] checked_extensions
;
2791 delete[] checked_keywords
;
2793 if (jsonattrib
->metainfo_unbound
) {
2794 Type
* parent
= get_parent_type();
2795 if (T_SEQ_T
== get_type_refd_last()->typetype
||
2796 T_SET_T
== get_type_refd_last()->typetype
) {
2797 // if it's set for the record/set, pass it onto its fields
2798 size_t nof_comps
= get_nof_comps();
2799 for (size_t i
= 0; i
< nof_comps
; i
++) {
2800 Type
* comp_type
= get_comp_byIndex(i
)->get_type();
2801 if (NULL
== comp_type
->jsonattrib
) {
2802 comp_type
->jsonattrib
= new JsonAST
;
2804 comp_type
->jsonattrib
->metainfo_unbound
= true;
2807 else if (T_SEQOF
!= get_type_refd_last()->typetype
&&
2808 T_SETOF
!= get_type_refd_last()->typetype
&&
2809 T_ARRAY
!= get_type_refd_last()->typetype
&&
2810 (NULL
== parent
|| (T_SEQ_T
!= parent
->typetype
&&
2811 T_SET_T
!= parent
->typetype
))) {
2812 // only allowed if it's an array type or a field of a record/set
2813 error("Invalid attribute 'metainfo for unbound', requires record, set, "
2814 "record of, set of, array or field of a record or set");
2820 void Type::chk_json_default()
2822 const char* dval
= jsonattrib
->default_value
;
2823 const size_t dval_len
= strlen(dval
);
2824 Type
*last
= get_type_refd_last();
2826 switch (last
->typetype
) {
2828 if (strcmp(dval
, "true") != 0 && strcmp(dval
, "false") != 0) {
2833 for (size_t i
= (dval
[0] == '-') ? 1 : 0; i
< dval_len
; ++i
) {
2834 if (dval
[i
] < '0' || dval
[i
] > '9') {
2836 break; // from the loop
2841 if (strcmp(dval
, "infinity") == 0 || strcmp(dval
, "-infinity") == 0 ||
2842 strcmp(dval
, "not_a_number") == 0) {
2843 // special float values => skip the rest of the check
2847 boolean first_digit
= false; // first non-zero digit reached
2848 boolean zero
= false; // first zero digit reached
2849 boolean decimal_point
= false; // decimal point (.) reached
2850 boolean exponent_mark
= false; // exponential mark (e or E) reached
2851 boolean exponent_sign
= false; // sign of the exponential (- or +) reached
2853 size_t i
= (dval
[0] == '-') ? 1 : 0;
2854 while(!err
&& i
< dval_len
) {
2857 if (decimal_point
|| exponent_mark
|| (!first_digit
&& !zero
)) {
2860 decimal_point
= true;
2861 first_digit
= false;
2866 if (exponent_mark
|| (!first_digit
&& !zero
)) {
2869 exponent_mark
= true;
2870 first_digit
= false;
2874 if (!first_digit
&& (exponent_mark
|| (!decimal_point
&& zero
))) {
2888 if (!first_digit
&& zero
&& (!decimal_point
|| exponent_mark
)) {
2895 if (exponent_sign
|| !exponent_mark
|| zero
|| first_digit
) {
2898 exponent_sign
= true;
2905 err
= !first_digit
&& !zero
;
2908 for (size_t i
= 0; i
< dval_len
; ++i
) {
2909 if (dval
[i
] < '0' || dval
[i
] > '1') {
2911 break; // from the loop
2916 if (dval_len
% 2 != 0) {
2922 for (size_t i
= 0; i
< dval_len
; ++i
) {
2923 if ((dval
[i
] < '0' || dval
[i
] > '9') && (dval
[i
] < 'a' || dval
[i
] > 'f') &&
2924 (dval
[i
] < 'A' || dval
[i
] > 'F')) {
2926 break; // from the loop
2933 while(!err
&& i
< dval_len
) {
2934 if (dval
[i
] < 0 && last
->typetype
== T_CSTR
) {
2937 else if (dval
[i
] == '\\') {
2938 if (i
== dval_len
- 1) {
2951 break; // these are OK
2953 if (i
+ 4 >= dval_len
) {
2955 } else if (last
->typetype
== T_CSTR
&&
2956 (dval
[i
+ 1] != '0' || dval
[i
+ 2] != '0' ||
2957 dval
[i
+ 3] < '0' || dval
[i
+ 3] > '7')) {
2960 for (size_t j
= (last
->typetype
== T_CSTR
) ? 4 : 1; j
<= 4; ++j
) {
2961 if ((dval
[i
+ j
] < '0' || dval
[i
+ j
] > '9') &&
2962 (dval
[i
+ j
] < 'a' || dval
[i
+ j
] > 'f') &&
2963 (dval
[i
+ j
] < 'A' || dval
[i
+ j
] > 'F')) {
2965 break; // from the loop
2981 Common::Identifier
id(Identifier::ID_TTCN
, string(dval
));
2982 if (!last
->has_ei_withName(id
)) {
2987 if (strcmp(dval
, "none") != 0 && strcmp(dval
, "pass") != 0 &&
2988 strcmp(dval
, "inconc") != 0 && strcmp(dval
, "fail") != 0 &&
2989 strcmp(dval
, "error") != 0) {
2994 error("JSON default values are not available for type `%s'",
2995 last
->get_stringRepr().c_str());
3000 if (last
->typetype
== T_ENUM_T
) {
3001 error("Invalid JSON default value for enumerated type `%s'",
3002 last
->get_stringRepr().c_str());
3004 error("Invalid %s JSON default value", get_typename_builtin(last
->typetype
));
3009 void Type::force_json()
3024 jsonattrib
= new JsonAST
;
3027 if (is_ref()) get_type_refd()->force_json();
3036 int Type::get_length_multiplier()
3040 return get_type_refd()->get_length_multiplier();
3056 /** \todo review, especially the string types... */
3057 bool Type::is_compatible_tt_tt(typetype_t p_tt1
, typetype_t p_tt2
,
3058 bool p_is_asn11
, bool p_is_asn12
)
3060 if (p_tt2
== T_ERROR
) return true;
3062 // error type is compatible with everything
3065 // unambiguous built-in types
3081 return p_tt1
== p_tt2
;
3083 return p_tt2
==T_OSTR
|| (!p_is_asn11
&& p_tt2
==T_ANY
);
3089 case T_UNIVERSALSTRING
:
3090 case T_TELETEXSTRING
:
3091 case T_VIDEOTEXSTRING
:
3092 case T_GRAPHICSTRING
:
3093 case T_OBJECTDESCRIPTOR
:
3094 case T_GENERALSTRING
:
3096 case T_NUMERICSTRING
:
3097 case T_PRINTABLESTRING
:
3099 case T_VISIBLESTRING
:
3101 case T_GENERALIZEDTIME
:
3106 // character string group 1
3109 case T_UNIVERSALSTRING
:
3114 case T_UNIVERSALSTRING
:
3116 case T_NUMERICSTRING
:
3117 case T_PRINTABLESTRING
:
3119 case T_VISIBLESTRING
:
3121 case T_GENERALIZEDTIME
:
3126 // character string group 2
3127 case T_TELETEXSTRING
:
3128 case T_VIDEOTEXSTRING
:
3129 case T_GRAPHICSTRING
:
3130 case T_OBJECTDESCRIPTOR
:
3131 case T_GENERALSTRING
:
3133 case T_TELETEXSTRING
:
3134 case T_VIDEOTEXSTRING
:
3135 case T_GRAPHICSTRING
:
3136 case T_OBJECTDESCRIPTOR
:
3137 case T_GENERALSTRING
:
3139 case T_NUMERICSTRING
:
3140 case T_PRINTABLESTRING
:
3142 case T_VISIBLESTRING
:
3144 case T_GENERALIZEDTIME
:
3147 // maybe :) is ustr.is_cstr()
3152 // character string group 3
3154 case T_NUMERICSTRING
:
3155 case T_PRINTABLESTRING
:
3157 case T_VISIBLESTRING
:
3159 case T_GENERALIZEDTIME
:
3162 case T_NUMERICSTRING
:
3163 case T_PRINTABLESTRING
:
3165 case T_VISIBLESTRING
:
3167 case T_GENERALIZEDTIME
:
3172 // polymorphic built-in types
3175 return p_tt2
== T_BSTR
|| p_tt2
== T_BSTR_A
;
3178 return p_tt2
== T_INT
|| p_tt2
== T_INT_A
;
3179 // ROID is visible as OID from TTCN-3
3181 return p_tt2
== T_OID
||
3182 (!p_is_asn11
&& p_tt2
== T_ROID
);
3184 return p_tt2
== T_ROID
||
3185 (!p_is_asn12
&& p_tt2
== T_OID
);
3188 return p_tt2
==T_ENUM_A
|| p_tt2
==T_ENUM_T
;
3192 return p_tt2
==T_CHOICE_T
|| p_tt2
==T_CHOICE_A
|| p_tt2
==T_OPENTYPE
;
3195 return p_tt2
==T_SEQ_A
|| p_tt2
==T_SEQ_T
;
3198 return p_tt2
==T_SET_A
|| p_tt2
==T_SET_T
;
3200 return p_tt2
== T_ANY
|| p_tt2
== T_OSTR
;
3201 // these should never appear?
3208 FATAL_ERROR("Type::is_compatible_tt_tt()");
3213 bool Type::is_compatible_tt(typetype_t p_tt
, bool p_is_asn1
)
3216 Type
*t1
=get_type_refd_last();
3217 if (p_tt
== T_ERROR
) return true;
3218 switch (t1
->typetype
) {
3219 // these should never appear
3224 FATAL_ERROR("Type::is_compatible_tt()");
3227 return is_compatible_tt_tt(t1
->typetype
, p_tt
, is_asn1(), p_is_asn1
);
3231 bool Type::is_compatible(Type
*p_type
, TypeCompatInfo
*p_info
,
3232 TypeChain
*p_left_chain
, TypeChain
*p_right_chain
,
3233 bool p_is_inline_template
)
3237 Type
*t1
= get_type_refd_last();
3238 Type
*t2
= p_type
->get_type_refd_last();
3239 // Error type is compatible with everything.
3240 if (t1
->typetype
== T_ERROR
|| t2
->typetype
== T_ERROR
) return true;
3242 switch (t1
->typetype
) {
3243 // Unambiguous built-in types.
3250 is_type_comp
= (t1
->typetype
== t2
->typetype
);
3253 is_type_comp
= ( t2
->typetype
==T_OSTR
|| (!is_asn1() && t2
->typetype
==T_ANY
) );
3256 switch (t2
->typetype
) {
3260 case T_UNIVERSALSTRING
:
3261 case T_TELETEXSTRING
:
3262 case T_VIDEOTEXSTRING
:
3263 case T_GRAPHICSTRING
:
3264 case T_OBJECTDESCRIPTOR
:
3265 case T_GENERALSTRING
:
3267 case T_NUMERICSTRING
:
3268 case T_PRINTABLESTRING
:
3270 case T_VISIBLESTRING
:
3272 case T_GENERALIZEDTIME
:
3273 is_type_comp
= true;
3276 is_type_comp
= false;
3280 // Character string group 1.
3283 case T_UNIVERSALSTRING
:
3284 switch (t2
->typetype
) {
3288 case T_UNIVERSALSTRING
:
3290 case T_NUMERICSTRING
:
3291 case T_PRINTABLESTRING
:
3293 case T_VISIBLESTRING
:
3295 case T_GENERALIZEDTIME
:
3296 is_type_comp
= true;
3299 is_type_comp
= false;
3303 // Character string group 2.
3304 case T_TELETEXSTRING
:
3305 case T_VIDEOTEXSTRING
:
3306 case T_GRAPHICSTRING
:
3307 case T_OBJECTDESCRIPTOR
:
3308 case T_GENERALSTRING
:
3309 switch (t2
->typetype
) {
3310 case T_TELETEXSTRING
:
3311 case T_VIDEOTEXSTRING
:
3312 case T_GRAPHICSTRING
:
3313 case T_OBJECTDESCRIPTOR
:
3314 case T_GENERALSTRING
:
3316 case T_NUMERICSTRING
:
3317 case T_PRINTABLESTRING
:
3319 case T_VISIBLESTRING
:
3321 case T_GENERALIZEDTIME
:
3322 is_type_comp
= true;
3325 // Maybe :) is ustr.is_cstr().
3326 is_type_comp
= true;
3329 is_type_comp
= false;
3333 // Character string group 3.
3335 case T_NUMERICSTRING
:
3336 case T_PRINTABLESTRING
:
3338 case T_VISIBLESTRING
:
3340 case T_GENERALIZEDTIME
:
3341 switch (t2
->typetype
) {
3343 case T_NUMERICSTRING
:
3344 case T_PRINTABLESTRING
:
3346 case T_VISIBLESTRING
:
3348 case T_GENERALIZEDTIME
:
3349 is_type_comp
= true;
3352 is_type_comp
= false;
3356 // Polymorphic built-in types.
3359 is_type_comp
= ( t2
->typetype
== T_BSTR
|| t2
->typetype
== T_BSTR_A
);
3363 is_type_comp
= ( t2
->typetype
== T_INT
|| t2
->typetype
== T_INT_A
);
3365 // ROID is visible as OID from TTCN-3.
3367 is_type_comp
= ( t2
->typetype
== T_OID
|| (!is_asn1() && t2
->typetype
== T_ROID
) );
3370 is_type_comp
= ( t2
->typetype
== T_ROID
|| (!p_type
->is_asn1() && t2
->typetype
== T_OID
) );
3373 is_type_comp
= ( t2
->typetype
== T_COMPONENT
&& t1
->u
.component
->is_compatible(t2
->u
.component
) );
3377 is_type_comp
= t1
->is_compatible_record(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3380 is_type_comp
= t1
->is_compatible_record_of(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3384 is_type_comp
= t1
->is_compatible_set(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3387 is_type_comp
= t1
->is_compatible_set_of(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3390 is_type_comp
= t1
->is_compatible_array(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3395 is_type_comp
= t1
->is_compatible_choice_anytype(t2
, p_info
, p_left_chain
, p_right_chain
, p_is_inline_template
);
3402 is_type_comp
= ( t1
== t2
);
3407 // TODO: Compatibility.
3408 is_type_comp
= ( t1
== t2
);
3411 is_type_comp
= ( t2
->typetype
== T_ANY
|| t2
->typetype
== T_OSTR
);
3414 FATAL_ERROR("Type::is_compatible()");
3416 // if types are compatible then check subtype compatibility
3417 // skip check if p_info is NULL
3418 if ((p_info
!=NULL
) && is_type_comp
&& (sub_type
!=NULL
) && (p_type
->sub_type
!=NULL
) &&
3419 (sub_type
->get_subtypetype()==p_type
->sub_type
->get_subtypetype()))
3421 if (p_info
->get_str1_elem()) {
3422 if (p_info
->get_str2_elem()) {
3423 // both are string elements -> nothing to do
3426 if (!p_type
->sub_type
->is_compatible_with_elem()) {
3427 is_type_comp
= false;
3428 p_info
->set_subtype_error(
3429 string("Subtype mismatch: string element has no common value with subtype ")+
3430 p_type
->sub_type
->to_string());
3434 if (p_info
->get_str2_elem()) {
3436 if (!sub_type
->is_compatible_with_elem()) {
3437 is_type_comp
= false;
3438 p_info
->set_subtype_error(string("Subtype mismatch: subtype ")+
3439 sub_type
->to_string()+string(" has no common value with a string element"));
3442 // string <-> string
3443 if (!sub_type
->is_compatible(p_type
->sub_type
)) {
3444 is_type_comp
= false;
3445 p_info
->set_subtype_error(string("Subtype mismatch: subtype ")+
3446 sub_type
->to_string()+string(" has no common value with subtype ")+
3447 p_type
->sub_type
->to_string());
3452 return is_type_comp
;
3455 bool Type::is_structured_type() const
3474 bool Type::is_subtype_length_compatible(Type
*p_type
)
3476 if (typetype
!= T_SEQOF
&& typetype
!= T_SETOF
)
3477 FATAL_ERROR("Type::is_subtype_length_compatible()");
3478 if (!sub_type
) return true;
3479 SubtypeConstraint::subtype_t st_t
= typetype
== T_SEQOF
?
3480 SubtypeConstraint::ST_RECORDOF
: SubtypeConstraint::ST_SETOF
;
3481 switch (p_type
->typetype
) {
3486 vector
<SubTypeParse
> p_stp_v
;
3487 Value
*p_nof_comps
= new Value(Value::V_INT
,
3488 new int_val_t(p_type
->get_nof_comps()));
3489 p_stp_v
.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps
)));
3490 SubType
p_st(st_t
, this, NULL
, &p_stp_v
, NULL
);
3494 return sub_type
->is_length_compatible(&p_st
); }
3497 if (!p_type
->sub_type
) return true;
3498 else return sub_type
->is_length_compatible(p_type
->sub_type
);
3500 if (p_type
->u
.array
.dimension
->get_has_error()) return false;
3501 vector
<SubTypeParse
> p_stp_v
;
3503 = new Value(Value::V_INT
,
3504 new int_val_t(p_type
->u
.array
.dimension
->get_size()));
3505 p_stp_v
.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps
)));
3506 SubType
p_st(st_t
, this, NULL
, &p_stp_v
, NULL
);
3507 p_st
.chk(); // Convert SubTypeParse to SubType.
3510 return sub_type
->is_length_compatible(&p_st
); }
3512 FATAL_ERROR("Type::is_subtype_length_compatible()");
3516 // Errors and warnings are reported in an upper level. We just make a
3517 // simple decision here.
3518 bool Type::is_compatible_record(Type
*p_type
, TypeCompatInfo
*p_info
,
3519 TypeChain
*p_left_chain
,
3520 TypeChain
*p_right_chain
,
3521 bool p_is_inline_template
)
3523 if (typetype
!= T_SEQ_A
&& typetype
!= T_SEQ_T
)
3524 FATAL_ERROR("Type::is_compatible_record()");
3525 // The get_type_refd_last() was called for both Types at this point. All
3526 // this code runs in both run-times.
3527 if (this == p_type
) return true;
3528 else if (!use_runtime_2
|| !p_info
3529 || (p_info
&& p_info
->is_strict())) return false;
3530 size_t nof_comps
= get_nof_comps();
3531 switch (p_type
->typetype
) {
3534 // According to 6.3.2.2 the # of fields and the optionality must be
3535 // the same for record types. It's good news for compile-time checks.
3536 // Conversion is always from "p_type -> this".
3537 size_t p_nof_comps
= p_type
->get_nof_comps();
3538 if (nof_comps
!= p_nof_comps
) {
3539 p_info
->set_is_erroneous(this, p_type
, string("The number of fields in "
3540 "record/SEQUENCE types must be the same"));
3543 // If p_info is present we have the chains as well.
3544 if (p_left_chain
->empty()) p_left_chain
->add(this);
3545 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3546 for (size_t i
= 0; i
< nof_comps
; i
++) {
3547 CompField
*cf
= get_comp_byIndex(i
);
3548 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3549 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
3550 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3551 string cf_name
= cf
->get_name().get_dispname();
3552 string p_cf_name
= p_cf
->get_name().get_dispname();
3553 if (cf
->get_is_optional() != p_cf
->get_is_optional()) {
3554 p_info
->append_ref_str(0, "." + cf_name
);
3555 p_info
->append_ref_str(1, "." + p_cf_name
);
3556 p_info
->set_is_erroneous(cf_type
, p_cf_type
, string("The optionality of "
3557 "fields in record/SEQUENCE types must be "
3561 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
3563 p_left_chain
->mark_state();
3564 p_right_chain
->mark_state();
3565 p_left_chain
->add(cf_type
);
3566 p_right_chain
->add(p_cf_type
);
3567 if (cf_type
!= p_cf_type
3568 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3569 && !cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3570 p_right_chain
, p_is_inline_template
)) {
3571 p_info
->append_ref_str(0, "." + cf_name
+ info_tmp
.get_ref_str(0));
3572 p_info
->append_ref_str(1, "." + p_cf_name
+ info_tmp
.get_ref_str(1));
3573 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3574 info_tmp
.get_error_str());
3575 p_left_chain
->previous_state();
3576 p_right_chain
->previous_state();
3579 p_left_chain
->previous_state();
3580 p_right_chain
->previous_state();
3582 if (!p_is_inline_template
) {
3583 p_info
->set_needs_conversion(true);
3584 p_info
->add_type_conversion(p_type
, this);
3588 if (!p_type
->is_subtype_length_compatible(this)) {
3589 p_info
->set_is_erroneous(this, p_type
, string("Incompatible record of/SEQUENCE "
3595 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3596 if (p_type
->typetype
== T_ARRAY
) {
3597 if (p_of_type
->get_typetype() == T_ARRAY
) {
3598 p_info
->set_is_erroneous(this, p_type
, string("record/SEQUENCE types are "
3599 "compatible only with single-dimension "
3603 size_t nof_opt_fields
= 0;
3604 for (size_t i
= 0; i
< nof_comps
; i
++)
3605 if (get_comp_byIndex(i
)->get_is_optional()) nof_opt_fields
++;
3606 if (p_type
->u
.array
.dimension
->get_size()
3607 < nof_comps
- nof_opt_fields
) {
3608 p_info
->set_is_erroneous(this, p_type
, string("The dimension of the array "
3609 "must be >= than the number of mandatory "
3610 "fields in the record/SEQUENCE type"));
3614 if (p_left_chain
->empty()) p_left_chain
->add(this);
3615 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3616 for (size_t i
= 0; i
< nof_comps
; i
++) {
3617 Type
*cf_type
= get_comp_byIndex(i
)->get_type()->get_type_refd_last();
3618 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_of_type
,
3620 p_left_chain
->mark_state();
3621 p_right_chain
->mark_state();
3622 p_left_chain
->add(cf_type
);
3623 p_right_chain
->add(p_of_type
);
3624 if (cf_type
!= p_of_type
3625 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3626 && !cf_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3627 p_right_chain
, p_is_inline_template
)) {
3628 p_info
->append_ref_str(0, "." + get_comp_byIndex(i
)
3629 ->get_name().get_dispname() + info_tmp
.get_ref_str(0));
3630 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
3631 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3632 info_tmp
.get_error_str());
3633 p_left_chain
->previous_state();
3634 p_right_chain
->previous_state();
3637 p_left_chain
->previous_state();
3638 p_right_chain
->previous_state();
3640 if (!p_is_inline_template
) {
3641 p_info
->set_needs_conversion(true);
3642 p_info
->add_type_conversion(p_type
, this);
3648 // 6.3.2.4 makes our job very easy...
3649 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3650 "compatible only with other "
3651 "union/CHOICE/anytype types"));
3656 // Only set/set of types are compatible with other set/set of types.
3657 // 6.3.2.3 is a little bit unclear about set of types, but we treat them
3658 // this way. Otherwise, it would be possible to use compatibility with
3659 // a "middle-man" set of variable between record/set types:
3660 // type set S { integer f1, integer f2 }
3661 // type record { integer f1, integer f2 }
3662 // type set of integer SO
3663 // var S s := { 1, 2 }
3664 // var R r := { 1, 2 }
3667 // if (r == s) { ... } // Not allowed.
3668 // if (r == so) { ... } // Not allowed. (?)
3669 // Seems to be a fair decision. If we would want compatibility between
3670 // variables of record/set types, we should allow it directly.
3671 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3672 "types are compatible only with other set/SET "
3673 "set of/SET OF types"));
3680 bool Type::is_compatible_record_of(Type
*p_type
, TypeCompatInfo
*p_info
,
3681 TypeChain
*p_left_chain
,
3682 TypeChain
*p_right_chain
,
3683 bool p_is_inline_template
)
3685 if (typetype
!= T_SEQOF
) FATAL_ERROR("Type::is_compatible_record_of()");
3686 if (this == p_type
) return true;
3687 else if (T_SEQOF
== p_type
->get_type_refd_last()->typetype
&&
3688 is_pregenerated() && p_type
->is_pregenerated() &&
3689 get_ofType()->get_type_refd_last()->typetype
==
3690 p_type
->get_ofType()->get_type_refd_last()->typetype
&&
3691 (use_runtime_2
|| get_optimize_attribute() == p_type
->get_optimize_attribute())) {
3692 // Pre-generated record-ofs of the same element type are compatible with
3693 // each other (in RT1 optimized record-ofs are not compatible with non-optimized ones)
3694 if (!is_subtype_length_compatible(p_type
)) {
3695 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3696 "record of/SEQUENCE OF subtypes"));
3701 else if (!use_runtime_2
|| !p_info
3702 || (p_info
&& p_info
->is_strict())) return false;
3703 switch (p_type
->typetype
) {
3706 if (!is_subtype_length_compatible(p_type
)) {
3707 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3708 "record of/SEQUENCE OF subtypes"));
3711 Type
*of_type
= get_ofType()->get_type_refd_last();
3712 if (p_left_chain
->empty()) p_left_chain
->add(this);
3713 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3714 for (size_t i
= 0; i
< p_type
->get_nof_comps(); i
++) {
3715 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3716 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3717 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3719 p_left_chain
->mark_state();
3720 p_right_chain
->mark_state();
3721 p_left_chain
->add(of_type
);
3722 p_right_chain
->add(p_cf_type
);
3723 if (of_type
!= p_cf_type
3724 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3725 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3726 p_right_chain
, p_is_inline_template
)) {
3727 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3728 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3729 info_tmp
.get_ref_str(1));
3730 p_info
->set_is_erroneous(info_tmp
.get_type(0),
3731 info_tmp
.get_type(1),
3732 info_tmp
.get_error_str());
3733 p_left_chain
->previous_state();
3734 p_right_chain
->previous_state();
3737 p_left_chain
->previous_state();
3738 p_right_chain
->previous_state();
3740 if (!p_is_inline_template
) {
3741 p_info
->set_needs_conversion(true);
3742 p_info
->add_type_conversion(p_type
, this);
3747 if (!is_subtype_length_compatible(p_type
)) {
3748 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3749 "record of/SEQUENCE OF subtypes"));
3752 Type
*of_type
= get_ofType()->get_type_refd_last();
3753 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3754 if (p_left_chain
->empty()) p_left_chain
->add(this);
3755 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3756 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3758 p_left_chain
->mark_state();
3759 p_right_chain
->mark_state();
3760 p_left_chain
->add(of_type
);
3761 p_right_chain
->add(p_of_type
);
3762 if (of_type
== p_of_type
3763 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3764 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3765 p_right_chain
, p_is_inline_template
)) {
3766 if (!p_is_inline_template
) {
3767 p_info
->set_needs_conversion(true);
3768 p_info
->add_type_conversion(p_type
, this);
3770 p_left_chain
->previous_state();
3771 p_right_chain
->previous_state();
3774 p_left_chain
->previous_state();
3775 p_right_chain
->previous_state();
3776 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
3777 // Arrays already have the "[]" in their names.
3778 if (p_type
->get_typetype() != T_ARRAY
) p_info
->append_ref_str(1, string("[]"));
3779 p_info
->append_ref_str(1, info_tmp
.get_ref_str(1));
3780 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3781 info_tmp
.get_error_str());
3786 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3787 "compatible only with other "
3788 "union/CHOICE/anytype types"));
3793 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3794 "types are compatible only with other set/SET "
3795 "set of/SET OF types"));
3802 bool Type::is_compatible_array(Type
*p_type
, TypeCompatInfo
*p_info
,
3803 TypeChain
*p_left_chain
,
3804 TypeChain
*p_right_chain
,
3805 bool p_is_inline_template
)
3807 if (typetype
!= T_ARRAY
) FATAL_ERROR("Type::is_compatible_array()");
3808 // Copied from the original checker code. The type of the elements and
3809 // the dimension of the array must be the same.
3810 if (this == p_type
) return true;
3811 if (p_type
->typetype
== T_ARRAY
&& u
.array
.element_type
3812 ->is_compatible(p_type
->u
.array
.element_type
, NULL
, NULL
, NULL
, p_is_inline_template
)
3813 && u
.array
.dimension
->is_identical(p_type
->u
.array
.dimension
))
3815 else if (!use_runtime_2
|| !p_info
3816 || (p_info
&& p_info
->is_strict())) return false;
3817 Type
*of_type
= get_ofType()->get_type_refd_last();
3818 switch (p_type
->get_typetype()) {
3821 if (of_type
->get_typetype() == T_ARRAY
) {
3822 p_info
->set_is_erroneous(this, p_type
, string("record/SEQUENCE types are "
3823 "compatible only with single-dimension "
3827 size_t p_nof_comps
= p_type
->get_nof_comps();
3828 size_t p_nof_opt_fields
= 0;
3829 for (size_t i
= 0; i
< p_nof_comps
; i
++)
3830 if (p_type
->get_comp_byIndex(i
)->get_is_optional())
3832 if (u
.array
.dimension
->get_size() < p_nof_comps
- p_nof_opt_fields
) {
3833 p_info
->set_is_erroneous(this, p_type
, string("The dimension of the array "
3834 "must be >= than the number of mandatory "
3835 "fields in the record/SEQUENCE type"));
3838 if (p_left_chain
->empty()) p_left_chain
->add(this);
3839 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3840 for (size_t i
= 0; i
< p_nof_comps
; ++i
) {
3841 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3842 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3843 string p_cf_name
= p_cf
->get_name().get_dispname();
3844 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
3846 p_left_chain
->mark_state();
3847 p_right_chain
->mark_state();
3848 p_left_chain
->add(of_type
);
3849 p_right_chain
->add(p_cf_type
);
3850 if (of_type
!= p_cf_type
3851 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3852 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3853 p_right_chain
, p_is_inline_template
)) {
3854 p_info
->append_ref_str(0, info_tmp
.get_ref_str(0));
3855 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
3856 info_tmp
.get_ref_str(1));
3857 p_info
->set_is_erroneous(info_tmp
.get_type(0),
3858 info_tmp
.get_type(1),
3859 info_tmp
.get_error_str());
3860 p_left_chain
->previous_state();
3861 p_right_chain
->previous_state();
3864 p_left_chain
->previous_state();
3865 p_right_chain
->previous_state();
3867 if (!p_is_inline_template
) {
3868 p_info
->set_needs_conversion(true);
3869 p_info
->add_type_conversion(p_type
, this);
3873 if (!p_type
->is_subtype_length_compatible(this)) {
3874 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
3875 "record of/SEQUENCE OF subtypes"));
3879 if (p_type
->get_typetype() == T_ARRAY
3880 && !u
.array
.dimension
->is_identical(p_type
->u
.array
.dimension
)) {
3881 p_info
->set_is_erroneous(this, p_type
, string("Array types should have "
3882 "the same dimension"));
3885 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
3886 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
3888 if (p_left_chain
->empty()) p_left_chain
->add(this);
3889 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3890 p_left_chain
->mark_state();
3891 p_right_chain
->mark_state();
3892 p_left_chain
->add(of_type
);
3893 p_right_chain
->add(p_of_type
);
3894 if (of_type
== p_of_type
3895 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3896 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
3897 p_right_chain
, p_is_inline_template
)) {
3898 if (!p_is_inline_template
) {
3899 p_info
->set_needs_conversion(true);
3900 p_info
->add_type_conversion(p_type
, this);
3902 p_left_chain
->previous_state();
3903 p_right_chain
->previous_state();
3906 p_left_chain
->previous_state();
3907 p_right_chain
->previous_state();
3908 p_info
->append_ref_str(0, info_tmp
.get_ref_str(0));
3909 if (p_type
->get_typetype() != T_ARRAY
) p_info
->append_ref_str(1, string("[]"));
3910 p_info
->append_ref_str(1, info_tmp
.get_ref_str(1));
3911 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3912 info_tmp
.get_error_str());
3917 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
3918 "compatible only with other "
3919 "union/CHOICE/anytype types"));
3924 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
3925 "types are compatible only with other set/SET "
3926 "set of/SET OF types"));
3933 bool Type::is_compatible_set(Type
*p_type
, TypeCompatInfo
*p_info
,
3934 TypeChain
*p_left_chain
,
3935 TypeChain
*p_right_chain
,
3936 bool p_is_inline_template
)
3938 if (typetype
!= T_SET_A
&& typetype
!= T_SET_T
)
3939 FATAL_ERROR("Type::is_compatible_set()");
3940 if (this == p_type
) return true;
3941 else if (!use_runtime_2
|| !p_info
3942 || (p_info
&& p_info
->is_strict())) return false;
3943 size_t nof_comps
= get_nof_comps();
3944 switch (p_type
->typetype
) {
3947 // The standard is very generous. We don't need to check for a possible
3948 // combination of compatible fields. According to 6.3.2.3, simply do
3949 // the same thing as for T_SEQ_{A,T} types. The fields are in their
3951 size_t p_nof_comps
= p_type
->get_nof_comps();
3952 if (nof_comps
!= p_nof_comps
) {
3953 p_info
->set_is_erroneous(this, p_type
, string("The number of fields in "
3954 "set/SET types must be the same"));
3957 if (p_left_chain
->empty()) p_left_chain
->add(this);
3958 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
3959 for (size_t i
= 0; i
< nof_comps
; i
++) {
3960 CompField
*cf
= get_comp_byIndex(i
);
3961 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
3962 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
3963 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
3964 string cf_name
= cf
->get_name().get_dispname();
3965 string p_cf_name
= p_cf
->get_name().get_dispname();
3966 if (cf
->get_is_optional() != p_cf
->get_is_optional()) {
3967 p_info
->append_ref_str(0, "." + cf_name
);
3968 p_info
->append_ref_str(1, "." + p_cf_name
);
3969 p_info
->set_is_erroneous(cf_type
, p_cf_type
, string("The optionality of "
3970 "fields in set/SET types must be the "
3974 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
3976 p_left_chain
->mark_state();
3977 p_right_chain
->mark_state();
3978 p_left_chain
->add(cf_type
);
3979 p_right_chain
->add(p_cf_type
);
3980 if (cf_type
!= p_cf_type
3981 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
3982 && !cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
3983 p_right_chain
, p_is_inline_template
)) {
3984 p_info
->append_ref_str(0, "." + cf_name
+ info_tmp
.get_ref_str(0));
3985 p_info
->append_ref_str(1, "." + p_cf_name
+ info_tmp
.get_ref_str(1));
3986 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
3987 info_tmp
.get_error_str());
3988 p_left_chain
->previous_state();
3989 p_right_chain
->previous_state();
3992 p_left_chain
->previous_state();
3993 p_right_chain
->previous_state();
3995 if (!p_is_inline_template
) {
3996 p_info
->set_needs_conversion(true);
3997 p_info
->add_type_conversion(p_type
, this);
4001 if (!p_type
->is_subtype_length_compatible(this)) {
4002 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
4006 if (p_left_chain
->empty()) p_left_chain
->add(this);
4007 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4008 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
4009 for (size_t i
= 0; i
< nof_comps
; i
++) {
4010 Type
*cf_type
= get_comp_byIndex(i
)->get_type()->get_type_refd_last();
4011 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_of_type
,
4013 p_left_chain
->mark_state();
4014 p_right_chain
->mark_state();
4015 p_left_chain
->add(cf_type
);
4016 p_right_chain
->add(p_of_type
);
4017 if (cf_type
!= p_of_type
4018 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4019 && !cf_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
4020 p_right_chain
, p_is_inline_template
)) {
4021 p_info
->append_ref_str(0, "." + get_comp_byIndex(i
)
4022 ->get_name().get_dispname() + info_tmp
.get_ref_str(0));
4023 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
4024 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
4025 info_tmp
.get_error_str());
4026 p_left_chain
->previous_state();
4027 p_right_chain
->previous_state();
4030 p_left_chain
->previous_state();
4031 p_right_chain
->previous_state();
4033 if (!p_is_inline_template
) {
4034 p_info
->set_needs_conversion(true);
4035 p_info
->add_type_conversion(p_type
, this);
4041 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
4042 "compatible only with other "
4043 "union/CHOICE/anytype types"));
4049 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
4050 "types are compatible only with other set/SET "
4051 "set of/SET OF types"));
4058 bool Type::is_compatible_set_of(Type
*p_type
, TypeCompatInfo
*p_info
,
4059 TypeChain
*p_left_chain
,
4060 TypeChain
*p_right_chain
,
4061 bool p_is_inline_template
)
4063 if (typetype
!= T_SETOF
) FATAL_ERROR("Type::is_compatible_set_of()");
4064 if (this == p_type
) return true;
4065 else if (T_SETOF
== p_type
->get_type_refd_last()->typetype
&&
4066 is_pregenerated() && p_type
->is_pregenerated() &&
4067 get_ofType()->get_type_refd_last()->typetype
==
4068 p_type
->get_ofType()->get_type_refd_last()->typetype
&&
4069 (use_runtime_2
|| get_optimize_attribute() == p_type
->get_optimize_attribute())) {
4070 // Pre-generated set-ofs of the same element type are compatible with
4071 // each other (in RT1 optimized set-ofs are not compatible with non-optimized ones)
4072 if (!is_subtype_length_compatible(p_type
)) {
4073 p_info
->set_is_erroneous(this, p_type
, string("Incompatible "
4074 "set of/SET OF subtypes"));
4079 else if (!use_runtime_2
|| !p_info
4080 || (p_info
&& p_info
->is_strict())) return false;
4081 Type
*of_type
= get_ofType();
4082 switch (p_type
->get_typetype()) {
4085 if (!is_subtype_length_compatible(p_type
)) {
4086 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
4090 if (p_left_chain
->empty()) p_left_chain
->add(this);
4091 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4092 for (size_t i
= 0; i
< p_type
->get_nof_comps(); i
++) {
4093 CompField
*p_cf
= p_type
->get_comp_byIndex(i
);
4094 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
4095 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_cf_type
,
4097 p_left_chain
->mark_state();
4098 p_right_chain
->mark_state();
4099 p_left_chain
->add(of_type
);
4100 p_right_chain
->add(p_cf_type
);
4101 if (of_type
!= p_cf_type
4102 && !(p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4103 && !of_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
4104 p_right_chain
, p_is_inline_template
)) {
4105 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
4106 p_info
->append_ref_str(1, "." + p_cf
->get_name().get_dispname() +
4107 info_tmp
.get_ref_str(1));
4108 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
4109 info_tmp
.get_error_str());
4110 p_left_chain
->previous_state();
4111 p_right_chain
->previous_state();
4114 p_left_chain
->previous_state();
4115 p_right_chain
->previous_state();
4117 if (!p_is_inline_template
) {
4118 p_info
->set_needs_conversion(true);
4119 p_info
->add_type_conversion(p_type
, this);
4123 if (!is_subtype_length_compatible(p_type
)) {
4124 p_info
->set_is_erroneous(this, p_type
, string("Incompatible set of/SET OF "
4128 if (p_left_chain
->empty()) p_left_chain
->add(this);
4129 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4130 Type
*p_of_type
= p_type
->get_ofType()->get_type_refd_last();
4131 TypeCompatInfo
info_tmp(p_info
->get_my_module(), of_type
, p_of_type
,
4133 p_left_chain
->mark_state();
4134 p_right_chain
->mark_state();
4135 p_left_chain
->add(of_type
);
4136 p_right_chain
->add(p_of_type
);
4137 if (of_type
== p_of_type
4138 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4139 || of_type
->is_compatible(p_of_type
, &info_tmp
, p_left_chain
,
4140 p_right_chain
, p_is_inline_template
)) {
4141 if (!p_is_inline_template
) {
4142 p_info
->set_needs_conversion(true);
4143 p_info
->add_type_conversion(p_type
, this);
4145 p_left_chain
->previous_state();
4146 p_right_chain
->previous_state();
4149 p_info
->append_ref_str(0, "[]" + info_tmp
.get_ref_str(0));
4150 p_info
->append_ref_str(1, "[]" + info_tmp
.get_ref_str(1));
4151 p_info
->set_is_erroneous(info_tmp
.get_type(0), info_tmp
.get_type(1),
4152 info_tmp
.get_error_str());
4153 p_left_chain
->previous_state();
4154 p_right_chain
->previous_state();
4159 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype "
4160 "types are compatible only with other "
4161 "union/CHOICE/anytype types"));
4167 p_info
->set_is_erroneous(this, p_type
, string("set/SET and set of/SET OF "
4168 "types are compatible only with other set/SET "
4169 "set of/SET OF types"));
4176 bool Type::is_compatible_choice_anytype(Type
*p_type
,
4177 TypeCompatInfo
*p_info
,
4178 TypeChain
*p_left_chain
,
4179 TypeChain
*p_right_chain
,
4180 bool p_is_inline_template
)
4182 if (typetype
!= T_ANYTYPE
&& typetype
!= T_CHOICE_A
4183 && typetype
!= T_CHOICE_T
)
4184 FATAL_ERROR("Type::is_compatible_choice_anytype()");
4185 if (this == p_type
) return true; // Original "true" leaf...
4186 else if (!use_runtime_2
|| !p_info
4187 || (p_info
&& p_info
->is_strict())) return false; // ...and "false".
4188 if ((typetype
== T_ANYTYPE
&& p_type
->get_typetype() != T_ANYTYPE
)
4189 || (p_type
->get_typetype() == T_ANYTYPE
&& typetype
!= T_ANYTYPE
)) {
4190 p_info
->set_is_erroneous(this, p_type
, string("Type anytype is compatible only "
4191 "with other anytype types"));
4194 switch (p_type
->get_typetype()) {
4202 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE/anytype types are "
4203 "compatible only with other union/CHOICE/anytype "
4208 if (typetype
!= T_CHOICE_A
&& typetype
!= T_CHOICE_T
) {
4209 p_info
->set_is_erroneous(this, p_type
, string("union/CHOICE types are "
4210 "compatible only with other union/CHOICE "
4216 if (p_left_chain
->empty()) p_left_chain
->add(this);
4217 if (p_right_chain
->empty()) p_right_chain
->add(p_type
);
4218 // Find a field with the same name and with compatible type. There can
4219 // be more alternatives, we need to generate all conversion functions.
4220 // The same field types must be avoided. (For anytypes the "field
4221 // name = module name + field name".)
4222 bool alles_okay
= false;
4223 for (size_t i
= 0; i
< get_nof_comps(); i
++) {
4224 CompField
*cf
= get_comp_byIndex(i
);
4225 Type
*cf_type
= cf
->get_type()->get_type_refd_last();
4226 for (size_t j
= 0; j
< p_type
->get_nof_comps(); ++j
) {
4227 CompField
*p_cf
= p_type
->get_comp_byIndex(j
);
4228 Type
*p_cf_type
= p_cf
->get_type()->get_type_refd_last();
4229 if (cf
->get_name().get_name() != p_cf
->get_name().get_name())
4231 // Don't report errors for each incompatible field, it would be a
4232 // complete mess. Use this temporary for all fields. And forget
4234 TypeCompatInfo
info_tmp(p_info
->get_my_module(), cf_type
, p_cf_type
,
4236 p_left_chain
->mark_state();
4237 p_right_chain
->mark_state();
4238 p_left_chain
->add(cf_type
);
4239 p_right_chain
->add(p_cf_type
);
4240 if (cf_type
== p_cf_type
4241 || (p_left_chain
->has_recursion() && p_right_chain
->has_recursion())
4242 || cf_type
->is_compatible(p_cf_type
, &info_tmp
, p_left_chain
,
4243 p_right_chain
, p_is_inline_template
)) {
4244 if (cf_type
!= p_cf_type
&& cf_type
->is_structured_type()
4245 && p_cf_type
->is_structured_type()) {
4246 if (typetype
== T_ANYTYPE
&& cf_type
->get_my_scope()
4247 ->get_scope_mod() != p_cf_type
->get_my_scope()
4248 ->get_scope_mod()) {
4249 p_left_chain
->previous_state();
4250 p_right_chain
->previous_state();
4253 p_info
->add_type_conversion(p_cf_type
, cf_type
);
4257 p_left_chain
->previous_state();
4258 p_right_chain
->previous_state();
4261 if (alles_okay
&& !p_is_inline_template
) {
4262 p_info
->set_needs_conversion(true);
4263 p_info
->add_type_conversion(p_type
, this);
4266 p_info
->set_is_erroneous(this, p_type
, string("No compatible "
4267 "union/CHOICE/anytype field found"));
4275 /** \todo consider subtype constraints */
4276 bool Type::is_identical(Type
*p_type
)
4280 Type
*t1
= get_type_refd_last();
4281 Type
*t2
= p_type
->get_type_refd_last();
4282 if (t2
->typetype
== T_ERROR
) return true;
4283 switch (t1
->typetype
) {
4285 // error type is identical to everything
4305 // user-defined structured types must be identical
4308 // the embedded type and the dimension must be identical in case of arrays
4309 return t2
->typetype
== T_ARRAY
&&
4310 t1
->u
.array
.element_type
->is_identical(t2
->u
.array
.element_type
) &&
4311 t1
->u
.array
.dimension
->is_identical(t2
->u
.array
.dimension
);
4313 // in case of built-in types the TTCN-3 view of typetype must be the same
4314 return get_typetype_ttcn3(t1
->typetype
) ==
4315 get_typetype_ttcn3(t2
->typetype
);
4319 void Type::tr_compsof(ReferenceChain
*refch
)
4321 if (typetype
!=T_SEQ_A
&& typetype
!=T_SET_A
)
4322 FATAL_ERROR("Type::tr_compsof()");
4323 if (u
.secho
.tr_compsof_ready
) return;
4324 if (u
.secho
.block
) parse_block_Se();
4325 bool auto_tagging
=u
.secho
.ctss
->needs_auto_tags();
4327 refch
->mark_state();
4328 if (refch
->add(get_fullname())) u
.secho
.ctss
->tr_compsof(refch
, false);
4329 refch
->prev_state();
4330 u
.secho
.tr_compsof_ready
= true;
4331 u
.secho
.ctss
->tr_compsof(0, true);
4333 ReferenceChain
refch2(this, "While resolving COMPONENTS OF");
4334 refch2
.add(get_fullname());
4335 Error_Context
cntxt(this, "While resolving COMPONENTS OF");
4336 u
.secho
.ctss
->tr_compsof(&refch2
, false);
4337 u
.secho
.tr_compsof_ready
= true;
4338 u
.secho
.ctss
->tr_compsof(0, true);
4340 if(auto_tagging
) u
.secho
.ctss
->add_auto_tags();
4343 bool Type::is_startable()
4345 if(typetype
!= T_FUNCTION
)
4346 FATAL_ERROR("Type::is_startable()");
4348 return u
.fatref
.is_startable
;
4351 bool Type::is_list_type(bool allow_array
)
4353 switch (get_type_refd_last()->get_typetype_ttcn3()) {
4369 void Type::set_coding_function(bool encode
, const string
& function_name
)
4371 string
& coding_str
= encode
? encoding_str
: decoding_str
;
4372 if (!coding_str
.empty()) {
4373 error("Multiple custom %s functions declared for type '%s' (function `%s' "
4374 "is already set)", encode
? "encoding" : "decoding",
4375 get_typename().c_str(), coding_str
.c_str());
4378 coding_str
= function_name
;
4379 coding_by_function
= true;
4382 void Type::chk_coding(bool encode
, bool delayed
/* = false */) {
4383 string
& coding_str
= encode
? encoding_str
: decoding_str
;
4384 if (!coding_str
.empty())
4386 coding_by_function
= false;
4388 if (!w_attrib_path
) {
4389 error("No coding rule specified for type '%s'", get_typename().c_str());
4392 Type::MessageEncodingType_t coding
= CT_UNDEF
;
4394 // Checking extension attributes
4395 Ttcn::ExtensionAttributes
* extatrs
= parse_extattributes(w_attrib_path
);
4396 if (extatrs
!= 0) { // NULL means parsing error
4397 for (size_t k
= 0; k
< extatrs
->size(); ++k
) {
4398 Ttcn::ExtensionAttribute
&ea
= extatrs
->get(k
);
4399 Ttcn::TypeMappings
*inmaps
= 0, *maps
= 0;
4400 Ttcn::TypeMapping
* mapping
= 0;
4401 Ttcn::TypeMappingTarget
* target
= 0;
4403 switch (ea
.get_type()) {
4404 case Ttcn::ExtensionAttribute::ENCDECVALUE
:
4405 ea
.get_encdecvalue_mappings(inmaps
, maps
);
4406 maps
= encode
? maps
: inmaps
;
4407 maps
->set_my_scope(this->get_my_scope());
4409 // look for coding settings
4410 t
= encode
? this : Type::get_pooltype(T_BSTR
);
4411 mapping
= maps
->get_mapping_byType(t
);
4412 if (mapping
->get_nof_targets() == 0)
4415 for (size_t ind
= 0; ind
< mapping
->get_nof_targets(); ind
++) {
4416 target
= mapping
->get_target_byIndex(ind
);
4417 t
= target
->get_target_type();
4418 if ((encode
&& (t
->get_typetype() == T_BSTR
)) ||
4419 (!encode
&& (t
->get_typename() == this->get_typename())))
4421 if (target
->get_mapping_type() ==
4422 Ttcn::TypeMappingTarget::TM_FUNCTION
) {
4423 if (!coding_str
.empty())
4424 target
->error("Multiple definition of this target");
4425 coding_str
= target
->get_function()->
4426 get_genname_from_scope(my_scope
);
4427 coding_by_function
= true;
4429 target
->error("Only function is supported to do this mapping");
4433 if (coding_str
.empty()) {
4434 ea
.warning("Extension attribute is found for %s but without "
4435 "typemappings", encode
? "encvalue" : "decvalue");
4440 case Ttcn::ExtensionAttribute::ANYTYPELIST
:
4441 break; // ignore (may be inherited from the module)
4443 case Ttcn::ExtensionAttribute::NONE
:
4444 break; // ignore erroneous attribute
4447 ea
.error("A type can only have type mapping extension attribute: "
4448 "in(...) or out(...)");
4455 if (!coding_str
.empty())
4459 const vector
<SingleWithAttrib
>& real_attribs
4460 = w_attrib_path
->get_real_attrib();
4462 for (size_t i
= real_attribs
.size(); i
> 0 && !found
; i
--) {
4463 if (real_attribs
[i
-1]->get_attribKeyword()
4464 == SingleWithAttrib::AT_ENCODE
) {
4466 coding
= get_enc_type(*real_attribs
[i
-1]);
4469 if (coding
== CT_UNDEF
) {
4470 // no "encode" attribute found
4471 error("No coding rule specified for type '%s'", get_typename().c_str());
4474 if (coding
!= CT_CUSTOM
&& !has_encoding(coding
)) {
4475 error("Type '%s' cannot be coded with the selected method '%s'",
4476 get_typename().c_str(),
4477 get_encoding_name(coding
));
4485 coding_str
= "TEXT";
4491 coding_str
= "XER, XER_EXTENDED"; // TODO: fine tuning this parameter
4494 coding_str
= "JSON";
4497 coding_str
= "BER, ";
4498 BerAST
* ber
= berattrib
;
4499 if (!ber
) // use default settings if attributes are not specified
4502 coding_str
+= ber
->get_encode_str();
4504 coding_str
+= ber
->get_decode_str();
4510 // coding_str is set by the coding function's checker in this case;
4511 // it's possible, that the function exists, but has not been reached yet;
4512 // delay this function until everything else has been checked
4513 Modules::delay_type_encode_check(this, encode
);
4515 else if (coding_str
.empty()) {
4516 // this is the delayed call, and the custom coding function has still
4518 error("No custom %s function found for type `%s'",
4519 encode
? "encoding" : "decoding", get_typename().c_str());
4523 error("Unknown coding selected for type '%s'", get_typename().c_str());
4526 coding_by_function
= false;
4529 bool Type::is_coding_by_function() const {
4530 return coding_by_function
;
4533 const string
& Type::get_coding(bool encode
) const {
4535 return encoding_str
;
4537 return decoding_str
;
4540 namespace { // unnamed
4541 const string
ex_emm_ell("XML"), ex_ee_arr("XER");
4544 Type::MessageEncodingType_t
Type::get_enc_type(const SingleWithAttrib
& atr
) {
4545 const string
& enc
= atr
.get_attribSpec().get_spec();
4548 else if (enc
== "TEXT")
4550 else if (enc
== "JSON")
4552 else if (enc
== "BER:2002" || enc
== "CER:2002" || enc
== "DER:2002")
4554 else if (enc
== ex_emm_ell
)
4556 else if (enc
== ex_ee_arr
) {
4557 atr
.warning("The correct name of the encoding is ''XML''");
4560 else if (enc
== "PER")
4565 bool Type::has_ei_withName(const Identifier
& p_id
) const
4573 FATAL_ERROR("Type::has_ei_withName()");
4575 return u
.enums
.eis
->has_ei_withName(p_id
);
4578 EnumItem
*Type::get_ei_byName(const Identifier
& p_id
) const
4586 FATAL_ERROR("Type::get_ei_byName()");
4588 return u
.enums
.eis
->get_ei_byName(p_id
);
4591 EnumItem
*Type::get_ei_byIndex(size_t n
) const
4599 FATAL_ERROR("Type::get_ei_byIndex()");
4601 return u
.enums
.eis
->get_ei_byIndex(n
);
4604 size_t Type::get_nof_comps()
4612 return u
.secho
.cfm
->get_nof_comps();
4615 if(u
.secho
.block
) parse_block_Se();
4616 return u
.secho
.ctss
->get_nof_comps();
4618 if(u
.secho
.block
) parse_block_Choice();
4619 return u
.secho
.ctss
->get_nof_comps();
4621 return u
.array
.dimension
->get_size();
4623 if (u
.signature
.parameters
)
4624 return u
.signature
.parameters
->get_nof_params();
4627 FATAL_ERROR("Type::get_nof_comps(%d)", typetype
);
4632 const Identifier
& Type::get_comp_id_byIndex(size_t n
)
4640 return u
.secho
.cfm
->get_comp_byIndex(n
)->get_name();
4643 if(u
.secho
.block
) parse_block_Se();
4644 return u
.secho
.ctss
->get_comp_byIndex(n
)->get_name();
4646 if(u
.secho
.block
) parse_block_Choice();
4647 return u
.secho
.ctss
->get_comp_byIndex(n
)->get_name();
4649 return u
.signature
.parameters
->get_param_byIndex(n
)->get_id();
4651 FATAL_ERROR("Type::get_comp_id_byIndex()");
4653 // to avoid warnings
4654 const Identifier
*fake
= 0;
4658 CompField
* Type::get_comp_byIndex(size_t n
)
4666 return u
.secho
.cfm
->get_comp_byIndex(n
);
4669 if(u
.secho
.block
) parse_block_Se();
4670 return u
.secho
.ctss
->get_comp_byIndex(n
);
4672 if(u
.secho
.block
) parse_block_Choice();
4673 return u
.secho
.ctss
->get_comp_byIndex(n
);
4675 FATAL_ERROR("Type::get_comp_byIndex()");
4680 size_t Type::get_comp_index_byName(const Identifier
& p_name
)
4682 Type
*t
= get_type_refd_last();
4684 FATAL_ERROR("Type::get_comp_index_byName()");
4685 if (!t
->u
.secho
.field_by_name
) {
4686 t
->u
.secho
.field_by_name
= new map
<string
, size_t>;
4687 size_t nof_comps
= t
->get_nof_comps();
4688 for (size_t i
= 0; i
< nof_comps
; i
++) {
4689 const string
& field_name
=
4690 t
->get_comp_byIndex(i
)->get_name().get_name();
4691 if (!t
->u
.secho
.field_by_name
->has_key(field_name
))
4692 t
->u
.secho
.field_by_name
->add(field_name
, new size_t(i
));
4695 return *(*t
->u
.secho
.field_by_name
)[p_name
.get_name()];
4698 size_t Type::get_eis_index_byName(const Identifier
& p_name
)
4700 Type
*t
= get_type_refd_last();
4701 switch (t
->typetype
) {
4706 FATAL_ERROR("Type::get_eis_index_byName()");
4708 if (!t
->u
.enums
.eis_by_name
) {
4709 t
->u
.enums
.eis_by_name
= new map
<string
, size_t>;
4710 size_t nof_eis
= t
->u
.enums
.eis
->get_nof_eis();
4711 for (size_t i
= 0; i
< nof_eis
; i
++) {
4712 const string
& enum_name
=
4713 t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name().get_name();
4714 if (!t
->u
.enums
.eis_by_name
->has_key(enum_name
))
4715 t
->u
.enums
.eis_by_name
->add(enum_name
, new size_t(i
));
4718 return *(*t
->u
.enums
.eis_by_name
)[p_name
.get_name()];
4721 const Int
& Type::get_enum_val_byId(const Identifier
& p_name
)
4723 if(!checked
) FATAL_ERROR("Type::get_enum_val_byId(): Not checked.");
4729 FATAL_ERROR("Type::get_enum_val_byId()");
4731 return u
.enums
.eis
->get_ei_byName(p_name
)->get_value()
4732 ->get_value_refd_last()->get_val_Int()->get_val();
4735 size_t Type::get_nof_root_comps()
4740 if(u
.secho
.block
) parse_block_Se();
4741 return u
.secho
.ctss
->get_nof_root_comps();
4744 FATAL_ERROR("Type::get_nof_root_comps()");
4749 CompField
* Type::get_root_comp_byIndex(size_t n
)
4754 if(u
.secho
.block
) parse_block_Se();
4755 return u
.secho
.ctss
->get_root_comp_byIndex(n
);
4758 FATAL_ERROR("Type::get_root_comp_byIndex()");
4763 bool Type::has_comp_withName(const Identifier
& p_name
)
4765 Type
*t
= get_type_refd_last();
4766 switch (t
->typetype
) {
4772 return t
->u
.secho
.cfm
->has_comp_withName(p_name
);
4775 if (t
->u
.secho
.block
) t
->parse_block_Se();
4776 return t
->u
.secho
.ctss
->has_comp_withName(p_name
);
4778 if (t
->u
.secho
.block
) t
->parse_block_Choice();
4779 return t
->u
.secho
.ctss
->has_comp_withName(p_name
);
4781 if (t
->u
.signature
.parameters
)
4782 return t
->u
.signature
.parameters
->has_param_withName(p_name
);
4785 FATAL_ERROR("Type::has_comp_withName()");
4790 CompField
* Type::get_comp_byName(const Identifier
& p_name
)
4792 Type
*t
= get_type_refd_last();
4793 switch (t
->typetype
) {
4799 return t
->u
.secho
.cfm
->get_comp_byName(p_name
);
4802 if (t
->u
.secho
.block
) t
->parse_block_Se();
4803 return t
->u
.secho
.ctss
->get_comp_byName(p_name
);
4805 if(t
->u
.secho
.block
) t
->parse_block_Choice();
4806 return t
->u
.secho
.ctss
->get_comp_byName(p_name
);
4808 FATAL_ERROR("Type::get_comp_byName()");
4813 void Type::add_comp(CompField
*p_cf
)
4821 u
.secho
.cfm
->add_comp(p_cf
);
4824 FATAL_ERROR("Type::add_comp()");
4828 Type
*Type::get_ofType()
4830 Type
*t
=get_type_refd_last();
4831 switch (t
->typetype
) {
4834 return t
->u
.seof
.ofType
;
4836 return t
->u
.array
.element_type
;
4838 FATAL_ERROR("Type::get_ofType()");
4843 OC_defn
* Type::get_my_oc()
4847 return u
.ref
.oc_defn
;
4850 return u
.secho
.oc_defn
;
4853 FATAL_ERROR("Type::get_my_oc()");
4858 const Identifier
& Type::get_oc_fieldname()
4862 return *u
.ref
.oc_fieldname
;
4865 return *u
.secho
.oc_fieldname
;
4868 FATAL_ERROR("Type::get_oc_fieldname()");
4869 // to avoid warning...
4870 return *u
.secho
.oc_fieldname
;
4874 void Type::set_my_tableconstraint(const TableConstraint
*p_tc
)
4878 u
.secho
.my_tableconstraint
=p_tc
;
4881 FATAL_ERROR("Type::set_my_tableconstraint()");
4885 const TableConstraint
* Type::get_my_tableconstraint()
4889 return u
.secho
.my_tableconstraint
;
4892 FATAL_ERROR("Type::get_my_tableconstraint()");
4897 Ttcn::ArrayDimension
*Type::get_dimension() const
4899 if (typetype
!= T_ARRAY
) FATAL_ERROR("Type::get_dimension()");
4900 return u
.array
.dimension
;
4903 Ttcn::PortTypeBody
*Type::get_PortBody() const
4905 if (typetype
!= T_PORT
) FATAL_ERROR("Type::get_PortBody()");
4909 ComponentTypeBody
*Type::get_CompBody() const
4911 if (typetype
!= T_COMPONENT
) FATAL_ERROR("Type::get_CompBody()");
4915 SignatureParamList
*Type::get_signature_parameters() const
4917 if (typetype
!= T_SIGNATURE
|| !checked
)
4918 FATAL_ERROR("Type::get_signature_parameters()");
4919 return u
.signature
.parameters
;
4922 SignatureExceptions
*Type::get_signature_exceptions() const
4924 if (typetype
!= T_SIGNATURE
|| !checked
)
4925 FATAL_ERROR("Type::get_signature_exceptions()");
4926 return u
.signature
.exceptions
;
4929 Type
*Type::get_signature_return_type() const
4931 if (typetype
!= T_SIGNATURE
|| !checked
)
4932 FATAL_ERROR("Type::get_signature_return_type()");
4933 return u
.signature
.return_type
;
4936 bool Type::is_nonblocking_signature() const
4938 if (typetype
!= T_SIGNATURE
|| !checked
)
4939 FATAL_ERROR("Type::is_nonblocking_signature()");
4940 return u
.signature
.no_block
;
4943 Ttcn::FormalParList
*Type::get_fat_parameters()
4945 if(!checked
) FATAL_ERROR("Type::get_fat_parameteres()");
4950 return u
.fatref
.fp_list
;
4952 FATAL_ERROR("Type::get_fat_parameteres()");
4957 Type
*Type::get_function_return_type()
4959 if(!checked
) FATAL_ERROR("Type::get_function_return_type()");
4962 return u
.fatref
.return_type
;
4964 FATAL_ERROR("Type::get_function_return_type()");
4969 Type
*Type::get_fat_runs_on_type()
4971 if(!checked
) FATAL_ERROR("Type::get_fat_runs_on_type()");
4976 return u
.fatref
.runs_on
.type
;
4978 FATAL_ERROR("Type::get_fat_runs_on_type()");
4983 bool Type::get_fat_runs_on_self()
4985 if(!checked
) FATAL_ERROR("Type::get_fat_runs_on_self()");
4990 return u
.fatref
.runs_on
.self
;
4992 FATAL_ERROR("Type::get_fat_runs_on_self()");
4997 bool Type::get_returns_template()
4999 if (!checked
|| typetype
!= T_FUNCTION
)
5000 FATAL_ERROR("Type::Returns_template()");
5001 return u
.fatref
.returns_template
;
5004 void Type::add_tag(Tag
*p_tag
)
5006 if(!tags
) tags
=new Tags();
5007 tags
->add_tag(p_tag
);
5010 void Type::add_constraints(Constraints
*p_constraints
)
5012 if(!p_constraints
) return;
5014 FATAL_ERROR("This type already has its constraints");
5015 constraints
=p_constraints
;
5016 constraints
->set_my_type(this);
5019 Reference
* Type::get_Reference()
5024 void Type::chk_table_constraints()
5026 if(!tbl_cons_checked
) {
5027 tbl_cons_checked
=true;
5028 if (constraints
) constraints
->chk_table();
5037 for(size_t i
=0; i
<get_nof_comps(); i
++)
5038 get_comp_byIndex(i
)->get_type()->chk_table_constraints();
5042 u
.seof
.ofType
->chk_table_constraints();
5050 void Type::check_subtype_constraints()
5052 if (sub_type
!=NULL
) FATAL_ERROR("Type::check_subtype_constraints()");
5054 // get parent subtype or NULL if it doesn't exist
5055 SubType
* parent_subtype
= NULL
;
5056 if (is_ref()) parent_subtype
= get_type_refd()->sub_type
;
5058 // if the parent subtype is erroneous then ignore it, the error was already
5060 if ( (parent_subtype
!=NULL
) &&
5061 (parent_subtype
->get_subtypetype()==SubtypeConstraint::ST_ERROR
) )
5062 parent_subtype
= NULL
;
5064 // return if there are neither inherited nor own constraints
5065 if ( (parent_subtype
==NULL
) && (parsed_restr
==NULL
) && (constraints
==NULL
)
5066 && (SubtypeConstraint::get_asn_type_constraint(this)==NULL
) ) return;
5068 // the subtype type is determined by the type of this type
5069 if (get_type_refd_last()->get_typetype()==T_ERROR
) return;
5070 SubtypeConstraint::subtype_t s_t
= get_subtype_type();
5071 if (s_t
==SubtypeConstraint::ST_ERROR
) {
5072 error("Subtype constraints are not applicable to type `%s'",
5073 get_typename().c_str());
5077 // create the aggregate subtype for this type
5078 sub_type
= new SubType(s_t
, this, parent_subtype
, parsed_restr
, constraints
);
5082 bool Type::has_multiple_tags()
5084 if (tags
) return false;
5093 return get_type_refd()->has_multiple_tags();
5099 Tag
*Type::get_tag()
5102 Tag
*tag
=tags
->get_tag_byIndex(tags
->get_nof_tags()-1);
5106 else return get_default_tag();
5109 void Type::get_tags(TagCollection
& coll
, map
<Type
*, void>& chain
)
5111 if(typetype
!=T_CHOICE_A
)
5112 FATAL_ERROR("Type::get_tags()");
5113 if (chain
.has_key(this)) return;
5115 if(u
.secho
.block
) parse_block_Choice();
5116 size_t n_alts
= u
.secho
.ctss
->get_nof_comps();
5117 for(size_t i
=0; i
<n_alts
; i
++) {
5118 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
5119 Type
*type
= cf
->get_type();
5120 if(type
->has_multiple_tags()) {
5121 type
=type
->get_type_refd_last();
5122 type
->get_tags(coll
, chain
);
5125 const Tag
*tag
=type
->get_tag();
5126 if(coll
.hasTag(tag
))
5127 error("Alternative `%s' in CHOICE has non-distinct tag",
5128 cf
->get_name().get_dispname().c_str());
5129 else coll
.addTag(tag
);
5132 if(u
.secho
.ctss
->has_ellipsis()) coll
.setExtensible();
5135 Tag
*Type::get_smallest_tag()
5137 if(!has_multiple_tags()) return get_tag()->clone();
5138 Type
*t
=get_type_refd_last();
5139 TagCollection tagcoll
;
5140 map
<Type
*, void> chain
;
5141 t
->get_tags(tagcoll
, chain
);
5143 return tagcoll
.getSmallestTag()->clone();
5146 bool Type::needs_explicit_tag()
5155 if(!dynamic_cast<Asn::Ref_pard
*>(u
.ref
.ref
)) {
5156 Scope
*s
=u
.ref
.ref
->get_refd_assignment()->get_my_scope();
5157 if(s
->get_parent_scope()!=s
->get_scope_mod()) {
5158 // Not in the module scope, so it is a dummyreference (X.680
5161 WARNING("%s is a dummyreference, i give him an explicit tag :)",
5162 get_fullname().c_str());
5163 WARNING("0: %s", s->get_scope_name().c_str());
5164 WARNING("1: %s", s->get_parent_scope()->get_scope_name().c_str());
5165 WARNING("2: %s", s->get_scope_mod()->get_scope_name().c_str());
5175 Type
*t
= get_type_refd();
5176 if(t
->is_tagged()) return false;
5177 else return t
->needs_explicit_tag();
5180 // T_ANYTYPE probably does not need explicit tagging
5185 void Type::cut_auto_tags()
5188 tags
->cut_auto_tags();
5189 if (tags
->get_nof_tags() == 0) {
5197 * I suppose in this function that tags->chk() and
5198 * tags->set_plicit() are already done.
5200 Tags
* Type::build_tags_joined(Tags
*p_tags
)
5202 if(!p_tags
) p_tags
=new Tags();
5209 get_type_refd()->build_tags_joined(p_tags
);
5213 //TODO case T_ANYTYPE: for build_tags_joined ?
5218 p_tags
->add_tag(get_default_tag()->clone());
5222 for(size_t i
=0; i
<tags
->get_nof_tags(); i
++) {
5223 Tag
*tag
=tags
->get_tag_byIndex(i
);
5224 switch(tag
->get_plicit()) {
5225 case Tag::TAG_EXPLICIT
:
5226 p_tags
->add_tag(tag
->clone());
5228 case Tag::TAG_IMPLICIT
: {
5229 Tag
*t_p_tag
=p_tags
->get_tag_byIndex(p_tags
->get_nof_tags()-1);
5230 t_p_tag
->set_tagclass(tag
->get_tagclass());
5231 t_p_tag
->set_tagvalue(tag
->get_tagvalue());
5234 FATAL_ERROR("Type::build_tags_joined()");
5241 void Type::set_with_attr(Ttcn::MultiWithAttrib
* p_attrib
)
5245 w_attrib_path
= new WithAttribPath();
5248 w_attrib_path
->set_with_attr(p_attrib
);
5251 void Type::set_parent_path(WithAttribPath
* p_path
)
5255 w_attrib_path
= new WithAttribPath();
5257 w_attrib_path
->set_parent(p_path
);
5258 if (typetype
== T_COMPONENT
)
5259 u
.component
->set_parent_path(w_attrib_path
);
5262 WithAttribPath
* Type::get_attrib_path() const
5264 return w_attrib_path
;
5267 bool Type::hasRawAttrs()
5269 if(rawattrib
) return true;
5273 if(w_attrib_path
->get_had_global_variants()) return true;
5275 vector
<SingleWithAttrib
> const &real_attribs
5276 = w_attrib_path
->get_real_attrib();
5278 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
5279 if (real_attribs
[i
]->get_attribKeyword()
5280 == SingleWithAttrib::AT_VARIANT
)
5285 MultiWithAttrib
* temp_attrib
= w_attrib_path
->get_with_attr();
5287 for(size_t i
= 0; i
< temp_attrib
->get_nof_elements(); i
++)
5288 if(temp_attrib
->get_element(i
)->get_attribKeyword()
5289 == SingleWithAttrib::AT_VARIANT
5290 && (!temp_attrib
->get_element(i
)->get_attribQualifiers()
5291 || temp_attrib
->get_element(i
)->get_attribQualifiers()
5292 ->get_nof_qualifiers() == 0))
5294 w_attrib_path
->set_had_global_variants( true );
5302 bool Type::hasNeedofRawAttrs()
5304 if(rawattrib
) return true;
5311 nof_comps
= get_nof_comps();
5312 for(size_t i
=0; i
< nof_comps
; i
++)
5314 if(get_comp_byIndex(i
)->get_type()->hasNeedofRawAttrs())
5326 bool Type::hasNeedofTextAttrs()
5328 if(textattrib
) return true;
5335 nof_comps
= get_nof_comps();
5336 for(size_t i
=0; i
< nof_comps
; i
++)
5338 if(get_comp_byIndex(i
)->get_type()->hasNeedofTextAttrs())
5350 bool Type::hasNeedofJsonAttrs()
5352 if(jsonattrib
) return true;
5359 nof_comps
= get_nof_comps();
5360 for (size_t i
= 0; i
< nof_comps
; ++i
)
5362 if (get_comp_byIndex(i
)->get_type()->hasNeedofJsonAttrs())
5374 bool Type::hasNeedofXerAttrs()
5376 if(xerattrib
&& !xerattrib
->empty()) return true;
5383 nof_comps
= get_nof_comps();
5384 for(size_t i
=0; i
< nof_comps
; i
++)
5386 if(get_comp_byIndex(i
)->get_type()->hasNeedofXerAttrs())
5398 bool Type::hasVariantAttrs()
5402 if(w_attrib_path
->get_had_global_variants()) return true;
5404 vector
<SingleWithAttrib
> const &real_attribs
5405 = w_attrib_path
->get_real_attrib();
5407 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
5408 if (real_attribs
[i
]->get_attribKeyword()
5409 == SingleWithAttrib::AT_VARIANT
)
5414 MultiWithAttrib
* temp_attrib
= w_attrib_path
->get_with_attr();
5416 for(size_t i
= 0; i
< temp_attrib
->get_nof_elements(); i
++)
5417 if(temp_attrib
->get_element(i
)->get_attribKeyword()
5418 == SingleWithAttrib::AT_VARIANT
5419 && (!temp_attrib
->get_element(i
)->get_attribQualifiers()
5420 || temp_attrib
->get_element(i
)->get_attribQualifiers()
5421 ->get_nof_qualifiers() != 0))
5423 w_attrib_path
->set_had_global_variants( true );
5431 bool Type::hasEncodeAttr(const char* encoding_name
)
5433 if (0 == strcmp(encoding_name
, "JSON") && (implicit_json_encoding
5434 || is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) {
5435 // ASN.1 types automatically support JSON encoding
5438 // Check the type itself first, then the root type
5439 WithAttribPath
*aps
[2] = { 0, 0 };
5440 size_t num_aps
= ((aps
[0] = get_attrib_path()) != 0);
5441 // assign, compare, then add 0 or 1
5443 num_aps
+= ((aps
[num_aps
] = get_type_refd()->get_attrib_path()) != 0);
5445 for (size_t a
= 0; a
< num_aps
; ++a
) {
5446 const vector
<SingleWithAttrib
>& real
= aps
[a
]->get_real_attrib();
5447 const size_t num_atr
= real
.size();
5448 for (size_t i
= 0; i
< num_atr
; ++i
) {
5449 const SingleWithAttrib
& s
= *real
[i
];
5450 if (s
.get_attribKeyword() == SingleWithAttrib::AT_ENCODE
) {
5451 const string
& spec
= s
.get_attribSpec().get_spec();
5452 if (spec
== encoding_name
) {
5461 namespace { // unnamed
5463 enum state
{ PROCESSING
= -1, ANSWER_NO
, ANSWER_YES
};
5465 struct memoizer
: private map
<Type
*, state
> {
5466 memoizer() : map
<Type
*, state
>() {}
5469 for (int i
= size()-1; i
>= 0; --i
) {
5470 delete get_nth_elem(i
);
5475 bool remember (Type
*t
, state s
) {
5480 add(t
, new state(s
));
5482 return s
== ANSWER_YES
;
5485 bool has_key(Type
*t
) {
5486 return map
<Type
*, state
>::has_key(t
);
5489 state
* get(Type
*t
) {
5490 return operator [](t
);
5496 bool Type::has_encoding(MessageEncodingType_t encoding_type
, const string
* custom_encoding
/* = NULL */)
5498 static memoizer memory
;
5499 static memoizer json_mem
;
5501 switch (encoding_type
) {
5505 if (t
->is_asn1()) return true;
5506 else if (t
->is_ref()) t
= t
->get_type_refd();
5508 switch (t
->typetype
) {
5516 // these basic TTCN-3 types have ASN.1 equivalents
5525 if (memory
.has_key(this)) {
5526 state
*s
= memory
.get(this);
5538 // For ASN.1 types, the answer depends solely on the -a switch.
5539 // They are all considered to have Basic (i.e. useless) XER,
5540 // unless the -a switch says removes XER from all ASN.1 types.
5541 if (t
->is_asn1()) return memory
.remember(t
,
5542 asn1_xer
? ANSWER_YES
: ANSWER_NO
);
5543 else if (t
->is_ref()) t
= t
->get_type_refd();
5544 else { // at the end of the ref. chain
5545 switch (t
->typetype
) {
5551 // The octetstring type can always be encoded in XER.
5552 // XSD:base64Binary is only needed for Type::is_charenc()
5554 case T_HSTR
: // TTCN-3 hexstring
5555 case T_VERDICT
: // TTCN-3 verdict
5556 case T_CSTR
: // TTCN3 charstring
5557 case T_USTR
: // TTCN3 universal charstring
5558 return memory
.remember(t
, ANSWER_YES
);
5561 break; // the switch; skip to checking if it has encode "XML";
5563 case T_PORT
: // TTCN-3 port (the list of in's, out's, inout's)
5564 case T_COMPONENT
: // TTCN-3 comp. type (extends, and { ... })
5565 case T_DEFAULT
: // TTCN-3
5566 case T_SIGNATURE
: // TTCN-3
5567 case T_FUNCTION
: // TTCN-3
5568 case T_ALTSTEP
: // TTCN-3
5569 case T_TESTCASE
: // TTCN-3
5570 case T_ANYTYPE
: // TTCN-3 anytype
5571 return memory
.remember(t
, ANSWER_NO
);
5576 return false; // why don't we remember these ?
5581 // No field may reject XER
5582 size_t ncomp
= t
->get_nof_comps();
5583 for (size_t i
= 0; i
< ncomp
; ++i
) {
5584 Type
*t2
= t
->get_comp_byIndex(i
)->get_type();
5585 bool subresult
= false;
5586 if (memory
.has_key(t2
)) {
5587 switch (*memory
.get(t2
)) {
5589 // This type contains itself and is in the process
5590 // of being checked. Pretend it doesn't exist.
5591 // The answer will be determined by the other fields,
5592 // and it will propagate back up.
5593 // Avoids infinite recursion for self-referencing types.
5604 memory
.remember(t2
, PROCESSING
);
5605 subresult
= t2
->has_encoding(CT_XER
);
5608 if (subresult
) memory
.remember(t2
, ANSWER_YES
);
5609 else return memory
.remember(t2
, ANSWER_NO
);
5610 // Note: return only if the answer (false) is known.
5611 // If the answer is true, keep checking.
5613 // Empty record, or all fields supported XER: answer maybe yes.
5618 bool subresult
= false;
5619 Type
*t2
= t
->u
.seof
.ofType
;
5620 if (memory
.has_key(t2
)) {
5621 switch (*memory
.get(t2
)) {
5623 // Recursive record-of. This is OK because the recursion
5624 // can always be broken with an empty record-of.
5636 memory
.remember(t2
, PROCESSING
);
5637 // Check the contained type
5638 subresult
= t2
->has_encoding(CT_XER
);
5640 if (subresult
) break; // continue checking
5641 else return memory
.remember(t
, ANSWER_NO
); // No means no.
5644 case T_NULL
: // ASN.1 null
5645 case T_INT_A
: // ASN.1 integer
5646 case T_ENUM_A
:// ASN.1 enum
5647 case T_BSTR_A
:// ASN.1 bitstring
5648 case T_UTF8STRING
: // ASN.1
5649 case T_NUMERICSTRING
:
5650 case T_PRINTABLESTRING
:
5651 case T_TELETEXSTRING
:
5652 case T_VIDEOTEXSTRING
:
5654 case T_GRAPHICSTRING
:
5655 case T_VISIBLESTRING
:
5656 case T_GENERALSTRING
:
5657 case T_UNIVERSALSTRING
:
5659 case T_UNRESTRICTEDSTRING
: // still ASN.1
5660 case T_UTCTIME
: // ASN.1 string
5661 case T_GENERALIZEDTIME
: // ASN.1 string
5662 case T_OBJECTDESCRIPTOR
: // ASN.1 string
5663 case T_ROID
: // relative OID (ASN.1)
5666 case T_SEQ_A
: // ASN.1 versions of choice,sequence,set
5669 case T_OCFT
: // ObjectClassFieldType (ASN.1)
5670 case T_OPENTYPE
: // ASN.1 open type
5671 case T_ANY
: // deprecated ASN.1 ANY
5673 case T_EXTERNAL
: // ASN.1 external
5674 case T_EMBEDDED_PDV
: // ASN.1 embedded pdv
5675 case T_SELTYPE
: // selection type (ASN.1)
5676 FATAL_ERROR("Type::has_encoding(): typetype %d should be asn1",
5678 break; // not reached
5680 case T_REFD
: // reference to another type
5681 case T_ADDRESS
: // TTCN-3 address type
5682 case T_ARRAY
: // TTCN-3 array
5683 default: // FIXME: if compiling with -Wswitch, the default should be removed
5684 return memory
.remember(t
, ANSWER_NO
);
5685 } // switch t->typetype
5687 // Check to see if it has an encode "XML"; first the type itself,
5688 // then the root type.
5689 WithAttribPath
*aps
[2] = {0,0};
5690 size_t num_aps
= ((aps
[0] = this->get_attrib_path()) != 0);
5691 // assign, compare, then add 0 or 1
5693 num_aps
+= ((aps
[num_aps
] = t
->get_attrib_path()) != 0);
5695 for (size_t a
= 0; a
< num_aps
; ++a
) {
5696 const vector
<SingleWithAttrib
>& real
= aps
[a
]->get_real_attrib();
5697 const size_t num_atr
= real
.size();
5698 for (size_t i
= 0; i
< num_atr
; ++i
) {
5699 const SingleWithAttrib
& s
= *real
[i
];
5700 if (s
.get_attribKeyword() == SingleWithAttrib::AT_ENCODE
) {
5701 const string
& spec
= s
.get_attribSpec().get_spec();
5702 if (spec
== ex_emm_ell
// the right answer
5703 ||spec
== ex_ee_arr
) // the acceptable answer
5704 return memory
.remember(t
, ANSWER_YES
);
5708 return memory
.remember(t
, ANSWER_NO
); // no encode XER
5711 return memory
.remember(t
, ANSWER_NO
); }
5715 if (t
->rawattrib
) return true;
5716 else if (t
->is_ref()) t
= t
->get_type_refd();
5718 switch (t
->typetype
) {
5728 // these basic types support RAW encoding by default
5738 if (t
->textattrib
) return true;
5739 else if (t
->is_ref()) t
= t
->get_type_refd();
5741 switch (t
->typetype
) {
5747 case T_USTR
: // TTCN3 universal charstring
5748 // these basic types support TEXT encoding by default
5758 if (json_mem
.has_key(t
)) {
5759 switch (*json_mem
.get(t
)) {
5768 if (t
->jsonattrib
) {
5769 return json_mem
.remember(t
, ANSWER_YES
);
5772 t
= t
->get_type_refd();
5775 switch (t
->typetype
) {
5788 case T_NUMERICSTRING
:
5789 case T_PRINTABLESTRING
:
5790 case T_TELETEXSTRING
:
5791 case T_VIDEOTEXSTRING
:
5793 case T_GRAPHICSTRING
:
5794 case T_VISIBLESTRING
:
5795 case T_GENERALSTRING
:
5796 case T_UNIVERSALSTRING
:
5803 // these basic types support JSON encoding by default
5804 return json_mem
.remember(t
, ANSWER_YES
);
5813 // all fields must also support JSON encoding
5814 size_t ncomp
= t
->get_nof_comps();
5815 for (size_t i
= 0; i
< ncomp
; ++i
) {
5816 Type
*t2
= t
->get_comp_byIndex(i
)->get_type();
5817 if (json_mem
.has_key(t2
)) {
5818 switch (*json_mem
.get(t2
)) {
5820 // This field is OK, but we still need to check the others
5822 // This type contains itself and is in the process
5823 // of being checked. Pretend it doesn't exist.
5824 // The answer will be determined by the other fields,
5825 // and it will propagate back up.
5826 // Avoids infinite recursion for self-referencing types.
5829 // One field is not OK => the structure is not OK
5830 return json_mem
.remember(t
, ANSWER_NO
);
5834 json_mem
.remember(t2
, PROCESSING
);
5835 bool enabled
= t2
->has_encoding(CT_JSON
);
5836 json_mem
.remember(t2
, enabled
? ANSWER_YES
: ANSWER_NO
);
5838 // One field is not OK => the structure is not OK
5839 return json_mem
.remember(t
, ANSWER_NO
);
5843 break; // check for an encode attribute
5848 Type
*t2
= t
->u
.seof
.ofType
;
5849 if (json_mem
.has_key(t2
)) {
5850 switch (*json_mem
.get(t2
)) {
5852 // Continue checking
5854 // Recursive record-of. This is OK because the recursion
5855 // can always be broken with an empty record-of.
5858 return json_mem
.remember(t
, ANSWER_NO
);
5863 json_mem
.remember(t2
, PROCESSING
);
5864 bool enabled
= t2
->has_encoding(CT_JSON
);
5865 json_mem
.remember(t2
, enabled
? ANSWER_YES
: ANSWER_NO
);
5867 // One field is not OK => the structure is not OK
5868 return json_mem
.remember(t
, ANSWER_NO
);
5871 break; // check for an encode attribute
5875 break; // check for an encode attribute
5877 return json_mem
.remember(t
, ANSWER_NO
);
5879 return json_mem
.remember(t
, hasEncodeAttr(get_encoding_name(CT_JSON
)) ? ANSWER_YES
: ANSWER_NO
);
5884 // the encoding name parameter has to be the same as the encoding name
5885 // specified for the type
5886 return custom_encoding
? hasEncodeAttr(custom_encoding
->c_str()) : false;
5889 FATAL_ERROR("Type::has_encoding()");
5895 bool Type::is_pure_refd()
5899 // ASN.1 parameterized references are not pure :)
5900 if(dynamic_cast<Asn::Ref_pard
*>(u
.ref
.ref
)) return false;
5905 if (sub_type
|| constraints
) return false;
5906 else if (tags
&& enable_ber()) return false;
5907 else if (rawattrib
&& enable_raw()) return false;
5908 else if (textattrib
&& enable_text()) return false;
5909 else if (enable_xer()) return false;
5910 else if (jsonattrib
&& enable_json()) return false;
5917 string
Type::create_stringRepr()
5919 if(is_tagged() || hasRawAttrs())
5920 return get_genname_own();
5923 return string("NULL");
5925 return string("BOOLEAN");
5928 return string("INTEGER");
5930 return string("REAL");
5933 return string("BIT__STRING");
5935 return string("HEX__STRING");
5937 return string("OCTET__STRING");
5939 return string("CHAR__STRING");
5941 return string("UNIVERSAL__CHARSTRING");
5943 return string("UTF8String");
5944 case T_NUMERICSTRING
:
5945 return string("NumericString");
5946 case T_PRINTABLESTRING
:
5947 return string("PrintableString");
5948 case T_TELETEXSTRING
:
5949 return string("TeletexString");
5950 case T_VIDEOTEXSTRING
:
5951 return string("VideotexString");
5953 return string("IA5String");
5954 case T_GRAPHICSTRING
:
5955 return string("GraphicString");
5956 case T_VISIBLESTRING
:
5957 return string("VisibleString");
5958 case T_GENERALSTRING
:
5959 return string("GeneralString");
5960 case T_UNIVERSALSTRING
:
5961 return string("UniversalString");
5963 return string("BMPString");
5964 case T_UNRESTRICTEDSTRING
:
5965 return string("CHARACTER__STRING");
5967 return string("UTCTime");
5968 case T_GENERALIZEDTIME
:
5969 return string("GeneralizedTime");
5970 case T_OBJECTDESCRIPTOR
:
5971 return string("ObjectDescriptor");
5973 return string("OBJECT__IDENTIFIER");
5975 return string("RELATIVE__OID");
5977 return string("ANY");
5982 if (tags
|| constraints
||
5983 (w_attrib_path
&& w_attrib_path
->has_attribs()))
5984 return get_genname_own();
5985 else return get_type_refd()->get_stringRepr();
5987 return string("<Error_type>");
5989 return get_genname_own();
5993 Identifier
Type::get_otaltname(bool& is_strange
)
5996 if (is_tagged() || is_constrained() || hasRawAttrs()) {
5997 s
= get_genname_own();
5999 } else if (typetype
== T_REFD
) {
6000 Ref_simple
* t_ref
=dynamic_cast<Ref_simple
*>(u
.ref
.ref
);
6002 const Identifier
*id
= t_ref
->get_id();
6003 const string
& dispname
= id
->get_dispname();
6004 if (dispname
.find('.') < dispname
.size()) {
6005 // id is not regular because t_ref is a parameterized reference
6006 // use that id anyway
6007 s
+= id
->get_name();
6010 Scope
*ass_scope
= t_ref
->get_refd_assignment()->get_my_scope();
6011 if (ass_scope
->get_parent_scope() == ass_scope
->get_scope_mod()) {
6012 // t_ref points to an assignment at module scope
6013 // use the simple id of the reference (in lowercase)
6017 // t_ref is a dummy reference in a parameterized assignment
6018 // (i.e. it points to a parameter assignment of an instantiation)
6019 // perform the same examination recursively on the referenced type
6020 // (which is the actual parameter)
6021 return get_type_refd()->get_otaltname(is_strange
);
6025 // the type comes from an information object [class]
6026 // examine the referenced type recursively
6027 return get_type_refd()->get_otaltname(is_strange
);
6030 s
= get_stringRepr();
6031 // throw away the leading @ if this is an instantiated type
6032 // (e.g. an in-line SEQUENCE from a parameterized reference)
6033 if (!strncmp(s
.c_str(), "_root_", 6)) s
.replace(0, 6, "");
6034 // the name is strange if it contains a single underscore
6036 // transform "__" -> "-"
6037 for (size_t pos
= 0; ; ) {
6038 pos
= s2
.find("__", pos
);
6039 if (pos
< s2
.size()) {
6040 s2
.replace(pos
, 2, "-");
6044 is_strange
= s2
.find('_') < s2
.size();
6047 size_t pos=s.find_if(0, s.size(), isupper);
6048 if(pos==s.size()) FATAL_ERROR("Type::get_otaltname() (`%s')", s.c_str());
6049 s[pos]=tolower(s[pos]);
6052 Identifier
tmp_id(Identifier::ID_NAME
, s
, true);
6053 /* This is because the origin of the returned ID must be ASN. */
6054 return Identifier(Identifier::ID_ASN
, tmp_id
.get_asnname());
6057 string
Type::get_genname_value(Scope
*p_scope
)
6059 Type
*t
= get_type_refd_last();
6060 switch (t
->typetype
) {
6063 case T_UNRESTRICTEDSTRING
:
6066 case T_EMBEDDED_PDV
:
6070 FATAL_ERROR("Type::get_genname_value()");
6072 return string("ASN_NULL");
6074 return string("BOOLEAN");
6077 return string("INTEGER");
6079 return string("FLOAT");
6082 return string("BITSTRING");
6084 return string("HEXSTRING");
6086 return string("OCTETSTRING");
6088 case T_NUMERICSTRING
:
6089 case T_PRINTABLESTRING
:
6091 case T_VISIBLESTRING
:
6093 case T_GENERALIZEDTIME
:
6094 return string("CHARSTRING");
6095 case T_USTR
: // ttcn3 universal charstring
6097 case T_TELETEXSTRING
:
6098 case T_VIDEOTEXSTRING
:
6099 case T_GRAPHICSTRING
:
6100 case T_GENERALSTRING
:
6101 case T_UNIVERSALSTRING
:
6103 case T_OBJECTDESCRIPTOR
:
6104 return string("UNIVERSAL_CHARSTRING");
6107 return string("OBJID");
6109 return string("ASN_ANY");
6111 return string("VERDICTTYPE");
6113 return string("COMPONENT");
6115 return string("DEFAULT");
6117 if (!t
->u
.array
.in_typedef
)
6118 return t
->u
.array
.dimension
->get_value_type(t
->u
.array
.element_type
,
6122 return t
->get_genname_own(p_scope
);
6126 string
Type::get_genname_template(Scope
*p_scope
)
6128 Type
*t
= get_type_refd_last();
6130 switch (t
->typetype
) {
6133 // template classes do not exist for these types
6134 FATAL_ERROR("Type::get_genname_template()");
6136 // a template class has to be instantiated in case of arrays
6137 // outside type definitions
6138 if (!t
->u
.array
.in_typedef
) {
6139 ret_val
= t
->u
.array
.dimension
->get_template_type(
6140 t
->u
.array
.element_type
, p_scope
);
6145 // in case of other types the name of the template class is derived
6146 // from the value class by appending a suffix
6147 ret_val
= t
->get_genname_value(p_scope
);
6148 ret_val
+= "_template";
6154 string
Type::get_genname_altname()
6156 Type
*t_last
= get_type_refd_last();
6157 Scope
*t_scope
= t_last
->get_my_scope();
6158 switch (t_last
->typetype
) {
6161 case T_UNRESTRICTEDSTRING
:
6164 case T_EMBEDDED_PDV
:
6168 FATAL_ERROR("Type::get_genname_altname()");
6180 case T_ANYTYPE
: // FIXME this does not yet work
6188 // user-defined types
6189 // always use the qualified name (including module identifier)
6190 string
ret_val(t_scope
->get_scope_mod_gen()->get_modid().get_name());
6192 ret_val
+= t_last
->get_genname_own();
6196 // use the simple class name from the base library
6197 return t_last
->get_genname_value(t_scope
);
6201 string
Type::get_typename()
6203 Type
*t
= get_type_refd_last();
6204 const char* tn
= get_typename_builtin(t
->typetype
);
6205 if (tn
!= 0) return string(tn
);
6206 switch (t
->typetype
) {
6224 return t
->get_fullname();
6226 string
dimensions(t
->u
.array
.dimension
->get_stringRepr());
6227 t
= t
->u
.array
.element_type
;
6228 while (t
->typetype
== T_ARRAY
) {
6229 dimensions
+= t
->u
.array
.dimension
->get_stringRepr();
6230 t
= t
->u
.array
.element_type
;
6232 return t
->get_typename() + dimensions
; }
6234 FATAL_ERROR("Type::get_typename()");
6240 const char* Type::get_typename_builtin(typetype_t tt
)
6244 return "Erroneous type";
6260 return "octetstring";
6262 return "charstring";
6264 return "universal charstring";
6266 return "UTF8String";
6267 case T_NUMERICSTRING
:
6268 return "NumericString";
6269 case T_PRINTABLESTRING
:
6270 return "PrintableString";
6271 case T_TELETEXSTRING
:
6272 return "TeletexString";
6273 case T_VIDEOTEXSTRING
:
6274 return "VideotexString";
6277 case T_GRAPHICSTRING
:
6278 return "GraphicString";
6279 case T_VISIBLESTRING
:
6280 return "VisibleString";
6281 case T_GENERALSTRING
:
6282 return "GeneralString";
6283 case T_UNIVERSALSTRING
:
6284 return "UniversalString";
6289 case T_GENERALIZEDTIME
:
6290 return "GeneralizedTime";
6291 case T_OBJECTDESCRIPTOR
:
6292 return "ObjectDescriptor";
6299 return "verdicttype";
6304 case T_EMBEDDED_PDV
:
6305 return "EMBEDDED PDV";
6306 case T_UNRESTRICTEDSTRING
:
6307 return "CHARACTER STRING";
6317 string
Type::get_genname_typedescriptor(Scope
*p_scope
)
6321 /* If it has tags or encoding attributes, then its encoding may be
6322 * different from the other "equivalent" types and needs to have its own
6325 if (t
->is_tagged() || t
->rawattrib
|| t
->textattrib
|| t
->jsonattrib
||
6326 (t
->xerattrib
&& !t
->xerattrib
->empty() ))
6328 return t
->get_genname_own(p_scope
);
6330 else if (t
->is_ref()) {
6331 if (t
->has_encoding(CT_XER
)) {
6332 // just fetch the referenced type and return
6333 return t
->get_type_refd()->get_genname_own(p_scope
);
6336 { // follow the white rabbit
6337 t
= t
->get_type_refd();
6342 return t
->get_genname_typename(p_scope
);
6345 string
Type::get_genname_typename(Scope
*p_scope
)
6347 Type
*t
= get_type_refd_last();
6348 switch (t
->typetype
) {
6350 return string("UTF8String");
6351 case T_NUMERICSTRING
:
6352 return string("NumericString");
6353 case T_PRINTABLESTRING
:
6354 return string("PrintableString");
6355 case T_TELETEXSTRING
:
6356 return string("TeletexString");
6357 case T_VIDEOTEXSTRING
:
6358 return string("VideotexString");
6360 return string("IA5String");
6361 case T_GRAPHICSTRING
:
6362 return string("GraphicString");
6363 case T_VISIBLESTRING
:
6364 return string("VisibleString");
6365 case T_GENERALSTRING
:
6366 return string("GeneralString");
6367 case T_UNIVERSALSTRING
:
6368 return string("UniversalString");
6370 return string("BMPString");
6372 return string("ASN_UTCTime");
6373 case T_GENERALIZEDTIME
:
6374 return string("ASN_GeneralizedTime");
6375 case T_OBJECTDESCRIPTOR
:
6376 return string("ObjectDescriptor");
6378 return string("ASN_ROID");
6380 return t
->get_genname_value(p_scope
);
6384 string
Type::get_genname_berdescriptor()
6388 if (t
->is_tagged()) return t
->get_genname_own(my_scope
);
6389 else if (t
->is_ref()) t
= t
->get_type_refd();
6392 switch (t
->typetype
) {
6395 return string("ENUMERATED");
6399 return string("CHOICE");
6403 return string("SEQUENCE");
6407 return string("SET");
6409 return t
->get_genname_typename(my_scope
);
6413 string
Type::get_genname_rawdescriptor()
6417 if (t
->rawattrib
) return t
->get_genname_own(my_scope
);
6418 else if (t
->is_ref()) t
= t
->get_type_refd();
6421 return t
->get_genname_typename(my_scope
);
6424 string
Type::get_genname_textdescriptor()
6428 if (t
->textattrib
) return t
->get_genname_own(my_scope
);
6429 else if (t
->is_ref()) t
= t
->get_type_refd();
6432 return t
->get_genname_typename(my_scope
);
6435 string
Type::get_genname_xerdescriptor()
6437 if (T_REFDSPEC
== typetype
) {
6438 return get_genname_typedescriptor(my_scope
);
6440 else return genname
;
6443 string
Type::get_genname_jsondescriptor()
6447 if (t
->jsonattrib
) return t
->get_genname_own(my_scope
);
6448 else if (t
->is_ref()) t
= t
->get_type_refd();
6451 return t
->get_genname_typename(my_scope
);
6454 const char* Type::get_genname_typedescr_asnbasetype()
6456 switch (get_type_refd_last()->typetype
) {
6459 case T_UNIVERSALSTRING
:
6460 return "UNIVERSALSTRING";
6462 return "UTF8STRING";
6463 case T_TELETEXSTRING
:
6464 return "TELETEXSTRING";
6465 case T_VIDEOTEXSTRING
:
6466 return "VIDEOTEXSTRING";
6467 case T_OBJECTDESCRIPTOR
:
6468 case T_GRAPHICSTRING
:
6469 return "GRAPHICSTRING";
6470 case T_GENERALSTRING
:
6471 return "GENERALSTRING";
6481 void Type::dump(unsigned level
) const
6483 DEBUG(level
, "Type @ %p, '%s'", (const void*)this, get_fullname().c_str());
6486 DEBUG(level
, "Type: <erroneous>");
6489 DEBUG(level
, "Type: NULL");
6492 DEBUG(level
, "Type: boolean");
6495 DEBUG(level
, "Type: integer");
6498 DEBUG(level
, "Type: INTEGER");
6499 if(u
.namednums
.block
)
6500 DEBUG(level
, "with unparsed block");
6501 if(u
.namednums
.nvs
) {
6502 DEBUG(level
, "with named numbers (%lu pcs.)",
6503 (unsigned long) u
.namednums
.nvs
->get_nof_nvs());
6504 u
.namednums
.nvs
->dump(level
+1);
6508 DEBUG(level
, "Type: float/REAL");
6512 DEBUG(level
, "Type: enumerated");
6513 u
.enums
.eis
->dump(level
+1);
6516 DEBUG(level
, "Type: bitstring");
6519 DEBUG(level
, "Type: BIT STRING");
6520 if(u
.namednums
.block
)
6521 DEBUG(level
, "with unparsed block");
6522 if(u
.namednums
.nvs
) {
6523 DEBUG(level
, "with named numbers (%lu pcs.)",
6524 (unsigned long) u
.namednums
.nvs
->get_nof_nvs());
6525 u
.namednums
.nvs
->dump(level
+1);
6529 DEBUG(level
, "Type: hexstring");
6532 DEBUG(level
, "Type: octetstring");
6535 DEBUG(level
, "Type: charstring");
6538 DEBUG(level
, "Type: universal charstring");
6541 DEBUG(level
, "Type: UTF8String");
6543 case T_NUMERICSTRING
:
6544 DEBUG(level
, "Type: NumericString");
6546 case T_PRINTABLESTRING
:
6547 DEBUG(level
, "Type: PrintableString");
6549 case T_TELETEXSTRING
:
6550 DEBUG(level
, "Type: TeletexString");
6552 case T_VIDEOTEXSTRING
:
6553 DEBUG(level
, "Type: VideotexString");
6556 DEBUG(level
, "Type: IA5String");
6558 case T_GRAPHICSTRING
:
6559 DEBUG(level
, "Type: GraphicString");
6561 case T_VISIBLESTRING
:
6562 DEBUG(level
, "Type: VisibleString");
6564 case T_GENERALSTRING
:
6565 DEBUG(level
, "Type: GeneralString");
6567 case T_UNIVERSALSTRING
:
6568 DEBUG(level
, "Type: UniversalString");
6571 DEBUG(level
, "Type: BMPString");
6573 case T_UNRESTRICTEDSTRING
:
6574 DEBUG(level
, "Type: CHARACTER STRING");
6577 DEBUG(level
, "Type: UTCTime");
6579 case T_GENERALIZEDTIME
:
6580 DEBUG(level
, "Type: GeneralizedTime");
6582 case T_OBJECTDESCRIPTOR
:
6583 DEBUG(level
, "Type: OBJECT DESCRIPTOR");
6586 DEBUG(level
, "Type: objid/OBJECT IDENTIFIER");
6589 DEBUG(level
, "Type: RELATIVE-OID");
6592 DEBUG(level
, "Type: anytype!!!");
6593 u
.secho
.cfm
->dump(level
+1);
6596 DEBUG(level
, "Type: union");
6597 u
.secho
.cfm
->dump(level
+1);
6600 DEBUG(level
, "Type: CHOICE");
6602 DEBUG(level
, "with unparsed block");
6604 DEBUG(level
, "with alternatives (%lu pcs.)",
6605 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6606 u
.secho
.ctss
->dump(level
+1);
6610 DEBUG(level
, "Type: record of/SEQUENCE OF");
6611 DEBUG(level
+1, "of type:");
6612 u
.seof
.ofType
->dump(level
+2);
6615 DEBUG(level
, "Type: set of/SET OF");
6616 DEBUG(level
+1, "of type:");
6617 u
.seof
.ofType
->dump(level
+2);
6620 DEBUG(level
, "Type: record");
6621 u
.secho
.cfm
->dump(level
+1);
6624 DEBUG(level
, "Type: set");
6625 u
.secho
.cfm
->dump(level
+1);
6628 DEBUG(level
, "Type: SEQUENCE");
6630 DEBUG(level
, "with unparsed block");
6632 DEBUG(level
, "with components (%lu pcs.)",
6633 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6634 u
.secho
.ctss
->dump(level
+1);
6638 DEBUG(level
, "Type: SET");
6640 DEBUG(level
, "with unparsed block");
6642 DEBUG(level
, "with components (%lu pcs.)",
6643 (unsigned long) u
.secho
.ctss
->get_nof_comps());
6644 u
.secho
.ctss
->dump(level
+1);
6648 DEBUG(level
, "Type: ObjectClassFieldType (%s)",
6649 const_cast<Type
*>(this)->get_type_refd()->get_stringRepr().c_str());
6652 DEBUG(level
, "Type: opentype (mapped to CHOICE)");
6653 u
.secho
.cfm
->dump(level
+1);
6656 DEBUG(level
, "Type: ANY");
6659 DEBUG(level
, "Type: EXTERNAL");
6661 case T_EMBEDDED_PDV
:
6662 DEBUG(level
, "Type: EMBEDDED PDV");
6665 DEBUG(level
, "Type: reference");
6666 u
.ref
.ref
->dump(level
+1);
6667 if(u
.ref
.type_refd
&& u
.ref
.type_refd
->typetype
==T_OPENTYPE
)
6668 u
.ref
.type_refd
->dump(level
+1);
6671 DEBUG(level
, "Type: reference (spec) to %s:",
6672 u
.ref
.type_refd
->get_fullname().c_str());
6673 u
.ref
.type_refd
->dump(level
+ 1);
6676 DEBUG(level
, "Type: selection type");
6677 DEBUG(level
+1, "`%s' <", u
.seltype
.id
->get_dispname().c_str());
6678 u
.seltype
.type
->dump(level
+1);
6681 DEBUG(level
, "Type: verdicttype");
6684 DEBUG(level
, "Type: port");
6685 u
.port
->dump(level
+ 1);
6688 DEBUG(level
, "Type: component");
6689 u
.component
->dump(level
+ 1);
6692 DEBUG(level
, "Type: address");
6695 DEBUG(level
, "Type: default");
6698 DEBUG(level
, "Type: array");
6699 DEBUG(level
+ 1, "element type:");
6700 u
.array
.element_type
->dump(level
+ 2);
6701 DEBUG(level
+ 1, "dimension:");
6702 u
.array
.dimension
->dump(level
+ 2);
6705 DEBUG(level
, "Type: signature");
6706 if (u
.signature
.parameters
) {
6707 DEBUG(level
+1,"parameter(s):");
6708 u
.signature
.parameters
->dump(level
+2);
6710 if (u
.signature
.return_type
) {
6711 DEBUG(level
+1,"return type");
6712 u
.signature
.return_type
->dump(level
+2);
6714 if (u
.signature
.no_block
) DEBUG(level
+1,"no block");
6715 if (u
.signature
.exceptions
) {
6716 DEBUG(level
+1,"exception(s):");
6717 u
.signature
.exceptions
->dump(level
+2);
6721 DEBUG(level
, "Type: function");
6722 DEBUG(level
+1, "Parameters:");
6723 u
.fatref
.fp_list
->dump(level
+2);
6724 if (u
.fatref
.return_type
) {
6725 if (!u
.fatref
.returns_template
) {
6726 DEBUG(level
+1, "Return type:");
6728 if (u
.fatref
.template_restriction
==TR_OMIT
)
6729 DEBUG(level
+1, "Returns template of type:");
6731 DEBUG(level
+1, "Returns template(%s) of type:",
6732 Template::get_restriction_name(u
.fatref
.template_restriction
));
6734 u
.fatref
.return_type
->dump(level
+2);
6736 if(u
.fatref
.runs_on
.ref
) {
6737 DEBUG(level
+1, "Runs on clause:");
6738 u
.fatref
.runs_on
.ref
->dump(level
+2);
6740 if (u
.fatref
.runs_on
.self
) DEBUG(level
+1, "Runs on self");
6744 DEBUG(level
, "Type: altstep");
6745 DEBUG(level
+1, "Parameters:");
6746 u
.fatref
.fp_list
->dump(level
+2);
6747 if(u
.fatref
.runs_on
.ref
) {
6748 DEBUG(level
+1, "Runs on clause:");
6749 u
.fatref
.runs_on
.ref
->dump(level
+2);
6751 if (u
.fatref
.runs_on
.self
) DEBUG(level
+1, "Runs on self");
6755 DEBUG(level
, "Type: testcase");
6756 DEBUG(level
+1, "Parameters:");
6757 u
.fatref
.fp_list
->dump(level
+2);
6758 if(u
.fatref
.runs_on
.ref
) {
6759 DEBUG(level
+1, "Runs on clause:");
6760 u
.fatref
.runs_on
.ref
->dump(level
+2);
6762 if(u
.fatref
.system
.ref
) {
6763 DEBUG(level
+1, "System clause:");
6764 u
.fatref
.system
.ref
->dump(level
+2);
6768 DEBUG(level
, "type (%d - %s)", typetype
, const_cast<Type
*>(this)->get_stringRepr().c_str());
6770 DEBUG(level
, "ownertype %2d", ownertype
);
6771 if(sub_type
!=NULL
) {
6772 DEBUG(level
, "with subtype");
6773 sub_type
->dump(level
+1);
6776 DEBUG(level
, "with tags");
6777 tags
->dump(level
+1);
6780 if(w_attrib_path
&& w_attrib_path
->get_with_attr())
6782 DEBUG(level
, "Attributes");
6783 w_attrib_path
->dump(level
);
6784 //w_attrib_path->get_with_attr()->dump(level);
6788 xerattrib
->print(get_fullname().c_str());
6792 SubtypeConstraint::subtype_t
Type::get_subtype_type()
6794 Type
* t
= get_type_refd_last();
6795 switch (t
->get_typetype()) {
6798 return SubtypeConstraint::ST_INTEGER
;
6800 return SubtypeConstraint::ST_FLOAT
;
6802 return SubtypeConstraint::ST_BOOLEAN
;
6804 return SubtypeConstraint::ST_VERDICTTYPE
;
6807 return SubtypeConstraint::ST_OBJID
;
6810 return SubtypeConstraint::ST_BITSTRING
;
6812 return SubtypeConstraint::ST_HEXSTRING
;
6814 return SubtypeConstraint::ST_OCTETSTRING
;
6815 case T_TELETEXSTRING
:
6816 case T_VIDEOTEXSTRING
:
6817 case T_GRAPHICSTRING
:
6818 case T_GENERALSTRING
:
6819 case T_OBJECTDESCRIPTOR
:
6822 case T_NUMERICSTRING
:
6823 case T_PRINTABLESTRING
:
6825 case T_VISIBLESTRING
:
6827 case T_GENERALIZEDTIME
:
6828 return SubtypeConstraint::ST_CHARSTRING
;
6831 case T_UNIVERSALSTRING
:
6833 return SubtypeConstraint::ST_UNIVERSAL_CHARSTRING
;
6836 case T_NULL
: // FIXME: this should have it's own ST_NULL case
6837 return SubtypeConstraint::ST_ENUM
;
6840 case T_ANYTYPE
: // (titan's hacked anytype is a choice)
6842 return SubtypeConstraint::ST_UNION
;
6844 return SubtypeConstraint::ST_RECORDOF
;
6846 return SubtypeConstraint::ST_SETOF
;
6849 case T_EXTERNAL
: // associated ASN.1 type is a SEQUENCE
6850 case T_EMBEDDED_PDV
: // associated ASN.1 type is a SEQUENCE
6851 case T_UNRESTRICTEDSTRING
: // associated ASN.1 type is a SEQUENCE
6852 return SubtypeConstraint::ST_RECORD
;
6855 return SubtypeConstraint::ST_SET
;
6857 return SubtypeConstraint::ST_FUNCTION
;
6859 return SubtypeConstraint::ST_ALTSTEP
;
6861 return SubtypeConstraint::ST_TESTCASE
;
6863 return SubtypeConstraint::ST_ERROR
;
6867 void Type::set_parsed_restrictions(vector
<SubTypeParse
> *stp
)
6869 if(!parsed_restr
)parsed_restr
=stp
;
6870 else FATAL_ERROR("Type::set_parsed_restrictions(): restrictions "
6871 "are already set.");
6874 bool Type::is_component_internal()
6876 if (!checked
) chk();
6883 return u
.fatref
.runs_on
.self
;
6887 return u
.secho
.component_internal
;
6890 return u
.seof
.component_internal
;
6892 return u
.array
.component_internal
;
6894 return u
.signature
.component_internal
;
6897 return u
.ref
.component_internal
;
6903 void Type::chk_component_internal(map
<Type
*,void>& type_chain
,
6906 Type
* t_last
= get_type_refd_last();
6907 switch (t_last
->typetype
) {
6908 // types that cannot be sent
6910 error("Default type cannot be %s", p_what
);
6913 error("Port type `%s' cannot be %s", t_last
->get_typename().c_str(),
6917 if (t_last
->u
.fatref
.runs_on
.self
) {
6918 error("Function type `%s' with 'runs on self' clause cannot be %s",
6919 t_last
->get_typename().c_str(), p_what
);
6923 if (t_last
->u
.fatref
.runs_on
.self
) {
6924 error("Altstep type `%s' with 'runs on self' clause cannot be %s",
6925 t_last
->get_typename().c_str(), p_what
);
6928 // structured types that may contain types that cannot be sent
6936 if (type_chain
.has_key(t_last
)) break;
6937 type_chain
.add(t_last
, 0);
6938 Error_Context
cntxt(this, "In type `%s'", get_typename().c_str());
6939 switch (t_last
->typetype
) {
6943 size_t nof_comps
= t_last
->get_nof_comps();
6944 for (size_t i
=0; i
<nof_comps
; i
++) {
6945 Type
* t
= t_last
->get_comp_byIndex(i
)->get_type();
6946 if (t
->is_component_internal())
6947 t
->chk_component_internal(type_chain
, p_what
);
6952 if (t_last
->u
.seof
.ofType
->is_component_internal())
6953 t_last
->u
.seof
.ofType
->chk_component_internal(type_chain
, p_what
);
6956 if (t_last
->u
.array
.element_type
->is_component_internal())
6957 t_last
->u
.array
.element_type
->chk_component_internal(type_chain
,
6961 if (t_last
->u
.signature
.parameters
) {
6962 size_t nof_params
= t_last
->u
.signature
.parameters
->get_nof_params();
6963 for (size_t i
=0; i
<nof_params
; i
++) {
6964 Type
* t
= t_last
->u
.signature
.parameters
->
6965 get_param_byIndex(i
)->get_type();
6966 if (t
->is_component_internal())
6967 t
->chk_component_internal(type_chain
, p_what
);
6970 if (t_last
->u
.signature
.return_type
&&
6971 t_last
->u
.signature
.return_type
->is_component_internal()) {
6972 t_last
->u
.signature
.return_type
->chk_component_internal(type_chain
,
6975 if (t_last
->u
.signature
.exceptions
) {
6976 size_t nof_types
= t_last
->u
.signature
.exceptions
->get_nof_types();
6977 for (size_t i
=0; i
<nof_types
; i
++) {
6978 Type
* t
= t_last
->u
.signature
.exceptions
->get_type_byIndex(i
);
6979 if (t
->is_component_internal())
6980 t
->chk_component_internal(type_chain
, p_what
);
6985 FATAL_ERROR("Type::chk_component_internal()");
6987 type_chain
.erase(t_last
);
6989 default: //all other types are Ok.
6994 Type::typetype_t
Type::search_for_not_allowed_type(map
<Type
*,void>& type_chain
,
6995 map
<typetype_t
, void>& not_allowed
)
6997 if (!checked
) chk();
6998 Type
* t_last
= get_type_refd_last();
6999 Type::typetype_t ret
= t_last
->typetype
;
7001 if (not_allowed
.has_key(t_last
->typetype
)) {
7005 switch (t_last
->typetype
) {
7012 if (type_chain
.has_key(t_last
)) {
7015 type_chain
.add(t_last
, 0);
7016 switch (t_last
->typetype
) {
7020 size_t nof_comps
= t_last
->get_nof_comps();
7021 for (size_t i
= 0; i
< nof_comps
; ++i
) {
7022 Type
* t
= t_last
->get_comp_byIndex(i
)->get_type();
7023 ret
= t
->search_for_not_allowed_type(type_chain
, not_allowed
);
7024 if (not_allowed
.has_key(ret
)) {
7032 ret
= t_last
->get_ofType()->search_for_not_allowed_type(type_chain
, not_allowed
);
7033 if (not_allowed
.has_key(ret
)) {
7040 type_chain
.erase(t_last
);
7046 return t_last
->typetype
;
7049 string
Type::get_dispname() const
7051 string dispname
= genname
;
7053 while(pos
< dispname
.size()) {
7054 pos
= dispname
.find("__", pos
);
7055 if (pos
== dispname
.size()) {
7058 dispname
.replace(pos
, 1, "");
7064 bool Type::is_pregenerated()
7066 // records/sets of base types are already pre-generated, only a type alias will be generated
7067 // exception: record of universal charstring with the XER coding instruction "anyElement"
7068 if (!force_gen_seof
&& (T_SEQOF
== get_type_refd_last()->typetype
||
7069 T_SETOF
== get_type_refd_last()->typetype
) &&
7070 (NULL
== xerattrib
|| /* check for "anyElement" at the record of type */
7071 NamespaceRestriction::UNUSED
== xerattrib
->anyElement_
.type_
) &&
7072 (NULL
== u
.seof
.ofType
->xerattrib
|| /* check for "anyElement" at the element type */
7073 NamespaceRestriction::UNUSED
== u
.seof
.ofType
->xerattrib
->anyElement_
.type_
)) {
7074 switch(u
.seof
.ofType
->get_type_refd_last()->typetype
) {
7084 case T_NUMERICSTRING
:
7085 case T_PRINTABLESTRING
:
7087 case T_VISIBLESTRING
:
7088 case T_UNRESTRICTEDSTRING
:
7090 case T_GENERALIZEDTIME
:
7093 case T_TELETEXSTRING
:
7094 case T_VIDEOTEXSTRING
:
7095 case T_GRAPHICSTRING
:
7096 case T_GENERALSTRING
:
7097 case T_UNIVERSALSTRING
:
7099 case T_OBJECTDESCRIPTOR
:
7108 bool Type::has_as_value_union()
7110 if (jsonattrib
!= NULL
&& jsonattrib
->as_value
) {
7113 Type
* t
= get_type_refd_last();
7114 switch (t
->get_typetype_ttcn3()) {
7116 if (t
->jsonattrib
!= NULL
&& t
->jsonattrib
->as_value
) {
7119 // no break, check alternatives
7122 for (size_t i
= 0; i
< t
->get_nof_comps(); ++i
) {
7123 if (t
->get_comp_byIndex(i
)->get_type()->has_as_value_union()) {
7130 return t
->get_ofType()->has_as_value_union();
7136 } // namespace Common