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
9 Binary file (standard input) matches
11 ******************************************************************************/
12 #include "../common/dbgnew.hh"
14 #include "Typestuff.hh" // FIXME CTs
15 #include "CompField.hh"
16 #include "CompType.hh"
17 #include "TypeCompat.hh"
18 #include "EnumItem.hh"
19 #include "SigParam.hh"
21 #include "Valuestuff.hh"
24 #include "ttcn3/Ttcnstuff.hh"
25 #include "ttcn3/TtcnTemplate.hh"
26 #include "ttcn3/Templatestuff.hh"
27 #include "ttcn3/Attributes.hh"
28 #include "ttcn3/ArrayDimensions.hh"
29 #include "ttcn3/PatternString.hh"
31 #include "asn1/Tag.hh"
32 #include "XerAttributes.hh"
35 #include <stdlib.h> // for qsort
38 extern int rawAST_debug
;
42 using Ttcn::MultiWithAttrib
;
43 using Ttcn::SingleWithAttrib
;
44 using Ttcn::WithAttribPath
;
45 using Ttcn::Qualifier
;
46 using Ttcn::Qualifiers
;
50 if(w_attrib_path
) w_attrib_path
->chk_global_attrib();
70 case T_PRINTABLESTRING
:
72 case T_VIDEOTEXSTRING
:
77 case T_UNIVERSALSTRING
:
80 case T_GENERALIZEDTIME
:
81 case T_OBJECTDESCRIPTOR
:
87 case T_UNRESTRICTEDSTRING
:
107 // TODO maybe check for address type and add it automagically, then fall through
112 // If this sequence type has no attributes but one of its fields does,
113 // create an empty attribute structure.
114 if(!rawattrib
&& hasVariantAttrs() && hasNeedofRawAttrs())
115 rawattrib
= new RawAST
;
116 if(!textattrib
&& hasVariantAttrs() && hasNeedofTextAttrs())
117 textattrib
= new TextAST
;
118 if(!xerattrib
&& hasVariantAttrs() && hasNeedofXerAttrs())
119 xerattrib
= new XerAttributes
;
120 if (!jsonattrib
&& (hasVariantAttrs() || hasEncodeAttr(get_encoding_name(CT_JSON
)) || hasNeedofJsonAttrs())) {
121 jsonattrib
= new JsonAST
;
126 // TODO create an empty XerAttrib as above, when ASN.1 gets XER ?
127 // The code was originally for TTCN-only encodings.
132 // TODO create an empty XerAttrib as above, when ASN.1 gets XER ?
147 u
.ref
.type_refd
->chk();
148 u
.ref
.component_internal
= u
.ref
.type_refd
->is_component_internal();
155 if (w_attrib_path
) u
.port
->chk_attributes(w_attrib_path
);
169 FATAL_ERROR("Type::chk()");
173 switch (get_type_refd_last()->typetype
) {
177 // These types may have qualified attributes
179 case T_SEQOF
: case T_SETOF
:
182 w_attrib_path
->chk_no_qualif();
187 if(tags
) tags
->set_plicit(this);
190 Check all non-table subtype constraints. Table/relational constraints
192 TODO: non-relational table constraints shall not be ignored.
194 if (check_subtype
) check_subtype_constraints();
197 * Checking the constraints can be done only if the entire type
198 * (including the nested typedefs) is checked, because the
199 * component relation constraint has to 'look' into other
202 if (!parent_type
) chk_table_constraints();
204 if(rawattrib
|| is_root_basic()){
207 if(textattrib
|| is_root_basic()) {
211 if (jsonattrib
|| is_root_basic()) {
215 // We need to call chk_xer() always because it is collecting
216 // XER attributes from parent types.
222 void Type::parse_attributes()
224 if (raw_parsed
) return;
226 // The type has no attributes of its own; connect it to the nearest group
227 // or the module. This allows global attributes to propagate.
228 for (Type
*t
= this; t
&& w_attrib_path
== 0; t
= t
->parent_type
) {
229 switch (t
->ownertype
) {
231 Ttcn::Def_Type
*pwn
= static_cast<Ttcn::Def_Type
*>(t
->owner
);
232 Ttcn::Group
*nearest_group
= pwn
->get_parent_group();
234 w_attrib_path
= new WithAttribPath
;
235 if (nearest_group
) { // there is a group
236 w_attrib_path
->set_parent(nearest_group
->get_attrib_path());
238 else { // no group, use the module
239 Common::Module
*mymod
= t
->my_scope
->get_scope_mod();
240 // OT_TYPE_DEF is always from a TTCN-3 module
241 Ttcn::Module
*my_ttcn_module
= static_cast<Ttcn::Module
*>(mymod
);
242 w_attrib_path
->set_parent(my_ttcn_module
->get_attrib_path());
248 continue; // try the enclosing type
256 if ((hasVariantAttrs())
257 && (enable_text() || enable_raw() || enable_xer())) {
259 const char *fn
= get_fullname().c_str();
261 fprintf(stderr
, "parse_attributes for %s\n", fn
);
264 bool new_raw
=false; // a RawAST object was allocated here
265 bool new_text
=false; // a TextAST object was allocated here
266 bool new_xer
=false; // a XerAttribute object was allocated here
267 bool new_ber
=false; // a BerAST object was allocated here
268 bool new_json
= false; // a JsonAST object was allocated here
269 bool raw_found
=false; // a raw attribute was found by the parser
270 bool text_found
=false; // a text attribute was found by the parser
271 bool xer_found
=false; // a XER attribute was found by the parser
272 bool ber_found
=false; // a BER attribute was found by the parser
273 bool json_found
= false; // a JSON attribute was found by the parser
276 json_checked
= false;
278 bool override_ref
=false;
279 // Parse RAW attributes
282 ReferenceChain
refch(this, "While checking attributes");
285 // Get all the attributes that apply (from outer scopes too).
286 // Outer (generic) first, inner (specific) last.
287 const vector
<SingleWithAttrib
> & real_attribs
288 = w_attrib_path
->get_real_attrib();
290 // see if there's an encode with override
291 for(size_t i
= real_attribs
.size(); i
> 0 && !override_ref
; i
--)
293 if(real_attribs
[i
-1]->has_override()
294 && real_attribs
[i
-1]->get_attribKeyword()
295 != SingleWithAttrib::AT_ENCODE
)
299 if(!rawattrib
&& !override_ref
){
300 Type
*t
=get_type_refd_last(&refch
);
301 typetype_t basic_type
=t
->typetype
;
302 t
=this; // go back to the beginning
304 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd(&refch
);
305 rawattrib
=new RawAST(t
->rawattrib
,basic_type
==T_INT
);
306 if(!t
->rawattrib
&& basic_type
==T_REAL
) rawattrib
->fieldlength
=64;
309 if(!textattrib
&& !override_ref
){
312 while(!t
->textattrib
&& t
->is_ref()) t
=t
->get_type_refd(&refch
);
313 textattrib
=new TextAST(t
->textattrib
);
316 if (!jsonattrib
&& !override_ref
){
319 while (!t
->jsonattrib
&& t
->is_ref()) {
320 t
= t
->get_type_refd(&refch
);
322 jsonattrib
= new JsonAST(t
->jsonattrib
);
333 case T_CSTR
: // TTCN-3 charstring
335 /* The list of types supporting RAW encoding is described in the
336 * API guide, section 3.3; this batch of labels plus the next three
337 * accurately match the list.
339 * For TEXT, it's section 3.4; the list does not include real and
340 * bin/hex/octet strings
342 case T_USTR
: // TTCN-3 universal charstring, this is an addition for XER attributes
343 case T_VERDICT
: // TTCN-3 verdict, for XER
346 rawattrib
= new RawAST(typetype
==T_INT
);
347 if(typetype
==T_REAL
) rawattrib
->fieldlength
=64;
350 if(textattrib
==NULL
){textattrib
= new TextAST
; new_text
=true;}
351 if (xerattrib
==NULL
) {
352 xerattrib
= new XerAttributes
; new_xer
= true;
354 if (berattrib
==NULL
) {
355 berattrib
= new BerAST
;
359 if (NULL
== jsonattrib
) {
360 jsonattrib
= new JsonAST
;
366 vector
<SingleWithAttrib
> const &real_attribs
367 = w_attrib_path
->get_real_attrib();
368 // These are attributes without qualifiers.
370 size_t nof_elements
= real_attribs
.size();
371 for(size_t i
= 0; i
< nof_elements
; i
++)
373 SingleWithAttrib
*temp_single
= real_attribs
[i
];
374 if (temp_single
->get_attribKeyword() ==
375 SingleWithAttrib::AT_VARIANT
) { // only "variant" is parsed
376 parse_rawAST(rawattrib
, textattrib
, xerattrib
, berattrib
, jsonattrib
,
377 temp_single
->get_attribSpec(), get_length_multiplier(),
378 my_scope
->get_scope_mod(),
379 raw_found
, text_found
, xer_found
, ber_found
, json_found
);
380 // textattrib->print_TextAST();
381 // rawattrib->print_RawAST();
382 // xerattrib->print(get_fullname().c_str());
387 if(!raw_found
&& new_raw
){ delete rawattrib
; rawattrib
=NULL
;}
388 if(!text_found
&& new_text
){ delete textattrib
; textattrib
=NULL
;}
389 if(!xer_found
&& new_xer
){ delete xerattrib
; xerattrib
= NULL
; }
390 if(!ber_found
&& new_ber
){ delete berattrib
; berattrib
= NULL
; }
391 if (!json_found
&& new_json
) {
403 if(rawattrib
==NULL
) {rawattrib
= new RawAST
; new_raw
=true;}
404 if(textattrib
==NULL
){textattrib
= new TextAST
; new_text
=true;}
405 if(xerattrib
==NULL
) {xerattrib
= new XerAttributes
; new_xer
= true;}
406 if(berattrib
==NULL
) {berattrib
= new BerAST
; new_ber
= true;}
407 if (NULL
== jsonattrib
) {
408 jsonattrib
= new JsonAST
;
414 vector
<SingleWithAttrib
> const &real_attribs
415 = w_attrib_path
->get_real_attrib();
417 //calculate the type's attributes (the qualifierless ones)
418 size_t nof_elements
= real_attribs
.size();
419 for(size_t i
= 0; i
< nof_elements
; i
++)
421 SingleWithAttrib
*temp_single
= real_attribs
[i
];
422 if(temp_single
->get_attribKeyword() == SingleWithAttrib::AT_VARIANT
423 && (!temp_single
->get_attribQualifiers()
424 || temp_single
->get_attribQualifiers()->get_nof_qualifiers()
426 // raw/text/xer/ber/json attributes for the whole record/seq.
427 // (own or inherited)
428 parse_rawAST(rawattrib
, textattrib
, xerattrib
, berattrib
, jsonattrib
,
429 temp_single
->get_attribSpec(), get_length_multiplier(),
430 my_scope
->get_scope_mod(),
431 raw_found
, text_found
, xer_found
, ber_found
, json_found
);
434 //calculate the components attributes
435 MultiWithAttrib
* self_attribs
= w_attrib_path
->get_with_attr();
438 MultiWithAttrib
* new_self_attribs
= new MultiWithAttrib
;
439 SingleWithAttrib
* swa
= 0;
441 // copy all the "encode" attributes
442 for(size_t i
= 0; i
< self_attribs
->get_nof_elements(); i
++)
444 if(self_attribs
->get_element(i
)->get_attribKeyword()
445 == SingleWithAttrib::AT_ENCODE
)
447 // Copy the attribute without qualifiers
448 const SingleWithAttrib
* swaref
= self_attribs
->get_element(i
);
449 swa
= new SingleWithAttrib(swaref
->get_attribKeyword(),
450 swaref
->has_override(), 0, swaref
->get_attribSpec().clone());
451 new_self_attribs
->add_element(swa
);
455 if(new_self_attribs
->get_nof_elements() > 0)
456 { // One or more "encode"s were copied; create a context for them.
457 // This is a member because is has to be owned by this Type
458 // (the components only refer to it).
459 encode_attrib_path
= new WithAttribPath
;
460 encode_attrib_path
->set_with_attr(new_self_attribs
);
461 encode_attrib_path
->set_parent(w_attrib_path
->get_parent());
463 else delete new_self_attribs
;
465 // This should be bool, but gcc 4.1.2-sol8 generates incorrect code
467 const int se_of
= (typetype
== T_SEQOF
|| typetype
== T_SETOF
||
468 typetype
== T_ARRAY
);
469 const size_t nof_comps
= se_of
? 1 : get_nof_comps();
471 // Distribute the attributes with qualifiers to the components.
472 // If the type is a sequence-of or set-of, we pretend it to have
473 // one component with the name "_0" (a valid TTCN-3 identifier
474 // can't begin with an underscore). compiler.y has created
475 // the appropriate identifier in the qualifier for a "[-]".
476 for(size_t i
= 0; i
< nof_comps
; i
++)
478 const Identifier
& comp_id
=
479 se_of
? underscore_zero
: get_comp_id_byIndex(i
);
480 MultiWithAttrib
* component_attribs
= new MultiWithAttrib
;
482 for(size_t j
= 0; j
< self_attribs
->get_nof_elements(); j
++)
484 const SingleWithAttrib
*temp_single
=
485 self_attribs
->get_element(j
);
486 Qualifiers
* temp_qualifiers
=
487 temp_single
->get_attribQualifiers();
489 || temp_qualifiers
->get_nof_qualifiers() == 0) continue;
491 Qualifiers
* calculated_qualifiers
= new Qualifiers
;
492 bool qualifier_added
= false;
493 for(size_t k
=0; k
< temp_qualifiers
->get_nof_qualifiers(); )
495 const Qualifier
* temp_qualifier
=
496 temp_qualifiers
->get_qualifier(k
);
497 if(temp_qualifier
->get_nof_identifiers() > 0
498 && (*temp_qualifier
->get_identifier(0) == comp_id
))
500 // Found a qualifier whose first identifier matches
501 // the component name. Remove the qualifier from the
502 // enclosing type, chop off its head,
503 // and add it to the component's qualifiers.
504 calculated_qualifiers
->add_qualifier(
505 temp_qualifier
->get_qualifier_without_first_id());
506 temp_qualifiers
->delete_qualifier(k
);
507 qualifier_added
= true;
514 // A copy of temp_single, with new qualifiers
515 SingleWithAttrib
* temp_single2
516 = new SingleWithAttrib(temp_single
->get_attribKeyword(),
517 temp_single
->has_override(),
518 calculated_qualifiers
,
519 temp_single
->get_attribSpec().clone());
520 temp_single2
->set_location(*temp_single
);
521 component_attribs
->add_element(temp_single2
);
523 else delete calculated_qualifiers
;
526 if (component_attribs
->get_nof_elements() > 0) {
527 Type
* component_type
= se_of
?
528 get_ofType() : get_comp_byIndex(i
)->get_type();
530 if(encode_attrib_path
)
531 // The record's "encode" attributes (only) apply to the fields.
532 // Interpose them in the path of the field.
533 component_type
->set_parent_path(encode_attrib_path
);
535 component_type
->set_parent_path(w_attrib_path
->get_parent());
537 component_type
->set_with_attr(component_attribs
);
539 else delete component_attribs
;
540 } // next component index
542 // Any remaining attributes with qualifiers are erroneous
543 for(size_t i
= 0; i
< self_attribs
->get_nof_elements();)
545 Qualifiers
*temp_qualifiers
= self_attribs
->get_element(i
)
546 ->get_attribQualifiers();
547 if(temp_qualifiers
&& temp_qualifiers
->get_nof_qualifiers() != 0)
549 size_t nof_qualifiers
= temp_qualifiers
->get_nof_qualifiers();
550 for(size_t j
= 0; j
< nof_qualifiers
; j
++)
552 const Qualifier
*temp_qualifier
=
553 temp_qualifiers
->get_qualifier(j
);
554 const Identifier
& tmp_id
= *temp_qualifier
->get_identifier(0);
555 // Special case when trying to reference the inner type
556 // of a record-of when it wasn't a record-of.
557 if (tmp_id
== underscore_zero
) temp_qualifier
->error(
558 "Invalid field qualifier [-]");
559 else temp_qualifier
->error("Invalid field qualifier %s",
560 tmp_id
.get_dispname().c_str());
562 self_attribs
->delete_element(i
);
567 } // end if(self_attribs)
568 } // end if(w_attrib_path)
569 if (!raw_found
&& new_raw
) { delete rawattrib
; rawattrib
= NULL
; }
570 if (!text_found
&& new_text
){ delete textattrib
; textattrib
= NULL
; }
571 if (!xer_found
&& new_xer
) { delete xerattrib
; xerattrib
= NULL
; }
572 if (!ber_found
&& new_ber
) { delete berattrib
; berattrib
= NULL
; }
573 if (!json_found
&& new_json
) {
579 // nothing to do, ASN1 types or types without defined raw attribute
582 if (rawattrib
&& !enable_raw()) { delete rawattrib
; rawattrib
= NULL
;}
583 if (textattrib
&& !enable_text()){ delete textattrib
; textattrib
= NULL
;}
584 if (xerattrib
&& !enable_xer()) { delete xerattrib
; xerattrib
= NULL
;}
585 if (berattrib
&& !enable_ber()) { delete berattrib
; berattrib
= NULL
;}
586 if (NULL
!= jsonattrib
&& !enable_json()) {
590 } // endif( hasVariantAttrs && enable_{raw,text,xer} )
595 // Implements "NAME AS ..." transformations.
596 void change_name(string
&name
, XerAttributes::NameChange change
) {
597 switch (change
.kw_
) {
598 case NamespaceSpecification::NO_MANGLING
:
599 break; // cool, nothing to do!
601 case NamespaceSpecification::UPPERCASED
:
602 // Walking backwards calls size() only once. Loop var must be signed.
603 for (int i
= name
.size()-1; i
>= 0; --i
) {
604 name
[i
] = toupper(name
[i
]);
608 case NamespaceSpecification::LOWERCASED
:
609 for (int i
= name
.size()-1; i
>= 0; --i
) {
610 name
[i
] = tolower(name
[i
]);
614 case NamespaceSpecification::CAPITALIZED
:
615 name
[0] = toupper(name
[0]);
618 case NamespaceSpecification::UNCAPITALIZED
:
619 name
[0] = tolower(name
[0]);
622 default: // explicitly specified name
628 void Type::chk_xer_any_attributes()
630 Type
* const last
= get_type_refd_last();
631 switch (last
->typetype
== T_SEQOF
?
632 last
->u
.seof
.ofType
->get_type_refd_last()->typetype
: 0) {
633 case T_UTF8STRING
: // SEQUENCE OF UTF8String, ASN.1
634 case T_USTR
: // record of universal charstring
638 error("ANY-ATTRIBUTES can only be applied to record of string");
642 switch (parent_type
!= NULL
? parent_type
->typetype
: 0) {
643 case T_SEQ_A
: case T_SET_A
:
644 case T_SEQ_T
: case T_SET_T
:
645 for (size_t x
= 0; x
< parent_type
->get_nof_comps(); ++x
) {
646 CompField
* cf
= parent_type
->get_comp_byIndex(x
);
647 if (cf
->get_type() != this) continue;
648 if (cf
->has_default()) {
649 error("The field with ANY-ATTRIBUTES cannot have DEFAULT");
654 error("ANY-ATTRIBUTES can only be applied to a member of "
655 "SEQUENCE, SET, record or set");
659 if (xerattrib
->untagged_
660 || (parent_type
&& parent_type
->xerattrib
&& parent_type
->xerattrib
->untagged_
)) {
661 error("Neither the type with ANY-ATTRIBUTES, nor its enclosing type "
662 "may be marked UNTAGGED");
666 void Type::chk_xer_any_element()
668 Type
*const last
= get_type_refd_last();
669 switch (last
->typetype
) {
670 case T_UTF8STRING
: // UTF8String, ASN.1
671 case T_USTR
: // universal charstring
674 /* A special case for TTCN-3 where applying ANY-ELEMENT to the record-of
675 * has the same effect as applying it to the string member.
676 * This should no longer be necessary now that we can refer
677 * to the embedded type of a record-of with [-], but it has to stay
678 * unless the standard deprecates it. */
679 Type
*oftype
= last
->u
.seof
.ofType
;
680 if (oftype
->xerattrib
== 0) oftype
->xerattrib
= new XerAttributes
;
681 // Transfer the ANY-ATTRIBUTE from the record-of to its member type
682 oftype
->xerattrib
->anyElement_
= xerattrib
->anyElement_
;
683 xerattrib
->anyElement_
.nElements_
= 0;
684 xerattrib
->anyElement_
.uris_
= 0;
685 // Re-check the member type since we fiddled with it
686 const char * type_name
= "record of";
687 Error_Context
cntxt(this, "In embedded type of %s", type_name
);
688 oftype
->xer_checked
= false;
692 error("ANY-ELEMENT can only be applied to UTF8String "
693 "or universal charstring type");
697 if (xerattrib
->attribute_
|| xerattrib
->base64_
|| xerattrib
->untagged_
698 || xerattrib
->defaultForEmpty_
!= NULL
699 || xerattrib
->whitespace_
!= XerAttributes::PRESERVE
) {
700 error("A type with ANY-ELEMENT may not have any of the following encoding instructions: "
701 "ATTRIBUTE, BASE64, DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED or WHITESPACE");
705 void Type::chk_xer_attribute()
707 if (xerattrib
->element_
) {
708 error("ELEMENT and ATTRIBUTE are incompatible");
711 switch (parent_type
!=NULL
? parent_type
->typetype
:-0) {
712 case 0: // no parent accepted in case a field of this type is declared
713 case T_SEQ_A
: case T_SEQ_T
:
714 case T_SET_A
: case T_SET_T
:
717 error("A type with ATTRIBUTE must be a member of "
718 "SEQUENCE, SET, record or set");
722 if (xerattrib
->untagged_
723 || (parent_type
&& parent_type
->xerattrib
&& parent_type
->xerattrib
->untagged_
)) {
724 error("Neither the type with ATTRIBUTE, nor its enclosing type "
725 "may be marked UNTAGGED");
728 if (has_ae(xerattrib
)) {
729 // TODO: || (xerattrib->defaultForEmpty_ && it is an ASN.1 type)
730 // DEFAULT-FOR-EMPTY is allowed only for TTCN-3
731 error("A type with ATTRIBUTE shall not also have any of the final "
732 "encoding instructions ANY-ELEMENT" /*", DEFAULT-FOR-EMPTY"*/ " or PI-OR-COMMENT");
738 /// Pointer to the field
740 /// The type of the field
742 /// The ultimate type, top->get_type_refd_last()
744 /// The typetype of last, on which we sort. Its name is meant to be
745 /// mnemonic (it belongs to \c last, not \c top)
746 Type::typetype_t lastt
;
749 /// Comparison function for CFCache based on typetype
750 int tcomp(const void *l
, const void *r
)
752 int retval
= ((const CFCache
*)l
)->lastt
- ((const CFCache
*)r
)->lastt
;
756 /** Find the original component name if it was changed by TEXT
758 * If there is a TEXT whose \a new_text matches \p text, return
759 * the corresponding \a target.
761 * If there are no TEXT coding instructions, always returns \p text.
763 * @param[in,out] text on input, a name possibly modified by any TEXT encoding
764 * instruction; on output, the actual component name
766 void Type::target_of_text(string
& text
)
768 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
769 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
771 if ((unsigned long)txt
.prefix
== 0
772 ||(unsigned long)txt
.prefix
== NamespaceSpecification::ALL
) {
773 FATAL_ERROR("Type::target_of_text()");
777 string
target(txt
.target
);
779 switch ((unsigned long)txt
.new_text
) {
780 case NamespaceSpecification::CAPITALIZED
: // tARGET -> TARGET
781 target
[0] = toupper(target
[0]);
783 case NamespaceSpecification::UNCAPITALIZED
:
784 target
[0] = tolower(target
[0]); // TARGET -> tARGET
786 case NamespaceSpecification::UPPERCASED
:
787 for (int si
= target
.size() - 1; si
>= 0; --si
) {
788 target
[si
] = toupper(target
[si
]);
791 case NamespaceSpecification::LOWERCASED
:
792 for (int si
= target
.size() - 1; si
>= 0; --si
) {
793 target
[si
] = tolower(target
[si
]);
797 case 0: // "text" not possible
798 FATAL_ERROR("Type::target_of_text() Text with no target and DFE");
801 default: // it's a string, "text 'field' as 'string'"
806 if (target
== text
) {
807 text
= txt
.target
; // we want the value before the change
813 // The suffix of the name of the variable which contains the D-F-E value.
814 static const string
dfe_suffix("_dfe");
816 /** Construct a Value to represent defaultForEmpty
818 * @param last pointer to a Type which is the end of the reference chain,
819 * usually this->get_type_refd_last()
820 * @param dfe_str string containing the value from defaultForEmpty
821 * @return a newly allocated Common::Value
823 Value
*Type::new_value_for_dfe(Type
*last
, const char *dfe_str
)
825 string
defaultstring(dfe_str
);
826 switch (last
->typetype
) {
830 return new Value(Common::Value::V_CSTR
,
831 new string(defaultstring
));
835 return new Value(Common::Value::V_INT
,
836 new int_val_t(dfe_str
, *this));
839 const Real
& rval
= string2Real(dfe_str
, *this);
840 return new Value(Value::V_REAL
, rval
);
844 if (!strcmp(dfe_str
, "true")
845 ||!strcmp(dfe_str
, "1")) {
846 return new Value(Value::V_BOOL
, true);
848 else if (!strcmp(dfe_str
, "false")
849 || !strcmp(dfe_str
, "0")) {
850 return new Value(Value::V_BOOL
, false);
852 else error("Invalid boolean default value");
856 case T_ENUM_A
: case T_ENUM_T
: {
857 // If there is a TEXT, the DFE value corresponds to TextToBeUsed.
858 // Fetch the "real" name of the field (Target).
860 target_of_text(defaultstring
);
862 Identifier
*val_id
= new Identifier(Common::Identifier::ID_TTCN
, // FIXME when ASN1 is supported
865 if (!last
->has_ei_withName(*val_id
)) {
866 error("No enumeration item item '%s'", defaultstring
.c_str());
868 for (size_t ee
=0; ee
< last
->u
.enums
.eis
->get_nof_eis(); ++ee
) {
869 note("Maybe %s", last
->u
.enums
.eis
->get_ei_byIndex(ee
)->get_name().get_name().c_str());
874 return new Value(Common::Value::V_ENUM
, val_id
);
877 case T_CHOICE_A
: case T_CHOICE_T
: {
878 // Try to guess which alternative the given DFE text belongs to.
879 // Sort the fields based on typetype, so BOOL, INT, REAL, ENUM
880 // are tried before the various string types
881 // (any string looks 'right' for a string value).
882 size_t num_comps
= last
->get_nof_comps();
883 CFCache
*sorted
= new CFCache
[num_comps
];
884 for (size_t c
= 0; c
< num_comps
; c
++) {
885 CompField
*cf
= last
->get_comp_byIndex(c
);
886 Type
*cft
= cf
->get_type();
887 Type
*cftlast
= cft
->get_type_refd_last();
890 sorted
[c
].last
= cftlast
;
891 sorted
[c
].lastt
= cftlast
->typetype
;
893 qsort(sorted
, num_comps
, sizeof(CFCache
), tcomp
);
897 for (c
= 0; c
< num_comps
&& retval
== 0; c
++) {
898 CFCache
¤t
= sorted
[c
];
899 // We can't just call new_value_for_dfe(), because some alternatives
900 // would generate errors even if a later type could accept the value.
901 switch (current
.lastt
) {
903 if (!strcmp(dfe_str
, "true")
904 ||!strcmp(dfe_str
, "1")) {
905 retval
= new Value(Value::V_BOOL
, true);
907 else if (!strcmp(dfe_str
, "false")
908 || !strcmp(dfe_str
, "0")) {
909 retval
= new Value(Value::V_BOOL
, false);
913 case T_INT
: case T_INT_A
: {
914 const char *start
= dfe_str
, *end
;
915 while (isspace((const unsigned char)*start
)) ++start
;
916 if (*start
== '+') ++start
;
917 int ndigits
= BN_dec2bn(NULL
, start
); // includes any '-' sign
918 end
= start
+ ndigits
;
919 // Pretend that all trailing whitespace characters were digits
920 while (isspace(*end
)) ++ndigits
, ++end
;
922 // Check that all the string was used up in the conversion,
923 // otherwise "3.1415" and "1e6" would appear as integers.
924 if (defaultstring
.size() == (size_t)ndigits
+ (start
- dfe_str
)) {
925 retval
= current
.top
->new_value_for_dfe(current
.last
, start
);
932 int num_converted
= sscanf(dfe_str
, "%f %1s", &f
, tail
);
933 // If tail was converted (num_converted>1) that's an error
934 if (num_converted
== 1) { // sscanf was happy
935 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
939 case T_ENUM_A
: case T_ENUM_T
: {
940 current
.top
->target_of_text(defaultstring
);
941 Identifier
alt(Identifier::ID_TTCN
, defaultstring
);
942 if (current
.last
->has_ei_withName(alt
)) {
943 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
950 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
960 retval
->set_genname(sorted
[c
].top
->genname
, dfe_suffix
);
961 retval
->set_my_scope(sorted
[c
].top
->my_scope
);
962 retval
->set_my_governor(sorted
[c
].top
);
963 Value
*choice_retval
= new Value(Value::V_CHOICE
,
964 new Identifier(sorted
[c
].cf
->get_name()), retval
);
965 retval
= choice_retval
;
971 /* Useless without a properly constructed Value(V_SEQ)
972 case T_SEQ_A: case T_SEQ_T: {
973 NamedValues *nvs = new NamedValues;
974 //NamedValue *nv = new NamedValue(new Identifier, new Value);
976 xerattrib->defaultValue_ = new Value(Value::V_SEQ, nvs);
980 default: // complain later
986 void Type::chk_xer_dfe()
988 Type
* const last
= get_type_refd_last();
990 if (/* TODO xerattrib->attribute_ is error for ASN.1 only */
991 xerattrib
->untagged_
|| has_ae(xerattrib
)) {
992 error("A type with DEFAULT-FOR-EMPTY shall not have any of the final "
993 "encoding instructions ANY-ELEMENT, ATTRIBUTE, UNTAGGED."); // 23.2.8
996 if (is_charenc() == Yes
) {
997 xerattrib
->defaultValue_
= new_value_for_dfe(last
, xerattrib
->defaultForEmpty_
);
999 if (xerattrib
->defaultValue_
!= 0) {
1000 xerattrib
->defaultValue_
->set_genname(this->genname
, dfe_suffix
);
1001 xerattrib
->defaultValue_
->set_my_scope(this->my_scope
);
1002 xerattrib
->defaultValue_
->set_my_governor(last
);
1005 error("DEFAULT-FOR-EMPTY not supported for character-encodable type %s",
1006 last
->get_stringRepr().c_str());
1009 else if (last
->typetype
== T_SEQ_A
|| last
->typetype
== T_SEQ_T
) {
1010 // If DEFAULT-FOR-EMPTY applies to a record (SEQUENCE), then only one
1011 // component can produce element content, and it should be the last,
1012 // because all the others should have ATTRIBUTE or ANY-ATTRIBUTE,
1013 // and those are moved to the front. 23.2.2 b)
1014 // FIXME only b) appears to have this restriction, not c)d)e)
1015 const size_t num_cf
= last
->get_nof_comps();
1017 CompField
*cf
= last
->get_comp_byIndex(num_cf
-1); // last field
1018 Type
*cft
= cf
->get_type(); // cft: CompField type
1019 cft
= cft
->get_type_refd_last();
1020 //typetype_t cftt = cft->get_typetype();
1022 xerattrib
->defaultValue_
= new_value_for_dfe(cft
, xerattrib
->defaultForEmpty_
);
1023 if (xerattrib
->defaultValue_
!= 0) {
1024 xerattrib
->defaultValue_
->set_genname(last
->genname
, string("_dfe"));
1025 xerattrib
->defaultValue_
->set_my_scope(cft
->my_scope
);
1026 xerattrib
->defaultValue_
->set_my_governor(cft
);
1029 error("DEFAULT-FOR-EMPTY not supported for fields of type %s",
1030 cft
->get_stringRepr().c_str());
1035 error("DEFAULT-FOR-EMPTY not applicable to type");
1039 void Type::chk_xer_embed_values(int num_attributes
)
1041 Type
* const last
= get_type_refd_last();
1043 enum complaint_type
{ ALL_GOOD
, HAVE_DEFAULT
, UNTAGGED_EMBEDVAL
,
1044 NOT_SEQUENCE
, EMPTY_SEQUENCE
, FIRST_NOT_SEQOF
, SEQOF_NOT_STRING
,
1045 SEQOF_BAD_LENGTH
, UNTAGGED_OTHER
} ;
1046 complaint_type complaint
= ALL_GOOD
;
1047 size_t expected_length
= (size_t)-1;
1048 Type
*cf0t
= 0; // type of first component
1050 switch (last
->typetype
) {
1051 case T_SEQ_A
: case T_SEQ_T
: { // 25.2.1, the type must be a sequence
1052 const size_t num_cf
= last
->get_nof_comps();
1054 complaint
= EMPTY_SEQUENCE
; // must have a "first component"
1057 CompField
*cf0
= last
->get_comp_byIndex(0);
1058 cf0t
= cf0
->get_type()->get_type_refd_last();
1059 if (cf0
->has_default()) {
1060 complaint
= HAVE_DEFAULT
;
1061 break; // 25.2.1 first component cannot have default
1064 switch (cf0t
->get_typetype()) { // check the first component
1066 Type
*cfot
= cf0t
->get_ofType(); // embedded type
1067 switch (cfot
->get_type_refd_last()->get_typetype()) {
1069 case T_USTR
: { // hooray, a SEQUENCE OF some string
1070 if ( (cf0t
->xerattrib
&& cf0t
->xerattrib
->untagged_
)
1071 || (cfot
->xerattrib
&& cfot
->xerattrib
->untagged_
)) {
1072 complaint
= UNTAGGED_EMBEDVAL
; // 25.2.2
1076 // Check length restriction on the record of. If there is one,
1077 // it better be the correct number.
1078 // FIXME: if there is also a USE-NIL, it cannot have a length restriction; only check at runtime
1079 const SubType
*sub
= cf0t
->sub_type
;
1080 const Int len
= sub
? sub
->get_length_restriction() :-1;
1081 // get_length_restriction() itself may return -1
1082 expected_length
= num_cf
-num_attributes
-xerattrib
->useOrder_
;
1083 if (len
> 0 && (size_t)len
!= expected_length
) {
1084 // The +1 from 25.2.6 b) is compensated because
1085 // the EMBED-VALUES member itself is ignored.
1086 complaint
= SEQOF_BAD_LENGTH
;
1089 break; } //acceptable
1092 complaint
= SEQOF_NOT_STRING
;
1098 complaint
= FIRST_NOT_SEQOF
;
1100 } // switch(type of first component)
1102 for (size_t c
= 1; c
< num_cf
; ++c
) { // check the other components
1103 cf
= last
->get_comp_byIndex(c
);
1104 Type
*cft
= cf
->get_type()->get_type_refd_last();
1105 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
&& (cft
->is_charenc() == Yes
)){
1106 complaint
= UNTAGGED_OTHER
;
1110 break; } // case T_SEQ*
1113 complaint
= NOT_SEQUENCE
;
1115 } // switch typetype
1117 // TODO 25.2.4, 25.2.5
1118 if (complaint
== ALL_GOOD
) embed_values_possible
= true;
1119 else if (xerattrib
->embedValues_
) {
1120 switch (complaint
) {
1121 case ALL_GOOD
: // Not possible; present in the switch so GCC checks
1122 // that all enum values are handled (make sure there's no default).
1125 case EMPTY_SEQUENCE
:
1126 case FIRST_NOT_SEQOF
:
1127 case SEQOF_NOT_STRING
:
1129 error("A type with EMBED-VALUES must be a sequence type. "
1130 "The first component of the sequence shall be SEQUENCE OF UTF8String "
1131 "and shall not be marked DEFAULT");
1133 case SEQOF_BAD_LENGTH
:
1134 cf0t
->error("Wrong length of SEQUENCE-OF for EMBED-VALUES, should be %lu",
1135 (unsigned long)expected_length
);
1137 case UNTAGGED_EMBEDVAL
:
1138 error("Neither the SEQUENCE-OF supporting EMBED-VALUES,"
1139 "nor its component shall have UNTAGGED."); // 25.2.2
1141 case UNTAGGED_OTHER
:
1142 cf
->error("There shall be no UNTAGGED on any character-encodable "
1143 "component of a type with DEFAULT-FOR-EMPTY"); // 25.2.3
1145 } // switch(complaint)
1146 } // if complaint and embedValues
1148 /** Wraps a C string but compares by contents, not by pointer */
1152 explicit stringval(const char *s
= 0) : str(s
) {}
1154 bool operator<(const stringval
& right
) const {
1155 if ( str
> (const char*)NamespaceSpecification::ALL
1156 && right
.str
> (const char*)NamespaceSpecification::ALL
)
1158 return strcmp(str
, right
.str
) < 0;
1160 else return str
< right
.str
;
1162 bool operator==(const stringval
& right
) const {
1163 if ( str
> (const char*)NamespaceSpecification::ALL
1164 && right
.str
> (const char*)NamespaceSpecification::ALL
)
1166 return strcmp(str
, right
.str
) == 0;
1168 else return str
== right
.str
;
1170 //bool operator!() const { return str==0; }
1171 const char *c_str() const { return str
; }
1175 void Type::chk_xer_text()
1177 if (xerattrib
->num_text_
== 0
1178 ||xerattrib
->text_
== 0 ) FATAL_ERROR("Type::chk_xer_text()");
1179 Type
* const last
= get_type_refd_last();
1180 static const stringval empty
; // NULL pointer
1182 // Check the type and quit early if wrong
1183 switch (last
->typetype
) {
1186 case T_ENUM_A
: // not yet
1187 error("No XER yet for ASN.1 enumerations");
1191 case T_BSTR_A
: // ASN.1 bit string with named bits, not yet
1192 error("No XER yet for ASN.1 bit strings");
1194 case T_INT_A
: // ASN.1 integer with named numbers, not yet
1195 error("No XER yet for ASN.1 named numbers");
1198 error("TEXT not allowed for type %s", get_typename().c_str());
1202 // Build a map to eliminate duplicates (new assignment to the same
1203 // enum item/field overwrites previous text).
1204 // Keys are the identifiers, values are the texts.
1205 typedef map
<stringval
, char> text_map_t
;
1206 text_map_t text_map
;
1208 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1209 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
1210 switch ((unsigned long)txt
.target
) {
1211 case 0: { // just "TEXT".
1212 // target=0 and new_text!=0 would have to come from "TEXT AS ..."
1213 // but that's not allowed by syntax, hence FATAL_ERROR.
1214 if (txt
.new_text
) FATAL_ERROR("Type::chk_xer_text");
1215 if (!text_map
.has_key(empty
)) {
1216 text_map
.add(empty
, txt
.new_text
);
1218 if (last
->typetype
!= T_BOOL
) {
1219 error("Lone 'TEXT' only allowed for boolean"); // only in TTCN-3 !
1223 case NamespaceSpecification::ALL
: {// TEXT ALL AS ...
1224 switch (txt
.keyword
) {
1225 case NamespaceSpecification::NO_MANGLING
:
1226 // Not possible due to syntax; there is no TTCN source from which
1227 // the bison parser would create such a NamespaceSpecification.
1228 FATAL_ERROR("Type::chk_xer_text");
1230 case NamespaceSpecification::CAPITALIZED
:
1231 case NamespaceSpecification::UNCAPITALIZED
:
1232 case NamespaceSpecification::LOWERCASED
:
1233 case NamespaceSpecification::UPPERCASED
:
1236 default: // TEXT ALL AS "some string" is not allowed
1237 error("text all as 'string' is not allowed");
1239 } // switch(keyword)
1242 switch (last
->typetype
) {
1244 text_map
.add(stringval(mcopystr("true")), txt
.new_text
);
1245 text_map
.add(stringval(mcopystr("false")), txt
.new_text
);
1250 size_t n_eis
= last
->u
.enums
.eis
->get_nof_eis();
1251 for (size_t i
= 0; i
< n_eis
; ++i
) {
1252 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byIndex(i
);
1253 const stringval
enum_name(mcopystr(ei
->get_name().get_ttcnname().c_str()));
1254 if (text_map
.has_key(enum_name
)) {
1255 // Duplicate enum name, flagged elsewhere as error.
1256 // Don't bother with: text_map[enum_name] = txt.new_text;
1257 Free(const_cast<char*>(enum_name
.c_str()));
1259 else text_map
.add(enum_name
, txt
.new_text
);
1264 FATAL_ERROR("Type::chk_xer_text");
1266 } // switch (typetype)
1270 default: {// a string: TEXT 'member' AS ...
1271 if (txt
.keyword
== NamespaceSpecification::NO_MANGLING
) {
1272 // Attribute syntax does not allow this combination
1273 FATAL_ERROR("Type::chk_xer_text");
1275 // HR39956: empty string is disregarded
1276 if (txt
.keyword
>NamespaceSpecification::LOWERCASED
&& !strcmp(txt
.new_text
,""))
1278 txt
.new_text
= (char*)Realloc(txt
.new_text
, sizeof(" "));
1279 strcpy(txt
.new_text
," ");
1281 stringval
ttarget(txt
.target
);
1282 if (text_map
.has_key(ttarget
)) {
1283 // Override the earlier TEXT instruction
1284 free_name_or_kw(text_map
[ttarget
]);
1285 text_map
[ttarget
] = txt
.new_text
;
1286 free_name_or_kw(txt
.target
);
1288 else text_map
.add(ttarget
, txt
.new_text
);
1293 xerattrib
->text_
= (NamespaceSpecification
*)Realloc(xerattrib
->text_
,
1294 text_map
.size() * sizeof(NamespaceSpecification
));
1296 // Zero out the newly allocated part
1297 if (text_map
.size() > xerattrib
->num_text_
) {
1299 xerattrib
->text_
+ xerattrib
->num_text_
,
1301 (text_map
.size() - xerattrib
->num_text_
) * sizeof(NamespaceSpecification
)
1305 xerattrib
->num_text_
= text_map
.size(); // accept the new size
1307 // Another map, to check for duplicate text (decoding would be impossible)
1310 // Reconstruct the TEXT structure from the map
1311 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1312 const stringval
& k
= text_map
.get_nth_key(t
);
1313 char * v
= text_map
.get_nth_elem(t
);
1314 char * newstr
= const_cast<char*>(k
.c_str());
1316 xerattrib
->text_
[t
].target
= newstr
;
1317 xerattrib
->text_
[t
].new_text
= v
;
1319 stringval
txtval(v
); // somebody else owns v
1320 if (map2
.has_key(txtval
)) {
1321 switch (xerattrib
->text_
[t
].keyword
) {
1322 case NamespaceSpecification::NO_MANGLING
:
1323 FATAL_ERROR("nope");
1324 break; // not possible
1326 case NamespaceSpecification::CAPITALIZED
:
1327 case NamespaceSpecification::UNCAPITALIZED
:
1328 case NamespaceSpecification::LOWERCASED
:
1329 case NamespaceSpecification::UPPERCASED
:
1330 // Duplication may have been caused by expanding TEXT ALL ...
1333 default: // string must be unique
1334 error("Duplicate text '%s'", v
);
1338 else map2
.add(txtval
, newstr
);
1343 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1344 if (xerattrib
->useNumber_
) {
1345 error("USE-NUMBER and TEXT are incompatible");
1348 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
1350 switch (last
->typetype
) {
1352 /* In ASN.1, Only Booleantype:ALL can have TEXT
1353 * Currently for TTCN, only the following three case are supported:
1355 * "text 'true' as '1'"
1356 * "text 'false' as '0'"
1357 * and we convert the last two to the first
1359 switch ((unsigned long)txt
.prefix
) {
1360 case 0: // no Target (ok);
1361 if (txt
.uri
!= 0) error("Only \"text\" implemented for boolean");
1363 case NamespaceSpecification::ALL
: // Target = 'all' not allowed for boolean
1364 error("TEXT all not implemented for boolean");
1366 default: // a string, must be "true" or "false"
1367 if (!strcmp(txt
.prefix
, "true")) {
1368 // only "1" is allowed for "true"
1369 switch ((unsigned long)txt
.uri
) {
1370 default: // it's a string
1371 if (txt
.uri
[0] == '1' && txt
.uri
[1] == '\0') {
1372 // Free the strings to pretend it was a simple "text"
1373 Free(txt
.prefix
); txt
.prefix
= 0;
1374 Free(txt
.uri
); txt
.uri
= 0;
1375 // These should come in pairs, warn if not
1376 if (xerattrib
->num_text_
== 1) warning("\"text 'false' as '0'\" was implied");
1379 // else fall through
1380 case NamespaceSpecification::CAPITALIZED
:
1381 case NamespaceSpecification::UNCAPITALIZED
:
1382 case NamespaceSpecification::UPPERCASED
:
1383 case NamespaceSpecification::LOWERCASED
:
1384 error("Only '1' is supported for 'true'");
1387 case 0: // "text 'true'" is not correct syntax, cannot get here
1388 FATAL_ERROR("Type::chk_xer_text()");
1391 else if (!strcmp(txt
.prefix
, "false")) {
1392 // only "0" is allowed for "false"
1393 switch ((unsigned long)txt
.uri
) {
1394 default: // it's a string
1395 if (txt
.uri
[0] == '0' && txt
.uri
[1] == '\0') {
1396 // Free the strings to pretend it was a simple "text"
1397 Free(txt
.prefix
); txt
.prefix
= 0;
1398 Free(txt
.uri
); txt
.uri
= 0;
1399 // These should come in pairs, warn if not
1400 if (xerattrib
->num_text_
== 1) warning("\"text 'true' as '1'\" was implied");
1403 // else fall through
1404 case NamespaceSpecification::CAPITALIZED
:
1405 case NamespaceSpecification::UNCAPITALIZED
:
1406 case NamespaceSpecification::UPPERCASED
:
1407 case NamespaceSpecification::LOWERCASED
:
1408 error("Only '0' is supported for 'false'");
1411 case 0: // "text 'false'" is not correct syntax, cannot get here
1412 FATAL_ERROR("Type::chk_xer_text()");
1420 //case T_ENUM_A: // fall through
1422 switch ((unsigned long)txt
.target
) {
1423 case 0: // "text as ..."
1424 case NamespaceSpecification::ALL
: { // "text all as ..."
1425 size_t neis
= last
->u
.enums
.eis
->get_nof_eis();
1426 for (size_t i
= 0; i
< neis
; ++i
) {
1427 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byIndex(i
);
1428 string
ei_name(ei
->get_name().get_dispname()); // use the element's own name
1429 XerAttributes::NameChange chg
;
1431 change_name(ei_name
, chg
);
1432 ei
->set_text(ei_name
);
1436 default: { // target is member name, from "text 'member' as ..."
1437 // FIXME: ID_TTCN will not be right if we implement XER for ASN.1
1438 Common::Identifier
id(Identifier::ID_TTCN
, string(txt
.prefix
));
1439 if (last
->u
.enums
.eis
->get_nof_eis()==0) FATAL_ERROR("No enum items!");
1440 if (last
->u
.enums
.eis
->has_ei_withName(id
)) {
1441 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byName(id
);
1442 string
ei_name(id
.get_dispname());
1443 XerAttributes::NameChange chg
;
1445 change_name(ei_name
, chg
);
1446 ei
->set_text(ei_name
);
1449 error("No enumeration item %s", txt
.prefix
);
1458 if (last->u.namednums.nvs->get_nof_nvs()) {
1459 Common::Identifier id(Identifier::ID_TTCN, txt.uri);
1460 NamedValue *nv = last->u.namednums.nvs->get_nv_byName(id);
1465 error("No component %s in %s", txt.uri, fn);
1469 error("TEXT cannot be assigned to an integer without named numbers");
1475 FATAL_ERROR("Type::chk_xer_text");
1478 } // next type for TEXT
1481 void Type::chk_xer_untagged()
1483 Type
* const last
= get_type_refd_last();
1484 switch (parent_type
? parent_type
->typetype
:-0) {
1485 case 0: // "no parent" is acceptable
1486 // Do not nag ("UNTAGGED encoding attribute is ignored on top-level type");
1487 // do it in Def_ExtFunction::chk_function_type when the type is actually
1488 // used as input for an encoding function.
1490 case T_SEQ_A
: case T_SEQ_T
:
1491 case T_SET_A
: case T_SET_T
:
1492 case T_CHOICE_A
: case T_CHOICE_T
:
1493 case T_SEQOF
: case T_SETOF
:
1494 break; // acceptable
1496 error("UNTAGGED can only be applied to a member of sequence, set, "
1497 "choice, sequence-of, or set-of type"); // X.693amd1, 32.2.1
1501 if ( has_aa(xerattrib
)
1502 || has_ae(xerattrib
)
1503 || xerattrib
->attribute_
|| 0 != xerattrib
->defaultForEmpty_
1504 || xerattrib
->embedValues_
|| xerattrib
->useNil_
1505 || (xerattrib
->useOrder_
&& is_asn1()) || xerattrib
->useType_
) {
1506 error("A type with final encoding attribute UNTAGGED shall not have"
1507 " any of the final encoding instructions ANY-ATTRIBUTES, ANY-ELEMENT,"
1508 " ATTRIBUTE, DEFAULT-FOR-EMPTY, EMBED-VALUES, PI-OR-COMMENT,"
1509 " USE-NIL%s or USE-TYPE",
1510 is_asn1() ? ", USE-ORDER" : ""); // X.693amd1, 32.2.6
1513 bool can_become_empty
= last
->has_empty_xml();
1514 if (can_become_empty
) { // checking 32.2.4
1515 switch (parent_type
? parent_type
->typetype
:-0) {
1517 break; // no parent, no problem
1519 case T_SEQ_A
: case T_SEQ_T
:
1520 case T_SET_A
: case T_SET_T
: {
1521 // This type can not have OPTIONAL or DEFAULT, 32.2.4 a)
1522 // No get_comp_byType(); do a linear search.
1523 size_t num_fields
= parent_type
->get_nof_comps();
1524 for (size_t i
= 0; i
< num_fields
; ++i
) {
1525 CompField
*cf
= parent_type
->get_comp_byIndex(i
);
1526 if (cf
->get_type() != this) continue;
1527 // found the component
1528 if (cf
->get_is_optional() || cf
->get_defval() != 0) {
1529 error("Type with final encoding attribute UNTAGGED"
1530 " shall not have OPTIONAL or DEFAULT");
1536 case T_SEQOF
: case T_SETOF
: // X.693amd1, 32.2.4 b)
1537 error("UNTAGGED type with possibly empty XML value can not be "
1538 "the member of a sequence-of or set-of"); // X.693amd1, 32.2.4 b)
1542 size_t num_fields
= parent_type
->get_nof_comps();
1543 size_t num_empty
= 0;
1544 for (size_t i
= 0; i
< num_fields
; ++i
) {
1545 CompField
*cf
= parent_type
->get_comp_byIndex(i
);
1546 Type
*cft
= cf
->get_type();
1547 if (cft
->has_empty_xml()) ++num_empty
;
1549 if (num_empty
> 1) { // X.693amd1, 32.2.4 c)
1550 /* FIXME: this should be error */
1551 warning("More than one alternative can be empty and has UNTAGGED");
1555 default: // do nothing
1558 } // end if(can_become_empty)
1561 void Type::chk_xer_use_nil()
1563 Type
* const last
= get_type_refd_last();
1565 enum complaint_type
{ ALL_GOOD
, NO_CONTROLNS
, NOT_SEQUENCE
, EMPTY_SEQUENCE
,
1566 UNTAGGED_USENIL
, COMPONENT_NOT_ATTRIBUTE
, LAST_IS_ATTRIBUTE
,
1567 LAST_NOT_OPTIONAL
, INCOMPATIBLE
, WRONG_OPTIONAL_TYPE
, EMBED_CHARENC
,
1568 NOT_COMPATIBLE_WITH_USEORDER
, BAD_ENUM
, FIRST_OPTIONAL
, NOTHING_TO_ORDER
,
1569 FIRST_NOT_RECORD_OF_ENUM
, ENUM_GAP
};
1570 complaint_type complaint
= ALL_GOOD
;
1572 CompField
*cf_last
= 0;
1573 const char *ns
, *prefix
;
1575 my_scope
->get_scope_mod()->get_controlns(ns
, prefix
);
1577 if (!prefix
) complaint
= NO_CONTROLNS
; // don't bother checking further
1578 else switch (last
->typetype
) {
1580 complaint
= NOT_SEQUENCE
;
1584 error("No XER yet for ASN.1 sequences");
1587 const size_t num_cf
= last
->get_nof_comps();
1588 if (num_cf
== 0) { // 33.2.1 ...must have a component...
1589 complaint
= EMPTY_SEQUENCE
;
1590 break; // stop checking to prevent accessing non-existing components
1592 if (xerattrib
->untagged_
) { // 33.2.2
1593 complaint
= UNTAGGED_USENIL
;
1597 // Skip components supporting USE-ORDER or EMBED-VALUES
1598 size_t i
= (xerattrib
->useOrder_
) + (xerattrib
->embedValues_
);
1599 // 33.2.1 All the others except the last must be (any)attributes
1600 for (; i
< num_cf
-1; ++i
) {
1601 cf
= last
->get_comp_byIndex(i
);
1602 Type
*cft
= cf
->get_type();
1603 if (! (cft
->xerattrib
1604 && ( cft
->xerattrib
->attribute_
|| has_aa(cft
->xerattrib
))))
1606 complaint
= COMPONENT_NOT_ATTRIBUTE
;
1610 // 33.2.1 The last component must be an OPTIONAL non-attribute
1611 cf_last
= last
->get_comp_byIndex(num_cf
-1);
1612 Type
*cft
= cf_last
->get_type();
1613 if (!cf_last
->get_is_optional()) {
1614 complaint
= LAST_NOT_OPTIONAL
;
1617 if(xerattrib
->useOrder_
&& cft
->get_type_refd_last()->get_typetype() != T_SEQ_A
1618 && cft
->get_type_refd_last()->get_typetype() != T_SEQ_T
){
1619 complaint
= NOT_COMPATIBLE_WITH_USEORDER
;
1620 }else if(xerattrib
->useOrder_
) {
1621 //This check needed, because if the record that has useOrder only
1622 //has one field that is a sequence type, then the useNilPossible
1623 //would be always true, that would lead to incorrect code generation.
1624 Type
* inner
= cft
->get_type_refd_last();
1625 size_t useorder_index
= xerattrib
->embedValues_
;
1626 CompField
*uo_field
= last
->get_comp_byIndex(useorder_index
);
1627 Type
*uot
= uo_field
->get_type();
1628 if (uot
->get_type_refd_last()->typetype
== T_SEQOF
) {
1629 the_enum
= uot
->get_ofType()->get_type_refd_last();
1630 if(the_enum
->typetype
!= T_ENUM_A
&& the_enum
->typetype
!= T_ENUM_T
){
1631 complaint
= FIRST_NOT_RECORD_OF_ENUM
;
1633 }else if (uo_field
->get_is_optional() || uo_field
->get_defval() != 0) {
1634 complaint
= FIRST_OPTIONAL
;
1638 size_t expected_enum_items
= inner
->get_nof_comps();
1639 size_t enum_index
= 0;
1640 if (expected_enum_items
== 0)
1641 complaint
= NOTHING_TO_ORDER
;
1642 else if (the_enum
->u
.enums
.eis
->get_nof_eis() != expected_enum_items
)
1643 complaint
= BAD_ENUM
;
1644 else for (size_t i
= 0; i
< expected_enum_items
; ++i
) {
1645 CompField
*inner_cf
= inner
->get_comp_byIndex(i
);
1646 Type
*inner_cft
= inner_cf
->get_type();
1647 if (inner_cft
->xerattrib
&& inner_cft
->xerattrib
->attribute_
) continue;
1648 // Found a non-attribute component. Its name must match an enumval
1649 const Identifier
& field_name
= inner_cf
->get_name();
1650 const EnumItem
*ei
= the_enum
->get_ei_byIndex(enum_index
);
1651 const Identifier
& enum_name
= ei
->get_name();
1652 if (field_name
!= enum_name
) {// X.693amd1 35.2.2.1 and 35.2.2.2
1653 complaint
= BAD_ENUM
;
1656 Value
*v
= ei
->get_value();
1657 const int_val_t
*ival
= v
->get_val_Int();
1658 const Int enumval
= ival
->get_val();
1659 if ((size_t)enumval
!= enum_index
) {
1660 complaint
= ENUM_GAP
; // 35.2.2.3
1668 if (cft
->xerattrib
) {
1669 if ( cft
->xerattrib
->attribute_
1670 || has_aa(cft
->xerattrib
)) {
1671 complaint
= LAST_IS_ATTRIBUTE
;
1675 if (has_ae(cft
->xerattrib
)
1676 ||has_aa(cft
->xerattrib
)
1677 ||cft
->xerattrib
->defaultForEmpty_
!= 0
1678 ||cft
->xerattrib
->untagged_
1679 ||cft
->xerattrib
->useNil_
1680 ||cft
->xerattrib
->useOrder_
1681 ||cft
->xerattrib
->useType_
) { // or PI-OR-COMMENT
1682 complaint
= INCOMPATIBLE
; // 33.2.3
1686 if (cft
->is_charenc() == Yes
) {
1687 // In a sequence EMBED-VALUES and USE-NIL, the optional component
1688 // supporting USE-NIL shall not be a character-encodable type.
1689 // So says OSS, and rightly so (there's no way to separate
1690 // the last field from the surrounding "embed" strings).
1691 if (xerattrib
->embedValues_
) complaint
= EMBED_CHARENC
;
1693 else switch (cft
->get_type_refd_last()->typetype
) {
1704 // or an octetstring or bitstring with a contained "Type" and without ENCODED BY
1705 break; // acceptable
1708 complaint
= WRONG_OPTIONAL_TYPE
;
1713 } // else switch(last->typetype)
1715 if (complaint
== ALL_GOOD
) use_nil_possible
= true;
1716 else if (xerattrib
->useNil_
) {
1717 switch (complaint
) {
1718 case ALL_GOOD
: // Not possible because of the if.
1719 // Present so GCC checks that all enum values are handled (no default!)
1722 error("Type has USE-NIL, but the module has no control namespace set");
1725 error("The target of an USE-NIL encoding instruction must be a record (SEQUENCE) or set type");
1727 case EMPTY_SEQUENCE
:
1728 error("The target of an USE-NIL must have at least one component");
1730 case UNTAGGED_USENIL
:
1731 error("The target of an USE-NIL encoding instruction shall not have"
1732 " a final UNTAGGED encoding instruction");
1734 case COMPONENT_NOT_ATTRIBUTE
:
1735 cf
->error("Component '%s' of USE-NIL not ATTRIBUTE", cf
->get_name().get_name().c_str());
1737 case LAST_IS_ATTRIBUTE
:
1738 cf_last
->error("Last component of USE-NIL must not have ATTRIBUTE");
1740 case LAST_NOT_OPTIONAL
:
1741 cf_last
->error("Last component of USE-NIL must be OPTIONAL");
1744 cf_last
->error("The OPTIONAL component of USE-NIL cannot have any of the "
1745 "following encoding instructions: ANY-ATTRIBUTES, ANY-ELEMENT, "
1746 "DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED, "
1747 "USE-NIL, USE-ORDER, USE-TYPE.");
1749 case WRONG_OPTIONAL_TYPE
:
1750 cf_last
->error("The OPTIONAL component of USE-NIL must be "
1751 "a character-encodable type, or a sequence, set, choice, "
1752 "sequence-of, set-of or open type.");
1755 cf_last
->error("In a sequence type with EMBED-VALUES and USE-NIL, "
1756 "the optional component supporting USE-NIL shall not be "
1757 "a character-encodable type.");
1759 case NOT_COMPATIBLE_WITH_USEORDER
:
1760 cf_last
->error("The OTIONAL component of USE-NIL must be "
1761 "a SEQUENCE/record when USE-ORDER is set for the parent type.");
1764 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1765 the_enum
->error("Enumeration items should match the"
1766 " non-attribute components of the field %s",
1767 cf_last
->get_name().get_dispname().c_str());
1769 case FIRST_OPTIONAL
:
1770 error("The record-of for USE-ORDER shall not be marked"
1771 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1773 case NOTHING_TO_ORDER
:
1774 error("The component (%s) should have at least one non-attribute"
1775 " component if USE-ORDER is present",
1776 cf_last
->get_name().get_dispname().c_str());
1778 case FIRST_NOT_RECORD_OF_ENUM
:
1779 error("The type with USE-ORDER should have a component "
1780 "which is a record-of enumerated");
1783 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1784 the_enum
->error("Enumeration values must start at 0 and have no gaps");
1790 void Type::chk_xer_use_order(int num_attributes
)
1792 Type
* const last
= get_type_refd_last();
1794 enum complaint_type
{ ALL_GOOD
, NOT_SEQUENCE
, NOT_ENOUGH_MEMBERS
,
1795 FIRST_NOT_RECORD_OF
, FIRST_NOT_RECORD_OF_ENUM
, FIRST_OPTIONAL
,
1796 LAST_NOT_RECORD
, BAD_ENUM
, ENUM_GAP
, NOTHING_TO_ORDER
};
1797 complaint_type complaint
= ALL_GOOD
;
1798 Type
*the_enum
= 0; // Well, it's supposed to be an enum.
1799 switch (last
->typetype
) {
1800 case T_SEQ_A
: case T_SEQ_T
: { // record/SEQUENCE acceptable
1801 size_t useorder_index
= xerattrib
->embedValues_
;
1802 // The first (or second, if the first is taken by EMBED_VALUES)
1803 // member must be a record of enumerated
1804 if (useorder_index
>= last
->get_nof_comps()) {
1805 complaint
= NOT_ENOUGH_MEMBERS
;
1808 CompField
*uo_field
= last
->get_comp_byIndex(useorder_index
);
1809 Type
*uot
= uo_field
->get_type();
1810 if (uot
->get_type_refd_last()->typetype
== T_SEQOF
) {
1811 the_enum
= uot
->get_ofType()->get_type_refd_last();
1812 switch (the_enum
->typetype
) {
1813 case T_ENUM_A
: case T_ENUM_T
: // acceptable
1814 if (uo_field
->get_is_optional() || uo_field
->get_defval() != 0) {
1815 complaint
= FIRST_OPTIONAL
;
1819 complaint
= FIRST_NOT_RECORD_OF_ENUM
;
1821 } // switch enum type
1822 size_t ncomps
= last
->get_nof_comps();
1823 // the components of this sequence will have to match the enum
1824 Type
*sequence_type
= 0;
1825 size_t expected_enum_items
, first_non_attr
;
1827 if (xerattrib
->useNil_
) { // useNil in addition to useOrder
1828 // This is an additional complication because USE-ORDER
1829 // will affect the optional component, rather than the type itself
1830 CompField
*cf
= last
->get_comp_byIndex(ncomps
-1);
1831 sequence_type
= cf
->get_type()->get_type_refd_last();
1832 if (sequence_type
->typetype
== T_SEQ_T
1833 ||sequence_type
->typetype
== T_SEQ_A
) {
1835 // No need to check that it has at least one component (35.2.1)
1836 // it can't match up with the enum which always has one
1837 ncomps
= sequence_type
->get_nof_comps();
1838 expected_enum_items
= ncomps
;
1841 else { // Whoops, not a sequence type!
1842 complaint
= LAST_NOT_RECORD
;
1843 break; // the switch(typetype)
1847 sequence_type
= last
;
1848 first_non_attr
= useorder_index
+1+num_attributes
;
1849 expected_enum_items
= ncomps
- first_non_attr
;
1852 size_t enum_index
= 0;
1853 if (expected_enum_items
== 0)
1854 complaint
= NOTHING_TO_ORDER
;
1855 else if (the_enum
->u
.enums
.eis
->get_nof_eis() != expected_enum_items
)
1856 complaint
= BAD_ENUM
;
1857 else for (size_t i
= first_non_attr
; i
< ncomps
; ++i
) {
1858 CompField
*cf
= sequence_type
->get_comp_byIndex(i
);
1859 Type
*cft
= cf
->get_type();
1860 if (cft
->xerattrib
&& cft
->xerattrib
->attribute_
) continue;
1861 // Found a non-attribute component. Its name must match an enumval
1862 const Identifier
& field_name
= cf
->get_name();
1863 // don't use get_eis_index_byName(); fatal error if not found :(
1864 const EnumItem
*ei
= the_enum
->get_ei_byIndex(enum_index
);
1865 const Identifier
& enum_name
= ei
->get_name();
1866 if (field_name
!= enum_name
) {// X.693amd1 35.2.2.1 and 35.2.2.2
1867 complaint
= BAD_ENUM
;
1870 Value
*v
= ei
->get_value();
1871 const int_val_t
*ival
= v
->get_val_Int();
1872 const Int enumval
= ival
->get_val();
1873 if ((size_t)enumval
!= enum_index
) {
1874 complaint
= ENUM_GAP
; // 35.2.2.3
1878 } // next enum component
1881 complaint
= FIRST_NOT_RECORD_OF
;
1886 complaint
= NOT_SEQUENCE
;
1888 } // switch typetype
1890 if (complaint
== ALL_GOOD
) use_order_possible
= true;
1891 else if (xerattrib
->useOrder_
) {
1892 switch (complaint
) {
1893 case ALL_GOOD
: // Not possible; present in the switch so GCC checks
1894 // that all enum values are handled (make sure there's no default).
1897 error("USE-ORDER can only be assigned to a SEQUENCE/record type.");
1899 case NOT_ENOUGH_MEMBERS
:
1900 case FIRST_NOT_RECORD_OF
:
1901 case FIRST_NOT_RECORD_OF_ENUM
:
1902 error("The type with USE-ORDER should have a component "
1903 "which is a record-of enumerated");
1905 case FIRST_OPTIONAL
:
1906 error("The record-of for USE-ORDER shall not be marked"
1907 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1909 case NOTHING_TO_ORDER
:
1910 error("The type with USE-ORDER should have at least one "
1911 "non-attribute component");
1913 case LAST_NOT_RECORD
:
1914 error("The OPTIONAL component supporting the USE-NIL "
1915 "encoding instruction should be a SEQUENCE/record");
1918 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1919 the_enum
->error("Enumeration items should match the"
1920 " non-attribute components of the sequence");
1923 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1924 the_enum
->error("Enumeration values must start at 0 and have no gaps");
1930 void Type::chk_xer_use_type()
1932 Type
* const last
= get_type_refd_last();
1934 const char *ns
, *prefix
;
1935 my_scope
->get_scope_mod()->get_controlns(ns
, prefix
);
1936 if (!prefix
) error("Type has USE-TYPE, but the module has no control namespace set");
1938 switch (last
->typetype
) {
1939 // USE-TYPE applied to anytype ? Just say no.
1940 case T_CHOICE_A
: case T_CHOICE_T
: { // must be CHOICE; 37.2.1
1941 if (xerattrib
->untagged_
|| xerattrib
->useUnion_
) { // 37.2.5
1942 error("A type with USE-TYPE encoding instruction shall not also have"
1943 " any of the final encoding instructions UNTAGGED or USE-UNION");
1945 // Now check the alternatives.
1946 // iterating backwards calls get_nof_comps only once
1947 for (int i
= last
->get_nof_comps() - 1; i
>= 0; --i
) {
1948 CompField
*cf
= last
->get_comp_byIndex(i
);
1949 Type
*cft
= cf
->get_type();
1950 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
) {
1951 cf
->error("Alternative of a union with USE-TYPE should not have UNTAGGED"); // 37.2.2
1954 switch (cft
->typetype
) {
1955 case T_CHOICE_A
: case T_CHOICE_T
:
1956 if (cft
->xerattrib
&& cft
->xerattrib
->useType_
) {
1957 cf
->error("Alternative of a CHOICE type with USE-TYPE shall not be"
1958 " a CHOICE type with a USE-TYPE encoding instruction"); // 37.2.3
1967 error("USE-TYPE can only applied to a CHOICE/union type");
1972 void Type::chk_xer_use_union()
1974 Type
* const last
= get_type_refd_last();
1975 switch (last
->typetype
) {
1976 case T_CHOICE_A
: case T_CHOICE_T
: {
1977 // Now check the alternatives.
1978 // iterating backwards calls get_nof_comps only once
1979 for (int i
= last
->get_nof_comps() - 1; i
>= 0; --i
) {
1980 CompField
*cf
= last
->get_comp_byIndex(i
);
1981 Type
*cft
= cf
->get_type();
1982 if (cft
->is_charenc() && !(cft
->xerattrib
&& cft
->xerattrib
->useType_
) &&
1983 !(cft
->xerattrib
&& cft
->xerattrib
->useQName_
)) { // currently not supported
1984 if (cft
->xerattrib
&& cft
->xerattrib
->useUnion_
) // it must be a union
1985 cf
->error("Alternative of a CHOICE/union with USE-UNION"
1986 " can not itself be a CHOICE/union with USE-UNION");
1988 else cf
->error("Alternative of a CHOICE/union with USE-UNION must be character-encodable");
1992 error("USE-UNION can only applied to a CHOICE/union type"); // 38.2.1
1998 static const char *xml98
= "http://www.w3.org/XML/1998/namespace";
2000 void Type::chk_xer() { // XERSTUFF semantic check
2001 // the type (and everything it contains) is fully checked now
2003 if (xer_checked
) return;
2006 Type
*last
= get_type_refd_last();
2008 // Check XER attributes if the type belongs to a type definition,
2009 // a field of a record/set/union, or is the embedded type of a record-of.
2010 if (ownertype
==OT_TYPE_DEF
2011 ||ownertype
==OT_COMP_FIELD
2012 ||ownertype
==OT_RECORD_OF
) {
2013 XerAttributes
*newx
= 0;
2015 // Merge XER attributes from the referenced type.
2016 // This implements X.693amd1 clause 15.1.2
2017 newx
= new XerAttributes
;
2018 Type
*t1
= get_type_refd();
2019 // chk_refd() (called by chk() for T_REFD) does not check
2020 // the referenced type; do it now. This makes it fully recursive.
2023 size_t old_text
= 0;
2024 if (t1
->xerattrib
&& !t1
->xerattrib
->empty()) {
2025 old_text
= t1
->xerattrib
->num_text_
;
2026 *newx
|= *t1
->xerattrib
; // get the ancestor's attributes, except...
2027 newx
->attribute_
= false; // attribute is not inherited
2028 newx
->element_
= false; // element is not inherited
2030 if (ownertype
== OT_TYPE_DEF
2031 ||ownertype
== OT_COMP_FIELD
) {
2032 // Name,Namespace is not inherited, X.693 amd1, 13.6
2033 // are you sure about the namespace?
2034 XerAttributes::FreeNameChange(newx
->name_
);
2035 //XerAttributes::FreeNamespace(newx->namespace_); // HR39678 bugfix beta
2038 // Now merge/override with our own attributes
2039 if (xerattrib
&& !xerattrib
->empty()) {
2040 if (xerattrib
->num_text_
> 0 && old_text
> 0
2041 && (last
->typetype
== T_ENUM_T
|| last
->typetype
== T_ENUM_A
)) {
2042 // Adding more TEXT attributes does not work right.
2043 error("Adding more TEXT attributes is not supported "
2044 "by the implementation.");
2046 *newx
|= *xerattrib
;
2049 if (newx
->empty()) delete newx
;
2050 else { // something interesting was found
2054 if (xerattrib
->attribute_
2055 && t1
->xerattrib
&& t1
->xerattrib
->attribute_
2056 && t1
->ownertype
== OT_TYPE_DEF
2057 && !(xerattrib
->form_
& XerAttributes::LOCALLY_SET
) ) {
2058 // The referenced type came from a global XSD attribute.
2059 // This type's form will be qualified, unless it has an explicit
2060 // "form as ..." (which overrides everything).
2061 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2064 if (t1
->xerattrib
&& t1
->xerattrib
->element_
2065 // The referenced type came from a global XSD element.
2066 && !(xerattrib
->form_
& XerAttributes::LOCALLY_SET
))
2067 { // and it doesn't have an explicit "form as ..."
2068 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2074 if (!xerattrib
) return;
2076 //const char *fn = get_fullname().c_str();
2077 //printf("chk_xer(%s)\n", fn);
2079 // In general, "last" should be used instead of "this" in the checks below
2080 // when accessing information about the type's characteristics, except
2081 // this->xerattrib MUST be used (and not last->xerattrib!).
2083 switch (ownertype
) {
2091 FATAL_ERROR("Unexpected ownertype %d", ownertype
);
2094 int num_attributes
= 0;
2095 switch (last
->typetype
) {
2096 case T_SEQ_A
: case T_SEQ_T
:
2097 case T_SET_A
: case T_SET_T
: {
2098 // Count attributes (ANY-ATTRIBUTES counts as one)
2099 const size_t num_cf
= last
->get_nof_comps();
2100 int specials
= xerattrib
->embedValues_
+ xerattrib
->useOrder_
;
2101 int num_any_attributes
= 0;
2102 for (int x
= num_cf
- 1; x
>= specials
; --x
) {
2103 CompField
*cf
= last
->get_comp_byIndex(x
);
2104 Type
*cft
= cf
->get_type() /* NOT get_type_refd_last() */;
2106 && (cft
->xerattrib
->attribute_
|| has_aa(cft
->xerattrib
)))
2108 if (cft
->xerattrib
->attribute_
) ++num_attributes
;
2109 else if (++num_any_attributes
> 1) {
2110 cf
->error("There can be at most one field with ANY-ATTRIBUTES");
2113 else if (num_attributes
+ num_any_attributes
> 0) {
2114 // Found a non-attribute when there was an attribute after it
2115 cf
->error("Non-attribute field before attribute not supported");
2119 num_attributes
+= num_any_attributes
;
2126 /* * * Check restrictions set out in X.693 amd1, clauses 18-39 * * */
2128 if (has_aa(xerattrib
)) {
2129 chk_xer_any_attributes();
2130 } // if ANY-ATTRIBUTES
2132 if (has_ae(xerattrib
)) {
2133 chk_xer_any_element();
2136 if (xerattrib
->attribute_
) {
2137 chk_xer_attribute();
2138 // It's an attribute, check for the attributeFormQualified bit
2139 // and transform it into unconditionally qualified.
2140 if (!(xerattrib
->form_
& XerAttributes::LOCALLY_SET
)
2141 && (xerattrib
->form_
& XerAttributes::ATTRIBUTE_DEFAULT_QUALIFIED
)) {
2142 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2146 // Element, check the elementFormQualified bit.
2147 if (!(xerattrib
->form_
& XerAttributes::LOCALLY_SET
)
2148 && (xerattrib
->form_
& XerAttributes::ELEMENT_DEFAULT_QUALIFIED
)) {
2149 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2153 if (xerattrib
->base64_
) {
2154 switch (last
->typetype
) {
2155 case T_OSTR
: // OCTET STRING
2156 case T_HSTR
: // hexstring
2159 case T_GENERALSTRING
:
2160 case T_GRAPHICSTRING
:
2163 case T_NUMERICSTRING
:
2164 case T_PRINTABLESTRING
:
2165 case T_TELETEXSTRING
:
2167 case T_UNIVERSALSTRING
:
2169 case T_VIDEOTEXSTRING
:
2170 case T_VISIBLESTRING
:
2174 break; // acceptable
2176 error("BASE64 can only be applied to OCTET STRING, open type or "
2177 "restricted character string type");
2181 if (has_ae(xerattrib
) || xerattrib
->whitespace_
!= XerAttributes::PRESERVE
) {
2182 error("A type with BASE64 shall not have any of the final "
2183 "encoding instructions ANY-ELEMENT or WHITESPACE");
2187 if (xerattrib
->decimal_
) {
2188 if (last
->typetype
!= T_REAL
) {
2189 error("DECIMAL shall only be assigned to a real type");
2193 if (xerattrib
->defaultForEmpty_
!= 0) {
2195 } // if defaultForEmpty
2197 chk_xer_embed_values(num_attributes
); // always
2199 if (xerattrib
->list_
) {
2200 switch (last
->typetype
) {
2201 case T_SEQOF
: case T_SETOF
:
2202 break; // acceptable
2204 error("LIST can only be assigned to SEQUENCE-OF or SET-OF");// 27.2.1
2208 if (has_aa(xerattrib
)) {
2209 error("A type with LIST shall not have ANY-ATTRIBUTES");// 27.2.3
2213 // NAME is handled later when generate_code_xerdescriptor call change_name
2215 if ((unsigned long)xerattrib
->namespace_
.keyword
2216 > (unsigned long)NamespaceSpecification::LOWERCASED
) {
2217 // Now both are proper non-NULL strings
2218 if (*xerattrib
->namespace_
.prefix
!= 0) { // there is a prefix, check it
2219 char first
[4] = {0,0,0,0};
2220 strncpy(first
, xerattrib
->namespace_
.prefix
, 3);
2221 first
[0] = toupper(first
[0]);
2222 first
[1] = toupper(first
[1]);
2223 first
[2] = toupper(first
[2]);
2224 if (!memcmp(first
, "XML", 3) // It _is_ "xml"
2225 // but the W3C XML namespace gets an exemption
2226 && strcmp(xerattrib
->namespace_
.uri
, xml98
)) error(
2227 "Prefix shall not commence with characters that"
2228 " when uppercased are 'XML'");
2229 // X.693 (11/2008), clause 29.1.7
2232 Common::Module::add_namespace(
2233 xerattrib
->namespace_
.uri
, xerattrib
->namespace_
.prefix
);
2235 else xerattrib
->namespace_
.uri
= NULL
; // really no namespace
2237 // PI-OR-COMMENT not supported
2239 if (xerattrib
->num_text_
> 0) {
2243 if (xerattrib
->untagged_
) {
2247 chk_xer_use_nil(); // always
2249 if (xerattrib
->useNumber_
) {
2250 switch (last
->typetype
) {
2252 error("No XER yet for ASN.1 enumerations");
2255 break; // acceptable
2257 warning("USE-NUMBER ignored unless assigned to an enumerated type");
2258 xerattrib
->useNumber_
= false;
2262 if (xerattrib
->num_text_
) {
2263 error("A type with USE-NUMBER shall not have TEXT");
2267 chk_xer_use_order(num_attributes
); //always
2269 if (xerattrib
->useQName_
) {
2270 switch (last
->typetype
) {
2271 case T_SEQ_A
: case T_SEQ_T
: {
2272 if (last
->get_nof_comps() != 2) goto complain
;
2273 const CompField
* cf
= last
->get_comp_byIndex(0);
2274 const Type
* cft
= cf
->get_type()->get_type_refd_last();
2275 if (cft
->typetype
!= T_USTR
&& cft
->typetype
!= T_UTF8STRING
)
2276 cft
->error ("Both components must be UTF8String or universal charstring");
2277 if (!cf
->get_is_optional()) cft
->error(
2278 "The first component of a type with USE-QNAME must be optional");
2280 cf
= last
->get_comp_byIndex(1);
2281 cft
= cf
->get_type()->get_type_refd_last();
2282 if (cft
->typetype
!= T_USTR
&& cft
->typetype
!= T_UTF8STRING
)
2283 cft
->error ("Both components must be UTF8String or universal charstring");
2284 if (cf
->get_is_optional()) cft
->error(
2285 "The second component of a type with USE-QNAME must NOT be optional");
2290 error("A type with USE-QNAME must be a sequence type with exactly two components.");
2293 if (xerattrib
->useNil_
) error("A type with USE-QNAME shall not have USE-NIL"); // 36.2.4
2296 if (xerattrib
->useType_
) {
2300 if (xerattrib
->useUnion_
) {
2301 chk_xer_use_union();
2305 CompFieldMap
& cfm
= *u
.secho
.cfm
;
2306 const size_t ncomps
= cfm
.get_nof_comps();
2307 CompField
*the_one
= 0; // ...and only untagged character-encodable field
2308 map
<int, CompField
> empties
; // potentially empties
2310 for (size_t i
=0; i
< ncomps
; ++i
) {
2311 CompField
* cf
= cfm
.get_comp_byIndex(i
);
2312 Type
*cft
= cf
->get_type();
2314 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
) {
2315 /* This check could be in chk_xer_untagged(), but then we couldn't
2316 * access the CompField in the parent type. */
2317 if (cft
->is_charenc() == Yes
) {
2318 if (the_one
) { // already has one
2319 cf
->error("More than one UNTAGGED character-encodable field");
2320 // break? to report only once
2323 the_one
= cf
; // this is used for further checks below
2324 u
.secho
.has_single_charenc
= true; // used while generating code
2326 case T_SEQ_A
: case T_SEQ_T
:
2327 if (xerattrib
->untagged_
) {
2328 error("Enclosing type of an UNTAGGED character-encodable type "
2329 "must not be UNTAGGED");
2331 break; // the small switch
2333 error("Enclosing type of an UNTAGGED character-encodable type "
2339 else { // untagged, not charenc
2340 switch (cft
->get_type_refd_last()->typetype
) {
2341 case T_SEQ_A
: case T_SEQ_T
:
2342 case T_SET_A
: case T_SET_T
:
2343 case T_CHOICE_A
: case T_CHOICE_T
:
2346 //case T_OSTR: with a contained type
2347 //case T_BSTR_A: with a contained type
2351 default: // 32.2.3 "If the type is not character-encodable..."
2352 cft
->error("UNTAGGED type should be sequence, set, choice, sequence-of, or set-of type");
2358 if (cft
->has_empty_xml()) {
2364 if (the_one
->get_is_optional() || the_one
->has_default()) {
2365 the_one
->error("UNTAGGED field should not be marked OPTIONAL or DEFAULT");
2367 // Check the other compfields. They must all be (ANY)?ATTRIBUTE
2368 for (size_t i
=0; i
< ncomps
; ++i
) {
2369 CompField
*cf
= cfm
.get_comp_byIndex(i
);
2370 if (cf
== the_one
) continue;
2372 Type
*cft
= cf
->get_type();
2373 if ( !cft
->xerattrib
// cannot be attribute, error
2374 || (!cft
->xerattrib
->attribute_
&& !has_aa(cft
->xerattrib
))) {
2375 the_one
->note("Due to this UNTAGGED component");
2376 cf
->error("All the other components should be ATTRIBUTE or ANY-ATTRIBUTE");
2377 // X.693 (2008) 32.2.2
2383 if (empties
.size() > 1
2384 && (typetype
==T_CHOICE_A
|| typetype
==T_CHOICE_T
)) {
2385 warning("More than one field can have empty XML. Decoding of empty"
2386 " XML is ambiguous, %s chosen arbitrarily.",
2387 empties
.get_nth_elem(empties
.size()-1)->get_name().get_name().c_str());
2392 if (xerattrib
->abstract_
|| xerattrib
->block_
) {
2393 switch (ownertype
) {
2395 if (parent_type
->typetype
== T_CHOICE_A
||
2396 parent_type
->typetype
== T_CHOICE_T
) {
2397 if (parent_type
->xerattrib
!= NULL
&& parent_type
->xerattrib
->useUnion_
) {
2398 error("ABSTRACT and BLOCK cannot be used on fields of a union with "
2399 "attribute USE-UNION.");
2403 // else fall through
2406 warning("ABSTRACT and BLOCK only affects union fields.");
2416 void Type::chk_Int_A()
2420 if(!u
.namednums
.block
) return;
2422 if(typetype
==T_ERROR
) return;
2423 /* check named numbers */
2424 if(!u
.namednums
.nvs
) return;
2425 map
<Int
, NamedValue
> value_map
;
2426 Error_Context
cntxt(this, "In named numbers");
2427 u
.namednums
.nvs
->chk_dupl_id();
2428 for (size_t i
= 0; i
< u
.namednums
.nvs
->get_nof_nvs(); i
++) {
2429 NamedValue
*nv
= u
.namednums
.nvs
->get_nv_byIndex(i
);
2430 Value
*value
= nv
->get_value();
2431 Value
*v
= value
->get_value_refd_last();
2432 switch (v
->get_valuetype()) {
2433 case Value::V_INT
: {
2434 const int_val_t
*int_val_int
= v
->get_val_Int();
2435 if (*int_val_int
> INT_MAX
) {
2436 value
->error("Integer value `%s' is too big to be used as a named "
2437 "number", (int_val_int
->t_str()).c_str());
2439 Int int_val
= int_val_int
->get_val();
2440 if (value_map
.has_key(int_val
)) {
2441 value
->error("Duplicate number %s for name `%s'",
2442 Int2string(int_val
).c_str(),
2443 nv
->get_name().get_dispname().c_str());
2444 NamedValue
*nv2
= value_map
[int_val
];
2445 nv2
->note("Number %s is already assigned to name `%s'",
2446 Int2string(int_val
).c_str(),
2447 nv2
->get_name().get_dispname().c_str());
2449 value_map
.add(int_val
, nv
);
2453 case Value::V_ERROR
:
2456 nv
->error("INTEGER value was expected for named number `%s'",
2457 nv
->get_name().get_dispname().c_str());
2464 void Type::chk_Enum_A()
2467 if(!u
.enums
.block
) return;
2469 if(typetype
==T_ERROR
) return;
2470 /* checking enumerations */
2471 map
<Int
, EnumItem
> value_map
;
2472 /* checking values before the ellipsis */
2473 for (size_t i
= 0; i
< u
.enums
.eis1
->get_nof_eis(); i
++)
2474 chk_Enum_item(u
.enums
.eis1
->get_ei_byIndex(i
), false, value_map
);
2475 /* assigning default values */
2476 Int
& first_unused
= u
.enums
.first_unused
;
2477 for (first_unused
= 0; value_map
.has_key(first_unused
); first_unused
++) ;
2478 for (size_t i
= 0; i
< u
.enums
.eis1
->get_nof_eis(); i
++) {
2479 EnumItem
*ei
= u
.enums
.eis1
->get_ei_byIndex(i
);
2480 if (!ei
->get_value()) {
2481 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2482 value_map
.add(first_unused
, ei
);
2483 while (value_map
.has_key(++first_unused
)) ;
2486 /* checking values after the ellipsis */
2488 for(size_t i
=0; i
< u
.enums
.eis2
->get_nof_eis(); i
++)
2489 chk_Enum_item(u
.enums
.eis2
->get_ei_byIndex(i
), true, value_map
);
2491 /* determining the first two unused non-negative integer values
2492 * for code generation */
2493 for (first_unused
= 0; value_map
.has_key(first_unused
); first_unused
++) ;
2494 Int
& second_unused
= u
.enums
.second_unused
;
2495 for (second_unused
= first_unused
+ 1; value_map
.has_key(second_unused
);
2498 u
.enums
.eis1
->release_eis();
2499 delete u
.enums
.eis1
;
2502 u
.enums
.eis2
->release_eis();
2503 delete u
.enums
.eis2
;
2508 void Type::chk_Enum_item(EnumItem
*ei
, bool after_ellipsis
,
2509 map
<Int
, EnumItem
>& value_map
)
2511 const Identifier
& name
= ei
->get_name();
2512 const char *dispname_str
= name
.get_dispname().c_str();
2513 if (u
.enums
.eis
->has_ei_withName(name
)) {
2514 ei
->error("Duplicate ENUMERATED identifier: `%s'", dispname_str
);
2515 u
.enums
.eis
->get_ei_byName(name
)->note("Previous definition of `%s' "
2516 "is here", dispname_str
);
2517 } else if (!name
.get_has_valid(Identifier::ID_TTCN
)) {
2518 ei
->warning("The identifier `%s' is not reachable from TTCN-3",
2521 u
.enums
.eis
->add_ei(ei
);
2522 Int
& first_unused
=u
.enums
.first_unused
;
2523 Value
*value
= ei
->get_value();
2527 Error_Context
cntxt(ei
, "In enumeration `%s'", dispname_str
);
2528 v
= value
->get_value_refd_last();
2530 switch (v
->get_valuetype()) {
2533 case Value::V_ERROR
:
2536 value
->error("INTEGER value was expected for enumeration `%s'",
2540 Int enum_value
= v
->get_val_Int()->get_val();
2541 if (static_cast<Int
>(static_cast<int>(enum_value
)) != enum_value
) {
2542 value
->error("The numeric value of enumeration `%s' (%s) is too "
2543 "large for being represented in memory", dispname_str
,
2544 Int2string(enum_value
).c_str());
2546 if (after_ellipsis
) {
2547 if (enum_value
>= first_unused
) {
2548 value_map
.add(enum_value
, ei
);
2549 for (first_unused
= enum_value
+ 1; value_map
.has_key(first_unused
);
2552 value
->error("ENUMERATED values shall be monotonically growing after "
2553 "the ellipsis: the value of `%s' must be at least %s instead of %s",
2554 dispname_str
, Int2string(first_unused
).c_str(),
2555 Int2string(enum_value
).c_str());
2558 if (value_map
.has_key(enum_value
)) {
2559 value
->error("Duplicate numeric value %s for enumeration `%s'",
2560 Int2string(enum_value
).c_str(), dispname_str
);
2561 EnumItem
*ei2
= value_map
[enum_value
];
2562 ei2
->note("Value %s is already assigned to `%s'",
2563 Int2string(enum_value
).c_str(),
2564 ei2
->get_name().get_dispname().c_str());
2565 } else value_map
.add(enum_value
, ei
);
2567 } else { // the item has no value
2568 if (after_ellipsis
) {
2569 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2570 value_map
.add(first_unused
, ei
);
2571 while (value_map
.has_key(++first_unused
)) ;
2576 void Type::chk_Enum_T()
2579 map
<Int
, EnumItem
> value_map
;
2580 map
<string
, EnumItem
> name_map
;
2581 bool error_flag
= false;
2582 /* checking the uniqueness of identifiers and values */
2583 size_t nof_eis
= u
.enums
.eis
->get_nof_eis();
2584 for(size_t i
= 0; i
< nof_eis
; i
++) {
2585 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
2586 const Identifier
& id
= ei
->get_name();
2587 const string
& name
= id
.get_name();
2588 if (name_map
.has_key(name
)) {
2589 const char *dispname_str
= id
.get_dispname().c_str();
2590 ei
->error("Duplicate enumeration identifier `%s'", dispname_str
);
2591 name_map
[name
]->note("Previous definition of `%s' is here",
2595 name_map
.add(name
, ei
);
2597 Value
*value
= ei
->get_value();
2599 /* Handle the error node created by the parser. */
2600 if (value
->get_valuetype() == Value::V_ERROR
) {
2601 value
->error("INTEGER value was expected for enumeration `%s'",
2602 id
.get_dispname().c_str());
2605 const int_val_t
*enum_value_int
= value
->get_val_Int();
2606 // It used to be the same check.
2607 if (*enum_value_int
> INT_MAX
||
2608 static_cast<Int
>(static_cast<int>(enum_value_int
->get_val()))
2609 != enum_value_int
->get_val()) {
2610 value
->error("The numeric value of enumeration `%s' (%s) is "
2611 "too large for being represented in memory",
2612 id
.get_dispname().c_str(), (enum_value_int
->t_str()).c_str());
2615 Int enum_value
= enum_value_int
->get_val();
2616 if (value_map
.has_key(enum_value
)) {
2617 const char *dispname_str
= id
.get_dispname().c_str();
2618 value
->error("Duplicate numeric value %s for enumeration `%s'",
2619 Int2string(enum_value
).c_str(), dispname_str
);
2620 EnumItem
*ei2
= value_map
[enum_value
];
2621 ei2
->note("Value %s is already assigned to `%s'",
2622 Int2string(enum_value
).c_str(),
2623 ei2
->get_name().get_dispname().c_str());
2626 value_map
.add(enum_value
, ei
);
2633 /* assigning default values */
2634 Int
& first_unused
=u
.enums
.first_unused
;
2635 for(first_unused
=0; value_map
.has_key(first_unused
); first_unused
++) ;
2636 for(size_t i
= 0; i
< nof_eis
; i
++) {
2637 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
2638 if(!ei
->get_value()) {
2639 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2640 value_map
.add(first_unused
, ei
);
2641 while (value_map
.has_key(++first_unused
)) ;
2644 Int
& second_unused
= u
.enums
.second_unused
;
2645 for (second_unused
= first_unused
+ 1; value_map
.has_key(second_unused
);
2652 void Type::chk_BStr_A()
2654 if(!u
.namednums
.block
) return;
2656 if(typetype
==T_ERROR
) return;
2657 if(u
.namednums
.nvs
) {
2658 /* check named bits */
2659 map
<Int
, NamedValue
> value_map
;
2661 Error_Context
cntxt(this, "In named bits");
2662 u
.namednums
.nvs
->chk_dupl_id();
2664 for(size_t i
= 0; i
< u
.namednums
.nvs
->get_nof_nvs(); i
++) {
2665 NamedValue
*nv
= u
.namednums
.nvs
->get_nv_byIndex(i
);
2666 const char *dispname_str
= nv
->get_name().get_dispname().c_str();
2667 Value
*value
= nv
->get_value();
2670 Error_Context
cntxt(this, "In named bit `%s'", dispname_str
);
2671 v
= value
->get_value_refd_last();
2673 switch (v
->get_valuetype()) {
2676 case Value::V_ERROR
:
2679 v
->error("INTEGER value was expected for named bit `%s'",
2683 const int_val_t
*int_val_int
= v
->get_val_Int();
2684 if (*int_val_int
> INT_MAX
) {
2685 value
->error("An INTEGER value less than `%d' was expected for "
2686 "named bit `%s' instead of %s", INT_MAX
, dispname_str
,
2687 (int_val_int
->t_str()).c_str());
2690 Int int_val
= int_val_int
->get_val();
2692 value
->error("A non-negative INTEGER value was expected for named "
2693 "bit `%s' instead of %s", dispname_str
,
2694 Int2string(int_val
).c_str());
2697 if (value_map
.has_key(int_val
)) {
2698 value
->error("Duplicate value %s for named bit `%s'",
2699 Int2string(int_val
).c_str(), dispname_str
);
2700 NamedValue
*nv2
= value_map
[int_val
];
2701 nv2
->note("Bit %s is already assigned to name `%s'",
2702 Int2string(int_val
).c_str(),
2703 nv2
->get_name().get_dispname().c_str());
2704 } else value_map
.add(int_val
, nv
);
2710 void Type::chk_SeCho_T()
2712 u
.secho
.cfm
->set_my_type(this);
2715 u
.secho
.component_internal
= false;
2716 size_t nof_comps
= u
.secho
.cfm
->get_nof_comps();
2717 for (size_t i
=0; i
<nof_comps
; i
++) {
2718 Type
* cft
= u
.secho
.cfm
->get_comp_byIndex(i
)->get_type();
2719 if (cft
&& cft
->is_component_internal()) {
2720 u
.secho
.component_internal
= true;
2726 void Type::chk_Choice_A()
2728 if(u
.secho
.block
) parse_block_Choice();
2729 if(typetype
==T_ERROR
) return;
2731 if(u
.secho
.ctss
->needs_auto_tags())
2732 u
.secho
.ctss
->add_auto_tags();
2733 u
.secho
.ctss
->chk();
2734 if (u
.secho
.ctss
->get_nof_comps() <= 0)
2735 FATAL_ERROR("CHOICE type must have at least one alternative");
2736 u
.secho
.ctss
->chk_tags();
2739 void Type::chk_Se_A()
2741 if(u
.secho
.block
) parse_block_Se();
2742 if(typetype
==T_ERROR
) return;
2745 u
.secho
.ctss
->chk();
2746 u
.secho
.ctss
->chk_tags();
2749 void Type::chk_SeOf()
2751 u
.seof
.ofType
->set_genname(get_genname_own(), string('0'));
2752 u
.seof
.ofType
->set_parent_type(this);
2754 const char *type_name
;
2755 bool asn1
= is_asn1();
2758 type_name
= asn1
? "SEQUENCE OF" : "record of";
2761 type_name
= asn1
? "SET OF" : "set of";
2764 type_name
= "<unknown>";
2767 Error_Context
cntxt(this, "In embedded type of %s", type_name
);
2768 u
.seof
.ofType
->chk();
2769 if (!asn1
) u
.seof
.ofType
->chk_embedded(true, "embedded into another type");
2770 u
.seof
.component_internal
= u
.seof
.ofType
->is_component_internal();
2773 void Type::chk_refd()
2776 ReferenceChain
refch(this, "While checking referenced type");
2777 Type
* t_last
= get_type_refd_last(&refch
);
2778 u
.ref
.component_internal
= t_last
->is_component_internal();
2781 void Type::chk_seltype()
2784 u
.seltype
.type
->set_genname(get_genname_own(), string('0'));
2785 ReferenceChain
refch(this, "In selection type");
2786 get_type_refd_last(&refch
);
2787 if(typetype
==T_ERROR
) return;
2788 u
.seltype
.type
->chk();
2791 void Type::chk_Array()
2793 u
.array
.element_type
->set_genname(get_genname_own(), string('0'));
2794 u
.array
.element_type
->set_parent_type(this);
2797 Error_Context
cntxt(this, "In element type of array");
2798 u
.array
.element_type
->chk();
2799 u
.array
.element_type
->chk_embedded(true, "embedded into an array type");
2801 u
.array
.dimension
->chk();
2802 u
.array
.component_internal
= u
.array
.element_type
->is_component_internal();
2805 void Type::chk_Signature()
2808 u
.signature
.component_internal
= false;
2809 if (u
.signature
.parameters
) {
2810 u
.signature
.parameters
->chk(this);
2811 size_t nof_params
= u
.signature
.parameters
->get_nof_params();
2812 for (size_t i
=0; i
<nof_params
; i
++) {
2813 Type
* spt
= u
.signature
.parameters
->get_param_byIndex(i
)->get_type();
2814 if (spt
&& spt
->is_component_internal()) {
2815 u
.signature
.component_internal
= true;
2820 if (u
.signature
.return_type
) {
2821 Error_Context
cntxt(u
.signature
.return_type
, "In return type");
2822 u
.signature
.return_type
->set_genname(get_genname_own(), string('0'));
2823 u
.signature
.return_type
->set_parent_type(this);
2824 u
.signature
.return_type
->chk();
2825 u
.signature
.return_type
->chk_embedded(false,
2826 "the return type of a signature");
2827 if (!u
.signature
.component_internal
&&
2828 u
.signature
.return_type
->is_component_internal())
2829 u
.signature
.component_internal
= true;
2831 if (u
.signature
.exceptions
) {
2832 u
.signature
.exceptions
->chk(this);
2833 if (!u
.signature
.component_internal
) {
2834 size_t nof_types
= u
.signature
.exceptions
->get_nof_types();
2835 for (size_t i
=0; i
<nof_types
; i
++) {
2836 if (u
.signature
.exceptions
->get_type_byIndex(i
)->
2837 is_component_internal()) {
2838 u
.signature
.component_internal
= true;
2846 void Type::chk_Fat()
2850 Scope
*parlist_scope
= my_scope
;
2851 // the runs on clause must be checked before the formal parameter list
2852 // in order to determine the right scope
2853 if (u
.fatref
.runs_on
.ref
) {
2854 if (typetype
== T_FUNCTION
) u
.fatref
.is_startable
= true;
2855 Error_Context
cntxt2(u
.fatref
.runs_on
.ref
, "In `runs on' clause");
2856 u
.fatref
.runs_on
.type
= u
.fatref
.runs_on
.ref
->chk_comptype_ref();
2857 if(u
.fatref
.runs_on
.type
) {
2858 Ttcn::Module
*my_module
=
2859 dynamic_cast<Ttcn::Module
*>(my_scope
->get_scope_mod());
2860 if (!my_module
) FATAL_ERROR("Type::chk_Fat()");
2861 parlist_scope
= my_module
->get_runs_on_scope(u
.fatref
.runs_on
.type
);
2864 u
.fatref
.fp_list
->set_my_scope(parlist_scope
);
2867 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_FUNCTION
);
2868 u
.fatref
.fp_list
->chk_noLazyParams();
2869 if (u
.fatref
.is_startable
&& !u
.fatref
.fp_list
->get_startability())
2870 u
.fatref
.is_startable
= false;
2871 if (u
.fatref
.return_type
) {
2872 Error_Context
cntxt2(u
.fatref
.return_type
, "In return type");
2873 u
.fatref
.return_type
->chk();
2874 u
.fatref
.return_type
->chk_as_return_type(!u
.fatref
.returns_template
,
2876 if (u
.fatref
.is_startable
&& u
.fatref
.return_type
->get_type_refd_last()
2877 ->get_typetype() == T_DEFAULT
) u
.fatref
.is_startable
= false;
2882 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_ALTSTEP
);
2883 u
.fatref
.fp_list
->chk_noLazyParams();
2886 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_TESTCASE
);
2887 u
.fatref
.fp_list
->chk_noLazyParams();
2888 if (u
.fatref
.system
.ref
) {
2889 Error_Context
cntxt2(u
.fatref
.runs_on
.ref
, "In `system' clause");
2890 u
.fatref
.system
.type
= u
.fatref
.system
.ref
->chk_comptype_ref();
2894 FATAL_ERROR("Type::chk_Fat()");
2896 if (!semantic_check_only
)
2897 u
.fatref
.fp_list
->set_genname(get_genname_own());
2900 void Type::chk_address()
2902 Type
*t
= get_type_refd_last();
2903 switch (t
->typetype
) {
2905 error("Port type `%s' cannot be the address type",
2906 t
->get_typename().c_str());
2909 error("Component type `%s' cannot be the address type",
2910 t
->get_typename().c_str());
2913 error("Signature `%s' cannot be the address type",
2914 t
->get_typename().c_str());
2917 error("Default type cannot be the address type");
2920 error("TTCN-3 anytype cannot be the address type");
2928 void Type::chk_embedded(bool default_allowed
, const char *error_msg
)
2930 Type
*t
=get_type_refd_last();
2931 switch (t
->typetype
) {
2933 error("Port type `%s' cannot be %s", t
->get_typename().c_str(),
2937 error("Signature `%s' cannot be %s", t
->get_typename().c_str(),
2941 if (!default_allowed
) error("Default type cannot be %s", error_msg
);
2948 void Type::chk_recursions(ReferenceChain
& refch
)
2950 if (recurs_checked
) return;
2953 if (!refch
.add(t
->get_fullname())) {
2954 // an error has been found (and reported by refch.add)
2955 recurs_checked
= true;
2958 if (!t
->is_ref()) break;
2959 t
= t
->get_type_refd();
2961 switch (t
->typetype
) {
2966 for(size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
2967 CompField
*cf
= t
->get_comp_byIndex(i
);
2968 if(!cf
->get_is_optional()) {
2970 cf
->get_type()->chk_recursions(refch
);
2973 // an optional field can "stop" the recursion
2978 refch
.set_error_reporting(false);
2979 refch
.mark_error_state();
2980 for (size_t i
= 0; i
< t
->get_nof_comps(); ++i
) {
2982 CompField
* cf
= t
->get_comp_byIndex(i
);
2983 cf
->get_type()->chk_recursions(refch
);
2987 if (refch
.nof_errors() == t
->get_nof_comps()) {
2988 refch
.report_errors();
2991 refch
.prev_error_state();
2992 refch
.set_error_reporting(true);
2997 if(t
->get_nof_comps()==1)
2998 t
->get_comp_byIndex(0)->get_type()->chk_recursions(refch
);
3001 t
->get_ofType()->chk_recursions(refch
);
3006 recurs_checked
= true;
3009 void Type::chk_constructor_name(const Identifier
& p_id
)
3019 // T_ANYTYPE can not have a field of type anytype, no need to check.
3020 if (has_comp_withName(p_id
)) {
3021 // HL26011: a field has the same name as the typedef.
3022 // Titan can't generate valid C++ code; better report an error.
3023 get_comp_byName(p_id
)->error("Field name clashes with type name");
3026 default: // can't have fields
3031 bool Type::chk_startability()
3033 if(typetype
!= T_FUNCTION
) FATAL_ERROR("Type::chk_startable()");
3034 if(!checked
) chk_Fat();
3035 if(u
.fatref
.is_startable
) return true;
3036 if (!u
.fatref
.runs_on
.ref
) error("Functions of type `%s' cannot be started "
3037 "on a parallel test component because the type does not have `runs on' "
3038 "clause", get_typename().c_str());
3039 u
.fatref
.fp_list
->chk_startability("Functions of type",
3040 get_typename().c_str());
3041 if (u
.fatref
.return_type
&& u
.fatref
.return_type
->is_component_internal()) {
3042 map
<Type
*,void> type_chain
;
3043 char* err_str
= mprintf("the return type or embedded in the return type "
3044 "of function type `%s' if it is started on a parallel test component",
3045 get_typename().c_str());
3046 u
.fatref
.return_type
->chk_component_internal(type_chain
, err_str
);
3052 void Type::chk_as_return_type(bool as_value
, const char* what
)
3054 Type
*t
= get_type_refd_last();
3055 switch(t
->get_typetype()) {
3057 error("Port type `%s' cannot be the return type of a %s"
3058 , t
->get_fullname().c_str(), what
);
3060 case Type::T_SIGNATURE
:
3061 if(as_value
) error("A value of signature `%s' cannot be the "
3062 "return type of a %s", t
->get_fullname().c_str(), what
);
3069 void Type::chk_this_value_ref(Value
*value
)
3071 switch (value
->get_valuetype()) {
3072 case Value::V_UNDEF_LOWERID
:
3075 if(value
->is_asn1()) {
3078 && u
.namednums
.nvs
->has_nv_withName(*value
->get_val_id())) {
3079 value
->set_valuetype(Value::V_NAMEDINT
);
3080 value
->set_my_governor(this);
3087 if (has_ei_withName(*value
->get_val_id())) {
3088 value
->set_valuetype(Value::V_ENUM
);
3089 value
->set_my_governor(this);
3097 get_type_refd()->chk_this_value_ref(value
);
3102 /* default behavior: interpret as reference */
3103 value
->set_valuetype(Value::V_REFD
);
3110 bool Type::chk_this_value(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3111 namedbool incomplete_allowed
, namedbool omit_allowed
,
3112 namedbool sub_chk
, namedbool implicit_omit
, namedbool is_str_elem
)
3114 bool self_ref
= false;
3116 Value
*v_last
= value
->get_value_refd_last(0, expected_value
);
3117 if (v_last
->get_valuetype() == Value::V_OMIT
) {
3118 if (!omit_allowed
) {
3119 value
->error("`omit' value is not allowed in this context");
3120 value
->set_valuetype(Value::V_ERROR
);
3125 switch (value
->get_valuetype()) {
3126 case Value::V_ERROR
:
3129 return chk_this_refd_value(value
, lhs
, expected_value
, 0, is_str_elem
);
3130 case Value::V_INVOKE
:
3131 chk_this_invoked_value(value
, lhs
, expected_value
);
3132 return false; // assumes no self-ref in invoke
3134 if (lhs
) self_ref
= value
->chk_expr_self_ref(lhs
);
3136 case Value::V_MACRO
:
3137 if (value
->is_unfoldable(0, expected_value
)) {
3138 typetype_t tt
= value
->get_expr_returntype(expected_value
);
3139 if (!is_compatible_tt(tt
, value
->is_asn1())) {
3140 value
->error("Incompatible value: `%s' value was expected",
3141 get_typename().c_str());
3142 value
->set_valuetype(Value::V_ERROR
);
3155 chk_this_value_Null(value
);
3158 chk_this_value_Bool(value
);
3161 chk_this_value_Int(value
);
3164 chk_this_value_Int_A(value
);
3167 chk_this_value_Real(value
);
3171 chk_this_value_Enum(value
);
3174 chk_this_value_BStr(value
);
3177 chk_this_value_BStr_A(value
);
3180 chk_this_value_HStr(value
);
3183 chk_this_value_OStr(value
);
3188 case T_NUMERICSTRING
:
3189 case T_PRINTABLESTRING
:
3190 case T_TELETEXSTRING
:
3191 case T_VIDEOTEXSTRING
:
3193 case T_GRAPHICSTRING
:
3194 case T_VISIBLESTRING
:
3195 case T_GENERALSTRING
:
3196 case T_UNIVERSALSTRING
:
3199 case T_GENERALIZEDTIME
:
3200 case T_OBJECTDESCRIPTOR
:
3201 chk_this_value_CStr(value
);
3204 chk_this_value_OID(value
);
3207 chk_this_value_ROID(value
);
3210 chk_this_value_Any(value
);
3216 self_ref
= chk_this_value_Choice(value
, lhs
, expected_value
, incomplete_allowed
,
3223 self_ref
= chk_this_value_Se(value
, lhs
, expected_value
, incomplete_allowed
,
3228 self_ref
= chk_this_value_SeOf(value
, lhs
, expected_value
, incomplete_allowed
,
3232 self_ref
= get_type_refd()->chk_this_value(value
, lhs
, expected_value
,
3233 incomplete_allowed
, omit_allowed
, NO_SUB_CHK
, implicit_omit
, is_str_elem
);
3235 case T_UNRESTRICTEDSTRING
:
3238 case T_EMBEDDED_PDV
:
3242 self_ref
= get_type_refd()->chk_this_value(value
, lhs
, expected_value
,
3243 incomplete_allowed
, omit_allowed
, NO_SUB_CHK
, NOT_IMPLICIT_OMIT
, is_str_elem
);
3246 chk_this_value_Verdict(value
);
3249 chk_this_value_Default(value
);
3252 self_ref
= chk_this_value_Array(value
, lhs
, expected_value
, incomplete_allowed
, implicit_omit
);
3255 // Remain silent. The error has already been reported in the definition
3256 // that the value belongs to.
3259 self_ref
= chk_this_value_Signature(value
, lhs
, expected_value
, incomplete_allowed
);
3262 chk_this_value_Component(value
);
3267 chk_this_value_FAT(value
);
3270 FATAL_ERROR("Type::chk_this_value()");
3273 // check value against subtype
3274 if(sub_chk
&& (sub_type
!=NULL
)) sub_type
->chk_this_value(value
);
3279 bool Type::chk_this_refd_value(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3280 ReferenceChain
* refch
, namedbool str_elem
)
3282 Reference
*ref
= value
->get_reference();
3283 Assignment
*ass
= ref
->get_refd_assignment();
3285 value
->set_valuetype(Value::V_ERROR
);
3290 bool self_ref
= (ass
== lhs
);
3292 // Exit immediately in case of infinite recursion.
3293 if (value
->get_valuetype() != Value::V_REFD
) return self_ref
;
3294 bool is_const
= false, error_flag
= false, chk_runs_on
= false;
3295 Type
*governor
= NULL
;
3296 switch (ass
->get_asstype()) {
3297 case Assignment::A_ERROR
:
3298 value
->set_valuetype(Value::V_ERROR
);
3300 case Assignment::A_CONST
:
3303 case Assignment::A_OBJECT
:
3304 case Assignment::A_OS
: {
3305 Setting
*setting
= ref
->get_refd_setting();
3306 if (!setting
|| setting
->get_st() == Setting::S_ERROR
) {
3307 value
->set_valuetype(Value::V_ERROR
);
3310 if (setting
->get_st() != Setting::S_V
) {
3311 ref
->error("This InformationFromObjects construct does not refer to "
3312 "a value: `%s'", value
->get_fullname().c_str());
3313 value
->set_valuetype(Value::V_ERROR
);
3316 governor
= dynamic_cast<Value
*>(setting
)->get_my_governor();
3317 if (!governor
) FATAL_ERROR("Type::chk_this_refd_value()");
3320 case Assignment::A_MODULEPAR
:
3324 case Assignment::A_EXT_CONST
:
3325 if (expected_value
== EXPECTED_CONSTANT
) {
3326 value
->error("Reference to an (evaluable) constant value was "
3327 "expected instead of %s",
3328 ass
->get_description().c_str());
3332 case Assignment::A_VAR
:
3333 case Assignment::A_PAR_VAL
:
3334 case Assignment::A_PAR_VAL_IN
:
3335 case Assignment::A_PAR_VAL_OUT
:
3336 case Assignment::A_PAR_VAL_INOUT
:
3337 switch (expected_value
) {
3338 case EXPECTED_CONSTANT
:
3339 value
->error("Reference to a constant value was expected instead of "
3340 "%s", ass
->get_description().c_str());
3343 case EXPECTED_STATIC_VALUE
:
3344 value
->error("Reference to a static value was expected instead of %s",
3345 ass
->get_description().c_str());
3352 case Assignment::A_MODULEPAR_TEMP
:
3353 case Assignment::A_TEMPLATE
:
3354 case Assignment::A_VAR_TEMPLATE
:
3355 case Assignment::A_PAR_TEMPL_IN
:
3356 case Assignment::A_PAR_TEMPL_OUT
:
3357 case Assignment::A_PAR_TEMPL_INOUT
:
3358 if (expected_value
!= EXPECTED_TEMPLATE
) {
3359 value
->error("Reference to a value was expected instead of %s",
3360 ass
->get_description().c_str());
3364 case Assignment::A_FUNCTION_RVAL
:
3367 case Assignment::A_EXT_FUNCTION_RVAL
:
3368 switch (expected_value
) {
3369 case EXPECTED_CONSTANT
:
3370 value
->error("Reference to a constant value was expected instead of "
3371 "the return value of %s",
3372 ass
->get_description().c_str());
3375 case EXPECTED_STATIC_VALUE
:
3376 value
->error("Reference to a static value was expected instead of "
3377 "the return value of %s",
3378 ass
->get_description().c_str());
3385 case Assignment::A_FUNCTION_RTEMP
:
3388 case Assignment::A_EXT_FUNCTION_RTEMP
:
3389 if (expected_value
!= EXPECTED_TEMPLATE
) {
3390 value
->error("Reference to a value was expected instead of a call of "
3391 "%s, which returns a template",
3392 ass
->get_description().c_str());
3396 case Assignment::A_FUNCTION
:
3397 case Assignment::A_EXT_FUNCTION
:
3398 value
->error("Reference to a %s was expected instead of a call of %s, "
3399 "which does not have return type",
3400 expected_value
== EXPECTED_TEMPLATE
3401 ? "value or template" : "value",
3402 ass
->get_description().c_str());
3403 value
->set_valuetype(Value::V_ERROR
);
3406 value
->error("Reference to a %s was expected instead of %s",
3407 expected_value
== EXPECTED_TEMPLATE
3408 ? "value or template" : "value",
3409 ass
->get_description().c_str());
3410 value
->set_valuetype(Value::V_ERROR
);
3412 } // switch ass->get_asstype()
3414 ref
->get_my_scope()->chk_runs_on_clause(ass
, *ref
, "call");
3416 governor
= ass
->get_Type()->get_field_type(ref
->get_subrefs(),
3419 value
->set_valuetype(Value::V_ERROR
);
3422 TypeCompatInfo
info(value
->get_my_scope()->get_scope_mod(), this,
3423 governor
, true, false);
3424 info
.set_str1_elem(str_elem
);
3425 if (ref
->get_subrefs()) info
.set_str2_elem(ref
->get_subrefs()->refers_to_string_element());
3428 if (!is_compatible(governor
, &info
, &l_chain
, &r_chain
)) {
3429 // Port or signature values do not exist at all. These errors are
3430 // already reported at those definitions. Extra errors should not be
3432 Type
*t
= get_type_refd_last();
3433 switch (t
->typetype
) {
3435 // Neither port values nor templates exist.
3438 // Only signature templates may exist.
3439 if (expected_value
== EXPECTED_TEMPLATE
)
3440 value
->error("Type mismatch: a signature template of type `%s' was "
3441 "expected instead of `%s'", get_typename().c_str(),
3442 governor
->get_typename().c_str());
3445 if (info
.is_subtype_error()) {
3446 value
->error("%s", info
.get_subtype_error().c_str());
3447 } else if (!info
.is_erroneous()) {
3448 value
->error("Type mismatch: a %s of type `%s' was expected "
3449 "instead of `%s'", expected_value
== EXPECTED_TEMPLATE
3450 ? "value or template" : "value",
3451 get_typename().c_str(),
3452 governor
->get_typename().c_str());
3454 // The semantic error was found by the new code. It was better to
3455 // do the assembly inside TypeCompatInfo.
3456 value
->error("%s", info
.get_error_str_str().c_str());
3462 if (info
.needs_conversion()) value
->set_needs_conversion();
3466 value
->set_valuetype(Value::V_ERROR
);
3469 // Checking for circular references.
3470 Value
*v_last
= value
->get_value_refd_last(refch
, expected_value
);
3471 if (is_const
&& v_last
->get_valuetype() != Value::V_ERROR
) {
3472 // If a referenced universal charstring value points to a literal
3473 // charstring then drop the reference and create a literal ustring to
3474 // avoid run-time conversion.
3475 if (v_last
->get_valuetype() == Value::V_CSTR
3476 && get_typetype_ttcn3(get_type_refd_last()->typetype
) == T_USTR
)
3477 value
->set_valuetype(Value::V_USTR
);
3478 // Check v_last against the subtype constraints.
3479 if (sub_type
!=NULL
) sub_type
->chk_this_value(value
);
3485 void Type::chk_this_invoked_value(Value
*value
, Common::Assignment
*,
3486 expected_value_t expected_value
)
3488 value
->get_value_refd_last(NULL
, expected_value
);
3489 if (value
->get_valuetype() == Value::V_ERROR
) return;
3490 Type
*invoked_t
= value
->get_invoked_type(expected_value
);
3491 if (invoked_t
->get_typetype() == T_ERROR
) return;
3492 invoked_t
= invoked_t
->get_type_refd_last();
3494 switch (invoked_t
->get_typetype()) {
3495 case Type::T_FUNCTION
:
3496 t
= invoked_t
->get_function_return_type();
3499 FATAL_ERROR("Type::chk_this_invoked_value()");
3503 value
->error("The type `%s' has no return type, `%s' expected",
3504 invoked_t
->get_typename().c_str(), get_typename().c_str());
3505 else if (!is_compatible(t
, NULL
)) {
3506 value
->error("Incompatible value: `%s' value was expected",
3507 get_typename().c_str());
3511 void Type::chk_this_value_Null(Value
*value
)
3513 Value
*v
=value
->get_value_refd_last();
3514 switch(v
->get_valuetype()) {
3518 value
->error("NULL value was expected");
3519 value
->set_valuetype(Value::V_ERROR
);
3524 void Type::chk_this_value_Bool(Value
*value
)
3526 Value
*v
=value
->get_value_refd_last();
3527 switch(v
->get_valuetype()) {
3531 value
->error("%s value was expected",
3532 value
->is_asn1() ? "BOOLEAN" : "boolean");
3533 value
->set_valuetype(Value::V_ERROR
);
3538 void Type::chk_this_value_Int(Value
*value
)
3540 Value
*v
=value
->get_value_refd_last();
3541 switch(v
->get_valuetype()) {
3545 value
->error("integer value was expected");
3546 value
->set_valuetype(Value::V_ERROR
);
3552 void Type::chk_this_value_Int_A(Value
*value
)
3554 Value
*v
=value
->get_value_refd_last();
3555 switch(v
->get_valuetype()) {
3558 case Value::V_NAMEDINT
:
3559 if(!u
.namednums
.nvs
)
3560 FATAL_ERROR("Type::chk_this_value_Int_A()");
3562 (Value::V_INT
, u
.namednums
.nvs
->
3563 get_nv_byName(*v
->get_val_id())->get_value()->get_val_Int()->get_val());
3566 value
->error("INTEGER value was expected");
3567 value
->set_valuetype(Value::V_ERROR
);
3572 void Type::chk_this_value_Real(Value
*value
)
3574 Value
*v
= value
->get_value_refd_last();
3575 if (value
->is_asn1()) {
3576 if (value
->is_ref()) {
3577 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3578 if (t
->get_typetype() != T_REAL
) {
3579 value
->error("REAL value was expected");
3580 value
->set_valuetype(Value::V_ERROR
);
3584 switch (v
->get_valuetype()) {
3587 case Value::V_UNDEF_BLOCK
:{
3588 v
->set_valuetype(Value::V_SEQ
);
3589 Identifier
t_id(Identifier::ID_ASN
, string("REAL"));
3590 bool self_ref
= get_my_scope()->get_scope_asss()->get_local_ass_byId(t_id
)
3591 ->get_Type()->chk_this_value(v
, 0, EXPECTED_CONSTANT
, INCOMPLETE_NOT_ALLOWED
,
3592 OMIT_NOT_ALLOWED
, SUB_CHK
);
3594 v
->set_valuetype(Value::V_REAL
);
3597 v
->set_valuetype(Value::V_REAL
);
3600 value
->error("REAL value was expected");
3601 value
->set_valuetype(Value::V_ERROR
);
3605 switch(v
->get_valuetype()) {
3609 value
->error("float value was expected");
3610 value
->set_valuetype(Value::V_ERROR
);
3616 void Type::chk_this_value_Enum(Value
*value
)
3618 switch(value
->get_valuetype()) {
3622 value
->error("%s value was expected",
3623 value
->is_asn1() ? "ENUMERATED" : "enumerated");
3624 value
->set_valuetype(Value::V_ERROR
);
3629 void Type::chk_this_value_BStr(Value
*value
)
3631 Value
*v
= value
->get_value_refd_last();
3632 switch(v
->get_valuetype()) {
3636 value
->error("bitstring value was expected");
3637 value
->set_valuetype(Value::V_ERROR
);
3642 void Type::chk_this_value_namedbits(Value
*value
)
3644 if (!value
) FATAL_ERROR("Type::chk_this_value_namedbits()");
3645 value
->set_valuetype(Value::V_NAMEDBITS
);
3646 if(!u
.namednums
.nvs
) {
3647 value
->error("No named bits are defined in type `%s'",
3648 get_typename().c_str());
3649 value
->set_valuetype(Value::V_ERROR
);
3652 string
*bstring
= new string("");
3653 for(size_t i
=0; i
< value
->get_nof_ids(); i
++) {
3654 Identifier
*id
= value
->get_id_byIndex(i
);
3655 if(!u
.namednums
.nvs
->has_nv_withName(*id
)) {
3657 error("No named bit with name `%s' is defined in type `%s'",
3658 id
->get_dispname().c_str(), get_typename().c_str());
3659 value
->set_valuetype(Value::V_ERROR
);
3662 size_t bitnum
= static_cast<size_t>
3663 (u
.namednums
.nvs
->get_nv_byName(*id
)->get_value()->get_val_Int()
3665 if(bstring
->size() < bitnum
+ 1) bstring
->resize(bitnum
+ 1, '0');
3666 (*bstring
)[bitnum
] = '1';
3668 value
->set_valuetype(Value::V_BSTR
, bstring
);
3671 void Type::chk_this_value_BStr_A(Value
*value
)
3673 Value
*v
= value
->get_value_refd_last();
3674 if (value
->is_asn1()) {
3675 if(value
->is_ref()) {
3676 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3677 if(t
->get_typetype()!=T_BSTR_A
&& t
->get_typetype()!=T_BSTR
) {
3678 value
->error("(reference to) BIT STRING value was expected");
3679 value
->set_valuetype(Value::V_ERROR
);
3683 switch(v
->get_valuetype()) {
3687 if (v
!= value
) FATAL_ERROR("Common::Type::chk_this_value_BStr_A()");
3688 v
->set_valuetype(Value::V_BSTR
);
3690 case Value::V_UNDEF_BLOCK
:
3691 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_BStr_A()");
3692 chk_this_value_namedbits(v
);
3695 value
->error("BIT STRING value was expected");
3696 value
->set_valuetype(Value::V_ERROR
);
3700 switch(v
->get_valuetype()) {
3704 value
->error("bitstring value was expected");
3705 value
->set_valuetype(Value::V_ERROR
);
3711 void Type::chk_this_value_HStr(Value
*value
)
3713 Value
*v
= value
->get_value_refd_last();
3714 switch (v
->get_valuetype()) {
3718 value
->error("hexstring value was expected");
3719 value
->set_valuetype(Value::V_ERROR
);
3724 void Type::chk_this_value_OStr(Value
*value
)
3726 Value
*v
= value
->get_value_refd_last();
3727 if (value
->is_asn1()) {
3728 if (value
->is_ref()) {
3729 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3730 if(t
->get_typetype() != T_OSTR
) {
3731 value
->error("(reference to) OCTET STRING value was expected");
3732 value
->set_valuetype(Value::V_ERROR
);
3736 switch(v
->get_valuetype()) {
3741 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_OStr()");
3742 v
->set_valuetype(Value::V_OSTR
);
3745 value
->error("OCTET STRING value was expected");
3746 value
->set_valuetype(Value::V_ERROR
);
3750 switch(v
->get_valuetype()) {
3754 value
->error("octetstring value was expected");
3755 value
->set_valuetype(Value::V_ERROR
);
3761 /** \todo enhance */
3762 void Type::chk_this_value_CStr(Value
*value
)
3765 switch(value
->get_valuetype()) {
3766 case Value::V_UNDEF_BLOCK
:
3767 value
->set_valuetype(Value::V_CHARSYMS
);
3768 if (value
->get_valuetype() == Value::V_ERROR
) return;
3770 case Value::V_CHARSYMS
:
3775 case T_UNIVERSALSTRING
:
3776 value
->set_valuetype(Value::V_USTR
);
3778 case T_TELETEXSTRING
:
3779 case T_VIDEOTEXSTRING
:
3780 case T_GRAPHICSTRING
:
3781 case T_OBJECTDESCRIPTOR
:
3782 case T_GENERALSTRING
:
3783 value
->set_valuetype(Value::V_ISO2022STR
);
3786 case T_NUMERICSTRING
:
3787 case T_PRINTABLESTRING
:
3789 case T_VISIBLESTRING
:
3791 case T_GENERALIZEDTIME
:
3792 value
->set_valuetype(Value::V_CSTR
);
3795 FATAL_ERROR("chk_this_value_CStr()");
3803 case T_UNIVERSALSTRING
:
3805 case T_TELETEXSTRING
:
3806 case T_VIDEOTEXSTRING
:
3807 case T_GRAPHICSTRING
:
3808 case T_OBJECTDESCRIPTOR
:
3809 case T_GENERALSTRING
:
3812 if(value->get_val_ustr().is_cstr()) {
3813 value->warning("ISO-2022 string value was expected (converting"
3814 " simple ISO-10646 string).");
3815 value->set_valuetype(Value::V_CSTR);
3818 value->error("ISO-2022 string value was expected (instead of"
3819 " ISO-10646 string).");
3820 value->set_valuetype(Value::V_ERROR);
3825 case T_NUMERICSTRING
:
3826 case T_PRINTABLESTRING
:
3828 case T_VISIBLESTRING
:
3830 case T_GENERALIZEDTIME
:
3831 value
->set_valuetype(Value::V_CSTR
);
3834 FATAL_ERROR("Type::chk_this_value_CStr()");
3842 case T_UNIVERSALSTRING
:
3843 value
->set_valuetype(Value::V_USTR
);
3845 case T_TELETEXSTRING
:
3846 case T_VIDEOTEXSTRING
:
3847 case T_GRAPHICSTRING
:
3848 case T_OBJECTDESCRIPTOR
:
3849 case T_GENERALSTRING
:
3850 value
->set_valuetype(Value::V_ISO2022STR
);
3853 case T_NUMERICSTRING
:
3854 case T_PRINTABLESTRING
:
3856 case T_VISIBLESTRING
:
3858 case T_GENERALIZEDTIME
:
3861 FATAL_ERROR("chk_this_value_CStr()");
3864 case Value::V_ISO2022STR
:
3869 case T_UNIVERSALSTRING
:
3870 value
->error("ISO-10646 string value was expected (instead of"
3871 " ISO-2022 string).");
3872 value
->set_valuetype(Value::V_ERROR
);
3874 case T_TELETEXSTRING
:
3875 case T_VIDEOTEXSTRING
:
3876 case T_GRAPHICSTRING
:
3877 case T_OBJECTDESCRIPTOR
:
3878 case T_GENERALSTRING
:
3881 case T_NUMERICSTRING
:
3882 case T_PRINTABLESTRING
:
3884 case T_VISIBLESTRING
:
3886 case T_GENERALIZEDTIME
:
3887 value
->set_valuetype(Value::V_ISO2022STR
);
3890 FATAL_ERROR("chk_this_value_CStr()");
3894 value
->error("character string value was expected");
3895 value
->set_valuetype(Value::V_ERROR
);
3900 void Type::chk_this_value_OID(Value
*value
)
3902 Value
*v
= value
->get_value_refd_last();
3903 if (value
->is_asn1()) {
3904 if (value
->is_ref()) {
3905 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3906 if (t
->get_typetype() != T_OID
) {
3907 value
->error("(reference to) OBJECT IDENTIFIER value was "
3909 value
->set_valuetype(Value::V_ERROR
);
3913 switch (v
->get_valuetype()) {
3916 case Value::V_UNDEF_BLOCK
:
3917 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_OID()");
3918 v
->set_valuetype(Value::V_OID
);
3922 value
->error("OBJECT IDENTIFIER value was expected");
3923 value
->set_valuetype(Value::V_ERROR
);
3927 switch (v
->get_valuetype()) {
3932 value
->error("objid value was expected");
3933 value
->set_valuetype(Value::V_ERROR
);
3939 void Type::chk_this_value_ROID(Value
*value
)
3941 Value
*v
= value
->get_value_refd_last();
3942 if(value
->is_ref()) {
3943 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3944 if (t
->get_typetype() != T_ROID
) {
3945 value
->error("(reference to) RELATIVE-OID value was expected");
3946 value
->set_valuetype(Value::V_ERROR
);
3950 switch(v
->get_valuetype()) {
3953 case Value::V_UNDEF_BLOCK
:
3954 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_ROID()");
3955 v
->set_valuetype(Value::V_ROID
);
3959 value
->error("RELATIVE-OID value was expected");
3960 value
->set_valuetype(Value::V_ERROR
);
3965 void Type::chk_this_value_Any(Value
*value
)
3967 Value
*v
= value
->get_value_refd_last();
3968 if (value
->is_asn1()) {
3969 if (value
->is_ref()) {
3970 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3971 if(t
->get_typetype()!=T_ANY
&& t
->get_typetype()!=T_OSTR
) {
3972 value
->error("(reference to) OCTET STRING or ANY type value"
3974 value
->set_valuetype(Value::V_ERROR
);
3978 switch(v
->get_valuetype()) {
3982 if (v
!=value
) FATAL_ERROR("Type::chk_this_value_Any()");
3983 v
->set_valuetype(Value::V_OSTR
);
3986 value
->error("ANY (OCTET STRING) value was expected");
3987 value
->set_valuetype(Value::V_ERROR
);
3992 switch(v
->get_valuetype()) {
3996 value
->error("octetstring value was expected for ASN ANY type");
3997 value
->set_valuetype(Value::V_ERROR
);
4003 /** Return a string containing the names of existing fields (components).
4005 * @param t a Type object
4006 * @return a string (l-value, temporary)
4007 * @pre t must be a sequence, choice, set, anytype, open type
4009 static string
actual_fields(Type
& t
) // alas, not even get_nof_comps() is const
4011 static const string
has_no(" has no ");
4012 size_t ncomps
= t
.get_nof_comps();
4013 const string
fields_or_comps(t
.is_asn1() ? "components" : "fields");
4015 string
msg("Valid ");
4016 msg
+= fields_or_comps
;
4018 msg
+= t
.get_comp_byIndex(0)->get_name().get_dispname();
4019 for (size_t ci
=1; ci
< ncomps
; ++ci
) {
4021 msg
+= t
.get_comp_byIndex(ci
)->get_name().get_dispname();
4025 else return t
.get_fullname() + has_no
+ fields_or_comps
;
4029 bool Type::chk_this_value_Choice(Value
*value
, Common::Assignment
*lhs
,
4030 expected_value_t expected_value
, namedbool incomplete_allowed
, namedbool implicit_omit
)
4032 bool self_ref
= false;
4033 switch(value
->get_valuetype()) {
4035 if (value
->is_asn1()) {
4036 value
->error("CHOICE value was expected for type `%s'",
4037 get_fullname().c_str());
4038 value
->set_valuetype(Value::V_ERROR
);
4041 // the valuetype can be ERROR if the value has no fields at all
4042 if (value
->get_valuetype() == Value::V_ERROR
) return false;
4043 // The value notation for TTCN record/union types
4044 // cannot be distinguished during parsing. Now we know it's a union.
4045 value
->set_valuetype(Value::V_CHOICE
);
4048 case Value::V_CHOICE
: {
4049 if (!value
->is_asn1() && typetype
== T_OPENTYPE
) {
4050 // allow the alternatives of open types as both lower and upper identifiers
4051 value
->set_alt_name_to_lowercase();
4053 const Identifier
& alt_name
= value
->get_alt_name();
4054 if(!has_comp_withName(alt_name
)) {
4055 if (value
->is_asn1()) {
4056 value
->error("Reference to non-existent alternative `%s' in CHOICE"
4057 " value for type `%s'",
4058 alt_name
.get_dispname().c_str(),
4059 get_fullname().c_str());
4061 value
->error("Reference to non-existent field `%s' in union "
4062 "value for type `%s'",
4063 alt_name
.get_dispname().c_str(),
4064 get_fullname().c_str());
4066 value
->set_valuetype(Value::V_ERROR
);
4067 value
->note("%s", actual_fields(*this).c_str());
4070 Type
*alt_type
= get_comp_byName(alt_name
)->get_type();
4071 Value
*alt_value
= value
->get_alt_value();
4072 Error_Context
cntxt(value
, "In value for %s `%s'",
4073 value
->is_asn1() ? "alternative" : "union field",
4074 alt_name
.get_dispname().c_str());
4075 alt_value
->set_my_governor(alt_type
);
4076 alt_type
->chk_this_value_ref(alt_value
);
4077 self_ref
|= alt_type
->chk_this_value(alt_value
, lhs
, expected_value
,
4078 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4079 if (alt_value
->get_valuetype() == Value::V_NOTUSED
) {
4080 value
->set_valuetype(Value::V_NOTUSED
);
4084 value
->error("%s value was expected for type `%s'",
4085 value
->is_asn1() ? "CHOICE" : "union",
4086 get_fullname().c_str());
4087 value
->set_valuetype(Value::V_ERROR
);
4093 bool Type::chk_this_value_Se(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4094 namedbool incomplete_allowed
, namedbool implicit_omit
)
4096 if (value
->is_asn1())
4097 return chk_this_value_Se_A(value
, lhs
, expected_value
, implicit_omit
);
4099 return chk_this_value_Se_T(value
, lhs
, expected_value
, incomplete_allowed
,
4103 bool Type::chk_this_value_Se_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4104 namedbool incomplete_allowed
, namedbool implicit_omit
)
4106 switch (value
->get_valuetype()) {
4108 if (typetype
== T_SET_A
|| typetype
== T_SET_T
) {
4109 value
->set_valuetype(Value::V_SET
);
4110 return chk_this_value_Set_T(value
, lhs
, expected_value
, incomplete_allowed
,
4113 return chk_this_value_Seq_T(value
, lhs
, expected_value
, incomplete_allowed
,
4117 case Value::V_SEQOF
:
4118 if (typetype
== T_SET_A
|| typetype
== T_SET_T
) {
4119 if (value
->get_nof_comps() == 0) {
4120 if (get_nof_comps() == 0) {
4121 value
->set_valuetype(Value::V_SET
);
4123 value
->error("A non-empty set value was expected for type `%s'",
4124 get_fullname().c_str());
4125 value
->set_valuetype(Value::V_ERROR
);
4128 // This will catch the indexed assignment notation as well.
4129 value
->error("Value list notation cannot be used for "
4130 "%s type `%s'", typetype
== T_SET_A
? "SET" : "set",
4131 get_fullname().c_str());
4132 value
->set_valuetype(Value::V_ERROR
);
4135 if (value
->is_indexed()) {
4136 value
->error("Indexed assignment notation cannot be used for %s "
4137 "type `%s'", typetype
== T_SEQ_A
4138 ? "SEQUENCE" : "record",
4139 get_fullname().c_str());
4140 value
->set_valuetype(Value::V_ERROR
);
4142 value
->set_valuetype(Value::V_SEQ
);
4143 return chk_this_value_Seq_T(value
, lhs
, expected_value
, incomplete_allowed
,
4149 value
->error("%s value was expected for type `%s'",
4150 typetype
== T_SEQ_T
? "Record" : "Set",
4151 get_fullname().c_str());
4152 value
->set_valuetype(Value::V_ERROR
);
4158 bool Type::chk_this_value_Seq_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4159 namedbool incomplete_allowed
, namedbool implicit_omit
)
4161 bool self_ref
= false;
4162 map
<string
, NamedValue
> comp_map
;
4163 // it is set to false if we have lost the ordering
4164 bool in_synch
= true;
4165 const size_t n_type_comps
= get_nof_comps();
4166 size_t n_value_comps
= value
->get_nof_comps();
4167 // for incomplete values
4168 CompField
*last_cf
= 0;
4169 size_t next_index
= 0;
4170 size_t seq_index
= 0;
4171 bool is_empty
= n_type_comps
> 0; // don't do this check if the record type has no fields
4172 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++, seq_index
++) {
4173 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4174 const Identifier
& value_id
= nv
->get_name();
4175 const string
& value_name
= value_id
.get_name();
4176 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4177 if (!has_comp_withName(value_id
)) {
4178 nv
->error("Reference to non-existent field `%s' in record value for "
4179 "type `%s'", value_dispname_str
, get_typename().c_str());
4180 nv
->note("%s", actual_fields(*this).c_str());
4183 } else if (comp_map
.has_key(value_name
)) {
4184 nv
->error("Duplicate record field `%s'", value_dispname_str
);
4185 comp_map
[value_name
]->note("Field `%s' is already given here",
4186 value_dispname_str
);
4188 } else comp_map
.add(value_name
, nv
);
4189 CompField
*cf
= get_comp_byName(value_id
);
4190 // check the ordering of fields
4192 if (incomplete_allowed
) {
4194 for (size_t i
= next_index
; i
< n_type_comps
; i
++) {
4195 CompField
*cf2
= get_comp_byIndex(i
);
4196 if (value_name
== cf2
->get_name().get_name()) {
4204 nv
->error("Field `%s' cannot appear after field `%s' in record "
4205 "value", value_dispname_str
,
4206 last_cf
->get_name().get_dispname().c_str());
4210 // the value must be complete unless implicit omit is set
4211 CompField
*cf2
= get_comp_byIndex(seq_index
);
4212 CompField
*cf2_orig
= cf2
;
4213 while (implicit_omit
&& seq_index
< n_type_comps
&& cf2
!= cf
&&
4214 cf2
->get_is_optional())
4215 cf2
= get_comp_byIndex(++seq_index
);
4216 if (seq_index
>= n_type_comps
|| cf2
!= cf
) {
4217 nv
->error("Unexpected field `%s' in record value, "
4218 "expecting `%s'", value_dispname_str
,
4219 cf2_orig
->get_name().get_dispname().c_str());
4224 Type
*type
= cf
->get_type();
4225 Value
*comp_value
= nv
->get_value();
4226 comp_value
->set_my_governor(type
);
4227 if (comp_value
->get_valuetype() == Value::V_NOTUSED
) {
4228 if (implicit_omit
) {
4229 comp_value
->set_valuetype(Value::V_OMIT
);
4234 Error_Context
cntxt(nv
, "In value for record field `%s'",
4235 value_dispname_str
);
4236 type
->chk_this_value_ref(comp_value
);
4237 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
, incomplete_allowed
,
4238 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4239 if (comp_value
->get_valuetype() != Value::V_NOTUSED
) {
4243 if (!incomplete_allowed
|| implicit_omit
) {
4244 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4245 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
4246 if (!comp_map
.has_key(id
.get_name())) {
4247 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
) {
4248 value
->add_se_comp(new NamedValue(new Identifier(id
),
4249 new Value(Value::V_OMIT
)));
4252 else if (!incomplete_allowed
)
4253 value
->error("Field `%s' is missing from record value",
4254 id
.get_dispname().c_str());
4259 // all of the record's fields are unused (-), set the record to unused
4260 // to avoid unnecessary code generation
4261 value
->set_valuetype(Value::V_NOTUSED
);
4267 bool Type::chk_this_value_Set_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4268 namedbool incomplete_allowed
, namedbool implicit_omit
)
4270 bool self_ref
= false;
4271 map
<string
, NamedValue
> comp_map
;
4272 size_t n_type_comps
= get_nof_comps();
4273 size_t n_value_comps
= value
->get_nof_comps();
4274 bool is_empty
= n_type_comps
> 0; // don't do this check if the set type has no fields
4275 for(size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4276 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4277 const Identifier
& value_id
= nv
->get_name();
4278 const string
& value_name
= value_id
.get_name();
4279 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4280 if (!has_comp_withName(value_id
)) {
4281 nv
->error("Reference to non-existent field `%s' in set value for "
4282 "type `%s'", value_dispname_str
, get_typename().c_str());
4283 nv
->note("%s", actual_fields(*this).c_str());
4285 } else if (comp_map
.has_key(value_name
)) {
4286 nv
->error("Duplicate set field `%s'", value_dispname_str
);
4287 comp_map
[value_name
]->note("Field `%s' is already given here",
4288 value_dispname_str
);
4289 } else comp_map
.add(value_name
, nv
);
4290 CompField
*cf
= get_comp_byName(value_id
);
4291 Type
*type
= cf
->get_type();
4292 Value
*comp_value
= nv
->get_value();
4293 comp_value
->set_my_governor(type
);
4294 if (comp_value
->get_valuetype() == Value::V_NOTUSED
) {
4295 if (implicit_omit
) {
4296 comp_value
->set_valuetype(Value::V_OMIT
);
4301 Error_Context
cntxt(nv
, "In value for set field `%s'",
4302 value_dispname_str
);
4303 type
->chk_this_value_ref(comp_value
);
4304 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
, incomplete_allowed
,
4305 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4306 if (comp_value
->get_valuetype() != Value::V_NOTUSED
) {
4310 if (!incomplete_allowed
|| implicit_omit
) {
4311 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4312 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
4313 if(!comp_map
.has_key(id
.get_name())) {
4314 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
) {
4315 value
->add_se_comp(new NamedValue(new Identifier(id
),
4316 new Value(Value::V_OMIT
)));
4319 else if (!incomplete_allowed
)
4320 value
->error("Field `%s' is missing from set value %s",
4321 id
.get_dispname().c_str(), implicit_omit
? "yes" : "no");
4326 // all of the set's fields are unused (-), set the set to unused to avoid
4327 // unnecessary code generation
4328 value
->set_valuetype(Value::V_NOTUSED
);
4334 bool Type::chk_this_value_Se_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4335 namedbool implicit_omit
)
4337 if(value
->get_valuetype()==Value::V_UNDEF_BLOCK
) {
4338 if(typetype
== T_SEQ_A
) value
->set_valuetype(Value::V_SEQ
);
4339 else value
->set_valuetype(Value::V_SET
);
4341 switch(value
->get_valuetype()) {
4343 return chk_this_value_Seq_A(value
, lhs
, expected_value
, implicit_omit
);
4345 return chk_this_value_Set_A(value
, lhs
, expected_value
, implicit_omit
);
4347 value
->error("%s value was expected",
4348 typetype
== T_SEQ_A
? "SEQUENCE" : "SET");
4349 value
->set_valuetype(Value::V_ERROR
);
4355 bool Type::chk_this_value_Seq_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4356 namedbool implicit_omit
)
4358 bool self_ref
= false;
4359 map
<string
, NamedValue
> comp_map
;
4360 // it is set to false if we have lost the ordering
4361 bool in_synch
= true;
4362 size_t n_type_comps
= u
.secho
.ctss
->get_nof_comps();
4363 size_t n_value_comps
= value
->get_nof_comps();
4365 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4366 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4367 const Identifier
& value_id
= nv
->get_name();
4368 const string
& value_name
= value_id
.get_name();
4369 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4370 if (!u
.secho
.ctss
->has_comp_withName(value_id
)) {
4371 nv
->error("Reference to non-existent component `%s' of SEQUENCE "
4372 "type `%s'", value_dispname_str
, get_typename().c_str());
4373 nv
->note("%s", actual_fields(*this).c_str());
4376 } else if (comp_map
.has_key(value_name
)) {
4377 nv
->error("Duplicate SEQUENCE component `%s'", value_dispname_str
);
4378 comp_map
[value_name
]->note("Component `%s' is already given here",
4379 value_dispname_str
);
4381 } else comp_map
.add(value_name
, nv
);
4382 CompField
*cf
= u
.secho
.ctss
->get_comp_byName(value_id
);
4385 for ( ; t_i
< n_type_comps
; t_i
++) {
4386 cf2
= u
.secho
.ctss
->get_comp_byIndex(t_i
);
4387 if (cf2
== cf
|| (!cf2
->get_is_optional() && !cf2
->has_default() &&
4392 if (t_i
< n_type_comps
) {
4393 nv
->error("Unexpected component `%s' in SEQUENCE value, "
4394 "expecting `%s'", value_dispname_str
,
4395 cf2
->get_name().get_dispname().c_str());
4397 nv
->error("Unexpected component `%s' in SEQUENCE value",
4398 value_dispname_str
);
4403 Type
*type
= cf
->get_type();
4404 Error_Context
cntxt(nv
, "In value for SEQUENCE component `%s'",
4405 value_dispname_str
);
4406 Value
*comp_value
= nv
->get_value();
4407 comp_value
->set_my_governor(type
);
4408 type
->chk_this_value_ref(comp_value
);
4409 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4410 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4412 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4413 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4414 const Identifier
& id
= cf
->get_name();
4415 if (!comp_map
.has_key(id
.get_name())) {
4416 if (!cf
->get_is_optional() && !cf
->has_default())
4417 value
->error("Mandatory component `%s' is missing from SEQUENCE value",
4418 id
.get_dispname().c_str());
4419 else if (cf
->get_is_optional() && implicit_omit
)
4420 value
->add_se_comp(new NamedValue(new Identifier(id
),
4421 new Value(Value::V_OMIT
)));
4428 bool Type::chk_this_value_Set_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4429 namedbool implicit_omit
)
4431 bool self_ref
= false;
4432 map
<string
, NamedValue
> comp_map
;
4433 size_t n_type_comps
= u
.secho
.ctss
->get_nof_comps();
4434 size_t n_value_comps
= value
->get_nof_comps();
4435 for(size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4436 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4437 const Identifier
& value_id
= nv
->get_name();
4438 const string
& value_name
= value_id
.get_name();
4439 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4440 if (!u
.secho
.ctss
->has_comp_withName(value_id
)) {
4441 value
->error("Reference to non-existent component `%s' of SET type "
4442 "`%s'", value_dispname_str
, get_typename().c_str());
4443 nv
->note("%s", actual_fields(*this).c_str());
4445 } else if (comp_map
.has_key(value_name
)) {
4446 nv
->error("Duplicate SET component `%s'", value_dispname_str
);
4447 comp_map
[value_name
]->note("Component `%s' is already given here",
4448 value_dispname_str
);
4449 } else comp_map
.add(value_name
, nv
);
4451 u
.secho
.ctss
->get_comp_byName(value_id
)->get_type();
4452 Value
*comp_value
= nv
->get_value();
4453 Error_Context
cntxt(nv
, "In value for SET component `%s'",
4454 value_dispname_str
);
4455 comp_value
->set_my_governor(type
);
4456 type
->chk_this_value_ref(comp_value
);
4457 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4458 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4460 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4461 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4462 const Identifier
& id
= cf
->get_name();
4463 if (!comp_map
.has_key(id
.get_name())) {
4464 if (!cf
->get_is_optional() && !cf
->has_default())
4465 value
->error("Mandatory component `%s' is missing from SET value",
4466 id
.get_dispname().c_str());
4467 else if (cf
->get_is_optional() && implicit_omit
)
4468 value
->add_se_comp(new NamedValue(new Identifier(id
),
4469 new Value(Value::V_OMIT
)));
4476 bool Type::chk_this_value_SeOf(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4477 namedbool incomplete_allowed
, namedbool implicit_omit
)
4479 bool self_ref
= false;
4480 const char *valuetypename
;
4481 if (value
->is_asn1()) {
4482 if (typetype
== T_SEQOF
) valuetypename
= "SEQUENCE OF";
4483 else valuetypename
= "SET OF";
4485 if (typetype
== T_SEQOF
) valuetypename
= "record of";
4486 else valuetypename
= "set of";
4488 if (value
->get_valuetype() == Value::V_UNDEF_BLOCK
) {
4489 if (typetype
== T_SEQOF
) value
->set_valuetype(Value::V_SEQOF
);
4490 else value
->set_valuetype(Value::V_SETOF
);
4492 switch (value
->get_valuetype()) {
4493 case Value::V_SEQOF
:
4494 if (typetype
== T_SETOF
) value
->set_valuetype(Value::V_SETOF
);
4496 case Value::V_SETOF
: {
4497 if (!value
->is_indexed()) {
4498 for (size_t i
= 0; i
< value
->get_nof_comps(); i
++) {
4499 Value
*v_comp
= value
->get_comp_byIndex(i
);
4500 Error_Context
cntxt(v_comp
, "In component #%lu",
4501 (unsigned long)(i
+ 1));
4502 v_comp
->set_my_governor(u
.seof
.ofType
);
4503 if (v_comp
->get_valuetype() == Value::V_NOTUSED
) {
4504 if (!incomplete_allowed
)
4505 v_comp
->error("Not used symbol `-' is not allowed in this "
4508 u
.seof
.ofType
->chk_this_value_ref(v_comp
);
4509 self_ref
|= u
.seof
.ofType
->chk_this_value(v_comp
, lhs
, expected_value
,
4510 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4514 // Only constant values with constant indicies can be checked at
4515 // compile time. Constant expressions evaluated.
4516 bool check_holes
= expected_value
== EXPECTED_CONSTANT
;
4518 map
<Int
, Int
> index_map
;
4519 for (size_t i
= 0; i
< value
->get_nof_comps(); i
++) {
4520 Error_Context
cntxt(this, "In component #%lu",
4521 (unsigned long)(i
+ 1));
4522 Value
*val
= value
->get_comp_byIndex(i
);
4523 Value
*index
= value
->get_index_byIndex(i
);
4524 index
->chk_expr_int(expected_value
);
4525 if (index
->get_valuetype() != Value::V_ERROR
&&
4526 index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
4527 const int_val_t
*index_int
= index
->get_value_refd_last()
4529 if (*index_int
> INT_MAX
) {
4530 index
->error("An integer value less than `%d' was expected for "
4531 "indexing type `%s' instead of `%s'", INT_MAX
,
4532 get_typename().c_str(),
4533 (index_int
->t_str()).c_str());
4534 index
->set_valuetype(Value::V_ERROR
);
4535 check_holes
= false;
4537 Int index_val
= index_int
->get_val();
4538 if (index_val
< 0) {
4539 index
->error("A non-negative integer value was expected for "
4540 "indexing type `%s' instead of `%s'",
4541 get_typename().c_str(),
4542 Int2string(index_val
).c_str());
4543 index
->set_valuetype(Value::V_ERROR
);
4544 check_holes
= false;
4545 } else if (index_map
.has_key(index_val
)) {
4546 index
->error("Duplicate index value `%s' for components `%s' "
4547 "and `%s'", Int2string(index_val
).c_str(),
4548 Int2string((Int
)i
+ 1).c_str(),
4549 Int2string(*index_map
[index_val
]).c_str());
4550 index
->set_valuetype(Value::V_ERROR
);
4551 check_holes
= false;
4553 index_map
.add(index_val
, new Int((Int
)i
+ 1));
4554 if (max_index
< index_val
)
4555 max_index
= index_val
;
4559 // The index cannot be determined.
4560 check_holes
= false;
4562 val
->set_my_governor(u
.seof
.ofType
);
4563 u
.seof
.ofType
->chk_this_value_ref(val
);
4564 self_ref
|= u
.seof
.ofType
->chk_this_value(val
, lhs
, expected_value
,
4565 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
);
4568 if ((size_t)max_index
!= index_map
.size() - 1) {
4569 value
->error("It's not allowed to create hole(s) in constant "
4571 value
->set_valuetype(Value::V_ERROR
);
4574 for (size_t i
= 0; i
< index_map
.size(); i
++)
4575 delete index_map
.get_nth_elem(i
);
4580 value
->error("%s value was expected", valuetypename
);
4581 value
->set_valuetype(Value::V_ERROR
);
4587 void Type::chk_this_value_Verdict(Value
*value
)
4589 Value
*v
= value
->get_value_refd_last();
4590 switch (v
->get_valuetype()) {
4591 case Value::V_VERDICT
:
4594 value
->error("verdict value was expected");
4595 value
->set_valuetype(Value::V_ERROR
);
4600 /** \todo enhance to handle activate */
4601 void Type::chk_this_value_Default(Value
*value
)
4603 switch (value
->get_valuetype()) {
4604 case Value::V_TTCN3_NULL
:
4605 value
->set_valuetype(Value::V_DEFAULT_NULL
);
4608 value
->error("default value was expected");
4609 value
->set_valuetype(Value::V_ERROR
);
4614 bool Type::chk_this_value_Array(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4615 namedbool incomplete_allowed
, namedbool implicit_omit
)
4617 bool self_ref
= false;
4618 switch (value
->get_valuetype()) {
4619 case Value::V_SEQOF
:
4620 value
->set_valuetype(Value::V_ARRAY
);
4622 case Value::V_ARRAY
: {
4623 size_t n_value_comps
= value
->get_nof_comps();
4624 Ttcn::ArrayDimension
*dim
= u
.array
.dimension
;
4625 if (!value
->is_indexed()) {
4626 // Value-list notation.
4627 if (!dim
->get_has_error()) {
4628 size_t array_size
= dim
->get_size();
4629 if (array_size
!= n_value_comps
)
4630 value
->error("Too %s elements in the array value: %lu was "
4631 "expected instead of %lu",
4632 array_size
> n_value_comps
? "few" : "many",
4633 (unsigned long)array_size
,
4634 (unsigned long)n_value_comps
);
4636 for (size_t i
= 0; i
< n_value_comps
; i
++) {
4637 Error_Context
cntxt(this, "In array element %lu",
4638 (unsigned long)(i
+ 1));
4639 Value
*v_comp
= value
->get_comp_byIndex(i
);
4640 v_comp
->set_my_governor(u
.array
.element_type
);
4641 if (v_comp
->get_valuetype() == Value::V_NOTUSED
) {
4642 if (!incomplete_allowed
)
4643 v_comp
->error("Not used symbol `-' is not allowed in this "
4646 u
.array
.element_type
->chk_this_value_ref(v_comp
);
4647 self_ref
|= u
.array
.element_type
->chk_this_value(v_comp
, lhs
,
4648 expected_value
, incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
,
4653 // Indexed-list notation.
4654 bool array_size_known
= !dim
->get_has_error();
4655 bool check_holes
= array_size_known
4656 && expected_value
== EXPECTED_CONSTANT
;
4657 size_t array_size
= 0;
4658 if (array_size_known
) array_size
= dim
->get_size();
4659 map
<Int
, Int
> index_map
;
4660 for (size_t i
= 0; i
< n_value_comps
; i
++) {
4661 Error_Context
cntxt(this, "In array element #%lu",
4662 (unsigned long)(i
+ 1));
4663 Value
*val
= value
->get_comp_byIndex(i
);
4664 Value
*index
= value
->get_index_byIndex(i
);
4665 dim
->chk_index(index
, expected_value
);
4666 if (index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
4667 const int_val_t
*index_int
= index
->get_value_refd_last()
4669 if (*index_int
> INT_MAX
) {
4670 index
->error("An integer value less than `%d' was expected for "
4671 "indexing type `%s' instead of `%s'", INT_MAX
,
4672 get_typename().c_str(),
4673 (index_int
->t_str()).c_str());
4674 index
->set_valuetype(Value::V_ERROR
);
4675 check_holes
= false;
4677 // Index overflows/underflows are already checked by
4678 // ArrayDimensions::chk_index() at this point. The only thing
4679 // we need to check is the uniqueness of constant index values.
4680 Int index_val
= index_int
->get_val();
4681 if (index_map
.has_key(index_val
)) {
4682 index
->error("Duplicate index value `%s' for components `%s' "
4683 "and `%s'", Int2string(index_val
).c_str(),
4684 Int2string((Int
)i
+ 1).c_str(),
4685 Int2string(*index_map
[index_val
]).c_str());
4686 index
->set_valuetype(Value::V_ERROR
);
4687 check_holes
= false;
4689 index_map
.add(index_val
, new Int((Int
)i
+ 1));
4693 check_holes
= false;
4695 val
->set_my_governor(u
.array
.element_type
);
4696 u
.array
.element_type
->chk_this_value_ref(val
);
4697 self_ref
|= u
.array
.element_type
->chk_this_value(val
, lhs
, expected_value
,
4698 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4701 if (index_map
.size() < array_size
) {
4702 // It's a constant array assigned with constant index values. The
4703 // # of constant index values doesn't reach the size of the array.
4704 value
->error("It's not allowed to create hole(s) in constant "
4706 value
->set_valuetype(Value::V_ERROR
);
4709 for (size_t i
= 0; i
< index_map
.size(); i
++)
4710 delete index_map
.get_nth_elem(i
);
4715 value
->error("array value was expected");
4716 value
->set_valuetype(Value::V_ERROR
);
4723 bool Type::chk_this_value_Signature(Value
*value
, Common::Assignment
*lhs
,
4724 expected_value_t expected_value
,
4725 namedbool incomplete_allowed
)
4727 bool self_ref
= false;
4728 switch(value
->get_valuetype()) {
4729 case Value::V_SEQOF
:
4730 value
->set_valuetype(Value::V_SEQ
);
4733 map
<string
, NamedValue
> comp_map
;
4734 // it is set to false if we have lost the ordering
4735 bool in_synch
= true;
4736 size_t n_type_comps
= get_nof_comps();
4737 size_t n_value_comps
= value
->get_nof_comps();
4738 // for incomplete values
4739 CompField
*last_cf
= 0;
4740 size_t next_index
= 0;
4741 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4742 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4743 const Identifier
& value_id
= nv
->get_name();
4744 const string
& value_name
= value_id
.get_name();
4745 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4746 if (!has_comp_withName(value_id
)) {
4747 nv
->error("Reference to non-existent parameter `%s' in signature value for "
4748 "type `%s'", value_dispname_str
, get_typename().c_str());
4751 } else if (comp_map
.has_key(value_name
)) {
4752 nv
->error("Duplicate signature parameter `%s'", value_dispname_str
);
4753 comp_map
[value_name
]->note("Parameter `%s' is already given here",
4754 value_dispname_str
);
4756 } else comp_map
.add(value_name
, nv
);
4757 CompField
*cf
= get_comp_byName(value_id
);
4758 // check the ordering of fields
4760 if (incomplete_allowed
) {
4762 for (size_t i
= next_index
; i
< n_type_comps
; i
++) {
4763 CompField
*cf2
= get_comp_byIndex(i
);
4764 if (value_name
== cf2
->get_name().get_name()) {
4772 nv
->error("Field `%s' cannot appear after parameter `%s' in signature "
4773 "value", value_dispname_str
,
4774 last_cf
->get_name().get_dispname().c_str());
4778 // the value must be complete
4779 CompField
*cf2
= get_comp_byIndex(v_i
);
4781 nv
->error("Unexpected field `%s' in record value, "
4782 "expecting `%s'", value_dispname_str
,
4783 cf2
->get_name().get_dispname().c_str());
4788 Type
*type
= cf
->get_type();
4789 Value
*comp_value
= nv
->get_value();
4790 comp_value
->set_my_governor(type
);
4791 Error_Context
cntxt(nv
, "In value for signature parameter `%s'",
4792 value_dispname_str
);
4793 type
->chk_this_value_ref(comp_value
);
4794 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4795 INCOMPLETE_NOT_ALLOWED
,
4796 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
);
4798 if (!incomplete_allowed
) {
4799 for (size_t i
= 0; i
< u
.signature
.parameters
->get_nof_in_params(); i
++) {
4800 const Identifier
& id
= get_comp_byIndex(i
)->get_name(); //u.signature.parameters->get_param_byIndex(n)
4801 if (!comp_map
.has_key(id
.get_name()) && SignatureParam::PARAM_OUT
!= u
.signature
.parameters
->get_in_param_byIndex(i
)->get_direction()) {
4802 value
->error("Field `%s' is missing from signature value",
4803 id
.get_dispname().c_str());
4810 value
->error("Signature value was expected for type `%s'",
4811 get_fullname().c_str());
4812 value
->set_valuetype(Value::V_ERROR
);
4819 /** \todo enhance to handle mtc, system, etc. */
4820 void Type::chk_this_value_Component(Value
*value
)
4822 switch (value
->get_valuetype()) {
4823 case Value::V_TTCN3_NULL
:
4824 value
->set_valuetype_COMP_NULL();
4827 if (value
->get_optype() == Value::OPTYPE_COMP_NULL
)
4828 break; // set_valuetype_COMP_NULL was called already
4831 value
->error("component reference value was expected");
4832 value
->set_valuetype(Value::V_ERROR
);
4837 void Type::chk_this_value_FAT(Value
*value
)
4839 switch (value
->get_valuetype()) {
4840 case Value::V_TTCN3_NULL
:
4841 value
->set_valuetype(Value::V_FAT_NULL
);
4843 case Value::V_REFER
:
4846 case Value::V_FUNCTION
:
4847 case Value::V_ALTSTEP
:
4848 case Value::V_TESTCASE
:
4849 case Value::V_FAT_NULL
:
4850 // This function (chk_this_value_FAT) might have transformed the value
4851 // from V_REFER or V_TTCN3_NULL to one of these. Return now,
4852 // otherwise spurious errors are generated.
4857 value
->error("Reference to a function or external function was "
4861 value
->error("Reference to an altstep was expected");
4864 value
->error("Reference to a testcase was expected");
4867 FATAL_ERROR("Type::chk_this_value_FAT()");
4869 value
->set_valuetype(Value::V_ERROR
);
4871 } // switch valuetype
4873 // Here value->valuetype is V_REFER
4874 Assignment
*t_ass
= value
->get_refered()->get_refd_assignment(false);
4876 value
->set_valuetype(Value::V_ERROR
);
4880 // check whether refers() points to the right definition
4881 Assignment::asstype_t t_asstype
= t_ass
->get_asstype();
4884 switch (t_asstype
) {
4885 case Assignment::A_FUNCTION
:
4886 case Assignment::A_FUNCTION_RVAL
:
4887 case Assignment::A_FUNCTION_RTEMP
:
4888 case Assignment::A_EXT_FUNCTION
:
4889 case Assignment::A_EXT_FUNCTION_RVAL
:
4890 case Assignment::A_EXT_FUNCTION_RTEMP
:
4891 value
->set_valuetype(Value::V_FUNCTION
, t_ass
);
4894 value
->error("Reference to a function or external function was "
4895 "expected instead of %s", t_ass
->get_description().c_str());
4896 value
->set_valuetype(Value::V_ERROR
);
4901 if (t_ass
->get_asstype() == Assignment::A_ALTSTEP
) {
4902 value
->set_valuetype(Value::V_ALTSTEP
, t_ass
);
4905 value
->error("Reference to an altstep was expected instead of %s",
4906 t_ass
->get_description().c_str());
4907 value
->set_valuetype(Value::V_ERROR
);
4911 if (t_ass
->get_asstype() == Assignment::A_TESTCASE
) {
4912 value
->set_valuetype(Value::V_TESTCASE
, t_ass
);
4915 value
->error("Reference to a testcase was expected instead of %s",
4916 t_ass
->get_description().c_str());
4917 value
->set_valuetype(Value::V_ERROR
);
4921 FATAL_ERROR("Type::chk_this_value_FAT()");
4923 // comparison of formal parameter lists
4925 Error_Context
cntxt(value
, "In comparing formal parameter lists of "
4926 "type `%s' and %s", get_typename().c_str(),
4927 t_ass
->get_description().c_str());
4928 u
.fatref
.fp_list
->chk_compatibility(t_ass
->get_FormalParList(),
4929 get_typename().c_str());
4931 // comparison of 'runs on' clauses
4932 Type
*t_runs_on_type
= t_ass
->get_RunsOnType();
4933 if (t_runs_on_type
) {
4934 if (u
.fatref
.runs_on
.self
) {
4935 if (u
.fatref
.runs_on
.ref
) {
4936 FATAL_ERROR("Type::chk_this_value_FAT()");
4937 } else { // "runs on self" case
4938 // check against the runs on component type of the scope of the value
4939 Scope
* value_scope
= value
->get_my_scope();
4940 if (!value_scope
) FATAL_ERROR("Type::chk_this_value_FAT()");
4941 Ttcn::RunsOnScope
*t_ros
= value_scope
->get_scope_runs_on();
4943 Type
*scope_comptype
= t_ros
->get_component_type();
4944 if (!t_runs_on_type
->is_compatible(scope_comptype
, NULL
)) {
4945 value
->error("Runs on clause mismatch: type `%s' has a "
4946 "'runs on self' clause and the current scope expects component "
4947 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4948 scope_comptype
->get_typename().c_str(),
4949 t_ass
->get_description().c_str(),
4950 t_runs_on_type
->get_typename().c_str());
4952 } else { // does not have 'runs on' clause
4953 // if the value's scope is a component body then check the runs on
4954 // compatibility using this component type as the scope
4955 ComponentTypeBody
* ct_body
=
4956 dynamic_cast<ComponentTypeBody
*>(value_scope
);
4958 if (!t_runs_on_type
->is_compatible(ct_body
->get_my_type(), NULL
)) {
4959 value
->error("Runs on clause mismatch: type `%s' has a "
4960 "'runs on self' clause and the current component definition "
4961 "is of type `%s', but %s runs on `%s'",
4962 get_typename().c_str(),
4963 ct_body
->get_my_type()->get_typename().c_str(),
4964 t_ass
->get_description().c_str(),
4965 t_runs_on_type
->get_typename().c_str());
4968 value
->error("Type `%s' has a 'runs on self' clause and the "
4969 "current scope does not have a 'runs on' clause, "
4970 "but %s runs on `%s'", get_typename().c_str(),
4971 t_ass
->get_description().c_str(),
4972 t_runs_on_type
->get_typename().c_str());
4977 if (u
.fatref
.runs_on
.ref
) {
4978 if (u
.fatref
.runs_on
.type
&&
4979 !t_runs_on_type
->is_compatible(u
.fatref
.runs_on
.type
, NULL
)) {
4980 value
->error("Runs on clause mismatch: type `%s' expects component "
4981 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4982 u
.fatref
.runs_on
.type
->get_typename().c_str(),
4983 t_ass
->get_description().c_str(),
4984 t_runs_on_type
->get_typename().c_str());
4987 value
->error("Type `%s' does not have 'runs on' clause, but %s runs "
4988 "on `%s'", get_typename().c_str(), t_ass
->get_description().c_str(),
4989 t_runs_on_type
->get_typename().c_str());
4993 if (typetype
== T_TESTCASE
) {
4994 // comparison of system clauses
4995 Ttcn::Def_Testcase
*t_testcase
= dynamic_cast<Ttcn::Def_Testcase
*>(t_ass
);
4996 if (!t_testcase
) FATAL_ERROR("Type::chk_this_value_FAT()");
4997 Type
*t_system_type
= t_testcase
->get_SystemType();
4998 // if the system clause is missing we shall examine the component type
4999 // that is given in the 'runs on' clause
5000 if (!t_system_type
) t_system_type
= t_runs_on_type
;
5001 Type
*my_system_type
=
5002 u
.fatref
.system
.ref
? u
.fatref
.system
.type
: u
.fatref
.runs_on
.type
;
5003 if (t_system_type
&& my_system_type
&&
5004 !t_system_type
->is_compatible(my_system_type
, NULL
)) {
5005 value
->error("System clause mismatch: testcase type `%s' expects "
5006 "component type `%s', but %s has `%s'", get_typename().c_str(),
5007 my_system_type
->get_typename().c_str(),
5008 t_ass
->get_description().c_str(),
5009 t_system_type
->get_typename().c_str());
5011 } else if (typetype
== T_FUNCTION
) {
5012 // comparison of return types
5013 bool t_returns_template
= false;
5014 switch (t_asstype
) {
5015 case Assignment::A_FUNCTION
:
5016 case Assignment::A_EXT_FUNCTION
:
5017 if (u
.fatref
.return_type
) {
5018 value
->error("Type `%s' expects a function or external function "
5019 "that returns a %s of type `%s', but %s does not have return type",
5020 get_typename().c_str(),
5021 u
.fatref
.returns_template
? "template" : "value",
5022 u
.fatref
.return_type
->get_typename().c_str(),
5023 t_ass
->get_description().c_str());
5026 case Assignment::A_FUNCTION_RTEMP
:
5027 case Assignment::A_EXT_FUNCTION_RTEMP
: {
5028 // comparison of template restrictions
5029 Ttcn::Def_Function_Base
* dfb
=
5030 dynamic_cast<Ttcn::Def_Function_Base
*>(t_ass
);
5031 if (!dfb
) FATAL_ERROR("Type::chk_this_value_FAT()");
5032 template_restriction_t refd_tr
= dfb
->get_template_restriction();
5033 if (refd_tr
!=u
.fatref
.template_restriction
) {
5034 value
->error("Type `%s' expects a function or external function "
5035 "that returns a template with %s restriction, "
5036 "but %s returns a template with %s restriction",
5037 get_typename().c_str(),
5038 u
.fatref
.template_restriction
==TR_NONE
? "no" :
5039 Template::get_restriction_name(u
.fatref
.template_restriction
),
5040 t_ass
->get_description().c_str(),
5041 refd_tr
==TR_NONE
? "no" : Template::get_restriction_name(refd_tr
));
5044 t_returns_template
= true;
5046 case Assignment::A_FUNCTION_RVAL
:
5047 case Assignment::A_EXT_FUNCTION_RVAL
:
5048 if (u
.fatref
.return_type
) {
5049 Type
*t_return_type
= t_ass
->get_Type();
5050 if (!u
.fatref
.return_type
->is_identical(t_return_type
)) {
5051 value
->error("Return type mismatch: type `%s' expects a function "
5052 "or external function that returns a %s of type `%s', but %s "
5053 "returns a %s of type `%s'", get_typename().c_str(),
5054 u
.fatref
.returns_template
? "template" : "value",
5055 u
.fatref
.return_type
->get_typename().c_str(),
5056 t_ass
->get_description().c_str(),
5057 t_returns_template
? "template" : "value",
5058 t_return_type
->get_typename().c_str());
5059 } else if (u
.fatref
.return_type
->get_sub_type() && t_return_type
->get_sub_type() &&
5060 (u
.fatref
.return_type
->get_sub_type()->get_subtypetype()==t_return_type
->get_sub_type()->get_subtypetype()) &&
5061 (!u
.fatref
.return_type
->get_sub_type()->is_compatible(t_return_type
->get_sub_type()))) {
5062 // TODO: maybe equivalence should be checked, or maybe that is too strict
5063 value
->error("Return type subtype mismatch: subtype %s has no common value with subtype %s",
5064 u
.fatref
.return_type
->get_sub_type()->to_string().c_str(),
5065 t_return_type
->get_sub_type()->to_string().c_str());
5066 } else if (u
.fatref
.returns_template
!= t_returns_template
) {
5067 value
->error("Type `%s' expects a function or external function "
5068 "that returns a %s of type `%s', but %s returns a %s",
5069 get_typename().c_str(),
5070 u
.fatref
.returns_template
? "template" : "value",
5071 u
.fatref
.return_type
->get_typename().c_str(),
5072 t_ass
->get_description().c_str(),
5073 t_returns_template
? "template" : "value");
5076 value
->error("Type `%s' expects a function or external function "
5077 "without return type, but %s returns a %s of type `%s'",
5078 get_typename().c_str(), t_ass
->get_description().c_str(),
5079 t_returns_template
? "template" : "value",
5080 t_ass
->get_Type()->get_typename().c_str());
5084 FATAL_ERROR("Type::chk_this_value_FAT()");
5089 void Type::chk_this_template_length_restriction(Template
*t
)
5091 Ttcn::LengthRestriction
*lr
= t
->get_length_restriction();
5092 if (!lr
) FATAL_ERROR("Type::chk_this_template_length_restriction()");
5093 // first check the length restriction itself
5094 lr
->chk(EXPECTED_DYNAMIC_VALUE
);
5096 /** \todo check lr against the length subtype constraint of this */
5097 get_type_refd()->chk_this_template_length_restriction(t
);
5100 typetype_t tt
= get_typetype_ttcn3(typetype
);
5104 // return silently, the type of the template is erroneous anyway
5107 lr
->chk_array_size(u
.array
.dimension
);
5116 // length restriction is allowed for these types
5119 lr
->error("Length restriction cannot be used in a template of type `%s'",
5120 get_typename().c_str());
5123 // check whether the number of elements in t is in accordance with lr
5124 Template
*t_last
= t
->get_template_refd_last();
5125 switch (t_last
->get_templatetype()) {
5126 case Ttcn::Template::OMIT_VALUE
:
5127 lr
->error("Length restriction cannot be used with omit value");
5129 case Ttcn::Template::SPECIFIC_VALUE
: {
5130 Value
*v_last
= t_last
->get_specific_value()->get_value_refd_last();
5131 switch (v_last
->get_valuetype()) {
5134 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5138 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5142 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5145 if (tt
== T_CSTR
|| tt
== T_USTR
)
5146 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5150 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5152 case Value::V_SEQOF
:
5154 lr
->chk_nof_elements(v_last
->get_nof_comps(), false, *t
, "value");
5156 case Value::V_SETOF
:
5158 lr
->chk_nof_elements(v_last
->get_nof_comps(), false, *t
, "value");
5160 // note: do not check array values
5161 // they are already verified against the array size
5163 lr
->error("Length restriction cannot be used with omit value");
5165 // we cannot verify anything on other value types
5166 // they are either correct or not applicable to the type
5170 case Ttcn::Template::TEMPLATE_LIST
:
5171 if (tt
== T_SEQOF
|| tt
== T_SETOF
)
5172 lr
->chk_nof_elements(t_last
->get_nof_comps_not_anyornone(),
5173 t_last
->temps_contains_anyornone_symbol(), *t
, "template");
5174 // note: do not check array templates
5175 // they are already verified against the array size
5177 case Ttcn::Template::SUPERSET_MATCH
:
5179 lr
->chk_nof_elements(t_last
->get_nof_comps_not_anyornone(), true,
5182 case Ttcn::Template::BSTR_PATTERN
:
5184 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5185 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5187 case Ttcn::Template::HSTR_PATTERN
:
5189 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5190 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5192 case Ttcn::Template::OSTR_PATTERN
:
5194 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5195 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5197 case Ttcn::Template::CSTR_PATTERN
:
5198 if (tt
== T_CSTR
|| tt
== T_USTR
)
5199 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5200 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5203 // We cannot verify anything on other matching mechanisms.
5204 // They are either correct or not applicable to the type.
5209 void Type::chk_this_template_ref(Template
*t
)
5211 switch (t
->get_templatetype()) {
5212 case Ttcn::Template::SPECIFIC_VALUE
: {
5213 // if (t->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE) return;
5214 Value
*v
= t
->get_specific_value();
5215 chk_this_value_ref(v
);
5216 switch (v
->get_valuetype()) {
5217 case Value::V_REFD
: {
5218 // Do not check the actual parameter list of the reference yet to avoid
5219 // endless recursion in case of embedded circular references.
5220 // The parameter lists will be verified later.
5221 Assignment
*ass
= v
->get_reference()->get_refd_assignment(false);
5223 switch (ass
->get_asstype()) {
5224 case Assignment::A_VAR_TEMPLATE
: {
5225 Type
* type
= ass
->get_Type();
5226 switch (type
->typetype
) {
5234 case T_NUMERICSTRING
:
5235 case T_PRINTABLESTRING
:
5236 case T_TELETEXSTRING
:
5237 case T_VIDEOTEXSTRING
:
5239 case T_GRAPHICSTRING
:
5240 case T_VISIBLESTRING
:
5241 case T_GENERALSTRING
:
5242 case T_UNIVERSALSTRING
:
5245 case T_GENERALIZEDTIME
:
5246 case T_OBJECTDESCRIPTOR
: {
5247 // TR 921 (indexing of template strings)
5248 Ttcn::FieldOrArrayRefs
*subrefs
= v
->get_reference()
5250 if (!subrefs
) break;
5251 size_t nof_subrefs
= subrefs
->get_nof_refs();
5252 if (nof_subrefs
> 0) {
5253 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
5254 ->get_ref(nof_subrefs
- 1);
5255 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
5256 t
->error("Reference to %s can not be indexed",
5257 (ass
->get_description()).c_str());
5258 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5267 case Assignment::A_MODULEPAR_TEMP
:
5268 case Assignment::A_TEMPLATE
:
5269 case Assignment::A_PAR_TEMPL_IN
:
5270 case Assignment::A_PAR_TEMPL_OUT
:
5271 case Assignment::A_PAR_TEMPL_INOUT
:
5272 case Assignment::A_FUNCTION_RTEMP
:
5273 case Assignment::A_EXT_FUNCTION_RTEMP
:
5274 t
->set_templatetype(Ttcn::Template::TEMPLATE_REFD
);
5278 } else t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5280 case Value::V_INVOKE
: {
5281 Type
*t2
= v
->get_invoked_type(Type::EXPECTED_TEMPLATE
);
5282 if(t2
&& t2
->get_type_refd_last()->get_returns_template())
5283 t
->set_templatetype(Ttcn::Template::TEMPLATE_INVOKE
);
5290 case Ttcn::Template::TEMPLATE_REFD
: {
5291 // Do not check the actual parameter list of the reference yet to avoid
5292 // endless recursion in case of embedded circular references.
5293 // The parameter lists will be verified later.
5294 Assignment
*ass
= t
->get_reference()->get_refd_assignment(false);
5296 switch (ass
->get_asstype()) {
5297 case Assignment::A_VAR_TEMPLATE
: {
5298 Type
* type
= ass
->get_Type();
5299 switch (type
->typetype
) {
5307 case T_NUMERICSTRING
:
5308 case T_PRINTABLESTRING
:
5309 case T_TELETEXSTRING
:
5310 case T_VIDEOTEXSTRING
:
5312 case T_GRAPHICSTRING
:
5313 case T_VISIBLESTRING
:
5314 case T_GENERALSTRING
:
5315 case T_UNIVERSALSTRING
:
5318 case T_GENERALIZEDTIME
:
5319 case T_OBJECTDESCRIPTOR
: {
5320 // TR 921 (indexing of template strings)
5321 Ttcn::FieldOrArrayRefs
*subrefs
= t
->get_reference()
5323 if (!subrefs
) break;
5324 size_t nof_subrefs
= subrefs
->get_nof_refs();
5325 if (nof_subrefs
> 0) {
5326 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
5327 ->get_ref(nof_subrefs
- 1);
5328 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
5329 t
->error("Reference to %s can not be indexed",
5330 (ass
->get_description()).c_str());
5331 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5340 case Assignment::A_MODULEPAR_TEMP
:
5341 case Assignment::A_TEMPLATE
:
5342 case Assignment::A_PAR_TEMPL_IN
:
5343 case Assignment::A_PAR_TEMPL_OUT
:
5344 case Assignment::A_PAR_TEMPL_INOUT
:
5345 case Assignment::A_FUNCTION_RTEMP
:
5346 case Assignment::A_EXT_FUNCTION_RTEMP
:
5347 t
->set_templatetype(Ttcn::Template::TEMPLATE_REFD
);
5351 } else t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5359 bool Type::chk_this_template_ref_pard(Ttcn::Ref_pard
* ref_pard
, Common::Assignment
* lhs
)
5361 // Check if the reference on the left hand side of the assignment can be found
5362 // among the parameters
5363 Ttcn::ActualParList
* par_list
= ref_pard
->get_parlist();
5365 size_t nof_pars
= par_list
->get_nof_pars();
5366 for (size_t i
= 0; i
< nof_pars
; ++i
) {
5367 Ttcn::ActualPar
* par
= par_list
->get_par(i
);
5368 Ttcn::Ref_base
* par_ref
= 0;
5369 switch(par
->get_selection()) {
5370 case Ttcn::ActualPar::AP_TEMPLATE
: {
5371 Ttcn::TemplateInstance
* temp_ins
= par
->get_TemplateInstance();
5372 Ttcn::Template
* temp
= temp_ins
->get_Template();
5373 if (temp
->get_templatetype() == Ttcn::Template::TEMPLATE_REFD
) {
5374 par_ref
= temp
->get_reference();
5378 case Ttcn::ActualPar::AP_REF
: {
5379 par_ref
= par
->get_Ref();
5387 Common::Assignment
* ass
= par_ref
->get_refd_assignment(true); // also check parameters if there are any
5391 // In case a parameter is another function call / parametrised template
5392 // check their parameters as well
5393 if (ass
->get_asstype() == Assignment::A_FUNCTION_RTEMP
||
5394 ass
->get_asstype() == Assignment::A_EXT_FUNCTION_RTEMP
||
5395 ass
->get_asstype() == Assignment::A_TEMPLATE
) {
5396 ref_pard
= dynamic_cast<Ttcn::Ref_pard
*>(par_ref
);
5397 if (ref_pard
&& chk_this_template_ref_pard(ref_pard
, lhs
))
5406 bool Type::chk_this_template_generic(Template
*t
, namedbool incomplete_allowed
,
5407 namedbool allow_omit
, namedbool allow_any_or_omit
, namedbool sub_chk
,
5408 namedbool implicit_omit
, Common::Assignment
*lhs
)
5410 bool self_ref
= false;
5411 if (!allow_omit
&& t
->get_template_refd_last()->get_templatetype() ==
5412 Ttcn::Template::OMIT_VALUE
) {
5413 t
->error("`omit' value is not allowed in this context");
5415 if (!allow_any_or_omit
&& t
->get_template_refd_last()->get_templatetype() ==
5416 Ttcn::Template::ANY_OR_OMIT
) {
5417 t
->warning("Using `*' for mandatory field");
5420 Ttcn::Template::templatetype_t temptype
= t
->get_templatetype();
5422 case Ttcn::Template::TEMPLATE_ERROR
:
5424 case Ttcn::Template::TEMPLATE_NOTUSED
:
5425 case Ttcn::Template::OMIT_VALUE
:
5426 case Ttcn::Template::ANY_VALUE
:
5427 case Ttcn::Template::ANY_OR_OMIT
: {
5428 Type
*type
=get_type_refd_last();
5429 if (type
->get_typetype() == T_SIGNATURE
)
5430 t
->error("Generic wildcard `%s' cannot be used for signature `%s'",
5431 t
->get_templatetype_str(), type
->get_fullname().c_str());
5433 case Ttcn::Template::VALUE_LIST_ALL_FROM
:
5434 case Ttcn::Template::ALL_FROM
: {
5435 Ttcn::Template
*af
= t
->get_all_from();
5436 switch (af
->get_templatetype()) {
5437 case Ttcn::Template::SPECIFIC_VALUE
: {
5438 Value
*v
= af
->get_specific_value();
5439 v
->set_lowerid_to_ref();
5440 Reference
*ref
= v
->get_reference();
5441 Assignment
*ass
= ref
->get_refd_assignment(true); // also check parameters if there are any
5442 if (!ass
) break; // probably erroneous
5443 //warning("asstype %d", ass->get_asstype());
5445 switch (ass
->get_asstype()) {
5446 case Assignment::A_VAR
:
5447 case Assignment::A_PAR_VAL_IN
:
5448 case Assignment::A_PAR_VAL_INOUT
:
5449 case Assignment::A_MODULEPAR
:
5450 case Assignment::A_CONST
:
5451 case Assignment::A_MODULEPAR_TEMP
:
5452 break; // acceptable
5453 case Assignment::A_VAR_TEMPLATE
:
5454 case Assignment::A_PAR_TEMPL_IN
:
5455 case Assignment::A_PAR_TEMPL_INOUT
:
5458 break; // acceptable
5459 case Assignment::A_FUNCTION_RVAL
:
5460 case Assignment::A_EXT_FUNCTION_RVAL
:
5461 case Assignment::A_FUNCTION_RTEMP
:
5462 case Assignment::A_EXT_FUNCTION_RTEMP
:
5463 case Assignment::A_TEMPLATE
: {
5464 Ttcn::Ref_pard
* ref_pard
= dynamic_cast<Ttcn::Ref_pard
*>(ref
);
5466 self_ref
|= chk_this_template_ref_pard(ref_pard
, lhs
);
5467 break; // acceptable
5470 error("A %s cannot be used as the target of `all from'",
5471 ass
->get_assname());
5474 //self_ref |= chk_this_value(v, lhs, EXPECTED_TEMPLATE, incomplete_allowed,
5475 // allow_omit, sub_chk, implicit_omit, NOT_STR_ELEM /* ?? */);
5479 error("The target of an 'all from' must be a specific value template, not a %s",
5480 af
->get_templatetype_str());
5485 case Ttcn::Template::VALUE_LIST
:
5486 case Ttcn::Template::COMPLEMENTED_LIST
: {
5487 size_t nof_comps
= t
->get_nof_comps();
5488 for (size_t i
= 0; i
< nof_comps
; i
++) {
5489 Template
* t_comp
= t
->get_temp_byIndex(i
);
5490 Error_Context
cntxt(t
, "In list item %lu", (unsigned long) (i
+ 1));
5491 t_comp
->set_my_governor(this);
5492 chk_this_template_ref(t_comp
);
5493 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
5494 omit_in_value_list
? allow_omit
: OMIT_NOT_ALLOWED
,
5495 ANY_OR_OMIT_ALLOWED
, sub_chk
, implicit_omit
, lhs
);
5496 if(temptype
==Ttcn::Template::COMPLEMENTED_LIST
&&
5497 t_comp
->get_template_refd_last()->get_templatetype() ==
5498 Ttcn::Template::ANY_OR_OMIT
)
5499 t_comp
->warning("`*' in complemented list."
5500 " This template will not match anything");
5503 case Ttcn::Template::SPECIFIC_VALUE
: {
5504 Value
*v
= t
->get_specific_value();
5505 v
->set_my_governor(this);
5506 self_ref
|= chk_this_value(v
, lhs
, EXPECTED_TEMPLATE
, incomplete_allowed
,
5507 allow_omit
, SUB_CHK
);
5509 case Ttcn::Template::TEMPLATE_INVOKE
: {
5511 Type
*governor
= t
->get_expr_governor(EXPECTED_DYNAMIC_VALUE
);
5513 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5514 else if (!is_compatible(governor
, NULL
)) {
5515 t
->error("Type mismatch: a value or template of type `%s' was "
5516 "expected instead of `%s'", get_typename().c_str(),
5517 governor
->get_typename().c_str());
5518 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5521 case Ttcn::Template::TEMPLATE_REFD
:
5522 self_ref
= chk_this_refd_template(t
, lhs
);
5525 self_ref
= chk_this_template(t
, incomplete_allowed
, sub_chk
, implicit_omit
, lhs
);
5528 if (t
->get_length_restriction()) chk_this_template_length_restriction(t
);
5529 if (!allow_omit
&& t
->get_ifpresent())
5530 t
->error("`ifpresent' is not allowed here");
5531 if(sub_chk
&& temptype
!= Ttcn::Template::PERMUTATION_MATCH
) {
5532 /* Note: A "permuation" itself has no type - it is just a fragment. */
5533 if(sub_type
!=NULL
) sub_type
->chk_this_template_generic(t
);
5539 bool Type::chk_this_refd_template(Template
*t
, Common::Assignment
*lhs
)
5541 if (t
->get_templatetype() != Template::TEMPLATE_REFD
) return false;
5542 Reference
*ref
= t
->get_reference();
5543 Assignment
*ass
= ref
->get_refd_assignment();
5544 if (!ass
) FATAL_ERROR("Type::chk_this_refd_template()");
5547 Type
*governor
= ass
->get_Type()
5548 ->get_field_type(ref
->get_subrefs(), EXPECTED_DYNAMIC_VALUE
);
5550 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5552 TypeCompatInfo
info(t
->get_my_scope()->get_scope_mod(), this, governor
,
5554 if (ref
->get_subrefs()) info
.set_str2_elem(ref
->get_subrefs()->refers_to_string_element());
5557 if (!is_compatible(governor
, &info
, &l_chain
, &r_chain
)) {
5558 Type
*type
= get_type_refd_last();
5559 switch (type
->typetype
) {
5561 // Port templates do not exist, remain silent.
5564 t
->error("Type mismatch: a signature template of type `%s' was "
5565 "expected instead of `%s'", get_typename().c_str(),
5566 governor
->get_typename().c_str());
5569 if (info
.is_subtype_error()) {
5570 t
->error("%s", info
.get_subtype_error().c_str());
5571 } else if (!info
.is_erroneous()) {
5572 t
->error("Type mismatch: a value or template of type `%s' was "
5573 "expected instead of `%s'", get_typename().c_str(),
5574 governor
->get_typename().c_str());
5576 t
->error("%s", info
.get_error_str_str().c_str());
5580 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5582 // Detect circular references.
5583 t
->get_template_refd_last();
5585 if (info
.needs_conversion()) t
->set_needs_conversion();
5588 return (lhs
== ass
);
5591 bool Type::chk_this_template(Template
*t
, namedbool is_modified
, namedbool
,
5592 namedbool implicit_omit
, Common::Assignment
*lhs
)
5594 bool self_ref
= false;
5595 Type
*t_last
= get_type_refd_last();
5596 t
->set_my_governor(t_last
);
5598 switch(t_last
->typetype
) {
5609 t_last
->chk_this_template_builtin(t
);
5618 case T_NUMERICSTRING
:
5619 case T_PRINTABLESTRING
:
5620 case T_TELETEXSTRING
:
5621 case T_VIDEOTEXSTRING
:
5623 case T_GRAPHICSTRING
:
5624 case T_VISIBLESTRING
:
5625 case T_GENERALSTRING
:
5626 case T_UNIVERSALSTRING
:
5629 case T_GENERALIZEDTIME
:
5630 case T_OBJECTDESCRIPTOR
:
5631 self_ref
= t_last
->chk_this_template_Str(t
, implicit_omit
, lhs
);
5636 t_last
->chk_this_template_Int_Real(t
);
5640 t_last
->chk_this_template_Enum(t
);
5646 self_ref
= t_last
->chk_this_template_Choice(t
, is_modified
, implicit_omit
, lhs
);
5650 self_ref
= t_last
->chk_this_template_Seq(t
, is_modified
, implicit_omit
, lhs
);
5654 self_ref
= t_last
->chk_this_template_Set(t
, is_modified
, implicit_omit
, lhs
);
5657 self_ref
= t_last
->chk_this_template_SeqOf(t
, is_modified
, implicit_omit
, lhs
);
5660 self_ref
= t_last
->chk_this_template_SetOf(t
, is_modified
, implicit_omit
, lhs
);
5663 self_ref
= t_last
->chk_this_template_array(t
, is_modified
, implicit_omit
, lhs
);
5666 t
->error("Template cannot be defined for port type `%s'",
5667 get_fullname().c_str());
5670 t_last
->chk_this_template_Signature(t
, is_modified
);
5675 t_last
->chk_this_template_Fat(t
);
5678 FATAL_ERROR("Type::chk_this_template()");
5683 bool Type::chk_this_template_Str(Template
*t
, namedbool implicit_omit
,
5684 Common::Assignment
*lhs
)
5686 bool self_ref
= false;
5687 typetype_t tt
= get_typetype_ttcn3(typetype
);
5688 bool report_error
= false;
5689 switch (t
->get_templatetype()) {
5690 case Ttcn::Template::VALUE_RANGE
:
5691 if (tt
== T_CSTR
|| tt
== T_USTR
) {
5692 Error_Context
cntxt(t
, "In value range");
5693 Ttcn::ValueRange
*vr
= t
->get_value_range();
5694 Value
*v_lower
= chk_range_boundary(vr
->get_min_v(), "lower", *t
);
5695 Value
*v_upper
= chk_range_boundary(vr
->get_max_v(), "upper", *t
);
5696 if (v_lower
&& v_upper
) {
5697 // both boundaries are available and have correct type
5699 if (v_lower
->get_val_str() > v_upper
->get_val_str())
5700 t
->error("The lower boundary has higher character code than the "
5703 if (v_lower
->get_val_ustr() > v_upper
->get_val_ustr())
5704 t
->error("The lower boundary has higher character code than the "
5708 } else report_error
= true;
5710 case Ttcn::Template::BSTR_PATTERN
:
5711 if (tt
!= T_BSTR
) report_error
= true;
5713 case Ttcn::Template::HSTR_PATTERN
:
5714 if (tt
!= T_HSTR
) report_error
= true;
5716 case Ttcn::Template::OSTR_PATTERN
:
5717 if (tt
!= T_OSTR
) report_error
= true;
5719 case Ttcn::Template::CSTR_PATTERN
:
5721 Ttcn::PatternString
*pstr
= t
->get_cstr_pattern();
5722 Error_Context
cntxt(t
, "In character string pattern");
5724 pstr
->join_strings();
5725 if (!pstr
->has_refs()) pstr
->chk_pattern();
5727 } else if (tt
== T_USTR
) {
5728 t
->set_templatetype(Template::USTR_PATTERN
);
5729 t
->get_ustr_pattern()
5730 ->set_pattern_type(Ttcn::PatternString::USTR_PATTERN
);
5733 report_error
= true;
5737 case Ttcn::Template::USTR_PATTERN
:
5739 Ttcn::PatternString
*pstr
= t
->get_ustr_pattern();
5740 Error_Context
cntxt(t
, "In universal string pattern");
5742 pstr
->join_strings();
5743 if (!pstr
->has_refs()) pstr
->chk_pattern();
5744 } else report_error
= true;
5746 case Ttcn::Template::DECODE_MATCH
:
5748 Error_Context
cntxt(t
, "In decoding target");
5749 TemplateInstance
* target
= t
->get_decode_target();
5750 target
->get_Template()->set_lowerid_to_ref();
5751 Type
* target_type
= target
->get_expr_governor(EXPECTED_TEMPLATE
);
5752 if (target_type
== NULL
) {
5753 target
->error("Type of template instance cannot be determined");
5756 if (target
->get_Type() != NULL
) {
5757 target_type
= target_type
->get_type_refd();
5759 self_ref
= target_type
->chk_this_template_generic(
5760 target
->get_Template(), (target
->get_DerivedRef() != NULL
) ?
5761 INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
,
5762 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
5763 target_type
->get_type_refd_last()->chk_coding(false);
5766 Value
* str_enc
= t
->get_string_encoding();
5767 if (str_enc
!= NULL
) {
5769 str_enc
->error("The encoding format parameter is only available to "
5770 "universal charstring templates");
5773 Error_Context
cntxt(t
, "In encoding format");
5774 str_enc
->set_lowerid_to_ref();
5775 get_pooltype(T_CSTR
)->chk_this_value(str_enc
, lhs
, EXPECTED_DYNAMIC_VALUE
,
5776 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, NO_SUB_CHK
);
5777 if (!str_enc
->is_unfoldable()) {
5778 string enc_name
= str_enc
->get_val_str();
5779 if (enc_name
!= "UTF-8" && enc_name
!= "UTF-16" && enc_name
!= "UTF-32"
5780 && enc_name
!= "UTF-16LE" && enc_name
!= "UTF-16BE"
5781 && enc_name
!= "UTF-32LE" && enc_name
!= "UTF-32BE") {
5782 str_enc
->error("'%s' is not a valid encoding format", enc_name
.c_str());
5789 report_error
= true;
5793 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5794 get_typename().c_str());
5799 void Type::chk_range_boundary_infinity(Value
*v
, bool is_upper
)
5802 v
->set_my_governor(this);
5804 Error_Context
cntxt2(v
, "In %s boundary", is_upper
? "upper" : "lower");
5805 chk_this_value_ref(v
);
5806 Value
*v_last
= v
->get_value_refd_last(0, EXPECTED_STATIC_VALUE
);
5807 if (v_last
->get_valuetype() == Value::V_OMIT
) {
5808 v
->error("`omit' value is not allowed in this context");
5809 v
->set_valuetype(Value::V_ERROR
);
5812 if (sub_type
!= NULL
) {
5814 if (!sub_type
->get_root()->is_upper_limit_infinity()) {
5815 v
->error("Infinity is not a valid value for type '%s' which has subtype %s",
5816 asString(), sub_type
->to_string().c_str());
5820 if (!sub_type
->get_root()->is_lower_limit_infinity()) {
5821 v
->error("Infinity is not a valid value for type '%s' which has subtype %s",
5822 asString(), sub_type
->to_string().c_str());
5830 Value
*Type::chk_range_boundary(Value
*v
, const char *which
,
5831 const Location
& loc
)
5833 typetype_t tt
= get_typetype_ttcn3(typetype
);
5836 v
->set_my_governor(this);
5838 Error_Context
cntxt2(v
, "In %s boundary", which
);
5839 chk_this_value_ref(v
);
5840 chk_this_value(v
, 0, EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
,
5841 OMIT_NOT_ALLOWED
, SUB_CHK
);
5843 ret_val
= v
->get_value_refd_last();
5844 switch (ret_val
->get_valuetype()) {
5846 if (tt
!= T_INT
) ret_val
= 0;
5849 if (tt
!= T_REAL
) ret_val
= 0;
5852 if (tt
!= T_CSTR
) ret_val
= 0;
5855 if (tt
!= T_USTR
) ret_val
= 0;
5858 // unfoldable or erroneous
5862 if ((tt
== T_CSTR
|| tt
== T_USTR
) && ret_val
&&
5863 ret_val
->get_val_strlen() != 1) {
5864 v
->error("The %s boundary must be a %scharstring value containing a "
5865 "single character", which
, tt
== T_USTR
? "universal ": "");
5869 // the boundary is + or - infinity
5870 if (tt
== T_CSTR
|| tt
== T_USTR
) {
5871 loc
.error("The %s boundary must be a %scharstring value", which
,
5872 tt
== T_USTR
? "universal ": "");
5879 void Type::chk_this_template_builtin(Template
*t
)
5881 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5882 get_typename().c_str());
5883 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5884 "allowed for type `%s'", get_typename().c_str());
5887 void Type::chk_this_template_Int_Real(Template
*t
)
5889 switch (t
->get_templatetype()) {
5890 case Ttcn::Template::VALUE_RANGE
: {
5891 Error_Context
cntxt(t
, "In value range");
5892 Ttcn::ValueRange
*vr
= t
->get_value_range();
5893 Value
*v_lower
= chk_range_boundary(vr
->get_min_v(), "lower", *t
);
5894 Value
*v_upper
= chk_range_boundary(vr
->get_max_v(), "upper", *t
);
5895 if (v_lower
&& v_upper
) {
5896 // both boundaries are available and have correct type
5897 switch (get_typetype_ttcn3(typetype
)) {
5899 if (*v_lower
->get_val_Int() > *v_upper
->get_val_Int())
5900 t
->error("The lower boundary is higher than the upper boundary");
5903 if (v_lower
->get_val_Real() > v_upper
->get_val_Real())
5904 t
->error("The lower boundary is higher than the upper boundary");
5907 FATAL_ERROR("Type::chk_this_template_Int_Real()");
5910 if (v_lower
&& !vr
->get_max_v()) {
5911 chk_range_boundary_infinity(v_lower
, true);
5913 if (!vr
->get_min_v() && v_upper
) {
5914 chk_range_boundary_infinity(v_upper
, false);
5918 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5919 get_typename().c_str());
5922 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5923 "allowed for type `%s'", get_typename().c_str());
5926 void Type::chk_this_template_Enum(Template
*t
)
5928 t
->error("%s cannot be used for enumerated type `%s'",
5929 t
->get_templatetype_str(), get_typename().c_str());
5930 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5931 "allowed for enumerated type `%s'", get_typename().c_str());
5934 bool Type::chk_this_template_Choice(Template
*t
, namedbool is_modified
,
5935 namedbool implicit_omit
, Common::Assignment
*lhs
)
5937 bool self_ref
= false;
5938 switch (t
->get_templatetype()) {
5939 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5940 size_t nof_nts
= t
->get_nof_comps();
5941 if (nof_nts
!= 1) t
->error("A template for union type must contain "
5942 "exactly one selected field");
5943 // We check all named templates, even though it is an error
5944 // to have more than one here.
5945 for (size_t i
= 0; i
< nof_nts
; i
++) {
5946 Ttcn::NamedTemplate
*nt
= t
->get_namedtemp_byIndex(i
);
5947 if (typetype
== T_OPENTYPE
) {
5948 // allow the alternatives of open types as both lower and upper identifiers
5949 nt
->set_name_to_lowercase();
5951 const Identifier
& nt_name
= nt
->get_name();
5953 if (!has_comp_withName(nt_name
)) {
5954 nt
->error("Reference to non-existent field `%s' in union "
5955 "template for type `%s'", nt_name
.get_dispname().c_str(),
5956 get_fullname().c_str());
5957 nt
->note("%s", actual_fields(*this).c_str());
5961 Type
*field_type
= get_comp_byName(nt_name
)->get_type();
5962 Template
*nt_templ
= nt
->get_template();
5964 Error_Context
cntxt(nt_templ
, "In template for union field `%s'",
5965 nt_name
.get_dispname().c_str());
5967 nt_templ
->set_my_governor(field_type
);
5968 field_type
->chk_this_template_ref(nt_templ
);
5969 bool incompl_ok
= t
->get_completeness_condition_choice(is_modified
, nt_name
) ==
5970 Ttcn::Template::C_MAY_INCOMPLETE
;
5971 self_ref
|= field_type
->chk_this_template_generic(nt_templ
,
5972 (incompl_ok
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
5973 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
5977 t
->error("%s cannot be used for union type `%s'",
5978 t
->get_templatetype_str(), get_typename().c_str());
5981 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5982 "allowed for union type `%s'", get_typename().c_str());
5987 bool Type::chk_this_template_Seq(Template
*t
, namedbool is_modified
,
5988 namedbool implicit_omit
, Common::Assignment
*lhs
)
5990 bool self_ref
= false;
5991 size_t n_type_comps
= get_nof_comps();
5992 switch (t
->get_templatetype()) {
5993 case Ttcn::Template::TEMPLATE_LIST
:
5994 // conversion: value list -> assignment notation
5995 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
5997 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5998 map
<string
, Ttcn::NamedTemplate
> comp_map
;
5999 // it is set to false if we have lost the ordering
6000 bool in_synch
= true;
6001 size_t n_template_comps
= t
->get_nof_comps();
6002 // the two variables below are used for modified templates only
6003 CompField
*last_cf
= 0;
6004 size_t next_index
= 0;
6005 for (size_t i
= 0; i
< n_template_comps
; i
++) {
6006 Ttcn::NamedTemplate
*namedtemp
= t
->get_namedtemp_byIndex(i
);
6007 const Identifier
& temp_id
= namedtemp
->get_name();
6008 const string
& temp_name
= temp_id
.get_name();
6009 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
6010 if (!has_comp_withName(temp_id
)) {
6011 namedtemp
->error("Reference to non-existent field `%s' in record "
6012 "template for type `%s'", temp_dispname_str
,
6013 get_typename().c_str());
6014 namedtemp
->note("%s", actual_fields(*this).c_str());
6017 } else if (comp_map
.has_key(temp_name
)) {
6018 namedtemp
->error("Duplicate record field `%s' in template",
6020 comp_map
[temp_name
]->note("Field `%s' is already given here",
6023 } else comp_map
.add(temp_name
, namedtemp
);
6025 CompField
*cf
= get_comp_byName(temp_id
);
6028 // missing fields are allowed, but take care of ordering
6030 for (size_t j
= next_index
; j
< n_type_comps
; j
++) {
6031 CompField
*cf2
= get_comp_byIndex(j
);
6032 if (temp_name
== cf2
->get_name().get_name()) {
6040 namedtemp
->error("Field `%s' cannot appear after field `%s' in "
6041 "a template for record type `%s'", temp_dispname_str
,
6042 last_cf
->get_name().get_dispname().c_str(),
6043 get_fullname().c_str());
6047 // the template must be complete
6048 CompField
*cf2
= get_comp_byIndex(i
);
6050 if (!cf2
->get_is_optional() || !implicit_omit
) {
6051 namedtemp
->error("Unexpected field `%s' in record template, "
6052 "expecting `%s'", temp_dispname_str
,
6053 cf2
->get_name().get_dispname().c_str());
6059 Type
*type
= cf
->get_type();
6060 Template
*comp_t
= namedtemp
->get_template();
6061 Error_Context
cntxt(comp_t
, "In template for record field `%s'",
6063 comp_t
->set_my_governor(type
);
6064 type
->chk_this_template_ref(comp_t
);
6065 bool is_optional
= cf
->get_is_optional(); // || cf->has_default()
6066 self_ref
|= type
->chk_this_template_generic(comp_t
, is_modified
,
6067 (is_optional
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
),
6068 (is_optional
? ANY_OR_OMIT_ALLOWED
: ANY_OR_OMIT_NOT_ALLOWED
),
6069 SUB_CHK
, implicit_omit
, lhs
);
6071 if (!is_modified
|| implicit_omit
) {
6072 // check missing fields
6073 for (size_t i
= 0; i
< n_type_comps
; i
++) {
6074 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
6075 if (!comp_map
.has_key(id
.get_name())) {
6076 if (implicit_omit
&& get_comp_byIndex(i
)->get_is_optional()) {
6077 // do not overwrite base fields
6078 if (!t
->get_base_template())
6079 t
->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id
),
6080 new Template(Template::OMIT_VALUE
)));
6081 } else if (!is_modified
) {
6082 t
->error("Field `%s' is missing from template for record type `%s'",
6083 id
.get_dispname().c_str(), get_typename().c_str());
6091 t
->error("%s cannot be used for record type `%s'",
6092 t
->get_templatetype_str(), get_typename().c_str());
6095 if (t
->get_length_restriction()) t
->error("Length restriction is not "
6096 "allowed for record type `%s'", get_typename().c_str());
6100 bool Type::chk_this_template_Set(Template
*t
,
6101 namedbool is_modified
, namedbool implicit_omit
, Common::Assignment
*lhs
)
6103 bool self_ref
= false;
6104 size_t n_type_comps
= get_nof_comps();
6105 switch (t
->get_templatetype()) {
6106 case Ttcn::Template::TEMPLATE_LIST
:
6107 if (t
->get_nof_comps() > 0) {
6108 t
->error("Value list notation is not allowed for set type `%s'",
6109 get_fullname().c_str());
6111 } else if (n_type_comps
> 0) {
6112 t
->error("A non-empty set template was expected for type `%s'",
6113 get_fullname().c_str());
6116 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
6118 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
6119 map
<string
, Ttcn::NamedTemplate
> comp_map
;
6120 size_t n_template_comps
= t
->get_nof_comps();
6121 for (size_t i
= 0; i
< n_template_comps
; i
++) {
6122 Ttcn::NamedTemplate
*namedtemp
= t
->get_namedtemp_byIndex(i
);
6123 const Identifier
& temp_id
=namedtemp
->get_name();
6124 const string
& temp_name
= temp_id
.get_name();
6125 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
6126 if (!has_comp_withName(temp_id
)) {
6127 namedtemp
->error("Reference to non-existent field `%s' in a "
6128 "template for set type `%s'", temp_dispname_str
,
6129 get_typename().c_str());
6130 namedtemp
->note("%s", actual_fields(*this).c_str());
6132 } else if (comp_map
.has_key(temp_name
)) {
6133 namedtemp
->error("Duplicate set field `%s' in template",
6135 comp_map
[temp_name
]->note("Field `%s' is already given here",
6137 } else comp_map
.add(temp_name
, namedtemp
);
6138 CompField
*cf
= get_comp_byName(temp_id
);
6139 Type
*type
= cf
->get_type();
6140 Template
*comp_t
= namedtemp
->get_template();
6141 Error_Context
cntxt(comp_t
, "In template for set field `%s'",
6143 comp_t
->set_my_governor(type
);
6144 type
->chk_this_template_ref(comp_t
);
6145 bool is_optional
= cf
->get_is_optional();
6146 self_ref
|= type
->chk_this_template_generic(comp_t
,
6147 (is_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6148 (is_optional
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
),
6149 (is_optional
? ANY_OR_OMIT_ALLOWED
: ANY_OR_OMIT_NOT_ALLOWED
),
6150 SUB_CHK
, implicit_omit
, lhs
);
6152 if (!is_modified
|| implicit_omit
) {
6153 // check missing fields
6154 for (size_t i
= 0; i
< n_type_comps
; i
++) {
6155 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
6156 if (!comp_map
.has_key(id
.get_name())) {
6157 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
) {
6158 // do not overwrite base fields
6159 if (!t
->get_base_template())
6160 t
->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id
),
6161 new Template(Template::OMIT_VALUE
)));
6162 } else if (!is_modified
) {
6163 t
->error("Field `%s' is missing from template for set type `%s'",
6164 id
.get_dispname().c_str(), get_typename().c_str());
6172 t
->error("%s cannot be used for set type `%s'",
6173 t
->get_templatetype_str(), get_typename().c_str());
6176 if (t
->get_length_restriction()) t
->error("Length restriction is not "
6177 "allowed for set type `%s'", get_typename().c_str());
6181 bool Type::chk_this_template_SeqOf(Template
*t
, namedbool is_modified
,
6182 namedbool implicit_omit
, Common::Assignment
*lhs
)
6184 bool self_ref
= false;
6185 switch(t
->get_templatetype()) {
6186 case Ttcn::Template::OMIT_VALUE
:
6187 if(t
->get_length_restriction())
6188 t
->warning("Redundant usage of length restriction with `omit'");
6190 case Ttcn::Template::PERMUTATION_MATCH
: {
6191 size_t nof_comps
= t
->get_nof_comps();
6192 for (size_t i
= 0; i
< nof_comps
; i
++) {
6193 Template
*t_comp
= t
->get_temp_byIndex(i
);
6194 Error_Context
cntxt(t_comp
, "In element %lu of permutation",
6195 (unsigned long) (i
+ 1));
6196 t_comp
->set_my_governor(u
.seof
.ofType
);
6197 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6198 // the elements of permutation must be always complete
6199 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6200 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6201 NOT_IMPLICIT_OMIT
, lhs
);
6204 case Ttcn::Template::TEMPLATE_LIST
: {
6205 Ttcn::Template::completeness_t c
=
6206 t
->get_completeness_condition_seof(is_modified
);
6208 size_t nof_base_comps
;
6209 if (c
== Ttcn::Template::C_PARTIAL
) {
6210 t_base
= t
->get_base_template()->get_template_refd_last();
6211 // it is sure that t_base is a TEMPLATE_LIST
6212 nof_base_comps
= t_base
->get_nof_comps();
6217 size_t nof_comps
= t
->get_nof_comps();
6218 for(size_t i
= 0; i
< nof_comps
; i
++) {
6219 Template
*t_comp
= t
->get_temp_byIndex(i
);
6220 Error_Context
cntxt(t_comp
, "In component %lu", (unsigned long)(i
+1));
6221 t_comp
->set_my_governor(u
.seof
.ofType
);
6222 if (t_base
&& i
< nof_base_comps
)
6223 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6224 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6225 switch (t_comp
->get_templatetype()) {
6226 case Ttcn::Template::PERMUTATION_MATCH
:
6227 // the elements of permutation has to be checked by u.seof.ofType
6228 // the templates within the permutation always have to be complete
6229 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
6230 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6231 implicit_omit
, lhs
);
6233 case Ttcn::Template::TEMPLATE_NOTUSED
:
6234 if (c
== Ttcn::Template::C_MUST_COMPLETE
) {
6235 t_comp
->error("Not used symbol `-' is not allowed in this context");
6236 } else if (c
== Ttcn::Template::C_PARTIAL
&& i
>= nof_base_comps
) {
6237 t_comp
->error("Not used symbol `-' cannot be used here because "
6238 "there is no corresponding element in the base template");
6242 bool embedded_modified
= (c
== Ttcn::Template::C_MAY_INCOMPLETE
) ||
6243 (c
== Ttcn::Template::C_PARTIAL
&& i
< nof_base_comps
);
6244 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6245 (embedded_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6246 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6251 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6252 map
<Int
, Int
> index_map
;
6253 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6254 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6255 Value
*index_value
= (it
->get_index()).get_val();
6256 // The index value must be Type::EXPECTED_DYNAMIC_VALUE integer, but
6257 // it's not required to be known at compile time.
6258 index_value
->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
6259 Template
*it_comp
= it
->get_template();
6260 Error_Context
cntxt(it_comp
, "In component %lu",
6261 (unsigned long)(i
+ 1));
6262 if (index_value
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
6263 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6265 if (*index_int
> INT_MAX
) {
6266 index_value
->error("An integer value less than `%d' was expected "
6267 "for indexing type `%s' instead of `%s'", INT_MAX
,
6268 get_typename().c_str(), (index_int
->t_str()).c_str());
6269 index_value
->set_valuetype(Value::V_ERROR
);
6271 Int index
= index_int
->get_val();
6273 index_value
->error("A non-negative integer value was expected "
6274 "for indexing type `%s' instead of `%s'",
6275 get_typename().c_str(), Int2string(index
).c_str());
6276 index_value
->set_valuetype(Value::V_ERROR
);
6277 } else if (index_map
.has_key(index
)) {
6278 index_value
->error("Duplicate index value `%s' for components "
6279 "`%s' and `%s'", Int2string(index
).c_str(),
6280 Int2string((Int
)i
+ 1).c_str(),
6281 Int2string(*index_map
[index
]).c_str());
6282 index_value
->set_valuetype(Value::V_ERROR
);
6284 index_map
.add(index
, new Int((Int
)i
+ 1));
6288 it_comp
->set_my_governor(u
.seof
.ofType
);
6289 u
.seof
.ofType
->chk_this_template_ref(it_comp
);
6290 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(it_comp
,
6291 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6292 SUB_CHK
, implicit_omit
, lhs
);
6294 for (size_t i
= 0; i
< index_map
.size(); i
++)
6295 delete index_map
.get_nth_elem(i
);
6299 t
->error("%s cannot be used for `record of' type `%s'",
6300 t
->get_templatetype_str(), get_typename().c_str());
6306 bool Type::chk_this_template_SetOf(Template
*t
, namedbool is_modified
,
6307 namedbool implicit_omit
, Common::Assignment
*lhs
)
6309 bool self_ref
= false;
6310 Ttcn::Template::templatetype_t temptype
= t
->get_templatetype();
6312 case Ttcn::Template::OMIT_VALUE
:
6313 if(t
->get_length_restriction())
6314 t
->warning("Redundant usage of length restriction with `omit'");
6316 case Ttcn::Template::SUPERSET_MATCH
:
6317 case Ttcn::Template::SUBSET_MATCH
: {
6318 const char *settype
= temptype
== Ttcn::Template::SUPERSET_MATCH
?
6319 "superset" : "subset";
6320 size_t nof_comps
= t
->get_nof_comps();
6321 for (size_t i
= 0; i
< nof_comps
; i
++) {
6322 Template
*t_comp
= t
->get_temp_byIndex(i
);
6323 Error_Context
cntxt(t_comp
, "In element %lu of %s",
6324 (unsigned long) (i
+ 1), settype
);
6325 t_comp
->set_my_governor(u
.seof
.ofType
);
6326 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6327 // the elements of sets must be always complete
6328 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6329 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6330 SUB_CHK
, implicit_omit
, lhs
);
6331 if (t_comp
->get_template_refd_last()->get_templatetype() ==
6332 Ttcn::Template::ANY_OR_OMIT
) {
6333 if (temptype
== Ttcn::Template::SUPERSET_MATCH
)
6334 t_comp
->warning("`*' in superset has no effect during matching");
6335 else t_comp
->warning("`*' in subset. This template will match "
6340 case Ttcn::Template::TEMPLATE_LIST
: {
6341 Ttcn::Template::completeness_t c
=
6342 t
->get_completeness_condition_seof(is_modified
);
6344 size_t nof_base_comps
;
6345 if (c
== Ttcn::Template::C_PARTIAL
) {
6346 t_base
= t
->get_base_template()->get_template_refd_last();
6347 // it is sure that t_base is a TEMPLATE_LIST
6348 nof_base_comps
= t_base
->get_nof_comps();
6353 size_t nof_comps
= t
->get_nof_comps();
6354 for(size_t i
= 0; i
< nof_comps
; i
++) {
6355 Template
*t_comp
= t
->get_temp_byIndex(i
);
6356 Error_Context
cntxt(t_comp
, "In component %lu", (unsigned long)(i
+1));
6357 t_comp
->set_my_governor(u
.seof
.ofType
);
6358 if (t_base
&& i
< nof_base_comps
)
6359 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6360 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6361 switch (t_comp
->get_templatetype()) {
6362 case Ttcn::Template::PERMUTATION_MATCH
:
6363 t_comp
->error("%s cannot be used for `set of' type `%s'",
6364 t_comp
->get_templatetype_str(), get_typename().c_str());
6366 case Ttcn::Template::TEMPLATE_NOTUSED
:
6367 if (c
== Ttcn::Template::C_MUST_COMPLETE
) {
6368 t_comp
->error("Not used symbol `-' is not allowed in this context");
6369 } else if (c
== Ttcn::Template::C_PARTIAL
&& i
>= nof_base_comps
) {
6370 t_comp
->error("Not used symbol `-' cannot be used here because "
6371 "there is no corresponding element in the base template");
6375 bool embedded_modified
= (c
== Ttcn::Template::C_MAY_INCOMPLETE
) ||
6376 (c
== Ttcn::Template::C_PARTIAL
&& i
< nof_base_comps
);
6377 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6378 (embedded_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6379 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6384 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6385 map
<Int
, Int
> index_map
;
6386 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6387 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6388 Value
*index_value
= (it
->get_index()).get_val();
6389 index_value
->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
6390 Template
*it_comp
= it
->get_template();
6391 Error_Context
cntxt(it_comp
, "In component %lu",
6392 (unsigned long)(i
+ 1));
6393 if (index_value
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
6394 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6396 if (*index_int
> INT_MAX
) {
6397 index_value
->error("An integer value less than `%d' was expected "
6398 "for indexing type `%s' instead of `%s'", INT_MAX
,
6399 get_typename().c_str(), (index_int
->t_str()).c_str());
6400 index_value
->set_valuetype(Value::V_ERROR
);
6402 Int index
= index_int
->get_val();
6404 index_value
->error("A non-negative integer value was expected "
6405 "for indexing type `%s' instead of `%s'",
6406 get_typename().c_str(), Int2string(index
).c_str());
6407 index_value
->set_valuetype(Value::V_ERROR
);
6408 } else if (index_map
.has_key(index
)) {
6409 index_value
->error("Duplicate index value `%s' for components "
6410 "`%s' and `%s'", Int2string(index
).c_str(),
6411 Int2string((Int
)i
+ 1).c_str(),
6412 Int2string(*index_map
[index
]).c_str());
6413 index_value
->set_valuetype(Value::V_ERROR
);
6415 index_map
.add(index
, new Int((Int
)i
+ 1));
6419 it_comp
->set_my_governor(u
.seof
.ofType
);
6420 u
.seof
.ofType
->chk_this_template_ref(it_comp
);
6421 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(it_comp
,
6422 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6423 SUB_CHK
, implicit_omit
, lhs
);
6425 for (size_t i
= 0; i
< index_map
.size(); i
++)
6426 delete index_map
.get_nth_elem(i
);
6430 t
->error("%s cannot be used for `set of' type `%s'",
6431 t
->get_templatetype_str(), get_typename().c_str());
6437 bool Type::chk_this_template_array(Template
*t
, namedbool is_modified
,
6438 namedbool implicit_omit
, Common::Assignment
*lhs
)
6440 bool self_ref
= false;
6441 switch (t
->get_templatetype()) {
6442 case Ttcn::Template::OMIT_VALUE
:
6443 if (t
->get_length_restriction())
6444 t
->warning("Redundant usage of length restriction with `omit'");
6446 case Ttcn::Template::PERMUTATION_MATCH
: {
6447 size_t nof_comps
= t
->get_nof_comps();
6448 for (size_t i
= 0; i
< nof_comps
; i
++) {
6449 Template
*t_comp
= t
->get_temp_byIndex(i
);
6450 Error_Context
cntxt(t_comp
, "In element %lu of permutation",
6451 (unsigned long) (i
+ 1));
6452 t_comp
->set_my_governor(u
.array
.element_type
);
6453 u
.array
.element_type
->chk_this_template_ref(t_comp
);
6454 // the elements of permutation must be always complete
6455 self_ref
|= u
.array
.element_type
->chk_this_template_generic(t_comp
,
6456 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6457 NOT_IMPLICIT_OMIT
, lhs
);
6460 case Ttcn::Template::TEMPLATE_LIST
: {
6461 Template
*t_base
= t
->get_base_template();
6462 size_t nof_base_comps
= 0;
6464 t_base
= t_base
->get_template_refd_last();
6465 if (t_base
->get_templatetype() == Ttcn::Template::TEMPLATE_LIST
)
6466 nof_base_comps
= t_base
->get_nof_comps();
6467 else t_base
= 0; // error recovery
6469 if (!u
.array
.dimension
->get_has_error()) {
6470 size_t array_size
= u
.array
.dimension
->get_size();
6471 size_t template_size
= t
->get_nof_listitems();
6472 if (array_size
!= template_size
) {
6473 if (t
->is_flattened()){
6474 t
->error("Too %s elements in the array template: %lu was expected "
6476 array_size
> template_size
? "few" : "many",
6477 (unsigned long)array_size
, (unsigned long)template_size
);
6480 t
->warning("The size of template cannot be resolved "
6481 "so it could not be compared to the array size");
6485 size_t nof_comps
= t
->get_nof_comps();
6486 for (size_t i
= 0; i
< nof_comps
; i
++) {
6487 Template
*t_comp
= t
->get_temp_byIndex(i
);
6488 Error_Context
cntxt(t_comp
, "In array element %lu",
6489 (unsigned long)(i
+ 1));
6490 t_comp
->set_my_governor(u
.array
.element_type
);
6491 if (t_base
&& i
< nof_base_comps
)
6492 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6493 u
.array
.element_type
->chk_this_template_ref(t_comp
);
6494 switch (t_comp
->get_templatetype()) {
6495 case Ttcn::Template::PERMUTATION_MATCH
:
6496 // the elements of permutation has to be checked by u.seof.ofType
6497 // the templates within the permutation always have to be complete
6498 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
6499 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6500 implicit_omit
, lhs
);
6502 case Ttcn::Template::TEMPLATE_NOTUSED
:
6504 t_comp
->error("Not used symbol `-' is not allowed in this "
6508 self_ref
|= u
.array
.element_type
->chk_this_template_generic(t_comp
,
6509 is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6514 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6515 map
<Int
, Int
> index_map
;
6516 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6517 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6518 Value
*index_value
= (it
->get_index()).get_val();
6519 u
.array
.dimension
->chk_index(index_value
,
6520 Type::EXPECTED_DYNAMIC_VALUE
);
6521 Template
*it_comp
= it
->get_template();
6522 Error_Context
cntxt(it_comp
, "In component %lu",
6523 (unsigned long)(i
+ 1));
6524 if (index_value
->get_value_refd_last()
6525 ->get_valuetype() == Value::V_INT
) {
6526 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6528 if (*index_int
> INT_MAX
) {
6529 index_value
->error("An integer value less than `%d' was expected "
6530 "for indexing type `%s' instead of `%s'",
6531 INT_MAX
, get_typename().c_str(),
6532 (index_int
->t_str()).c_str());
6533 index_value
->set_valuetype(Value::V_ERROR
);
6535 Int index
= index_int
->get_val();
6536 if (index_map
.has_key(index
)) {
6537 index_value
->error("Duplicate index value `%s' for components "
6538 "`%s' and `%s'", Int2string(index
).c_str(),
6539 Int2string((Int
)i
+ 1).c_str(),
6540 Int2string(*index_map
[index
]).c_str());
6541 index_value
->set_valuetype(Value::V_ERROR
);
6543 index_map
.add(index
, new Int((Int
)i
+ 1));
6547 it_comp
->set_my_governor(u
.array
.element_type
);
6548 u
.array
.element_type
->chk_this_template_ref(it_comp
);
6549 self_ref
|= u
.array
.element_type
->chk_this_template_generic(it_comp
,
6550 is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6552 for (size_t i
= 0; i
< index_map
.size(); i
++)
6553 delete index_map
.get_nth_elem(i
);
6557 t
->error("%s cannot be used for array type `%s'",
6558 t
->get_templatetype_str(), get_typename().c_str());
6564 void Type::chk_this_template_Fat(Template
*t
)
6566 t
->error("%s cannot be used for type `%s'",t
->get_templatetype_str(),
6567 get_typename().c_str());
6568 if(t
->get_length_restriction()) t
->error("Length restriction is not "
6569 "allowed for type `%s'", get_typename().c_str());
6572 void Type::chk_this_template_Signature(Template
*t
, namedbool is_modified
)
6574 bool self_ref
= false;
6575 size_t n_type_params
= get_nof_comps();
6576 switch (t
->get_templatetype()) {
6577 case Ttcn::Template::TEMPLATE_LIST
:
6578 // conversion: value list -> assignment notation
6579 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
6581 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
6582 map
<string
, Ttcn::NamedTemplate
> comp_map
;
6583 // it is set to false if we have lost the ordering
6584 bool in_synch
= true;
6585 size_t n_template_comps
= t
->get_nof_comps();
6587 for (size_t v_i
= 0; v_i
< n_template_comps
; v_i
++) {
6588 Ttcn::NamedTemplate
*nt
= t
->get_namedtemp_byIndex(v_i
);
6589 const Identifier
& temp_id
= nt
->get_name();
6590 const string
& temp_name
= temp_id
.get_name();
6591 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
6592 if (!has_comp_withName(temp_id
)) {
6593 nt
->error("Reference to non-existent parameter `%s' in template "
6594 "for signature `%s'", temp_dispname_str
, get_typename().c_str());
6597 } else if (comp_map
.has_key(temp_name
)) {
6598 nt
->error("Duplicate parameter `%s' in template for signature `%s'",
6599 temp_dispname_str
, get_typename().c_str());
6600 comp_map
[temp_name
]->note("Parameter `%s' is already given here",
6603 } else comp_map
.add(temp_name
, nt
);
6604 const SignatureParam
*par
=
6605 u
.signature
.parameters
->get_param_byName(temp_id
);
6607 SignatureParam
*par2
= 0;
6608 for ( ; t_i
< n_type_params
; t_i
++) {
6609 par2
= u
.signature
.parameters
->get_param_byIndex(t_i
);
6610 if (par2
== par
) break;
6613 nt
->error("Unexpected parameter `%s' in signature template",
6618 Type
*type
= par
->get_type();
6619 Template
*comp_t
= nt
->get_template();
6620 Error_Context
cntxt(comp_t
, "In template for signature parameter `%s'",
6622 comp_t
->set_my_governor(type
);
6623 type
->chk_this_template_ref(comp_t
);
6624 self_ref
|= type
->chk_this_template_generic(comp_t
, is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_NOT_ALLOWED
,
6625 SUB_CHK
, NOT_IMPLICIT_OMIT
, NULL
);
6628 SignatureParam
*first_undef_in
= NULL
,
6629 *first_undef_out
= NULL
;
6630 for (size_t i
= 0; i
< n_type_params
; i
++) {
6631 SignatureParam
*par
= u
.signature
.parameters
->get_param_byIndex(i
);
6632 const Identifier
& id
= par
->get_id();
6633 if (!comp_map
.has_key(id
.get_name()) ||
6634 comp_map
[id
.get_name()]->get_template()->get_templatetype() ==
6635 Template::TEMPLATE_NOTUSED
) {
6636 switch(par
->get_direction()) {
6637 case SignatureParam::PARAM_IN
:
6638 if(!first_undef_in
) first_undef_in
= par
;
6640 case SignatureParam::PARAM_OUT
:
6641 if(!first_undef_out
) first_undef_out
= par
;
6644 t
->error("Signature template is incomplete, because the inout "
6645 "parameter `%s' is missing", id
.get_dispname().c_str());
6649 if(first_undef_in
!=NULL
&& first_undef_out
!=NULL
)
6650 t
->error("Signature template is incomplete, because the in parameter "
6651 "`%s' and the out parameter `%s' is missing",
6652 first_undef_in
->get_id().get_dispname().c_str(),
6653 first_undef_out
->get_id().get_dispname().c_str());
6658 t
->error("%s cannot be used for signature `%s'",
6659 t
->get_templatetype_str(), get_typename().c_str());
6662 if (t
->get_length_restriction())
6663 t
->error("Length restriction is not allowed in a template for "
6664 "signature `%s'", get_typename().c_str());
6667 } // namespace Common