1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../common/dbgnew.hh"
10 #include "Typestuff.hh" // FIXME CTs
11 #include "CompField.hh"
12 #include "CompType.hh"
13 #include "TypeCompat.hh"
14 #include "EnumItem.hh"
15 #include "SigParam.hh"
17 #include "Valuestuff.hh"
20 #include "ttcn3/Ttcnstuff.hh"
21 #include "ttcn3/TtcnTemplate.hh"
22 #include "ttcn3/Templatestuff.hh"
23 #include "ttcn3/Attributes.hh"
24 #include "ttcn3/ArrayDimensions.hh"
25 #include "ttcn3/PatternString.hh"
27 #include "asn1/Tag.hh"
28 #include "XerAttributes.hh"
31 #include <stdlib.h> // for qsort
34 extern int rawAST_debug
;
38 using Ttcn::MultiWithAttrib
;
39 using Ttcn::SingleWithAttrib
;
40 using Ttcn::WithAttribPath
;
41 using Ttcn::Qualifier
;
42 using Ttcn::Qualifiers
;
46 if(w_attrib_path
) w_attrib_path
->chk_global_attrib();
66 case T_PRINTABLESTRING
:
68 case T_VIDEOTEXSTRING
:
73 case T_UNIVERSALSTRING
:
76 case T_GENERALIZEDTIME
:
77 case T_OBJECTDESCRIPTOR
:
83 case T_UNRESTRICTEDSTRING
:
103 // TODO maybe check for address type and add it automagically, then fall through
108 // If this sequence type has no attributes but one of its fields does,
109 // create an empty attribute structure.
110 if(!rawattrib
&& hasVariantAttrs() && hasNeedofRawAttrs())
111 rawattrib
= new RawAST
;
112 if(!textattrib
&& hasVariantAttrs() && hasNeedofTextAttrs())
113 textattrib
= new TextAST
;
114 if(!xerattrib
&& hasVariantAttrs() && hasNeedofXerAttrs())
115 xerattrib
= new XerAttributes
;
116 if (!jsonattrib
&& (hasVariantAttrs() || hasEncodeAttr(get_encoding_name(CT_JSON
)) || hasNeedofJsonAttrs())) {
117 jsonattrib
= new JsonAST
;
122 // TODO create an empty XerAttrib as above, when ASN.1 gets XER ?
123 // The code was originally for TTCN-only encodings.
128 // TODO create an empty XerAttrib as above, when ASN.1 gets XER ?
143 u
.ref
.type_refd
->chk();
144 u
.ref
.component_internal
= u
.ref
.type_refd
->is_component_internal();
151 if (w_attrib_path
) u
.port
->chk_attributes(w_attrib_path
);
165 FATAL_ERROR("Type::chk()");
169 switch (get_type_refd_last()->typetype
) {
173 // These types may have qualified attributes
175 case T_SEQOF
: case T_SETOF
:
178 w_attrib_path
->chk_no_qualif();
183 if(tags
) tags
->set_plicit(this);
186 Check all non-table subtype constraints. Table/relational constraints
188 TODO: non-relational table constraints shall not be ignored.
190 if (check_subtype
) check_subtype_constraints();
193 * Checking the constraints can be done only if the entire type
194 * (including the nested typedefs) is checked, because the
195 * component relation constraint has to 'look' into other
198 if (!parent_type
) chk_table_constraints();
200 if(rawattrib
|| is_root_basic()){
203 if(textattrib
|| is_root_basic()) {
207 if (jsonattrib
|| is_root_basic()) {
211 // We need to call chk_xer() always because it is collecting
212 // XER attributes from parent types.
218 void Type::parse_attributes()
220 if (raw_parsed
) return;
222 // The type has no attributes of its own; connect it to the nearest group
223 // or the module. This allows global attributes to propagate.
224 for (Type
*t
= this; t
&& w_attrib_path
== 0; t
= t
->parent_type
) {
225 switch (t
->ownertype
) {
227 Ttcn::Def_Type
*pwn
= static_cast<Ttcn::Def_Type
*>(t
->owner
);
228 Ttcn::Group
*nearest_group
= pwn
->get_parent_group();
230 w_attrib_path
= new WithAttribPath
;
231 if (nearest_group
) { // there is a group
232 w_attrib_path
->set_parent(nearest_group
->get_attrib_path());
234 else { // no group, use the module
235 Common::Module
*mymod
= t
->my_scope
->get_scope_mod();
236 // OT_TYPE_DEF is always from a TTCN-3 module
237 Ttcn::Module
*my_ttcn_module
= static_cast<Ttcn::Module
*>(mymod
);
238 w_attrib_path
->set_parent(my_ttcn_module
->get_attrib_path());
244 continue; // try the enclosing type
252 if ((hasVariantAttrs())
253 && (enable_text() || enable_raw() || enable_xer())) {
255 const char *fn
= get_fullname().c_str();
257 fprintf(stderr
, "parse_attributes for %s\n", fn
);
260 bool new_raw
=false; // a RawAST object was allocated here
261 bool new_text
=false; // a TextAST object was allocated here
262 bool new_xer
=false; // a XerAttribute object was allocated here
263 bool new_ber
=false; // a BerAST object was allocated here
264 bool new_json
= false; // a JsonAST object was allocated here
265 bool raw_found
=false; // a raw attribute was found by the parser
266 bool text_found
=false; // a text attribute was found by the parser
267 bool xer_found
=false; // a XER attribute was found by the parser
268 bool ber_found
=false; // a BER attribute was found by the parser
269 bool json_found
= false; // a JSON attribute was found by the parser
272 json_checked
= false;
274 bool override_ref
=false;
275 // Parse RAW attributes
278 ReferenceChain
refch(this, "While checking attributes");
281 // Get all the attributes that apply (from outer scopes too).
282 // Outer (generic) first, inner (specific) last.
283 const vector
<SingleWithAttrib
> & real_attribs
284 = w_attrib_path
->get_real_attrib();
286 // see if there's an encode with override
287 for(size_t i
= real_attribs
.size(); i
> 0 && !override_ref
; i
--)
289 if(real_attribs
[i
-1]->has_override()
290 && real_attribs
[i
-1]->get_attribKeyword()
291 != SingleWithAttrib::AT_ENCODE
)
295 if(!rawattrib
&& !override_ref
){
296 Type
*t
=get_type_refd_last(&refch
);
297 typetype_t basic_type
=t
->typetype
;
298 t
=this; // go back to the beginning
300 while(!t
->rawattrib
&& t
->is_ref()) t
=t
->get_type_refd(&refch
);
301 rawattrib
=new RawAST(t
->rawattrib
,basic_type
==T_INT
);
302 if(!t
->rawattrib
&& basic_type
==T_REAL
) rawattrib
->fieldlength
=64;
305 if(!textattrib
&& !override_ref
){
308 while(!t
->textattrib
&& t
->is_ref()) t
=t
->get_type_refd(&refch
);
309 textattrib
=new TextAST(t
->textattrib
);
312 if (!jsonattrib
&& !override_ref
){
315 while (!t
->jsonattrib
&& t
->is_ref()) {
316 t
= t
->get_type_refd(&refch
);
318 jsonattrib
= new JsonAST(t
->jsonattrib
);
329 case T_CSTR
: // TTCN-3 charstring
331 /* The list of types supporting RAW encoding is described in the
332 * API guide, section 3.3; this batch of labels plus the next three
333 * accurately match the list.
335 * For TEXT, it's section 3.4; the list does not include real and
336 * bin/hex/octet strings
338 case T_USTR
: // TTCN-3 universal charstring, this is an addition for XER attributes
339 case T_VERDICT
: // TTCN-3 verdict, for XER
342 rawattrib
= new RawAST(typetype
==T_INT
);
343 if(typetype
==T_REAL
) rawattrib
->fieldlength
=64;
346 if(textattrib
==NULL
){textattrib
= new TextAST
; new_text
=true;}
347 if (xerattrib
==NULL
) {
348 xerattrib
= new XerAttributes
; new_xer
= true;
350 if (berattrib
==NULL
) {
351 berattrib
= new BerAST
;
355 if (NULL
== jsonattrib
) {
356 jsonattrib
= new JsonAST
;
362 vector
<SingleWithAttrib
> const &real_attribs
363 = w_attrib_path
->get_real_attrib();
364 // These are attributes without qualifiers.
366 size_t nof_elements
= real_attribs
.size();
367 for(size_t i
= 0; i
< nof_elements
; i
++)
369 SingleWithAttrib
*temp_single
= real_attribs
[i
];
370 if (temp_single
->get_attribKeyword() ==
371 SingleWithAttrib::AT_VARIANT
) { // only "variant" is parsed
372 parse_rawAST(rawattrib
, textattrib
, xerattrib
, berattrib
, jsonattrib
,
373 temp_single
->get_attribSpec(), get_length_multiplier(),
374 my_scope
->get_scope_mod(),
375 raw_found
, text_found
, xer_found
, ber_found
, json_found
);
376 // textattrib->print_TextAST();
377 // rawattrib->print_RawAST();
378 // xerattrib->print(get_fullname().c_str());
383 if(!raw_found
&& new_raw
){ delete rawattrib
; rawattrib
=NULL
;}
384 if(!text_found
&& new_text
){ delete textattrib
; textattrib
=NULL
;}
385 if(!xer_found
&& new_xer
){ delete xerattrib
; xerattrib
= NULL
; }
386 if(!ber_found
&& new_ber
){ delete berattrib
; berattrib
= NULL
; }
387 if (!json_found
&& new_json
) {
399 if(rawattrib
==NULL
) {rawattrib
= new RawAST
; new_raw
=true;}
400 if(textattrib
==NULL
){textattrib
= new TextAST
; new_text
=true;}
401 if(xerattrib
==NULL
) {xerattrib
= new XerAttributes
; new_xer
= true;}
402 if(berattrib
==NULL
) {berattrib
= new BerAST
; new_ber
= true;}
403 if (NULL
== jsonattrib
) {
404 jsonattrib
= new JsonAST
;
410 vector
<SingleWithAttrib
> const &real_attribs
411 = w_attrib_path
->get_real_attrib();
413 //calculate the type's attributes (the qualifierless ones)
414 size_t nof_elements
= real_attribs
.size();
415 for(size_t i
= 0; i
< nof_elements
; i
++)
417 SingleWithAttrib
*temp_single
= real_attribs
[i
];
418 if(temp_single
->get_attribKeyword() == SingleWithAttrib::AT_VARIANT
419 && (!temp_single
->get_attribQualifiers()
420 || temp_single
->get_attribQualifiers()->get_nof_qualifiers()
422 // raw/text/xer/ber/json attributes for the whole record/seq.
423 // (own or inherited)
424 parse_rawAST(rawattrib
, textattrib
, xerattrib
, berattrib
, jsonattrib
,
425 temp_single
->get_attribSpec(), get_length_multiplier(),
426 my_scope
->get_scope_mod(),
427 raw_found
, text_found
, xer_found
, ber_found
, json_found
);
430 //calculate the components attributes
431 MultiWithAttrib
* self_attribs
= w_attrib_path
->get_with_attr();
434 MultiWithAttrib
* new_self_attribs
= new MultiWithAttrib
;
435 SingleWithAttrib
* swa
= 0;
437 // copy all the "encode" attributes
438 for(size_t i
= 0; i
< self_attribs
->get_nof_elements(); i
++)
440 if(self_attribs
->get_element(i
)->get_attribKeyword()
441 == SingleWithAttrib::AT_ENCODE
)
443 // Copy the attribute without qualifiers
444 const SingleWithAttrib
* swaref
= self_attribs
->get_element(i
);
445 swa
= new SingleWithAttrib(swaref
->get_attribKeyword(),
446 swaref
->has_override(), 0, swaref
->get_attribSpec().clone());
447 new_self_attribs
->add_element(swa
);
451 if(new_self_attribs
->get_nof_elements() > 0)
452 { // One or more "encode"s were copied; create a context for them.
453 // This is a member because is has to be owned by this Type
454 // (the components only refer to it).
455 encode_attrib_path
= new WithAttribPath
;
456 encode_attrib_path
->set_with_attr(new_self_attribs
);
457 encode_attrib_path
->set_parent(w_attrib_path
->get_parent());
459 else delete new_self_attribs
;
461 // This should be bool, but gcc 4.1.2-sol8 generates incorrect code
463 const int se_of
= (typetype
== T_SEQOF
|| typetype
== T_SETOF
||
464 typetype
== T_ARRAY
);
465 const size_t nof_comps
= se_of
? 1 : get_nof_comps();
467 // Distribute the attributes with qualifiers to the components.
468 // If the type is a sequence-of or set-of, we pretend it to have
469 // one component with the name "_0" (a valid TTCN-3 identifier
470 // can't begin with an underscore). compiler.y has created
471 // the appropriate identifier in the qualifier for a "[-]".
472 for(size_t i
= 0; i
< nof_comps
; i
++)
474 const Identifier
& comp_id
=
475 se_of
? underscore_zero
: get_comp_id_byIndex(i
);
476 MultiWithAttrib
* component_attribs
= new MultiWithAttrib
;
478 for(size_t j
= 0; j
< self_attribs
->get_nof_elements(); j
++)
480 const SingleWithAttrib
*temp_single
=
481 self_attribs
->get_element(j
);
482 Qualifiers
* temp_qualifiers
=
483 temp_single
->get_attribQualifiers();
485 || temp_qualifiers
->get_nof_qualifiers() == 0) continue;
487 Qualifiers
* calculated_qualifiers
= new Qualifiers
;
488 bool qualifier_added
= false;
489 for(size_t k
=0; k
< temp_qualifiers
->get_nof_qualifiers(); )
491 const Qualifier
* temp_qualifier
=
492 temp_qualifiers
->get_qualifier(k
);
493 if(temp_qualifier
->get_nof_identifiers() > 0
494 && (*temp_qualifier
->get_identifier(0) == comp_id
))
496 // Found a qualifier whose first identifier matches
497 // the component name. Remove the qualifier from the
498 // enclosing type, chop off its head,
499 // and add it to the component's qualifiers.
500 calculated_qualifiers
->add_qualifier(
501 temp_qualifier
->get_qualifier_without_first_id());
502 temp_qualifiers
->delete_qualifier(k
);
503 qualifier_added
= true;
510 // A copy of temp_single, with new qualifiers
511 SingleWithAttrib
* temp_single2
512 = new SingleWithAttrib(temp_single
->get_attribKeyword(),
513 temp_single
->has_override(),
514 calculated_qualifiers
,
515 temp_single
->get_attribSpec().clone());
516 temp_single2
->set_location(*temp_single
);
517 component_attribs
->add_element(temp_single2
);
519 else delete calculated_qualifiers
;
522 if (component_attribs
->get_nof_elements() > 0) {
523 Type
* component_type
= se_of
?
524 get_ofType() : get_comp_byIndex(i
)->get_type();
526 if(encode_attrib_path
)
527 // The record's "encode" attributes (only) apply to the fields.
528 // Interpose them in the path of the field.
529 component_type
->set_parent_path(encode_attrib_path
);
531 component_type
->set_parent_path(w_attrib_path
->get_parent());
533 component_type
->set_with_attr(component_attribs
);
535 else delete component_attribs
;
536 } // next component index
538 // Any remaining attributes with qualifiers are erroneous
539 for(size_t i
= 0; i
< self_attribs
->get_nof_elements();)
541 Qualifiers
*temp_qualifiers
= self_attribs
->get_element(i
)
542 ->get_attribQualifiers();
543 if(temp_qualifiers
&& temp_qualifiers
->get_nof_qualifiers() != 0)
545 size_t nof_qualifiers
= temp_qualifiers
->get_nof_qualifiers();
546 for(size_t j
= 0; j
< nof_qualifiers
; j
++)
548 const Qualifier
*temp_qualifier
=
549 temp_qualifiers
->get_qualifier(j
);
550 const Identifier
& tmp_id
= *temp_qualifier
->get_identifier(0);
551 // Special case when trying to reference the inner type
552 // of a record-of when it wasn't a record-of.
553 if (tmp_id
== underscore_zero
) temp_qualifier
->error(
554 "Invalid field qualifier [-]");
555 else temp_qualifier
->error("Invalid field qualifier %s",
556 tmp_id
.get_dispname().c_str());
558 self_attribs
->delete_element(i
);
563 } // end if(self_attribs)
564 } // end if(w_attrib_path)
565 if (!raw_found
&& new_raw
) { delete rawattrib
; rawattrib
= NULL
; }
566 if (!text_found
&& new_text
){ delete textattrib
; textattrib
= NULL
; }
567 if (!xer_found
&& new_xer
) { delete xerattrib
; xerattrib
= NULL
; }
568 if (!ber_found
&& new_ber
) { delete berattrib
; berattrib
= NULL
; }
569 if (!json_found
&& new_json
) {
575 // nothing to do, ASN1 types or types without defined raw attribute
578 if (rawattrib
&& !enable_raw()) { delete rawattrib
; rawattrib
= NULL
;}
579 if (textattrib
&& !enable_text()){ delete textattrib
; textattrib
= NULL
;}
580 if (xerattrib
&& !enable_xer()) { delete xerattrib
; xerattrib
= NULL
;}
581 if (berattrib
&& !enable_ber()) { delete berattrib
; berattrib
= NULL
;}
582 if (NULL
!= jsonattrib
&& !enable_json()) {
586 } // endif( hasVariantAttrs && enable_{raw,text,xer} )
591 // Implements "NAME AS ..." transformations.
592 void change_name(string
&name
, XerAttributes::NameChange change
) {
593 switch (change
.kw_
) {
594 case NamespaceSpecification::NO_MANGLING
:
595 break; // cool, nothing to do!
597 case NamespaceSpecification::UPPERCASED
:
598 // Walking backwards calls size() only once. Loop var must be signed.
599 for (int i
= name
.size()-1; i
>= 0; --i
) {
600 name
[i
] = toupper(name
[i
]);
604 case NamespaceSpecification::LOWERCASED
:
605 for (int i
= name
.size()-1; i
>= 0; --i
) {
606 name
[i
] = tolower(name
[i
]);
610 case NamespaceSpecification::CAPITALIZED
:
611 name
[0] = toupper(name
[0]);
614 case NamespaceSpecification::UNCAPITALIZED
:
615 name
[0] = tolower(name
[0]);
618 default: // explicitly specified name
624 void Type::chk_xer_any_attributes()
626 Type
* const last
= get_type_refd_last();
627 switch (last
->typetype
== T_SEQOF
?
628 last
->u
.seof
.ofType
->get_type_refd_last()->typetype
: 0) {
629 case T_UTF8STRING
: // SEQUENCE OF UTF8String, ASN.1
630 case T_USTR
: // record of universal charstring
634 error("ANY-ATTRIBUTES can only be applied to record of string");
638 switch (parent_type
!= NULL
? parent_type
->typetype
: 0) {
639 case T_SEQ_A
: case T_SET_A
:
640 case T_SEQ_T
: case T_SET_T
:
641 for (size_t x
= 0; x
< parent_type
->get_nof_comps(); ++x
) {
642 CompField
* cf
= parent_type
->get_comp_byIndex(x
);
643 if (cf
->get_type() != this) continue;
644 if (cf
->has_default()) {
645 error("The field with ANY-ATTRIBUTES cannot have DEFAULT");
650 error("ANY-ATTRIBUTES can only be applied to a member of "
651 "SEQUENCE, SET, record or set");
655 if (xerattrib
->untagged_
656 || (parent_type
&& parent_type
->xerattrib
&& parent_type
->xerattrib
->untagged_
)) {
657 error("Neither the type with ANY-ATTRIBUTES, nor its enclosing type "
658 "may be marked UNTAGGED");
662 void Type::chk_xer_any_element()
664 Type
*const last
= get_type_refd_last();
665 switch (last
->typetype
) {
666 case T_UTF8STRING
: // UTF8String, ASN.1
667 case T_USTR
: // universal charstring
670 /* A special case for TTCN-3 where applying ANY-ELEMENT to the record-of
671 * has the same effect as applying it to the string member.
672 * This should no longer be necessary now that we can refer
673 * to the embedded type of a record-of with [-], but it has to stay
674 * unless the standard deprecates it. */
675 Type
*oftype
= last
->u
.seof
.ofType
;
676 if (oftype
->xerattrib
== 0) oftype
->xerattrib
= new XerAttributes
;
677 // Transfer the ANY-ATTRIBUTE from the record-of to its member type
678 oftype
->xerattrib
->anyElement_
= xerattrib
->anyElement_
;
679 xerattrib
->anyElement_
.nElements_
= 0;
680 xerattrib
->anyElement_
.uris_
= 0;
681 // Re-check the member type since we fiddled with it
682 const char * type_name
= "record of";
683 Error_Context
cntxt(this, "In embedded type of %s", type_name
);
684 oftype
->xer_checked
= false;
688 error("ANY-ELEMENT can only be applied to UTF8String "
689 "or universal charstring type");
693 if (xerattrib
->attribute_
|| xerattrib
->base64_
|| xerattrib
->untagged_
694 || xerattrib
->defaultForEmpty_
!= NULL
695 || xerattrib
->whitespace_
!= XerAttributes::PRESERVE
) {
696 error("A type with ANY-ELEMENT may not have any of the following encoding instructions: "
697 "ATTRIBUTE, BASE64, DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED or WHITESPACE");
701 void Type::chk_xer_attribute()
703 if (xerattrib
->element_
) {
704 error("ELEMENT and ATTRIBUTE are incompatible");
707 switch (parent_type
!=NULL
? parent_type
->typetype
:-0) {
708 case 0: // no parent accepted in case a field of this type is declared
709 case T_SEQ_A
: case T_SEQ_T
:
710 case T_SET_A
: case T_SET_T
:
713 error("A type with ATTRIBUTE must be a member of "
714 "SEQUENCE, SET, record or set");
718 if (xerattrib
->untagged_
719 || (parent_type
&& parent_type
->xerattrib
&& parent_type
->xerattrib
->untagged_
)) {
720 error("Neither the type with ATTRIBUTE, nor its enclosing type "
721 "may be marked UNTAGGED");
724 if (has_ae(xerattrib
)) {
725 // TODO: || (xerattrib->defaultForEmpty_ && it is an ASN.1 type)
726 // DEFAULT-FOR-EMPTY is allowed only for TTCN-3
727 error("A type with ATTRIBUTE shall not also have any of the final "
728 "encoding instructions ANY-ELEMENT" /*", DEFAULT-FOR-EMPTY"*/ " or PI-OR-COMMENT");
734 /// Pointer to the field
736 /// The type of the field
738 /// The ultimate type, top->get_type_refd_last()
740 /// The typetype of last, on which we sort. Its name is meant to be
741 /// mnemonic (it belongs to \c last, not \c top)
742 Type::typetype_t lastt
;
745 /// Comparison function for CFCache based on typetype
746 int tcomp(const void *l
, const void *r
)
748 int retval
= ((const CFCache
*)l
)->lastt
- ((const CFCache
*)r
)->lastt
;
752 /** Find the original component name if it was changed by TEXT
754 * If there is a TEXT whose \a new_text matches \p text, return
755 * the corresponding \a target.
757 * If there are no TEXT coding instructions, always returns \p text.
759 * @param[in,out] text on input, a name possibly modified by any TEXT encoding
760 * instruction; on output, the actual component name
762 void Type::target_of_text(string
& text
)
764 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
765 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
767 if ((unsigned long)txt
.prefix
== 0
768 ||(unsigned long)txt
.prefix
== NamespaceSpecification::ALL
) {
769 FATAL_ERROR("Type::target_of_text()");
773 string
target(txt
.target
);
775 switch ((unsigned long)txt
.new_text
) {
776 case NamespaceSpecification::CAPITALIZED
: // tARGET -> TARGET
777 target
[0] = toupper(target
[0]);
779 case NamespaceSpecification::UNCAPITALIZED
:
780 target
[0] = tolower(target
[0]); // TARGET -> tARGET
782 case NamespaceSpecification::UPPERCASED
:
783 for (int si
= target
.size() - 1; si
>= 0; --si
) {
784 target
[si
] = toupper(target
[si
]);
787 case NamespaceSpecification::LOWERCASED
:
788 for (int si
= target
.size() - 1; si
>= 0; --si
) {
789 target
[si
] = tolower(target
[si
]);
793 case 0: // "text" not possible
794 FATAL_ERROR("Type::target_of_text() Text with no target and DFE");
797 default: // it's a string, "text 'field' as 'string'"
802 if (target
== text
) {
803 text
= txt
.target
; // we want the value before the change
809 // The suffix of the name of the variable which contains the D-F-E value.
810 static const string
dfe_suffix("_dfe");
812 /** Construct a Value to represent defaultForEmpty
814 * @param last pointer to a Type which is the end of the reference chain,
815 * usually this->get_type_refd_last()
816 * @param dfe_str string containing the value from defaultForEmpty
817 * @return a newly allocated Common::Value
819 Value
*Type::new_value_for_dfe(Type
*last
, const char *dfe_str
)
821 string
defaultstring(dfe_str
);
822 switch (last
->typetype
) {
826 return new Value(Common::Value::V_CSTR
,
827 new string(defaultstring
));
831 return new Value(Common::Value::V_INT
,
832 new int_val_t(dfe_str
, *this));
835 const Real
& rval
= string2Real(dfe_str
, *this);
836 return new Value(Value::V_REAL
, rval
);
840 if (!strcmp(dfe_str
, "true")
841 ||!strcmp(dfe_str
, "1")) {
842 return new Value(Value::V_BOOL
, true);
844 else if (!strcmp(dfe_str
, "false")
845 || !strcmp(dfe_str
, "0")) {
846 return new Value(Value::V_BOOL
, false);
848 else error("Invalid boolean default value");
852 case T_ENUM_A
: case T_ENUM_T
: {
853 // If there is a TEXT, the DFE value corresponds to TextToBeUsed.
854 // Fetch the "real" name of the field (Target).
856 target_of_text(defaultstring
);
858 Identifier
*val_id
= new Identifier(Common::Identifier::ID_TTCN
, // FIXME when ASN1 is supported
861 if (!last
->has_ei_withName(*val_id
)) {
862 error("No enumeration item item '%s'", defaultstring
.c_str());
864 for (size_t ee
=0; ee
< last
->u
.enums
.eis
->get_nof_eis(); ++ee
) {
865 note("Maybe %s", last
->u
.enums
.eis
->get_ei_byIndex(ee
)->get_name().get_name().c_str());
870 return new Value(Common::Value::V_ENUM
, val_id
);
873 case T_CHOICE_A
: case T_CHOICE_T
: {
874 // Try to guess which alternative the given DFE text belongs to.
875 // Sort the fields based on typetype, so BOOL, INT, REAL, ENUM
876 // are tried before the various string types
877 // (any string looks 'right' for a string value).
878 size_t num_comps
= last
->get_nof_comps();
879 CFCache
*sorted
= new CFCache
[num_comps
];
880 for (size_t c
= 0; c
< num_comps
; c
++) {
881 CompField
*cf
= last
->get_comp_byIndex(c
);
882 Type
*cft
= cf
->get_type();
883 Type
*cftlast
= cft
->get_type_refd_last();
886 sorted
[c
].last
= cftlast
;
887 sorted
[c
].lastt
= cftlast
->typetype
;
889 qsort(sorted
, num_comps
, sizeof(CFCache
), tcomp
);
893 for (c
= 0; c
< num_comps
&& retval
== 0; c
++) {
894 CFCache
¤t
= sorted
[c
];
895 // We can't just call new_value_for_dfe(), because some alternatives
896 // would generate errors even if a later type could accept the value.
897 switch (current
.lastt
) {
899 if (!strcmp(dfe_str
, "true")
900 ||!strcmp(dfe_str
, "1")) {
901 retval
= new Value(Value::V_BOOL
, true);
903 else if (!strcmp(dfe_str
, "false")
904 || !strcmp(dfe_str
, "0")) {
905 retval
= new Value(Value::V_BOOL
, false);
909 case T_INT
: case T_INT_A
: {
910 const char *start
= dfe_str
, *end
;
911 while (isspace((const unsigned char)*start
)) ++start
;
912 if (*start
== '+') ++start
;
913 int ndigits
= BN_dec2bn(NULL
, start
); // includes any '-' sign
914 end
= start
+ ndigits
;
915 // Pretend that all trailing whitespace characters were digits
916 while (isspace(*end
)) ++ndigits
, ++end
;
918 // Check that all the string was used up in the conversion,
919 // otherwise "3.1415" and "1e6" would appear as integers.
920 if (defaultstring
.size() == (size_t)ndigits
+ (start
- dfe_str
)) {
921 retval
= current
.top
->new_value_for_dfe(current
.last
, start
);
928 int num_converted
= sscanf(dfe_str
, "%f %1s", &f
, tail
);
929 // If tail was converted (num_converted>1) that's an error
930 if (num_converted
== 1) { // sscanf was happy
931 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
935 case T_ENUM_A
: case T_ENUM_T
: {
936 current
.top
->target_of_text(defaultstring
);
937 Identifier
alt(Identifier::ID_TTCN
, defaultstring
);
938 if (current
.last
->has_ei_withName(alt
)) {
939 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
946 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
956 retval
->set_genname(sorted
[c
].top
->genname
, dfe_suffix
);
957 retval
->set_my_scope(sorted
[c
].top
->my_scope
);
958 retval
->set_my_governor(sorted
[c
].top
);
959 Value
*choice_retval
= new Value(Value::V_CHOICE
,
960 new Identifier(sorted
[c
].cf
->get_name()), retval
);
961 retval
= choice_retval
;
967 /* Useless without a properly constructed Value(V_SEQ)
968 case T_SEQ_A: case T_SEQ_T: {
969 NamedValues *nvs = new NamedValues;
970 //NamedValue *nv = new NamedValue(new Identifier, new Value);
972 xerattrib->defaultValue_ = new Value(Value::V_SEQ, nvs);
976 default: // complain later
982 void Type::chk_xer_dfe()
984 Type
* const last
= get_type_refd_last();
986 if (/* TODO xerattrib->attribute_ is error for ASN.1 only */
987 xerattrib
->untagged_
|| has_ae(xerattrib
)) {
988 error("A type with DEFAULT-FOR-EMPTY shall not have any of the final "
989 "encoding instructions ANY-ELEMENT, ATTRIBUTE, UNTAGGED."); // 23.2.8
992 if (is_charenc() == Yes
) {
993 xerattrib
->defaultValue_
= new_value_for_dfe(last
, xerattrib
->defaultForEmpty_
);
995 if (xerattrib
->defaultValue_
!= 0) {
996 xerattrib
->defaultValue_
->set_genname(this->genname
, dfe_suffix
);
997 xerattrib
->defaultValue_
->set_my_scope(this->my_scope
);
998 xerattrib
->defaultValue_
->set_my_governor(last
);
1001 error("DEFAULT-FOR-EMPTY not supported for character-encodable type %s",
1002 last
->get_stringRepr().c_str());
1005 else if (last
->typetype
== T_SEQ_A
|| last
->typetype
== T_SEQ_T
) {
1006 // If DEFAULT-FOR-EMPTY applies to a record (SEQUENCE), then only one
1007 // component can produce element content, and it should be the last,
1008 // because all the others should have ATTRIBUTE or ANY-ATTRIBUTE,
1009 // and those are moved to the front. 23.2.2 b)
1010 // FIXME only b) appears to have this restriction, not c)d)e)
1011 const size_t num_cf
= last
->get_nof_comps();
1013 CompField
*cf
= last
->get_comp_byIndex(num_cf
-1); // last field
1014 Type
*cft
= cf
->get_type(); // cft: CompField type
1015 cft
= cft
->get_type_refd_last();
1016 //typetype_t cftt = cft->get_typetype();
1018 xerattrib
->defaultValue_
= new_value_for_dfe(cft
, xerattrib
->defaultForEmpty_
);
1019 if (xerattrib
->defaultValue_
!= 0) {
1020 xerattrib
->defaultValue_
->set_genname(last
->genname
, string("_dfe"));
1021 xerattrib
->defaultValue_
->set_my_scope(cft
->my_scope
);
1022 xerattrib
->defaultValue_
->set_my_governor(cft
);
1025 error("DEFAULT-FOR-EMPTY not supported for fields of type %s",
1026 cft
->get_stringRepr().c_str());
1031 error("DEFAULT-FOR-EMPTY not applicable to type");
1035 void Type::chk_xer_embed_values(int num_attributes
)
1037 Type
* const last
= get_type_refd_last();
1039 enum complaint_type
{ ALL_GOOD
, HAVE_DEFAULT
, UNTAGGED_EMBEDVAL
,
1040 NOT_SEQUENCE
, EMPTY_SEQUENCE
, FIRST_NOT_SEQOF
, SEQOF_NOT_STRING
,
1041 SEQOF_BAD_LENGTH
, UNTAGGED_OTHER
} ;
1042 complaint_type complaint
= ALL_GOOD
;
1043 size_t expected_length
= (size_t)-1;
1044 Type
*cf0t
= 0; // type of first component
1046 switch (last
->typetype
) {
1047 case T_SEQ_A
: case T_SEQ_T
: { // 25.2.1, the type must be a sequence
1048 const size_t num_cf
= last
->get_nof_comps();
1050 complaint
= EMPTY_SEQUENCE
; // must have a "first component"
1053 CompField
*cf0
= last
->get_comp_byIndex(0);
1054 cf0t
= cf0
->get_type()->get_type_refd_last();
1055 if (cf0
->has_default()) {
1056 complaint
= HAVE_DEFAULT
;
1057 break; // 25.2.1 first component cannot have default
1060 switch (cf0t
->get_typetype()) { // check the first component
1062 Type
*cfot
= cf0t
->get_ofType(); // embedded type
1063 switch (cfot
->get_type_refd_last()->get_typetype()) {
1065 case T_USTR
: { // hooray, a SEQUENCE OF some string
1066 if ( (cf0t
->xerattrib
&& cf0t
->xerattrib
->untagged_
)
1067 || (cfot
->xerattrib
&& cfot
->xerattrib
->untagged_
)) {
1068 complaint
= UNTAGGED_EMBEDVAL
; // 25.2.2
1072 // Check length restriction on the record of. If there is one,
1073 // it better be the correct number.
1074 // FIXME: if there is also a USE-NIL, it cannot have a length restriction; only check at runtime
1075 const SubType
*sub
= cf0t
->sub_type
;
1076 const Int len
= sub
? sub
->get_length_restriction() :-1;
1077 // get_length_restriction() itself may return -1
1078 expected_length
= num_cf
-num_attributes
-xerattrib
->useOrder_
;
1079 if (len
> 0 && (size_t)len
!= expected_length
) {
1080 // The +1 from 25.2.6 b) is compensated because
1081 // the EMBED-VALUES member itself is ignored.
1082 complaint
= SEQOF_BAD_LENGTH
;
1085 break; } //acceptable
1088 complaint
= SEQOF_NOT_STRING
;
1094 complaint
= FIRST_NOT_SEQOF
;
1096 } // switch(type of first component)
1098 for (size_t c
= 1; c
< num_cf
; ++c
) { // check the other components
1099 cf
= last
->get_comp_byIndex(c
);
1100 Type
*cft
= cf
->get_type()->get_type_refd_last();
1101 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
&& (cft
->is_charenc() == Yes
)){
1102 complaint
= UNTAGGED_OTHER
;
1106 break; } // case T_SEQ*
1109 complaint
= NOT_SEQUENCE
;
1111 } // switch typetype
1113 // TODO 25.2.4, 25.2.5
1114 if (complaint
== ALL_GOOD
) embed_values_possible
= true;
1115 else if (xerattrib
->embedValues_
) {
1116 switch (complaint
) {
1117 case ALL_GOOD
: // Not possible; present in the switch so GCC checks
1118 // that all enum values are handled (make sure there's no default).
1121 case EMPTY_SEQUENCE
:
1122 case FIRST_NOT_SEQOF
:
1123 case SEQOF_NOT_STRING
:
1125 error("A type with EMBED-VALUES must be a sequence type. "
1126 "The first component of the sequence shall be SEQUENCE OF UTF8String "
1127 "and shall not be marked DEFAULT");
1129 case SEQOF_BAD_LENGTH
:
1130 cf0t
->error("Wrong length of SEQUENCE-OF for EMBED-VALUES, should be %lu",
1131 (unsigned long)expected_length
);
1133 case UNTAGGED_EMBEDVAL
:
1134 error("Neither the SEQUENCE-OF supporting EMBED-VALUES,"
1135 "nor its component shall have UNTAGGED."); // 25.2.2
1137 case UNTAGGED_OTHER
:
1138 cf
->error("There shall be no UNTAGGED on any character-encodable "
1139 "component of a type with DEFAULT-FOR-EMPTY"); // 25.2.3
1141 } // switch(complaint)
1142 } // if complaint and embedValues
1144 /** Wraps a C string but compares by contents, not by pointer */
1148 explicit stringval(const char *s
= 0) : str(s
) {}
1150 bool operator<(const stringval
& right
) const {
1151 if ( str
> (const char*)NamespaceSpecification::ALL
1152 && right
.str
> (const char*)NamespaceSpecification::ALL
)
1154 return strcmp(str
, right
.str
) < 0;
1156 else return str
< right
.str
;
1158 bool operator==(const stringval
& right
) const {
1159 if ( str
> (const char*)NamespaceSpecification::ALL
1160 && right
.str
> (const char*)NamespaceSpecification::ALL
)
1162 return strcmp(str
, right
.str
) == 0;
1164 else return str
== right
.str
;
1166 //bool operator!() const { return str==0; }
1167 const char *c_str() const { return str
; }
1171 void Type::chk_xer_text()
1173 if (xerattrib
->num_text_
== 0
1174 ||xerattrib
->text_
== 0 ) FATAL_ERROR("Type::chk_xer_text()");
1175 Type
* const last
= get_type_refd_last();
1176 static const stringval empty
; // NULL pointer
1178 // Check the type and quit early if wrong
1179 switch (last
->typetype
) {
1182 case T_ENUM_A
: // not yet
1183 error("No XER yet for ASN.1 enumerations");
1187 case T_BSTR_A
: // ASN.1 bit string with named bits, not yet
1188 error("No XER yet for ASN.1 bit strings");
1190 case T_INT_A
: // ASN.1 integer with named numbers, not yet
1191 error("No XER yet for ASN.1 named numbers");
1194 error("TEXT not allowed for type %s", get_typename().c_str());
1198 // Build a map to eliminate duplicates (new assignment to the same
1199 // enum item/field overwrites previous text).
1200 // Keys are the identifiers, values are the texts.
1201 typedef map
<stringval
, char> text_map_t
;
1202 text_map_t text_map
;
1204 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1205 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
1206 switch ((unsigned long)txt
.target
) {
1207 case 0: { // just "TEXT".
1208 // target=0 and new_text!=0 would have to come from "TEXT AS ..."
1209 // but that's not allowed by syntax, hence FATAL_ERROR.
1210 if (txt
.new_text
) FATAL_ERROR("Type::chk_xer_text");
1211 if (!text_map
.has_key(empty
)) {
1212 text_map
.add(empty
, txt
.new_text
);
1214 if (last
->typetype
!= T_BOOL
) {
1215 error("Lone 'TEXT' only allowed for boolean"); // only in TTCN-3 !
1219 case NamespaceSpecification::ALL
: {// TEXT ALL AS ...
1220 switch (txt
.keyword
) {
1221 case NamespaceSpecification::NO_MANGLING
:
1222 // Not possible due to syntax; there is no TTCN source from which
1223 // the bison parser would create such a NamespaceSpecification.
1224 FATAL_ERROR("Type::chk_xer_text");
1226 case NamespaceSpecification::CAPITALIZED
:
1227 case NamespaceSpecification::UNCAPITALIZED
:
1228 case NamespaceSpecification::LOWERCASED
:
1229 case NamespaceSpecification::UPPERCASED
:
1232 default: // TEXT ALL AS "some string" is not allowed
1233 error("text all as 'string' is not allowed");
1235 } // switch(keyword)
1238 switch (last
->typetype
) {
1240 text_map
.add(stringval(mcopystr("true")), txt
.new_text
);
1241 text_map
.add(stringval(mcopystr("false")), txt
.new_text
);
1246 size_t n_eis
= last
->u
.enums
.eis
->get_nof_eis();
1247 for (size_t i
= 0; i
< n_eis
; ++i
) {
1248 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byIndex(i
);
1249 const stringval
enum_name(mcopystr(ei
->get_name().get_ttcnname().c_str()));
1250 if (text_map
.has_key(enum_name
)) {
1251 // Duplicate enum name, flagged elsewhere as error.
1252 // Don't bother with: text_map[enum_name] = txt.new_text;
1253 Free(const_cast<char*>(enum_name
.c_str()));
1255 else text_map
.add(enum_name
, txt
.new_text
);
1260 FATAL_ERROR("Type::chk_xer_text");
1262 } // switch (typetype)
1266 default: {// a string: TEXT 'member' AS ...
1267 if (txt
.keyword
== NamespaceSpecification::NO_MANGLING
) {
1268 // Attribute syntax does not allow this combination
1269 FATAL_ERROR("Type::chk_xer_text");
1271 // HR39956: empty string is disregarded
1272 if (txt
.keyword
>NamespaceSpecification::LOWERCASED
&& !strcmp(txt
.new_text
,""))
1274 txt
.new_text
= (char*)Realloc(txt
.new_text
, sizeof(" "));
1275 strcpy(txt
.new_text
," ");
1277 stringval
ttarget(txt
.target
);
1278 if (text_map
.has_key(ttarget
)) {
1279 // Override the earlier TEXT instruction
1280 free_name_or_kw(text_map
[ttarget
]);
1281 text_map
[ttarget
] = txt
.new_text
;
1282 free_name_or_kw(txt
.target
);
1284 else text_map
.add(ttarget
, txt
.new_text
);
1289 xerattrib
->text_
= (NamespaceSpecification
*)Realloc(xerattrib
->text_
,
1290 text_map
.size() * sizeof(NamespaceSpecification
));
1292 // Zero out the newly allocated part
1293 if (text_map
.size() > xerattrib
->num_text_
) {
1295 xerattrib
->text_
+ xerattrib
->num_text_
,
1297 (text_map
.size() - xerattrib
->num_text_
) * sizeof(NamespaceSpecification
)
1301 xerattrib
->num_text_
= text_map
.size(); // accept the new size
1303 // Another map, to check for duplicate text (decoding would be impossible)
1306 // Reconstruct the TEXT structure from the map
1307 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1308 const stringval
& k
= text_map
.get_nth_key(t
);
1309 char * v
= text_map
.get_nth_elem(t
);
1310 char * newstr
= const_cast<char*>(k
.c_str());
1312 xerattrib
->text_
[t
].target
= newstr
;
1313 xerattrib
->text_
[t
].new_text
= v
;
1315 stringval
txtval(v
); // somebody else owns v
1316 if (map2
.has_key(txtval
)) {
1317 switch (xerattrib
->text_
[t
].keyword
) {
1318 case NamespaceSpecification::NO_MANGLING
:
1319 FATAL_ERROR("nope");
1320 break; // not possible
1322 case NamespaceSpecification::CAPITALIZED
:
1323 case NamespaceSpecification::UNCAPITALIZED
:
1324 case NamespaceSpecification::LOWERCASED
:
1325 case NamespaceSpecification::UPPERCASED
:
1326 // Duplication may have been caused by expanding TEXT ALL ...
1329 default: // string must be unique
1330 error("Duplicate text '%s'", v
);
1334 else map2
.add(txtval
, newstr
);
1339 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1340 if (xerattrib
->useNumber_
) {
1341 error("USE-NUMBER and TEXT are incompatible");
1344 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
1346 switch (last
->typetype
) {
1348 /* In ASN.1, Only Booleantype:ALL can have TEXT
1349 * Currently for TTCN, only the following three case are supported:
1351 * "text 'true' as '1'"
1352 * "text 'false' as '0'"
1353 * and we convert the last two to the first
1355 switch ((unsigned long)txt
.prefix
) {
1356 case 0: // no Target (ok);
1357 if (txt
.uri
!= 0) error("Only \"text\" implemented for boolean");
1359 case NamespaceSpecification::ALL
: // Target = 'all' not allowed for boolean
1360 error("TEXT all not implemented for boolean");
1362 default: // a string, must be "true" or "false"
1363 if (!strcmp(txt
.prefix
, "true")) {
1364 // only "1" is allowed for "true"
1365 switch ((unsigned long)txt
.uri
) {
1366 default: // it's a string
1367 if (txt
.uri
[0] == '1' && txt
.uri
[1] == '\0') {
1368 // Free the strings to pretend it was a simple "text"
1369 Free(txt
.prefix
); txt
.prefix
= 0;
1370 Free(txt
.uri
); txt
.uri
= 0;
1371 // These should come in pairs, warn if not
1372 if (xerattrib
->num_text_
== 1) warning("\"text 'false' as '0'\" was implied");
1375 // else fall through
1376 case NamespaceSpecification::CAPITALIZED
:
1377 case NamespaceSpecification::UNCAPITALIZED
:
1378 case NamespaceSpecification::UPPERCASED
:
1379 case NamespaceSpecification::LOWERCASED
:
1380 error("Only '1' is supported for 'true'");
1383 case 0: // "text 'true'" is not correct syntax, cannot get here
1384 FATAL_ERROR("Type::chk_xer_text()");
1387 else if (!strcmp(txt
.prefix
, "false")) {
1388 // only "0" is allowed for "false"
1389 switch ((unsigned long)txt
.uri
) {
1390 default: // it's a string
1391 if (txt
.uri
[0] == '0' && txt
.uri
[1] == '\0') {
1392 // Free the strings to pretend it was a simple "text"
1393 Free(txt
.prefix
); txt
.prefix
= 0;
1394 Free(txt
.uri
); txt
.uri
= 0;
1395 // These should come in pairs, warn if not
1396 if (xerattrib
->num_text_
== 1) warning("\"text 'true' as '1'\" was implied");
1399 // else fall through
1400 case NamespaceSpecification::CAPITALIZED
:
1401 case NamespaceSpecification::UNCAPITALIZED
:
1402 case NamespaceSpecification::UPPERCASED
:
1403 case NamespaceSpecification::LOWERCASED
:
1404 error("Only '0' is supported for 'false'");
1407 case 0: // "text 'false'" is not correct syntax, cannot get here
1408 FATAL_ERROR("Type::chk_xer_text()");
1416 //case T_ENUM_A: // fall through
1418 switch ((unsigned long)txt
.target
) {
1419 case 0: // "text as ..."
1420 case NamespaceSpecification::ALL
: { // "text all as ..."
1421 size_t neis
= last
->u
.enums
.eis
->get_nof_eis();
1422 for (size_t i
= 0; i
< neis
; ++i
) {
1423 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byIndex(i
);
1424 string
ei_name(ei
->get_name().get_dispname()); // use the element's own name
1425 XerAttributes::NameChange chg
;
1427 change_name(ei_name
, chg
);
1428 ei
->set_text(ei_name
);
1432 default: { // target is member name, from "text 'member' as ..."
1433 // FIXME: ID_TTCN will not be right if we implement XER for ASN.1
1434 Common::Identifier
id(Identifier::ID_TTCN
, string(txt
.prefix
));
1435 if (last
->u
.enums
.eis
->get_nof_eis()==0) FATAL_ERROR("No enum items!");
1436 if (last
->u
.enums
.eis
->has_ei_withName(id
)) {
1437 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byName(id
);
1438 string
ei_name(id
.get_dispname());
1439 XerAttributes::NameChange chg
;
1441 change_name(ei_name
, chg
);
1442 ei
->set_text(ei_name
);
1445 error("No enumeration item %s", txt
.prefix
);
1454 if (last->u.namednums.nvs->get_nof_nvs()) {
1455 Common::Identifier id(Identifier::ID_TTCN, txt.uri);
1456 NamedValue *nv = last->u.namednums.nvs->get_nv_byName(id);
1461 error("No component %s in %s", txt.uri, fn);
1465 error("TEXT cannot be assigned to an integer without named numbers");
1471 FATAL_ERROR("Type::chk_xer_text");
1474 } // next type for TEXT
1477 void Type::chk_xer_untagged()
1479 Type
* const last
= get_type_refd_last();
1480 switch (parent_type
? parent_type
->typetype
:-0) {
1481 case 0: // "no parent" is acceptable
1482 // Do not nag ("UNTAGGED encoding attribute is ignored on top-level type");
1483 // do it in Def_ExtFunction::chk_function_type when the type is actually
1484 // used as input for an encoding function.
1486 case T_SEQ_A
: case T_SEQ_T
:
1487 case T_SET_A
: case T_SET_T
:
1488 case T_CHOICE_A
: case T_CHOICE_T
:
1489 case T_SEQOF
: case T_SETOF
:
1490 break; // acceptable
1492 error("UNTAGGED can only be applied to a member of sequence, set, "
1493 "choice, sequence-of, or set-of type"); // X.693amd1, 32.2.1
1497 if ( has_aa(xerattrib
)
1498 || has_ae(xerattrib
)
1499 || xerattrib
->attribute_
|| 0 != xerattrib
->defaultForEmpty_
1500 || xerattrib
->embedValues_
|| xerattrib
->useNil_
1501 || (xerattrib
->useOrder_
&& is_asn1()) || xerattrib
->useType_
) {
1502 error("A type with final encoding attribute UNTAGGED shall not have"
1503 " any of the final encoding instructions ANY-ATTRIBUTES, ANY-ELEMENT,"
1504 " ATTRIBUTE, DEFAULT-FOR-EMPTY, EMBED-VALUES, PI-OR-COMMENT,"
1505 " USE-NIL%s or USE-TYPE",
1506 is_asn1() ? ", USE-ORDER" : ""); // X.693amd1, 32.2.6
1509 bool can_become_empty
= last
->has_empty_xml();
1510 if (can_become_empty
) { // checking 32.2.4
1511 switch (parent_type
? parent_type
->typetype
:-0) {
1513 break; // no parent, no problem
1515 case T_SEQ_A
: case T_SEQ_T
:
1516 case T_SET_A
: case T_SET_T
: {
1517 // This type can not have OPTIONAL or DEFAULT, 32.2.4 a)
1518 // No get_comp_byType(); do a linear search.
1519 size_t num_fields
= parent_type
->get_nof_comps();
1520 for (size_t i
= 0; i
< num_fields
; ++i
) {
1521 CompField
*cf
= parent_type
->get_comp_byIndex(i
);
1522 if (cf
->get_type() != this) continue;
1523 // found the component
1524 if (cf
->get_is_optional() || cf
->get_defval() != 0) {
1525 error("Type with final encoding attribute UNTAGGED"
1526 " shall not have OPTIONAL or DEFAULT");
1532 case T_SEQOF
: case T_SETOF
: // X.693amd1, 32.2.4 b)
1533 error("UNTAGGED type with possibly empty XML value can not be "
1534 "the member of a sequence-of or set-of"); // X.693amd1, 32.2.4 b)
1538 size_t num_fields
= parent_type
->get_nof_comps();
1539 size_t num_empty
= 0;
1540 for (size_t i
= 0; i
< num_fields
; ++i
) {
1541 CompField
*cf
= parent_type
->get_comp_byIndex(i
);
1542 Type
*cft
= cf
->get_type();
1543 if (cft
->has_empty_xml()) ++num_empty
;
1545 if (num_empty
> 1) { // X.693amd1, 32.2.4 c)
1546 /* FIXME: this should be error */
1547 warning("More than one alternative can be empty and has UNTAGGED");
1551 default: // do nothing
1554 } // end if(can_become_empty)
1557 void Type::chk_xer_use_nil()
1559 Type
* const last
= get_type_refd_last();
1561 enum complaint_type
{ ALL_GOOD
, NO_CONTROLNS
, NOT_SEQUENCE
, EMPTY_SEQUENCE
,
1562 UNTAGGED_USENIL
, COMPONENT_NOT_ATTRIBUTE
, LAST_IS_ATTRIBUTE
,
1563 LAST_NOT_OPTIONAL
, INCOMPATIBLE
, WRONG_OPTIONAL_TYPE
, EMBED_CHARENC
,
1564 NOT_COMPATIBLE_WITH_USEORDER
, BAD_ENUM
, FIRST_OPTIONAL
, NOTHING_TO_ORDER
,
1565 FIRST_NOT_RECORD_OF_ENUM
, ENUM_GAP
};
1566 complaint_type complaint
= ALL_GOOD
;
1568 CompField
*cf_last
= 0;
1569 const char *ns
, *prefix
;
1571 my_scope
->get_scope_mod()->get_controlns(ns
, prefix
);
1573 if (!prefix
) complaint
= NO_CONTROLNS
; // don't bother checking further
1574 else switch (last
->typetype
) {
1576 complaint
= NOT_SEQUENCE
;
1580 error("No XER yet for ASN.1 sequences");
1583 const size_t num_cf
= last
->get_nof_comps();
1584 if (num_cf
== 0) { // 33.2.1 ...must have a component...
1585 complaint
= EMPTY_SEQUENCE
;
1586 break; // stop checking to prevent accessing non-existing components
1588 if (xerattrib
->untagged_
) { // 33.2.2
1589 complaint
= UNTAGGED_USENIL
;
1593 // Skip components supporting USE-ORDER or EMBED-VALUES
1594 size_t i
= (xerattrib
->useOrder_
) + (xerattrib
->embedValues_
);
1595 // 33.2.1 All the others except the last must be (any)attributes
1596 for (; i
< num_cf
-1; ++i
) {
1597 cf
= last
->get_comp_byIndex(i
);
1598 Type
*cft
= cf
->get_type();
1599 if (! (cft
->xerattrib
1600 && ( cft
->xerattrib
->attribute_
|| has_aa(cft
->xerattrib
))))
1602 complaint
= COMPONENT_NOT_ATTRIBUTE
;
1606 // 33.2.1 The last component must be an OPTIONAL non-attribute
1607 cf_last
= last
->get_comp_byIndex(num_cf
-1);
1608 Type
*cft
= cf_last
->get_type();
1609 if (!cf_last
->get_is_optional()) {
1610 complaint
= LAST_NOT_OPTIONAL
;
1613 if(xerattrib
->useOrder_
&& cft
->get_type_refd_last()->get_typetype() != T_SEQ_A
1614 && cft
->get_type_refd_last()->get_typetype() != T_SEQ_T
){
1615 complaint
= NOT_COMPATIBLE_WITH_USEORDER
;
1616 }else if(xerattrib
->useOrder_
) {
1617 //This check needed, because if the record that has useOrder only
1618 //has one field that is a sequence type, then the useNilPossible
1619 //would be always true, that would lead to incorrect code generation.
1620 Type
* inner
= cft
->get_type_refd_last();
1621 size_t useorder_index
= xerattrib
->embedValues_
;
1622 CompField
*uo_field
= last
->get_comp_byIndex(useorder_index
);
1623 Type
*uot
= uo_field
->get_type();
1624 if (uot
->get_type_refd_last()->typetype
== T_SEQOF
) {
1625 the_enum
= uot
->get_ofType()->get_type_refd_last();
1626 if(the_enum
->typetype
!= T_ENUM_A
&& the_enum
->typetype
!= T_ENUM_T
){
1627 complaint
= FIRST_NOT_RECORD_OF_ENUM
;
1629 }else if (uo_field
->get_is_optional() || uo_field
->get_defval() != 0) {
1630 complaint
= FIRST_OPTIONAL
;
1634 size_t expected_enum_items
= inner
->get_nof_comps();
1635 size_t enum_index
= 0;
1636 if (expected_enum_items
== 0)
1637 complaint
= NOTHING_TO_ORDER
;
1638 else if (the_enum
->u
.enums
.eis
->get_nof_eis() != expected_enum_items
)
1639 complaint
= BAD_ENUM
;
1640 else for (size_t i
= 0; i
< expected_enum_items
; ++i
) {
1641 CompField
*inner_cf
= inner
->get_comp_byIndex(i
);
1642 Type
*inner_cft
= inner_cf
->get_type();
1643 if (inner_cft
->xerattrib
&& inner_cft
->xerattrib
->attribute_
) continue;
1644 // Found a non-attribute component. Its name must match an enumval
1645 const Identifier
& field_name
= inner_cf
->get_name();
1646 const EnumItem
*ei
= the_enum
->get_ei_byIndex(enum_index
);
1647 const Identifier
& enum_name
= ei
->get_name();
1648 if (field_name
!= enum_name
) {// X.693amd1 35.2.2.1 and 35.2.2.2
1649 complaint
= BAD_ENUM
;
1652 Value
*v
= ei
->get_value();
1653 const int_val_t
*ival
= v
->get_val_Int();
1654 const Int enumval
= ival
->get_val();
1655 if ((size_t)enumval
!= enum_index
) {
1656 complaint
= ENUM_GAP
; // 35.2.2.3
1664 if (cft
->xerattrib
) {
1665 if ( cft
->xerattrib
->attribute_
1666 || has_aa(cft
->xerattrib
)) {
1667 complaint
= LAST_IS_ATTRIBUTE
;
1671 if (has_ae(cft
->xerattrib
)
1672 ||has_aa(cft
->xerattrib
)
1673 ||cft
->xerattrib
->defaultForEmpty_
!= 0
1674 ||cft
->xerattrib
->untagged_
1675 ||cft
->xerattrib
->useNil_
1676 ||cft
->xerattrib
->useOrder_
1677 ||cft
->xerattrib
->useType_
) { // or PI-OR-COMMENT
1678 complaint
= INCOMPATIBLE
; // 33.2.3
1682 if (cft
->is_charenc() == Yes
) {
1683 // In a sequence EMBED-VALUES and USE-NIL, the optional component
1684 // supporting USE-NIL shall not be a character-encodable type.
1685 // So says OSS, and rightly so (there's no way to separate
1686 // the last field from the surrounding "embed" strings).
1687 if (xerattrib
->embedValues_
) complaint
= EMBED_CHARENC
;
1689 else switch (cft
->get_type_refd_last()->typetype
) {
1700 // or an octetstring or bitstring with a contained "Type" and without ENCODED BY
1701 break; // acceptable
1704 complaint
= WRONG_OPTIONAL_TYPE
;
1709 } // else switch(last->typetype)
1711 if (complaint
== ALL_GOOD
) use_nil_possible
= true;
1712 else if (xerattrib
->useNil_
) {
1713 switch (complaint
) {
1714 case ALL_GOOD
: // Not possible because of the if.
1715 // Present so GCC checks that all enum values are handled (no default!)
1718 error("Type has USE-NIL, but the module has no control namespace set");
1721 error("The target of an USE-NIL encoding instruction must be a record (SEQUENCE) or set type");
1723 case EMPTY_SEQUENCE
:
1724 error("The target of an USE-NIL must have at least one component");
1726 case UNTAGGED_USENIL
:
1727 error("The target of an USE-NIL encoding instruction shall not have"
1728 " a final UNTAGGED encoding instruction");
1730 case COMPONENT_NOT_ATTRIBUTE
:
1731 cf
->error("Component '%s' of USE-NIL not ATTRIBUTE", cf
->get_name().get_name().c_str());
1733 case LAST_IS_ATTRIBUTE
:
1734 cf_last
->error("Last component of USE-NIL must not have ATTRIBUTE");
1736 case LAST_NOT_OPTIONAL
:
1737 cf_last
->error("Last component of USE-NIL must be OPTIONAL");
1740 cf_last
->error("The OPTIONAL component of USE-NIL cannot have any of the "
1741 "following encoding instructions: ANY-ATTRIBUTES, ANY-ELEMENT, "
1742 "DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED, "
1743 "USE-NIL, USE-ORDER, USE-TYPE.");
1745 case WRONG_OPTIONAL_TYPE
:
1746 cf_last
->error("The OPTIONAL component of USE-NIL must be "
1747 "a character-encodable type, or a sequence, set, choice, "
1748 "sequence-of, set-of or open type.");
1751 cf_last
->error("In a sequence type with EMBED-VALUES and USE-NIL, "
1752 "the optional component supporting USE-NIL shall not be "
1753 "a character-encodable type.");
1755 case NOT_COMPATIBLE_WITH_USEORDER
:
1756 cf_last
->error("The OTIONAL component of USE-NIL must be "
1757 "a SEQUENCE/record when USE-ORDER is set for the parent type.");
1760 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1761 the_enum
->error("Enumeration items should match the"
1762 " non-attribute components of the field %s",
1763 cf_last
->get_name().get_dispname().c_str());
1765 case FIRST_OPTIONAL
:
1766 error("The record-of for USE-ORDER shall not be marked"
1767 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1769 case NOTHING_TO_ORDER
:
1770 error("The component (%s) should have at least one non-attribute"
1771 " component if USE-ORDER is present",
1772 cf_last
->get_name().get_dispname().c_str());
1774 case FIRST_NOT_RECORD_OF_ENUM
:
1775 error("The type with USE-ORDER should have a component "
1776 "which is a record-of enumerated");
1779 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1780 the_enum
->error("Enumeration values must start at 0 and have no gaps");
1786 void Type::chk_xer_use_order(int num_attributes
)
1788 Type
* const last
= get_type_refd_last();
1790 enum complaint_type
{ ALL_GOOD
, NOT_SEQUENCE
, NOT_ENOUGH_MEMBERS
,
1791 FIRST_NOT_RECORD_OF
, FIRST_NOT_RECORD_OF_ENUM
, FIRST_OPTIONAL
,
1792 LAST_NOT_RECORD
, BAD_ENUM
, ENUM_GAP
, NOTHING_TO_ORDER
};
1793 complaint_type complaint
= ALL_GOOD
;
1794 Type
*the_enum
= 0; // Well, it's supposed to be an enum.
1795 switch (last
->typetype
) {
1796 case T_SEQ_A
: case T_SEQ_T
: { // record/SEQUENCE acceptable
1797 size_t useorder_index
= xerattrib
->embedValues_
;
1798 // The first (or second, if the first is taken by EMBED_VALUES)
1799 // member must be a record of enumerated
1800 if (useorder_index
>= last
->get_nof_comps()) {
1801 complaint
= NOT_ENOUGH_MEMBERS
;
1804 CompField
*uo_field
= last
->get_comp_byIndex(useorder_index
);
1805 Type
*uot
= uo_field
->get_type();
1806 if (uot
->get_type_refd_last()->typetype
== T_SEQOF
) {
1807 the_enum
= uot
->get_ofType()->get_type_refd_last();
1808 switch (the_enum
->typetype
) {
1809 case T_ENUM_A
: case T_ENUM_T
: // acceptable
1810 if (uo_field
->get_is_optional() || uo_field
->get_defval() != 0) {
1811 complaint
= FIRST_OPTIONAL
;
1815 complaint
= FIRST_NOT_RECORD_OF_ENUM
;
1817 } // switch enum type
1818 size_t ncomps
= last
->get_nof_comps();
1819 // the components of this sequence will have to match the enum
1820 Type
*sequence_type
= 0;
1821 size_t expected_enum_items
, first_non_attr
;
1823 if (xerattrib
->useNil_
) { // useNil in addition to useOrder
1824 // This is an additional complication because USE-ORDER
1825 // will affect the optional component, rather than the type itself
1826 CompField
*cf
= last
->get_comp_byIndex(ncomps
-1);
1827 sequence_type
= cf
->get_type()->get_type_refd_last();
1828 if (sequence_type
->typetype
== T_SEQ_T
1829 ||sequence_type
->typetype
== T_SEQ_A
) {
1831 // No need to check that it has at least one component (35.2.1)
1832 // it can't match up with the enum which always has one
1833 ncomps
= sequence_type
->get_nof_comps();
1834 expected_enum_items
= ncomps
;
1837 else { // Whoops, not a sequence type!
1838 complaint
= LAST_NOT_RECORD
;
1839 break; // the switch(typetype)
1843 sequence_type
= last
;
1844 first_non_attr
= useorder_index
+1+num_attributes
;
1845 expected_enum_items
= ncomps
- first_non_attr
;
1848 size_t enum_index
= 0;
1849 if (expected_enum_items
== 0)
1850 complaint
= NOTHING_TO_ORDER
;
1851 else if (the_enum
->u
.enums
.eis
->get_nof_eis() != expected_enum_items
)
1852 complaint
= BAD_ENUM
;
1853 else for (size_t i
= first_non_attr
; i
< ncomps
; ++i
) {
1854 CompField
*cf
= sequence_type
->get_comp_byIndex(i
);
1855 Type
*cft
= cf
->get_type();
1856 if (cft
->xerattrib
&& cft
->xerattrib
->attribute_
) continue;
1857 // Found a non-attribute component. Its name must match an enumval
1858 const Identifier
& field_name
= cf
->get_name();
1859 // don't use get_eis_index_byName(); fatal error if not found :(
1860 const EnumItem
*ei
= the_enum
->get_ei_byIndex(enum_index
);
1861 const Identifier
& enum_name
= ei
->get_name();
1862 if (field_name
!= enum_name
) {// X.693amd1 35.2.2.1 and 35.2.2.2
1863 complaint
= BAD_ENUM
;
1866 Value
*v
= ei
->get_value();
1867 const int_val_t
*ival
= v
->get_val_Int();
1868 const Int enumval
= ival
->get_val();
1869 if ((size_t)enumval
!= enum_index
) {
1870 complaint
= ENUM_GAP
; // 35.2.2.3
1874 } // next enum component
1877 complaint
= FIRST_NOT_RECORD_OF
;
1882 complaint
= NOT_SEQUENCE
;
1884 } // switch typetype
1886 if (complaint
== ALL_GOOD
) use_order_possible
= true;
1887 else if (xerattrib
->useOrder_
) {
1888 switch (complaint
) {
1889 case ALL_GOOD
: // Not possible; present in the switch so GCC checks
1890 // that all enum values are handled (make sure there's no default).
1893 error("USE-ORDER can only be assigned to a SEQUENCE/record type.");
1895 case NOT_ENOUGH_MEMBERS
:
1896 case FIRST_NOT_RECORD_OF
:
1897 case FIRST_NOT_RECORD_OF_ENUM
:
1898 error("The type with USE-ORDER should have a component "
1899 "which is a record-of enumerated");
1901 case FIRST_OPTIONAL
:
1902 error("The record-of for USE-ORDER shall not be marked"
1903 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1905 case NOTHING_TO_ORDER
:
1906 error("The type with USE-ORDER should have at least one "
1907 "non-attribute component");
1909 case LAST_NOT_RECORD
:
1910 error("The OPTIONAL component supporting the USE-NIL "
1911 "encoding instruction should be a SEQUENCE/record");
1914 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1915 the_enum
->error("Enumeration items should match the"
1916 " non-attribute components of the sequence");
1919 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1920 the_enum
->error("Enumeration values must start at 0 and have no gaps");
1926 void Type::chk_xer_use_type()
1928 Type
* const last
= get_type_refd_last();
1930 const char *ns
, *prefix
;
1931 my_scope
->get_scope_mod()->get_controlns(ns
, prefix
);
1932 if (!prefix
) error("Type has USE-TYPE, but the module has no control namespace set");
1934 switch (last
->typetype
) {
1935 // USE-TYPE applied to anytype ? Just say no.
1936 case T_CHOICE_A
: case T_CHOICE_T
: { // must be CHOICE; 37.2.1
1937 if (xerattrib
->untagged_
|| xerattrib
->useUnion_
) { // 37.2.5
1938 error("A type with USE-TYPE encoding instruction shall not also have"
1939 " any of the final encoding instructions UNTAGGED or USE-UNION");
1941 // Now check the alternatives.
1942 // iterating backwards calls get_nof_comps only once
1943 for (int i
= last
->get_nof_comps() - 1; i
>= 0; --i
) {
1944 CompField
*cf
= last
->get_comp_byIndex(i
);
1945 Type
*cft
= cf
->get_type();
1946 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
) {
1947 cf
->error("Alternative of a union with USE-TYPE should not have UNTAGGED"); // 37.2.2
1950 switch (cft
->typetype
) {
1951 case T_CHOICE_A
: case T_CHOICE_T
:
1952 if (cft
->xerattrib
&& cft
->xerattrib
->useType_
) {
1953 cf
->error("Alternative of a CHOICE type with USE-TYPE shall not be"
1954 " a CHOICE type with a USE-TYPE encoding instruction"); // 37.2.3
1963 error("USE-TYPE can only applied to a CHOICE/union type");
1968 void Type::chk_xer_use_union()
1970 Type
* const last
= get_type_refd_last();
1971 switch (last
->typetype
) {
1972 case T_CHOICE_A
: case T_CHOICE_T
: {
1973 // Now check the alternatives.
1974 // iterating backwards calls get_nof_comps only once
1975 for (int i
= last
->get_nof_comps() - 1; i
>= 0; --i
) {
1976 CompField
*cf
= last
->get_comp_byIndex(i
);
1977 Type
*cft
= cf
->get_type();
1978 if (cft
->is_charenc() && !(cft
->xerattrib
&& cft
->xerattrib
->useType_
) &&
1979 !(cft
->xerattrib
&& cft
->xerattrib
->useQName_
)) { // currently not supported
1980 if (cft
->xerattrib
&& cft
->xerattrib
->useUnion_
) // it must be a union
1981 cf
->error("Alternative of a CHOICE/union with USE-UNION"
1982 " can not itself be a CHOICE/union with USE-UNION");
1984 else cf
->error("Alternative of a CHOICE/union with USE-UNION must be character-encodable");
1988 error("USE-UNION can only applied to a CHOICE/union type"); // 38.2.1
1994 static const char *xml98
= "http://www.w3.org/XML/1998/namespace";
1996 void Type::chk_xer() { // XERSTUFF semantic check
1997 // the type (and everything it contains) is fully checked now
1999 if (xer_checked
) return;
2002 Type
*last
= get_type_refd_last();
2004 // Check XER attributes if the type belongs to a type definition,
2005 // a field of a record/set/union, or is the embedded type of a record-of.
2006 if (ownertype
==OT_TYPE_DEF
2007 ||ownertype
==OT_COMP_FIELD
2008 ||ownertype
==OT_RECORD_OF
) {
2009 XerAttributes
*newx
= 0;
2011 // Merge XER attributes from the referenced type.
2012 // This implements X.693amd1 clause 15.1.2
2013 newx
= new XerAttributes
;
2014 Type
*t1
= get_type_refd();
2015 // chk_refd() (called by chk() for T_REFD) does not check
2016 // the referenced type; do it now. This makes it fully recursive.
2019 size_t old_text
= 0;
2020 if (t1
->xerattrib
&& !t1
->xerattrib
->empty()) {
2021 old_text
= t1
->xerattrib
->num_text_
;
2022 *newx
|= *t1
->xerattrib
; // get the ancestor's attributes, except...
2023 newx
->attribute_
= false; // attribute is not inherited
2024 newx
->element_
= false; // element is not inherited
2026 if (ownertype
== OT_TYPE_DEF
2027 ||ownertype
== OT_COMP_FIELD
) {
2028 // Name,Namespace is not inherited, X.693 amd1, 13.6
2029 // are you sure about the namespace?
2030 XerAttributes::FreeNameChange(newx
->name_
);
2031 //XerAttributes::FreeNamespace(newx->namespace_); // HR39678 bugfix beta
2034 // Now merge/override with our own attributes
2035 if (xerattrib
&& !xerattrib
->empty()) {
2036 if (xerattrib
->num_text_
> 0 && old_text
> 0
2037 && (last
->typetype
== T_ENUM_T
|| last
->typetype
== T_ENUM_A
)) {
2038 // Adding more TEXT attributes does not work right.
2039 error("Adding more TEXT attributes is not supported "
2040 "by the implementation.");
2042 *newx
|= *xerattrib
;
2045 if (newx
->empty()) delete newx
;
2046 else { // something interesting was found
2050 if (xerattrib
->attribute_
2051 && t1
->xerattrib
&& t1
->xerattrib
->attribute_
2052 && t1
->ownertype
== OT_TYPE_DEF
2053 && !(xerattrib
->form_
& XerAttributes::LOCALLY_SET
) ) {
2054 // The referenced type came from a global XSD attribute.
2055 // This type's form will be qualified, unless it has an explicit
2056 // "form as ..." (which overrides everything).
2057 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2060 if (t1
->xerattrib
&& t1
->xerattrib
->element_
2061 // The referenced type came from a global XSD element.
2062 && !(xerattrib
->form_
& XerAttributes::LOCALLY_SET
))
2063 { // and it doesn't have an explicit "form as ..."
2064 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2070 if (!xerattrib
) return;
2072 //const char *fn = get_fullname().c_str();
2073 //printf("chk_xer(%s)\n", fn);
2075 // In general, "last" should be used instead of "this" in the checks below
2076 // when accessing information about the type's characteristics, except
2077 // this->xerattrib MUST be used (and not last->xerattrib!).
2079 switch (ownertype
) {
2087 FATAL_ERROR("Unexpected ownertype %d", ownertype
);
2090 int num_attributes
= 0;
2091 switch (last
->typetype
) {
2092 case T_SEQ_A
: case T_SEQ_T
:
2093 case T_SET_A
: case T_SET_T
: {
2094 // Count attributes (ANY-ATTRIBUTES counts as one)
2095 const size_t num_cf
= last
->get_nof_comps();
2096 int specials
= xerattrib
->embedValues_
+ xerattrib
->useOrder_
;
2097 int num_any_attributes
= 0;
2098 for (int x
= num_cf
- 1; x
>= specials
; --x
) {
2099 CompField
*cf
= last
->get_comp_byIndex(x
);
2100 Type
*cft
= cf
->get_type() /* NOT get_type_refd_last() */;
2102 && (cft
->xerattrib
->attribute_
|| has_aa(cft
->xerattrib
)))
2104 if (cft
->xerattrib
->attribute_
) ++num_attributes
;
2105 else if (++num_any_attributes
> 1) {
2106 cf
->error("There can be at most one field with ANY-ATTRIBUTES");
2109 else if (num_attributes
+ num_any_attributes
> 0) {
2110 // Found a non-attribute when there was an attribute after it
2111 cf
->error("Non-attribute field before attribute not supported");
2115 num_attributes
+= num_any_attributes
;
2122 /* * * Check restrictions set out in X.693 amd1, clauses 18-39 * * */
2124 if (has_aa(xerattrib
)) {
2125 chk_xer_any_attributes();
2126 } // if ANY-ATTRIBUTES
2128 if (has_ae(xerattrib
)) {
2129 chk_xer_any_element();
2132 if (xerattrib
->attribute_
) {
2133 chk_xer_attribute();
2134 // It's an attribute, check for the attributeFormQualified bit
2135 // and transform it into unconditionally qualified.
2136 if (!(xerattrib
->form_
& XerAttributes::LOCALLY_SET
)
2137 && (xerattrib
->form_
& XerAttributes::ATTRIBUTE_DEFAULT_QUALIFIED
)) {
2138 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2142 // Element, check the elementFormQualified bit.
2143 if (!(xerattrib
->form_
& XerAttributes::LOCALLY_SET
)
2144 && (xerattrib
->form_
& XerAttributes::ELEMENT_DEFAULT_QUALIFIED
)) {
2145 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2149 if (xerattrib
->base64_
) {
2150 switch (last
->typetype
) {
2151 case T_OSTR
: // OCTET STRING
2152 case T_HSTR
: // hexstring
2155 case T_GENERALSTRING
:
2156 case T_GRAPHICSTRING
:
2159 case T_NUMERICSTRING
:
2160 case T_PRINTABLESTRING
:
2161 case T_TELETEXSTRING
:
2163 case T_UNIVERSALSTRING
:
2165 case T_VIDEOTEXSTRING
:
2166 case T_VISIBLESTRING
:
2170 break; // acceptable
2172 error("BASE64 can only be applied to OCTET STRING, open type or "
2173 "restricted character string type");
2177 if (has_ae(xerattrib
) || xerattrib
->whitespace_
!= XerAttributes::PRESERVE
) {
2178 error("A type with BASE64 shall not have any of the final "
2179 "encoding instructions ANY-ELEMENT or WHITESPACE");
2183 if (xerattrib
->decimal_
) {
2184 if (last
->typetype
!= T_REAL
) {
2185 error("DECIMAL shall only be assigned to a real type");
2189 if (xerattrib
->defaultForEmpty_
!= 0) {
2191 } // if defaultForEmpty
2193 chk_xer_embed_values(num_attributes
); // always
2195 if (xerattrib
->list_
) {
2196 switch (last
->typetype
) {
2197 case T_SEQOF
: case T_SETOF
:
2198 break; // acceptable
2200 error("LIST can only be assigned to SEQUENCE-OF or SET-OF");// 27.2.1
2204 if (has_aa(xerattrib
)) {
2205 error("A type with LIST shall not have ANY-ATTRIBUTES");// 27.2.3
2209 // NAME is handled later when generate_code_xerdescriptor call change_name
2211 if ((unsigned long)xerattrib
->namespace_
.keyword
2212 > (unsigned long)NamespaceSpecification::LOWERCASED
) {
2213 // Now both are proper non-NULL strings
2214 if (*xerattrib
->namespace_
.prefix
!= 0) { // there is a prefix, check it
2215 char first
[4] = {0,0,0,0};
2216 strncpy(first
, xerattrib
->namespace_
.prefix
, 3);
2217 first
[0] = toupper(first
[0]);
2218 first
[1] = toupper(first
[1]);
2219 first
[2] = toupper(first
[2]);
2220 if (!memcmp(first
, "XML", 3) // It _is_ "xml"
2221 // but the W3C XML namespace gets an exemption
2222 && strcmp(xerattrib
->namespace_
.uri
, xml98
)) error(
2223 "Prefix shall not commence with characters that"
2224 " when uppercased are 'XML'");
2225 // X.693 (11/2008), clause 29.1.7
2228 Common::Module::add_namespace(
2229 xerattrib
->namespace_
.uri
, xerattrib
->namespace_
.prefix
);
2231 else xerattrib
->namespace_
.uri
= NULL
; // really no namespace
2233 // PI-OR-COMMENT not supported
2235 if (xerattrib
->num_text_
> 0) {
2239 if (xerattrib
->untagged_
) {
2243 chk_xer_use_nil(); // always
2245 if (xerattrib
->useNumber_
) {
2246 switch (last
->typetype
) {
2248 error("No XER yet for ASN.1 enumerations");
2251 break; // acceptable
2253 warning("USE-NUMBER ignored unless assigned to an enumerated type");
2254 xerattrib
->useNumber_
= false;
2258 if (xerattrib
->num_text_
) {
2259 error("A type with USE-NUMBER shall not have TEXT");
2263 chk_xer_use_order(num_attributes
); //always
2265 if (xerattrib
->useQName_
) {
2266 switch (last
->typetype
) {
2267 case T_SEQ_A
: case T_SEQ_T
: {
2268 if (last
->get_nof_comps() != 2) goto complain
;
2269 const CompField
* cf
= last
->get_comp_byIndex(0);
2270 const Type
* cft
= cf
->get_type()->get_type_refd_last();
2271 if (cft
->typetype
!= T_USTR
&& cft
->typetype
!= T_UTF8STRING
)
2272 cft
->error ("Both components must be UTF8String or universal charstring");
2273 if (!cf
->get_is_optional()) cft
->error(
2274 "The first component of a type with USE-QNAME must be optional");
2276 cf
= last
->get_comp_byIndex(1);
2277 cft
= cf
->get_type()->get_type_refd_last();
2278 if (cft
->typetype
!= T_USTR
&& cft
->typetype
!= T_UTF8STRING
)
2279 cft
->error ("Both components must be UTF8String or universal charstring");
2280 if (cf
->get_is_optional()) cft
->error(
2281 "The second component of a type with USE-QNAME must NOT be optional");
2286 error("A type with USE-QNAME must be a sequence type with exactly two components.");
2289 if (xerattrib
->useNil_
) error("A type with USE-QNAME shall not have USE-NIL"); // 36.2.4
2292 if (xerattrib
->useType_
) {
2296 if (xerattrib
->useUnion_
) {
2297 chk_xer_use_union();
2301 CompFieldMap
& cfm
= *u
.secho
.cfm
;
2302 const size_t ncomps
= cfm
.get_nof_comps();
2303 CompField
*the_one
= 0; // ...and only untagged character-encodable field
2304 map
<int, CompField
> empties
; // potentially empties
2306 for (size_t i
=0; i
< ncomps
; ++i
) {
2307 CompField
* cf
= cfm
.get_comp_byIndex(i
);
2308 Type
*cft
= cf
->get_type();
2310 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
) {
2311 /* This check could be in chk_xer_untagged(), but then we couldn't
2312 * access the CompField in the parent type. */
2313 if (cft
->is_charenc() == Yes
) {
2314 if (the_one
) { // already has one
2315 cf
->error("More than one UNTAGGED character-encodable field");
2316 // break? to report only once
2319 the_one
= cf
; // this is used for further checks below
2320 u
.secho
.has_single_charenc
= true; // used while generating code
2322 case T_SEQ_A
: case T_SEQ_T
:
2323 if (xerattrib
->untagged_
) {
2324 error("Enclosing type of an UNTAGGED character-encodable type "
2325 "must not be UNTAGGED");
2327 break; // the small switch
2329 error("Enclosing type of an UNTAGGED character-encodable type "
2335 else { // untagged, not charenc
2336 switch (cft
->get_type_refd_last()->typetype
) {
2337 case T_SEQ_A
: case T_SEQ_T
:
2338 case T_SET_A
: case T_SET_T
:
2339 case T_CHOICE_A
: case T_CHOICE_T
:
2342 //case T_OSTR: with a contained type
2343 //case T_BSTR_A: with a contained type
2347 default: // 32.2.3 "If the type is not character-encodable..."
2348 cft
->error("UNTAGGED type should be sequence, set, choice, sequence-of, or set-of type");
2354 if (cft
->has_empty_xml()) {
2360 if (the_one
->get_is_optional() || the_one
->has_default()) {
2361 the_one
->error("UNTAGGED field should not be marked OPTIONAL or DEFAULT");
2363 // Check the other compfields. They must all be (ANY)?ATTRIBUTE
2364 for (size_t i
=0; i
< ncomps
; ++i
) {
2365 CompField
*cf
= cfm
.get_comp_byIndex(i
);
2366 if (cf
== the_one
) continue;
2368 Type
*cft
= cf
->get_type();
2369 if ( !cft
->xerattrib
// cannot be attribute, error
2370 || (!cft
->xerattrib
->attribute_
&& !has_aa(cft
->xerattrib
))) {
2371 the_one
->note("Due to this UNTAGGED component");
2372 cf
->error("All the other components should be ATTRIBUTE or ANY-ATTRIBUTE");
2373 // X.693 (2008) 32.2.2
2379 if (empties
.size() > 1
2380 && (typetype
==T_CHOICE_A
|| typetype
==T_CHOICE_T
)) {
2381 warning("More than one field can have empty XML. Decoding of empty"
2382 " XML is ambiguous, %s chosen arbitrarily.",
2383 empties
.get_nth_elem(empties
.size()-1)->get_name().get_name().c_str());
2388 if (xerattrib
->abstract_
|| xerattrib
->block_
) {
2389 switch (ownertype
) {
2391 if (parent_type
->typetype
== T_CHOICE_A
||
2392 parent_type
->typetype
== T_CHOICE_T
) {
2393 if (parent_type
->xerattrib
!= NULL
&& parent_type
->xerattrib
->useUnion_
) {
2394 error("ABSTRACT and BLOCK cannot be used on fields of a union with "
2395 "attribute USE-UNION.");
2399 // else fall through
2402 warning("ABSTRACT and BLOCK only affects union fields.");
2412 void Type::chk_Int_A()
2416 if(!u
.namednums
.block
) return;
2418 if(typetype
==T_ERROR
) return;
2419 /* check named numbers */
2420 if(!u
.namednums
.nvs
) return;
2421 map
<Int
, NamedValue
> value_map
;
2422 Error_Context
cntxt(this, "In named numbers");
2423 u
.namednums
.nvs
->chk_dupl_id();
2424 for (size_t i
= 0; i
< u
.namednums
.nvs
->get_nof_nvs(); i
++) {
2425 NamedValue
*nv
= u
.namednums
.nvs
->get_nv_byIndex(i
);
2426 Value
*value
= nv
->get_value();
2427 Value
*v
= value
->get_value_refd_last();
2428 switch (v
->get_valuetype()) {
2429 case Value::V_INT
: {
2430 const int_val_t
*int_val_int
= v
->get_val_Int();
2431 if (*int_val_int
> INT_MAX
) {
2432 value
->error("Integer value `%s' is too big to be used as a named "
2433 "number", (int_val_int
->t_str()).c_str());
2435 Int int_val
= int_val_int
->get_val();
2436 if (value_map
.has_key(int_val
)) {
2437 value
->error("Duplicate number %s for name `%s'",
2438 Int2string(int_val
).c_str(),
2439 nv
->get_name().get_dispname().c_str());
2440 NamedValue
*nv2
= value_map
[int_val
];
2441 nv2
->note("Number %s is already assigned to name `%s'",
2442 Int2string(int_val
).c_str(),
2443 nv2
->get_name().get_dispname().c_str());
2445 value_map
.add(int_val
, nv
);
2449 case Value::V_ERROR
:
2452 nv
->error("INTEGER value was expected for named number `%s'",
2453 nv
->get_name().get_dispname().c_str());
2460 void Type::chk_Enum_A()
2463 if(!u
.enums
.block
) return;
2465 if(typetype
==T_ERROR
) return;
2466 /* checking enumerations */
2467 map
<Int
, EnumItem
> value_map
;
2468 /* checking values before the ellipsis */
2469 for (size_t i
= 0; i
< u
.enums
.eis1
->get_nof_eis(); i
++)
2470 chk_Enum_item(u
.enums
.eis1
->get_ei_byIndex(i
), false, value_map
);
2471 /* assigning default values */
2472 Int
& first_unused
= u
.enums
.first_unused
;
2473 for (first_unused
= 0; value_map
.has_key(first_unused
); first_unused
++) ;
2474 for (size_t i
= 0; i
< u
.enums
.eis1
->get_nof_eis(); i
++) {
2475 EnumItem
*ei
= u
.enums
.eis1
->get_ei_byIndex(i
);
2476 if (!ei
->get_value()) {
2477 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2478 value_map
.add(first_unused
, ei
);
2479 while (value_map
.has_key(++first_unused
)) ;
2482 /* checking values after the ellipsis */
2484 for(size_t i
=0; i
< u
.enums
.eis2
->get_nof_eis(); i
++)
2485 chk_Enum_item(u
.enums
.eis2
->get_ei_byIndex(i
), true, value_map
);
2487 /* determining the first two unused non-negative integer values
2488 * for code generation */
2489 for (first_unused
= 0; value_map
.has_key(first_unused
); first_unused
++) ;
2490 Int
& second_unused
= u
.enums
.second_unused
;
2491 for (second_unused
= first_unused
+ 1; value_map
.has_key(second_unused
);
2494 u
.enums
.eis1
->release_eis();
2495 delete u
.enums
.eis1
;
2498 u
.enums
.eis2
->release_eis();
2499 delete u
.enums
.eis2
;
2504 void Type::chk_Enum_item(EnumItem
*ei
, bool after_ellipsis
,
2505 map
<Int
, EnumItem
>& value_map
)
2507 const Identifier
& name
= ei
->get_name();
2508 const char *dispname_str
= name
.get_dispname().c_str();
2509 if (u
.enums
.eis
->has_ei_withName(name
)) {
2510 ei
->error("Duplicate ENUMERATED identifier: `%s'", dispname_str
);
2511 u
.enums
.eis
->get_ei_byName(name
)->note("Previous definition of `%s' "
2512 "is here", dispname_str
);
2513 } else if (!name
.get_has_valid(Identifier::ID_TTCN
)) {
2514 ei
->warning("The identifier `%s' is not reachable from TTCN-3",
2517 u
.enums
.eis
->add_ei(ei
);
2518 Int
& first_unused
=u
.enums
.first_unused
;
2519 Value
*value
= ei
->get_value();
2523 Error_Context
cntxt(ei
, "In enumeration `%s'", dispname_str
);
2524 v
= value
->get_value_refd_last();
2526 switch (v
->get_valuetype()) {
2529 case Value::V_ERROR
:
2532 value
->error("INTEGER value was expected for enumeration `%s'",
2536 Int enum_value
= v
->get_val_Int()->get_val();
2537 if (static_cast<Int
>(static_cast<int>(enum_value
)) != enum_value
) {
2538 value
->error("The numeric value of enumeration `%s' (%s) is too "
2539 "large for being represented in memory", dispname_str
,
2540 Int2string(enum_value
).c_str());
2542 if (after_ellipsis
) {
2543 if (enum_value
>= first_unused
) {
2544 value_map
.add(enum_value
, ei
);
2545 for (first_unused
= enum_value
+ 1; value_map
.has_key(first_unused
);
2548 value
->error("ENUMERATED values shall be monotonically growing after "
2549 "the ellipsis: the value of `%s' must be at least %s instead of %s",
2550 dispname_str
, Int2string(first_unused
).c_str(),
2551 Int2string(enum_value
).c_str());
2554 if (value_map
.has_key(enum_value
)) {
2555 value
->error("Duplicate numeric value %s for enumeration `%s'",
2556 Int2string(enum_value
).c_str(), dispname_str
);
2557 EnumItem
*ei2
= value_map
[enum_value
];
2558 ei2
->note("Value %s is already assigned to `%s'",
2559 Int2string(enum_value
).c_str(),
2560 ei2
->get_name().get_dispname().c_str());
2561 } else value_map
.add(enum_value
, ei
);
2563 } else { // the item has no value
2564 if (after_ellipsis
) {
2565 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2566 value_map
.add(first_unused
, ei
);
2567 while (value_map
.has_key(++first_unused
)) ;
2572 void Type::chk_Enum_T()
2575 map
<Int
, EnumItem
> value_map
;
2576 map
<string
, EnumItem
> name_map
;
2577 bool error_flag
= false;
2578 /* checking the uniqueness of identifiers and values */
2579 size_t nof_eis
= u
.enums
.eis
->get_nof_eis();
2580 for(size_t i
= 0; i
< nof_eis
; i
++) {
2581 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
2582 const Identifier
& id
= ei
->get_name();
2583 const string
& name
= id
.get_name();
2584 if (name_map
.has_key(name
)) {
2585 const char *dispname_str
= id
.get_dispname().c_str();
2586 ei
->error("Duplicate enumeration identifier `%s'", dispname_str
);
2587 name_map
[name
]->note("Previous definition of `%s' is here",
2591 name_map
.add(name
, ei
);
2593 Value
*value
= ei
->get_value();
2595 /* Handle the error node created by the parser. */
2596 if (value
->get_valuetype() == Value::V_ERROR
) {
2597 value
->error("INTEGER value was expected for enumeration `%s'",
2598 id
.get_dispname().c_str());
2601 const int_val_t
*enum_value_int
= value
->get_val_Int();
2602 // It used to be the same check.
2603 if (*enum_value_int
> INT_MAX
||
2604 static_cast<Int
>(static_cast<int>(enum_value_int
->get_val()))
2605 != enum_value_int
->get_val()) {
2606 value
->error("The numeric value of enumeration `%s' (%s) is "
2607 "too large for being represented in memory",
2608 id
.get_dispname().c_str(), (enum_value_int
->t_str()).c_str());
2611 Int enum_value
= enum_value_int
->get_val();
2612 if (value_map
.has_key(enum_value
)) {
2613 const char *dispname_str
= id
.get_dispname().c_str();
2614 value
->error("Duplicate numeric value %s for enumeration `%s'",
2615 Int2string(enum_value
).c_str(), dispname_str
);
2616 EnumItem
*ei2
= value_map
[enum_value
];
2617 ei2
->note("Value %s is already assigned to `%s'",
2618 Int2string(enum_value
).c_str(),
2619 ei2
->get_name().get_dispname().c_str());
2622 value_map
.add(enum_value
, ei
);
2629 /* assigning default values */
2630 Int
& first_unused
=u
.enums
.first_unused
;
2631 for(first_unused
=0; value_map
.has_key(first_unused
); first_unused
++) ;
2632 for(size_t i
= 0; i
< nof_eis
; i
++) {
2633 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
2634 if(!ei
->get_value()) {
2635 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2636 value_map
.add(first_unused
, ei
);
2637 while (value_map
.has_key(++first_unused
)) ;
2640 Int
& second_unused
= u
.enums
.second_unused
;
2641 for (second_unused
= first_unused
+ 1; value_map
.has_key(second_unused
);
2648 void Type::chk_BStr_A()
2650 if(!u
.namednums
.block
) return;
2652 if(typetype
==T_ERROR
) return;
2653 if(u
.namednums
.nvs
) {
2654 /* check named bits */
2655 map
<Int
, NamedValue
> value_map
;
2657 Error_Context
cntxt(this, "In named bits");
2658 u
.namednums
.nvs
->chk_dupl_id();
2660 for(size_t i
= 0; i
< u
.namednums
.nvs
->get_nof_nvs(); i
++) {
2661 NamedValue
*nv
= u
.namednums
.nvs
->get_nv_byIndex(i
);
2662 const char *dispname_str
= nv
->get_name().get_dispname().c_str();
2663 Value
*value
= nv
->get_value();
2666 Error_Context
cntxt(this, "In named bit `%s'", dispname_str
);
2667 v
= value
->get_value_refd_last();
2669 switch (v
->get_valuetype()) {
2672 case Value::V_ERROR
:
2675 v
->error("INTEGER value was expected for named bit `%s'",
2679 const int_val_t
*int_val_int
= v
->get_val_Int();
2680 if (*int_val_int
> INT_MAX
) {
2681 value
->error("An INTEGER value less than `%d' was expected for "
2682 "named bit `%s' instead of %s", INT_MAX
, dispname_str
,
2683 (int_val_int
->t_str()).c_str());
2686 Int int_val
= int_val_int
->get_val();
2688 value
->error("A non-negative INTEGER value was expected for named "
2689 "bit `%s' instead of %s", dispname_str
,
2690 Int2string(int_val
).c_str());
2693 if (value_map
.has_key(int_val
)) {
2694 value
->error("Duplicate value %s for named bit `%s'",
2695 Int2string(int_val
).c_str(), dispname_str
);
2696 NamedValue
*nv2
= value_map
[int_val
];
2697 nv2
->note("Bit %s is already assigned to name `%s'",
2698 Int2string(int_val
).c_str(),
2699 nv2
->get_name().get_dispname().c_str());
2700 } else value_map
.add(int_val
, nv
);
2706 void Type::chk_SeCho_T()
2708 u
.secho
.cfm
->set_my_type(this);
2711 u
.secho
.component_internal
= false;
2712 size_t nof_comps
= u
.secho
.cfm
->get_nof_comps();
2713 for (size_t i
=0; i
<nof_comps
; i
++) {
2714 Type
* cft
= u
.secho
.cfm
->get_comp_byIndex(i
)->get_type();
2715 if (cft
&& cft
->is_component_internal()) {
2716 u
.secho
.component_internal
= true;
2722 void Type::chk_Choice_A()
2724 if(u
.secho
.block
) parse_block_Choice();
2725 if(typetype
==T_ERROR
) return;
2727 if(u
.secho
.ctss
->needs_auto_tags())
2728 u
.secho
.ctss
->add_auto_tags();
2729 u
.secho
.ctss
->chk();
2730 if (u
.secho
.ctss
->get_nof_comps() <= 0)
2731 FATAL_ERROR("CHOICE type must have at least one alternative");
2732 u
.secho
.ctss
->chk_tags();
2735 void Type::chk_Se_A()
2737 if(u
.secho
.block
) parse_block_Se();
2738 if(typetype
==T_ERROR
) return;
2741 u
.secho
.ctss
->chk();
2742 u
.secho
.ctss
->chk_tags();
2745 void Type::chk_SeOf()
2747 u
.seof
.ofType
->set_genname(get_genname_own(), string('0'));
2748 u
.seof
.ofType
->set_parent_type(this);
2750 const char *type_name
;
2751 bool asn1
= is_asn1();
2754 type_name
= asn1
? "SEQUENCE OF" : "record of";
2757 type_name
= asn1
? "SET OF" : "set of";
2760 type_name
= "<unknown>";
2763 Error_Context
cntxt(this, "In embedded type of %s", type_name
);
2764 u
.seof
.ofType
->chk();
2765 if (!asn1
) u
.seof
.ofType
->chk_embedded(true, "embedded into another type");
2766 u
.seof
.component_internal
= u
.seof
.ofType
->is_component_internal();
2769 void Type::chk_refd()
2772 ReferenceChain
refch(this, "While checking referenced type");
2773 Type
* t_last
= get_type_refd_last(&refch
);
2774 u
.ref
.component_internal
= t_last
->is_component_internal();
2777 void Type::chk_seltype()
2780 u
.seltype
.type
->set_genname(get_genname_own(), string('0'));
2781 ReferenceChain
refch(this, "In selection type");
2782 get_type_refd_last(&refch
);
2783 if(typetype
==T_ERROR
) return;
2784 u
.seltype
.type
->chk();
2787 void Type::chk_Array()
2789 u
.array
.element_type
->set_genname(get_genname_own(), string('0'));
2790 u
.array
.element_type
->set_parent_type(this);
2793 Error_Context
cntxt(this, "In element type of array");
2794 u
.array
.element_type
->chk();
2795 u
.array
.element_type
->chk_embedded(true, "embedded into an array type");
2797 u
.array
.dimension
->chk();
2798 u
.array
.component_internal
= u
.array
.element_type
->is_component_internal();
2801 void Type::chk_Signature()
2804 u
.signature
.component_internal
= false;
2805 if (u
.signature
.parameters
) {
2806 u
.signature
.parameters
->chk(this);
2807 size_t nof_params
= u
.signature
.parameters
->get_nof_params();
2808 for (size_t i
=0; i
<nof_params
; i
++) {
2809 Type
* spt
= u
.signature
.parameters
->get_param_byIndex(i
)->get_type();
2810 if (spt
&& spt
->is_component_internal()) {
2811 u
.signature
.component_internal
= true;
2816 if (u
.signature
.return_type
) {
2817 Error_Context
cntxt(u
.signature
.return_type
, "In return type");
2818 u
.signature
.return_type
->set_genname(get_genname_own(), string('0'));
2819 u
.signature
.return_type
->set_parent_type(this);
2820 u
.signature
.return_type
->chk();
2821 u
.signature
.return_type
->chk_embedded(false,
2822 "the return type of a signature");
2823 if (!u
.signature
.component_internal
&&
2824 u
.signature
.return_type
->is_component_internal())
2825 u
.signature
.component_internal
= true;
2827 if (u
.signature
.exceptions
) {
2828 u
.signature
.exceptions
->chk(this);
2829 if (!u
.signature
.component_internal
) {
2830 size_t nof_types
= u
.signature
.exceptions
->get_nof_types();
2831 for (size_t i
=0; i
<nof_types
; i
++) {
2832 if (u
.signature
.exceptions
->get_type_byIndex(i
)->
2833 is_component_internal()) {
2834 u
.signature
.component_internal
= true;
2842 void Type::chk_Fat()
2846 Scope
*parlist_scope
= my_scope
;
2847 // the runs on clause must be checked before the formal parameter list
2848 // in order to determine the right scope
2849 if (u
.fatref
.runs_on
.ref
) {
2850 if (typetype
== T_FUNCTION
) u
.fatref
.is_startable
= true;
2851 Error_Context
cntxt2(u
.fatref
.runs_on
.ref
, "In `runs on' clause");
2852 u
.fatref
.runs_on
.type
= u
.fatref
.runs_on
.ref
->chk_comptype_ref();
2853 if(u
.fatref
.runs_on
.type
) {
2854 Ttcn::Module
*my_module
=
2855 dynamic_cast<Ttcn::Module
*>(my_scope
->get_scope_mod());
2856 if (!my_module
) FATAL_ERROR("Type::chk_Fat()");
2857 parlist_scope
= my_module
->get_runs_on_scope(u
.fatref
.runs_on
.type
);
2860 u
.fatref
.fp_list
->set_my_scope(parlist_scope
);
2863 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_FUNCTION
);
2864 u
.fatref
.fp_list
->chk_noLazyParams();
2865 if (u
.fatref
.is_startable
&& !u
.fatref
.fp_list
->get_startability())
2866 u
.fatref
.is_startable
= false;
2867 if (u
.fatref
.return_type
) {
2868 Error_Context
cntxt2(u
.fatref
.return_type
, "In return type");
2869 u
.fatref
.return_type
->chk();
2870 u
.fatref
.return_type
->chk_as_return_type(!u
.fatref
.returns_template
,
2872 if (u
.fatref
.is_startable
&& u
.fatref
.return_type
->get_type_refd_last()
2873 ->get_typetype() == T_DEFAULT
) u
.fatref
.is_startable
= false;
2878 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_ALTSTEP
);
2879 u
.fatref
.fp_list
->chk_noLazyParams();
2882 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_TESTCASE
);
2883 u
.fatref
.fp_list
->chk_noLazyParams();
2884 if (u
.fatref
.system
.ref
) {
2885 Error_Context
cntxt2(u
.fatref
.runs_on
.ref
, "In `system' clause");
2886 u
.fatref
.system
.type
= u
.fatref
.system
.ref
->chk_comptype_ref();
2890 FATAL_ERROR("Type::chk_Fat()");
2892 if (!semantic_check_only
)
2893 u
.fatref
.fp_list
->set_genname(get_genname_own());
2896 void Type::chk_address()
2898 Type
*t
= get_type_refd_last();
2899 switch (t
->typetype
) {
2901 error("Port type `%s' cannot be the address type",
2902 t
->get_typename().c_str());
2905 error("Component type `%s' cannot be the address type",
2906 t
->get_typename().c_str());
2909 error("Signature `%s' cannot be the address type",
2910 t
->get_typename().c_str());
2913 error("Default type cannot be the address type");
2916 error("TTCN-3 anytype cannot be the address type");
2924 void Type::chk_embedded(bool default_allowed
, const char *error_msg
)
2926 Type
*t
=get_type_refd_last();
2927 switch (t
->typetype
) {
2929 error("Port type `%s' cannot be %s", t
->get_typename().c_str(),
2933 error("Signature `%s' cannot be %s", t
->get_typename().c_str(),
2937 if (!default_allowed
) error("Default type cannot be %s", error_msg
);
2944 void Type::chk_recursions(ReferenceChain
& refch
)
2946 if (recurs_checked
) return;
2949 if (!refch
.add(t
->get_fullname())) {
2950 // an error has been found (and reported by refch.add)
2951 recurs_checked
= true;
2954 if (!t
->is_ref()) break;
2955 t
= t
->get_type_refd();
2957 switch (t
->typetype
) {
2962 for(size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
2963 CompField
*cf
= t
->get_comp_byIndex(i
);
2964 if(!cf
->get_is_optional()) {
2966 cf
->get_type()->chk_recursions(refch
);
2969 // an optional field can "stop" the recursion
2974 refch
.set_error_reporting(false);
2975 refch
.mark_error_state();
2976 for (size_t i
= 0; i
< t
->get_nof_comps(); ++i
) {
2978 CompField
* cf
= t
->get_comp_byIndex(i
);
2979 cf
->get_type()->chk_recursions(refch
);
2983 if (refch
.nof_errors() == t
->get_nof_comps()) {
2984 refch
.report_errors();
2987 refch
.prev_error_state();
2988 refch
.set_error_reporting(true);
2993 if(t
->get_nof_comps()==1)
2994 t
->get_comp_byIndex(0)->get_type()->chk_recursions(refch
);
2997 t
->get_ofType()->chk_recursions(refch
);
3002 recurs_checked
= true;
3005 void Type::chk_constructor_name(const Identifier
& p_id
)
3015 // T_ANYTYPE can not have a field of type anytype, no need to check.
3016 if (has_comp_withName(p_id
)) {
3017 // HL26011: a field has the same name as the typedef.
3018 // Titan can't generate valid C++ code; better report an error.
3019 get_comp_byName(p_id
)->error("Field name clashes with type name");
3022 default: // can't have fields
3027 bool Type::chk_startability()
3029 if(typetype
!= T_FUNCTION
) FATAL_ERROR("Type::chk_startable()");
3030 if(!checked
) chk_Fat();
3031 if(u
.fatref
.is_startable
) return true;
3032 if (!u
.fatref
.runs_on
.ref
) error("Functions of type `%s' cannot be started "
3033 "on a parallel test component because the type does not have `runs on' "
3034 "clause", get_typename().c_str());
3035 u
.fatref
.fp_list
->chk_startability("Functions of type",
3036 get_typename().c_str());
3037 if (u
.fatref
.return_type
&& u
.fatref
.return_type
->is_component_internal()) {
3038 map
<Type
*,void> type_chain
;
3039 char* err_str
= mprintf("the return type or embedded in the return type "
3040 "of function type `%s' if it is started on a parallel test component",
3041 get_typename().c_str());
3042 u
.fatref
.return_type
->chk_component_internal(type_chain
, err_str
);
3048 void Type::chk_as_return_type(bool as_value
, const char* what
)
3050 Type
*t
= get_type_refd_last();
3051 switch(t
->get_typetype()) {
3053 error("Port type `%s' cannot be the return type of a %s"
3054 , t
->get_fullname().c_str(), what
);
3056 case Type::T_SIGNATURE
:
3057 if(as_value
) error("A value of signature `%s' cannot be the "
3058 "return type of a %s", t
->get_fullname().c_str(), what
);
3065 void Type::chk_this_value_ref(Value
*value
)
3067 switch (value
->get_valuetype()) {
3068 case Value::V_UNDEF_LOWERID
:
3071 if(value
->is_asn1()) {
3074 && u
.namednums
.nvs
->has_nv_withName(*value
->get_val_id())) {
3075 value
->set_valuetype(Value::V_NAMEDINT
);
3076 value
->set_my_governor(this);
3083 if (has_ei_withName(*value
->get_val_id())) {
3084 value
->set_valuetype(Value::V_ENUM
);
3085 value
->set_my_governor(this);
3093 get_type_refd()->chk_this_value_ref(value
);
3098 /* default behavior: interpret as reference */
3099 value
->set_valuetype(Value::V_REFD
);
3106 bool Type::chk_this_value(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3107 namedbool incomplete_allowed
, namedbool omit_allowed
,
3108 namedbool sub_chk
, namedbool implicit_omit
, namedbool is_str_elem
)
3110 bool self_ref
= false;
3112 Value
*v_last
= value
->get_value_refd_last(0, expected_value
);
3113 if (v_last
->get_valuetype() == Value::V_OMIT
) {
3114 if (!omit_allowed
) {
3115 value
->error("`omit' value is not allowed in this context");
3116 value
->set_valuetype(Value::V_ERROR
);
3121 switch (value
->get_valuetype()) {
3122 case Value::V_ERROR
:
3125 return chk_this_refd_value(value
, lhs
, expected_value
, 0, is_str_elem
);
3126 case Value::V_INVOKE
:
3127 chk_this_invoked_value(value
, lhs
, expected_value
);
3128 return false; // assumes no self-ref in invoke
3130 if (lhs
) self_ref
= value
->chk_expr_self_ref(lhs
);
3132 case Value::V_MACRO
:
3133 if (value
->is_unfoldable(0, expected_value
)) {
3134 typetype_t tt
= value
->get_expr_returntype(expected_value
);
3135 if (!is_compatible_tt(tt
, value
->is_asn1())) {
3136 value
->error("Incompatible value: `%s' value was expected",
3137 get_typename().c_str());
3138 value
->set_valuetype(Value::V_ERROR
);
3151 chk_this_value_Null(value
);
3154 chk_this_value_Bool(value
);
3157 chk_this_value_Int(value
);
3160 chk_this_value_Int_A(value
);
3163 chk_this_value_Real(value
);
3167 chk_this_value_Enum(value
);
3170 chk_this_value_BStr(value
);
3173 chk_this_value_BStr_A(value
);
3176 chk_this_value_HStr(value
);
3179 chk_this_value_OStr(value
);
3184 case T_NUMERICSTRING
:
3185 case T_PRINTABLESTRING
:
3186 case T_TELETEXSTRING
:
3187 case T_VIDEOTEXSTRING
:
3189 case T_GRAPHICSTRING
:
3190 case T_VISIBLESTRING
:
3191 case T_GENERALSTRING
:
3192 case T_UNIVERSALSTRING
:
3195 case T_GENERALIZEDTIME
:
3196 case T_OBJECTDESCRIPTOR
:
3197 chk_this_value_CStr(value
);
3200 chk_this_value_OID(value
);
3203 chk_this_value_ROID(value
);
3206 chk_this_value_Any(value
);
3212 self_ref
= chk_this_value_Choice(value
, lhs
, expected_value
, incomplete_allowed
,
3219 self_ref
= chk_this_value_Se(value
, lhs
, expected_value
, incomplete_allowed
,
3224 self_ref
= chk_this_value_SeOf(value
, lhs
, expected_value
, incomplete_allowed
,
3228 self_ref
= get_type_refd()->chk_this_value(value
, lhs
, expected_value
,
3229 incomplete_allowed
, omit_allowed
, NO_SUB_CHK
, implicit_omit
, is_str_elem
);
3231 case T_UNRESTRICTEDSTRING
:
3234 case T_EMBEDDED_PDV
:
3238 self_ref
= get_type_refd()->chk_this_value(value
, lhs
, expected_value
,
3239 incomplete_allowed
, omit_allowed
, NO_SUB_CHK
, NOT_IMPLICIT_OMIT
, is_str_elem
);
3242 chk_this_value_Verdict(value
);
3245 chk_this_value_Default(value
);
3248 self_ref
= chk_this_value_Array(value
, lhs
, expected_value
, incomplete_allowed
, implicit_omit
);
3251 // Remain silent. The error has already been reported in the definition
3252 // that the value belongs to.
3255 self_ref
= chk_this_value_Signature(value
, lhs
, expected_value
, incomplete_allowed
);
3258 chk_this_value_Component(value
);
3263 chk_this_value_FAT(value
);
3266 FATAL_ERROR("Type::chk_this_value()");
3269 // check value against subtype
3270 if(sub_chk
&& (sub_type
!=NULL
)) sub_type
->chk_this_value(value
);
3275 bool Type::chk_this_refd_value(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3276 ReferenceChain
* refch
, namedbool str_elem
)
3278 Reference
*ref
= value
->get_reference();
3279 Assignment
*ass
= ref
->get_refd_assignment();
3281 value
->set_valuetype(Value::V_ERROR
);
3286 bool self_ref
= (ass
== lhs
);
3288 // Exit immediately in case of infinite recursion.
3289 if (value
->get_valuetype() != Value::V_REFD
) return self_ref
;
3290 bool is_const
= false, error_flag
= false, chk_runs_on
= false;
3291 Type
*governor
= NULL
;
3292 switch (ass
->get_asstype()) {
3293 case Assignment::A_ERROR
:
3294 value
->set_valuetype(Value::V_ERROR
);
3296 case Assignment::A_CONST
:
3299 case Assignment::A_OBJECT
:
3300 case Assignment::A_OS
: {
3301 Setting
*setting
= ref
->get_refd_setting();
3302 if (!setting
|| setting
->get_st() == Setting::S_ERROR
) {
3303 value
->set_valuetype(Value::V_ERROR
);
3306 if (setting
->get_st() != Setting::S_V
) {
3307 ref
->error("This InformationFromObjects construct does not refer to "
3308 "a value: `%s'", value
->get_fullname().c_str());
3309 value
->set_valuetype(Value::V_ERROR
);
3312 governor
= dynamic_cast<Value
*>(setting
)->get_my_governor();
3313 if (!governor
) FATAL_ERROR("Type::chk_this_refd_value()");
3316 case Assignment::A_MODULEPAR
:
3320 case Assignment::A_EXT_CONST
:
3321 if (expected_value
== EXPECTED_CONSTANT
) {
3322 value
->error("Reference to an (evaluable) constant value was "
3323 "expected instead of %s",
3324 ass
->get_description().c_str());
3328 case Assignment::A_VAR
:
3329 case Assignment::A_PAR_VAL
:
3330 case Assignment::A_PAR_VAL_IN
:
3331 case Assignment::A_PAR_VAL_OUT
:
3332 case Assignment::A_PAR_VAL_INOUT
:
3333 switch (expected_value
) {
3334 case EXPECTED_CONSTANT
:
3335 value
->error("Reference to a constant value was expected instead of "
3336 "%s", ass
->get_description().c_str());
3339 case EXPECTED_STATIC_VALUE
:
3340 value
->error("Reference to a static value was expected instead of %s",
3341 ass
->get_description().c_str());
3348 case Assignment::A_MODULEPAR_TEMP
:
3349 case Assignment::A_TEMPLATE
:
3350 case Assignment::A_VAR_TEMPLATE
:
3351 case Assignment::A_PAR_TEMPL_IN
:
3352 case Assignment::A_PAR_TEMPL_OUT
:
3353 case Assignment::A_PAR_TEMPL_INOUT
:
3354 if (expected_value
!= EXPECTED_TEMPLATE
) {
3355 value
->error("Reference to a value was expected instead of %s",
3356 ass
->get_description().c_str());
3360 case Assignment::A_FUNCTION_RVAL
:
3363 case Assignment::A_EXT_FUNCTION_RVAL
:
3364 switch (expected_value
) {
3365 case EXPECTED_CONSTANT
:
3366 value
->error("Reference to a constant value was expected instead of "
3367 "the return value of %s",
3368 ass
->get_description().c_str());
3371 case EXPECTED_STATIC_VALUE
:
3372 value
->error("Reference to a static value was expected instead of "
3373 "the return value of %s",
3374 ass
->get_description().c_str());
3381 case Assignment::A_FUNCTION_RTEMP
:
3384 case Assignment::A_EXT_FUNCTION_RTEMP
:
3385 if (expected_value
!= EXPECTED_TEMPLATE
) {
3386 value
->error("Reference to a value was expected instead of a call of "
3387 "%s, which returns a template",
3388 ass
->get_description().c_str());
3392 case Assignment::A_FUNCTION
:
3393 case Assignment::A_EXT_FUNCTION
:
3394 value
->error("Reference to a %s was expected instead of a call of %s, "
3395 "which does not have return type",
3396 expected_value
== EXPECTED_TEMPLATE
3397 ? "value or template" : "value",
3398 ass
->get_description().c_str());
3399 value
->set_valuetype(Value::V_ERROR
);
3402 value
->error("Reference to a %s was expected instead of %s",
3403 expected_value
== EXPECTED_TEMPLATE
3404 ? "value or template" : "value",
3405 ass
->get_description().c_str());
3406 value
->set_valuetype(Value::V_ERROR
);
3408 } // switch ass->get_asstype()
3410 ref
->get_my_scope()->chk_runs_on_clause(ass
, *ref
, "call");
3412 governor
= ass
->get_Type()->get_field_type(ref
->get_subrefs(),
3415 value
->set_valuetype(Value::V_ERROR
);
3418 TypeCompatInfo
info(value
->get_my_scope()->get_scope_mod(), this,
3419 governor
, true, false);
3420 info
.set_str1_elem(str_elem
);
3421 if (ref
->get_subrefs()) info
.set_str2_elem(ref
->get_subrefs()->refers_to_string_element());
3424 if (!is_compatible(governor
, &info
, &l_chain
, &r_chain
)) {
3425 // Port or signature values do not exist at all. These errors are
3426 // already reported at those definitions. Extra errors should not be
3428 Type
*t
= get_type_refd_last();
3429 switch (t
->typetype
) {
3431 // Neither port values nor templates exist.
3434 // Only signature templates may exist.
3435 if (expected_value
== EXPECTED_TEMPLATE
)
3436 value
->error("Type mismatch: a signature template of type `%s' was "
3437 "expected instead of `%s'", get_typename().c_str(),
3438 governor
->get_typename().c_str());
3441 if (info
.is_subtype_error()) {
3442 value
->error("%s", info
.get_subtype_error().c_str());
3443 } else if (!info
.is_erroneous()) {
3444 value
->error("Type mismatch: a %s of type `%s' was expected "
3445 "instead of `%s'", expected_value
== EXPECTED_TEMPLATE
3446 ? "value or template" : "value",
3447 get_typename().c_str(),
3448 governor
->get_typename().c_str());
3450 // The semantic error was found by the new code. It was better to
3451 // do the assembly inside TypeCompatInfo.
3452 value
->error("%s", info
.get_error_str_str().c_str());
3458 if (info
.needs_conversion()) value
->set_needs_conversion();
3462 value
->set_valuetype(Value::V_ERROR
);
3465 // Checking for circular references.
3466 Value
*v_last
= value
->get_value_refd_last(refch
, expected_value
);
3467 if (is_const
&& v_last
->get_valuetype() != Value::V_ERROR
) {
3468 // If a referenced universal charstring value points to a literal
3469 // charstring then drop the reference and create a literal ustring to
3470 // avoid run-time conversion.
3471 if (v_last
->get_valuetype() == Value::V_CSTR
3472 && get_typetype_ttcn3(get_type_refd_last()->typetype
) == T_USTR
)
3473 value
->set_valuetype(Value::V_USTR
);
3474 // Check v_last against the subtype constraints.
3475 if (sub_type
!=NULL
) sub_type
->chk_this_value(value
);
3481 void Type::chk_this_invoked_value(Value
*value
, Common::Assignment
*,
3482 expected_value_t expected_value
)
3484 value
->get_value_refd_last(NULL
, expected_value
);
3485 if (value
->get_valuetype() == Value::V_ERROR
) return;
3486 Type
*invoked_t
= value
->get_invoked_type(expected_value
);
3487 if (invoked_t
->get_typetype() == T_ERROR
) return;
3488 invoked_t
= invoked_t
->get_type_refd_last();
3490 switch (invoked_t
->get_typetype()) {
3491 case Type::T_FUNCTION
:
3492 t
= invoked_t
->get_function_return_type();
3495 FATAL_ERROR("Type::chk_this_invoked_value()");
3499 value
->error("The type `%s' has no return type, `%s' expected",
3500 invoked_t
->get_typename().c_str(), get_typename().c_str());
3501 else if (!is_compatible(t
, NULL
)) {
3502 value
->error("Incompatible value: `%s' value was expected",
3503 get_typename().c_str());
3507 void Type::chk_this_value_Null(Value
*value
)
3509 Value
*v
=value
->get_value_refd_last();
3510 switch(v
->get_valuetype()) {
3514 value
->error("NULL value was expected");
3515 value
->set_valuetype(Value::V_ERROR
);
3520 void Type::chk_this_value_Bool(Value
*value
)
3522 Value
*v
=value
->get_value_refd_last();
3523 switch(v
->get_valuetype()) {
3527 value
->error("%s value was expected",
3528 value
->is_asn1() ? "BOOLEAN" : "boolean");
3529 value
->set_valuetype(Value::V_ERROR
);
3534 void Type::chk_this_value_Int(Value
*value
)
3536 Value
*v
=value
->get_value_refd_last();
3537 switch(v
->get_valuetype()) {
3541 value
->error("integer value was expected");
3542 value
->set_valuetype(Value::V_ERROR
);
3548 void Type::chk_this_value_Int_A(Value
*value
)
3550 Value
*v
=value
->get_value_refd_last();
3551 switch(v
->get_valuetype()) {
3554 case Value::V_NAMEDINT
:
3555 if(!u
.namednums
.nvs
)
3556 FATAL_ERROR("Type::chk_this_value_Int_A()");
3558 (Value::V_INT
, u
.namednums
.nvs
->
3559 get_nv_byName(*v
->get_val_id())->get_value()->get_val_Int()->get_val());
3562 value
->error("INTEGER value was expected");
3563 value
->set_valuetype(Value::V_ERROR
);
3568 void Type::chk_this_value_Real(Value
*value
)
3570 Value
*v
= value
->get_value_refd_last();
3571 if (value
->is_asn1()) {
3572 if (value
->is_ref()) {
3573 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3574 if (t
->get_typetype() != T_REAL
) {
3575 value
->error("REAL value was expected");
3576 value
->set_valuetype(Value::V_ERROR
);
3580 switch (v
->get_valuetype()) {
3583 case Value::V_UNDEF_BLOCK
:{
3584 v
->set_valuetype(Value::V_SEQ
);
3585 Identifier
t_id(Identifier::ID_ASN
, string("REAL"));
3586 bool self_ref
= get_my_scope()->get_scope_asss()->get_local_ass_byId(t_id
)
3587 ->get_Type()->chk_this_value(v
, 0, EXPECTED_CONSTANT
, INCOMPLETE_NOT_ALLOWED
,
3588 OMIT_NOT_ALLOWED
, SUB_CHK
);
3590 v
->set_valuetype(Value::V_REAL
);
3593 v
->set_valuetype(Value::V_REAL
);
3596 value
->error("REAL value was expected");
3597 value
->set_valuetype(Value::V_ERROR
);
3601 switch(v
->get_valuetype()) {
3605 value
->error("float value was expected");
3606 value
->set_valuetype(Value::V_ERROR
);
3612 void Type::chk_this_value_Enum(Value
*value
)
3614 switch(value
->get_valuetype()) {
3618 value
->error("%s value was expected",
3619 value
->is_asn1() ? "ENUMERATED" : "enumerated");
3620 value
->set_valuetype(Value::V_ERROR
);
3625 void Type::chk_this_value_BStr(Value
*value
)
3627 Value
*v
= value
->get_value_refd_last();
3628 switch(v
->get_valuetype()) {
3632 value
->error("bitstring value was expected");
3633 value
->set_valuetype(Value::V_ERROR
);
3638 void Type::chk_this_value_namedbits(Value
*value
)
3640 if (!value
) FATAL_ERROR("Type::chk_this_value_namedbits()");
3641 value
->set_valuetype(Value::V_NAMEDBITS
);
3642 if(!u
.namednums
.nvs
) {
3643 value
->error("No named bits are defined in type `%s'",
3644 get_typename().c_str());
3645 value
->set_valuetype(Value::V_ERROR
);
3648 string
*bstring
= new string("");
3649 for(size_t i
=0; i
< value
->get_nof_ids(); i
++) {
3650 Identifier
*id
= value
->get_id_byIndex(i
);
3651 if(!u
.namednums
.nvs
->has_nv_withName(*id
)) {
3653 error("No named bit with name `%s' is defined in type `%s'",
3654 id
->get_dispname().c_str(), get_typename().c_str());
3655 value
->set_valuetype(Value::V_ERROR
);
3658 size_t bitnum
= static_cast<size_t>
3659 (u
.namednums
.nvs
->get_nv_byName(*id
)->get_value()->get_val_Int()
3661 if(bstring
->size() < bitnum
+ 1) bstring
->resize(bitnum
+ 1, '0');
3662 (*bstring
)[bitnum
] = '1';
3664 value
->set_valuetype(Value::V_BSTR
, bstring
);
3667 void Type::chk_this_value_BStr_A(Value
*value
)
3669 Value
*v
= value
->get_value_refd_last();
3670 if (value
->is_asn1()) {
3671 if(value
->is_ref()) {
3672 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3673 if(t
->get_typetype()!=T_BSTR_A
&& t
->get_typetype()!=T_BSTR
) {
3674 value
->error("(reference to) BIT STRING value was expected");
3675 value
->set_valuetype(Value::V_ERROR
);
3679 switch(v
->get_valuetype()) {
3683 if (v
!= value
) FATAL_ERROR("Common::Type::chk_this_value_BStr_A()");
3684 v
->set_valuetype(Value::V_BSTR
);
3686 case Value::V_UNDEF_BLOCK
:
3687 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_BStr_A()");
3688 chk_this_value_namedbits(v
);
3691 value
->error("BIT STRING value was expected");
3692 value
->set_valuetype(Value::V_ERROR
);
3696 switch(v
->get_valuetype()) {
3700 value
->error("bitstring value was expected");
3701 value
->set_valuetype(Value::V_ERROR
);
3707 void Type::chk_this_value_HStr(Value
*value
)
3709 Value
*v
= value
->get_value_refd_last();
3710 switch (v
->get_valuetype()) {
3714 value
->error("hexstring value was expected");
3715 value
->set_valuetype(Value::V_ERROR
);
3720 void Type::chk_this_value_OStr(Value
*value
)
3722 Value
*v
= value
->get_value_refd_last();
3723 if (value
->is_asn1()) {
3724 if (value
->is_ref()) {
3725 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3726 if(t
->get_typetype() != T_OSTR
) {
3727 value
->error("(reference to) OCTET STRING value was expected");
3728 value
->set_valuetype(Value::V_ERROR
);
3732 switch(v
->get_valuetype()) {
3737 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_OStr()");
3738 v
->set_valuetype(Value::V_OSTR
);
3741 value
->error("OCTET STRING value was expected");
3742 value
->set_valuetype(Value::V_ERROR
);
3746 switch(v
->get_valuetype()) {
3750 value
->error("octetstring value was expected");
3751 value
->set_valuetype(Value::V_ERROR
);
3757 /** \todo enhance */
3758 void Type::chk_this_value_CStr(Value
*value
)
3761 switch(value
->get_valuetype()) {
3762 case Value::V_UNDEF_BLOCK
:
3763 value
->set_valuetype(Value::V_CHARSYMS
);
3764 if (value
->get_valuetype() == Value::V_ERROR
) return;
3766 case Value::V_CHARSYMS
:
3771 case T_UNIVERSALSTRING
:
3772 value
->set_valuetype(Value::V_USTR
);
3774 case T_TELETEXSTRING
:
3775 case T_VIDEOTEXSTRING
:
3776 case T_GRAPHICSTRING
:
3777 case T_OBJECTDESCRIPTOR
:
3778 case T_GENERALSTRING
:
3779 value
->set_valuetype(Value::V_ISO2022STR
);
3782 case T_NUMERICSTRING
:
3783 case T_PRINTABLESTRING
:
3785 case T_VISIBLESTRING
:
3787 case T_GENERALIZEDTIME
:
3788 value
->set_valuetype(Value::V_CSTR
);
3791 FATAL_ERROR("chk_this_value_CStr()");
3799 case T_UNIVERSALSTRING
:
3801 case T_TELETEXSTRING
:
3802 case T_VIDEOTEXSTRING
:
3803 case T_GRAPHICSTRING
:
3804 case T_OBJECTDESCRIPTOR
:
3805 case T_GENERALSTRING
:
3808 if(value->get_val_ustr().is_cstr()) {
3809 value->warning("ISO-2022 string value was expected (converting"
3810 " simple ISO-10646 string).");
3811 value->set_valuetype(Value::V_CSTR);
3814 value->error("ISO-2022 string value was expected (instead of"
3815 " ISO-10646 string).");
3816 value->set_valuetype(Value::V_ERROR);
3821 case T_NUMERICSTRING
:
3822 case T_PRINTABLESTRING
:
3824 case T_VISIBLESTRING
:
3826 case T_GENERALIZEDTIME
:
3827 value
->set_valuetype(Value::V_CSTR
);
3830 FATAL_ERROR("Type::chk_this_value_CStr()");
3838 case T_UNIVERSALSTRING
:
3839 value
->set_valuetype(Value::V_USTR
);
3841 case T_TELETEXSTRING
:
3842 case T_VIDEOTEXSTRING
:
3843 case T_GRAPHICSTRING
:
3844 case T_OBJECTDESCRIPTOR
:
3845 case T_GENERALSTRING
:
3846 value
->set_valuetype(Value::V_ISO2022STR
);
3849 case T_NUMERICSTRING
:
3850 case T_PRINTABLESTRING
:
3852 case T_VISIBLESTRING
:
3854 case T_GENERALIZEDTIME
:
3857 FATAL_ERROR("chk_this_value_CStr()");
3860 case Value::V_ISO2022STR
:
3865 case T_UNIVERSALSTRING
:
3866 value
->error("ISO-10646 string value was expected (instead of"
3867 " ISO-2022 string).");
3868 value
->set_valuetype(Value::V_ERROR
);
3870 case T_TELETEXSTRING
:
3871 case T_VIDEOTEXSTRING
:
3872 case T_GRAPHICSTRING
:
3873 case T_OBJECTDESCRIPTOR
:
3874 case T_GENERALSTRING
:
3877 case T_NUMERICSTRING
:
3878 case T_PRINTABLESTRING
:
3880 case T_VISIBLESTRING
:
3882 case T_GENERALIZEDTIME
:
3883 value
->set_valuetype(Value::V_ISO2022STR
);
3886 FATAL_ERROR("chk_this_value_CStr()");
3890 value
->error("character string value was expected");
3891 value
->set_valuetype(Value::V_ERROR
);
3896 void Type::chk_this_value_OID(Value
*value
)
3898 Value
*v
= value
->get_value_refd_last();
3899 if (value
->is_asn1()) {
3900 if (value
->is_ref()) {
3901 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3902 if (t
->get_typetype() != T_OID
) {
3903 value
->error("(reference to) OBJECT IDENTIFIER value was "
3905 value
->set_valuetype(Value::V_ERROR
);
3909 switch (v
->get_valuetype()) {
3912 case Value::V_UNDEF_BLOCK
:
3913 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_OID()");
3914 v
->set_valuetype(Value::V_OID
);
3918 value
->error("OBJECT IDENTIFIER value was expected");
3919 value
->set_valuetype(Value::V_ERROR
);
3923 switch (v
->get_valuetype()) {
3928 value
->error("objid value was expected");
3929 value
->set_valuetype(Value::V_ERROR
);
3935 void Type::chk_this_value_ROID(Value
*value
)
3937 Value
*v
= value
->get_value_refd_last();
3938 if(value
->is_ref()) {
3939 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3940 if (t
->get_typetype() != T_ROID
) {
3941 value
->error("(reference to) RELATIVE-OID value was expected");
3942 value
->set_valuetype(Value::V_ERROR
);
3946 switch(v
->get_valuetype()) {
3949 case Value::V_UNDEF_BLOCK
:
3950 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_ROID()");
3951 v
->set_valuetype(Value::V_ROID
);
3955 value
->error("RELATIVE-OID value was expected");
3956 value
->set_valuetype(Value::V_ERROR
);
3961 void Type::chk_this_value_Any(Value
*value
)
3963 Value
*v
= value
->get_value_refd_last();
3964 if (value
->is_asn1()) {
3965 if (value
->is_ref()) {
3966 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3967 if(t
->get_typetype()!=T_ANY
&& t
->get_typetype()!=T_OSTR
) {
3968 value
->error("(reference to) OCTET STRING or ANY type value"
3970 value
->set_valuetype(Value::V_ERROR
);
3974 switch(v
->get_valuetype()) {
3978 if (v
!=value
) FATAL_ERROR("Type::chk_this_value_Any()");
3979 v
->set_valuetype(Value::V_OSTR
);
3982 value
->error("ANY (OCTET STRING) value was expected");
3983 value
->set_valuetype(Value::V_ERROR
);
3988 switch(v
->get_valuetype()) {
3992 value
->error("octetstring value was expected for ASN ANY type");
3993 value
->set_valuetype(Value::V_ERROR
);
3999 /** Return a string containing the names of existing fields (components).
4001 * @param t a Type object
4002 * @return a string (l-value, temporary)
4003 * @pre t must be a sequence, choice, set, anytype, open type
4005 static string
actual_fields(Type
& t
) // alas, not even get_nof_comps() is const
4007 static const string
has_no(" has no ");
4008 size_t ncomps
= t
.get_nof_comps();
4009 const string
fields_or_comps(t
.is_asn1() ? "components" : "fields");
4011 string
msg("Valid ");
4012 msg
+= fields_or_comps
;
4014 msg
+= t
.get_comp_byIndex(0)->get_name().get_dispname();
4015 for (size_t ci
=1; ci
< ncomps
; ++ci
) {
4017 msg
+= t
.get_comp_byIndex(ci
)->get_name().get_dispname();
4021 else return t
.get_fullname() + has_no
+ fields_or_comps
;
4025 bool Type::chk_this_value_Choice(Value
*value
, Common::Assignment
*lhs
,
4026 expected_value_t expected_value
, namedbool incomplete_allowed
, namedbool implicit_omit
)
4028 bool self_ref
= false;
4029 switch(value
->get_valuetype()) {
4031 if (value
->is_asn1()) {
4032 value
->error("CHOICE value was expected for type `%s'",
4033 get_fullname().c_str());
4034 value
->set_valuetype(Value::V_ERROR
);
4037 // the valuetype can be ERROR if the value has no fields at all
4038 if (value
->get_valuetype() == Value::V_ERROR
) return false;
4039 // The value notation for TTCN record/union types
4040 // cannot be distinguished during parsing. Now we know it's a union.
4041 value
->set_valuetype(Value::V_CHOICE
);
4044 case Value::V_CHOICE
: {
4045 if (!value
->is_asn1() && typetype
== T_OPENTYPE
) {
4046 // allow the alternatives of open types as both lower and upper identifiers
4047 value
->set_alt_name_to_lowercase();
4049 const Identifier
& alt_name
= value
->get_alt_name();
4050 if(!has_comp_withName(alt_name
)) {
4051 if (value
->is_asn1()) {
4052 value
->error("Reference to non-existent alternative `%s' in CHOICE"
4053 " value for type `%s'",
4054 alt_name
.get_dispname().c_str(),
4055 get_fullname().c_str());
4057 value
->error("Reference to non-existent field `%s' in union "
4058 "value for type `%s'",
4059 alt_name
.get_dispname().c_str(),
4060 get_fullname().c_str());
4062 value
->set_valuetype(Value::V_ERROR
);
4063 value
->note("%s", actual_fields(*this).c_str());
4066 Type
*alt_type
= get_comp_byName(alt_name
)->get_type();
4067 Value
*alt_value
= value
->get_alt_value();
4068 Error_Context
cntxt(value
, "In value for %s `%s'",
4069 value
->is_asn1() ? "alternative" : "union field",
4070 alt_name
.get_dispname().c_str());
4071 alt_value
->set_my_governor(alt_type
);
4072 alt_type
->chk_this_value_ref(alt_value
);
4073 self_ref
|= alt_type
->chk_this_value(alt_value
, lhs
, expected_value
,
4074 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4075 if (alt_value
->get_valuetype() == Value::V_NOTUSED
) {
4076 value
->set_valuetype(Value::V_NOTUSED
);
4080 value
->error("%s value was expected for type `%s'",
4081 value
->is_asn1() ? "CHOICE" : "union",
4082 get_fullname().c_str());
4083 value
->set_valuetype(Value::V_ERROR
);
4089 bool Type::chk_this_value_Se(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4090 namedbool incomplete_allowed
, namedbool implicit_omit
)
4092 if (value
->is_asn1())
4093 return chk_this_value_Se_A(value
, lhs
, expected_value
, implicit_omit
);
4095 return chk_this_value_Se_T(value
, lhs
, expected_value
, incomplete_allowed
,
4099 bool Type::chk_this_value_Se_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4100 namedbool incomplete_allowed
, namedbool implicit_omit
)
4102 switch (value
->get_valuetype()) {
4104 if (typetype
== T_SET_A
|| typetype
== T_SET_T
) {
4105 value
->set_valuetype(Value::V_SET
);
4106 return chk_this_value_Set_T(value
, lhs
, expected_value
, incomplete_allowed
,
4109 return chk_this_value_Seq_T(value
, lhs
, expected_value
, incomplete_allowed
,
4113 case Value::V_SEQOF
:
4114 if (typetype
== T_SET_A
|| typetype
== T_SET_T
) {
4115 if (value
->get_nof_comps() == 0) {
4116 if (get_nof_comps() == 0) {
4117 value
->set_valuetype(Value::V_SET
);
4119 value
->error("A non-empty set value was expected for type `%s'",
4120 get_fullname().c_str());
4121 value
->set_valuetype(Value::V_ERROR
);
4124 // This will catch the indexed assignment notation as well.
4125 value
->error("Value list notation cannot be used for "
4126 "%s type `%s'", typetype
== T_SET_A
? "SET" : "set",
4127 get_fullname().c_str());
4128 value
->set_valuetype(Value::V_ERROR
);
4131 if (value
->is_indexed()) {
4132 value
->error("Indexed assignment notation cannot be used for %s "
4133 "type `%s'", typetype
== T_SEQ_A
4134 ? "SEQUENCE" : "record",
4135 get_fullname().c_str());
4136 value
->set_valuetype(Value::V_ERROR
);
4138 value
->set_valuetype(Value::V_SEQ
);
4139 return chk_this_value_Seq_T(value
, lhs
, expected_value
, incomplete_allowed
,
4145 value
->error("%s value was expected for type `%s'",
4146 typetype
== T_SEQ_T
? "Record" : "Set",
4147 get_fullname().c_str());
4148 value
->set_valuetype(Value::V_ERROR
);
4154 bool Type::chk_this_value_Seq_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4155 namedbool incomplete_allowed
, namedbool implicit_omit
)
4157 bool self_ref
= false;
4158 map
<string
, NamedValue
> comp_map
;
4159 // it is set to false if we have lost the ordering
4160 bool in_synch
= true;
4161 const size_t n_type_comps
= get_nof_comps();
4162 size_t n_value_comps
= value
->get_nof_comps();
4163 // for incomplete values
4164 CompField
*last_cf
= 0;
4165 size_t next_index
= 0;
4166 size_t seq_index
= 0;
4167 bool is_empty
= n_type_comps
> 0; // don't do this check if the record type has no fields
4168 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++, seq_index
++) {
4169 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4170 const Identifier
& value_id
= nv
->get_name();
4171 const string
& value_name
= value_id
.get_name();
4172 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4173 if (!has_comp_withName(value_id
)) {
4174 nv
->error("Reference to non-existent field `%s' in record value for "
4175 "type `%s'", value_dispname_str
, get_typename().c_str());
4176 nv
->note("%s", actual_fields(*this).c_str());
4179 } else if (comp_map
.has_key(value_name
)) {
4180 nv
->error("Duplicate record field `%s'", value_dispname_str
);
4181 comp_map
[value_name
]->note("Field `%s' is already given here",
4182 value_dispname_str
);
4184 } else comp_map
.add(value_name
, nv
);
4185 CompField
*cf
= get_comp_byName(value_id
);
4186 // check the ordering of fields
4188 if (incomplete_allowed
) {
4190 for (size_t i
= next_index
; i
< n_type_comps
; i
++) {
4191 CompField
*cf2
= get_comp_byIndex(i
);
4192 if (value_name
== cf2
->get_name().get_name()) {
4200 nv
->error("Field `%s' cannot appear after field `%s' in record "
4201 "value", value_dispname_str
,
4202 last_cf
->get_name().get_dispname().c_str());
4206 // the value must be complete unless implicit omit is set
4207 CompField
*cf2
= get_comp_byIndex(seq_index
);
4208 CompField
*cf2_orig
= cf2
;
4209 while (implicit_omit
&& seq_index
< n_type_comps
&& cf2
!= cf
&&
4210 cf2
->get_is_optional())
4211 cf2
= get_comp_byIndex(++seq_index
);
4212 if (seq_index
>= n_type_comps
|| cf2
!= cf
) {
4213 nv
->error("Unexpected field `%s' in record value, "
4214 "expecting `%s'", value_dispname_str
,
4215 cf2_orig
->get_name().get_dispname().c_str());
4220 Type
*type
= cf
->get_type();
4221 Value
*comp_value
= nv
->get_value();
4222 comp_value
->set_my_governor(type
);
4223 if (comp_value
->get_valuetype() == Value::V_NOTUSED
) {
4224 if (implicit_omit
) {
4225 comp_value
->set_valuetype(Value::V_OMIT
);
4230 Error_Context
cntxt(nv
, "In value for record field `%s'",
4231 value_dispname_str
);
4232 type
->chk_this_value_ref(comp_value
);
4233 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
, incomplete_allowed
,
4234 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4235 if (comp_value
->get_valuetype() != Value::V_NOTUSED
) {
4240 // all of the record's fields are unused (-), set the record to unused
4241 // to avoid unnecessary code generation
4242 value
->set_valuetype(Value::V_NOTUSED
);
4244 else if (!incomplete_allowed
|| implicit_omit
) {
4245 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4246 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
4247 if (!comp_map
.has_key(id
.get_name())) {
4248 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
)
4249 value
->add_se_comp(new NamedValue(new Identifier(id
),
4250 new Value(Value::V_OMIT
)));
4251 else if (!incomplete_allowed
)
4252 value
->error("Field `%s' is missing from record value",
4253 id
.get_dispname().c_str());
4261 bool Type::chk_this_value_Set_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4262 namedbool incomplete_allowed
, namedbool implicit_omit
)
4264 bool self_ref
= false;
4265 map
<string
, NamedValue
> comp_map
;
4266 size_t n_type_comps
= get_nof_comps();
4267 size_t n_value_comps
= value
->get_nof_comps();
4268 bool is_empty
= n_type_comps
> 0; // don't do this check if the set type has no fields
4269 for(size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4270 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4271 const Identifier
& value_id
= nv
->get_name();
4272 const string
& value_name
= value_id
.get_name();
4273 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4274 if (!has_comp_withName(value_id
)) {
4275 nv
->error("Reference to non-existent field `%s' in set value for "
4276 "type `%s'", value_dispname_str
, get_typename().c_str());
4277 nv
->note("%s", actual_fields(*this).c_str());
4279 } else if (comp_map
.has_key(value_name
)) {
4280 nv
->error("Duplicate set field `%s'", value_dispname_str
);
4281 comp_map
[value_name
]->note("Field `%s' is already given here",
4282 value_dispname_str
);
4283 } else comp_map
.add(value_name
, nv
);
4284 CompField
*cf
= get_comp_byName(value_id
);
4285 Type
*type
= cf
->get_type();
4286 Value
*comp_value
= nv
->get_value();
4287 comp_value
->set_my_governor(type
);
4288 if (comp_value
->get_valuetype() == Value::V_NOTUSED
) {
4289 if (implicit_omit
) {
4290 comp_value
->set_valuetype(Value::V_OMIT
);
4295 Error_Context
cntxt(nv
, "In value for set field `%s'",
4296 value_dispname_str
);
4297 type
->chk_this_value_ref(comp_value
);
4298 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
, incomplete_allowed
,
4299 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4300 if (comp_value
->get_valuetype() != Value::V_NOTUSED
) {
4305 // all of the set's fields are unused (-), set the set to unused to avoid
4306 // unnecessary code generation
4307 value
->set_valuetype(Value::V_NOTUSED
);
4309 else if (!incomplete_allowed
|| implicit_omit
) {
4310 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4311 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
4312 if(!comp_map
.has_key(id
.get_name())) {
4313 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
)
4314 value
->add_se_comp(new NamedValue(new Identifier(id
),
4315 new Value(Value::V_OMIT
)));
4316 else if (!incomplete_allowed
)
4317 value
->error("Field `%s' is missing from set value %s",
4318 id
.get_dispname().c_str(), implicit_omit
? "yes" : "no");
4326 bool Type::chk_this_value_Se_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4327 namedbool implicit_omit
)
4329 if(value
->get_valuetype()==Value::V_UNDEF_BLOCK
) {
4330 if(typetype
== T_SEQ_A
) value
->set_valuetype(Value::V_SEQ
);
4331 else value
->set_valuetype(Value::V_SET
);
4333 switch(value
->get_valuetype()) {
4335 return chk_this_value_Seq_A(value
, lhs
, expected_value
, implicit_omit
);
4337 return chk_this_value_Set_A(value
, lhs
, expected_value
, implicit_omit
);
4339 value
->error("%s value was expected",
4340 typetype
== T_SEQ_A
? "SEQUENCE" : "SET");
4341 value
->set_valuetype(Value::V_ERROR
);
4347 bool Type::chk_this_value_Seq_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4348 namedbool implicit_omit
)
4350 bool self_ref
= false;
4351 map
<string
, NamedValue
> comp_map
;
4352 // it is set to false if we have lost the ordering
4353 bool in_synch
= true;
4354 size_t n_type_comps
= u
.secho
.ctss
->get_nof_comps();
4355 size_t n_value_comps
= value
->get_nof_comps();
4357 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4358 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4359 const Identifier
& value_id
= nv
->get_name();
4360 const string
& value_name
= value_id
.get_name();
4361 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4362 if (!u
.secho
.ctss
->has_comp_withName(value_id
)) {
4363 nv
->error("Reference to non-existent component `%s' of SEQUENCE "
4364 "type `%s'", value_dispname_str
, get_typename().c_str());
4365 nv
->note("%s", actual_fields(*this).c_str());
4368 } else if (comp_map
.has_key(value_name
)) {
4369 nv
->error("Duplicate SEQUENCE component `%s'", value_dispname_str
);
4370 comp_map
[value_name
]->note("Component `%s' is already given here",
4371 value_dispname_str
);
4373 } else comp_map
.add(value_name
, nv
);
4374 CompField
*cf
= u
.secho
.ctss
->get_comp_byName(value_id
);
4377 for ( ; t_i
< n_type_comps
; t_i
++) {
4378 cf2
= u
.secho
.ctss
->get_comp_byIndex(t_i
);
4379 if (cf2
== cf
|| (!cf2
->get_is_optional() && !cf2
->has_default() &&
4384 if (t_i
< n_type_comps
) {
4385 nv
->error("Unexpected component `%s' in SEQUENCE value, "
4386 "expecting `%s'", value_dispname_str
,
4387 cf2
->get_name().get_dispname().c_str());
4389 nv
->error("Unexpected component `%s' in SEQUENCE value",
4390 value_dispname_str
);
4395 Type
*type
= cf
->get_type();
4396 Error_Context
cntxt(nv
, "In value for SEQUENCE component `%s'",
4397 value_dispname_str
);
4398 Value
*comp_value
= nv
->get_value();
4399 comp_value
->set_my_governor(type
);
4400 type
->chk_this_value_ref(comp_value
);
4401 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4402 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4404 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4405 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4406 const Identifier
& id
= cf
->get_name();
4407 if (!comp_map
.has_key(id
.get_name())) {
4408 if (!cf
->get_is_optional() && !cf
->has_default())
4409 value
->error("Mandatory component `%s' is missing from SEQUENCE value",
4410 id
.get_dispname().c_str());
4411 else if (cf
->get_is_optional() && implicit_omit
)
4412 value
->add_se_comp(new NamedValue(new Identifier(id
),
4413 new Value(Value::V_OMIT
)));
4420 bool Type::chk_this_value_Set_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4421 namedbool implicit_omit
)
4423 bool self_ref
= false;
4424 map
<string
, NamedValue
> comp_map
;
4425 size_t n_type_comps
= u
.secho
.ctss
->get_nof_comps();
4426 size_t n_value_comps
= value
->get_nof_comps();
4427 for(size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4428 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4429 const Identifier
& value_id
= nv
->get_name();
4430 const string
& value_name
= value_id
.get_name();
4431 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4432 if (!u
.secho
.ctss
->has_comp_withName(value_id
)) {
4433 value
->error("Reference to non-existent component `%s' of SET type "
4434 "`%s'", value_dispname_str
, get_typename().c_str());
4435 nv
->note("%s", actual_fields(*this).c_str());
4437 } else if (comp_map
.has_key(value_name
)) {
4438 nv
->error("Duplicate SET component `%s'", value_dispname_str
);
4439 comp_map
[value_name
]->note("Component `%s' is already given here",
4440 value_dispname_str
);
4441 } else comp_map
.add(value_name
, nv
);
4443 u
.secho
.ctss
->get_comp_byName(value_id
)->get_type();
4444 Value
*comp_value
= nv
->get_value();
4445 Error_Context
cntxt(nv
, "In value for SET component `%s'",
4446 value_dispname_str
);
4447 comp_value
->set_my_governor(type
);
4448 type
->chk_this_value_ref(comp_value
);
4449 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4450 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4452 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4453 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4454 const Identifier
& id
= cf
->get_name();
4455 if (!comp_map
.has_key(id
.get_name())) {
4456 if (!cf
->get_is_optional() && !cf
->has_default())
4457 value
->error("Mandatory component `%s' is missing from SET value",
4458 id
.get_dispname().c_str());
4459 else if (cf
->get_is_optional() && implicit_omit
)
4460 value
->add_se_comp(new NamedValue(new Identifier(id
),
4461 new Value(Value::V_OMIT
)));
4468 bool Type::chk_this_value_SeOf(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4469 namedbool incomplete_allowed
, namedbool implicit_omit
)
4471 bool self_ref
= false;
4472 const char *valuetypename
;
4473 if (value
->is_asn1()) {
4474 if (typetype
== T_SEQOF
) valuetypename
= "SEQUENCE OF";
4475 else valuetypename
= "SET OF";
4477 if (typetype
== T_SEQOF
) valuetypename
= "record of";
4478 else valuetypename
= "set of";
4480 if (value
->get_valuetype() == Value::V_UNDEF_BLOCK
) {
4481 if (typetype
== T_SEQOF
) value
->set_valuetype(Value::V_SEQOF
);
4482 else value
->set_valuetype(Value::V_SETOF
);
4484 switch (value
->get_valuetype()) {
4485 case Value::V_SEQOF
:
4486 if (typetype
== T_SETOF
) value
->set_valuetype(Value::V_SETOF
);
4488 case Value::V_SETOF
: {
4489 if (!value
->is_indexed()) {
4490 for (size_t i
= 0; i
< value
->get_nof_comps(); i
++) {
4491 Value
*v_comp
= value
->get_comp_byIndex(i
);
4492 Error_Context
cntxt(v_comp
, "In component #%lu",
4493 (unsigned long)(i
+ 1));
4494 v_comp
->set_my_governor(u
.seof
.ofType
);
4495 if (v_comp
->get_valuetype() == Value::V_NOTUSED
) {
4496 if (!incomplete_allowed
)
4497 v_comp
->error("Not used symbol `-' is not allowed in this "
4500 u
.seof
.ofType
->chk_this_value_ref(v_comp
);
4501 self_ref
|= u
.seof
.ofType
->chk_this_value(v_comp
, lhs
, expected_value
,
4502 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4506 // Only constant values with constant indicies can be checked at
4507 // compile time. Constant expressions evaluated.
4508 bool check_holes
= expected_value
== EXPECTED_CONSTANT
;
4510 map
<Int
, Int
> index_map
;
4511 for (size_t i
= 0; i
< value
->get_nof_comps(); i
++) {
4512 Error_Context
cntxt(this, "In component #%lu",
4513 (unsigned long)(i
+ 1));
4514 Value
*val
= value
->get_comp_byIndex(i
);
4515 Value
*index
= value
->get_index_byIndex(i
);
4516 index
->chk_expr_int(expected_value
);
4517 if (index
->get_valuetype() != Value::V_ERROR
&&
4518 index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
4519 const int_val_t
*index_int
= index
->get_value_refd_last()
4521 if (*index_int
> INT_MAX
) {
4522 index
->error("An integer value less than `%d' was expected for "
4523 "indexing type `%s' instead of `%s'", INT_MAX
,
4524 get_typename().c_str(),
4525 (index_int
->t_str()).c_str());
4526 index
->set_valuetype(Value::V_ERROR
);
4527 check_holes
= false;
4529 Int index_val
= index_int
->get_val();
4530 if (index_val
< 0) {
4531 index
->error("A non-negative integer value was expected for "
4532 "indexing type `%s' instead of `%s'",
4533 get_typename().c_str(),
4534 Int2string(index_val
).c_str());
4535 index
->set_valuetype(Value::V_ERROR
);
4536 check_holes
= false;
4537 } else if (index_map
.has_key(index_val
)) {
4538 index
->error("Duplicate index value `%s' for components `%s' "
4539 "and `%s'", Int2string(index_val
).c_str(),
4540 Int2string((Int
)i
+ 1).c_str(),
4541 Int2string(*index_map
[index_val
]).c_str());
4542 index
->set_valuetype(Value::V_ERROR
);
4543 check_holes
= false;
4545 index_map
.add(index_val
, new Int((Int
)i
+ 1));
4546 if (max_index
< index_val
)
4547 max_index
= index_val
;
4551 // The index cannot be determined.
4552 check_holes
= false;
4554 val
->set_my_governor(u
.seof
.ofType
);
4555 u
.seof
.ofType
->chk_this_value_ref(val
);
4556 self_ref
|= u
.seof
.ofType
->chk_this_value(val
, lhs
, expected_value
,
4557 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
);
4560 if ((size_t)max_index
!= index_map
.size() - 1) {
4561 value
->error("It's not allowed to create hole(s) in constant "
4563 value
->set_valuetype(Value::V_ERROR
);
4566 for (size_t i
= 0; i
< index_map
.size(); i
++)
4567 delete index_map
.get_nth_elem(i
);
4572 value
->error("%s value was expected", valuetypename
);
4573 value
->set_valuetype(Value::V_ERROR
);
4579 void Type::chk_this_value_Verdict(Value
*value
)
4581 Value
*v
= value
->get_value_refd_last();
4582 switch (v
->get_valuetype()) {
4583 case Value::V_VERDICT
:
4586 value
->error("verdict value was expected");
4587 value
->set_valuetype(Value::V_ERROR
);
4592 /** \todo enhance to handle activate */
4593 void Type::chk_this_value_Default(Value
*value
)
4595 switch (value
->get_valuetype()) {
4596 case Value::V_TTCN3_NULL
:
4597 value
->set_valuetype(Value::V_DEFAULT_NULL
);
4600 value
->error("default value was expected");
4601 value
->set_valuetype(Value::V_ERROR
);
4606 bool Type::chk_this_value_Array(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4607 namedbool incomplete_allowed
, namedbool implicit_omit
)
4609 bool self_ref
= false;
4610 switch (value
->get_valuetype()) {
4611 case Value::V_SEQOF
:
4612 value
->set_valuetype(Value::V_ARRAY
);
4614 case Value::V_ARRAY
: {
4615 size_t n_value_comps
= value
->get_nof_comps();
4616 Ttcn::ArrayDimension
*dim
= u
.array
.dimension
;
4617 if (!value
->is_indexed()) {
4618 // Value-list notation.
4619 if (!dim
->get_has_error()) {
4620 size_t array_size
= dim
->get_size();
4621 if (array_size
!= n_value_comps
)
4622 value
->error("Too %s elements in the array value: %lu was "
4623 "expected instead of %lu",
4624 array_size
> n_value_comps
? "few" : "many",
4625 (unsigned long)array_size
,
4626 (unsigned long)n_value_comps
);
4628 for (size_t i
= 0; i
< n_value_comps
; i
++) {
4629 Error_Context
cntxt(this, "In array element %lu",
4630 (unsigned long)(i
+ 1));
4631 Value
*v_comp
= value
->get_comp_byIndex(i
);
4632 v_comp
->set_my_governor(u
.array
.element_type
);
4633 if (v_comp
->get_valuetype() == Value::V_NOTUSED
) {
4634 if (!incomplete_allowed
)
4635 v_comp
->error("Not used symbol `-' is not allowed in this "
4638 u
.array
.element_type
->chk_this_value_ref(v_comp
);
4639 self_ref
|= u
.array
.element_type
->chk_this_value(v_comp
, lhs
,
4640 expected_value
, incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
,
4645 // Indexed-list notation.
4646 bool array_size_known
= !dim
->get_has_error();
4647 bool check_holes
= array_size_known
4648 && expected_value
== EXPECTED_CONSTANT
;
4649 size_t array_size
= 0;
4650 if (array_size_known
) array_size
= dim
->get_size();
4651 map
<Int
, Int
> index_map
;
4652 for (size_t i
= 0; i
< n_value_comps
; i
++) {
4653 Error_Context
cntxt(this, "In array element #%lu",
4654 (unsigned long)(i
+ 1));
4655 Value
*val
= value
->get_comp_byIndex(i
);
4656 Value
*index
= value
->get_index_byIndex(i
);
4657 dim
->chk_index(index
, expected_value
);
4658 if (index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
4659 const int_val_t
*index_int
= index
->get_value_refd_last()
4661 if (*index_int
> INT_MAX
) {
4662 index
->error("An integer value less than `%d' was expected for "
4663 "indexing type `%s' instead of `%s'", INT_MAX
,
4664 get_typename().c_str(),
4665 (index_int
->t_str()).c_str());
4666 index
->set_valuetype(Value::V_ERROR
);
4667 check_holes
= false;
4669 // Index overflows/underflows are already checked by
4670 // ArrayDimensions::chk_index() at this point. The only thing
4671 // we need to check is the uniqueness of constant index values.
4672 Int index_val
= index_int
->get_val();
4673 if (index_map
.has_key(index_val
)) {
4674 index
->error("Duplicate index value `%s' for components `%s' "
4675 "and `%s'", Int2string(index_val
).c_str(),
4676 Int2string((Int
)i
+ 1).c_str(),
4677 Int2string(*index_map
[index_val
]).c_str());
4678 index
->set_valuetype(Value::V_ERROR
);
4679 check_holes
= false;
4681 index_map
.add(index_val
, new Int((Int
)i
+ 1));
4685 check_holes
= false;
4687 val
->set_my_governor(u
.array
.element_type
);
4688 u
.array
.element_type
->chk_this_value_ref(val
);
4689 self_ref
|= u
.array
.element_type
->chk_this_value(val
, lhs
, expected_value
,
4690 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4693 if (index_map
.size() < array_size
) {
4694 // It's a constant array assigned with constant index values. The
4695 // # of constant index values doesn't reach the size of the array.
4696 value
->error("It's not allowed to create hole(s) in constant "
4698 value
->set_valuetype(Value::V_ERROR
);
4701 for (size_t i
= 0; i
< index_map
.size(); i
++)
4702 delete index_map
.get_nth_elem(i
);
4707 value
->error("array value was expected");
4708 value
->set_valuetype(Value::V_ERROR
);
4715 bool Type::chk_this_value_Signature(Value
*value
, Common::Assignment
*lhs
,
4716 expected_value_t expected_value
,
4717 namedbool incomplete_allowed
)
4719 bool self_ref
= false;
4720 switch(value
->get_valuetype()) {
4721 case Value::V_SEQOF
:
4722 value
->set_valuetype(Value::V_SEQ
);
4725 map
<string
, NamedValue
> comp_map
;
4726 // it is set to false if we have lost the ordering
4727 bool in_synch
= true;
4728 size_t n_type_comps
= get_nof_comps();
4729 size_t n_value_comps
= value
->get_nof_comps();
4730 // for incomplete values
4731 CompField
*last_cf
= 0;
4732 size_t next_index
= 0;
4733 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4734 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4735 const Identifier
& value_id
= nv
->get_name();
4736 const string
& value_name
= value_id
.get_name();
4737 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4738 if (!has_comp_withName(value_id
)) {
4739 nv
->error("Reference to non-existent parameter `%s' in signature value for "
4740 "type `%s'", value_dispname_str
, get_typename().c_str());
4743 } else if (comp_map
.has_key(value_name
)) {
4744 nv
->error("Duplicate signature parameter `%s'", value_dispname_str
);
4745 comp_map
[value_name
]->note("Parameter `%s' is already given here",
4746 value_dispname_str
);
4748 } else comp_map
.add(value_name
, nv
);
4749 CompField
*cf
= get_comp_byName(value_id
);
4750 // check the ordering of fields
4752 if (incomplete_allowed
) {
4754 for (size_t i
= next_index
; i
< n_type_comps
; i
++) {
4755 CompField
*cf2
= get_comp_byIndex(i
);
4756 if (value_name
== cf2
->get_name().get_name()) {
4764 nv
->error("Field `%s' cannot appear after parameter `%s' in signature "
4765 "value", value_dispname_str
,
4766 last_cf
->get_name().get_dispname().c_str());
4770 // the value must be complete
4771 CompField
*cf2
= get_comp_byIndex(v_i
);
4773 nv
->error("Unexpected field `%s' in record value, "
4774 "expecting `%s'", value_dispname_str
,
4775 cf2
->get_name().get_dispname().c_str());
4780 Type
*type
= cf
->get_type();
4781 Value
*comp_value
= nv
->get_value();
4782 comp_value
->set_my_governor(type
);
4783 Error_Context
cntxt(nv
, "In value for signature parameter `%s'",
4784 value_dispname_str
);
4785 type
->chk_this_value_ref(comp_value
);
4786 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4787 INCOMPLETE_NOT_ALLOWED
,
4788 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
);
4790 if (!incomplete_allowed
) {
4791 for (size_t i
= 0; i
< u
.signature
.parameters
->get_nof_in_params(); i
++) {
4792 const Identifier
& id
= get_comp_byIndex(i
)->get_name(); //u.signature.parameters->get_param_byIndex(n)
4793 if (!comp_map
.has_key(id
.get_name()) && SignatureParam::PARAM_OUT
!= u
.signature
.parameters
->get_in_param_byIndex(i
)->get_direction()) {
4794 value
->error("Field `%s' is missing from signature value",
4795 id
.get_dispname().c_str());
4802 value
->error("Signature value was expected for type `%s'",
4803 get_fullname().c_str());
4804 value
->set_valuetype(Value::V_ERROR
);
4811 /** \todo enhance to handle mtc, system, etc. */
4812 void Type::chk_this_value_Component(Value
*value
)
4814 switch (value
->get_valuetype()) {
4815 case Value::V_TTCN3_NULL
:
4816 value
->set_valuetype_COMP_NULL();
4819 if (value
->get_optype() == Value::OPTYPE_COMP_NULL
)
4820 break; // set_valuetype_COMP_NULL was called already
4823 value
->error("component reference value was expected");
4824 value
->set_valuetype(Value::V_ERROR
);
4829 void Type::chk_this_value_FAT(Value
*value
)
4831 switch (value
->get_valuetype()) {
4832 case Value::V_TTCN3_NULL
:
4833 value
->set_valuetype(Value::V_FAT_NULL
);
4835 case Value::V_REFER
:
4838 case Value::V_FUNCTION
:
4839 case Value::V_ALTSTEP
:
4840 case Value::V_TESTCASE
:
4841 case Value::V_FAT_NULL
:
4842 // This function (chk_this_value_FAT) might have transformed the value
4843 // from V_REFER or V_TTCN3_NULL to one of these. Return now,
4844 // otherwise spurious errors are generated.
4849 value
->error("Reference to a function or external function was "
4853 value
->error("Reference to an altstep was expected");
4856 value
->error("Reference to a testcase was expected");
4859 FATAL_ERROR("Type::chk_this_value_FAT()");
4861 value
->set_valuetype(Value::V_ERROR
);
4863 } // switch valuetype
4865 // Here value->valuetype is V_REFER
4866 Assignment
*t_ass
= value
->get_refered()->get_refd_assignment(false);
4868 value
->set_valuetype(Value::V_ERROR
);
4872 // check whether refers() points to the right definition
4873 Assignment::asstype_t t_asstype
= t_ass
->get_asstype();
4876 switch (t_asstype
) {
4877 case Assignment::A_FUNCTION
:
4878 case Assignment::A_FUNCTION_RVAL
:
4879 case Assignment::A_FUNCTION_RTEMP
:
4880 case Assignment::A_EXT_FUNCTION
:
4881 case Assignment::A_EXT_FUNCTION_RVAL
:
4882 case Assignment::A_EXT_FUNCTION_RTEMP
:
4883 value
->set_valuetype(Value::V_FUNCTION
, t_ass
);
4886 value
->error("Reference to a function or external function was "
4887 "expected instead of %s", t_ass
->get_description().c_str());
4888 value
->set_valuetype(Value::V_ERROR
);
4893 if (t_ass
->get_asstype() == Assignment::A_ALTSTEP
) {
4894 value
->set_valuetype(Value::V_ALTSTEP
, t_ass
);
4897 value
->error("Reference to an altstep was expected instead of %s",
4898 t_ass
->get_description().c_str());
4899 value
->set_valuetype(Value::V_ERROR
);
4903 if (t_ass
->get_asstype() == Assignment::A_TESTCASE
) {
4904 value
->set_valuetype(Value::V_TESTCASE
, t_ass
);
4907 value
->error("Reference to a testcase was expected instead of %s",
4908 t_ass
->get_description().c_str());
4909 value
->set_valuetype(Value::V_ERROR
);
4913 FATAL_ERROR("Type::chk_this_value_FAT()");
4915 // comparison of formal parameter lists
4917 Error_Context
cntxt(value
, "In comparing formal parameter lists of "
4918 "type `%s' and %s", get_typename().c_str(),
4919 t_ass
->get_description().c_str());
4920 u
.fatref
.fp_list
->chk_compatibility(t_ass
->get_FormalParList(),
4921 get_typename().c_str());
4923 // comparison of 'runs on' clauses
4924 Type
*t_runs_on_type
= t_ass
->get_RunsOnType();
4925 if (t_runs_on_type
) {
4926 if (u
.fatref
.runs_on
.self
) {
4927 if (u
.fatref
.runs_on
.ref
) {
4928 FATAL_ERROR("Type::chk_this_value_FAT()");
4929 } else { // "runs on self" case
4930 // check against the runs on component type of the scope of the value
4931 Scope
* value_scope
= value
->get_my_scope();
4932 if (!value_scope
) FATAL_ERROR("Type::chk_this_value_FAT()");
4933 Ttcn::RunsOnScope
*t_ros
= value_scope
->get_scope_runs_on();
4935 Type
*scope_comptype
= t_ros
->get_component_type();
4936 if (!t_runs_on_type
->is_compatible(scope_comptype
, NULL
)) {
4937 value
->error("Runs on clause mismatch: type `%s' has a "
4938 "'runs on self' clause and the current scope expects component "
4939 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4940 scope_comptype
->get_typename().c_str(),
4941 t_ass
->get_description().c_str(),
4942 t_runs_on_type
->get_typename().c_str());
4944 } else { // does not have 'runs on' clause
4945 // if the value's scope is a component body then check the runs on
4946 // compatibility using this component type as the scope
4947 ComponentTypeBody
* ct_body
=
4948 dynamic_cast<ComponentTypeBody
*>(value_scope
);
4950 if (!t_runs_on_type
->is_compatible(ct_body
->get_my_type(), NULL
)) {
4951 value
->error("Runs on clause mismatch: type `%s' has a "
4952 "'runs on self' clause and the current component definition "
4953 "is of type `%s', but %s runs on `%s'",
4954 get_typename().c_str(),
4955 ct_body
->get_my_type()->get_typename().c_str(),
4956 t_ass
->get_description().c_str(),
4957 t_runs_on_type
->get_typename().c_str());
4960 value
->error("Type `%s' has a 'runs on self' clause and the "
4961 "current scope does not have a 'runs on' clause, "
4962 "but %s runs on `%s'", get_typename().c_str(),
4963 t_ass
->get_description().c_str(),
4964 t_runs_on_type
->get_typename().c_str());
4969 if (u
.fatref
.runs_on
.ref
) {
4970 if (u
.fatref
.runs_on
.type
&&
4971 !t_runs_on_type
->is_compatible(u
.fatref
.runs_on
.type
, NULL
)) {
4972 value
->error("Runs on clause mismatch: type `%s' expects component "
4973 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4974 u
.fatref
.runs_on
.type
->get_typename().c_str(),
4975 t_ass
->get_description().c_str(),
4976 t_runs_on_type
->get_typename().c_str());
4979 value
->error("Type `%s' does not have 'runs on' clause, but %s runs "
4980 "on `%s'", get_typename().c_str(), t_ass
->get_description().c_str(),
4981 t_runs_on_type
->get_typename().c_str());
4985 if (typetype
== T_TESTCASE
) {
4986 // comparison of system clauses
4987 Ttcn::Def_Testcase
*t_testcase
= dynamic_cast<Ttcn::Def_Testcase
*>(t_ass
);
4988 if (!t_testcase
) FATAL_ERROR("Type::chk_this_value_FAT()");
4989 Type
*t_system_type
= t_testcase
->get_SystemType();
4990 // if the system clause is missing we shall examine the component type
4991 // that is given in the 'runs on' clause
4992 if (!t_system_type
) t_system_type
= t_runs_on_type
;
4993 Type
*my_system_type
=
4994 u
.fatref
.system
.ref
? u
.fatref
.system
.type
: u
.fatref
.runs_on
.type
;
4995 if (t_system_type
&& my_system_type
&&
4996 !t_system_type
->is_compatible(my_system_type
, NULL
)) {
4997 value
->error("System clause mismatch: testcase type `%s' expects "
4998 "component type `%s', but %s has `%s'", get_typename().c_str(),
4999 my_system_type
->get_typename().c_str(),
5000 t_ass
->get_description().c_str(),
5001 t_system_type
->get_typename().c_str());
5003 } else if (typetype
== T_FUNCTION
) {
5004 // comparison of return types
5005 bool t_returns_template
= false;
5006 switch (t_asstype
) {
5007 case Assignment::A_FUNCTION
:
5008 case Assignment::A_EXT_FUNCTION
:
5009 if (u
.fatref
.return_type
) {
5010 value
->error("Type `%s' expects a function or external function "
5011 "that returns a %s of type `%s', but %s does not have return type",
5012 get_typename().c_str(),
5013 u
.fatref
.returns_template
? "template" : "value",
5014 u
.fatref
.return_type
->get_typename().c_str(),
5015 t_ass
->get_description().c_str());
5018 case Assignment::A_FUNCTION_RTEMP
:
5019 case Assignment::A_EXT_FUNCTION_RTEMP
: {
5020 // comparison of template restrictions
5021 Ttcn::Def_Function_Base
* dfb
=
5022 dynamic_cast<Ttcn::Def_Function_Base
*>(t_ass
);
5023 if (!dfb
) FATAL_ERROR("Type::chk_this_value_FAT()");
5024 template_restriction_t refd_tr
= dfb
->get_template_restriction();
5025 if (refd_tr
!=u
.fatref
.template_restriction
) {
5026 value
->error("Type `%s' expects a function or external function "
5027 "that returns a template with %s restriction, "
5028 "but %s returns a template with %s restriction",
5029 get_typename().c_str(),
5030 u
.fatref
.template_restriction
==TR_NONE
? "no" :
5031 Template::get_restriction_name(u
.fatref
.template_restriction
),
5032 t_ass
->get_description().c_str(),
5033 refd_tr
==TR_NONE
? "no" : Template::get_restriction_name(refd_tr
));
5036 t_returns_template
= true;
5038 case Assignment::A_FUNCTION_RVAL
:
5039 case Assignment::A_EXT_FUNCTION_RVAL
:
5040 if (u
.fatref
.return_type
) {
5041 Type
*t_return_type
= t_ass
->get_Type();
5042 if (!u
.fatref
.return_type
->is_identical(t_return_type
)) {
5043 value
->error("Return type mismatch: type `%s' expects a function "
5044 "or external function that returns a %s of type `%s', but %s "
5045 "returns a %s of type `%s'", get_typename().c_str(),
5046 u
.fatref
.returns_template
? "template" : "value",
5047 u
.fatref
.return_type
->get_typename().c_str(),
5048 t_ass
->get_description().c_str(),
5049 t_returns_template
? "template" : "value",
5050 t_return_type
->get_typename().c_str());
5051 } else if (u
.fatref
.return_type
->get_sub_type() && t_return_type
->get_sub_type() &&
5052 (u
.fatref
.return_type
->get_sub_type()->get_subtypetype()==t_return_type
->get_sub_type()->get_subtypetype()) &&
5053 (!u
.fatref
.return_type
->get_sub_type()->is_compatible(t_return_type
->get_sub_type()))) {
5054 // TODO: maybe equivalence should be checked, or maybe that is too strict
5055 value
->error("Return type subtype mismatch: subtype %s has no common value with subtype %s",
5056 u
.fatref
.return_type
->get_sub_type()->to_string().c_str(),
5057 t_return_type
->get_sub_type()->to_string().c_str());
5058 } else if (u
.fatref
.returns_template
!= t_returns_template
) {
5059 value
->error("Type `%s' expects a function or external function "
5060 "that returns a %s of type `%s', but %s returns a %s",
5061 get_typename().c_str(),
5062 u
.fatref
.returns_template
? "template" : "value",
5063 u
.fatref
.return_type
->get_typename().c_str(),
5064 t_ass
->get_description().c_str(),
5065 t_returns_template
? "template" : "value");
5068 value
->error("Type `%s' expects a function or external function "
5069 "without return type, but %s returns a %s of type `%s'",
5070 get_typename().c_str(), t_ass
->get_description().c_str(),
5071 t_returns_template
? "template" : "value",
5072 t_ass
->get_Type()->get_typename().c_str());
5076 FATAL_ERROR("Type::chk_this_value_FAT()");
5081 void Type::chk_this_template_length_restriction(Template
*t
)
5083 Ttcn::LengthRestriction
*lr
= t
->get_length_restriction();
5084 if (!lr
) FATAL_ERROR("Type::chk_this_template_length_restriction()");
5085 // first check the length restriction itself
5086 lr
->chk(EXPECTED_DYNAMIC_VALUE
);
5088 /** \todo check lr against the length subtype constraint of this */
5089 get_type_refd()->chk_this_template_length_restriction(t
);
5092 typetype_t tt
= get_typetype_ttcn3(typetype
);
5096 // return silently, the type of the template is erroneous anyway
5099 lr
->chk_array_size(u
.array
.dimension
);
5108 // length restriction is allowed for these types
5111 lr
->error("Length restriction cannot be used in a template of type `%s'",
5112 get_typename().c_str());
5115 // check whether the number of elements in t is in accordance with lr
5116 Template
*t_last
= t
->get_template_refd_last();
5117 switch (t_last
->get_templatetype()) {
5118 case Ttcn::Template::OMIT_VALUE
:
5119 lr
->error("Length restriction cannot be used with omit value");
5121 case Ttcn::Template::SPECIFIC_VALUE
: {
5122 Value
*v_last
= t_last
->get_specific_value()->get_value_refd_last();
5123 switch (v_last
->get_valuetype()) {
5126 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5130 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5134 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5137 if (tt
== T_CSTR
|| tt
== T_USTR
)
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");
5144 case Value::V_SEQOF
:
5146 lr
->chk_nof_elements(v_last
->get_nof_comps(), false, *t
, "value");
5148 case Value::V_SETOF
:
5150 lr
->chk_nof_elements(v_last
->get_nof_comps(), false, *t
, "value");
5152 // note: do not check array values
5153 // they are already verified against the array size
5155 lr
->error("Length restriction cannot be used with omit value");
5157 // we cannot verify anything on other value types
5158 // they are either correct or not applicable to the type
5162 case Ttcn::Template::TEMPLATE_LIST
:
5163 if (tt
== T_SEQOF
|| tt
== T_SETOF
)
5164 lr
->chk_nof_elements(t_last
->get_nof_comps_not_anyornone(),
5165 t_last
->temps_contains_anyornone_symbol(), *t
, "template");
5166 // note: do not check array templates
5167 // they are already verified against the array size
5169 case Ttcn::Template::SUPERSET_MATCH
:
5171 lr
->chk_nof_elements(t_last
->get_nof_comps_not_anyornone(), true,
5174 case Ttcn::Template::BSTR_PATTERN
:
5176 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5177 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5179 case Ttcn::Template::HSTR_PATTERN
:
5181 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5182 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5184 case Ttcn::Template::OSTR_PATTERN
:
5186 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5187 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5189 case Ttcn::Template::CSTR_PATTERN
:
5190 if (tt
== T_CSTR
|| tt
== T_USTR
)
5191 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5192 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5195 // We cannot verify anything on other matching mechanisms.
5196 // They are either correct or not applicable to the type.
5201 void Type::chk_this_template_ref(Template
*t
)
5203 switch (t
->get_templatetype()) {
5204 case Ttcn::Template::SPECIFIC_VALUE
: {
5205 // if (t->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE) return;
5206 Value
*v
= t
->get_specific_value();
5207 chk_this_value_ref(v
);
5208 switch (v
->get_valuetype()) {
5209 case Value::V_REFD
: {
5210 // Do not check the actual parameter list of the reference yet to avoid
5211 // endless recursion in case of embedded circular references.
5212 // The parameter lists will be verified later.
5213 Assignment
*ass
= v
->get_reference()->get_refd_assignment(false);
5215 switch (ass
->get_asstype()) {
5216 case Assignment::A_VAR_TEMPLATE
: {
5217 Type
* type
= ass
->get_Type();
5218 switch (type
->typetype
) {
5226 case T_NUMERICSTRING
:
5227 case T_PRINTABLESTRING
:
5228 case T_TELETEXSTRING
:
5229 case T_VIDEOTEXSTRING
:
5231 case T_GRAPHICSTRING
:
5232 case T_VISIBLESTRING
:
5233 case T_GENERALSTRING
:
5234 case T_UNIVERSALSTRING
:
5237 case T_GENERALIZEDTIME
:
5238 case T_OBJECTDESCRIPTOR
: {
5239 // TR 921 (indexing of template strings)
5240 Ttcn::FieldOrArrayRefs
*subrefs
= v
->get_reference()
5242 if (!subrefs
) break;
5243 size_t nof_subrefs
= subrefs
->get_nof_refs();
5244 if (nof_subrefs
> 0) {
5245 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
5246 ->get_ref(nof_subrefs
- 1);
5247 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
5248 t
->error("Reference to %s can not be indexed",
5249 (ass
->get_description()).c_str());
5250 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5259 case Assignment::A_MODULEPAR_TEMP
:
5260 case Assignment::A_TEMPLATE
:
5261 case Assignment::A_PAR_TEMPL_IN
:
5262 case Assignment::A_PAR_TEMPL_OUT
:
5263 case Assignment::A_PAR_TEMPL_INOUT
:
5264 case Assignment::A_FUNCTION_RTEMP
:
5265 case Assignment::A_EXT_FUNCTION_RTEMP
:
5266 t
->set_templatetype(Ttcn::Template::TEMPLATE_REFD
);
5270 } else t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5272 case Value::V_INVOKE
: {
5273 Type
*t2
= v
->get_invoked_type(Type::EXPECTED_TEMPLATE
);
5274 if(t2
&& t2
->get_type_refd_last()->get_returns_template())
5275 t
->set_templatetype(Ttcn::Template::TEMPLATE_INVOKE
);
5282 case Ttcn::Template::TEMPLATE_REFD
: {
5283 // Do not check the actual parameter list of the reference yet to avoid
5284 // endless recursion in case of embedded circular references.
5285 // The parameter lists will be verified later.
5286 Assignment
*ass
= t
->get_reference()->get_refd_assignment(false);
5288 switch (ass
->get_asstype()) {
5289 case Assignment::A_VAR_TEMPLATE
: {
5290 Type
* type
= ass
->get_Type();
5291 switch (type
->typetype
) {
5299 case T_NUMERICSTRING
:
5300 case T_PRINTABLESTRING
:
5301 case T_TELETEXSTRING
:
5302 case T_VIDEOTEXSTRING
:
5304 case T_GRAPHICSTRING
:
5305 case T_VISIBLESTRING
:
5306 case T_GENERALSTRING
:
5307 case T_UNIVERSALSTRING
:
5310 case T_GENERALIZEDTIME
:
5311 case T_OBJECTDESCRIPTOR
: {
5312 // TR 921 (indexing of template strings)
5313 Ttcn::FieldOrArrayRefs
*subrefs
= t
->get_reference()
5315 if (!subrefs
) break;
5316 size_t nof_subrefs
= subrefs
->get_nof_refs();
5317 if (nof_subrefs
> 0) {
5318 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
5319 ->get_ref(nof_subrefs
- 1);
5320 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
5321 t
->error("Reference to %s can not be indexed",
5322 (ass
->get_description()).c_str());
5323 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5332 case Assignment::A_MODULEPAR_TEMP
:
5333 case Assignment::A_TEMPLATE
:
5334 case Assignment::A_PAR_TEMPL_IN
:
5335 case Assignment::A_PAR_TEMPL_OUT
:
5336 case Assignment::A_PAR_TEMPL_INOUT
:
5337 case Assignment::A_FUNCTION_RTEMP
:
5338 case Assignment::A_EXT_FUNCTION_RTEMP
:
5339 t
->set_templatetype(Ttcn::Template::TEMPLATE_REFD
);
5343 } else t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5351 bool Type::chk_this_template_ref_pard(Ttcn::Ref_pard
* ref_pard
, Common::Assignment
* lhs
)
5353 // Check if the reference on the left hand side of the assignment can be found
5354 // among the parameters
5355 Ttcn::ActualParList
* par_list
= ref_pard
->get_parlist();
5357 size_t nof_pars
= par_list
->get_nof_pars();
5358 for (size_t i
= 0; i
< nof_pars
; ++i
) {
5359 Ttcn::ActualPar
* par
= par_list
->get_par(i
);
5360 Ttcn::Ref_base
* par_ref
= 0;
5361 switch(par
->get_selection()) {
5362 case Ttcn::ActualPar::AP_TEMPLATE
: {
5363 Ttcn::TemplateInstance
* temp_ins
= par
->get_TemplateInstance();
5364 Ttcn::Template
* temp
= temp_ins
->get_Template();
5365 if (temp
->get_templatetype() == Ttcn::Template::TEMPLATE_REFD
) {
5366 par_ref
= temp
->get_reference();
5370 case Ttcn::ActualPar::AP_REF
: {
5371 par_ref
= par
->get_Ref();
5379 Common::Assignment
* ass
= par_ref
->get_refd_assignment(true); // also check parameters if there are any
5383 // In case a parameter is another function call / parametrised template
5384 // check their parameters as well
5385 if (ass
->get_asstype() == Assignment::A_FUNCTION_RTEMP
||
5386 ass
->get_asstype() == Assignment::A_EXT_FUNCTION_RTEMP
||
5387 ass
->get_asstype() == Assignment::A_TEMPLATE
) {
5388 ref_pard
= dynamic_cast<Ttcn::Ref_pard
*>(par_ref
);
5389 if (ref_pard
&& chk_this_template_ref_pard(ref_pard
, lhs
))
5398 bool Type::chk_this_template_generic(Template
*t
, namedbool incomplete_allowed
,
5399 namedbool allow_omit
, namedbool allow_any_or_omit
, namedbool sub_chk
,
5400 namedbool implicit_omit
, Common::Assignment
*lhs
)
5402 bool self_ref
= false;
5403 if (!allow_omit
&& t
->get_template_refd_last()->get_templatetype() ==
5404 Ttcn::Template::OMIT_VALUE
) {
5405 t
->error("`omit' value is not allowed in this context");
5407 if (!allow_any_or_omit
&& t
->get_template_refd_last()->get_templatetype() ==
5408 Ttcn::Template::ANY_OR_OMIT
) {
5409 t
->warning("Using `*' for mandatory field");
5412 Ttcn::Template::templatetype_t temptype
= t
->get_templatetype();
5414 case Ttcn::Template::TEMPLATE_ERROR
:
5416 case Ttcn::Template::TEMPLATE_NOTUSED
:
5417 case Ttcn::Template::OMIT_VALUE
:
5418 case Ttcn::Template::ANY_VALUE
:
5419 case Ttcn::Template::ANY_OR_OMIT
: {
5420 Type
*type
=get_type_refd_last();
5421 if (type
->get_typetype() == T_SIGNATURE
)
5422 t
->error("Generic wildcard `%s' cannot be used for signature `%s'",
5423 t
->get_templatetype_str(), type
->get_fullname().c_str());
5425 case Ttcn::Template::VALUE_LIST_ALL_FROM
:
5426 case Ttcn::Template::ALL_FROM
: {
5427 Ttcn::Template
*af
= t
->get_all_from();
5428 switch (af
->get_templatetype()) {
5429 case Ttcn::Template::SPECIFIC_VALUE
: {
5430 Value
*v
= af
->get_specific_value();
5431 v
->set_lowerid_to_ref();
5432 Reference
*ref
= v
->get_reference();
5433 Assignment
*ass
= ref
->get_refd_assignment(true); // also check parameters if there are any
5434 if (!ass
) break; // probably erroneous
5435 //warning("asstype %d", ass->get_asstype());
5437 switch (ass
->get_asstype()) {
5438 case Assignment::A_VAR
:
5439 case Assignment::A_PAR_VAL_IN
:
5440 case Assignment::A_PAR_VAL_INOUT
:
5441 case Assignment::A_MODULEPAR
:
5442 case Assignment::A_CONST
:
5443 case Assignment::A_MODULEPAR_TEMP
:
5444 break; // acceptable
5445 case Assignment::A_VAR_TEMPLATE
:
5446 case Assignment::A_PAR_TEMPL_IN
:
5447 case Assignment::A_PAR_TEMPL_INOUT
:
5450 break; // acceptable
5451 case Assignment::A_FUNCTION_RVAL
:
5452 case Assignment::A_EXT_FUNCTION_RVAL
:
5453 case Assignment::A_FUNCTION_RTEMP
:
5454 case Assignment::A_EXT_FUNCTION_RTEMP
:
5455 case Assignment::A_TEMPLATE
: {
5456 Ttcn::Ref_pard
* ref_pard
= dynamic_cast<Ttcn::Ref_pard
*>(ref
);
5458 self_ref
|= chk_this_template_ref_pard(ref_pard
, lhs
);
5459 break; // acceptable
5462 error("A %s cannot be used as the target of `all from'",
5463 ass
->get_assname());
5466 //self_ref |= chk_this_value(v, lhs, EXPECTED_TEMPLATE, incomplete_allowed,
5467 // allow_omit, sub_chk, implicit_omit, NOT_STR_ELEM /* ?? */);
5471 error("The target of an 'all from' must be a specific value template, not a %s",
5472 af
->get_templatetype_str());
5477 case Ttcn::Template::VALUE_LIST
:
5478 case Ttcn::Template::COMPLEMENTED_LIST
: {
5479 size_t nof_comps
= t
->get_nof_comps();
5480 for (size_t i
= 0; i
< nof_comps
; i
++) {
5481 Template
* t_comp
= t
->get_temp_byIndex(i
);
5482 Error_Context
cntxt(t
, "In list item %lu", (unsigned long) (i
+ 1));
5483 t_comp
->set_my_governor(this);
5484 chk_this_template_ref(t_comp
);
5485 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
5486 omit_in_value_list
? allow_omit
: OMIT_NOT_ALLOWED
,
5487 ANY_OR_OMIT_ALLOWED
, sub_chk
, implicit_omit
, lhs
);
5488 if(temptype
==Ttcn::Template::COMPLEMENTED_LIST
&&
5489 t_comp
->get_template_refd_last()->get_templatetype() ==
5490 Ttcn::Template::ANY_OR_OMIT
)
5491 t_comp
->warning("`*' in complemented list."
5492 " This template will not match anything");
5495 case Ttcn::Template::SPECIFIC_VALUE
: {
5496 Value
*v
= t
->get_specific_value();
5497 v
->set_my_governor(this);
5498 self_ref
|= chk_this_value(v
, lhs
, EXPECTED_TEMPLATE
, incomplete_allowed
,
5499 allow_omit
, SUB_CHK
);
5501 case Ttcn::Template::TEMPLATE_INVOKE
: {
5503 Type
*governor
= t
->get_expr_governor(EXPECTED_DYNAMIC_VALUE
);
5505 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5506 else if (!is_compatible(governor
, NULL
)) {
5507 t
->error("Type mismatch: a value or template of type `%s' was "
5508 "expected instead of `%s'", get_typename().c_str(),
5509 governor
->get_typename().c_str());
5510 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5513 case Ttcn::Template::TEMPLATE_REFD
:
5514 self_ref
= chk_this_refd_template(t
, lhs
);
5517 self_ref
= chk_this_template(t
, incomplete_allowed
, sub_chk
, implicit_omit
, lhs
);
5520 if (t
->get_length_restriction()) chk_this_template_length_restriction(t
);
5521 if (!allow_omit
&& t
->get_ifpresent())
5522 t
->error("`ifpresent' is not allowed here");
5523 if(sub_chk
&& temptype
!= Ttcn::Template::PERMUTATION_MATCH
) {
5524 /* Note: A "permuation" itself has no type - it is just a fragment. */
5525 if(sub_type
!=NULL
) sub_type
->chk_this_template_generic(t
);
5531 bool Type::chk_this_refd_template(Template
*t
, Common::Assignment
*lhs
)
5533 if (t
->get_templatetype() != Template::TEMPLATE_REFD
) return false;
5534 Reference
*ref
= t
->get_reference();
5535 Assignment
*ass
= ref
->get_refd_assignment();
5536 if (!ass
) FATAL_ERROR("Type::chk_this_refd_template()");
5539 Type
*governor
= ass
->get_Type()
5540 ->get_field_type(ref
->get_subrefs(), EXPECTED_DYNAMIC_VALUE
);
5542 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5544 TypeCompatInfo
info(t
->get_my_scope()->get_scope_mod(), this, governor
,
5546 if (ref
->get_subrefs()) info
.set_str2_elem(ref
->get_subrefs()->refers_to_string_element());
5549 if (!is_compatible(governor
, &info
, &l_chain
, &r_chain
)) {
5550 Type
*type
= get_type_refd_last();
5551 switch (type
->typetype
) {
5553 // Port templates do not exist, remain silent.
5556 t
->error("Type mismatch: a signature template of type `%s' was "
5557 "expected instead of `%s'", get_typename().c_str(),
5558 governor
->get_typename().c_str());
5561 if (info
.is_subtype_error()) {
5562 t
->error("%s", info
.get_subtype_error().c_str());
5563 } else if (!info
.is_erroneous()) {
5564 t
->error("Type mismatch: a value or template of type `%s' was "
5565 "expected instead of `%s'", get_typename().c_str(),
5566 governor
->get_typename().c_str());
5568 t
->error("%s", info
.get_error_str_str().c_str());
5572 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5574 // Detect circular references.
5575 t
->get_template_refd_last();
5577 if (info
.needs_conversion()) t
->set_needs_conversion();
5580 return (lhs
== ass
);
5583 bool Type::chk_this_template(Template
*t
, namedbool is_modified
, namedbool
,
5584 namedbool implicit_omit
, Common::Assignment
*lhs
)
5586 bool self_ref
= false;
5587 Type
*t_last
= get_type_refd_last();
5588 t
->set_my_governor(t_last
);
5590 switch(t_last
->typetype
) {
5601 t_last
->chk_this_template_builtin(t
);
5610 case T_NUMERICSTRING
:
5611 case T_PRINTABLESTRING
:
5612 case T_TELETEXSTRING
:
5613 case T_VIDEOTEXSTRING
:
5615 case T_GRAPHICSTRING
:
5616 case T_VISIBLESTRING
:
5617 case T_GENERALSTRING
:
5618 case T_UNIVERSALSTRING
:
5621 case T_GENERALIZEDTIME
:
5622 case T_OBJECTDESCRIPTOR
:
5623 t_last
->chk_this_template_Str(t
);
5628 t_last
->chk_this_template_Int_Real(t
);
5632 t_last
->chk_this_template_Enum(t
);
5638 self_ref
= t_last
->chk_this_template_Choice(t
, is_modified
, implicit_omit
, lhs
);
5642 self_ref
= t_last
->chk_this_template_Seq(t
, is_modified
, implicit_omit
, lhs
);
5646 self_ref
= t_last
->chk_this_template_Set(t
, is_modified
, implicit_omit
, lhs
);
5649 self_ref
= t_last
->chk_this_template_SeqOf(t
, is_modified
, implicit_omit
, lhs
);
5652 self_ref
= t_last
->chk_this_template_SetOf(t
, is_modified
, implicit_omit
, lhs
);
5655 self_ref
= t_last
->chk_this_template_array(t
, is_modified
, implicit_omit
, lhs
);
5658 t
->error("Template cannot be defined for port type `%s'",
5659 get_fullname().c_str());
5662 t_last
->chk_this_template_Signature(t
, is_modified
);
5667 t_last
->chk_this_template_Fat(t
);
5670 FATAL_ERROR("Type::chk_this_template()");
5675 void Type::chk_this_template_Str(Template
*t
)
5677 typetype_t tt
= get_typetype_ttcn3(typetype
);
5678 bool report_error
= false;
5679 switch (t
->get_templatetype()) {
5680 case Ttcn::Template::VALUE_RANGE
:
5681 if (tt
== T_CSTR
|| tt
== T_USTR
) {
5682 Error_Context
cntxt(t
, "In value range");
5683 Ttcn::ValueRange
*vr
= t
->get_value_range();
5684 Value
*v_lower
= chk_range_boundary(vr
->get_min_v(), "lower", *t
);
5685 Value
*v_upper
= chk_range_boundary(vr
->get_max_v(), "upper", *t
);
5686 if (v_lower
&& v_upper
) {
5687 // both boundaries are available and have correct type
5689 if (v_lower
->get_val_str() > v_upper
->get_val_str())
5690 t
->error("The lower boundary has higher character code than the "
5693 if (v_lower
->get_val_ustr() > v_upper
->get_val_ustr())
5694 t
->error("The lower boundary has higher character code than the "
5698 } else report_error
= true;
5700 case Ttcn::Template::BSTR_PATTERN
:
5701 if (tt
!= T_BSTR
) report_error
= true;
5703 case Ttcn::Template::HSTR_PATTERN
:
5704 if (tt
!= T_HSTR
) report_error
= true;
5706 case Ttcn::Template::OSTR_PATTERN
:
5707 if (tt
!= T_OSTR
) report_error
= true;
5709 case Ttcn::Template::CSTR_PATTERN
:
5711 Ttcn::PatternString
*pstr
= t
->get_cstr_pattern();
5712 Error_Context
cntxt(t
, "In character string pattern");
5714 pstr
->join_strings();
5715 if (!pstr
->has_refs()) pstr
->chk_pattern();
5717 } else if (tt
== T_USTR
) {
5718 t
->set_templatetype(Template::USTR_PATTERN
);
5719 t
->get_ustr_pattern()
5720 ->set_pattern_type(Ttcn::PatternString::USTR_PATTERN
);
5723 report_error
= true;
5727 case Ttcn::Template::USTR_PATTERN
:
5729 Ttcn::PatternString
*pstr
= t
->get_ustr_pattern();
5730 Error_Context
cntxt(t
, "In universal string pattern");
5732 pstr
->join_strings();
5733 if (!pstr
->has_refs()) pstr
->chk_pattern();
5734 } else report_error
= true;
5737 report_error
= true;
5741 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5742 get_typename().c_str());
5746 void Type::chk_range_boundary_infinity(Value
*v
, bool is_upper
)
5749 v
->set_my_governor(this);
5751 Error_Context
cntxt2(v
, "In %s boundary", is_upper
? "upper" : "lower");
5752 chk_this_value_ref(v
);
5753 Value
*v_last
= v
->get_value_refd_last(0, EXPECTED_STATIC_VALUE
);
5754 if (v_last
->get_valuetype() == Value::V_OMIT
) {
5755 v
->error("`omit' value is not allowed in this context");
5756 v
->set_valuetype(Value::V_ERROR
);
5759 if (sub_type
!= NULL
) {
5761 if (!sub_type
->get_root()->is_upper_limit_infinity()) {
5762 v
->error("Infinity is not a valid value for type '%s' which has subtype %s",
5763 asString(), sub_type
->to_string().c_str());
5767 if (!sub_type
->get_root()->is_lower_limit_infinity()) {
5768 v
->error("Infinity is not a valid value for type '%s' which has subtype %s",
5769 asString(), sub_type
->to_string().c_str());
5777 Value
*Type::chk_range_boundary(Value
*v
, const char *which
,
5778 const Location
& loc
)
5780 typetype_t tt
= get_typetype_ttcn3(typetype
);
5783 v
->set_my_governor(this);
5785 Error_Context
cntxt2(v
, "In %s boundary", which
);
5786 chk_this_value_ref(v
);
5787 chk_this_value(v
, 0, EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
,
5788 OMIT_NOT_ALLOWED
, SUB_CHK
);
5790 ret_val
= v
->get_value_refd_last();
5791 switch (ret_val
->get_valuetype()) {
5793 if (tt
!= T_INT
) ret_val
= 0;
5796 if (tt
!= T_REAL
) ret_val
= 0;
5799 if (tt
!= T_CSTR
) ret_val
= 0;
5802 if (tt
!= T_USTR
) ret_val
= 0;
5805 // unfoldable or erroneous
5809 if ((tt
== T_CSTR
|| tt
== T_USTR
) && ret_val
&&
5810 ret_val
->get_val_strlen() != 1) {
5811 v
->error("The %s boundary must be a %scharstring value containing a "
5812 "single character", which
, tt
== T_USTR
? "universal ": "");
5816 // the boundary is + or - infinity
5817 if (tt
== T_CSTR
|| tt
== T_USTR
) {
5818 loc
.error("The %s boundary must be a %scharstring value", which
,
5819 tt
== T_USTR
? "universal ": "");
5826 void Type::chk_this_template_builtin(Template
*t
)
5828 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5829 get_typename().c_str());
5830 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5831 "allowed for type `%s'", get_typename().c_str());
5834 void Type::chk_this_template_Int_Real(Template
*t
)
5836 switch (t
->get_templatetype()) {
5837 case Ttcn::Template::VALUE_RANGE
: {
5838 Error_Context
cntxt(t
, "In value range");
5839 Ttcn::ValueRange
*vr
= t
->get_value_range();
5840 Value
*v_lower
= chk_range_boundary(vr
->get_min_v(), "lower", *t
);
5841 Value
*v_upper
= chk_range_boundary(vr
->get_max_v(), "upper", *t
);
5842 if (v_lower
&& v_upper
) {
5843 // both boundaries are available and have correct type
5844 switch (get_typetype_ttcn3(typetype
)) {
5846 if (*v_lower
->get_val_Int() > *v_upper
->get_val_Int())
5847 t
->error("The lower boundary is higher than the upper boundary");
5850 if (v_lower
->get_val_Real() > v_upper
->get_val_Real())
5851 t
->error("The lower boundary is higher than the upper boundary");
5854 FATAL_ERROR("Type::chk_this_template_Int_Real()");
5857 if (v_lower
&& !vr
->get_max_v()) {
5858 chk_range_boundary_infinity(v_lower
, true);
5860 if (!vr
->get_min_v() && v_upper
) {
5861 chk_range_boundary_infinity(v_upper
, false);
5865 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5866 get_typename().c_str());
5869 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5870 "allowed for type `%s'", get_typename().c_str());
5873 void Type::chk_this_template_Enum(Template
*t
)
5875 t
->error("%s cannot be used for enumerated type `%s'",
5876 t
->get_templatetype_str(), get_typename().c_str());
5877 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5878 "allowed for enumerated type `%s'", get_typename().c_str());
5881 bool Type::chk_this_template_Choice(Template
*t
, namedbool is_modified
,
5882 namedbool implicit_omit
, Common::Assignment
*lhs
)
5884 bool self_ref
= false;
5885 switch (t
->get_templatetype()) {
5886 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5887 size_t nof_nts
= t
->get_nof_comps();
5888 if (nof_nts
!= 1) t
->error("A template for union type must contain "
5889 "exactly one selected field");
5890 // We check all named templates, even though it is an error
5891 // to have more than one here.
5892 for (size_t i
= 0; i
< nof_nts
; i
++) {
5893 Ttcn::NamedTemplate
*nt
= t
->get_namedtemp_byIndex(i
);
5894 if (typetype
== T_OPENTYPE
) {
5895 // allow the alternatives of open types as both lower and upper identifiers
5896 nt
->set_name_to_lowercase();
5898 const Identifier
& nt_name
= nt
->get_name();
5900 if (!has_comp_withName(nt_name
)) {
5901 nt
->error("Reference to non-existent field `%s' in union "
5902 "template for type `%s'", nt_name
.get_dispname().c_str(),
5903 get_fullname().c_str());
5904 nt
->note("%s", actual_fields(*this).c_str());
5908 Type
*field_type
= get_comp_byName(nt_name
)->get_type();
5909 Template
*nt_templ
= nt
->get_template();
5911 Error_Context
cntxt(nt_templ
, "In template for union field `%s'",
5912 nt_name
.get_dispname().c_str());
5914 nt_templ
->set_my_governor(field_type
);
5915 field_type
->chk_this_template_ref(nt_templ
);
5916 bool incompl_ok
= t
->get_completeness_condition_choice(is_modified
, nt_name
) ==
5917 Ttcn::Template::C_MAY_INCOMPLETE
;
5918 self_ref
|= field_type
->chk_this_template_generic(nt_templ
,
5919 (incompl_ok
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
5920 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
5924 t
->error("%s cannot be used for union type `%s'",
5925 t
->get_templatetype_str(), get_typename().c_str());
5928 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5929 "allowed for union type `%s'", get_typename().c_str());
5934 bool Type::chk_this_template_Seq(Template
*t
, namedbool is_modified
,
5935 namedbool implicit_omit
, Common::Assignment
*lhs
)
5937 bool self_ref
= false;
5938 size_t n_type_comps
= get_nof_comps();
5939 switch (t
->get_templatetype()) {
5940 case Ttcn::Template::TEMPLATE_LIST
:
5941 // conversion: value list -> assignment notation
5942 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
5944 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5945 map
<string
, Ttcn::NamedTemplate
> comp_map
;
5946 // it is set to false if we have lost the ordering
5947 bool in_synch
= true;
5948 size_t n_template_comps
= t
->get_nof_comps();
5949 // the two variables below are used for modified templates only
5950 CompField
*last_cf
= 0;
5951 size_t next_index
= 0;
5952 for (size_t i
= 0; i
< n_template_comps
; i
++) {
5953 Ttcn::NamedTemplate
*namedtemp
= t
->get_namedtemp_byIndex(i
);
5954 const Identifier
& temp_id
= namedtemp
->get_name();
5955 const string
& temp_name
= temp_id
.get_name();
5956 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
5957 if (!has_comp_withName(temp_id
)) {
5958 namedtemp
->error("Reference to non-existent field `%s' in record "
5959 "template for type `%s'", temp_dispname_str
,
5960 get_typename().c_str());
5961 namedtemp
->note("%s", actual_fields(*this).c_str());
5964 } else if (comp_map
.has_key(temp_name
)) {
5965 namedtemp
->error("Duplicate record field `%s' in template",
5967 comp_map
[temp_name
]->note("Field `%s' is already given here",
5970 } else comp_map
.add(temp_name
, namedtemp
);
5972 CompField
*cf
= get_comp_byName(temp_id
);
5975 // missing fields are allowed, but take care of ordering
5977 for (size_t j
= next_index
; j
< n_type_comps
; j
++) {
5978 CompField
*cf2
= get_comp_byIndex(j
);
5979 if (temp_name
== cf2
->get_name().get_name()) {
5987 namedtemp
->error("Field `%s' cannot appear after field `%s' in "
5988 "a template for record type `%s'", temp_dispname_str
,
5989 last_cf
->get_name().get_dispname().c_str(),
5990 get_fullname().c_str());
5994 // the template must be complete
5995 CompField
*cf2
= get_comp_byIndex(i
);
5997 if (!cf2
->get_is_optional() || !implicit_omit
) {
5998 namedtemp
->error("Unexpected field `%s' in record template, "
5999 "expecting `%s'", temp_dispname_str
,
6000 cf2
->get_name().get_dispname().c_str());
6006 Type
*type
= cf
->get_type();
6007 Template
*comp_t
= namedtemp
->get_template();
6008 Error_Context
cntxt(comp_t
, "In template for record field `%s'",
6010 comp_t
->set_my_governor(type
);
6011 type
->chk_this_template_ref(comp_t
);
6012 bool is_optional
= cf
->get_is_optional(); // || cf->has_default()
6013 self_ref
|= type
->chk_this_template_generic(comp_t
, is_modified
,
6014 (is_optional
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
),
6015 (is_optional
? ANY_OR_OMIT_ALLOWED
: ANY_OR_OMIT_NOT_ALLOWED
),
6016 SUB_CHK
, implicit_omit
, lhs
);
6018 if (!is_modified
|| implicit_omit
) {
6019 // check missing fields
6020 for (size_t i
= 0; i
< n_type_comps
; i
++) {
6021 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
6022 if (!comp_map
.has_key(id
.get_name())) {
6023 if (implicit_omit
&& get_comp_byIndex(i
)->get_is_optional()) {
6024 // do not overwrite base fields
6025 if (!t
->get_base_template())
6026 t
->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id
),
6027 new Template(Template::OMIT_VALUE
)));
6028 } else if (!is_modified
) {
6029 t
->error("Field `%s' is missing from template for record type `%s'",
6030 id
.get_dispname().c_str(), get_typename().c_str());
6038 t
->error("%s cannot be used for record type `%s'",
6039 t
->get_templatetype_str(), get_typename().c_str());
6042 if (t
->get_length_restriction()) t
->error("Length restriction is not "
6043 "allowed for record type `%s'", get_typename().c_str());
6047 bool Type::chk_this_template_Set(Template
*t
,
6048 namedbool is_modified
, namedbool implicit_omit
, Common::Assignment
*lhs
)
6050 bool self_ref
= false;
6051 size_t n_type_comps
= get_nof_comps();
6052 switch (t
->get_templatetype()) {
6053 case Ttcn::Template::TEMPLATE_LIST
:
6054 if (t
->get_nof_comps() > 0) {
6055 t
->error("Value list notation is not allowed for set type `%s'",
6056 get_fullname().c_str());
6058 } else if (n_type_comps
> 0) {
6059 t
->error("A non-empty set template was expected for type `%s'",
6060 get_fullname().c_str());
6063 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
6065 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
6066 map
<string
, Ttcn::NamedTemplate
> comp_map
;
6067 size_t n_template_comps
= t
->get_nof_comps();
6068 for (size_t i
= 0; i
< n_template_comps
; i
++) {
6069 Ttcn::NamedTemplate
*namedtemp
= t
->get_namedtemp_byIndex(i
);
6070 const Identifier
& temp_id
=namedtemp
->get_name();
6071 const string
& temp_name
= temp_id
.get_name();
6072 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
6073 if (!has_comp_withName(temp_id
)) {
6074 namedtemp
->error("Reference to non-existent field `%s' in a "
6075 "template for set type `%s'", temp_dispname_str
,
6076 get_typename().c_str());
6077 namedtemp
->note("%s", actual_fields(*this).c_str());
6079 } else if (comp_map
.has_key(temp_name
)) {
6080 namedtemp
->error("Duplicate set field `%s' in template",
6082 comp_map
[temp_name
]->note("Field `%s' is already given here",
6084 } else comp_map
.add(temp_name
, namedtemp
);
6085 CompField
*cf
= get_comp_byName(temp_id
);
6086 Type
*type
= cf
->get_type();
6087 Template
*comp_t
= namedtemp
->get_template();
6088 Error_Context
cntxt(comp_t
, "In template for set field `%s'",
6090 comp_t
->set_my_governor(type
);
6091 type
->chk_this_template_ref(comp_t
);
6092 bool is_optional
= cf
->get_is_optional();
6093 self_ref
|= type
->chk_this_template_generic(comp_t
,
6094 (is_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6095 (is_optional
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
),
6096 (is_optional
? ANY_OR_OMIT_ALLOWED
: ANY_OR_OMIT_NOT_ALLOWED
),
6097 SUB_CHK
, implicit_omit
, lhs
);
6099 if (!is_modified
|| implicit_omit
) {
6100 // check missing fields
6101 for (size_t i
= 0; i
< n_type_comps
; i
++) {
6102 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
6103 if (!comp_map
.has_key(id
.get_name())) {
6104 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
) {
6105 // do not overwrite base fields
6106 if (!t
->get_base_template())
6107 t
->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id
),
6108 new Template(Template::OMIT_VALUE
)));
6109 } else if (!is_modified
) {
6110 t
->error("Field `%s' is missing from template for set type `%s'",
6111 id
.get_dispname().c_str(), get_typename().c_str());
6119 t
->error("%s cannot be used for set type `%s'",
6120 t
->get_templatetype_str(), get_typename().c_str());
6123 if (t
->get_length_restriction()) t
->error("Length restriction is not "
6124 "allowed for set type `%s'", get_typename().c_str());
6128 bool Type::chk_this_template_SeqOf(Template
*t
, namedbool is_modified
,
6129 namedbool implicit_omit
, Common::Assignment
*lhs
)
6131 bool self_ref
= false;
6132 switch(t
->get_templatetype()) {
6133 case Ttcn::Template::OMIT_VALUE
:
6134 if(t
->get_length_restriction())
6135 t
->warning("Redundant usage of length restriction with `omit'");
6137 case Ttcn::Template::PERMUTATION_MATCH
: {
6138 size_t nof_comps
= t
->get_nof_comps();
6139 for (size_t i
= 0; i
< nof_comps
; i
++) {
6140 Template
*t_comp
= t
->get_temp_byIndex(i
);
6141 Error_Context
cntxt(t_comp
, "In element %lu of permutation",
6142 (unsigned long) (i
+ 1));
6143 t_comp
->set_my_governor(u
.seof
.ofType
);
6144 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6145 // the elements of permutation must be always complete
6146 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6147 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6148 NOT_IMPLICIT_OMIT
, lhs
);
6151 case Ttcn::Template::TEMPLATE_LIST
: {
6152 Ttcn::Template::completeness_t c
=
6153 t
->get_completeness_condition_seof(is_modified
);
6155 size_t nof_base_comps
;
6156 if (c
== Ttcn::Template::C_PARTIAL
) {
6157 t_base
= t
->get_base_template()->get_template_refd_last();
6158 // it is sure that t_base is a TEMPLATE_LIST
6159 nof_base_comps
= t_base
->get_nof_comps();
6164 size_t nof_comps
= t
->get_nof_comps();
6165 for(size_t i
= 0; i
< nof_comps
; i
++) {
6166 Template
*t_comp
= t
->get_temp_byIndex(i
);
6167 Error_Context
cntxt(t_comp
, "In component %lu", (unsigned long)(i
+1));
6168 t_comp
->set_my_governor(u
.seof
.ofType
);
6169 if (t_base
&& i
< nof_base_comps
)
6170 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6171 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6172 switch (t_comp
->get_templatetype()) {
6173 case Ttcn::Template::PERMUTATION_MATCH
:
6174 // the elements of permutation has to be checked by u.seof.ofType
6175 // the templates within the permutation always have to be complete
6176 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
6177 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6178 implicit_omit
, lhs
);
6180 case Ttcn::Template::TEMPLATE_NOTUSED
:
6181 if (c
== Ttcn::Template::C_MUST_COMPLETE
) {
6182 t_comp
->error("Not used symbol `-' is not allowed in this context");
6183 } else if (c
== Ttcn::Template::C_PARTIAL
&& i
>= nof_base_comps
) {
6184 t_comp
->error("Not used symbol `-' cannot be used here because "
6185 "there is no corresponding element in the base template");
6189 bool embedded_modified
= (c
== Ttcn::Template::C_MAY_INCOMPLETE
) ||
6190 (c
== Ttcn::Template::C_PARTIAL
&& i
< nof_base_comps
);
6191 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6192 (embedded_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6193 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6198 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6199 map
<Int
, Int
> index_map
;
6200 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6201 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6202 Value
*index_value
= (it
->get_index()).get_val();
6203 // The index value must be Type::EXPECTED_DYNAMIC_VALUE integer, but
6204 // it's not required to be known at compile time.
6205 index_value
->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
6206 Template
*it_comp
= it
->get_template();
6207 Error_Context
cntxt(it_comp
, "In component %lu",
6208 (unsigned long)(i
+ 1));
6209 if (index_value
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
6210 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6212 if (*index_int
> INT_MAX
) {
6213 index_value
->error("An integer value less than `%d' was expected "
6214 "for indexing type `%s' instead of `%s'", INT_MAX
,
6215 get_typename().c_str(), (index_int
->t_str()).c_str());
6216 index_value
->set_valuetype(Value::V_ERROR
);
6218 Int index
= index_int
->get_val();
6220 index_value
->error("A non-negative integer value was expected "
6221 "for indexing type `%s' instead of `%s'",
6222 get_typename().c_str(), Int2string(index
).c_str());
6223 index_value
->set_valuetype(Value::V_ERROR
);
6224 } else if (index_map
.has_key(index
)) {
6225 index_value
->error("Duplicate index value `%s' for components "
6226 "`%s' and `%s'", Int2string(index
).c_str(),
6227 Int2string((Int
)i
+ 1).c_str(),
6228 Int2string(*index_map
[index
]).c_str());
6229 index_value
->set_valuetype(Value::V_ERROR
);
6231 index_map
.add(index
, new Int((Int
)i
+ 1));
6235 it_comp
->set_my_governor(u
.seof
.ofType
);
6236 u
.seof
.ofType
->chk_this_template_ref(it_comp
);
6237 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(it_comp
,
6238 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6239 SUB_CHK
, implicit_omit
, lhs
);
6241 for (size_t i
= 0; i
< index_map
.size(); i
++)
6242 delete index_map
.get_nth_elem(i
);
6246 t
->error("%s cannot be used for `record of' type `%s'",
6247 t
->get_templatetype_str(), get_typename().c_str());
6253 bool Type::chk_this_template_SetOf(Template
*t
, namedbool is_modified
,
6254 namedbool implicit_omit
, Common::Assignment
*lhs
)
6256 bool self_ref
= false;
6257 Ttcn::Template::templatetype_t temptype
= t
->get_templatetype();
6259 case Ttcn::Template::OMIT_VALUE
:
6260 if(t
->get_length_restriction())
6261 t
->warning("Redundant usage of length restriction with `omit'");
6263 case Ttcn::Template::SUPERSET_MATCH
:
6264 case Ttcn::Template::SUBSET_MATCH
: {
6265 const char *settype
= temptype
== Ttcn::Template::SUPERSET_MATCH
?
6266 "superset" : "subset";
6267 size_t nof_comps
= t
->get_nof_comps();
6268 for (size_t i
= 0; i
< nof_comps
; i
++) {
6269 Template
*t_comp
= t
->get_temp_byIndex(i
);
6270 Error_Context
cntxt(t_comp
, "In element %lu of %s",
6271 (unsigned long) (i
+ 1), settype
);
6272 t_comp
->set_my_governor(u
.seof
.ofType
);
6273 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6274 // the elements of sets must be always complete
6275 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6276 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6277 SUB_CHK
, implicit_omit
, lhs
);
6278 if (t_comp
->get_template_refd_last()->get_templatetype() ==
6279 Ttcn::Template::ANY_OR_OMIT
) {
6280 if (temptype
== Ttcn::Template::SUPERSET_MATCH
)
6281 t_comp
->warning("`*' in superset has no effect during matching");
6282 else t_comp
->warning("`*' in subset. This template will match "
6287 case Ttcn::Template::TEMPLATE_LIST
: {
6288 Ttcn::Template::completeness_t c
=
6289 t
->get_completeness_condition_seof(is_modified
);
6291 size_t nof_base_comps
;
6292 if (c
== Ttcn::Template::C_PARTIAL
) {
6293 t_base
= t
->get_base_template()->get_template_refd_last();
6294 // it is sure that t_base is a TEMPLATE_LIST
6295 nof_base_comps
= t_base
->get_nof_comps();
6300 size_t nof_comps
= t
->get_nof_comps();
6301 for(size_t i
= 0; i
< nof_comps
; i
++) {
6302 Template
*t_comp
= t
->get_temp_byIndex(i
);
6303 Error_Context
cntxt(t_comp
, "In component %lu", (unsigned long)(i
+1));
6304 t_comp
->set_my_governor(u
.seof
.ofType
);
6305 if (t_base
&& i
< nof_base_comps
)
6306 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6307 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6308 switch (t_comp
->get_templatetype()) {
6309 case Ttcn::Template::PERMUTATION_MATCH
:
6310 t_comp
->error("%s cannot be used for `set of' type `%s'",
6311 t_comp
->get_templatetype_str(), get_typename().c_str());
6313 case Ttcn::Template::TEMPLATE_NOTUSED
:
6314 if (c
== Ttcn::Template::C_MUST_COMPLETE
) {
6315 t_comp
->error("Not used symbol `-' is not allowed in this context");
6316 } else if (c
== Ttcn::Template::C_PARTIAL
&& i
>= nof_base_comps
) {
6317 t_comp
->error("Not used symbol `-' cannot be used here because "
6318 "there is no corresponding element in the base template");
6322 bool embedded_modified
= (c
== Ttcn::Template::C_MAY_INCOMPLETE
) ||
6323 (c
== Ttcn::Template::C_PARTIAL
&& i
< nof_base_comps
);
6324 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6325 (embedded_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6326 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6331 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6332 map
<Int
, Int
> index_map
;
6333 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6334 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6335 Value
*index_value
= (it
->get_index()).get_val();
6336 index_value
->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
6337 Template
*it_comp
= it
->get_template();
6338 Error_Context
cntxt(it_comp
, "In component %lu",
6339 (unsigned long)(i
+ 1));
6340 if (index_value
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
6341 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6343 if (*index_int
> INT_MAX
) {
6344 index_value
->error("An integer value less than `%d' was expected "
6345 "for indexing type `%s' instead of `%s'", INT_MAX
,
6346 get_typename().c_str(), (index_int
->t_str()).c_str());
6347 index_value
->set_valuetype(Value::V_ERROR
);
6349 Int index
= index_int
->get_val();
6351 index_value
->error("A non-negative integer value was expected "
6352 "for indexing type `%s' instead of `%s'",
6353 get_typename().c_str(), Int2string(index
).c_str());
6354 index_value
->set_valuetype(Value::V_ERROR
);
6355 } else if (index_map
.has_key(index
)) {
6356 index_value
->error("Duplicate index value `%s' for components "
6357 "`%s' and `%s'", Int2string(index
).c_str(),
6358 Int2string((Int
)i
+ 1).c_str(),
6359 Int2string(*index_map
[index
]).c_str());
6360 index_value
->set_valuetype(Value::V_ERROR
);
6362 index_map
.add(index
, new Int((Int
)i
+ 1));
6366 it_comp
->set_my_governor(u
.seof
.ofType
);
6367 u
.seof
.ofType
->chk_this_template_ref(it_comp
);
6368 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(it_comp
,
6369 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6370 SUB_CHK
, implicit_omit
, lhs
);
6372 for (size_t i
= 0; i
< index_map
.size(); i
++)
6373 delete index_map
.get_nth_elem(i
);
6377 t
->error("%s cannot be used for `set of' type `%s'",
6378 t
->get_templatetype_str(), get_typename().c_str());
6384 bool Type::chk_this_template_array(Template
*t
, namedbool is_modified
,
6385 namedbool implicit_omit
, Common::Assignment
*lhs
)
6387 bool self_ref
= false;
6388 switch (t
->get_templatetype()) {
6389 case Ttcn::Template::OMIT_VALUE
:
6390 if (t
->get_length_restriction())
6391 t
->warning("Redundant usage of length restriction with `omit'");
6393 case Ttcn::Template::PERMUTATION_MATCH
: {
6394 size_t nof_comps
= t
->get_nof_comps();
6395 for (size_t i
= 0; i
< nof_comps
; i
++) {
6396 Template
*t_comp
= t
->get_temp_byIndex(i
);
6397 Error_Context
cntxt(t_comp
, "In element %lu of permutation",
6398 (unsigned long) (i
+ 1));
6399 t_comp
->set_my_governor(u
.array
.element_type
);
6400 u
.array
.element_type
->chk_this_template_ref(t_comp
);
6401 // the elements of permutation must be always complete
6402 self_ref
|= u
.array
.element_type
->chk_this_template_generic(t_comp
,
6403 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6404 NOT_IMPLICIT_OMIT
, lhs
);
6407 case Ttcn::Template::TEMPLATE_LIST
: {
6408 Template
*t_base
= t
->get_base_template();
6409 size_t nof_base_comps
= 0;
6411 t_base
= t_base
->get_template_refd_last();
6412 if (t_base
->get_templatetype() == Ttcn::Template::TEMPLATE_LIST
)
6413 nof_base_comps
= t_base
->get_nof_comps();
6414 else t_base
= 0; // error recovery
6416 if (!u
.array
.dimension
->get_has_error()) {
6417 size_t array_size
= u
.array
.dimension
->get_size();
6418 size_t template_size
= t
->get_nof_listitems();
6419 if (array_size
!= template_size
) {
6420 if (t
->is_flattened()){
6421 t
->error("Too %s elements in the array template: %lu was expected "
6423 array_size
> template_size
? "few" : "many",
6424 (unsigned long)array_size
, (unsigned long)template_size
);
6427 t
->warning("The size of template cannot be resolved "
6428 "so it could not be compared to the array size");
6432 size_t nof_comps
= t
->get_nof_comps();
6433 for (size_t i
= 0; i
< nof_comps
; i
++) {
6434 Template
*t_comp
= t
->get_temp_byIndex(i
);
6435 Error_Context
cntxt(t_comp
, "In array element %lu",
6436 (unsigned long)(i
+ 1));
6437 t_comp
->set_my_governor(u
.array
.element_type
);
6438 if (t_base
&& i
< nof_base_comps
)
6439 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6440 u
.array
.element_type
->chk_this_template_ref(t_comp
);
6441 switch (t_comp
->get_templatetype()) {
6442 case Ttcn::Template::PERMUTATION_MATCH
:
6443 // the elements of permutation has to be checked by u.seof.ofType
6444 // the templates within the permutation always have to be complete
6445 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
6446 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6447 implicit_omit
, lhs
);
6449 case Ttcn::Template::TEMPLATE_NOTUSED
:
6451 t_comp
->error("Not used symbol `-' is not allowed in this "
6455 self_ref
|= u
.array
.element_type
->chk_this_template_generic(t_comp
,
6456 is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6461 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6462 map
<Int
, Int
> index_map
;
6463 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6464 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6465 Value
*index_value
= (it
->get_index()).get_val();
6466 u
.array
.dimension
->chk_index(index_value
,
6467 Type::EXPECTED_DYNAMIC_VALUE
);
6468 Template
*it_comp
= it
->get_template();
6469 Error_Context
cntxt(it_comp
, "In component %lu",
6470 (unsigned long)(i
+ 1));
6471 if (index_value
->get_value_refd_last()
6472 ->get_valuetype() == Value::V_INT
) {
6473 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6475 if (*index_int
> INT_MAX
) {
6476 index_value
->error("An integer value less than `%d' was expected "
6477 "for indexing type `%s' instead of `%s'",
6478 INT_MAX
, get_typename().c_str(),
6479 (index_int
->t_str()).c_str());
6480 index_value
->set_valuetype(Value::V_ERROR
);
6482 Int index
= index_int
->get_val();
6483 if (index_map
.has_key(index
)) {
6484 index_value
->error("Duplicate index value `%s' for components "
6485 "`%s' and `%s'", Int2string(index
).c_str(),
6486 Int2string((Int
)i
+ 1).c_str(),
6487 Int2string(*index_map
[index
]).c_str());
6488 index_value
->set_valuetype(Value::V_ERROR
);
6490 index_map
.add(index
, new Int((Int
)i
+ 1));
6494 it_comp
->set_my_governor(u
.array
.element_type
);
6495 u
.array
.element_type
->chk_this_template_ref(it_comp
);
6496 self_ref
|= u
.array
.element_type
->chk_this_template_generic(it_comp
,
6497 is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6499 for (size_t i
= 0; i
< index_map
.size(); i
++)
6500 delete index_map
.get_nth_elem(i
);
6504 t
->error("%s cannot be used for array type `%s'",
6505 t
->get_templatetype_str(), get_typename().c_str());
6511 void Type::chk_this_template_Fat(Template
*t
)
6513 t
->error("%s cannot be used for type `%s'",t
->get_templatetype_str(),
6514 get_typename().c_str());
6515 if(t
->get_length_restriction()) t
->error("Length restriction is not "
6516 "allowed for type `%s'", get_typename().c_str());
6519 void Type::chk_this_template_Signature(Template
*t
, namedbool is_modified
)
6521 bool self_ref
= false;
6522 size_t n_type_params
= get_nof_comps();
6523 switch (t
->get_templatetype()) {
6524 case Ttcn::Template::TEMPLATE_LIST
:
6525 // conversion: value list -> assignment notation
6526 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
6528 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
6529 map
<string
, Ttcn::NamedTemplate
> comp_map
;
6530 // it is set to false if we have lost the ordering
6531 bool in_synch
= true;
6532 size_t n_template_comps
= t
->get_nof_comps();
6534 for (size_t v_i
= 0; v_i
< n_template_comps
; v_i
++) {
6535 Ttcn::NamedTemplate
*nt
= t
->get_namedtemp_byIndex(v_i
);
6536 const Identifier
& temp_id
= nt
->get_name();
6537 const string
& temp_name
= temp_id
.get_name();
6538 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
6539 if (!has_comp_withName(temp_id
)) {
6540 nt
->error("Reference to non-existent parameter `%s' in template "
6541 "for signature `%s'", temp_dispname_str
, get_typename().c_str());
6544 } else if (comp_map
.has_key(temp_name
)) {
6545 nt
->error("Duplicate parameter `%s' in template for signature `%s'",
6546 temp_dispname_str
, get_typename().c_str());
6547 comp_map
[temp_name
]->note("Parameter `%s' is already given here",
6550 } else comp_map
.add(temp_name
, nt
);
6551 const SignatureParam
*par
=
6552 u
.signature
.parameters
->get_param_byName(temp_id
);
6554 SignatureParam
*par2
= 0;
6555 for ( ; t_i
< n_type_params
; t_i
++) {
6556 par2
= u
.signature
.parameters
->get_param_byIndex(t_i
);
6557 if (par2
== par
) break;
6560 nt
->error("Unexpected parameter `%s' in signature template",
6565 Type
*type
= par
->get_type();
6566 Template
*comp_t
= nt
->get_template();
6567 Error_Context
cntxt(comp_t
, "In template for signature parameter `%s'",
6569 comp_t
->set_my_governor(type
);
6570 type
->chk_this_template_ref(comp_t
);
6571 self_ref
|= type
->chk_this_template_generic(comp_t
, is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_NOT_ALLOWED
,
6572 SUB_CHK
, NOT_IMPLICIT_OMIT
, NULL
);
6575 SignatureParam
*first_undef_in
= NULL
,
6576 *first_undef_out
= NULL
;
6577 for (size_t i
= 0; i
< n_type_params
; i
++) {
6578 SignatureParam
*par
= u
.signature
.parameters
->get_param_byIndex(i
);
6579 const Identifier
& id
= par
->get_id();
6580 if (!comp_map
.has_key(id
.get_name()) ||
6581 comp_map
[id
.get_name()]->get_template()->get_templatetype() ==
6582 Template::TEMPLATE_NOTUSED
) {
6583 switch(par
->get_direction()) {
6584 case SignatureParam::PARAM_IN
:
6585 if(!first_undef_in
) first_undef_in
= par
;
6587 case SignatureParam::PARAM_OUT
:
6588 if(!first_undef_out
) first_undef_out
= par
;
6591 t
->error("Signature template is incomplete, because the inout "
6592 "parameter `%s' is missing", id
.get_dispname().c_str());
6596 if(first_undef_in
!=NULL
&& first_undef_out
!=NULL
)
6597 t
->error("Signature template is incomplete, because the in parameter "
6598 "`%s' and the out parameter `%s' is missing",
6599 first_undef_in
->get_id().get_dispname().c_str(),
6600 first_undef_out
->get_id().get_dispname().c_str());
6605 t
->error("%s cannot be used for signature `%s'",
6606 t
->get_templatetype_str(), get_typename().c_str());
6609 if (t
->get_length_restriction())
6610 t
->error("Length restriction is not allowed in a template for "
6611 "signature `%s'", get_typename().c_str());
6614 } // namespace Common