1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../common/dbgnew.hh"
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(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
) {
398 if(rawattrib
==NULL
) {rawattrib
= new RawAST
; new_raw
=true;}
399 if(textattrib
==NULL
){textattrib
= new TextAST
; new_text
=true;}
400 if(xerattrib
==NULL
) {xerattrib
= new XerAttributes
; new_xer
= true;}
401 if(berattrib
==NULL
) {berattrib
= new BerAST
; new_ber
= true;}
402 if (NULL
== jsonattrib
) {
403 jsonattrib
= new JsonAST
;
409 vector
<SingleWithAttrib
> const &real_attribs
410 = w_attrib_path
->get_real_attrib();
412 //calculate the type's attributes (the qualifierless ones)
413 size_t nof_elements
= real_attribs
.size();
414 for(size_t i
= 0; i
< nof_elements
; i
++)
416 SingleWithAttrib
*temp_single
= real_attribs
[i
];
417 if(temp_single
->get_attribKeyword() == SingleWithAttrib::AT_VARIANT
418 && (!temp_single
->get_attribQualifiers()
419 || temp_single
->get_attribQualifiers()->get_nof_qualifiers()
421 // raw/text/xer/ber/json attributes for the whole record/seq.
422 // (own or inherited)
423 parse_rawAST(rawattrib
, textattrib
, xerattrib
, berattrib
, jsonattrib
,
424 temp_single
->get_attribSpec(), get_length_multiplier(),
425 my_scope
->get_scope_mod(),
426 raw_found
, text_found
, xer_found
, ber_found
, json_found
);
429 //calculate the components attributes
430 MultiWithAttrib
* self_attribs
= w_attrib_path
->get_with_attr();
433 MultiWithAttrib
* new_self_attribs
= new MultiWithAttrib
;
434 SingleWithAttrib
* swa
= 0;
436 // copy all the "encode" attributes
437 for(size_t i
= 0; i
< self_attribs
->get_nof_elements(); i
++)
439 if(self_attribs
->get_element(i
)->get_attribKeyword()
440 == SingleWithAttrib::AT_ENCODE
)
442 // Copy the attribute without qualifiers
443 const SingleWithAttrib
* swaref
= self_attribs
->get_element(i
);
444 swa
= new SingleWithAttrib(swaref
->get_attribKeyword(),
445 swaref
->has_override(), 0, swaref
->get_attribSpec().clone());
446 new_self_attribs
->add_element(swa
);
450 if(new_self_attribs
->get_nof_elements() > 0)
451 { // One or more "encode"s were copied; create a context for them.
452 // This is a member because is has to be owned by this Type
453 // (the components only refer to it).
454 encode_attrib_path
= new WithAttribPath
;
455 encode_attrib_path
->set_with_attr(new_self_attribs
);
456 encode_attrib_path
->set_parent(w_attrib_path
->get_parent());
458 else delete new_self_attribs
;
460 // This should be bool, but gcc 4.1.2-sol8 generates incorrect code
462 const int se_of
= (typetype
== T_SEQOF
|| typetype
== T_SETOF
);
463 const size_t nof_comps
= se_of
? 1 : get_nof_comps();
465 // Distribute the attributes with qualifiers to the components.
466 // If the type is a sequence-of or set-of, we pretend it to have
467 // one component with the name "_0" (a valid TTCN-3 identifier
468 // can't begin with an underscore). compiler.y has created
469 // the appropriate identifier in the qualifier for a "[-]".
470 for(size_t i
= 0; i
< nof_comps
; i
++)
472 const Identifier
& comp_id
=
473 se_of
? underscore_zero
: get_comp_id_byIndex(i
);
474 MultiWithAttrib
* component_attribs
= new MultiWithAttrib
;
476 for(size_t j
= 0; j
< self_attribs
->get_nof_elements(); j
++)
478 const SingleWithAttrib
*temp_single
=
479 self_attribs
->get_element(j
);
480 Qualifiers
* temp_qualifiers
=
481 temp_single
->get_attribQualifiers();
483 || temp_qualifiers
->get_nof_qualifiers() == 0) continue;
485 Qualifiers
* calculated_qualifiers
= new Qualifiers
;
486 bool qualifier_added
= false;
487 for(size_t k
=0; k
< temp_qualifiers
->get_nof_qualifiers(); )
489 const Qualifier
* temp_qualifier
=
490 temp_qualifiers
->get_qualifier(k
);
491 if(temp_qualifier
->get_nof_identifiers() > 0
492 && (*temp_qualifier
->get_identifier(0) == comp_id
))
494 // Found a qualifier whose first identifier matches
495 // the component name. Remove the qualifier from the
496 // enclosing type, chop off its head,
497 // and add it to the component's qualifiers.
498 calculated_qualifiers
->add_qualifier(
499 temp_qualifier
->get_qualifier_without_first_id());
500 temp_qualifiers
->delete_qualifier(k
);
501 qualifier_added
= true;
508 // A copy of temp_single, with new qualifiers
509 SingleWithAttrib
* temp_single2
510 = new SingleWithAttrib(temp_single
->get_attribKeyword(),
511 temp_single
->has_override(),
512 calculated_qualifiers
,
513 temp_single
->get_attribSpec().clone());
514 temp_single2
->set_location(*temp_single
);
515 component_attribs
->add_element(temp_single2
);
517 else delete calculated_qualifiers
;
520 if (component_attribs
->get_nof_elements() > 0) {
521 Type
* component_type
= se_of
?
522 get_ofType() : get_comp_byIndex(i
)->get_type();
524 if(encode_attrib_path
)
525 // The record's "encode" attributes (only) apply to the fields.
526 // Interpose them in the path of the field.
527 component_type
->set_parent_path(encode_attrib_path
);
529 component_type
->set_parent_path(w_attrib_path
->get_parent());
531 component_type
->set_with_attr(component_attribs
);
533 else delete component_attribs
;
534 } // next component index
536 // Any remaining attributes with qualifiers are erroneous
537 for(size_t i
= 0; i
< self_attribs
->get_nof_elements();)
539 Qualifiers
*temp_qualifiers
= self_attribs
->get_element(i
)
540 ->get_attribQualifiers();
541 if(temp_qualifiers
&& temp_qualifiers
->get_nof_qualifiers() != 0)
543 size_t nof_qualifiers
= temp_qualifiers
->get_nof_qualifiers();
544 for(size_t j
= 0; j
< nof_qualifiers
; j
++)
546 const Qualifier
*temp_qualifier
=
547 temp_qualifiers
->get_qualifier(j
);
548 const Identifier
& tmp_id
= *temp_qualifier
->get_identifier(0);
549 // Special case when trying to reference the inner type
550 // of a record-of when it wasn't a record-of.
551 if (tmp_id
== underscore_zero
) temp_qualifier
->error(
552 "Invalid field qualifier [-]");
553 else temp_qualifier
->error("Invalid field qualifier %s",
554 tmp_id
.get_dispname().c_str());
556 self_attribs
->delete_element(i
);
561 } // end if(self_attribs)
562 } // end if(w_attrib_path)
563 if (!raw_found
&& new_raw
) { delete rawattrib
; rawattrib
= NULL
; }
564 if (!text_found
&& new_text
){ delete textattrib
; textattrib
= NULL
; }
565 if (!xer_found
&& new_xer
) { delete xerattrib
; xerattrib
= NULL
; }
566 if (!ber_found
&& new_ber
) { delete berattrib
; berattrib
= NULL
; }
567 if (!json_found
&& new_json
) {
573 // nothing to do, ASN1 types or types without defined raw attribute
576 if (rawattrib
&& !enable_raw()) { delete rawattrib
; rawattrib
= NULL
;}
577 if (textattrib
&& !enable_text()){ delete textattrib
; textattrib
= NULL
;}
578 if (xerattrib
&& !enable_xer()) { delete xerattrib
; xerattrib
= NULL
;}
579 if (berattrib
&& !enable_ber()) { delete berattrib
; berattrib
= NULL
;}
580 if (NULL
!= jsonattrib
&& !enable_json()) {
584 } // endif( hasVariantAttrs && enable_{raw,text,xer} )
589 // Implements "NAME AS ..." transformations.
590 void change_name(string
&name
, XerAttributes::NameChange change
) {
591 switch (change
.kw_
) {
592 case NamespaceSpecification::NO_MANGLING
:
593 break; // cool, nothing to do!
595 case NamespaceSpecification::UPPERCASED
:
596 // Walking backwards calls size() only once. Loop var must be signed.
597 for (int i
= name
.size()-1; i
>= 0; --i
) {
598 name
[i
] = toupper(name
[i
]);
602 case NamespaceSpecification::LOWERCASED
:
603 for (int i
= name
.size()-1; i
>= 0; --i
) {
604 name
[i
] = tolower(name
[i
]);
608 case NamespaceSpecification::CAPITALIZED
:
609 name
[0] = toupper(name
[0]);
612 case NamespaceSpecification::UNCAPITALIZED
:
613 name
[0] = tolower(name
[0]);
616 default: // explicitly specified name
622 void Type::chk_xer_any_attributes()
624 Type
* const last
= get_type_refd_last();
625 switch (last
->typetype
== T_SEQOF
?
626 last
->u
.seof
.ofType
->get_type_refd_last()->typetype
: 0) {
627 case T_UTF8STRING
: // SEQUENCE OF UTF8String, ASN.1
628 case T_USTR
: // record of universal charstring
632 error("ANY-ATTRIBUTES can only be applied to record of string");
636 switch (parent_type
!= NULL
? parent_type
->typetype
: 0) {
637 case T_SEQ_A
: case T_SET_A
:
638 case T_SEQ_T
: case T_SET_T
:
639 for (size_t x
= 0; x
< parent_type
->get_nof_comps(); ++x
) {
640 CompField
* cf
= parent_type
->get_comp_byIndex(x
);
641 if (cf
->get_type() != this) continue;
642 if (cf
->has_default()) {
643 error("The field with ANY-ATTRIBUTES cannot have DEFAULT");
648 error("ANY-ATTRIBUTES can only be applied to a member of "
649 "SEQUENCE, SET, record or set");
653 if (xerattrib
->untagged_
654 || (parent_type
&& parent_type
->xerattrib
&& parent_type
->xerattrib
->untagged_
)) {
655 error("Neither the type with ANY-ATTRIBUTES, nor its enclosing type "
656 "may be marked UNTAGGED");
660 void Type::chk_xer_any_element()
662 Type
*const last
= get_type_refd_last();
663 switch (last
->typetype
) {
664 case T_UTF8STRING
: // UTF8String, ASN.1
665 case T_USTR
: // universal charstring
668 /* A special case for TTCN-3 where applying ANY-ELEMENT to the record-of
669 * has the same effect as applying it to the string member.
670 * This should no longer be necessary now that we can refer
671 * to the embedded type of a record-of with [-], but it has to stay
672 * unless the standard deprecates it. */
673 Type
*oftype
= last
->u
.seof
.ofType
;
674 if (oftype
->xerattrib
== 0) oftype
->xerattrib
= new XerAttributes
;
675 // Transfer the ANY-ATTRIBUTE from the record-of to its member type
676 oftype
->xerattrib
->anyElement_
= xerattrib
->anyElement_
;
677 xerattrib
->anyElement_
.nElements_
= 0;
678 xerattrib
->anyElement_
.uris_
= 0;
679 // Re-check the member type since we fiddled with it
680 const char * type_name
= "record of";
681 Error_Context
cntxt(this, "In embedded type of %s", type_name
);
682 oftype
->xer_checked
= false;
686 error("ANY-ELEMENT can only be applied to UTF8String "
687 "or universal charstring type");
691 if (xerattrib
->attribute_
|| xerattrib
->base64_
|| xerattrib
->untagged_
692 || xerattrib
->defaultForEmpty_
!= NULL
693 || xerattrib
->whitespace_
!= XerAttributes::PRESERVE
) {
694 error("A type with ANY-ELEMENT may not have any of the following encoding instructions: "
695 "ATTRIBUTE, BASE64, DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED or WHITESPACE");
699 void Type::chk_xer_attribute()
701 if (xerattrib
->element_
) {
702 error("ELEMENT and ATTRIBUTE are incompatible");
705 switch (parent_type
!=NULL
? parent_type
->typetype
:-0) {
706 case 0: // no parent accepted in case a field of this type is declared
707 case T_SEQ_A
: case T_SEQ_T
:
708 case T_SET_A
: case T_SET_T
:
711 error("A type with ATTRIBUTE must be a member of "
712 "SEQUENCE, SET, record or set");
716 if (xerattrib
->untagged_
717 || (parent_type
&& parent_type
->xerattrib
&& parent_type
->xerattrib
->untagged_
)) {
718 error("Neither the type with ATTRIBUTE, nor its enclosing type "
719 "may be marked UNTAGGED");
722 if (has_ae(xerattrib
)) {
723 // TODO: || (xerattrib->defaultForEmpty_ && it is an ASN.1 type)
724 // DEFAULT-FOR-EMPTY is allowed only for TTCN-3
725 error("A type with ATTRIBUTE shall not also have any of the final "
726 "encoding instructions ANY-ELEMENT" /*", DEFAULT-FOR-EMPTY"*/ " or PI-OR-COMMENT");
732 /// Pointer to the field
734 /// The type of the field
736 /// The ultimate type, top->get_type_refd_last()
738 /// The typetype of last, on which we sort. Its name is meant to be
739 /// mnemonic (it belongs to \c last, not \c top)
740 Type::typetype_t lastt
;
743 /// Comparison function for CFCache based on typetype
744 int tcomp(const void *l
, const void *r
)
746 int retval
= ((const CFCache
*)l
)->lastt
- ((const CFCache
*)r
)->lastt
;
750 /** Find the original component name if it was changed by TEXT
752 * If there is a TEXT whose \a new_text matches \p text, return
753 * the corresponding \a target.
755 * If there are no TEXT coding instructions, always returns \p text.
757 * @param[in,out] text on input, a name possibly modified by any TEXT encoding
758 * instruction; on output, the actual component name
760 void Type::target_of_text(string
& text
)
762 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
763 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
765 if ((unsigned long)txt
.prefix
== 0
766 ||(unsigned long)txt
.prefix
== NamespaceSpecification::ALL
) {
767 FATAL_ERROR("Type::target_of_text()");
771 string
target(txt
.target
);
773 switch ((unsigned long)txt
.new_text
) {
774 case NamespaceSpecification::CAPITALIZED
: // tARGET -> TARGET
775 target
[0] = toupper(target
[0]);
777 case NamespaceSpecification::UNCAPITALIZED
:
778 target
[0] = tolower(target
[0]); // TARGET -> tARGET
780 case NamespaceSpecification::UPPERCASED
:
781 for (int si
= target
.size() - 1; si
>= 0; --si
) {
782 target
[si
] = toupper(target
[si
]);
785 case NamespaceSpecification::LOWERCASED
:
786 for (int si
= target
.size() - 1; si
>= 0; --si
) {
787 target
[si
] = tolower(target
[si
]);
791 case 0: // "text" not possible
792 FATAL_ERROR("Type::target_of_text() Text with no target and DFE");
795 default: // it's a string, "text 'field' as 'string'"
800 if (target
== text
) {
801 text
= txt
.target
; // we want the value before the change
807 // The suffix of the name of the variable which contains the D-F-E value.
808 static const string
dfe_suffix("_dfe");
810 /** Construct a Value to represent defaultForEmpty
812 * @param last pointer to a Type which is the end of the reference chain,
813 * usually this->get_type_refd_last()
814 * @param dfe_str string containing the value from defaultForEmpty
815 * @return a newly allocated Common::Value
817 Value
*Type::new_value_for_dfe(Type
*last
, const char *dfe_str
)
819 string
defaultstring(dfe_str
);
820 switch (last
->typetype
) {
824 return new Value(Common::Value::V_CSTR
,
825 new string(defaultstring
));
829 return new Value(Common::Value::V_INT
,
830 new int_val_t(dfe_str
, *this));
833 const Real
& rval
= string2Real(dfe_str
, *this);
834 return new Value(Value::V_REAL
, rval
);
838 if (!strcmp(dfe_str
, "true")
839 ||!strcmp(dfe_str
, "1")) {
840 return new Value(Value::V_BOOL
, true);
842 else if (!strcmp(dfe_str
, "false")
843 || !strcmp(dfe_str
, "0")) {
844 return new Value(Value::V_BOOL
, false);
846 else error("Invalid boolean default value");
850 case T_ENUM_A
: case T_ENUM_T
: {
851 // If there is a TEXT, the DFE value corresponds to TextToBeUsed.
852 // Fetch the "real" name of the field (Target).
854 target_of_text(defaultstring
);
856 Identifier
*val_id
= new Identifier(Common::Identifier::ID_TTCN
, // FIXME when ASN1 is supported
859 if (!last
->has_ei_withName(*val_id
)) {
860 error("No enumeration item item '%s'", defaultstring
.c_str());
862 for (size_t ee
=0; ee
< last
->u
.enums
.eis
->get_nof_eis(); ++ee
) {
863 note("Maybe %s", last
->u
.enums
.eis
->get_ei_byIndex(ee
)->get_name().get_name().c_str());
868 return new Value(Common::Value::V_ENUM
, val_id
);
871 case T_CHOICE_A
: case T_CHOICE_T
: {
872 // Try to guess which alternative the given DFE text belongs to.
873 // Sort the fields based on typetype, so BOOL, INT, REAL, ENUM
874 // are tried before the various string types
875 // (any string looks 'right' for a string value).
876 size_t num_comps
= last
->get_nof_comps();
877 CFCache
*sorted
= new CFCache
[num_comps
];
878 for (size_t c
= 0; c
< num_comps
; c
++) {
879 CompField
*cf
= last
->get_comp_byIndex(c
);
880 Type
*cft
= cf
->get_type();
881 Type
*cftlast
= cft
->get_type_refd_last();
884 sorted
[c
].last
= cftlast
;
885 sorted
[c
].lastt
= cftlast
->typetype
;
887 qsort(sorted
, num_comps
, sizeof(CFCache
), tcomp
);
891 for (c
= 0; c
< num_comps
&& retval
== 0; c
++) {
892 CFCache
¤t
= sorted
[c
];
893 // We can't just call new_value_for_dfe(), because some alternatives
894 // would generate errors even if a later type could accept the value.
895 switch (current
.lastt
) {
897 if (!strcmp(dfe_str
, "true")
898 ||!strcmp(dfe_str
, "1")) {
899 retval
= new Value(Value::V_BOOL
, true);
901 else if (!strcmp(dfe_str
, "false")
902 || !strcmp(dfe_str
, "0")) {
903 retval
= new Value(Value::V_BOOL
, false);
907 case T_INT
: case T_INT_A
: {
908 const char *start
= dfe_str
, *end
;
909 while (isspace((const unsigned char)*start
)) ++start
;
910 if (*start
== '+') ++start
;
911 int ndigits
= BN_dec2bn(NULL
, start
); // includes any '-' sign
912 end
= start
+ ndigits
;
913 // Pretend that all trailing whitespace characters were digits
914 while (isspace(*end
)) ++ndigits
, ++end
;
916 // Check that all the string was used up in the conversion,
917 // otherwise "3.1415" and "1e6" would appear as integers.
918 if (defaultstring
.size() == (size_t)ndigits
+ (start
- dfe_str
)) {
919 retval
= current
.top
->new_value_for_dfe(current
.last
, start
);
926 int num_converted
= sscanf(dfe_str
, "%f %1s", &f
, tail
);
927 // If tail was converted (num_converted>1) that's an error
928 if (num_converted
== 1) { // sscanf was happy
929 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
933 case T_ENUM_A
: case T_ENUM_T
: {
934 current
.top
->target_of_text(defaultstring
);
935 Identifier
alt(Identifier::ID_TTCN
, defaultstring
);
936 if (current
.last
->has_ei_withName(alt
)) {
937 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
944 retval
= current
.top
->new_value_for_dfe(current
.last
, dfe_str
);
954 retval
->set_genname(sorted
[c
].top
->genname
, dfe_suffix
);
955 retval
->set_my_scope(sorted
[c
].top
->my_scope
);
956 retval
->set_my_governor(sorted
[c
].top
);
957 Value
*choice_retval
= new Value(Value::V_CHOICE
,
958 new Identifier(sorted
[c
].cf
->get_name()), retval
);
959 retval
= choice_retval
;
965 /* Useless without a properly constructed Value(V_SEQ)
966 case T_SEQ_A: case T_SEQ_T: {
967 NamedValues *nvs = new NamedValues;
968 //NamedValue *nv = new NamedValue(new Identifier, new Value);
970 xerattrib->defaultValue_ = new Value(Value::V_SEQ, nvs);
974 default: // complain later
980 void Type::chk_xer_dfe()
982 Type
* const last
= get_type_refd_last();
984 if (/* TODO xerattrib->attribute_ is error for ASN.1 only */
985 xerattrib
->untagged_
|| has_ae(xerattrib
)) {
986 error("A type with DEFAULT-FOR-EMPTY shall not have any of the final "
987 "encoding instructions ANY-ELEMENT, ATTRIBUTE, UNTAGGED."); // 23.2.8
990 if (is_charenc() == Yes
) {
991 xerattrib
->defaultValue_
= new_value_for_dfe(last
, xerattrib
->defaultForEmpty_
);
993 if (xerattrib
->defaultValue_
!= 0) {
994 xerattrib
->defaultValue_
->set_genname(this->genname
, dfe_suffix
);
995 xerattrib
->defaultValue_
->set_my_scope(this->my_scope
);
996 xerattrib
->defaultValue_
->set_my_governor(last
);
999 error("DEFAULT-FOR-EMPTY not supported for character-encodable type %s",
1000 last
->get_stringRepr().c_str());
1003 else if (last
->typetype
== T_SEQ_A
|| last
->typetype
== T_SEQ_T
) {
1004 // If DEFAULT-FOR-EMPTY applies to a record (SEQUENCE), then only one
1005 // component can produce element content, and it should be the last,
1006 // because all the others should have ATTRIBUTE or ANY-ATTRIBUTE,
1007 // and those are moved to the front. 23.2.2 b)
1008 // FIXME only b) appears to have this restriction, not c)d)e)
1009 const size_t num_cf
= last
->get_nof_comps();
1011 CompField
*cf
= last
->get_comp_byIndex(num_cf
-1); // last field
1012 Type
*cft
= cf
->get_type(); // cft: CompField type
1013 cft
= cft
->get_type_refd_last();
1014 //typetype_t cftt = cft->get_typetype();
1016 xerattrib
->defaultValue_
= new_value_for_dfe(cft
, xerattrib
->defaultForEmpty_
);
1017 if (xerattrib
->defaultValue_
!= 0) {
1018 xerattrib
->defaultValue_
->set_genname(last
->genname
, string("_dfe"));
1019 xerattrib
->defaultValue_
->set_my_scope(cft
->my_scope
);
1020 xerattrib
->defaultValue_
->set_my_governor(cft
);
1023 error("DEFAULT-FOR-EMPTY not supported for fields of type %s",
1024 cft
->get_stringRepr().c_str());
1029 error("DEFAULT-FOR-EMPTY not applicable to type");
1033 void Type::chk_xer_embed_values(int num_attributes
)
1035 Type
* const last
= get_type_refd_last();
1037 enum complaint_type
{ ALL_GOOD
, OPTIONAL_OR_DEFAULT
, UNTAGGED_EMBEDVAL
,
1038 NOT_SEQUENCE
, EMPTY_SEQUENCE
, FIRST_NOT_SEQOF
, SEQOF_NOT_STRING
,
1039 SEQOF_BAD_LENGTH
, UNTAGGED_OTHER
} ;
1040 complaint_type complaint
= ALL_GOOD
;
1041 size_t expected_length
= (size_t)-1;
1042 Type
*cf0t
= 0; // type of first component
1044 switch (last
->typetype
) {
1045 case T_SEQ_A
: case T_SEQ_T
: { // 25.2.1, the type must be a sequence
1046 const size_t num_cf
= last
->get_nof_comps();
1048 complaint
= EMPTY_SEQUENCE
; // must have a "first component"
1051 CompField
*cf0
= last
->get_comp_byIndex(0);
1052 cf0t
= cf0
->get_type()->get_type_refd_last();
1053 if (cf0
->get_is_optional() || cf0
->has_default()) {
1054 complaint
= OPTIONAL_OR_DEFAULT
;
1055 break; // 25.2.1 first component cannot be optional or have default
1058 switch (cf0t
->get_typetype()) { // check the first component
1060 Type
*cfot
= cf0t
->get_ofType(); // embedded type
1061 switch (cfot
->get_type_refd_last()->get_typetype()) {
1063 case T_USTR
: { // hooray, a SEQUENCE OF some string
1064 if ( (cf0t
->xerattrib
&& cf0t
->xerattrib
->untagged_
)
1065 || (cfot
->xerattrib
&& cfot
->xerattrib
->untagged_
)) {
1066 complaint
= UNTAGGED_EMBEDVAL
; // 25.2.2
1070 // Check length restriction on the record of. If there is one,
1071 // it better be the correct number.
1072 // FIXME: if there is also a USE-NIL, it cannot have a length restriction; only check at runtime
1073 const SubType
*sub
= cf0t
->sub_type
;
1074 const Int len
= sub
? sub
->get_length_restriction() :-1;
1075 // get_length_restriction() itself may return -1
1076 expected_length
= num_cf
-num_attributes
-xerattrib
->useOrder_
;
1077 if (len
> 0 && (size_t)len
!= expected_length
) {
1078 // The +1 from 25.2.6 b) is compensated because
1079 // the EMBED-VALUES member itself is ignored.
1080 complaint
= SEQOF_BAD_LENGTH
;
1083 break; } //acceptable
1086 complaint
= SEQOF_NOT_STRING
;
1092 complaint
= FIRST_NOT_SEQOF
;
1094 } // switch(type of first component)
1096 for (size_t c
= 1; c
< num_cf
; ++c
) { // check the other components
1097 cf
= last
->get_comp_byIndex(c
);
1098 Type
*cft
= cf
->get_type()->get_type_refd_last();
1099 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
&& (cft
->is_charenc() == Yes
)){
1100 complaint
= UNTAGGED_OTHER
;
1104 break; } // case T_SEQ*
1107 complaint
= NOT_SEQUENCE
;
1109 } // switch typetype
1111 // TODO 25.2.4, 25.2.5
1112 if (complaint
== ALL_GOOD
) embed_values_possible
= true;
1113 else if (xerattrib
->embedValues_
) {
1114 switch (complaint
) {
1115 case ALL_GOOD
: // Not possible; present in the switch so GCC checks
1116 // that all enum values are handled (make sure there's no default).
1119 case EMPTY_SEQUENCE
:
1120 case FIRST_NOT_SEQOF
:
1121 case SEQOF_NOT_STRING
:
1122 case OPTIONAL_OR_DEFAULT
:
1123 error("A type with EMBED-VALUES must be a sequence type. "
1124 "The first component of the sequence shall be SEQUENCE OF UTF8String "
1125 "and shall not be marked OPTIONAL or DEFAULT");
1127 case SEQOF_BAD_LENGTH
:
1128 cf0t
->error("Wrong length of SEQUENCE-OF for EMBED-VALUES, should be %lu",
1129 (unsigned long)expected_length
);
1131 case UNTAGGED_EMBEDVAL
:
1132 error("Neither the SEQUENCE-OF supporting EMBED-VALUES,"
1133 "nor its component shall have UNTAGGED."); // 25.2.2
1135 case UNTAGGED_OTHER
:
1136 cf
->error("There shall be no UNTAGGED on any character-encodable "
1137 "component of a type with DEFAULT-FOR-EMPTY"); // 25.2.3
1139 } // switch(complaint)
1140 } // if complaint and embedValues
1143 /** Wraps a C string but compares by contents, not by pointer */
1147 explicit stringval(const char *s
= 0) : str(s
) {}
1149 bool operator<(const stringval
& right
) const {
1150 if ( str
> (const char*)NamespaceSpecification::ALL
1151 && right
.str
> (const char*)NamespaceSpecification::ALL
)
1153 return strcmp(str
, right
.str
) < 0;
1155 else return str
< right
.str
;
1157 bool operator==(const stringval
& right
) const {
1158 if ( str
> (const char*)NamespaceSpecification::ALL
1159 && right
.str
> (const char*)NamespaceSpecification::ALL
)
1161 return strcmp(str
, right
.str
) == 0;
1163 else return str
== right
.str
;
1165 //bool operator!() const { return str==0; }
1166 const char *c_str() const { return str
; }
1170 void Type::chk_xer_text()
1172 if (xerattrib
->num_text_
== 0
1173 ||xerattrib
->text_
== 0 ) FATAL_ERROR("Type::chk_xer_text()");
1174 Type
* const last
= get_type_refd_last();
1175 static const stringval empty
; // NULL pointer
1177 // Check the type and quit early if wrong
1178 switch (last
->typetype
) {
1181 case T_ENUM_A
: // not yet
1182 error("No XER yet for ASN.1 enumerations");
1186 case T_BSTR_A
: // ASN.1 bit string with named bits, not yet
1187 error("No XER yet for ASN.1 bit strings");
1189 case T_INT_A
: // ASN.1 integer with named numbers, not yet
1190 error("No XER yet for ASN.1 named numbers");
1193 error("TEXT not allowed for type %s", get_typename().c_str());
1197 // Build a map to eliminate duplicates (new assignment to the same
1198 // enum item/field overwrites previous text).
1199 // Keys are the identifiers, values are the texts.
1200 typedef map
<stringval
, char> text_map_t
;
1201 text_map_t text_map
;
1203 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1204 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
1205 switch ((unsigned long)txt
.target
) {
1206 case 0: { // just "TEXT".
1207 // target=0 and new_text!=0 would have to come from "TEXT AS ..."
1208 // but that's not allowed by syntax, hence FATAL_ERROR.
1209 if (txt
.new_text
) FATAL_ERROR("Type::chk_xer_text");
1210 if (!text_map
.has_key(empty
)) {
1211 text_map
.add(empty
, txt
.new_text
);
1213 if (last
->typetype
!= T_BOOL
) {
1214 error("Lone 'TEXT' only allowed for boolean"); // only in TTCN-3 !
1218 case NamespaceSpecification::ALL
: {// TEXT ALL AS ...
1219 switch (txt
.keyword
) {
1220 case NamespaceSpecification::NO_MANGLING
:
1221 // Not possible due to syntax; there is no TTCN source from which
1222 // the bison parser would create such a NamespaceSpecification.
1223 FATAL_ERROR("Type::chk_xer_text");
1225 case NamespaceSpecification::CAPITALIZED
:
1226 case NamespaceSpecification::UNCAPITALIZED
:
1227 case NamespaceSpecification::LOWERCASED
:
1228 case NamespaceSpecification::UPPERCASED
:
1231 default: // TEXT ALL AS "some string" is not allowed
1232 error("text all as 'string' is not allowed");
1234 } // switch(keyword)
1237 switch (last
->typetype
) {
1239 text_map
.add(stringval(mcopystr("true")), txt
.new_text
);
1240 text_map
.add(stringval(mcopystr("false")), txt
.new_text
);
1245 size_t n_eis
= last
->u
.enums
.eis
->get_nof_eis();
1246 for (size_t i
= 0; i
< n_eis
; ++i
) {
1247 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byIndex(i
);
1248 const stringval
enum_name(mcopystr(ei
->get_name().get_ttcnname().c_str()));
1249 if (text_map
.has_key(enum_name
)) {
1250 // Duplicate enum name, flagged elsewhere as error.
1251 // Don't bother with: text_map[enum_name] = txt.new_text;
1252 Free(const_cast<char*>(enum_name
.c_str()));
1254 else text_map
.add(enum_name
, txt
.new_text
);
1259 FATAL_ERROR("Type::chk_xer_text");
1261 } // switch (typetype)
1265 default: {// a string: TEXT 'member' AS ...
1266 if (txt
.keyword
== NamespaceSpecification::NO_MANGLING
) {
1267 // Attribute syntax does not allow this combination
1268 FATAL_ERROR("Type::chk_xer_text");
1270 // HR39956: empty string is disregarded
1271 if (txt
.keyword
>NamespaceSpecification::LOWERCASED
&& !strcmp(txt
.new_text
,""))
1273 txt
.new_text
= (char*)Realloc(txt
.new_text
, sizeof(" "));
1274 strcpy(txt
.new_text
," ");
1276 stringval
ttarget(txt
.target
);
1277 if (text_map
.has_key(ttarget
)) {
1278 // Override the earlier TEXT instruction
1279 free_name_or_kw(text_map
[ttarget
]);
1280 text_map
[ttarget
] = txt
.new_text
;
1281 free_name_or_kw(txt
.target
);
1283 else text_map
.add(ttarget
, txt
.new_text
);
1288 xerattrib
->text_
= (NamespaceSpecification
*)Realloc(xerattrib
->text_
,
1289 text_map
.size() * sizeof(NamespaceSpecification
));
1291 // Zero out the newly allocated part
1292 if (text_map
.size() > xerattrib
->num_text_
) {
1294 xerattrib
->text_
+ xerattrib
->num_text_
,
1296 (text_map
.size() - xerattrib
->num_text_
) * sizeof(NamespaceSpecification
)
1300 xerattrib
->num_text_
= text_map
.size(); // accept the new size
1302 // Another map, to check for duplicate text (decoding would be impossible)
1305 // Reconstruct the TEXT structure from the map
1306 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1307 const stringval
& k
= text_map
.get_nth_key(t
);
1308 char * v
= text_map
.get_nth_elem(t
);
1309 char * newstr
= const_cast<char*>(k
.c_str());
1311 xerattrib
->text_
[t
].target
= newstr
;
1312 xerattrib
->text_
[t
].new_text
= v
;
1314 stringval
txtval(v
); // somebody else owns v
1315 if (map2
.has_key(txtval
)) {
1316 switch (xerattrib
->text_
[t
].keyword
) {
1317 case NamespaceSpecification::NO_MANGLING
:
1318 FATAL_ERROR("nope");
1319 break; // not possible
1321 case NamespaceSpecification::CAPITALIZED
:
1322 case NamespaceSpecification::UNCAPITALIZED
:
1323 case NamespaceSpecification::LOWERCASED
:
1324 case NamespaceSpecification::UPPERCASED
:
1325 // Duplication may have been caused by expanding TEXT ALL ...
1328 default: // string must be unique
1329 error("Duplicate text '%s'", v
);
1333 else map2
.add(txtval
, newstr
);
1338 for (size_t t
= 0; t
< xerattrib
->num_text_
; ++t
) {
1339 if (xerattrib
->useNumber_
) {
1340 error("USE-NUMBER and TEXT are incompatible");
1343 NamespaceSpecification
& txt
= xerattrib
->text_
[t
];
1345 switch (last
->typetype
) {
1347 /* In ASN.1, Only Booleantype:ALL can have TEXT
1348 * Currently for TTCN, only the following three case are supported:
1350 * "text 'true' as '1'"
1351 * "text 'false' as '0'"
1352 * and we convert the last two to the first
1354 switch ((unsigned long)txt
.prefix
) {
1355 case 0: // no Target (ok);
1356 if (txt
.uri
!= 0) error("Only \"text\" implemented for boolean");
1358 case NamespaceSpecification::ALL
: // Target = 'all' not allowed for boolean
1359 error("TEXT all not implemented for boolean");
1361 default: // a string, must be "true" or "false"
1362 if (!strcmp(txt
.prefix
, "true")) {
1363 // only "1" is allowed for "true"
1364 switch ((unsigned long)txt
.uri
) {
1365 default: // it's a string
1366 if (txt
.uri
[0] == '1' && txt
.uri
[1] == '\0') {
1367 // Free the strings to pretend it was a simple "text"
1368 Free(txt
.prefix
); txt
.prefix
= 0;
1369 Free(txt
.uri
); txt
.uri
= 0;
1370 // These should come in pairs, warn if not
1371 if (xerattrib
->num_text_
== 1) warning("\"text 'false' as '0'\" was implied");
1374 // else fall through
1375 case NamespaceSpecification::CAPITALIZED
:
1376 case NamespaceSpecification::UNCAPITALIZED
:
1377 case NamespaceSpecification::UPPERCASED
:
1378 case NamespaceSpecification::LOWERCASED
:
1379 error("Only '1' is supported for 'true'");
1382 case 0: // "text 'true'" is not correct syntax, cannot get here
1383 FATAL_ERROR("Type::chk_xer_text()");
1386 else if (!strcmp(txt
.prefix
, "false")) {
1387 // only "0" is allowed for "false"
1388 switch ((unsigned long)txt
.uri
) {
1389 default: // it's a string
1390 if (txt
.uri
[0] == '0' && txt
.uri
[1] == '\0') {
1391 // Free the strings to pretend it was a simple "text"
1392 Free(txt
.prefix
); txt
.prefix
= 0;
1393 Free(txt
.uri
); txt
.uri
= 0;
1394 // These should come in pairs, warn if not
1395 if (xerattrib
->num_text_
== 1) warning("\"text 'true' as '1'\" was implied");
1398 // else fall through
1399 case NamespaceSpecification::CAPITALIZED
:
1400 case NamespaceSpecification::UNCAPITALIZED
:
1401 case NamespaceSpecification::UPPERCASED
:
1402 case NamespaceSpecification::LOWERCASED
:
1403 error("Only '0' is supported for 'false'");
1406 case 0: // "text 'false'" is not correct syntax, cannot get here
1407 FATAL_ERROR("Type::chk_xer_text()");
1415 //case T_ENUM_A: // fall through
1417 switch ((unsigned long)txt
.target
) {
1418 case 0: // "text as ..."
1419 case NamespaceSpecification::ALL
: { // "text all as ..."
1420 size_t neis
= last
->u
.enums
.eis
->get_nof_eis();
1421 for (size_t i
= 0; i
< neis
; ++i
) {
1422 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byIndex(i
);
1423 string
ei_name(ei
->get_name().get_dispname()); // use the element's own name
1424 XerAttributes::NameChange chg
;
1426 change_name(ei_name
, chg
);
1427 ei
->set_text(ei_name
);
1431 default: { // target is member name, from "text 'member' as ..."
1432 // FIXME: ID_TTCN will not be right if we implement XER for ASN.1
1433 Common::Identifier
id(Identifier::ID_TTCN
, string(txt
.prefix
));
1434 if (last
->u
.enums
.eis
->get_nof_eis()==0) FATAL_ERROR("No enum items!");
1435 if (last
->u
.enums
.eis
->has_ei_withName(id
)) {
1436 EnumItem
*ei
= last
->u
.enums
.eis
->get_ei_byName(id
);
1437 string
ei_name(id
.get_dispname());
1438 XerAttributes::NameChange chg
;
1440 change_name(ei_name
, chg
);
1441 ei
->set_text(ei_name
);
1444 error("No enumeration item %s", txt
.prefix
);
1453 if (last->u.namednums.nvs->get_nof_nvs()) {
1454 Common::Identifier id(Identifier::ID_TTCN, txt.uri);
1455 NamedValue *nv = last->u.namednums.nvs->get_nv_byName(id);
1460 error("No component %s in %s", txt.uri, fn);
1464 error("TEXT cannot be assigned to an integer without named numbers");
1470 FATAL_ERROR("Type::chk_xer_text");
1473 } // next type for TEXT
1476 void Type::chk_xer_untagged()
1478 Type
* const last
= get_type_refd_last();
1479 switch (parent_type
? parent_type
->typetype
:-0) {
1480 case 0: // "no parent" is acceptable
1481 // Do not nag ("UNTAGGED encoding attribute is ignored on top-level type");
1482 // do it in Def_ExtFunction::chk_function_type when the type is actually
1483 // used as input for an encoding function.
1485 case T_SEQ_A
: case T_SEQ_T
:
1486 case T_SET_A
: case T_SET_T
:
1487 case T_CHOICE_A
: case T_CHOICE_T
:
1488 case T_SEQOF
: case T_SETOF
:
1489 break; // acceptable
1491 error("UNTAGGED can only be applied to a member of sequence, set, "
1492 "choice, sequence-of, or set-of type"); // X.693amd1, 32.2.1
1496 if ( has_aa(xerattrib
)
1497 || has_ae(xerattrib
)
1498 || xerattrib
->attribute_
|| 0 != xerattrib
->defaultForEmpty_
1499 || xerattrib
->embedValues_
|| xerattrib
->useNil_
1500 || (xerattrib
->useOrder_
&& is_asn1()) || xerattrib
->useType_
) {
1501 error("A type with final encoding attribute UNTAGGED shall not have"
1502 " any of the final encoding instructions ANY-ATTRIBUTES, ANY-ELEMENT,"
1503 " ATTRIBUTE, DEFAULT-FOR-EMPTY, EMBED-VALUES, PI-OR-COMMENT,"
1504 " USE-NIL%s or USE-TYPE",
1505 is_asn1() ? ", USE-ORDER" : ""); // X.693amd1, 32.2.6
1508 bool can_become_empty
= last
->has_empty_xml();
1509 if (can_become_empty
) { // checking 32.2.4
1510 switch (parent_type
? parent_type
->typetype
:-0) {
1512 break; // no parent, no problem
1514 case T_SEQ_A
: case T_SEQ_T
:
1515 case T_SET_A
: case T_SET_T
: {
1516 // This type can not have OPTIONAL or DEFAULT, 32.2.4 a)
1517 // No get_comp_byType(); do a linear search.
1518 size_t num_fields
= parent_type
->get_nof_comps();
1519 for (size_t i
= 0; i
< num_fields
; ++i
) {
1520 CompField
*cf
= parent_type
->get_comp_byIndex(i
);
1521 if (cf
->get_type() != this) continue;
1522 // found the component
1523 if (cf
->get_is_optional() || cf
->get_defval() != 0) {
1524 error("Type with final encoding attribute UNTAGGED"
1525 " shall not have OPIONAL or DEFAULT");
1531 case T_SEQOF
: case T_SETOF
: // X.693amd1, 32.2.4 b)
1532 error("UNTAGGED type with possibly empty XML value can not be "
1533 "the member of a sequence-of or set-of"); // X.693amd1, 32.2.4 b)
1537 size_t num_fields
= parent_type
->get_nof_comps();
1538 size_t num_empty
= 0;
1539 for (size_t i
= 0; i
< num_fields
; ++i
) {
1540 CompField
*cf
= parent_type
->get_comp_byIndex(i
);
1541 Type
*cft
= cf
->get_type();
1542 if (cft
->has_empty_xml()) ++num_empty
;
1544 if (num_empty
> 1) { // X.693amd1, 32.2.4 c)
1545 /* FIXME: this should be error */
1546 warning("More than one alternative can be empty and has UNTAGGED");
1550 default: // do nothing
1553 } // end if(can_become_empty)
1556 void Type::chk_xer_use_nil()
1558 Type
* const last
= get_type_refd_last();
1560 enum complaint_type
{ ALL_GOOD
, NO_CONTROLNS
, NOT_SEQUENCE
, EMPTY_SEQUENCE
,
1561 UNTAGGED_USENIL
, COMPONENT_NOT_ATTRIBUTE
, LAST_IS_ATTRIBUTE
,
1562 LAST_NOT_OPTIONAL
, INCOMPATIBLE
, WRONG_OPTIONAL_TYPE
, EMBED_CHARENC
};
1563 complaint_type complaint
= ALL_GOOD
;
1565 CompField
*cf_last
= 0;
1566 const char *ns
, *prefix
;
1567 my_scope
->get_scope_mod()->get_controlns(ns
, prefix
);
1569 if (!prefix
) complaint
= NO_CONTROLNS
; // don't bother checking further
1570 else switch (last
->typetype
) {
1572 complaint
= NOT_SEQUENCE
;
1576 error("No XER yet for ASN.1 sequences");
1579 const size_t num_cf
= last
->get_nof_comps();
1580 if (num_cf
== 0) { // 33.2.1 ...must have a component...
1581 complaint
= EMPTY_SEQUENCE
;
1582 break; // stop checking to prevent accessing non-existing components
1584 if (xerattrib
->untagged_
) { // 33.2.2
1585 complaint
= UNTAGGED_USENIL
;
1589 // Skip components supporting USE-ORDER or EMBED-VALUES
1590 size_t i
= (xerattrib
->useOrder_
) + (xerattrib
->embedValues_
);
1591 // 33.2.1 All the others except the last must be (any)attributes
1592 for (; i
< num_cf
-1; ++i
) {
1593 cf
= last
->get_comp_byIndex(i
);
1594 Type
*cft
= cf
->get_type();
1595 if (! (cft
->xerattrib
1596 && ( cft
->xerattrib
->attribute_
|| has_aa(cft
->xerattrib
))))
1598 complaint
= COMPONENT_NOT_ATTRIBUTE
;
1602 // 33.2.1 The last component must be an OPTIONAL non-attribute
1603 cf_last
= last
->get_comp_byIndex(num_cf
-1);
1604 Type
*cft
= cf_last
->get_type();
1605 if (!cf_last
->get_is_optional()) {
1606 complaint
= LAST_NOT_OPTIONAL
;
1609 if (cft
->xerattrib
) {
1610 if ( cft
->xerattrib
->attribute_
1611 || has_aa(cft
->xerattrib
)) {
1612 complaint
= LAST_IS_ATTRIBUTE
;
1616 if (has_ae(cft
->xerattrib
)
1617 ||has_aa(cft
->xerattrib
)
1618 ||cft
->xerattrib
->defaultForEmpty_
!= 0
1619 ||cft
->xerattrib
->embedValues_
||cft
->xerattrib
->untagged_
1620 ||cft
->xerattrib
->useNil_
||cft
->xerattrib
->useOrder_
1621 ||cft
->xerattrib
->useType_
) { // or PI-OR-COMMENT
1622 complaint
= INCOMPATIBLE
; // 33.2.3
1626 if (cft
->is_charenc() == Yes
) {
1627 // In a sequence EMBED-VALUES and USE-NIL, the optional component
1628 // supporting USE-NIL shall not be a character-encodable type.
1629 // So says OSS, and rightly so (there's no way to separate
1630 // the last field from the surrounding "embed" strings).
1631 if (xerattrib
->embedValues_
) complaint
= EMBED_CHARENC
;
1633 else switch (cft
->get_type_refd_last()->typetype
) {
1644 // or an octetstring or bitstring with a contained "Type" and without ENCODED BY
1645 break; // acceptable
1648 complaint
= WRONG_OPTIONAL_TYPE
;
1653 } // else switch(last->typetype)
1655 if (complaint
== ALL_GOOD
) use_nil_possible
= true;
1656 else if (xerattrib
->useNil_
) {
1657 switch (complaint
) {
1658 case ALL_GOOD
: // Not possible because of the if.
1659 // Present so GCC checks that all enum values are handled (no default!)
1662 error("Type has USE-NIL, but the module has no control namespace set");
1665 error("The target of an USE-NIL encoding instruction must be a record (SEQUENCE) or set type");
1667 case EMPTY_SEQUENCE
:
1668 error("The target of an USE-NIL must have at least one component");
1670 case UNTAGGED_USENIL
:
1671 error("The target of an USE-NIL encoding instruction shall not have"
1672 " a final UNTAGGED encoding instruction");
1674 case COMPONENT_NOT_ATTRIBUTE
:
1675 cf
->error("Component '%s' of USE-NIL not ATTRIBUTE", cf
->get_name().get_name().c_str());
1677 case LAST_IS_ATTRIBUTE
:
1678 cf_last
->error("Last component of USE-NIL must not have ATTRIBUTE");
1680 case LAST_NOT_OPTIONAL
:
1681 cf_last
->error("Last component of USE-NIL must be OPTIONAL");
1684 cf_last
->error("The OPTIONAL component of USE-NIL cannot have any of the "
1685 "following encoding instructions: ANY-ATTRIBUTES, ANY-ELEMENT, "
1686 "DEFAULT-FOR-EMPTY, EMBED-VALUES, PI-OR-COMMENT, UNTAGGED, "
1687 "USE-NIL, USE-ORDER, USE-TYPE.");
1689 case WRONG_OPTIONAL_TYPE
:
1690 cf_last
->error("The OPTIONAL component of USE-NIL must be "
1691 "a character-encodable type, or a sequence, set, choice, "
1692 "sequence-of, set-of or open type.");
1695 cf_last
->error("In a sequence type with EMBED-VALUES and USE-NIL, "
1696 "the optional component supporting USE-NIL shall not be "
1697 "a character-encodable type.");
1703 void Type::chk_xer_use_order(int num_attributes
)
1705 Type
* const last
= get_type_refd_last();
1707 enum complaint_type
{ ALL_GOOD
, NOT_SEQUENCE
, NOT_ENOUGH_MEMBERS
,
1708 FIRST_NOT_RECORD_OF
, FIRST_NOT_RECORD_OF_ENUM
, FIRST_OPTIONAL
,
1709 LAST_NOT_RECORD
, BAD_ENUM
, ENUM_GAP
, NOTHING_TO_ORDER
};
1710 complaint_type complaint
= ALL_GOOD
;
1711 Type
*the_enum
= 0; // Well, it's supposed to be an enum.
1712 switch (last
->typetype
) {
1713 case T_SEQ_A
: case T_SEQ_T
: { // record/SEQUENCE acceptable
1714 size_t useorder_index
= xerattrib
->embedValues_
;
1715 // The first (or second, if the first is taken by EMBED_VALUES)
1716 // member must be a record of enumerated
1717 if (useorder_index
>= last
->get_nof_comps()) {
1718 complaint
= NOT_ENOUGH_MEMBERS
;
1721 CompField
*uo_field
= last
->get_comp_byIndex(useorder_index
);
1722 Type
*uot
= uo_field
->get_type();
1723 if (uot
->get_type_refd_last()->typetype
== T_SEQOF
) {
1724 the_enum
= uot
->get_ofType()->get_type_refd_last();
1725 switch (the_enum
->typetype
) {
1726 case T_ENUM_A
: case T_ENUM_T
: // acceptable
1727 if (uo_field
->get_is_optional() || uo_field
->get_defval() != 0) {
1728 complaint
= FIRST_OPTIONAL
;
1732 complaint
= FIRST_NOT_RECORD_OF_ENUM
;
1734 } // switch enum type
1735 size_t ncomps
= last
->get_nof_comps();
1736 // the components of this sequence will have to match the enum
1737 Type
*sequence_type
= 0;
1738 size_t expected_enum_items
, first_non_attr
;
1740 if (xerattrib
->useNil_
) { // useNil in addition to useOrder
1741 // This is an additional complication because USE-ORDER
1742 // will affect the optional component, rather than the type itself
1743 CompField
*cf
= get_comp_byIndex(ncomps
-1);
1744 sequence_type
= cf
->get_type()->get_type_refd_last();
1745 if (sequence_type
->typetype
== T_SEQ_T
1746 ||sequence_type
->typetype
== T_SEQ_A
) {
1748 // No need to check that it has at least one component (35.2.1)
1749 // it can't match up with the enum which always has one
1750 ncomps
= sequence_type
->get_nof_comps();
1751 expected_enum_items
= ncomps
;
1754 else { // Whoops, not a sequence type!
1755 complaint
= LAST_NOT_RECORD
;
1756 break; // the switch(typetype)
1760 sequence_type
= last
;
1761 first_non_attr
= useorder_index
+1+num_attributes
;
1762 expected_enum_items
= ncomps
- first_non_attr
;
1765 size_t enum_index
= 0;
1766 if (expected_enum_items
== 0)
1767 complaint
= NOTHING_TO_ORDER
;
1768 else if (the_enum
->u
.enums
.eis
->get_nof_eis() != expected_enum_items
)
1769 complaint
= BAD_ENUM
;
1770 else for (size_t i
= first_non_attr
; i
< ncomps
; ++i
) {
1771 CompField
*cf
= sequence_type
->get_comp_byIndex(i
);
1772 Type
*cft
= cf
->get_type();
1773 if (cft
->xerattrib
&& cft
->xerattrib
->attribute_
) continue;
1774 // Found a non-attribute component. Its name must match an enumval
1775 const Identifier
& field_name
= cf
->get_name();
1776 // don't use get_eis_index_byName(); fatal error if not found :(
1777 const EnumItem
*ei
= the_enum
->get_ei_byIndex(enum_index
);
1778 const Identifier
& enum_name
= ei
->get_name();
1779 if (field_name
!= enum_name
) {// X.693amd1 35.2.2.1 and 35.2.2.2
1780 complaint
= BAD_ENUM
;
1783 Value
*v
= ei
->get_value();
1784 const int_val_t
*ival
= v
->get_val_Int();
1785 const Int enumval
= ival
->get_val();
1786 if ((size_t)enumval
!= enum_index
) {
1787 complaint
= ENUM_GAP
; // 35.2.2.3
1791 } // next enum component
1794 complaint
= FIRST_NOT_RECORD_OF
;
1799 complaint
= NOT_SEQUENCE
;
1801 } // switch typetype
1803 if (complaint
== ALL_GOOD
) use_order_possible
= true;
1804 else if (xerattrib
->useOrder_
) {
1805 switch (complaint
) {
1806 case ALL_GOOD
: // Not possible; present in the switch so GCC checks
1807 // that all enum values are handled (make sure there's no default).
1810 error("USE-ORDER can only be assigned to a SEQUENCE/record type.");
1812 case NOT_ENOUGH_MEMBERS
:
1813 case FIRST_NOT_RECORD_OF
:
1814 case FIRST_NOT_RECORD_OF_ENUM
:
1815 error("The type with USE-ORDER should have a component "
1816 "which is a record-of enumerated");
1818 case FIRST_OPTIONAL
:
1819 error("The record-of for USE-ORDER shall not be marked"
1820 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1822 case NOTHING_TO_ORDER
:
1823 error("The type with USE-ORDER should have at least one "
1824 "non-attribute component");
1826 case LAST_NOT_RECORD
:
1827 error("The OPTIONAL component supporting the USE-NIL "
1828 "encoding instruction should be a SEQUENCE/record");
1831 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1832 the_enum
->error("Enumeration items should match the"
1833 " non-attribute components of the sequence");
1836 if (!the_enum
) FATAL_ERROR("Type::chk_xer_use_order()");
1837 the_enum
->error("Enumeration values must start at 0 and have no gaps");
1843 void Type::chk_xer_use_type()
1845 Type
* const last
= get_type_refd_last();
1847 const char *ns
, *prefix
;
1848 my_scope
->get_scope_mod()->get_controlns(ns
, prefix
);
1849 if (!prefix
) error("Type has USE-TYPE, but the module has no control namespace set");
1851 switch (last
->typetype
) {
1852 // USE-TYPE applied to anytype ? Just say no.
1853 case T_CHOICE_A
: case T_CHOICE_T
: { // must be CHOICE; 37.2.1
1854 if (xerattrib
->untagged_
|| xerattrib
->useUnion_
) { // 37.2.5
1855 error("A type with USE-TYPE encoding instruction shall not also have"
1856 " any of the final encoding instructions UNTAGGED or USE-UNION");
1858 // Now check the alternatives.
1859 // iterating backwards calls get_nof_comps only once
1860 for (int i
= last
->get_nof_comps() - 1; i
>= 0; --i
) {
1861 CompField
*cf
= last
->get_comp_byIndex(i
);
1862 Type
*cft
= cf
->get_type();
1863 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
) {
1864 cf
->error("Alternative of a union with USE-TYPE should not have UNTAGGED"); // 37.2.2
1867 switch (cft
->typetype
) {
1868 case T_CHOICE_A
: case T_CHOICE_T
:
1869 if (cft
->xerattrib
&& cft
->xerattrib
->useType_
) {
1870 cf
->error("Alternative of a CHOICE type with USE-TYPE shall not be"
1871 " a CHOICE type with a USE-TYPE encoding instruction"); // 37.2.3
1880 error("USE-TYPE can only applied to a CHOICE/union type");
1885 void Type::chk_xer_use_union()
1887 Type
* const last
= get_type_refd_last();
1888 switch (last
->typetype
) {
1889 case T_CHOICE_A
: case T_CHOICE_T
: {
1890 // Now check the alternatives.
1891 // iterating backwards calls get_nof_comps only once
1892 for (int i
= last
->get_nof_comps() - 1; i
>= 0; --i
) {
1893 CompField
*cf
= last
->get_comp_byIndex(i
);
1894 Type
*cft
= cf
->get_type();
1895 if (cft
->is_charenc() && !(cft
->xerattrib
&& cft
->xerattrib
->useType_
) &&
1896 !(cft
->xerattrib
&& cft
->xerattrib
->useQName_
)) { // currently not supported
1897 if (cft
->xerattrib
&& cft
->xerattrib
->useUnion_
) // it must be a union
1898 cf
->error("Alternative of a CHOICE/union with USE-UNION"
1899 " can not itself be a CHOICE/union with USE-UNION");
1901 else cf
->error("Alternative of a CHOICE/union with USE-UNION must be character-encodable");
1905 error("USE-UNION can only applied to a CHOICE/union type"); // 38.2.1
1911 static const char *xml98
= "http://www.w3.org/XML/1998/namespace";
1913 void Type::chk_xer() { // XERSTUFF semantic check
1914 // the type (and everything it contains) is fully checked now
1916 if (xer_checked
) return;
1919 Type
*last
= get_type_refd_last();
1921 // Check XER attributes if the type belongs to a type definition,
1922 // a field of a record/set/union, or is the embedded type of a record-of.
1923 if (ownertype
==OT_TYPE_DEF
1924 ||ownertype
==OT_COMP_FIELD
1925 ||ownertype
==OT_RECORD_OF
) {
1926 XerAttributes
*newx
= 0;
1928 // Merge XER attributes from the referenced type.
1929 // This implements X.693amd1 clause 15.1.2
1930 newx
= new XerAttributes
;
1931 Type
*t1
= get_type_refd();
1932 // chk_refd() (called by chk() for T_REFD) does not check
1933 // the referenced type; do it now. This makes it fully recursive.
1936 size_t old_text
= 0;
1937 if (t1
->xerattrib
&& !t1
->xerattrib
->empty()) {
1938 old_text
= t1
->xerattrib
->num_text_
;
1939 *newx
|= *t1
->xerattrib
; // get the ancestor's attributes, except...
1940 newx
->attribute_
= false; // attribute is not inherited
1941 newx
->element_
= false; // element is not inherited
1943 if (ownertype
== OT_TYPE_DEF
1944 ||ownertype
== OT_COMP_FIELD
) {
1945 // Name,Namespace is not inherited, X.693 amd1, 13.6
1946 // are you sure about the namespace?
1947 XerAttributes::FreeNameChange(newx
->name_
);
1948 //XerAttributes::FreeNamespace(newx->namespace_); // HR39678 bugfix beta
1951 // Now merge/override with our own attributes
1952 if (xerattrib
&& !xerattrib
->empty()) {
1953 if (xerattrib
->num_text_
> 0 && old_text
> 0
1954 && (last
->typetype
== T_ENUM_T
|| last
->typetype
== T_ENUM_A
)) {
1955 // Adding more TEXT attributes does not work right.
1956 error("Adding more TEXT attributes is not supported "
1957 "by the implementation.");
1959 *newx
|= *xerattrib
;
1962 if (newx
->empty()) delete newx
;
1963 else { // something interesting was found
1967 if (xerattrib
->attribute_
1968 && t1
->xerattrib
&& t1
->xerattrib
->attribute_
1969 && t1
->ownertype
== OT_TYPE_DEF
1970 && !(xerattrib
->form_
& XerAttributes::LOCALLY_SET
) ) {
1971 // The referenced type came from a global XSD attribute.
1972 // This type's form will be qualified, unless it has an explicit
1973 // "form as ..." (which overrides everything).
1974 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
1977 if (t1
->xerattrib
&& t1
->xerattrib
->element_
1978 // The referenced type came from a global XSD element.
1979 && !(xerattrib
->form_
& XerAttributes::LOCALLY_SET
))
1980 { // and it doesn't have an explicit "form as ..."
1981 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
1987 if (!xerattrib
) return;
1989 //const char *fn = get_fullname().c_str();
1990 //printf("chk_xer(%s)\n", fn);
1992 // In general, "last" should be used instead of "this" in the checks below
1993 // when accessing information about the type's characteristics, except
1994 // this->xerattrib MUST be used (and not last->xerattrib!).
1996 switch (ownertype
) {
2004 FATAL_ERROR("Unexpected ownertype %d", ownertype
);
2007 int num_attributes
= 0;
2008 switch (last
->typetype
) {
2009 case T_SEQ_A
: case T_SEQ_T
:
2010 case T_SET_A
: case T_SET_T
: {
2011 // Count attributes (ANY-ATTRIBUTES counts as one)
2012 const size_t num_cf
= last
->get_nof_comps();
2013 int specials
= xerattrib
->embedValues_
+ xerattrib
->useOrder_
;
2014 int num_any_attributes
= 0;
2015 for (int x
= num_cf
- 1; x
>= specials
; --x
) {
2016 CompField
*cf
= last
->get_comp_byIndex(x
);
2017 Type
*cft
= cf
->get_type() /* NOT get_type_refd_last() */;
2019 && (cft
->xerattrib
->attribute_
|| has_aa(cft
->xerattrib
)))
2021 if (cft
->xerattrib
->attribute_
) ++num_attributes
;
2022 else if (++num_any_attributes
> 1) {
2023 cf
->error("There can be at most one field with ANY-ATTRIBUTES");
2026 else if (num_attributes
+ num_any_attributes
> 0) {
2027 // Found a non-attribute when there was an attribute after it
2028 cf
->error("Non-attribute field before attribute not supported");
2032 num_attributes
+= num_any_attributes
;
2039 /* * * Check restrictions set out in X.693 amd1, clauses 18-39 * * */
2041 if (has_aa(xerattrib
)) {
2042 chk_xer_any_attributes();
2043 } // if ANY-ATTRIBUTES
2045 if (has_ae(xerattrib
)) {
2046 chk_xer_any_element();
2049 if (xerattrib
->attribute_
) {
2050 chk_xer_attribute();
2051 // It's an attribute, check for the attributeFormQualified bit
2052 // and transform it into unconditionally qualified.
2053 if (!(xerattrib
->form_
& XerAttributes::LOCALLY_SET
)
2054 && (xerattrib
->form_
& XerAttributes::ATTRIBUTE_DEFAULT_QUALIFIED
)) {
2055 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2059 // Element, check the elementFormQualified bit.
2060 if (!(xerattrib
->form_
& XerAttributes::LOCALLY_SET
)
2061 && (xerattrib
->form_
& XerAttributes::ELEMENT_DEFAULT_QUALIFIED
)) {
2062 xerattrib
->form_
|= XerAttributes::QUALIFIED
;
2066 if (xerattrib
->base64_
) {
2067 switch (last
->typetype
) {
2068 case T_OSTR
: // OCTET STRING
2069 case T_HSTR
: // hexstring
2072 case T_GENERALSTRING
:
2073 case T_GRAPHICSTRING
:
2076 case T_NUMERICSTRING
:
2077 case T_PRINTABLESTRING
:
2078 case T_TELETEXSTRING
:
2080 case T_UNIVERSALSTRING
:
2082 case T_VIDEOTEXSTRING
:
2083 case T_VISIBLESTRING
:
2087 break; // acceptable
2089 error("BASE64 can only be applied to OCTET STRING, open type or "
2090 "restricted character string type");
2094 if (has_ae(xerattrib
) || xerattrib
->whitespace_
!= XerAttributes::PRESERVE
) {
2095 error("A type with BASE64 shall not have any of the final "
2096 "encoding instructions ANY-ELEMENT or WHITESPACE");
2100 if (xerattrib
->decimal_
) {
2101 if (last
->typetype
!= T_REAL
) {
2102 error("DECIMAL shall only be assigned to a real type");
2106 if (xerattrib
->defaultForEmpty_
!= 0) {
2108 } // if defaultForEmpty
2110 chk_xer_embed_values(num_attributes
); // always
2112 if (xerattrib
->list_
) {
2113 switch (last
->typetype
) {
2114 case T_SEQOF
: case T_SETOF
:
2115 break; // acceptable
2117 error("LIST can only be assigned to SEQUENCE-OF or SET-OF");// 27.2.1
2121 if (has_aa(xerattrib
)) {
2122 error("A type with LIST shall not have ANY-ATTRIBUTES");// 27.2.3
2126 // NAME is handled later when generate_code_xerdescriptor call change_name
2128 if ((unsigned long)xerattrib
->namespace_
.keyword
2129 > (unsigned long)NamespaceSpecification::LOWERCASED
) {
2130 // Now both are proper non-NULL strings
2131 if (*xerattrib
->namespace_
.prefix
!= 0) { // there is a prefix, check it
2132 char first
[4] = {0,0,0,0};
2133 strncpy(first
, xerattrib
->namespace_
.prefix
, 3);
2134 first
[0] = toupper(first
[0]);
2135 first
[1] = toupper(first
[1]);
2136 first
[2] = toupper(first
[2]);
2137 if (!memcmp(first
, "XML", 3) // It _is_ "xml"
2138 // but the W3C XML namespace gets an exemption
2139 && strcmp(xerattrib
->namespace_
.uri
, xml98
)) error(
2140 "Prefix shall not commence with characters that"
2141 " when uppercased are 'XML'");
2142 // X.693 (11/2008), clause 29.1.7
2145 Common::Module::add_namespace(
2146 xerattrib
->namespace_
.uri
, xerattrib
->namespace_
.prefix
);
2148 else xerattrib
->namespace_
.uri
= NULL
; // really no namespace
2150 // PI-OR-COMMENT not supported
2152 if (xerattrib
->num_text_
> 0) {
2156 if (xerattrib
->untagged_
) {
2160 chk_xer_use_nil(); // always
2162 if (xerattrib
->useNumber_
) {
2163 switch (last
->typetype
) {
2165 error("No XER yet for ASN.1 enumerations");
2168 break; // acceptable
2170 warning("USE-NUMBER ignored unless assigned to an enumerated type");
2171 xerattrib
->useNumber_
= false;
2175 if (xerattrib
->num_text_
) {
2176 error("A type with USE-NUMBER shall not have TEXT");
2180 chk_xer_use_order(num_attributes
); //always
2182 if (xerattrib
->useQName_
) {
2183 switch (last
->typetype
) {
2184 case T_SEQ_A
: case T_SEQ_T
: {
2185 if (last
->get_nof_comps() != 2) goto complain
;
2186 const CompField
* cf
= last
->get_comp_byIndex(0);
2187 const Type
* cft
= cf
->get_type()->get_type_refd_last();
2188 if (cft
->typetype
!= T_USTR
&& cft
->typetype
!= T_UTF8STRING
)
2189 cft
->error ("Both components must be UTF8String or universal charstring");
2190 if (!cf
->get_is_optional()) cft
->error(
2191 "The first component of a type with USE-QNAME must be optional");
2193 cf
= last
->get_comp_byIndex(1);
2194 cft
= cf
->get_type()->get_type_refd_last();
2195 if (cft
->typetype
!= T_USTR
&& cft
->typetype
!= T_UTF8STRING
)
2196 cft
->error ("Both components must be UTF8String or universal charstring");
2197 if (cf
->get_is_optional()) cft
->error(
2198 "The second component of a type with USE-QNAME must NOT be optional");
2203 error("A type with USE-QNAME must be a sequence type with exactly two components.");
2206 if (xerattrib
->useNil_
) error("A type with USE-QNAME shall not have USE-NIL"); // 36.2.4
2209 if (xerattrib
->useType_
) {
2213 if (xerattrib
->useUnion_
) {
2214 chk_xer_use_union();
2218 CompFieldMap
& cfm
= *u
.secho
.cfm
;
2219 const size_t ncomps
= cfm
.get_nof_comps();
2220 CompField
*the_one
= 0; // ...and only untagged character-encodable field
2221 map
<int, CompField
> empties
; // potentially empties
2223 for (size_t i
=0; i
< ncomps
; ++i
) {
2224 CompField
* cf
= cfm
.get_comp_byIndex(i
);
2225 Type
*cft
= cf
->get_type();
2227 if (cft
->xerattrib
&& cft
->xerattrib
->untagged_
) {
2228 /* This check could be in chk_xer_untagged(), but then we couldn't
2229 * access the CompField in the parent type. */
2230 if (cft
->is_charenc() == Yes
) {
2231 if (the_one
) { // already has one
2232 cf
->error("More than one UNTAGGED character-encodable field");
2233 // break? to report only once
2236 the_one
= cf
; // this is used for further checks below
2237 u
.secho
.has_single_charenc
= true; // used while generating code
2239 case T_SEQ_A
: case T_SEQ_T
:
2240 if (xerattrib
->untagged_
) {
2241 error("Enclosing type of an UNTAGGED character-encodable type "
2242 "must not be UNTAGGED");
2244 break; // the small switch
2246 error("Enclosing type of an UNTAGGED character-encodable type "
2252 else { // untagged, not charenc
2253 switch (cft
->get_type_refd_last()->typetype
) {
2254 case T_SEQ_A
: case T_SEQ_T
:
2255 case T_SET_A
: case T_SET_T
:
2256 case T_CHOICE_A
: case T_CHOICE_T
:
2259 //case T_OSTR: with a contained type
2260 //case T_BSTR_A: with a contained type
2264 default: // 32.2.3 "If the type is not character-encodable..."
2265 cft
->error("UNTAGGED type should be sequence, set, choice, sequence-of, or set-of type");
2271 if (cft
->has_empty_xml()) {
2277 if (the_one
->get_is_optional() || the_one
->has_default()) {
2278 the_one
->error("UNTAGGED field should not be marked OPTIONAL or DEFAULT");
2280 // Check the other compfields. They must all be (ANY)?ATTRIBUTE
2281 for (size_t i
=0; i
< ncomps
; ++i
) {
2282 CompField
*cf
= cfm
.get_comp_byIndex(i
);
2283 if (cf
== the_one
) continue;
2285 Type
*cft
= cf
->get_type();
2286 if ( !cft
->xerattrib
// cannot be attribute, error
2287 || (!cft
->xerattrib
->attribute_
&& !has_aa(cft
->xerattrib
))) {
2288 the_one
->note("Due to this UNTAGGED component");
2289 cf
->error("All the other components should be ATTRIBUTE or ANY-ATTRIBUTE");
2290 // X.693 (2008) 32.2.2
2296 if (empties
.size() > 1
2297 && (typetype
==T_CHOICE_A
|| typetype
==T_CHOICE_T
)) {
2298 warning("More than one field can have empty XML. Decoding of empty"
2299 " XML is ambiguous, %s chosen arbitrarily.",
2300 empties
.get_nth_elem(empties
.size()-1)->get_name().get_name().c_str());
2308 void Type::chk_Int_A()
2312 if(!u
.namednums
.block
) return;
2314 if(typetype
==T_ERROR
) return;
2315 /* check named numbers */
2316 if(!u
.namednums
.nvs
) return;
2317 map
<Int
, NamedValue
> value_map
;
2318 Error_Context
cntxt(this, "In named numbers");
2319 u
.namednums
.nvs
->chk_dupl_id();
2320 for (size_t i
= 0; i
< u
.namednums
.nvs
->get_nof_nvs(); i
++) {
2321 NamedValue
*nv
= u
.namednums
.nvs
->get_nv_byIndex(i
);
2322 Value
*value
= nv
->get_value();
2323 Value
*v
= value
->get_value_refd_last();
2324 switch (v
->get_valuetype()) {
2325 case Value::V_INT
: {
2326 const int_val_t
*int_val_int
= v
->get_val_Int();
2327 if (*int_val_int
> INT_MAX
) {
2328 value
->error("Integer value `%s' is too big to be used as a named "
2329 "number", (int_val_int
->t_str()).c_str());
2331 Int int_val
= int_val_int
->get_val();
2332 if (value_map
.has_key(int_val
)) {
2333 value
->error("Duplicate number %s for name `%s'",
2334 Int2string(int_val
).c_str(),
2335 nv
->get_name().get_dispname().c_str());
2336 NamedValue
*nv2
= value_map
[int_val
];
2337 nv2
->note("Number %s is already assigned to name `%s'",
2338 Int2string(int_val
).c_str(),
2339 nv2
->get_name().get_dispname().c_str());
2341 value_map
.add(int_val
, nv
);
2345 case Value::V_ERROR
:
2348 nv
->error("INTEGER value was expected for named number `%s'",
2349 nv
->get_name().get_dispname().c_str());
2356 void Type::chk_Enum_A()
2359 if(!u
.enums
.block
) return;
2361 if(typetype
==T_ERROR
) return;
2362 /* checking enumerations */
2363 map
<Int
, EnumItem
> value_map
;
2364 /* checking values before the ellipsis */
2365 for (size_t i
= 0; i
< u
.enums
.eis1
->get_nof_eis(); i
++)
2366 chk_Enum_item(u
.enums
.eis1
->get_ei_byIndex(i
), false, value_map
);
2367 /* assigning default values */
2368 Int
& first_unused
= u
.enums
.first_unused
;
2369 for (first_unused
= 0; value_map
.has_key(first_unused
); first_unused
++) ;
2370 for (size_t i
= 0; i
< u
.enums
.eis1
->get_nof_eis(); i
++) {
2371 EnumItem
*ei
= u
.enums
.eis1
->get_ei_byIndex(i
);
2372 if (!ei
->get_value()) {
2373 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2374 value_map
.add(first_unused
, ei
);
2375 while (value_map
.has_key(++first_unused
)) ;
2378 /* checking values after the ellipsis */
2380 for(size_t i
=0; i
< u
.enums
.eis2
->get_nof_eis(); i
++)
2381 chk_Enum_item(u
.enums
.eis2
->get_ei_byIndex(i
), true, value_map
);
2383 /* determining the first two unused non-negative integer values
2384 * for code generation */
2385 for (first_unused
= 0; value_map
.has_key(first_unused
); first_unused
++) ;
2386 Int
& second_unused
= u
.enums
.second_unused
;
2387 for (second_unused
= first_unused
+ 1; value_map
.has_key(second_unused
);
2390 u
.enums
.eis1
->release_eis();
2391 delete u
.enums
.eis1
;
2394 u
.enums
.eis2
->release_eis();
2395 delete u
.enums
.eis2
;
2400 void Type::chk_Enum_item(EnumItem
*ei
, bool after_ellipsis
,
2401 map
<Int
, EnumItem
>& value_map
)
2403 const Identifier
& name
= ei
->get_name();
2404 const char *dispname_str
= name
.get_dispname().c_str();
2405 if (u
.enums
.eis
->has_ei_withName(name
)) {
2406 ei
->error("Duplicate ENUMERATED identifier: `%s'", dispname_str
);
2407 u
.enums
.eis
->get_ei_byName(name
)->note("Previous definition of `%s' "
2408 "is here", dispname_str
);
2409 } else if (!name
.get_has_valid(Identifier::ID_TTCN
)) {
2410 ei
->warning("The identifier `%s' is not reachable from TTCN-3",
2413 u
.enums
.eis
->add_ei(ei
);
2414 Int
& first_unused
=u
.enums
.first_unused
;
2415 Value
*value
= ei
->get_value();
2419 Error_Context
cntxt(ei
, "In enumeration `%s'", dispname_str
);
2420 v
= value
->get_value_refd_last();
2422 switch (v
->get_valuetype()) {
2425 case Value::V_ERROR
:
2428 value
->error("INTEGER value was expected for enumeration `%s'",
2432 Int enum_value
= v
->get_val_Int()->get_val();
2433 if (static_cast<Int
>(static_cast<int>(enum_value
)) != enum_value
) {
2434 value
->error("The numeric value of enumeration `%s' (%s) is too "
2435 "large for being represented in memory", dispname_str
,
2436 Int2string(enum_value
).c_str());
2438 if (after_ellipsis
) {
2439 if (enum_value
>= first_unused
) {
2440 value_map
.add(enum_value
, ei
);
2441 for (first_unused
= enum_value
+ 1; value_map
.has_key(first_unused
);
2444 value
->error("ENUMERATED values shall be monotonically growing after "
2445 "the ellipsis: the value of `%s' must be at least %s instead of %s",
2446 dispname_str
, Int2string(first_unused
).c_str(),
2447 Int2string(enum_value
).c_str());
2450 if (value_map
.has_key(enum_value
)) {
2451 value
->error("Duplicate numeric value %s for enumeration `%s'",
2452 Int2string(enum_value
).c_str(), dispname_str
);
2453 EnumItem
*ei2
= value_map
[enum_value
];
2454 ei2
->note("Value %s is already assigned to `%s'",
2455 Int2string(enum_value
).c_str(),
2456 ei2
->get_name().get_dispname().c_str());
2457 } else value_map
.add(enum_value
, ei
);
2459 } else { // the item has no value
2460 if (after_ellipsis
) {
2461 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2462 value_map
.add(first_unused
, ei
);
2463 while (value_map
.has_key(++first_unused
)) ;
2468 void Type::chk_Enum_T()
2471 map
<Int
, EnumItem
> value_map
;
2472 map
<string
, EnumItem
> name_map
;
2473 bool error_flag
= false;
2474 /* checking the uniqueness of identifiers and values */
2475 size_t nof_eis
= u
.enums
.eis
->get_nof_eis();
2476 for(size_t i
= 0; i
< nof_eis
; i
++) {
2477 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
2478 const Identifier
& id
= ei
->get_name();
2479 const string
& name
= id
.get_name();
2480 if (name_map
.has_key(name
)) {
2481 const char *dispname_str
= id
.get_dispname().c_str();
2482 ei
->error("Duplicate enumeration identifier `%s'", dispname_str
);
2483 name_map
[name
]->note("Previous definition of `%s' is here",
2487 name_map
.add(name
, ei
);
2489 Value
*value
= ei
->get_value();
2491 /* Handle the error node created by the parser. */
2492 if (value
->get_valuetype() == Value::V_ERROR
) {
2493 value
->error("INTEGER value was expected for enumeration `%s'",
2494 id
.get_dispname().c_str());
2497 const int_val_t
*enum_value_int
= value
->get_val_Int();
2498 // It used to be the same check.
2499 if (*enum_value_int
> INT_MAX
||
2500 static_cast<Int
>(static_cast<int>(enum_value_int
->get_val()))
2501 != enum_value_int
->get_val()) {
2502 value
->error("The numeric value of enumeration `%s' (%s) is "
2503 "too large for being represented in memory",
2504 id
.get_dispname().c_str(), (enum_value_int
->t_str()).c_str());
2507 Int enum_value
= enum_value_int
->get_val();
2508 if (value_map
.has_key(enum_value
)) {
2509 const char *dispname_str
= id
.get_dispname().c_str();
2510 value
->error("Duplicate numeric value %s for enumeration `%s'",
2511 Int2string(enum_value
).c_str(), dispname_str
);
2512 EnumItem
*ei2
= value_map
[enum_value
];
2513 ei2
->note("Value %s is already assigned to `%s'",
2514 Int2string(enum_value
).c_str(),
2515 ei2
->get_name().get_dispname().c_str());
2518 value_map
.add(enum_value
, ei
);
2525 /* assigning default values */
2526 Int
& first_unused
=u
.enums
.first_unused
;
2527 for(first_unused
=0; value_map
.has_key(first_unused
); first_unused
++) ;
2528 for(size_t i
= 0; i
< nof_eis
; i
++) {
2529 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
2530 if(!ei
->get_value()) {
2531 ei
->set_value(new Value(Value::V_INT
, first_unused
));
2532 value_map
.add(first_unused
, ei
);
2533 while (value_map
.has_key(++first_unused
)) ;
2536 Int
& second_unused
= u
.enums
.second_unused
;
2537 for (second_unused
= first_unused
+ 1; value_map
.has_key(second_unused
);
2544 void Type::chk_BStr_A()
2546 if(!u
.namednums
.block
) return;
2548 if(typetype
==T_ERROR
) return;
2549 if(u
.namednums
.nvs
) {
2550 /* check named bits */
2551 map
<Int
, NamedValue
> value_map
;
2553 Error_Context
cntxt(this, "In named bits");
2554 u
.namednums
.nvs
->chk_dupl_id();
2556 for(size_t i
= 0; i
< u
.namednums
.nvs
->get_nof_nvs(); i
++) {
2557 NamedValue
*nv
= u
.namednums
.nvs
->get_nv_byIndex(i
);
2558 const char *dispname_str
= nv
->get_name().get_dispname().c_str();
2559 Value
*value
= nv
->get_value();
2562 Error_Context
cntxt(this, "In named bit `%s'", dispname_str
);
2563 v
= value
->get_value_refd_last();
2565 switch (v
->get_valuetype()) {
2568 case Value::V_ERROR
:
2571 v
->error("INTEGER value was expected for named bit `%s'",
2575 const int_val_t
*int_val_int
= v
->get_val_Int();
2576 if (*int_val_int
> INT_MAX
) {
2577 value
->error("An INTEGER value less than `%d' was expected for "
2578 "named bit `%s' instead of %s", INT_MAX
, dispname_str
,
2579 (int_val_int
->t_str()).c_str());
2582 Int int_val
= int_val_int
->get_val();
2584 value
->error("A non-negative INTEGER value was expected for named "
2585 "bit `%s' instead of %s", dispname_str
,
2586 Int2string(int_val
).c_str());
2589 if (value_map
.has_key(int_val
)) {
2590 value
->error("Duplicate value %s for named bit `%s'",
2591 Int2string(int_val
).c_str(), dispname_str
);
2592 NamedValue
*nv2
= value_map
[int_val
];
2593 nv2
->note("Bit %s is already assigned to name `%s'",
2594 Int2string(int_val
).c_str(),
2595 nv2
->get_name().get_dispname().c_str());
2596 } else value_map
.add(int_val
, nv
);
2602 void Type::chk_SeCho_T()
2604 u
.secho
.cfm
->set_my_type(this);
2607 u
.secho
.component_internal
= false;
2608 size_t nof_comps
= u
.secho
.cfm
->get_nof_comps();
2609 for (size_t i
=0; i
<nof_comps
; i
++) {
2610 Type
* cft
= u
.secho
.cfm
->get_comp_byIndex(i
)->get_type();
2611 if (cft
&& cft
->is_component_internal()) {
2612 u
.secho
.component_internal
= true;
2618 void Type::chk_Choice_A()
2620 if(u
.secho
.block
) parse_block_Choice();
2621 if(typetype
==T_ERROR
) return;
2623 if(u
.secho
.ctss
->needs_auto_tags())
2624 u
.secho
.ctss
->add_auto_tags();
2625 u
.secho
.ctss
->chk();
2626 if (u
.secho
.ctss
->get_nof_comps() <= 0)
2627 FATAL_ERROR("CHOICE type must have at least one alternative");
2628 u
.secho
.ctss
->chk_tags();
2631 void Type::chk_Se_A()
2633 if(u
.secho
.block
) parse_block_Se();
2634 if(typetype
==T_ERROR
) return;
2637 u
.secho
.ctss
->chk();
2638 u
.secho
.ctss
->chk_tags();
2641 void Type::chk_SeOf()
2643 u
.seof
.ofType
->set_genname(get_genname_own(), string('0'));
2644 u
.seof
.ofType
->set_parent_type(this);
2646 const char *type_name
;
2647 bool asn1
= is_asn1();
2650 type_name
= asn1
? "SEQUENCE OF" : "record of";
2653 type_name
= asn1
? "SET OF" : "set of";
2656 type_name
= "<unknown>";
2659 Error_Context
cntxt(this, "In embedded type of %s", type_name
);
2660 u
.seof
.ofType
->chk();
2661 if (!asn1
) u
.seof
.ofType
->chk_embedded(true, "embedded into another type");
2662 u
.seof
.component_internal
= u
.seof
.ofType
->is_component_internal();
2665 void Type::chk_refd()
2668 ReferenceChain
refch(this, "While checking referenced type");
2669 Type
* t_last
= get_type_refd_last(&refch
);
2670 u
.ref
.component_internal
= t_last
->is_component_internal();
2673 void Type::chk_seltype()
2676 u
.seltype
.type
->set_genname(get_genname_own(), string('0'));
2677 ReferenceChain
refch(this, "In selection type");
2678 get_type_refd_last(&refch
);
2679 if(typetype
==T_ERROR
) return;
2680 u
.seltype
.type
->chk();
2683 void Type::chk_Array()
2685 u
.array
.element_type
->set_genname(get_genname_own(), string('0'));
2686 u
.array
.element_type
->set_parent_type(this);
2689 Error_Context
cntxt(this, "In element type of array");
2690 u
.array
.element_type
->chk();
2691 u
.array
.element_type
->chk_embedded(true, "embedded into an array type");
2693 u
.array
.dimension
->chk();
2694 u
.array
.component_internal
= u
.array
.element_type
->is_component_internal();
2697 void Type::chk_Signature()
2700 u
.signature
.component_internal
= false;
2701 if (u
.signature
.parameters
) {
2702 u
.signature
.parameters
->chk(this);
2703 size_t nof_params
= u
.signature
.parameters
->get_nof_params();
2704 for (size_t i
=0; i
<nof_params
; i
++) {
2705 Type
* spt
= u
.signature
.parameters
->get_param_byIndex(i
)->get_type();
2706 if (spt
&& spt
->is_component_internal()) {
2707 u
.signature
.component_internal
= true;
2712 if (u
.signature
.return_type
) {
2713 Error_Context
cntxt(u
.signature
.return_type
, "In return type");
2714 u
.signature
.return_type
->set_genname(get_genname_own(), string('0'));
2715 u
.signature
.return_type
->set_parent_type(this);
2716 u
.signature
.return_type
->chk();
2717 u
.signature
.return_type
->chk_embedded(false,
2718 "the return type of a signature");
2719 if (!u
.signature
.component_internal
&&
2720 u
.signature
.return_type
->is_component_internal())
2721 u
.signature
.component_internal
= true;
2723 if (u
.signature
.exceptions
) {
2724 u
.signature
.exceptions
->chk(this);
2725 if (!u
.signature
.component_internal
) {
2726 size_t nof_types
= u
.signature
.exceptions
->get_nof_types();
2727 for (size_t i
=0; i
<nof_types
; i
++) {
2728 if (u
.signature
.exceptions
->get_type_byIndex(i
)->
2729 is_component_internal()) {
2730 u
.signature
.component_internal
= true;
2738 void Type::chk_Fat()
2742 Scope
*parlist_scope
= my_scope
;
2743 // the runs on clause must be checked before the formal parameter list
2744 // in order to determine the right scope
2745 if (u
.fatref
.runs_on
.ref
) {
2746 if (typetype
== T_FUNCTION
) u
.fatref
.is_startable
= true;
2747 Error_Context
cntxt2(u
.fatref
.runs_on
.ref
, "In `runs on' clause");
2748 u
.fatref
.runs_on
.type
= u
.fatref
.runs_on
.ref
->chk_comptype_ref();
2749 if(u
.fatref
.runs_on
.type
) {
2750 Ttcn::Module
*my_module
=
2751 dynamic_cast<Ttcn::Module
*>(my_scope
->get_scope_mod());
2752 if (!my_module
) FATAL_ERROR("Type::chk_Fat()");
2753 parlist_scope
= my_module
->get_runs_on_scope(u
.fatref
.runs_on
.type
);
2756 u
.fatref
.fp_list
->set_my_scope(parlist_scope
);
2759 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_FUNCTION
);
2760 u
.fatref
.fp_list
->chk_noLazyParams();
2761 if (u
.fatref
.is_startable
&& !u
.fatref
.fp_list
->get_startability())
2762 u
.fatref
.is_startable
= false;
2763 if (u
.fatref
.return_type
) {
2764 Error_Context
cntxt2(u
.fatref
.return_type
, "In return type");
2765 u
.fatref
.return_type
->chk();
2766 u
.fatref
.return_type
->chk_as_return_type(!u
.fatref
.returns_template
,
2768 if (u
.fatref
.is_startable
&& u
.fatref
.return_type
->get_type_refd_last()
2769 ->get_typetype() == T_DEFAULT
) u
.fatref
.is_startable
= false;
2774 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_ALTSTEP
);
2775 u
.fatref
.fp_list
->chk_noLazyParams();
2778 u
.fatref
.fp_list
->chk(Ttcn::Definition::A_TESTCASE
);
2779 u
.fatref
.fp_list
->chk_noLazyParams();
2780 if (u
.fatref
.system
.ref
) {
2781 Error_Context
cntxt2(u
.fatref
.runs_on
.ref
, "In `system' clause");
2782 u
.fatref
.system
.type
= u
.fatref
.system
.ref
->chk_comptype_ref();
2786 FATAL_ERROR("Type::chk_Fat()");
2788 if (!semantic_check_only
)
2789 u
.fatref
.fp_list
->set_genname(get_genname_own());
2792 void Type::chk_address()
2794 Type
*t
= get_type_refd_last();
2795 switch (t
->typetype
) {
2797 error("Port type `%s' cannot be the address type",
2798 t
->get_typename().c_str());
2801 error("Component type `%s' cannot be the address type",
2802 t
->get_typename().c_str());
2805 error("Signature `%s' cannot be the address type",
2806 t
->get_typename().c_str());
2809 error("Default type cannot be the address type");
2812 error("TTCN-3 anytype cannot be the address type");
2820 void Type::chk_embedded(bool default_allowed
, const char *error_msg
)
2822 Type
*t
=get_type_refd_last();
2823 switch (t
->typetype
) {
2825 error("Port type `%s' cannot be %s", t
->get_typename().c_str(),
2829 error("Signature `%s' cannot be %s", t
->get_typename().c_str(),
2833 if (!default_allowed
) error("Default type cannot be %s", error_msg
);
2840 void Type::chk_recursions(ReferenceChain
& refch
)
2842 if (recurs_checked
) return;
2845 if (!refch
.add(t
->get_fullname())) {
2846 // an error has been found (and reported by refch.add)
2847 recurs_checked
= true;
2850 if (!t
->is_ref()) break;
2851 t
= t
->get_type_refd();
2853 switch (t
->typetype
) {
2858 for(size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
2859 CompField
*cf
= t
->get_comp_byIndex(i
);
2860 if(!cf
->get_is_optional()) {
2862 cf
->get_type()->chk_recursions(refch
);
2865 // an optional field can "stop" the recursion
2870 refch
.set_error_reporting(false);
2871 refch
.mark_error_state();
2872 for (size_t i
= 0; i
< t
->get_nof_comps(); ++i
) {
2874 CompField
* cf
= t
->get_comp_byIndex(i
);
2875 cf
->get_type()->chk_recursions(refch
);
2879 if (refch
.nof_errors() == t
->get_nof_comps()) {
2880 refch
.report_errors();
2883 refch
.prev_error_state();
2884 refch
.set_error_reporting(true);
2889 if(t
->get_nof_comps()==1)
2890 t
->get_comp_byIndex(0)->get_type()->chk_recursions(refch
);
2893 t
->get_ofType()->chk_recursions(refch
);
2898 recurs_checked
= true;
2901 void Type::chk_constructor_name(const Identifier
& p_id
)
2911 // T_ANYTYPE can not have a field of type anytype, no need to check.
2912 if (has_comp_withName(p_id
)) {
2913 // HL26011: a field has the same name as the typedef.
2914 // Titan can't generate valid C++ code; better report an error.
2915 get_comp_byName(p_id
)->error("Field name clashes with type name");
2918 default: // can't have fields
2923 bool Type::chk_startability()
2925 if(typetype
!= T_FUNCTION
) FATAL_ERROR("Type::chk_startable()");
2926 if(!checked
) chk_Fat();
2927 if(u
.fatref
.is_startable
) return true;
2928 if (!u
.fatref
.runs_on
.ref
) error("Functions of type `%s' cannot be started "
2929 "on a parallel test component because the type does not have `runs on' "
2930 "clause", get_typename().c_str());
2931 u
.fatref
.fp_list
->chk_startability("Functions of type",
2932 get_typename().c_str());
2933 if (u
.fatref
.return_type
&& u
.fatref
.return_type
->is_component_internal()) {
2934 map
<Type
*,void> type_chain
;
2935 char* err_str
= mprintf("the return type or embedded in the return type "
2936 "of function type `%s' if it is started on a parallel test component",
2937 get_typename().c_str());
2938 u
.fatref
.return_type
->chk_component_internal(type_chain
, err_str
);
2944 void Type::chk_as_return_type(bool as_value
, const char* what
)
2946 Type
*t
= get_type_refd_last();
2947 switch(t
->get_typetype()) {
2949 error("Port type `%s' cannot be the return type of a %s"
2950 , t
->get_fullname().c_str(), what
);
2952 case Type::T_SIGNATURE
:
2953 if(as_value
) error("A value of signature `%s' cannot be the "
2954 "return type of a %s", t
->get_fullname().c_str(), what
);
2961 void Type::chk_this_value_ref(Value
*value
)
2963 switch (value
->get_valuetype()) {
2964 case Value::V_UNDEF_LOWERID
:
2967 if(value
->is_asn1()) {
2970 && u
.namednums
.nvs
->has_nv_withName(*value
->get_val_id())) {
2971 value
->set_valuetype(Value::V_NAMEDINT
);
2972 value
->set_my_governor(this);
2979 if (has_ei_withName(*value
->get_val_id())) {
2980 value
->set_valuetype(Value::V_ENUM
);
2981 value
->set_my_governor(this);
2989 get_type_refd()->chk_this_value_ref(value
);
2994 /* default behavior: interpret as reference */
2995 value
->set_valuetype(Value::V_REFD
);
3002 bool Type::chk_this_value(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3003 namedbool incomplete_allowed
, namedbool omit_allowed
,
3004 namedbool sub_chk
, namedbool implicit_omit
, namedbool is_str_elem
)
3006 bool self_ref
= false;
3008 Value
*v_last
= value
->get_value_refd_last(0, expected_value
);
3009 if (v_last
->get_valuetype() == Value::V_OMIT
) {
3010 if (!omit_allowed
) {
3011 value
->error("`omit' value is not allowed in this context");
3012 value
->set_valuetype(Value::V_ERROR
);
3017 switch (value
->get_valuetype()) {
3018 case Value::V_ERROR
:
3021 return chk_this_refd_value(value
, lhs
, expected_value
, 0, is_str_elem
);
3022 case Value::V_INVOKE
:
3023 chk_this_invoked_value(value
, lhs
, expected_value
);
3024 return false; // assumes no self-ref in invoke
3026 if (lhs
) self_ref
= value
->chk_expr_self_ref(lhs
);
3028 case Value::V_MACRO
:
3029 if (value
->is_unfoldable(0, expected_value
)) {
3030 typetype_t tt
= value
->get_expr_returntype(expected_value
);
3031 if (!is_compatible_tt(tt
, value
->is_asn1())) {
3032 value
->error("Incompatible value: `%s' value was expected",
3033 get_typename().c_str());
3034 value
->set_valuetype(Value::V_ERROR
);
3047 chk_this_value_Null(value
);
3050 chk_this_value_Bool(value
);
3053 chk_this_value_Int(value
);
3056 chk_this_value_Int_A(value
);
3059 chk_this_value_Real(value
);
3063 chk_this_value_Enum(value
);
3066 chk_this_value_BStr(value
);
3069 chk_this_value_BStr_A(value
);
3072 chk_this_value_HStr(value
);
3075 chk_this_value_OStr(value
);
3080 case T_NUMERICSTRING
:
3081 case T_PRINTABLESTRING
:
3082 case T_TELETEXSTRING
:
3083 case T_VIDEOTEXSTRING
:
3085 case T_GRAPHICSTRING
:
3086 case T_VISIBLESTRING
:
3087 case T_GENERALSTRING
:
3088 case T_UNIVERSALSTRING
:
3091 case T_GENERALIZEDTIME
:
3092 case T_OBJECTDESCRIPTOR
:
3093 chk_this_value_CStr(value
);
3096 chk_this_value_OID(value
);
3099 chk_this_value_ROID(value
);
3102 chk_this_value_Any(value
);
3108 self_ref
= chk_this_value_Choice(value
, lhs
, expected_value
, incomplete_allowed
,
3115 self_ref
= chk_this_value_Se(value
, lhs
, expected_value
, incomplete_allowed
,
3120 self_ref
= chk_this_value_SeOf(value
, lhs
, expected_value
, incomplete_allowed
,
3124 self_ref
= get_type_refd()->chk_this_value(value
, lhs
, expected_value
,
3125 incomplete_allowed
, omit_allowed
, NO_SUB_CHK
, implicit_omit
, is_str_elem
);
3127 case T_UNRESTRICTEDSTRING
:
3130 case T_EMBEDDED_PDV
:
3134 self_ref
= get_type_refd()->chk_this_value(value
, lhs
, expected_value
,
3135 incomplete_allowed
, omit_allowed
, NO_SUB_CHK
, NOT_IMPLICIT_OMIT
, is_str_elem
);
3138 chk_this_value_Verdict(value
);
3141 chk_this_value_Default(value
);
3144 self_ref
= chk_this_value_Array(value
, lhs
, expected_value
, incomplete_allowed
, implicit_omit
);
3147 // Remain silent. The error has already been reported in the definition
3148 // that the value belongs to.
3151 self_ref
= chk_this_value_Signature(value
, lhs
, expected_value
, incomplete_allowed
);
3154 chk_this_value_Component(value
);
3159 chk_this_value_FAT(value
);
3162 FATAL_ERROR("Type::chk_this_value()");
3165 // check value against subtype
3166 if(sub_chk
&& (sub_type
!=NULL
)) sub_type
->chk_this_value(value
);
3171 bool Type::chk_this_refd_value(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3172 ReferenceChain
* refch
, namedbool str_elem
)
3174 Reference
*ref
= value
->get_reference();
3175 Assignment
*ass
= ref
->get_refd_assignment();
3177 value
->set_valuetype(Value::V_ERROR
);
3182 bool self_ref
= (ass
== lhs
);
3184 // Exit immediately in case of infinite recursion.
3185 if (value
->get_valuetype() != Value::V_REFD
) return self_ref
;
3186 bool is_const
= false, error_flag
= false, chk_runs_on
= false;
3187 Type
*governor
= NULL
;
3188 switch (ass
->get_asstype()) {
3189 case Assignment::A_ERROR
:
3190 value
->set_valuetype(Value::V_ERROR
);
3192 case Assignment::A_CONST
:
3195 case Assignment::A_OBJECT
:
3196 case Assignment::A_OS
: {
3197 Setting
*setting
= ref
->get_refd_setting();
3198 if (!setting
|| setting
->get_st() == Setting::S_ERROR
) {
3199 value
->set_valuetype(Value::V_ERROR
);
3202 if (setting
->get_st() != Setting::S_V
) {
3203 ref
->error("This InformationFromObjects construct does not refer to "
3204 "a value: `%s'", value
->get_fullname().c_str());
3205 value
->set_valuetype(Value::V_ERROR
);
3208 governor
= dynamic_cast<Value
*>(setting
)->get_my_governor();
3209 if (!governor
) FATAL_ERROR("Type::chk_this_refd_value()");
3212 case Assignment::A_MODULEPAR
:
3216 case Assignment::A_EXT_CONST
:
3217 if (expected_value
== EXPECTED_CONSTANT
) {
3218 value
->error("Reference to an (evaluatable) constant value was "
3219 "expected instead of %s",
3220 ass
->get_description().c_str());
3224 case Assignment::A_VAR
:
3225 case Assignment::A_PAR_VAL
:
3226 case Assignment::A_PAR_VAL_IN
:
3227 case Assignment::A_PAR_VAL_OUT
:
3228 case Assignment::A_PAR_VAL_INOUT
:
3229 switch (expected_value
) {
3230 case EXPECTED_CONSTANT
:
3231 value
->error("Reference to a constant value was expected instead of "
3232 "%s", ass
->get_description().c_str());
3235 case EXPECTED_STATIC_VALUE
:
3236 value
->error("Reference to a static value was expected instead of %s",
3237 ass
->get_description().c_str());
3244 case Assignment::A_MODULEPAR_TEMP
:
3245 case Assignment::A_TEMPLATE
:
3246 case Assignment::A_VAR_TEMPLATE
:
3247 case Assignment::A_PAR_TEMPL_IN
:
3248 case Assignment::A_PAR_TEMPL_OUT
:
3249 case Assignment::A_PAR_TEMPL_INOUT
:
3250 if (expected_value
!= EXPECTED_TEMPLATE
) {
3251 value
->error("Reference to a value was expected instead of %s",
3252 ass
->get_description().c_str());
3256 case Assignment::A_FUNCTION_RVAL
:
3259 case Assignment::A_EXT_FUNCTION_RVAL
:
3260 switch (expected_value
) {
3261 case EXPECTED_CONSTANT
:
3262 value
->error("Reference to a constant value was expected instead of "
3263 "the return value of %s",
3264 ass
->get_description().c_str());
3267 case EXPECTED_STATIC_VALUE
:
3268 value
->error("Reference to a static value was expected instead of "
3269 "the return value of %s",
3270 ass
->get_description().c_str());
3277 case Assignment::A_FUNCTION_RTEMP
:
3280 case Assignment::A_EXT_FUNCTION_RTEMP
:
3281 if (expected_value
!= EXPECTED_TEMPLATE
) {
3282 value
->error("Reference to a value was expected instead of a call of "
3283 "%s, which returns a template",
3284 ass
->get_description().c_str());
3288 case Assignment::A_FUNCTION
:
3289 case Assignment::A_EXT_FUNCTION
:
3290 value
->error("Reference to a %s was expected instead of a call of %s, "
3291 "which does not have return type",
3292 expected_value
== EXPECTED_TEMPLATE
3293 ? "value or template" : "value",
3294 ass
->get_description().c_str());
3295 value
->set_valuetype(Value::V_ERROR
);
3298 value
->error("Reference to a %s was expected instead of %s",
3299 expected_value
== EXPECTED_TEMPLATE
3300 ? "value or template" : "value",
3301 ass
->get_description().c_str());
3302 value
->set_valuetype(Value::V_ERROR
);
3304 } // switch ass->get_asstype()
3306 ref
->get_my_scope()->chk_runs_on_clause(ass
, *ref
, "call");
3308 governor
= ass
->get_Type()->get_field_type(ref
->get_subrefs(),
3311 value
->set_valuetype(Value::V_ERROR
);
3314 TypeCompatInfo
info(value
->get_my_scope()->get_scope_mod(), this,
3315 governor
, true, false);
3316 info
.set_str1_elem(str_elem
);
3317 if (ref
->get_subrefs()) info
.set_str2_elem(ref
->get_subrefs()->refers_to_string_element());
3320 if (!is_compatible(governor
, &info
, &l_chain
, &r_chain
)) {
3321 // Port or signature values do not exist at all. These errors are
3322 // already reported at those definitions. Extra errors should not be
3324 Type
*t
= get_type_refd_last();
3325 switch (t
->typetype
) {
3327 // Neither port values nor templates exist.
3330 // Only signature templates may exist.
3331 if (expected_value
== EXPECTED_TEMPLATE
)
3332 value
->error("Type mismatch: a signature template of type `%s' was "
3333 "expected instead of `%s'", get_typename().c_str(),
3334 governor
->get_typename().c_str());
3337 if (info
.is_subtype_error()) {
3338 value
->error("%s", info
.get_subtype_error().c_str());
3339 } else if (!info
.is_erroneous()) {
3340 value
->error("Type mismatch: a %s of type `%s' was expected "
3341 "instead of `%s'", expected_value
== EXPECTED_TEMPLATE
3342 ? "value or template" : "value",
3343 get_typename().c_str(),
3344 governor
->get_typename().c_str());
3346 // The semantic error was found by the new code. It was better to
3347 // do the assembly inside TypeCompatInfo.
3348 value
->error("%s", info
.get_error_str_str().c_str());
3354 if (info
.needs_conversion()) value
->set_needs_conversion();
3358 value
->set_valuetype(Value::V_ERROR
);
3361 // Checking for circular references.
3362 Value
*v_last
= value
->get_value_refd_last(refch
, expected_value
);
3363 if (is_const
&& v_last
->get_valuetype() != Value::V_ERROR
) {
3364 // If a referenced universal charstring value points to a literal
3365 // charstring then drop the reference and create a literal ustring to
3366 // avoid run-time conversion.
3367 if (v_last
->get_valuetype() == Value::V_CSTR
3368 && get_typetype_ttcn3(get_type_refd_last()->typetype
) == T_USTR
)
3369 value
->set_valuetype(Value::V_USTR
);
3370 // Check v_last against the subtype constraints.
3371 if (sub_type
!=NULL
) sub_type
->chk_this_value(value
);
3377 void Type::chk_this_invoked_value(Value
*value
, Common::Assignment
*,
3378 expected_value_t expected_value
)
3380 value
->get_value_refd_last(NULL
, expected_value
);
3381 if (value
->get_valuetype() == Value::V_ERROR
) return;
3382 Type
*invoked_t
= value
->get_invoked_type(expected_value
);
3383 if (invoked_t
->get_typetype() == T_ERROR
) return;
3384 invoked_t
= invoked_t
->get_type_refd_last();
3386 switch (invoked_t
->get_typetype()) {
3387 case Type::T_FUNCTION
:
3388 t
= invoked_t
->get_function_return_type();
3391 FATAL_ERROR("Type::chk_this_invoked_value()");
3395 value
->error("The type `%s' has no return type, `%s' expected",
3396 invoked_t
->get_typename().c_str(), get_typename().c_str());
3397 else if (!is_compatible(t
, NULL
)) {
3398 value
->error("Incompatible value: `%s' value was expected",
3399 get_typename().c_str());
3403 void Type::chk_this_value_Null(Value
*value
)
3405 Value
*v
=value
->get_value_refd_last();
3406 switch(v
->get_valuetype()) {
3410 value
->error("NULL value was expected");
3411 value
->set_valuetype(Value::V_ERROR
);
3416 void Type::chk_this_value_Bool(Value
*value
)
3418 Value
*v
=value
->get_value_refd_last();
3419 switch(v
->get_valuetype()) {
3423 value
->error("%s value was expected",
3424 value
->is_asn1() ? "BOOLEAN" : "boolean");
3425 value
->set_valuetype(Value::V_ERROR
);
3430 void Type::chk_this_value_Int(Value
*value
)
3432 Value
*v
=value
->get_value_refd_last();
3433 switch(v
->get_valuetype()) {
3437 value
->error("integer value was expected");
3438 value
->set_valuetype(Value::V_ERROR
);
3444 void Type::chk_this_value_Int_A(Value
*value
)
3446 Value
*v
=value
->get_value_refd_last();
3447 switch(v
->get_valuetype()) {
3450 case Value::V_NAMEDINT
:
3451 if(!u
.namednums
.nvs
)
3452 FATAL_ERROR("Type::chk_this_value_Int_A()");
3454 (Value::V_INT
, u
.namednums
.nvs
->
3455 get_nv_byName(*v
->get_val_id())->get_value()->get_val_Int()->get_val());
3458 value
->error("INTEGER value was expected");
3459 value
->set_valuetype(Value::V_ERROR
);
3464 void Type::chk_this_value_Real(Value
*value
)
3466 Value
*v
= value
->get_value_refd_last();
3467 if (value
->is_asn1()) {
3468 if (value
->is_ref()) {
3469 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3470 if (t
->get_typetype() != T_REAL
) {
3471 value
->error("REAL value was expected");
3472 value
->set_valuetype(Value::V_ERROR
);
3476 switch (v
->get_valuetype()) {
3479 case Value::V_UNDEF_BLOCK
:{
3480 v
->set_valuetype(Value::V_SEQ
);
3481 Identifier
t_id(Identifier::ID_ASN
, string("REAL"));
3482 bool self_ref
= get_my_scope()->get_scope_asss()->get_local_ass_byId(t_id
)
3483 ->get_Type()->chk_this_value(v
, 0, EXPECTED_CONSTANT
, INCOMPLETE_NOT_ALLOWED
,
3484 OMIT_NOT_ALLOWED
, SUB_CHK
);
3486 v
->set_valuetype(Value::V_REAL
);
3489 v
->set_valuetype(Value::V_REAL
);
3492 value
->error("REAL value was expected");
3493 value
->set_valuetype(Value::V_ERROR
);
3497 switch(v
->get_valuetype()) {
3501 value
->error("float value was expected");
3502 value
->set_valuetype(Value::V_ERROR
);
3508 void Type::chk_this_value_Enum(Value
*value
)
3510 switch(value
->get_valuetype()) {
3514 value
->error("%s value was expected",
3515 value
->is_asn1() ? "ENUMERATED" : "enumerated");
3516 value
->set_valuetype(Value::V_ERROR
);
3521 void Type::chk_this_value_BStr(Value
*value
)
3523 Value
*v
= value
->get_value_refd_last();
3524 switch(v
->get_valuetype()) {
3528 value
->error("bitstring value was expected");
3529 value
->set_valuetype(Value::V_ERROR
);
3534 void Type::chk_this_value_namedbits(Value
*value
)
3536 if (!value
) FATAL_ERROR("Type::chk_this_value_namedbits()");
3537 value
->set_valuetype(Value::V_NAMEDBITS
);
3538 if(!u
.namednums
.nvs
) {
3539 value
->error("No named bits are defined in type `%s'",
3540 get_typename().c_str());
3541 value
->set_valuetype(Value::V_ERROR
);
3544 string
*bstring
= new string("");
3545 for(size_t i
=0; i
< value
->get_nof_ids(); i
++) {
3546 Identifier
*id
= value
->get_id_byIndex(i
);
3547 if(!u
.namednums
.nvs
->has_nv_withName(*id
)) {
3549 error("No named bit with name `%s' is defined in type `%s'",
3550 id
->get_dispname().c_str(), get_typename().c_str());
3551 value
->set_valuetype(Value::V_ERROR
);
3554 size_t bitnum
= static_cast<size_t>
3555 (u
.namednums
.nvs
->get_nv_byName(*id
)->get_value()->get_val_Int()
3557 if(bstring
->size() < bitnum
+ 1) bstring
->resize(bitnum
+ 1, '0');
3558 (*bstring
)[bitnum
] = '1';
3560 value
->set_valuetype(Value::V_BSTR
, bstring
);
3563 void Type::chk_this_value_BStr_A(Value
*value
)
3565 Value
*v
= value
->get_value_refd_last();
3566 if (value
->is_asn1()) {
3567 if(value
->is_ref()) {
3568 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3569 if(t
->get_typetype()!=T_BSTR_A
&& t
->get_typetype()!=T_BSTR
) {
3570 value
->error("(reference to) BIT STRING value was expected");
3571 value
->set_valuetype(Value::V_ERROR
);
3575 switch(v
->get_valuetype()) {
3579 if (v
!= value
) FATAL_ERROR("Common::Type::chk_this_value_BStr_A()");
3580 v
->set_valuetype(Value::V_BSTR
);
3582 case Value::V_UNDEF_BLOCK
:
3583 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_BStr_A()");
3584 chk_this_value_namedbits(v
);
3587 value
->error("BIT STRING value was expected");
3588 value
->set_valuetype(Value::V_ERROR
);
3592 switch(v
->get_valuetype()) {
3596 value
->error("bitstring value was expected");
3597 value
->set_valuetype(Value::V_ERROR
);
3603 void Type::chk_this_value_HStr(Value
*value
)
3605 Value
*v
= value
->get_value_refd_last();
3606 switch (v
->get_valuetype()) {
3610 value
->error("hexstring value was expected");
3611 value
->set_valuetype(Value::V_ERROR
);
3616 void Type::chk_this_value_OStr(Value
*value
)
3618 Value
*v
= value
->get_value_refd_last();
3619 if (value
->is_asn1()) {
3620 if (value
->is_ref()) {
3621 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3622 if(t
->get_typetype() != T_OSTR
) {
3623 value
->error("(reference to) OCTET STRING value was expected");
3624 value
->set_valuetype(Value::V_ERROR
);
3628 switch(v
->get_valuetype()) {
3633 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_OStr()");
3634 v
->set_valuetype(Value::V_OSTR
);
3637 value
->error("OCTET STRING value was expected");
3638 value
->set_valuetype(Value::V_ERROR
);
3642 switch(v
->get_valuetype()) {
3646 value
->error("octetstring value was expected");
3647 value
->set_valuetype(Value::V_ERROR
);
3653 /** \todo enhance */
3654 void Type::chk_this_value_CStr(Value
*value
)
3657 switch(value
->get_valuetype()) {
3658 case Value::V_UNDEF_BLOCK
:
3659 value
->set_valuetype(Value::V_CHARSYMS
);
3660 if (value
->get_valuetype() == Value::V_ERROR
) return;
3662 case Value::V_CHARSYMS
:
3667 case T_UNIVERSALSTRING
:
3668 value
->set_valuetype(Value::V_USTR
);
3670 case T_TELETEXSTRING
:
3671 case T_VIDEOTEXSTRING
:
3672 case T_GRAPHICSTRING
:
3673 case T_OBJECTDESCRIPTOR
:
3674 case T_GENERALSTRING
:
3675 value
->set_valuetype(Value::V_ISO2022STR
);
3678 case T_NUMERICSTRING
:
3679 case T_PRINTABLESTRING
:
3681 case T_VISIBLESTRING
:
3683 case T_GENERALIZEDTIME
:
3684 value
->set_valuetype(Value::V_CSTR
);
3687 FATAL_ERROR("chk_this_value_CStr()");
3695 case T_UNIVERSALSTRING
:
3697 case T_TELETEXSTRING
:
3698 case T_VIDEOTEXSTRING
:
3699 case T_GRAPHICSTRING
:
3700 case T_OBJECTDESCRIPTOR
:
3701 case T_GENERALSTRING
:
3704 if(value->get_val_ustr().is_cstr()) {
3705 value->warning("ISO-2022 string value was expected (converting"
3706 " simple ISO-10646 string).");
3707 value->set_valuetype(Value::V_CSTR);
3710 value->error("ISO-2022 string value was expected (instead of"
3711 " ISO-10646 string).");
3712 value->set_valuetype(Value::V_ERROR);
3717 case T_NUMERICSTRING
:
3718 case T_PRINTABLESTRING
:
3720 case T_VISIBLESTRING
:
3722 case T_GENERALIZEDTIME
:
3723 value
->set_valuetype(Value::V_CSTR
);
3726 FATAL_ERROR("Type::chk_this_value_CStr()");
3734 case T_UNIVERSALSTRING
:
3735 value
->set_valuetype(Value::V_USTR
);
3737 case T_TELETEXSTRING
:
3738 case T_VIDEOTEXSTRING
:
3739 case T_GRAPHICSTRING
:
3740 case T_OBJECTDESCRIPTOR
:
3741 case T_GENERALSTRING
:
3742 value
->set_valuetype(Value::V_ISO2022STR
);
3745 case T_NUMERICSTRING
:
3746 case T_PRINTABLESTRING
:
3748 case T_VISIBLESTRING
:
3750 case T_GENERALIZEDTIME
:
3753 FATAL_ERROR("chk_this_value_CStr()");
3756 case Value::V_ISO2022STR
:
3761 case T_UNIVERSALSTRING
:
3762 value
->error("ISO-10646 string value was expected (instead of"
3763 " ISO-2022 string).");
3764 value
->set_valuetype(Value::V_ERROR
);
3766 case T_TELETEXSTRING
:
3767 case T_VIDEOTEXSTRING
:
3768 case T_GRAPHICSTRING
:
3769 case T_OBJECTDESCRIPTOR
:
3770 case T_GENERALSTRING
:
3773 case T_NUMERICSTRING
:
3774 case T_PRINTABLESTRING
:
3776 case T_VISIBLESTRING
:
3778 case T_GENERALIZEDTIME
:
3779 value
->set_valuetype(Value::V_ISO2022STR
);
3782 FATAL_ERROR("chk_this_value_CStr()");
3786 value
->error("character string value was expected");
3787 value
->set_valuetype(Value::V_ERROR
);
3792 void Type::chk_this_value_OID(Value
*value
)
3794 Value
*v
= value
->get_value_refd_last();
3795 if (value
->is_asn1()) {
3796 if (value
->is_ref()) {
3797 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3798 if (t
->get_typetype() != T_OID
) {
3799 value
->error("(reference to) OBJECT IDENTIFIER value was "
3801 value
->set_valuetype(Value::V_ERROR
);
3805 switch (v
->get_valuetype()) {
3808 case Value::V_UNDEF_BLOCK
:
3809 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_OID()");
3810 v
->set_valuetype(Value::V_OID
);
3814 value
->error("OBJECT IDENTIFIER value was expected");
3815 value
->set_valuetype(Value::V_ERROR
);
3819 switch (v
->get_valuetype()) {
3824 value
->error("objid value was expected");
3825 value
->set_valuetype(Value::V_ERROR
);
3831 void Type::chk_this_value_ROID(Value
*value
)
3833 Value
*v
= value
->get_value_refd_last();
3834 if(value
->is_ref()) {
3835 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3836 if (t
->get_typetype() != T_ROID
) {
3837 value
->error("(reference to) RELATIVE-OID value was expected");
3838 value
->set_valuetype(Value::V_ERROR
);
3842 switch(v
->get_valuetype()) {
3845 case Value::V_UNDEF_BLOCK
:
3846 if (v
!= value
) FATAL_ERROR("Type::chk_this_value_ROID()");
3847 v
->set_valuetype(Value::V_ROID
);
3851 value
->error("RELATIVE-OID value was expected");
3852 value
->set_valuetype(Value::V_ERROR
);
3857 void Type::chk_this_value_Any(Value
*value
)
3859 Value
*v
= value
->get_value_refd_last();
3860 if (value
->is_asn1()) {
3861 if (value
->is_ref()) {
3862 Type
*t
= v
->get_my_governor()->get_type_refd_last();
3863 if(t
->get_typetype()!=T_ANY
&& t
->get_typetype()!=T_OSTR
) {
3864 value
->error("(reference to) OCTET STRING or ANY type value"
3866 value
->set_valuetype(Value::V_ERROR
);
3870 switch(v
->get_valuetype()) {
3874 if (v
!=value
) FATAL_ERROR("Type::chk_this_value_Any()");
3875 v
->set_valuetype(Value::V_OSTR
);
3878 value
->error("ANY (OCTET STRING) value was expected");
3879 value
->set_valuetype(Value::V_ERROR
);
3884 switch(v
->get_valuetype()) {
3888 value
->error("octetstring value was expected for ASN ANY type");
3889 value
->set_valuetype(Value::V_ERROR
);
3895 /** Return a string containing the names of existing fields (components).
3897 * @param t a Type object
3898 * @return a string (l-value, temporary)
3899 * @pre t must be a sequence, choice, set, anytype, open type
3901 static string
actual_fields(Type
& t
) // alas, not even get_nof_comps() is const
3903 static const string
has_no(" has no ");
3904 size_t ncomps
= t
.get_nof_comps();
3905 const string
fields_or_comps(t
.is_asn1() ? "components" : "fields");
3907 string
msg("Valid ");
3908 msg
+= fields_or_comps
;
3910 msg
+= t
.get_comp_byIndex(0)->get_name().get_dispname();
3911 for (size_t ci
=1; ci
< ncomps
; ++ci
) {
3913 msg
+= t
.get_comp_byIndex(ci
)->get_name().get_dispname();
3917 else return t
.get_fullname() + has_no
+ fields_or_comps
;
3921 bool Type::chk_this_value_Choice(Value
*value
, Common::Assignment
*lhs
,
3922 expected_value_t expected_value
, namedbool incomplete_allowed
, namedbool implicit_omit
)
3924 bool self_ref
= false;
3925 switch(value
->get_valuetype()) {
3927 if (value
->is_asn1()) {
3928 value
->error("CHOICE value was expected for type `%s'",
3929 get_fullname().c_str());
3930 value
->set_valuetype(Value::V_ERROR
);
3933 // the valuetype can be ERROR if the value has no fields at all
3934 if (value
->get_valuetype() == Value::V_ERROR
) return false;
3935 // The value notation for TTCN record/union types
3936 // cannot be distinguished during parsing. Now we know it's a union.
3937 value
->set_valuetype(Value::V_CHOICE
);
3940 case Value::V_CHOICE
: {
3941 const Identifier
& alt_name
= value
->get_alt_name();
3942 if(!has_comp_withName(alt_name
)) {
3943 if (value
->is_asn1()) {
3944 value
->error("Reference to non-existent alternative `%s' in CHOICE"
3945 " value for type `%s'",
3946 alt_name
.get_dispname().c_str(),
3947 get_fullname().c_str());
3949 value
->error("Reference to non-existent field `%s' in union "
3950 "value for type `%s'",
3951 alt_name
.get_dispname().c_str(),
3952 get_fullname().c_str());
3954 value
->set_valuetype(Value::V_ERROR
);
3955 value
->note("%s", actual_fields(*this).c_str());
3958 Type
*alt_type
= get_comp_byName(alt_name
)->get_type();
3959 Value
*alt_value
= value
->get_alt_value();
3960 Error_Context
cntxt(value
, "In value for %s `%s'",
3961 value
->is_asn1() ? "alternative" : "union field",
3962 alt_name
.get_dispname().c_str());
3963 alt_value
->set_my_governor(alt_type
);
3964 alt_type
->chk_this_value_ref(alt_value
);
3965 self_ref
|= alt_type
->chk_this_value(alt_value
, lhs
, expected_value
,
3966 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
3969 value
->error("%s value was expected for type `%s'",
3970 value
->is_asn1() ? "CHOICE" : "union",
3971 get_fullname().c_str());
3972 value
->set_valuetype(Value::V_ERROR
);
3978 bool Type::chk_this_value_Se(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3979 namedbool incomplete_allowed
, namedbool implicit_omit
)
3981 if (value
->is_asn1())
3982 return chk_this_value_Se_A(value
, lhs
, expected_value
, implicit_omit
);
3984 return chk_this_value_Se_T(value
, lhs
, expected_value
, incomplete_allowed
,
3988 bool Type::chk_this_value_Se_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
3989 namedbool incomplete_allowed
, namedbool implicit_omit
)
3991 switch (value
->get_valuetype()) {
3993 if (typetype
== T_SET_A
|| typetype
== T_SET_T
) {
3994 value
->set_valuetype(Value::V_SET
);
3995 return chk_this_value_Set_T(value
, lhs
, expected_value
, incomplete_allowed
,
3998 return chk_this_value_Seq_T(value
, lhs
, expected_value
, incomplete_allowed
,
4002 case Value::V_SEQOF
:
4003 if (typetype
== T_SET_A
|| typetype
== T_SET_T
) {
4004 if (value
->get_nof_comps() == 0) {
4005 if (get_nof_comps() == 0) {
4006 value
->set_valuetype(Value::V_SET
);
4008 value
->error("A non-empty set value was expected for type `%s'",
4009 get_fullname().c_str());
4010 value
->set_valuetype(Value::V_ERROR
);
4013 // This will catch the indexed assignment notation as well.
4014 value
->error("Value list notation cannot be used for "
4015 "%s type `%s'", typetype
== T_SET_A
? "SET" : "set",
4016 get_fullname().c_str());
4017 value
->set_valuetype(Value::V_ERROR
);
4020 if (value
->is_indexed()) {
4021 value
->error("Indexed assignment notation cannot be used for %s "
4022 "type `%s'", typetype
== T_SEQ_A
4023 ? "SEQUENCE" : "record",
4024 get_fullname().c_str());
4025 value
->set_valuetype(Value::V_ERROR
);
4027 value
->set_valuetype(Value::V_SEQ
);
4028 return chk_this_value_Seq_T(value
, lhs
, expected_value
, incomplete_allowed
,
4034 value
->error("%s value was expected for type `%s'",
4035 typetype
== T_SEQ_T
? "Record" : "Set",
4036 get_fullname().c_str());
4037 value
->set_valuetype(Value::V_ERROR
);
4043 bool Type::chk_this_value_Seq_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4044 namedbool incomplete_allowed
, namedbool implicit_omit
)
4046 bool self_ref
= false;
4047 map
<string
, NamedValue
> comp_map
;
4048 // it is set to false if we have lost the ordering
4049 bool in_synch
= true;
4050 const size_t n_type_comps
= get_nof_comps();
4051 size_t n_value_comps
= value
->get_nof_comps();
4052 // for incomplete values
4053 CompField
*last_cf
= 0;
4054 size_t next_index
= 0;
4055 size_t seq_index
= 0;
4056 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++, seq_index
++) {
4057 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4058 const Identifier
& value_id
= nv
->get_name();
4059 const string
& value_name
= value_id
.get_name();
4060 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4061 if (!has_comp_withName(value_id
)) {
4062 nv
->error("Reference to non-existent field `%s' in record value for "
4063 "type `%s'", value_dispname_str
, get_typename().c_str());
4064 nv
->note("%s", actual_fields(*this).c_str());
4067 } else if (comp_map
.has_key(value_name
)) {
4068 nv
->error("Duplicate record field `%s'", value_dispname_str
);
4069 comp_map
[value_name
]->note("Field `%s' is already given here",
4070 value_dispname_str
);
4072 } else comp_map
.add(value_name
, nv
);
4073 CompField
*cf
= get_comp_byName(value_id
);
4074 // check the ordering of fields
4076 if (incomplete_allowed
) {
4078 for (size_t i
= next_index
; i
< n_type_comps
; i
++) {
4079 CompField
*cf2
= get_comp_byIndex(i
);
4080 if (value_name
== cf2
->get_name().get_name()) {
4088 nv
->error("Field `%s' cannot appear after field `%s' in record "
4089 "value", value_dispname_str
,
4090 last_cf
->get_name().get_dispname().c_str());
4094 // the value must be complete unless implicit omit is set
4095 CompField
*cf2
= get_comp_byIndex(seq_index
);
4096 CompField
*cf2_orig
= cf2
;
4097 while (implicit_omit
&& seq_index
< n_type_comps
&& cf2
!= cf
&&
4098 cf2
->get_is_optional())
4099 cf2
= get_comp_byIndex(++seq_index
);
4100 if (seq_index
>= n_type_comps
|| cf2
!= cf
) {
4101 nv
->error("Unexpected field `%s' in record value, "
4102 "expecting `%s'", value_dispname_str
,
4103 cf2_orig
->get_name().get_dispname().c_str());
4108 Type
*type
= cf
->get_type();
4109 Value
*comp_value
= nv
->get_value();
4110 comp_value
->set_my_governor(type
);
4111 if (comp_value
->get_valuetype() == Value::V_NOTUSED
) {
4112 if (implicit_omit
) {
4113 comp_value
->set_valuetype(Value::V_OMIT
);
4118 Error_Context
cntxt(nv
, "In value for record field `%s'",
4119 value_dispname_str
);
4120 type
->chk_this_value_ref(comp_value
);
4121 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
, incomplete_allowed
,
4122 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4124 if (!incomplete_allowed
|| implicit_omit
) {
4125 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4126 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
4127 if (!comp_map
.has_key(id
.get_name())) {
4128 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
)
4129 value
->add_se_comp(new NamedValue(new Identifier(id
),
4130 new Value(Value::V_OMIT
)));
4131 else if (!incomplete_allowed
)
4132 value
->error("Field `%s' is missing from record value",
4133 id
.get_dispname().c_str());
4141 bool Type::chk_this_value_Set_T(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4142 namedbool incomplete_allowed
, namedbool implicit_omit
)
4144 bool self_ref
= false;
4145 map
<string
, NamedValue
> comp_map
;
4146 size_t n_type_comps
= get_nof_comps();
4147 size_t n_value_comps
= value
->get_nof_comps();
4148 for(size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4149 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4150 const Identifier
& value_id
= nv
->get_name();
4151 const string
& value_name
= value_id
.get_name();
4152 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4153 if (!has_comp_withName(value_id
)) {
4154 nv
->error("Reference to non-existent field `%s' in set value for "
4155 "type `%s'", value_dispname_str
, get_typename().c_str());
4156 nv
->note("%s", actual_fields(*this).c_str());
4158 } else if (comp_map
.has_key(value_name
)) {
4159 nv
->error("Duplicate set field `%s'", value_dispname_str
);
4160 comp_map
[value_name
]->note("Field `%s' is already given here",
4161 value_dispname_str
);
4162 } else comp_map
.add(value_name
, nv
);
4163 CompField
*cf
= get_comp_byName(value_id
);
4164 Type
*type
= cf
->get_type();
4165 Value
*comp_value
= nv
->get_value();
4166 comp_value
->set_my_governor(type
);
4167 if (comp_value
->get_valuetype() == Value::V_NOTUSED
) {
4168 if (implicit_omit
) {
4169 comp_value
->set_valuetype(Value::V_OMIT
);
4174 Error_Context
cntxt(nv
, "In value for set field `%s'",
4175 value_dispname_str
);
4176 type
->chk_this_value_ref(comp_value
);
4177 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
, incomplete_allowed
,
4178 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4180 if (!incomplete_allowed
|| implicit_omit
) {
4181 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4182 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
4183 if(!comp_map
.has_key(id
.get_name())) {
4184 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
)
4185 value
->add_se_comp(new NamedValue(new Identifier(id
),
4186 new Value(Value::V_OMIT
)));
4187 else if (!incomplete_allowed
)
4188 value
->error("Field `%s' is missing from set value %s",
4189 id
.get_dispname().c_str(), implicit_omit
? "yes" : "no");
4197 bool Type::chk_this_value_Se_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4198 namedbool implicit_omit
)
4200 if(value
->get_valuetype()==Value::V_UNDEF_BLOCK
) {
4201 if(typetype
== T_SEQ_A
) value
->set_valuetype(Value::V_SEQ
);
4202 else value
->set_valuetype(Value::V_SET
);
4204 switch(value
->get_valuetype()) {
4206 return chk_this_value_Seq_A(value
, lhs
, expected_value
, implicit_omit
);
4208 return chk_this_value_Set_A(value
, lhs
, expected_value
, implicit_omit
);
4210 value
->error("%s value was expected",
4211 typetype
== T_SEQ_A
? "SEQUENCE" : "SET");
4212 value
->set_valuetype(Value::V_ERROR
);
4218 bool Type::chk_this_value_Seq_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4219 namedbool implicit_omit
)
4221 bool self_ref
= false;
4222 map
<string
, NamedValue
> comp_map
;
4223 // it is set to false if we have lost the ordering
4224 bool in_synch
= true;
4225 size_t n_type_comps
= u
.secho
.ctss
->get_nof_comps();
4226 size_t n_value_comps
= value
->get_nof_comps();
4228 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4229 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4230 const Identifier
& value_id
= nv
->get_name();
4231 const string
& value_name
= value_id
.get_name();
4232 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4233 if (!u
.secho
.ctss
->has_comp_withName(value_id
)) {
4234 nv
->error("Reference to non-existent component `%s' of SEQUENCE "
4235 "type `%s'", value_dispname_str
, get_typename().c_str());
4236 nv
->note("%s", actual_fields(*this).c_str());
4239 } else if (comp_map
.has_key(value_name
)) {
4240 nv
->error("Duplicate SEQUENCE component `%s'", value_dispname_str
);
4241 comp_map
[value_name
]->note("Component `%s' is already given here",
4242 value_dispname_str
);
4244 } else comp_map
.add(value_name
, nv
);
4245 CompField
*cf
= u
.secho
.ctss
->get_comp_byName(value_id
);
4248 for ( ; t_i
< n_type_comps
; t_i
++) {
4249 cf2
= u
.secho
.ctss
->get_comp_byIndex(t_i
);
4250 if (cf2
== cf
|| (!cf2
->get_is_optional() && !cf2
->has_default() &&
4255 if (t_i
< n_type_comps
) {
4256 nv
->error("Unexpected component `%s' in SEQUENCE value, "
4257 "expecting `%s'", value_dispname_str
,
4258 cf2
->get_name().get_dispname().c_str());
4260 nv
->error("Unexpected component `%s' in SEQUENCE value",
4261 value_dispname_str
);
4266 Type
*type
= cf
->get_type();
4267 Error_Context
cntxt(nv
, "In value for SEQUENCE component `%s'",
4268 value_dispname_str
);
4269 Value
*comp_value
= nv
->get_value();
4270 comp_value
->set_my_governor(type
);
4271 type
->chk_this_value_ref(comp_value
);
4272 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4273 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4275 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4276 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4277 const Identifier
& id
= cf
->get_name();
4278 if (!comp_map
.has_key(id
.get_name())) {
4279 if (!cf
->get_is_optional() && !cf
->has_default())
4280 value
->error("Mandatory component `%s' is missing from SEQUENCE value",
4281 id
.get_dispname().c_str());
4282 else if (cf
->get_is_optional() && implicit_omit
)
4283 value
->add_se_comp(new NamedValue(new Identifier(id
),
4284 new Value(Value::V_OMIT
)));
4291 bool Type::chk_this_value_Set_A(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4292 namedbool implicit_omit
)
4294 bool self_ref
= false;
4295 map
<string
, NamedValue
> comp_map
;
4296 size_t n_type_comps
= u
.secho
.ctss
->get_nof_comps();
4297 size_t n_value_comps
= value
->get_nof_comps();
4298 for(size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4299 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4300 const Identifier
& value_id
= nv
->get_name();
4301 const string
& value_name
= value_id
.get_name();
4302 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4303 if (!u
.secho
.ctss
->has_comp_withName(value_id
)) {
4304 value
->error("Reference to non-existent component `%s' of SET type "
4305 "`%s'", value_dispname_str
, get_typename().c_str());
4306 nv
->note("%s", actual_fields(*this).c_str());
4308 } else if (comp_map
.has_key(value_name
)) {
4309 nv
->error("Duplicate SET component `%s'", value_dispname_str
);
4310 comp_map
[value_name
]->note("Component `%s' is already given here",
4311 value_dispname_str
);
4312 } else comp_map
.add(value_name
, nv
);
4314 u
.secho
.ctss
->get_comp_byName(value_id
)->get_type();
4315 Value
*comp_value
= nv
->get_value();
4316 Error_Context
cntxt(nv
, "In value for SET component `%s'",
4317 value_dispname_str
);
4318 comp_value
->set_my_governor(type
);
4319 type
->chk_this_value_ref(comp_value
);
4320 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4321 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4323 for (size_t i
= 0; i
< n_type_comps
; i
++) {
4324 CompField
*cf
= u
.secho
.ctss
->get_comp_byIndex(i
);
4325 const Identifier
& id
= cf
->get_name();
4326 if (!comp_map
.has_key(id
.get_name())) {
4327 if (!cf
->get_is_optional() && !cf
->has_default())
4328 value
->error("Mandatory component `%s' is missing from SET value",
4329 id
.get_dispname().c_str());
4330 else if (cf
->get_is_optional() && implicit_omit
)
4331 value
->add_se_comp(new NamedValue(new Identifier(id
),
4332 new Value(Value::V_OMIT
)));
4339 bool Type::chk_this_value_SeOf(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4340 namedbool incomplete_allowed
, namedbool implicit_omit
)
4342 bool self_ref
= false;
4343 const char *valuetypename
;
4344 if (value
->is_asn1()) {
4345 if (typetype
== T_SEQOF
) valuetypename
= "SEQUENCE OF";
4346 else valuetypename
= "SET OF";
4348 if (typetype
== T_SEQOF
) valuetypename
= "record of";
4349 else valuetypename
= "set of";
4351 if (value
->get_valuetype() == Value::V_UNDEF_BLOCK
) {
4352 if (typetype
== T_SEQOF
) value
->set_valuetype(Value::V_SEQOF
);
4353 else value
->set_valuetype(Value::V_SETOF
);
4355 switch (value
->get_valuetype()) {
4356 case Value::V_SEQOF
:
4357 if (typetype
== T_SETOF
) value
->set_valuetype(Value::V_SETOF
);
4359 case Value::V_SETOF
: {
4360 if (!value
->is_indexed()) {
4361 for (size_t i
= 0; i
< value
->get_nof_comps(); i
++) {
4362 Value
*v_comp
= value
->get_comp_byIndex(i
);
4363 Error_Context
cntxt(v_comp
, "In component #%lu",
4364 (unsigned long)(i
+ 1));
4365 v_comp
->set_my_governor(u
.seof
.ofType
);
4366 if (v_comp
->get_valuetype() == Value::V_NOTUSED
) {
4367 if (!incomplete_allowed
)
4368 v_comp
->error("Not used symbol `-' is not allowed in this "
4371 u
.seof
.ofType
->chk_this_value_ref(v_comp
);
4372 self_ref
|= u
.seof
.ofType
->chk_this_value(v_comp
, lhs
, expected_value
,
4373 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4377 // Only constant values with constant indicies can be checked at
4378 // compile time. Constant expressions evaluated.
4379 bool check_holes
= expected_value
== EXPECTED_CONSTANT
;
4381 map
<Int
, Int
> index_map
;
4382 for (size_t i
= 0; i
< value
->get_nof_comps(); i
++) {
4383 Error_Context
cntxt(this, "In component #%lu",
4384 (unsigned long)(i
+ 1));
4385 Value
*val
= value
->get_comp_byIndex(i
);
4386 Value
*index
= value
->get_index_byIndex(i
);
4387 index
->chk_expr_int(expected_value
);
4388 if (index
->get_valuetype() != Value::V_ERROR
&&
4389 index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
4390 const int_val_t
*index_int
= index
->get_value_refd_last()
4392 if (*index_int
> INT_MAX
) {
4393 index
->error("An integer value less than `%d' was expected for "
4394 "indexing type `%s' instead of `%s'", INT_MAX
,
4395 get_typename().c_str(),
4396 (index_int
->t_str()).c_str());
4397 index
->set_valuetype(Value::V_ERROR
);
4398 check_holes
= false;
4400 Int index_val
= index_int
->get_val();
4401 if (index_val
< 0) {
4402 index
->error("A non-negative integer value was expected for "
4403 "indexing type `%s' instead of `%s'",
4404 get_typename().c_str(),
4405 Int2string(index_val
).c_str());
4406 index
->set_valuetype(Value::V_ERROR
);
4407 check_holes
= false;
4408 } else if (index_map
.has_key(index_val
)) {
4409 index
->error("Duplicate index value `%s' for components `%s' "
4410 "and `%s'", Int2string(index_val
).c_str(),
4411 Int2string((Int
)i
+ 1).c_str(),
4412 Int2string(*index_map
[index_val
]).c_str());
4413 index
->set_valuetype(Value::V_ERROR
);
4414 check_holes
= false;
4416 index_map
.add(index_val
, new Int((Int
)i
+ 1));
4417 if (max_index
< index_val
)
4418 max_index
= index_val
;
4422 // The index cannot be determined.
4423 check_holes
= false;
4425 val
->set_my_governor(u
.seof
.ofType
);
4426 u
.seof
.ofType
->chk_this_value_ref(val
);
4427 self_ref
|= u
.seof
.ofType
->chk_this_value(val
, lhs
, expected_value
,
4428 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
);
4431 if ((size_t)max_index
!= index_map
.size() - 1) {
4432 value
->error("It's not allowed to create hole(s) in constant "
4434 value
->set_valuetype(Value::V_ERROR
);
4437 for (size_t i
= 0; i
< index_map
.size(); i
++)
4438 delete index_map
.get_nth_elem(i
);
4443 value
->error("%s value was expected", valuetypename
);
4444 value
->set_valuetype(Value::V_ERROR
);
4450 void Type::chk_this_value_Verdict(Value
*value
)
4452 Value
*v
= value
->get_value_refd_last();
4453 switch (v
->get_valuetype()) {
4454 case Value::V_VERDICT
:
4457 value
->error("verdict value was expected");
4458 value
->set_valuetype(Value::V_ERROR
);
4463 /** \todo enhance to handle activate */
4464 void Type::chk_this_value_Default(Value
*value
)
4466 switch (value
->get_valuetype()) {
4467 case Value::V_TTCN3_NULL
:
4468 value
->set_valuetype(Value::V_DEFAULT_NULL
);
4471 value
->error("default value was expected");
4472 value
->set_valuetype(Value::V_ERROR
);
4477 bool Type::chk_this_value_Array(Value
*value
, Common::Assignment
*lhs
, expected_value_t expected_value
,
4478 namedbool incomplete_allowed
, namedbool implicit_omit
)
4480 bool self_ref
= false;
4481 switch (value
->get_valuetype()) {
4482 case Value::V_SEQOF
:
4483 value
->set_valuetype(Value::V_ARRAY
);
4485 case Value::V_ARRAY
: {
4486 size_t n_value_comps
= value
->get_nof_comps();
4487 Ttcn::ArrayDimension
*dim
= u
.array
.dimension
;
4488 if (!value
->is_indexed()) {
4489 // Value-list notation.
4490 if (!dim
->get_has_error()) {
4491 size_t array_size
= dim
->get_size();
4492 if (array_size
!= n_value_comps
)
4493 value
->error("Too %s elements in the array value: %lu was "
4494 "expected instead of %lu",
4495 array_size
> n_value_comps
? "few" : "many",
4496 (unsigned long)array_size
,
4497 (unsigned long)n_value_comps
);
4499 for (size_t i
= 0; i
< n_value_comps
; i
++) {
4500 Error_Context
cntxt(this, "In array element %lu",
4501 (unsigned long)(i
+ 1));
4502 Value
*v_comp
= value
->get_comp_byIndex(i
);
4503 v_comp
->set_my_governor(u
.array
.element_type
);
4504 if (v_comp
->get_valuetype() == Value::V_NOTUSED
) {
4505 if (!incomplete_allowed
)
4506 v_comp
->error("Not used symbol `-' is not allowed in this "
4509 u
.array
.element_type
->chk_this_value_ref(v_comp
);
4510 self_ref
|= u
.array
.element_type
->chk_this_value(v_comp
, lhs
,
4511 expected_value
, incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
,
4516 // Indexed-list notation.
4517 bool array_size_known
= !dim
->get_has_error();
4518 bool check_holes
= array_size_known
4519 && expected_value
== EXPECTED_CONSTANT
;
4520 size_t array_size
= 0;
4521 if (array_size_known
) array_size
= dim
->get_size();
4522 map
<Int
, Int
> index_map
;
4523 for (size_t i
= 0; i
< n_value_comps
; i
++) {
4524 Error_Context
cntxt(this, "In array element #%lu",
4525 (unsigned long)(i
+ 1));
4526 Value
*val
= value
->get_comp_byIndex(i
);
4527 Value
*index
= value
->get_index_byIndex(i
);
4528 dim
->chk_index(index
, expected_value
);
4529 if (index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
4530 const int_val_t
*index_int
= index
->get_value_refd_last()
4532 if (*index_int
> INT_MAX
) {
4533 index
->error("An integer value less than `%d' was expected for "
4534 "indexing type `%s' instead of `%s'", INT_MAX
,
4535 get_typename().c_str(),
4536 (index_int
->t_str()).c_str());
4537 index
->set_valuetype(Value::V_ERROR
);
4538 check_holes
= false;
4540 // Index overflows/underflows are already checked by
4541 // ArrayDimensions::chk_index() at this point. The only thing
4542 // we need to check is the uniqueness of constant index values.
4543 Int index_val
= index_int
->get_val();
4544 if (index_map
.has_key(index_val
)) {
4545 index
->error("Duplicate index value `%s' for components `%s' "
4546 "and `%s'", Int2string(index_val
).c_str(),
4547 Int2string((Int
)i
+ 1).c_str(),
4548 Int2string(*index_map
[index_val
]).c_str());
4549 index
->set_valuetype(Value::V_ERROR
);
4550 check_holes
= false;
4552 index_map
.add(index_val
, new Int((Int
)i
+ 1));
4556 check_holes
= false;
4558 val
->set_my_governor(u
.array
.element_type
);
4559 u
.array
.element_type
->chk_this_value_ref(val
);
4560 self_ref
|= u
.array
.element_type
->chk_this_value(val
, lhs
, expected_value
,
4561 incomplete_allowed
, OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
);
4564 if (index_map
.size() < array_size
) {
4565 // It's a constant array assigned with constant index values. The
4566 // # of constant index values doesn't reach the size of the array.
4567 value
->error("It's not allowed to create hole(s) in constant "
4569 value
->set_valuetype(Value::V_ERROR
);
4572 for (size_t i
= 0; i
< index_map
.size(); i
++)
4573 delete index_map
.get_nth_elem(i
);
4578 value
->error("array value was expected");
4579 value
->set_valuetype(Value::V_ERROR
);
4586 bool Type::chk_this_value_Signature(Value
*value
, Common::Assignment
*lhs
,
4587 expected_value_t expected_value
,
4588 namedbool incomplete_allowed
)
4590 bool self_ref
= false;
4591 switch(value
->get_valuetype()) {
4592 case Value::V_SEQOF
:
4593 value
->set_valuetype(Value::V_SEQ
);
4596 map
<string
, NamedValue
> comp_map
;
4597 // it is set to false if we have lost the ordering
4598 bool in_synch
= true;
4599 size_t n_type_comps
= get_nof_comps();
4600 size_t n_value_comps
= value
->get_nof_comps();
4601 // for incomplete values
4602 CompField
*last_cf
= 0;
4603 size_t next_index
= 0;
4604 for (size_t v_i
= 0; v_i
< n_value_comps
; v_i
++) {
4605 NamedValue
*nv
= value
->get_se_comp_byIndex(v_i
);
4606 const Identifier
& value_id
= nv
->get_name();
4607 const string
& value_name
= value_id
.get_name();
4608 const char *value_dispname_str
= value_id
.get_dispname().c_str();
4609 if (!has_comp_withName(value_id
)) {
4610 nv
->error("Reference to non-existent parameter `%s' in signature value for "
4611 "type `%s'", value_dispname_str
, get_typename().c_str());
4614 } else if (comp_map
.has_key(value_name
)) {
4615 nv
->error("Duplicate signature parameter `%s'", value_dispname_str
);
4616 comp_map
[value_name
]->note("Parameter `%s' is already given here",
4617 value_dispname_str
);
4619 } else comp_map
.add(value_name
, nv
);
4620 CompField
*cf
= get_comp_byName(value_id
);
4621 // check the ordering of fields
4623 if (incomplete_allowed
) {
4625 for (size_t i
= next_index
; i
< n_type_comps
; i
++) {
4626 CompField
*cf2
= get_comp_byIndex(i
);
4627 if (value_name
== cf2
->get_name().get_name()) {
4635 nv
->error("Field `%s' cannot appear after parameter `%s' in signature "
4636 "value", value_dispname_str
,
4637 last_cf
->get_name().get_dispname().c_str());
4641 // the value must be complete
4642 CompField
*cf2
= get_comp_byIndex(v_i
);
4644 nv
->error("Unexpected field `%s' in record value, "
4645 "expecting `%s'", value_dispname_str
,
4646 cf2
->get_name().get_dispname().c_str());
4651 Type
*type
= cf
->get_type();
4652 Value
*comp_value
= nv
->get_value();
4653 comp_value
->set_my_governor(type
);
4654 Error_Context
cntxt(nv
, "In value for signature parameter `%s'",
4655 value_dispname_str
);
4656 type
->chk_this_value_ref(comp_value
);
4657 self_ref
|= type
->chk_this_value(comp_value
, lhs
, expected_value
,
4658 INCOMPLETE_NOT_ALLOWED
,
4659 cf
->get_is_optional() ? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
, SUB_CHK
);
4661 if (!incomplete_allowed
) {
4662 for (size_t i
= 0; i
< u
.signature
.parameters
->get_nof_in_params(); i
++) {
4663 const Identifier
& id
= get_comp_byIndex(i
)->get_name(); //u.signature.parameters->get_param_byIndex(n)
4664 if (!comp_map
.has_key(id
.get_name()) && SignatureParam::PARAM_OUT
!= u
.signature
.parameters
->get_in_param_byIndex(i
)->get_direction()) {
4665 value
->error("Field `%s' is missing from signature value",
4666 id
.get_dispname().c_str());
4673 value
->error("Signature value was expected for type `%s'",
4674 get_fullname().c_str());
4675 value
->set_valuetype(Value::V_ERROR
);
4682 /** \todo enhance to handle mtc, system, etc. */
4683 void Type::chk_this_value_Component(Value
*value
)
4685 switch (value
->get_valuetype()) {
4686 case Value::V_TTCN3_NULL
:
4687 value
->set_valuetype_COMP_NULL();
4690 if (value
->get_optype() == Value::OPTYPE_COMP_NULL
)
4691 break; // set_valuetype_COMP_NULL was called already
4694 value
->error("component reference value was expected");
4695 value
->set_valuetype(Value::V_ERROR
);
4700 void Type::chk_this_value_FAT(Value
*value
)
4702 switch (value
->get_valuetype()) {
4703 case Value::V_TTCN3_NULL
:
4704 value
->set_valuetype(Value::V_FAT_NULL
);
4706 case Value::V_REFER
:
4709 case Value::V_FUNCTION
:
4710 case Value::V_ALTSTEP
:
4711 case Value::V_TESTCASE
:
4712 case Value::V_FAT_NULL
:
4713 // This function (chk_this_value_FAT) might have transformed the value
4714 // from V_REFER or V_TTCN3_NULL to one of these. Return now,
4715 // otherwise spurious errors are generated.
4720 value
->error("Reference to a function or external function was "
4724 value
->error("Reference to an altstep was expected");
4727 value
->error("Reference to a testcase was expected");
4730 FATAL_ERROR("Type::chk_this_value_FAT()");
4732 value
->set_valuetype(Value::V_ERROR
);
4734 } // switch valuetype
4736 // Here value->valuetype is V_REFER
4737 Assignment
*t_ass
= value
->get_refered()->get_refd_assignment(false);
4739 value
->set_valuetype(Value::V_ERROR
);
4743 // check whether refers() points to the right definition
4744 Assignment::asstype_t t_asstype
= t_ass
->get_asstype();
4747 switch (t_asstype
) {
4748 case Assignment::A_FUNCTION
:
4749 case Assignment::A_FUNCTION_RVAL
:
4750 case Assignment::A_FUNCTION_RTEMP
:
4751 case Assignment::A_EXT_FUNCTION
:
4752 case Assignment::A_EXT_FUNCTION_RVAL
:
4753 case Assignment::A_EXT_FUNCTION_RTEMP
:
4754 value
->set_valuetype(Value::V_FUNCTION
, t_ass
);
4757 value
->error("Reference to a function or external function was "
4758 "expected instead of %s", t_ass
->get_description().c_str());
4759 value
->set_valuetype(Value::V_ERROR
);
4764 if (t_ass
->get_asstype() == Assignment::A_ALTSTEP
) {
4765 value
->set_valuetype(Value::V_ALTSTEP
, t_ass
);
4768 value
->error("Reference to an altstep was expected instead of %s",
4769 t_ass
->get_description().c_str());
4770 value
->set_valuetype(Value::V_ERROR
);
4774 if (t_ass
->get_asstype() == Assignment::A_TESTCASE
) {
4775 value
->set_valuetype(Value::V_TESTCASE
, t_ass
);
4778 value
->error("Reference to a testcase was expected instead of %s",
4779 t_ass
->get_description().c_str());
4780 value
->set_valuetype(Value::V_ERROR
);
4784 FATAL_ERROR("Type::chk_this_value_FAT()");
4786 // comparison of formal parameter lists
4788 Error_Context
cntxt(value
, "In comparing formal parameter lists of "
4789 "type `%s' and %s", get_typename().c_str(),
4790 t_ass
->get_description().c_str());
4791 u
.fatref
.fp_list
->chk_compatibility(t_ass
->get_FormalParList(),
4792 get_typename().c_str());
4794 // comparison of 'runs on' clauses
4795 Type
*t_runs_on_type
= t_ass
->get_RunsOnType();
4796 if (t_runs_on_type
) {
4797 if (u
.fatref
.runs_on
.self
) {
4798 if (u
.fatref
.runs_on
.ref
) {
4799 FATAL_ERROR("Type::chk_this_value_FAT()");
4800 } else { // "runs on self" case
4801 // check against the runs on component type of the scope of the value
4802 Scope
* value_scope
= value
->get_my_scope();
4803 if (!value_scope
) FATAL_ERROR("Type::chk_this_value_FAT()");
4804 Ttcn::RunsOnScope
*t_ros
= value_scope
->get_scope_runs_on();
4806 Type
*scope_comptype
= t_ros
->get_component_type();
4807 if (!t_runs_on_type
->is_compatible(scope_comptype
, NULL
)) {
4808 value
->error("Runs on clause mismatch: type `%s' has a "
4809 "'runs on self' clause and the current scope expects component "
4810 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4811 scope_comptype
->get_typename().c_str(),
4812 t_ass
->get_description().c_str(),
4813 t_runs_on_type
->get_typename().c_str());
4815 } else { // does not have 'runs on' clause
4816 // if the value's scope is a component body then check the runs on
4817 // compatibility using this component type as the scope
4818 ComponentTypeBody
* ct_body
=
4819 dynamic_cast<ComponentTypeBody
*>(value_scope
);
4821 if (!t_runs_on_type
->is_compatible(ct_body
->get_my_type(), NULL
)) {
4822 value
->error("Runs on clause mismatch: type `%s' has a "
4823 "'runs on self' clause and the current component definition "
4824 "is of type `%s', but %s runs on `%s'",
4825 get_typename().c_str(),
4826 ct_body
->get_my_type()->get_typename().c_str(),
4827 t_ass
->get_description().c_str(),
4828 t_runs_on_type
->get_typename().c_str());
4831 value
->error("Type `%s' has a 'runs on self' clause and the "
4832 "current scope does not have a 'runs on' clause, "
4833 "but %s runs on `%s'", get_typename().c_str(),
4834 t_ass
->get_description().c_str(),
4835 t_runs_on_type
->get_typename().c_str());
4840 if (u
.fatref
.runs_on
.ref
) {
4841 if (u
.fatref
.runs_on
.type
&&
4842 !t_runs_on_type
->is_compatible(u
.fatref
.runs_on
.type
, NULL
)) {
4843 value
->error("Runs on clause mismatch: type `%s' expects component "
4844 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4845 u
.fatref
.runs_on
.type
->get_typename().c_str(),
4846 t_ass
->get_description().c_str(),
4847 t_runs_on_type
->get_typename().c_str());
4850 value
->error("Type `%s' does not have 'runs on' clause, but %s runs "
4851 "on `%s'", get_typename().c_str(), t_ass
->get_description().c_str(),
4852 t_runs_on_type
->get_typename().c_str());
4856 if (typetype
== T_TESTCASE
) {
4857 // comparison of system clauses
4858 Ttcn::Def_Testcase
*t_testcase
= dynamic_cast<Ttcn::Def_Testcase
*>(t_ass
);
4859 if (!t_testcase
) FATAL_ERROR("Type::chk_this_value_FAT()");
4860 Type
*t_system_type
= t_testcase
->get_SystemType();
4861 // if the system clause is missing we shall examine the component type
4862 // that is given in the 'runs on' clause
4863 if (!t_system_type
) t_system_type
= t_runs_on_type
;
4864 Type
*my_system_type
=
4865 u
.fatref
.system
.ref
? u
.fatref
.system
.type
: u
.fatref
.runs_on
.type
;
4866 if (t_system_type
&& my_system_type
&&
4867 !t_system_type
->is_compatible(my_system_type
, NULL
)) {
4868 value
->error("System clause mismatch: testcase type `%s' expects "
4869 "component type `%s', but %s has `%s'", get_typename().c_str(),
4870 my_system_type
->get_typename().c_str(),
4871 t_ass
->get_description().c_str(),
4872 t_system_type
->get_typename().c_str());
4874 } else if (typetype
== T_FUNCTION
) {
4875 // comparison of return types
4876 bool t_returns_template
= false;
4877 switch (t_asstype
) {
4878 case Assignment::A_FUNCTION
:
4879 case Assignment::A_EXT_FUNCTION
:
4880 if (u
.fatref
.return_type
) {
4881 value
->error("Type `%s' expects a function or external function "
4882 "that returns a %s of type `%s', but %s does not have return type",
4883 get_typename().c_str(),
4884 u
.fatref
.returns_template
? "template" : "value",
4885 u
.fatref
.return_type
->get_typename().c_str(),
4886 t_ass
->get_description().c_str());
4889 case Assignment::A_FUNCTION_RTEMP
:
4890 case Assignment::A_EXT_FUNCTION_RTEMP
: {
4891 // comparison of template restrictions
4892 Ttcn::Def_Function_Base
* dfb
=
4893 dynamic_cast<Ttcn::Def_Function_Base
*>(t_ass
);
4894 if (!dfb
) FATAL_ERROR("Type::chk_this_value_FAT()");
4895 template_restriction_t refd_tr
= dfb
->get_template_restriction();
4896 if (refd_tr
!=u
.fatref
.template_restriction
) {
4897 value
->error("Type `%s' expects a function or external function "
4898 "that returns a template with %s restriction, "
4899 "but %s returns a template with %s restriction",
4900 get_typename().c_str(),
4901 u
.fatref
.template_restriction
==TR_NONE
? "no" :
4902 Template::get_restriction_name(u
.fatref
.template_restriction
),
4903 t_ass
->get_description().c_str(),
4904 refd_tr
==TR_NONE
? "no" : Template::get_restriction_name(refd_tr
));
4907 t_returns_template
= true;
4909 case Assignment::A_FUNCTION_RVAL
:
4910 case Assignment::A_EXT_FUNCTION_RVAL
:
4911 if (u
.fatref
.return_type
) {
4912 Type
*t_return_type
= t_ass
->get_Type();
4913 if (!u
.fatref
.return_type
->is_identical(t_return_type
)) {
4914 value
->error("Return type mismatch: type `%s' expects a function "
4915 "or external function that returns a %s of type `%s', but %s "
4916 "returns a %s of type `%s'", get_typename().c_str(),
4917 u
.fatref
.returns_template
? "template" : "value",
4918 u
.fatref
.return_type
->get_typename().c_str(),
4919 t_ass
->get_description().c_str(),
4920 t_returns_template
? "template" : "value",
4921 t_return_type
->get_typename().c_str());
4922 } else if (u
.fatref
.return_type
->get_sub_type() && t_return_type
->get_sub_type() &&
4923 (u
.fatref
.return_type
->get_sub_type()->get_subtypetype()==t_return_type
->get_sub_type()->get_subtypetype()) &&
4924 (!u
.fatref
.return_type
->get_sub_type()->is_compatible(t_return_type
->get_sub_type()))) {
4925 // TODO: maybe equivalence should be checked, or maybe that is too strict
4926 value
->error("Return type subtype mismatch: subtype %s has no common value with subtype %s",
4927 u
.fatref
.return_type
->get_sub_type()->to_string().c_str(),
4928 t_return_type
->get_sub_type()->to_string().c_str());
4929 } else if (u
.fatref
.returns_template
!= t_returns_template
) {
4930 value
->error("Type `%s' expects a function or external function "
4931 "that returns a %s of type `%s', but %s returns a %s",
4932 get_typename().c_str(),
4933 u
.fatref
.returns_template
? "template" : "value",
4934 u
.fatref
.return_type
->get_typename().c_str(),
4935 t_ass
->get_description().c_str(),
4936 t_returns_template
? "template" : "value");
4939 value
->error("Type `%s' expects a function or external function "
4940 "without return type, but %s returns a %s of type `%s'",
4941 get_typename().c_str(), t_ass
->get_description().c_str(),
4942 t_returns_template
? "template" : "value",
4943 t_ass
->get_Type()->get_typename().c_str());
4947 FATAL_ERROR("Type::chk_this_value_FAT()");
4952 void Type::chk_this_template_length_restriction(Template
*t
)
4954 Ttcn::LengthRestriction
*lr
= t
->get_length_restriction();
4955 if (!lr
) FATAL_ERROR("Type::chk_this_template_length_restriction()");
4956 // first check the length restriction itself
4957 lr
->chk(EXPECTED_DYNAMIC_VALUE
);
4959 /** \todo check lr against the length subtype constraint of this */
4960 get_type_refd()->chk_this_template_length_restriction(t
);
4963 typetype_t tt
= get_typetype_ttcn3(typetype
);
4967 // return silently, the type of the template is erroneous anyway
4970 lr
->chk_array_size(u
.array
.dimension
);
4979 // length restriction is allowed for these types
4982 lr
->error("Length restriction cannot be used in a template of type `%s'",
4983 get_typename().c_str());
4986 // check whether the number of elements in t is in accordance with lr
4987 Template
*t_last
= t
->get_template_refd_last();
4988 switch (t_last
->get_templatetype()) {
4989 case Ttcn::Template::OMIT_VALUE
:
4990 lr
->error("Length restriction cannot be used with omit value");
4992 case Ttcn::Template::SPECIFIC_VALUE
: {
4993 Value
*v_last
= t_last
->get_specific_value()->get_value_refd_last();
4994 switch (v_last
->get_valuetype()) {
4997 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5001 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5005 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5008 if (tt
== T_CSTR
|| tt
== T_USTR
)
5009 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5013 lr
->chk_nof_elements(v_last
->get_val_strlen(), false, *t
, "string");
5015 case Value::V_SEQOF
:
5017 lr
->chk_nof_elements(v_last
->get_nof_comps(), false, *t
, "value");
5019 case Value::V_SETOF
:
5021 lr
->chk_nof_elements(v_last
->get_nof_comps(), false, *t
, "value");
5023 // note: do not check array values
5024 // they are already verified against the array size
5026 lr
->error("Length restriction cannot be used with omit value");
5028 // we cannot verify anything on other value types
5029 // they are either correct or not applicable to the type
5033 case Ttcn::Template::TEMPLATE_LIST
:
5034 if (tt
== T_SEQOF
|| tt
== T_SETOF
)
5035 lr
->chk_nof_elements(t_last
->get_nof_comps_not_anyornone(),
5036 t_last
->temps_contains_anyornone_symbol(), *t
, "template");
5037 // note: do not check array templates
5038 // they are already verified against the array size
5040 case Ttcn::Template::SUPERSET_MATCH
:
5042 lr
->chk_nof_elements(t_last
->get_nof_comps_not_anyornone(), true,
5045 case Ttcn::Template::BSTR_PATTERN
:
5047 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5048 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5050 case Ttcn::Template::HSTR_PATTERN
:
5052 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5053 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5055 case Ttcn::Template::OSTR_PATTERN
:
5057 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5058 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5060 case Ttcn::Template::CSTR_PATTERN
:
5061 if (tt
== T_CSTR
|| tt
== T_USTR
)
5062 lr
->chk_nof_elements(t_last
->get_min_length_of_pattern(),
5063 t_last
->pattern_contains_anyornone_symbol(), *t
, "string");
5066 // We cannot verify anything on other matching mechanisms.
5067 // They are either correct or not applicable to the type.
5072 void Type::chk_this_template_ref(Template
*t
)
5074 switch (t
->get_templatetype()) {
5075 case Ttcn::Template::SPECIFIC_VALUE
: {
5076 // if (t->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE) return;
5077 Value
*v
= t
->get_specific_value();
5078 chk_this_value_ref(v
);
5079 switch (v
->get_valuetype()) {
5080 case Value::V_REFD
: {
5081 // Do not check the actual parameter list of the reference yet to avoid
5082 // endless recursion in case of embedded circular references.
5083 // The parameter lists will be verified later.
5084 Assignment
*ass
= v
->get_reference()->get_refd_assignment(false);
5086 switch (ass
->get_asstype()) {
5087 case Assignment::A_VAR_TEMPLATE
: {
5088 Type
* type
= ass
->get_Type();
5089 switch (type
->typetype
) {
5097 case T_NUMERICSTRING
:
5098 case T_PRINTABLESTRING
:
5099 case T_TELETEXSTRING
:
5100 case T_VIDEOTEXSTRING
:
5102 case T_GRAPHICSTRING
:
5103 case T_VISIBLESTRING
:
5104 case T_GENERALSTRING
:
5105 case T_UNIVERSALSTRING
:
5108 case T_GENERALIZEDTIME
:
5109 case T_OBJECTDESCRIPTOR
: {
5110 // TR 921 (indexing of template strings)
5111 Ttcn::FieldOrArrayRefs
*subrefs
= v
->get_reference()
5113 if (!subrefs
) break;
5114 size_t nof_subrefs
= subrefs
->get_nof_refs();
5115 if (nof_subrefs
> 0) {
5116 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
5117 ->get_ref(nof_subrefs
- 1);
5118 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
5119 t
->error("Reference to %s can not be indexed",
5120 (ass
->get_description()).c_str());
5121 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5130 case Assignment::A_MODULEPAR_TEMP
:
5131 case Assignment::A_TEMPLATE
:
5132 case Assignment::A_PAR_TEMPL_IN
:
5133 case Assignment::A_PAR_TEMPL_OUT
:
5134 case Assignment::A_PAR_TEMPL_INOUT
:
5135 case Assignment::A_FUNCTION_RTEMP
:
5136 case Assignment::A_EXT_FUNCTION_RTEMP
:
5137 t
->set_templatetype(Ttcn::Template::TEMPLATE_REFD
);
5141 } else t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5143 case Value::V_INVOKE
: {
5144 Type
*t2
= v
->get_invoked_type(Type::EXPECTED_TEMPLATE
);
5145 if(t2
&& t2
->get_type_refd_last()->get_returns_template())
5146 t
->set_templatetype(Ttcn::Template::TEMPLATE_INVOKE
);
5153 case Ttcn::Template::TEMPLATE_REFD
: {
5154 // Do not check the actual parameter list of the reference yet to avoid
5155 // endless recursion in case of embedded circular references.
5156 // The parameter lists will be verified later.
5157 Assignment
*ass
= t
->get_reference()->get_refd_assignment(false);
5159 switch (ass
->get_asstype()) {
5160 case Assignment::A_VAR_TEMPLATE
: {
5161 Type
* type
= ass
->get_Type();
5162 switch (type
->typetype
) {
5170 case T_NUMERICSTRING
:
5171 case T_PRINTABLESTRING
:
5172 case T_TELETEXSTRING
:
5173 case T_VIDEOTEXSTRING
:
5175 case T_GRAPHICSTRING
:
5176 case T_VISIBLESTRING
:
5177 case T_GENERALSTRING
:
5178 case T_UNIVERSALSTRING
:
5181 case T_GENERALIZEDTIME
:
5182 case T_OBJECTDESCRIPTOR
: {
5183 // TR 921 (indexing of template strings)
5184 Ttcn::FieldOrArrayRefs
*subrefs
= t
->get_reference()
5186 if (!subrefs
) break;
5187 size_t nof_subrefs
= subrefs
->get_nof_refs();
5188 if (nof_subrefs
> 0) {
5189 Ttcn::FieldOrArrayRef
*last_ref
= subrefs
5190 ->get_ref(nof_subrefs
- 1);
5191 if (last_ref
->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF
) {
5192 t
->error("Reference to %s can not be indexed",
5193 (ass
->get_description()).c_str());
5194 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5203 case Assignment::A_MODULEPAR_TEMP
:
5204 case Assignment::A_TEMPLATE
:
5205 case Assignment::A_PAR_TEMPL_IN
:
5206 case Assignment::A_PAR_TEMPL_OUT
:
5207 case Assignment::A_PAR_TEMPL_INOUT
:
5208 case Assignment::A_FUNCTION_RTEMP
:
5209 case Assignment::A_EXT_FUNCTION_RTEMP
:
5210 t
->set_templatetype(Ttcn::Template::TEMPLATE_REFD
);
5214 } else t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5222 bool Type::chk_this_template_ref_pard(Ttcn::Ref_pard
* ref_pard
, Common::Assignment
* lhs
)
5224 // Check if the reference on the left hand side of the assignment can be found
5225 // among the parameters
5226 Ttcn::ActualParList
* par_list
= ref_pard
->get_parlist();
5228 size_t nof_pars
= par_list
->get_nof_pars();
5229 for (size_t i
= 0; i
< nof_pars
; ++i
) {
5230 Ttcn::ActualPar
* par
= par_list
->get_par(i
);
5231 Ttcn::Ref_base
* par_ref
= 0;
5232 switch(par
->get_selection()) {
5233 case Ttcn::ActualPar::AP_TEMPLATE
: {
5234 Ttcn::TemplateInstance
* temp_ins
= par
->get_TemplateInstance();
5235 Ttcn::Template
* temp
= temp_ins
->get_Template();
5236 if (temp
->get_templatetype() == Ttcn::Template::TEMPLATE_REFD
) {
5237 par_ref
= temp
->get_reference();
5241 case Ttcn::ActualPar::AP_REF
: {
5242 par_ref
= par
->get_Ref();
5250 Common::Assignment
* ass
= par_ref
->get_refd_assignment(true); // also check parameters if there are any
5254 // In case a parameter is another function call / parametrised template
5255 // check their parameters as well
5256 if (ass
->get_asstype() == Assignment::A_FUNCTION_RTEMP
||
5257 ass
->get_asstype() == Assignment::A_EXT_FUNCTION_RTEMP
||
5258 ass
->get_asstype() == Assignment::A_TEMPLATE
) {
5259 ref_pard
= dynamic_cast<Ttcn::Ref_pard
*>(par_ref
);
5260 if (ref_pard
&& chk_this_template_ref_pard(ref_pard
, lhs
))
5269 bool Type::chk_this_template_generic(Template
*t
, namedbool incomplete_allowed
,
5270 namedbool allow_omit
, namedbool allow_any_or_omit
, namedbool sub_chk
,
5271 namedbool implicit_omit
, Common::Assignment
*lhs
)
5273 bool self_ref
= false;
5274 if (!allow_omit
&& t
->get_template_refd_last()->get_templatetype() ==
5275 Ttcn::Template::OMIT_VALUE
) {
5276 t
->error("`omit' value is not allowed in this context");
5278 if (!allow_any_or_omit
&& t
->get_template_refd_last()->get_templatetype() ==
5279 Ttcn::Template::ANY_OR_OMIT
) {
5280 t
->warning("Using `*' for mandatory field");
5283 Ttcn::Template::templatetype_t temptype
= t
->get_templatetype();
5285 case Ttcn::Template::TEMPLATE_ERROR
:
5287 case Ttcn::Template::TEMPLATE_NOTUSED
:
5288 case Ttcn::Template::OMIT_VALUE
:
5289 case Ttcn::Template::ANY_VALUE
:
5290 case Ttcn::Template::ANY_OR_OMIT
: {
5291 Type
*type
=get_type_refd_last();
5292 if (type
->get_typetype() == T_SIGNATURE
)
5293 t
->error("Generic wildcard `%s' cannot be used for signature `%s'",
5294 t
->get_templatetype_str(), type
->get_fullname().c_str());
5296 case Ttcn::Template::VALUE_LIST_ALL_FROM
:
5297 case Ttcn::Template::ALL_FROM
: {
5298 Ttcn::Template
*af
= t
->get_all_from();
5299 switch (af
->get_templatetype()) {
5300 case Ttcn::Template::SPECIFIC_VALUE
: {
5301 Value
*v
= af
->get_specific_value();
5302 v
->set_lowerid_to_ref();
5303 Reference
*ref
= v
->get_reference();
5304 Assignment
*ass
= ref
->get_refd_assignment(true); // also check parameters if there are any
5305 if (!ass
) break; // probably erroneous
5306 //warning("asstype %d", ass->get_asstype());
5308 switch (ass
->get_asstype()) {
5309 case Assignment::A_VAR
:
5310 case Assignment::A_PAR_VAL_IN
:
5311 case Assignment::A_PAR_VAL_INOUT
:
5312 case Assignment::A_MODULEPAR
:
5313 case Assignment::A_CONST
:
5314 case Assignment::A_MODULEPAR_TEMP
:
5315 break; // acceptable
5316 case Assignment::A_VAR_TEMPLATE
:
5317 case Assignment::A_PAR_TEMPL_IN
:
5318 case Assignment::A_PAR_TEMPL_INOUT
:
5321 break; // acceptable
5322 case Assignment::A_FUNCTION_RVAL
:
5323 case Assignment::A_EXT_FUNCTION_RVAL
:
5324 case Assignment::A_FUNCTION_RTEMP
:
5325 case Assignment::A_EXT_FUNCTION_RTEMP
:
5326 case Assignment::A_TEMPLATE
: {
5327 Ttcn::Ref_pard
* ref_pard
= dynamic_cast<Ttcn::Ref_pard
*>(ref
);
5329 self_ref
|= chk_this_template_ref_pard(ref_pard
, lhs
);
5330 break; // acceptable
5333 error("A %s cannot be used as the target of `all from'",
5334 ass
->get_assname());
5337 //self_ref |= chk_this_value(v, lhs, EXPECTED_TEMPLATE, incomplete_allowed,
5338 // allow_omit, sub_chk, implicit_omit, NOT_STR_ELEM /* ?? */);
5342 error("The target of an 'all from' must be a specific value template, not a %s",
5343 af
->get_templatetype_str());
5348 case Ttcn::Template::VALUE_LIST
:
5349 case Ttcn::Template::COMPLEMENTED_LIST
: {
5350 size_t nof_comps
= t
->get_nof_comps();
5351 for (size_t i
= 0; i
< nof_comps
; i
++) {
5352 Template
* t_comp
= t
->get_temp_byIndex(i
);
5353 Error_Context
cntxt(t
, "In list item %lu", (unsigned long) (i
+ 1));
5354 t_comp
->set_my_governor(this);
5355 chk_this_template_ref(t_comp
);
5356 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
5357 allow_omit
, ANY_OR_OMIT_ALLOWED
, sub_chk
, implicit_omit
, lhs
);
5358 if(temptype
==Ttcn::Template::COMPLEMENTED_LIST
&&
5359 t_comp
->get_template_refd_last()->get_templatetype() ==
5360 Ttcn::Template::ANY_OR_OMIT
)
5361 t_comp
->warning("`*' in complemented list."
5362 " This template will not match anything");
5365 case Ttcn::Template::SPECIFIC_VALUE
: {
5366 Value
*v
= t
->get_specific_value();
5367 v
->set_my_governor(this);
5368 self_ref
|= chk_this_value(v
, lhs
, EXPECTED_TEMPLATE
, incomplete_allowed
,
5369 allow_omit
, SUB_CHK
);
5371 case Ttcn::Template::TEMPLATE_INVOKE
: {
5373 Type
*governor
= t
->get_expr_governor(EXPECTED_DYNAMIC_VALUE
);
5375 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5376 else if (!is_compatible(governor
, NULL
)) {
5377 t
->error("Type mismatch: a value or template of type `%s' was "
5378 "expected instead of `%s'", get_typename().c_str(),
5379 governor
->get_typename().c_str());
5380 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5383 case Ttcn::Template::TEMPLATE_REFD
:
5384 self_ref
= chk_this_refd_template(t
, lhs
);
5387 self_ref
= chk_this_template(t
, incomplete_allowed
, sub_chk
, implicit_omit
, lhs
);
5390 if (t
->get_length_restriction()) chk_this_template_length_restriction(t
);
5391 if (!allow_omit
&& t
->get_ifpresent())
5392 t
->error("`ifpresent' is not allowed here");
5393 if(sub_chk
&& temptype
!= Ttcn::Template::PERMUTATION_MATCH
) {
5394 /* Note: A "permuation" itself has no type - it is just a fragment. */
5395 if(sub_type
!=NULL
) sub_type
->chk_this_template_generic(t
);
5401 bool Type::chk_this_refd_template(Template
*t
, Common::Assignment
*lhs
)
5403 if (t
->get_templatetype() != Template::TEMPLATE_REFD
) return false;
5404 Reference
*ref
= t
->get_reference();
5405 Assignment
*ass
= ref
->get_refd_assignment();
5406 if (!ass
) FATAL_ERROR("Type::chk_this_refd_template()");
5409 Type
*governor
= ass
->get_Type()
5410 ->get_field_type(ref
->get_subrefs(), EXPECTED_DYNAMIC_VALUE
);
5412 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5414 TypeCompatInfo
info(t
->get_my_scope()->get_scope_mod(), this, governor
,
5416 if (ref
->get_subrefs()) info
.set_str2_elem(ref
->get_subrefs()->refers_to_string_element());
5419 if (!is_compatible(governor
, &info
, &l_chain
, &r_chain
)) {
5420 Type
*type
= get_type_refd_last();
5421 switch (type
->typetype
) {
5423 // Port templates do not exist, remain silent.
5426 t
->error("Type mismatch: a signature template of type `%s' was "
5427 "expected instead of `%s'", get_typename().c_str(),
5428 governor
->get_typename().c_str());
5431 if (info
.is_subtype_error()) {
5432 t
->error("%s", info
.get_subtype_error().c_str());
5433 } else if (!info
.is_erroneous()) {
5434 t
->error("Type mismatch: a value or template of type `%s' was "
5435 "expected instead of `%s'", get_typename().c_str(),
5436 governor
->get_typename().c_str());
5438 t
->error("%s", info
.get_error_str_str().c_str());
5442 t
->set_templatetype(Ttcn::Template::TEMPLATE_ERROR
);
5444 // Detect circular references.
5445 t
->get_template_refd_last();
5447 if (info
.needs_conversion()) t
->set_needs_conversion();
5450 return (lhs
== ass
);
5453 bool Type::chk_this_template(Template
*t
, namedbool is_modified
, namedbool
,
5454 namedbool implicit_omit
, Common::Assignment
*lhs
)
5456 bool self_ref
= false;
5457 Type
*t_last
= get_type_refd_last();
5458 t
->set_my_governor(t_last
);
5460 switch(t_last
->typetype
) {
5471 t_last
->chk_this_template_builtin(t
);
5480 case T_NUMERICSTRING
:
5481 case T_PRINTABLESTRING
:
5482 case T_TELETEXSTRING
:
5483 case T_VIDEOTEXSTRING
:
5485 case T_GRAPHICSTRING
:
5486 case T_VISIBLESTRING
:
5487 case T_GENERALSTRING
:
5488 case T_UNIVERSALSTRING
:
5491 case T_GENERALIZEDTIME
:
5492 case T_OBJECTDESCRIPTOR
:
5493 t_last
->chk_this_template_Str(t
);
5498 t_last
->chk_this_template_Int_Real(t
);
5502 t_last
->chk_this_template_Enum(t
);
5508 self_ref
= t_last
->chk_this_template_Choice(t
, is_modified
, implicit_omit
, lhs
);
5512 self_ref
= t_last
->chk_this_template_Seq(t
, is_modified
, implicit_omit
, lhs
);
5516 self_ref
= t_last
->chk_this_template_Set(t
, is_modified
, implicit_omit
, lhs
);
5519 self_ref
= t_last
->chk_this_template_SeqOf(t
, is_modified
, implicit_omit
, lhs
);
5522 self_ref
= t_last
->chk_this_template_SetOf(t
, is_modified
, implicit_omit
, lhs
);
5525 self_ref
= t_last
->chk_this_template_array(t
, is_modified
, implicit_omit
, lhs
);
5528 t
->error("Template cannot be defined for port type `%s'",
5529 get_fullname().c_str());
5532 t_last
->chk_this_template_Signature(t
, is_modified
);
5537 t_last
->chk_this_template_Fat(t
);
5540 FATAL_ERROR("Type::chk_this_template()");
5545 void Type::chk_this_template_Str(Template
*t
)
5547 typetype_t tt
= get_typetype_ttcn3(typetype
);
5548 bool report_error
= false;
5549 switch (t
->get_templatetype()) {
5550 case Ttcn::Template::VALUE_RANGE
:
5551 if (tt
== T_CSTR
|| tt
== T_USTR
) {
5552 Error_Context
cntxt(t
, "In value range");
5553 Ttcn::ValueRange
*vr
= t
->get_value_range();
5554 Value
*v_lower
= chk_range_boundary(vr
->get_min_v(), "lower", *t
);
5555 Value
*v_upper
= chk_range_boundary(vr
->get_max_v(), "upper", *t
);
5556 if (v_lower
&& v_upper
) {
5557 // both boundaries are available and have correct type
5559 if (v_lower
->get_val_str() > v_upper
->get_val_str())
5560 t
->error("The lower boundary has higher character code than the "
5563 if (v_lower
->get_val_ustr() > v_upper
->get_val_ustr())
5564 t
->error("The lower boundary has higher character code than the "
5568 } else report_error
= true;
5570 case Ttcn::Template::BSTR_PATTERN
:
5571 if (tt
!= T_BSTR
) report_error
= true;
5573 case Ttcn::Template::HSTR_PATTERN
:
5574 if (tt
!= T_HSTR
) report_error
= true;
5576 case Ttcn::Template::OSTR_PATTERN
:
5577 if (tt
!= T_OSTR
) report_error
= true;
5579 case Ttcn::Template::CSTR_PATTERN
:
5581 Ttcn::PatternString
*pstr
= t
->get_cstr_pattern();
5582 Error_Context
cntxt(t
, "In character string pattern");
5584 pstr
->join_strings();
5585 if (!pstr
->has_refs()) pstr
->chk_pattern();
5587 } else if (tt
== T_USTR
) {
5588 t
->set_templatetype(Template::USTR_PATTERN
);
5589 t
->get_ustr_pattern()
5590 ->set_pattern_type(Ttcn::PatternString::USTR_PATTERN
);
5593 report_error
= true;
5597 case Ttcn::Template::USTR_PATTERN
:
5599 Ttcn::PatternString
*pstr
= t
->get_ustr_pattern();
5600 Error_Context
cntxt(t
, "In universal string pattern");
5602 pstr
->join_strings();
5603 if (!pstr
->has_refs()) pstr
->chk_pattern();
5604 } else report_error
= true;
5607 report_error
= true;
5611 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5612 get_typename().c_str());
5616 void Type::chk_range_boundary_infinity(Value
*v
, bool is_upper
)
5619 v
->set_my_governor(this);
5621 Error_Context
cntxt2(v
, "In %s boundary", is_upper
? "upper" : "lower");
5622 chk_this_value_ref(v
);
5623 Value
*v_last
= v
->get_value_refd_last(0, EXPECTED_STATIC_VALUE
);
5624 if (v_last
->get_valuetype() == Value::V_OMIT
) {
5625 v
->error("`omit' value is not allowed in this context");
5626 v
->set_valuetype(Value::V_ERROR
);
5629 if (sub_type
!= NULL
) {
5631 if (!sub_type
->get_root()->is_upper_limit_infinity()) {
5632 v
->error("Infinity is not a valid value for type '%s' which has subtype %s",
5633 asString(), sub_type
->to_string().c_str());
5637 if (!sub_type
->get_root()->is_lower_limit_infinity()) {
5638 v
->error("Infinity is not a valid value for type '%s' which has subtype %s",
5639 asString(), sub_type
->to_string().c_str());
5647 Value
*Type::chk_range_boundary(Value
*v
, const char *which
,
5648 const Location
& loc
)
5650 typetype_t tt
= get_typetype_ttcn3(typetype
);
5653 v
->set_my_governor(this);
5655 Error_Context
cntxt2(v
, "In %s boundary", which
);
5656 chk_this_value_ref(v
);
5657 chk_this_value(v
, 0, EXPECTED_DYNAMIC_VALUE
, INCOMPLETE_NOT_ALLOWED
,
5658 OMIT_NOT_ALLOWED
, SUB_CHK
);
5660 ret_val
= v
->get_value_refd_last();
5661 switch (ret_val
->get_valuetype()) {
5663 if (tt
!= T_INT
) ret_val
= 0;
5666 if (tt
!= T_REAL
) ret_val
= 0;
5669 if (tt
!= T_CSTR
) ret_val
= 0;
5672 if (tt
!= T_USTR
) ret_val
= 0;
5675 // unfoldable or erroneous
5679 if ((tt
== T_CSTR
|| tt
== T_USTR
) && ret_val
&&
5680 ret_val
->get_val_strlen() != 1) {
5681 v
->error("The %s boundary must be a %scharstring value containing a "
5682 "single character", which
, tt
== T_USTR
? "universal ": "");
5686 // the boundary is + or - infinity
5687 if (tt
== T_CSTR
|| tt
== T_USTR
) {
5688 loc
.error("The %s boundary must be a %scharstring value", which
,
5689 tt
== T_USTR
? "universal ": "");
5696 void Type::chk_this_template_builtin(Template
*t
)
5698 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5699 get_typename().c_str());
5700 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5701 "allowed for type `%s'", get_typename().c_str());
5704 void Type::chk_this_template_Int_Real(Template
*t
)
5706 switch (t
->get_templatetype()) {
5707 case Ttcn::Template::VALUE_RANGE
: {
5708 Error_Context
cntxt(t
, "In value range");
5709 Ttcn::ValueRange
*vr
= t
->get_value_range();
5710 Value
*v_lower
= chk_range_boundary(vr
->get_min_v(), "lower", *t
);
5711 Value
*v_upper
= chk_range_boundary(vr
->get_max_v(), "upper", *t
);
5712 if (v_lower
&& v_upper
) {
5713 // both boundaries are available and have correct type
5714 switch (get_typetype_ttcn3(typetype
)) {
5716 if (*v_lower
->get_val_Int() > *v_upper
->get_val_Int())
5717 t
->error("The lower boundary is higher than the upper boundary");
5720 if (v_lower
->get_val_Real() > v_upper
->get_val_Real())
5721 t
->error("The lower boundary is higher than the upper boundary");
5724 FATAL_ERROR("Type::chk_this_template_Int_Real()");
5727 if (v_lower
&& !v_upper
) {
5728 chk_range_boundary_infinity(v_lower
, true);
5730 if (!v_lower
&& v_upper
) {
5731 chk_range_boundary_infinity(v_upper
, false);
5735 t
->error("%s cannot be used for type `%s'", t
->get_templatetype_str(),
5736 get_typename().c_str());
5739 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5740 "allowed for type `%s'", get_typename().c_str());
5743 void Type::chk_this_template_Enum(Template
*t
)
5745 t
->error("%s cannot be used for enumerated type `%s'",
5746 t
->get_templatetype_str(), get_typename().c_str());
5747 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5748 "allowed for enumerated type `%s'", get_typename().c_str());
5751 bool Type::chk_this_template_Choice(Template
*t
, namedbool is_modified
,
5752 namedbool implicit_omit
, Common::Assignment
*lhs
)
5754 bool self_ref
= false;
5755 switch (t
->get_templatetype()) {
5756 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5757 size_t nof_nts
= t
->get_nof_comps();
5758 if (nof_nts
!= 1) t
->error("A template for union type must contain "
5759 "exactly one selected field");
5760 // We check all named templates, even though it is an error
5761 // to have more than one here.
5762 for (size_t i
= 0; i
< nof_nts
; i
++) {
5763 Ttcn::NamedTemplate
*nt
= t
->get_namedtemp_byIndex(i
);
5764 const Identifier
& nt_name
= nt
->get_name();
5766 if (!has_comp_withName(nt_name
)) {
5767 nt
->error("Reference to non-existent field `%s' in union "
5768 "template for type `%s'", nt_name
.get_dispname().c_str(),
5769 get_fullname().c_str());
5770 nt
->note("%s", actual_fields(*this).c_str());
5774 Type
*field_type
= get_comp_byName(nt_name
)->get_type();
5775 Template
*nt_templ
= nt
->get_template();
5777 Error_Context
cntxt(nt_templ
, "In template for union field `%s'",
5778 nt_name
.get_dispname().c_str());
5780 nt_templ
->set_my_governor(field_type
);
5781 field_type
->chk_this_template_ref(nt_templ
);
5782 bool incompl_ok
= t
->get_completeness_condition_choice(is_modified
, nt_name
) ==
5783 Ttcn::Template::C_MAY_INCOMPLETE
;
5784 self_ref
|= field_type
->chk_this_template_generic(nt_templ
,
5785 (incompl_ok
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
5786 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_NOT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
5790 t
->error("%s cannot be used for union type `%s'",
5791 t
->get_templatetype_str(), get_typename().c_str());
5794 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5795 "allowed for union type `%s'", get_typename().c_str());
5800 bool Type::chk_this_template_Seq(Template
*t
, namedbool is_modified
,
5801 namedbool implicit_omit
, Common::Assignment
*lhs
)
5803 bool self_ref
= false;
5804 size_t n_type_comps
= get_nof_comps();
5805 switch (t
->get_templatetype()) {
5806 case Ttcn::Template::TEMPLATE_LIST
:
5807 // conversion: value list -> assignment notation
5808 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
5810 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5811 map
<string
, Ttcn::NamedTemplate
> comp_map
;
5812 // it is set to false if we have lost the ordering
5813 bool in_synch
= true;
5814 size_t n_template_comps
= t
->get_nof_comps();
5815 // the two variables below are used for modified templates only
5816 CompField
*last_cf
= 0;
5817 size_t next_index
= 0;
5818 for (size_t i
= 0; i
< n_template_comps
; i
++) {
5819 Ttcn::NamedTemplate
*namedtemp
= t
->get_namedtemp_byIndex(i
);
5820 const Identifier
& temp_id
= namedtemp
->get_name();
5821 const string
& temp_name
= temp_id
.get_name();
5822 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
5823 if (!has_comp_withName(temp_id
)) {
5824 namedtemp
->error("Reference to non-existent field `%s' in record "
5825 "template for type `%s'", temp_dispname_str
,
5826 get_typename().c_str());
5827 namedtemp
->note("%s", actual_fields(*this).c_str());
5830 } else if (comp_map
.has_key(temp_name
)) {
5831 namedtemp
->error("Duplicate record field `%s' in template",
5833 comp_map
[temp_name
]->note("Field `%s' is already given here",
5836 } else comp_map
.add(temp_name
, namedtemp
);
5838 CompField
*cf
= get_comp_byName(temp_id
);
5841 // missing fields are allowed, but take care of ordering
5843 for (size_t j
= next_index
; j
< n_type_comps
; j
++) {
5844 CompField
*cf2
= get_comp_byIndex(j
);
5845 if (temp_name
== cf2
->get_name().get_name()) {
5853 namedtemp
->error("Field `%s' cannot appear after field `%s' in "
5854 "a template for record type `%s'", temp_dispname_str
,
5855 last_cf
->get_name().get_dispname().c_str(),
5856 get_fullname().c_str());
5860 // the template must be complete
5861 CompField
*cf2
= get_comp_byIndex(i
);
5863 if (!cf2
->get_is_optional() || !implicit_omit
) {
5864 namedtemp
->error("Unexpected field `%s' in record template, "
5865 "expecting `%s'", temp_dispname_str
,
5866 cf2
->get_name().get_dispname().c_str());
5872 Type
*type
= cf
->get_type();
5873 Template
*comp_t
= namedtemp
->get_template();
5874 Error_Context
cntxt(comp_t
, "In template for record field `%s'",
5876 comp_t
->set_my_governor(type
);
5877 type
->chk_this_template_ref(comp_t
);
5878 bool is_optional
= cf
->get_is_optional(); // || cf->has_default()
5879 self_ref
|= type
->chk_this_template_generic(comp_t
, is_modified
,
5880 (is_optional
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
),
5881 (is_optional
? ANY_OR_OMIT_ALLOWED
: ANY_OR_OMIT_NOT_ALLOWED
),
5882 SUB_CHK
, implicit_omit
, lhs
);
5884 if (!is_modified
|| implicit_omit
) {
5885 // check missing fields
5886 for (size_t i
= 0; i
< n_type_comps
; i
++) {
5887 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
5888 if (!comp_map
.has_key(id
.get_name())) {
5889 if (implicit_omit
&& get_comp_byIndex(i
)->get_is_optional()) {
5890 // do not overwrite base fields
5891 if (!t
->get_base_template())
5892 t
->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id
),
5893 new Template(Template::OMIT_VALUE
)));
5894 } else if (!is_modified
) {
5895 t
->error("Field `%s' is missing from template for record type `%s'",
5896 id
.get_dispname().c_str(), get_typename().c_str());
5904 t
->error("%s cannot be used for record type `%s'",
5905 t
->get_templatetype_str(), get_typename().c_str());
5908 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5909 "allowed for record type `%s'", get_typename().c_str());
5913 bool Type::chk_this_template_Set(Template
*t
,
5914 namedbool is_modified
, namedbool implicit_omit
, Common::Assignment
*lhs
)
5916 bool self_ref
= false;
5917 size_t n_type_comps
= get_nof_comps();
5918 switch (t
->get_templatetype()) {
5919 case Ttcn::Template::TEMPLATE_LIST
:
5920 if (t
->get_nof_comps() > 0) {
5921 t
->error("Value list notation is not allowed for set type `%s'",
5922 get_fullname().c_str());
5924 } else if (n_type_comps
> 0) {
5925 t
->error("A non-empty set template was expected for type `%s'",
5926 get_fullname().c_str());
5929 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
5931 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
5932 map
<string
, Ttcn::NamedTemplate
> comp_map
;
5933 size_t n_template_comps
= t
->get_nof_comps();
5934 for (size_t i
= 0; i
< n_template_comps
; i
++) {
5935 Ttcn::NamedTemplate
*namedtemp
= t
->get_namedtemp_byIndex(i
);
5936 const Identifier
& temp_id
=namedtemp
->get_name();
5937 const string
& temp_name
= temp_id
.get_name();
5938 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
5939 if (!has_comp_withName(temp_id
)) {
5940 namedtemp
->error("Reference to non-existent field `%s' in a "
5941 "template for set type `%s'", temp_dispname_str
,
5942 get_typename().c_str());
5943 namedtemp
->note("%s", actual_fields(*this).c_str());
5945 } else if (comp_map
.has_key(temp_name
)) {
5946 namedtemp
->error("Duplicate set field `%s' in template",
5948 comp_map
[temp_name
]->note("Field `%s' is already given here",
5950 } else comp_map
.add(temp_name
, namedtemp
);
5951 CompField
*cf
= get_comp_byName(temp_id
);
5952 Type
*type
= cf
->get_type();
5953 Template
*comp_t
= namedtemp
->get_template();
5954 Error_Context
cntxt(comp_t
, "In template for set field `%s'",
5956 comp_t
->set_my_governor(type
);
5957 type
->chk_this_template_ref(comp_t
);
5958 bool is_optional
= cf
->get_is_optional();
5959 self_ref
|= type
->chk_this_template_generic(comp_t
,
5960 (is_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
5961 (is_optional
? OMIT_ALLOWED
: OMIT_NOT_ALLOWED
),
5962 (is_optional
? ANY_OR_OMIT_ALLOWED
: ANY_OR_OMIT_NOT_ALLOWED
),
5963 SUB_CHK
, implicit_omit
, lhs
);
5965 if (!is_modified
|| implicit_omit
) {
5966 // check missing fields
5967 for (size_t i
= 0; i
< n_type_comps
; i
++) {
5968 const Identifier
& id
= get_comp_byIndex(i
)->get_name();
5969 if (!comp_map
.has_key(id
.get_name())) {
5970 if (get_comp_byIndex(i
)->get_is_optional() && implicit_omit
) {
5971 // do not overwrite base fields
5972 if (!t
->get_base_template())
5973 t
->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id
),
5974 new Template(Template::OMIT_VALUE
)));
5975 } else if (!is_modified
) {
5976 t
->error("Field `%s' is missing from template for set type `%s'",
5977 id
.get_dispname().c_str(), get_typename().c_str());
5985 t
->error("%s cannot be used for set type `%s'",
5986 t
->get_templatetype_str(), get_typename().c_str());
5989 if (t
->get_length_restriction()) t
->error("Length restriction is not "
5990 "allowed for set type `%s'", get_typename().c_str());
5994 bool Type::chk_this_template_SeqOf(Template
*t
, namedbool is_modified
,
5995 namedbool implicit_omit
, Common::Assignment
*lhs
)
5997 bool self_ref
= false;
5998 switch(t
->get_templatetype()) {
5999 case Ttcn::Template::OMIT_VALUE
:
6000 if(t
->get_length_restriction())
6001 t
->warning("Redundant usage of length restriction with `omit'");
6003 case Ttcn::Template::PERMUTATION_MATCH
: {
6004 size_t nof_comps
= t
->get_nof_comps();
6005 for (size_t i
= 0; i
< nof_comps
; i
++) {
6006 Template
*t_comp
= t
->get_temp_byIndex(i
);
6007 Error_Context
cntxt(t_comp
, "In element %lu of permutation",
6008 (unsigned long) (i
+ 1));
6009 t_comp
->set_my_governor(u
.seof
.ofType
);
6010 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6011 // the elements of permutation must be always complete
6012 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6013 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6014 NOT_IMPLICIT_OMIT
, lhs
);
6017 case Ttcn::Template::TEMPLATE_LIST
: {
6018 Ttcn::Template::completeness_t c
=
6019 t
->get_completeness_condition_seof(is_modified
);
6021 size_t nof_base_comps
;
6022 if (c
== Ttcn::Template::C_PARTIAL
) {
6023 t_base
= t
->get_base_template()->get_template_refd_last();
6024 // it is sure that t_base is a TEMPLATE_LIST
6025 nof_base_comps
= t_base
->get_nof_comps();
6030 size_t nof_comps
= t
->get_nof_comps();
6031 for(size_t i
= 0; i
< nof_comps
; i
++) {
6032 Template
*t_comp
= t
->get_temp_byIndex(i
);
6033 Error_Context
cntxt(t_comp
, "In component %lu", (unsigned long)(i
+1));
6034 t_comp
->set_my_governor(u
.seof
.ofType
);
6035 if (t_base
&& i
< nof_base_comps
)
6036 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6037 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6038 switch (t_comp
->get_templatetype()) {
6039 case Ttcn::Template::PERMUTATION_MATCH
:
6040 // the elements of permutation has to be checked by u.seof.ofType
6041 // the templates within the permutation always have to be complete
6042 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
6043 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6044 implicit_omit
, lhs
);
6046 case Ttcn::Template::TEMPLATE_NOTUSED
:
6047 if (c
== Ttcn::Template::C_MUST_COMPLETE
) {
6048 t_comp
->error("Not used symbol `-' is not allowed in this context");
6049 } else if (c
== Ttcn::Template::C_PARTIAL
&& i
>= nof_base_comps
) {
6050 t_comp
->error("Not used symbol `-' cannot be used here because "
6051 "there is no corresponding element in the base template");
6055 bool embedded_modified
= (c
== Ttcn::Template::C_MAY_INCOMPLETE
) ||
6056 (c
== Ttcn::Template::C_PARTIAL
&& i
< nof_base_comps
);
6057 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6058 (embedded_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6059 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6064 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6065 map
<Int
, Int
> index_map
;
6066 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6067 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6068 Value
*index_value
= (it
->get_index()).get_val();
6069 // The index value must be Type::EXPECTED_DYNAMIC_VALUE integer, but
6070 // it's not required to be known at compile time.
6071 index_value
->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
6072 Template
*it_comp
= it
->get_template();
6073 Error_Context
cntxt(it_comp
, "In component %lu",
6074 (unsigned long)(i
+ 1));
6075 if (index_value
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
6076 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6078 if (*index_int
> INT_MAX
) {
6079 index_value
->error("An integer value less than `%d' was expected "
6080 "for indexing type `%s' instead of `%s'", INT_MAX
,
6081 get_typename().c_str(), (index_int
->t_str()).c_str());
6082 index_value
->set_valuetype(Value::V_ERROR
);
6084 Int index
= index_int
->get_val();
6086 index_value
->error("A non-negative integer value was expected "
6087 "for indexing type `%s' instead of `%s'",
6088 get_typename().c_str(), Int2string(index
).c_str());
6089 index_value
->set_valuetype(Value::V_ERROR
);
6090 } else if (index_map
.has_key(index
)) {
6091 index_value
->error("Duplicate index value `%s' for components "
6092 "`%s' and `%s'", Int2string(index
).c_str(),
6093 Int2string((Int
)i
+ 1).c_str(),
6094 Int2string(*index_map
[index
]).c_str());
6095 index_value
->set_valuetype(Value::V_ERROR
);
6097 index_map
.add(index
, new Int((Int
)i
+ 1));
6101 it_comp
->set_my_governor(u
.seof
.ofType
);
6102 u
.seof
.ofType
->chk_this_template_ref(it_comp
);
6103 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(it_comp
,
6104 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6105 SUB_CHK
, implicit_omit
, lhs
);
6107 for (size_t i
= 0; i
< index_map
.size(); i
++)
6108 delete index_map
.get_nth_elem(i
);
6112 t
->error("%s cannot be used for `record of' type `%s'",
6113 t
->get_templatetype_str(), get_typename().c_str());
6119 bool Type::chk_this_template_SetOf(Template
*t
, namedbool is_modified
,
6120 namedbool implicit_omit
, Common::Assignment
*lhs
)
6122 bool self_ref
= false;
6123 Ttcn::Template::templatetype_t temptype
= t
->get_templatetype();
6125 case Ttcn::Template::OMIT_VALUE
:
6126 if(t
->get_length_restriction())
6127 t
->warning("Redundant usage of length restriction with `omit'");
6129 case Ttcn::Template::SUPERSET_MATCH
:
6130 case Ttcn::Template::SUBSET_MATCH
: {
6131 const char *settype
= temptype
== Ttcn::Template::SUPERSET_MATCH
?
6132 "superset" : "subset";
6133 size_t nof_comps
= t
->get_nof_comps();
6134 for (size_t i
= 0; i
< nof_comps
; i
++) {
6135 Template
*t_comp
= t
->get_temp_byIndex(i
);
6136 Error_Context
cntxt(t_comp
, "In element %lu of %s",
6137 (unsigned long) (i
+ 1), settype
);
6138 t_comp
->set_my_governor(u
.seof
.ofType
);
6139 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6140 // the elements of sets must be always complete
6141 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6142 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6143 SUB_CHK
, implicit_omit
, lhs
);
6144 if (t_comp
->get_template_refd_last()->get_templatetype() ==
6145 Ttcn::Template::ANY_OR_OMIT
) {
6146 if (temptype
== Ttcn::Template::SUPERSET_MATCH
)
6147 t_comp
->warning("`*' in superset has no effect during matching");
6148 else t_comp
->warning("`*' in subset. This template will match "
6153 case Ttcn::Template::TEMPLATE_LIST
: {
6154 Ttcn::Template::completeness_t c
=
6155 t
->get_completeness_condition_seof(is_modified
);
6157 size_t nof_base_comps
;
6158 if (c
== Ttcn::Template::C_PARTIAL
) {
6159 t_base
= t
->get_base_template()->get_template_refd_last();
6160 // it is sure that t_base is a TEMPLATE_LIST
6161 nof_base_comps
= t_base
->get_nof_comps();
6166 size_t nof_comps
= t
->get_nof_comps();
6167 for(size_t i
= 0; i
< nof_comps
; i
++) {
6168 Template
*t_comp
= t
->get_temp_byIndex(i
);
6169 Error_Context
cntxt(t_comp
, "In component %lu", (unsigned long)(i
+1));
6170 t_comp
->set_my_governor(u
.seof
.ofType
);
6171 if (t_base
&& i
< nof_base_comps
)
6172 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6173 u
.seof
.ofType
->chk_this_template_ref(t_comp
);
6174 switch (t_comp
->get_templatetype()) {
6175 case Ttcn::Template::PERMUTATION_MATCH
:
6176 t_comp
->error("%s cannot be used for `set of' type `%s'",
6177 t_comp
->get_templatetype_str(), get_typename().c_str());
6179 case Ttcn::Template::TEMPLATE_NOTUSED
:
6180 if (c
== Ttcn::Template::C_MUST_COMPLETE
) {
6181 t_comp
->error("Not used symbol `-' is not allowed in this context");
6182 } else if (c
== Ttcn::Template::C_PARTIAL
&& i
>= nof_base_comps
) {
6183 t_comp
->error("Not used symbol `-' cannot be used here because "
6184 "there is no corresponding element in the base template");
6188 bool embedded_modified
= (c
== Ttcn::Template::C_MAY_INCOMPLETE
) ||
6189 (c
== Ttcn::Template::C_PARTIAL
&& i
< nof_base_comps
);
6190 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(t_comp
,
6191 (embedded_modified
? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
6192 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6197 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6198 map
<Int
, Int
> index_map
;
6199 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6200 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6201 Value
*index_value
= (it
->get_index()).get_val();
6202 index_value
->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE
);
6203 Template
*it_comp
= it
->get_template();
6204 Error_Context
cntxt(it_comp
, "In component %lu",
6205 (unsigned long)(i
+ 1));
6206 if (index_value
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
6207 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6209 if (*index_int
> INT_MAX
) {
6210 index_value
->error("An integer value less than `%d' was expected "
6211 "for indexing type `%s' instead of `%s'", INT_MAX
,
6212 get_typename().c_str(), (index_int
->t_str()).c_str());
6213 index_value
->set_valuetype(Value::V_ERROR
);
6215 Int index
= index_int
->get_val();
6217 index_value
->error("A non-negative integer value was expected "
6218 "for indexing type `%s' instead of `%s'",
6219 get_typename().c_str(), Int2string(index
).c_str());
6220 index_value
->set_valuetype(Value::V_ERROR
);
6221 } else if (index_map
.has_key(index
)) {
6222 index_value
->error("Duplicate index value `%s' for components "
6223 "`%s' and `%s'", Int2string(index
).c_str(),
6224 Int2string((Int
)i
+ 1).c_str(),
6225 Int2string(*index_map
[index
]).c_str());
6226 index_value
->set_valuetype(Value::V_ERROR
);
6228 index_map
.add(index
, new Int((Int
)i
+ 1));
6232 it_comp
->set_my_governor(u
.seof
.ofType
);
6233 u
.seof
.ofType
->chk_this_template_ref(it_comp
);
6234 self_ref
|= u
.seof
.ofType
->chk_this_template_generic(it_comp
,
6235 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
,
6236 SUB_CHK
, implicit_omit
, lhs
);
6238 for (size_t i
= 0; i
< index_map
.size(); i
++)
6239 delete index_map
.get_nth_elem(i
);
6243 t
->error("%s cannot be used for `set of' type `%s'",
6244 t
->get_templatetype_str(), get_typename().c_str());
6250 bool Type::chk_this_template_array(Template
*t
, namedbool is_modified
,
6251 namedbool implicit_omit
, Common::Assignment
*lhs
)
6253 bool self_ref
= false;
6254 switch (t
->get_templatetype()) {
6255 case Ttcn::Template::OMIT_VALUE
:
6256 if (t
->get_length_restriction())
6257 t
->warning("Redundant usage of length restriction with `omit'");
6259 case Ttcn::Template::PERMUTATION_MATCH
: {
6260 size_t nof_comps
= t
->get_nof_comps();
6261 for (size_t i
= 0; i
< nof_comps
; i
++) {
6262 Template
*t_comp
= t
->get_temp_byIndex(i
);
6263 Error_Context
cntxt(t_comp
, "In element %lu of permutation",
6264 (unsigned long) (i
+ 1));
6265 t_comp
->set_my_governor(u
.array
.element_type
);
6266 u
.array
.element_type
->chk_this_template_ref(t_comp
);
6267 // the elements of permutation must be always complete
6268 self_ref
|= u
.array
.element_type
->chk_this_template_generic(t_comp
,
6269 INCOMPLETE_NOT_ALLOWED
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6270 NOT_IMPLICIT_OMIT
, lhs
);
6273 case Ttcn::Template::TEMPLATE_LIST
: {
6274 Template
*t_base
= t
->get_base_template();
6275 size_t nof_base_comps
= 0;
6277 t_base
= t_base
->get_template_refd_last();
6278 if (t_base
->get_templatetype() == Ttcn::Template::TEMPLATE_LIST
)
6279 nof_base_comps
= t_base
->get_nof_comps();
6280 else t_base
= 0; // error recovery
6282 if (!u
.array
.dimension
->get_has_error()) {
6283 size_t array_size
= u
.array
.dimension
->get_size();
6284 size_t template_size
= t
->get_nof_listitems();
6285 if (array_size
!= template_size
) {
6286 if (t
->is_flattened()){
6287 t
->error("Too %s elements in the array template: %lu was expected "
6289 array_size
> template_size
? "few" : "many",
6290 (unsigned long)array_size
, (unsigned long)template_size
);
6293 t
->warning("The size of template cannot be resolved "
6294 "so it could not be compared to the array size");
6298 size_t nof_comps
= t
->get_nof_comps();
6299 for (size_t i
= 0; i
< nof_comps
; i
++) {
6300 Template
*t_comp
= t
->get_temp_byIndex(i
);
6301 Error_Context
cntxt(t_comp
, "In array element %lu",
6302 (unsigned long)(i
+ 1));
6303 t_comp
->set_my_governor(u
.array
.element_type
);
6304 if (t_base
&& i
< nof_base_comps
)
6305 t_comp
->set_base_template(t_base
->get_temp_byIndex(i
));
6306 u
.array
.element_type
->chk_this_template_ref(t_comp
);
6307 switch (t_comp
->get_templatetype()) {
6308 case Ttcn::Template::PERMUTATION_MATCH
:
6309 // the elements of permutation has to be checked by u.seof.ofType
6310 // the templates within the permutation always have to be complete
6311 self_ref
|= chk_this_template_generic(t_comp
, INCOMPLETE_NOT_ALLOWED
,
6312 OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
6313 implicit_omit
, lhs
);
6315 case Ttcn::Template::TEMPLATE_NOTUSED
:
6317 t_comp
->error("Not used symbol `-' is not allowed in this "
6321 self_ref
|= u
.array
.element_type
->chk_this_template_generic(t_comp
,
6322 is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6327 case Ttcn::Template::INDEXED_TEMPLATE_LIST
: {
6328 map
<Int
, Int
> index_map
;
6329 for (size_t i
= 0; i
< t
->get_nof_comps(); i
++) {
6330 Ttcn::IndexedTemplate
*it
= t
->get_indexedtemp_byIndex(i
);
6331 Value
*index_value
= (it
->get_index()).get_val();
6332 u
.array
.dimension
->chk_index(index_value
,
6333 Type::EXPECTED_DYNAMIC_VALUE
);
6334 Template
*it_comp
= it
->get_template();
6335 Error_Context
cntxt(it_comp
, "In component %lu",
6336 (unsigned long)(i
+ 1));
6337 if (index_value
->get_value_refd_last()
6338 ->get_valuetype() == Value::V_INT
) {
6339 const int_val_t
*index_int
= index_value
->get_value_refd_last()
6341 if (*index_int
> INT_MAX
) {
6342 index_value
->error("An integer value less than `%d' was expected "
6343 "for indexing type `%s' instead of `%s'",
6344 INT_MAX
, get_typename().c_str(),
6345 (index_int
->t_str()).c_str());
6346 index_value
->set_valuetype(Value::V_ERROR
);
6348 Int index
= index_int
->get_val();
6349 if (index_map
.has_key(index
)) {
6350 index_value
->error("Duplicate index value `%s' for components "
6351 "`%s' and `%s'", Int2string(index
).c_str(),
6352 Int2string((Int
)i
+ 1).c_str(),
6353 Int2string(*index_map
[index
]).c_str());
6354 index_value
->set_valuetype(Value::V_ERROR
);
6356 index_map
.add(index
, new Int((Int
)i
+ 1));
6360 it_comp
->set_my_governor(u
.array
.element_type
);
6361 u
.array
.element_type
->chk_this_template_ref(it_comp
);
6362 self_ref
|= u
.array
.element_type
->chk_this_template_generic(it_comp
,
6363 is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, implicit_omit
, lhs
);
6365 for (size_t i
= 0; i
< index_map
.size(); i
++)
6366 delete index_map
.get_nth_elem(i
);
6370 t
->error("%s cannot be used for array type `%s'",
6371 t
->get_templatetype_str(), get_typename().c_str());
6377 void Type::chk_this_template_Fat(Template
*t
)
6379 t
->error("%s cannot be used for type `%s'",t
->get_templatetype_str(),
6380 get_typename().c_str());
6381 if(t
->get_length_restriction()) t
->error("Length restriction is not "
6382 "allowed for type `%s'", get_typename().c_str());
6385 void Type::chk_this_template_Signature(Template
*t
, namedbool is_modified
)
6387 bool self_ref
= false;
6388 size_t n_type_params
= get_nof_comps();
6389 switch (t
->get_templatetype()) {
6390 case Ttcn::Template::TEMPLATE_LIST
:
6391 // conversion: value list -> assignment notation
6392 t
->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST
);
6394 case Ttcn::Template::NAMED_TEMPLATE_LIST
: {
6395 map
<string
, Ttcn::NamedTemplate
> comp_map
;
6396 // it is set to false if we have lost the ordering
6397 bool in_synch
= true;
6398 size_t n_template_comps
= t
->get_nof_comps();
6400 for (size_t v_i
= 0; v_i
< n_template_comps
; v_i
++) {
6401 Ttcn::NamedTemplate
*nt
= t
->get_namedtemp_byIndex(v_i
);
6402 const Identifier
& temp_id
= nt
->get_name();
6403 const string
& temp_name
= temp_id
.get_name();
6404 const char *temp_dispname_str
= temp_id
.get_dispname().c_str();
6405 if (!has_comp_withName(temp_id
)) {
6406 nt
->error("Reference to non-existent parameter `%s' in template "
6407 "for signature `%s'", temp_dispname_str
, get_typename().c_str());
6410 } else if (comp_map
.has_key(temp_name
)) {
6411 nt
->error("Duplicate parameter `%s' in template for signature `%s'",
6412 temp_dispname_str
, get_typename().c_str());
6413 comp_map
[temp_name
]->note("Parameter `%s' is already given here",
6416 } else comp_map
.add(temp_name
, nt
);
6417 const SignatureParam
*par
=
6418 u
.signature
.parameters
->get_param_byName(temp_id
);
6420 SignatureParam
*par2
= 0;
6421 for ( ; t_i
< n_type_params
; t_i
++) {
6422 par2
= u
.signature
.parameters
->get_param_byIndex(t_i
);
6423 if (par2
== par
) break;
6426 nt
->error("Unexpected parameter `%s' in signature template",
6431 Type
*type
= par
->get_type();
6432 Template
*comp_t
= nt
->get_template();
6433 Error_Context
cntxt(comp_t
, "In template for signature parameter `%s'",
6435 comp_t
->set_my_governor(type
);
6436 type
->chk_this_template_ref(comp_t
);
6437 self_ref
|= type
->chk_this_template_generic(comp_t
, is_modified
, OMIT_NOT_ALLOWED
, ANY_OR_OMIT_NOT_ALLOWED
,
6438 SUB_CHK
, NOT_IMPLICIT_OMIT
, NULL
);
6441 SignatureParam
*first_undef_in
= NULL
,
6442 *first_undef_out
= NULL
;
6443 for (size_t i
= 0; i
< n_type_params
; i
++) {
6444 SignatureParam
*par
= u
.signature
.parameters
->get_param_byIndex(i
);
6445 const Identifier
& id
= par
->get_id();
6446 if (!comp_map
.has_key(id
.get_name()) ||
6447 comp_map
[id
.get_name()]->get_template()->get_templatetype() ==
6448 Template::TEMPLATE_NOTUSED
) {
6449 switch(par
->get_direction()) {
6450 case SignatureParam::PARAM_IN
:
6451 if(!first_undef_in
) first_undef_in
= par
;
6453 case SignatureParam::PARAM_OUT
:
6454 if(!first_undef_out
) first_undef_out
= par
;
6457 t
->error("Signature template is incomplete, because the inout "
6458 "parameter `%s' is missing", id
.get_dispname().c_str());
6462 if(first_undef_in
!=NULL
&& first_undef_out
!=NULL
)
6463 t
->error("Signature template is incomplete, because the in parameter "
6464 "`%s' and the out parameter `%s' is missing",
6465 first_undef_in
->get_id().get_dispname().c_str(),
6466 first_undef_out
->get_id().get_dispname().c_str());
6471 t
->error("%s cannot be used for signature `%s'",
6472 t
->get_templatetype_str(), get_typename().c_str());
6475 if (t
->get_length_restriction())
6476 t
->error("Length restriction is not allowed in a template for "
6477 "signature `%s'", get_typename().c_str());
6480 } // namespace Common