Update README.md
[deliverable/titan.core.git] / compiler2 / Type_chk.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
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"
9#include "Type.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"
16
17#include "Valuestuff.hh"
18#include "main.hh"
19
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"
26
27#include "asn1/Tag.hh"
28#include "XerAttributes.hh"
29
30#include <ctype.h>
31#include <stdlib.h> // for qsort
32#include <string.h>
33
34extern int rawAST_debug;
35
36namespace Common {
37
38using Ttcn::MultiWithAttrib;
39using Ttcn::SingleWithAttrib;
40using Ttcn::WithAttribPath;
41using Ttcn::Qualifier;
42using Ttcn::Qualifiers;
43
44void Type::chk()
45{
46 if(w_attrib_path) w_attrib_path->chk_global_attrib();
47 parse_attributes();
48 if(!tags_checked) {
49 tags_checked = true;
50 if(tags) tags->chk();
51 }
52 if (checked) return;
53 switch(typetype) {
54 case T_ERROR:
55 case T_NULL:
56 case T_BOOL:
57 case T_INT:
58 case T_REAL:
59 case T_BSTR:
60 case T_HSTR:
61 case T_OSTR:
62 case T_CSTR:
63 case T_USTR:
64 case T_UTF8STRING:
65 case T_NUMERICSTRING:
66 case T_PRINTABLESTRING:
67 case T_TELETEXSTRING:
68 case T_VIDEOTEXSTRING:
69 case T_IA5STRING:
70 case T_GRAPHICSTRING:
71 case T_VISIBLESTRING:
72 case T_GENERALSTRING:
73 case T_UNIVERSALSTRING:
74 case T_BMPSTRING:
75 case T_UTCTIME:
76 case T_GENERALIZEDTIME:
77 case T_OBJECTDESCRIPTOR:
78 case T_OID:
79 case T_ROID:
80 case T_ANY:
81 case T_EXTERNAL:
82 case T_EMBEDDED_PDV:
83 case T_UNRESTRICTEDSTRING:
84 case T_VERDICT:
85 case T_DEFAULT:
86 break;
87 case T_INT_A:
88 chk_Int_A();
89 break;
90 case T_ENUM_A:
91 chk_Enum_A();
92 break;
93 case T_ENUM_T:
94 chk_Enum_T();
95 break;
96 case T_BSTR_A:
97 chk_BStr_A();
98 break;
99 case T_OPENTYPE:
100 chk_SeCho_T();
101 break;
102 case T_ANYTYPE:
103 // TODO maybe check for address type and add it automagically, then fall through
104 case T_SEQ_T:
105 case T_SET_T:
106 case T_CHOICE_T:
107 chk_SeCho_T();
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;
3f84031e 116 if (!jsonattrib && (hasVariantAttrs() || hasEncodeAttr(get_encoding_name(CT_JSON)) || hasNeedofJsonAttrs())) {
970ed795
EL
117 jsonattrib = new JsonAST;
118 }
119 break;
120 case T_CHOICE_A:
121 chk_Choice_A();
122 // TODO create an empty XerAttrib as above, when ASN.1 gets XER ?
123 // The code was originally for TTCN-only encodings.
124 break;
125 case T_SEQ_A:
126 case T_SET_A:
127 chk_Se_A();
128 // TODO create an empty XerAttrib as above, when ASN.1 gets XER ?
129 break;
130 case T_SEQOF:
131 case T_SETOF:
132 chk_SeOf();
133 break;
134 case T_REFD:
135 case T_ADDRESS:
136 chk_refd();
137 break;
138 case T_SELTYPE:
139 chk_seltype();
140 break;
141 case T_REFDSPEC:
142 case T_OCFT:
143 u.ref.type_refd->chk();
144 u.ref.component_internal = u.ref.type_refd->is_component_internal();
145 break;
146 case T_ARRAY:
147 chk_Array();
148 break;
149 case T_PORT:
150 u.port->chk();
151 if (w_attrib_path) u.port->chk_attributes(w_attrib_path);
152 break;
153 case T_SIGNATURE:
154 chk_Signature();
155 break;
156 case T_COMPONENT:
157 u.component->chk();
158 break;
159 case T_FUNCTION:
160 case T_ALTSTEP:
161 case T_TESTCASE:
162 chk_Fat();
163 break;
164 default:
165 FATAL_ERROR("Type::chk()");
166 } // switch
167
168 if(w_attrib_path) {
169 switch (get_type_refd_last()->typetype) {
170 case T_SEQ_T:
171 case T_SET_T:
172 case T_CHOICE_T:
173 // These types may have qualified attributes
174 break;
175 case T_SEQOF: case T_SETOF:
176 break;
177 default:
178 w_attrib_path->chk_no_qualif();
179 break;
180 }
181 }
182 checked = true;
183 if(tags) tags->set_plicit(this);
184
185 /*
186 Check all non-table subtype constraints. Table/relational constraints
187 are ignored here.
188 TODO: non-relational table constraints shall not be ignored.
189 */
190 if (check_subtype) check_subtype_constraints();
191
192 /*
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
196 * components.
197 */
198 if (!parent_type) chk_table_constraints();
199
200 if(rawattrib || is_root_basic()){
201 chk_raw();
202 }
203 if(textattrib || is_root_basic()) {
204 chk_text();
205 }
206
207 if (jsonattrib || is_root_basic()) {
208 chk_json();
209 }
210
211 // We need to call chk_xer() always because it is collecting
212 // XER attributes from parent types.
213 chk_xer();
214
215 chk_finished = true;
216}
217
218void Type::parse_attributes()
219{
220 if (raw_parsed) return;
221
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) {
226 case OT_TYPE_DEF: {
227 Ttcn::Def_Type *pwn = static_cast<Ttcn::Def_Type*>(t->owner);
228 Ttcn::Group *nearest_group = pwn->get_parent_group();
229
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());
233 }
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());
239 }
240 break; }
241
242 case OT_RECORD_OF:
243 case OT_COMP_FIELD:
244 continue; // try the enclosing type
245
246 default:
247 break;
248 }
249 break;
250 }
251
252 if ((hasVariantAttrs())
253 && (enable_text() || enable_raw() || enable_xer())) {
254#ifndef NDEBUG
255 const char *fn = get_fullname().c_str();
256 if (rawAST_debug) {
257 fprintf(stderr, "parse_attributes for %s\n", fn);
258 }
259#endif
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
270 raw_checked=false;
271 text_checked=false;
272 json_checked = false;
273 xer_checked=false;
274 bool override_ref=false;
275 // Parse RAW attributes
276 switch(typetype) {
277 case T_REFD: {
278 ReferenceChain refch(this, "While checking attributes");
279 if(w_attrib_path)
280 {
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();
285
286 // see if there's an encode with override
287 for(size_t i = real_attribs.size(); i > 0 && !override_ref; i--)
288 {
289 if(real_attribs[i-1]->has_override()
290 && real_attribs[i-1]->get_attribKeyword()
291 != SingleWithAttrib::AT_ENCODE)
292 override_ref = true;
293 }
294 }
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
299 refch.reset();
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;
303 new_raw=true;
304 }
305 if(!textattrib && !override_ref){
306 Type *t=this;
307 refch.reset();
308 while(!t->textattrib && t->is_ref()) t=t->get_type_refd(&refch);
309 textattrib=new TextAST(t->textattrib);
310 new_text=true;
311 }
312 if (!jsonattrib && !override_ref){
313 Type *t = this;
314 refch.reset();
315 while (!t->jsonattrib && t->is_ref()) {
316 t = t->get_type_refd(&refch);
317 }
318 jsonattrib = new JsonAST(t->jsonattrib);
319 new_json = true;
320 }
321 }
322 // no break
323 case T_BOOL:
324 case T_INT:
325 case T_REAL:
326 case T_BSTR:
327 case T_HSTR:
328 case T_OSTR:
329 case T_CSTR: // TTCN-3 charstring
330 case T_ENUM_T:
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.
334 *
335 * For TEXT, it's section 3.4; the list does not include real and
336 * bin/hex/octet strings
337 */
338 case T_USTR: // TTCN-3 universal charstring, this is an addition for XER attributes
339 case T_VERDICT: // TTCN-3 verdict, for XER
340
341 if(rawattrib==NULL){
342 rawattrib= new RawAST(typetype==T_INT);
343 if(typetype==T_REAL) rawattrib->fieldlength=64;
344 new_raw=true;
345 }
346 if(textattrib==NULL){textattrib= new TextAST; new_text=true;}
347 if (xerattrib==NULL) {
348 xerattrib = new XerAttributes; new_xer = true;
349 }
350 if (berattrib==NULL) {
351 berattrib = new BerAST;
352 new_ber = true;
353 }
354
355 if (NULL == jsonattrib) {
356 jsonattrib = new JsonAST;
357 new_json = true;
358 }
359
360 if(w_attrib_path)
361 {
362 vector<SingleWithAttrib> const &real_attribs
363 = w_attrib_path->get_real_attrib();
364 // These are attributes without qualifiers.
365
366 size_t nof_elements = real_attribs.size();
367 for(size_t i = 0; i < nof_elements; i++)
368 {
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());
379 } // if AT_VARIANT
380 } // next i
381 }
382
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) {
388 delete jsonattrib;
389 jsonattrib = NULL;
390 }
391 break;
392 case T_SEQOF:
393 case T_SETOF:
394 case T_CHOICE_T:
395 case T_SEQ_T:
396 case T_SET_T:
397 case T_ANYTYPE:
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;
404 new_json = true;
405 }
406
407 if(w_attrib_path)
408 {
409 vector<SingleWithAttrib> const &real_attribs
410 = w_attrib_path->get_real_attrib();
411
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++)
415 {
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()
420 == 0)){
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);
427 }
428 }
429 //calculate the components attributes
430 MultiWithAttrib* self_attribs = w_attrib_path->get_with_attr();
431 if(self_attribs)
432 {
433 MultiWithAttrib* new_self_attribs = new MultiWithAttrib;
434 SingleWithAttrib* swa = 0;
435
436 // copy all the "encode" attributes
437 for(size_t i = 0; i < self_attribs->get_nof_elements(); i++)
438 {
439 if(self_attribs->get_element(i)->get_attribKeyword()
440 == SingleWithAttrib::AT_ENCODE)
441 {
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);
447 }
448 }
449
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());
457 }
458 else delete new_self_attribs;
459
460 // This should be bool, but gcc 4.1.2-sol8 generates incorrect code
461 // with -O2 :(
462 const int se_of = (typetype == T_SEQOF || typetype == T_SETOF);
463 const size_t nof_comps = se_of ? 1 : get_nof_comps();
464
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++)
471 {
472 const Identifier& comp_id =
473 se_of ? underscore_zero : get_comp_id_byIndex(i);
474 MultiWithAttrib* component_attribs = new MultiWithAttrib;
475
476 for(size_t j = 0; j < self_attribs->get_nof_elements(); j++)
477 {
478 const SingleWithAttrib *temp_single =
479 self_attribs->get_element(j);
480 Qualifiers* temp_qualifiers =
481 temp_single->get_attribQualifiers();
482 if( !temp_qualifiers
483 || temp_qualifiers->get_nof_qualifiers() == 0) continue;
484
485 Qualifiers* calculated_qualifiers = new Qualifiers;
486 bool qualifier_added = false;
487 for(size_t k=0; k < temp_qualifiers->get_nof_qualifiers(); )
488 {
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))
493 {
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;
502 }
503 else k++;
504 } // next qualifier
505
506 if(qualifier_added)
507 {
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);
516 }
517 else delete calculated_qualifiers;
518 } // next attrib
519
520 if (component_attribs->get_nof_elements() > 0) {
521 Type* component_type = se_of ?
522 get_ofType() : get_comp_byIndex(i)->get_type();
523
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);
528 else
529 component_type->set_parent_path(w_attrib_path->get_parent());
530
531 component_type->set_with_attr(component_attribs);
532 }
533 else delete component_attribs;
534 } // next component index
535
536 // Any remaining attributes with qualifiers are erroneous
537 for(size_t i = 0; i < self_attribs->get_nof_elements();)
538 {
539 Qualifiers *temp_qualifiers = self_attribs->get_element(i)
540 ->get_attribQualifiers();
541 if(temp_qualifiers && temp_qualifiers->get_nof_qualifiers() != 0)
542 {
543 size_t nof_qualifiers = temp_qualifiers->get_nof_qualifiers();
544 for(size_t j = 0; j < nof_qualifiers; j++)
545 {
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());
555 }
556 self_attribs->delete_element(i);
557 }else{
558 i++;
559 }
560 } // next 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) {
568 delete jsonattrib;
569 jsonattrib = NULL;
570 }
571 break;
572 default:
573 // nothing to do, ASN1 types or types without defined raw attribute
574 break;
575 } // switch
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()) {
581 delete jsonattrib;
582 jsonattrib = NULL;
583 }
584 } // endif( hasVariantAttrs && enable_{raw,text,xer} )
585
586 raw_parsed = true;
587}
588
589// Implements "NAME AS ..." transformations.
590void change_name(string &name, XerAttributes::NameChange change) {
591 switch (change.kw_) {
592 case NamespaceSpecification::NO_MANGLING:
593 break; // cool, nothing to do!
594
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]);
599 }
600 break;
601
602 case NamespaceSpecification::LOWERCASED:
603 for (int i = name.size()-1; i >= 0; --i) {
604 name[i] = tolower(name[i]);
605 }
606 break;
607
608 case NamespaceSpecification::CAPITALIZED:
609 name[0] = toupper(name[0]);
610 break;
611
612 case NamespaceSpecification::UNCAPITALIZED:
613 name[0] = tolower(name[0]);
614 break;
615
616 default: // explicitly specified name
617 name = change.nn_;
618 break;
619 } // switch for NAME
620}
621
622void Type::chk_xer_any_attributes()
623{
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
629 break;
630 // fall through
631 default:
632 error("ANY-ATTRIBUTES can only be applied to record of string");
633 break;
634 } // switch
635
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;
af710487 642 if (cf->has_default()) {
643 error("The field with ANY-ATTRIBUTES cannot have DEFAULT");
970ed795
EL
644 }
645 }
646 break;
647 default:
648 error("ANY-ATTRIBUTES can only be applied to a member of "
649 "SEQUENCE, SET, record or set");
650 break;
651 }
652
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");
657 }
658}
659
660void Type::chk_xer_any_element()
661{
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
666 break; // acceptable
667 case T_SEQOF: {
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;
683 oftype->chk_xer();
684 break; }
685 default:
686 error("ANY-ELEMENT can only be applied to UTF8String "
687 "or universal charstring type");
688 break;
689 } // switch
690
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");
696 }
697}
698
699void Type::chk_xer_attribute()
700{
701 if (xerattrib->element_) {
702 error("ELEMENT and ATTRIBUTE are incompatible");
703 }
704
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:
709 break; // acceptable
710 default:
711 error("A type with ATTRIBUTE must be a member of "
712 "SEQUENCE, SET, record or set");
713 break;
714 }
715
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");
720 }
721
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");
727 }
728}
729
730/// CompField cache
731struct CFCache {
732 /// Pointer to the field
733 CompField *cf;
734 /// The type of the field
735 Type *top;
736 /// The ultimate type, top->get_type_refd_last()
737 Type *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;
741};
742
743/// Comparison function for CFCache based on typetype
744int tcomp(const void *l, const void *r)
745{
746 int retval = ((const CFCache*)l)->lastt - ((const CFCache*)r)->lastt;
747 return retval;
748}
749
750/** Find the original component name if it was changed by TEXT
751 *
752 * If there is a TEXT whose \a new_text matches \p text, return
753 * the corresponding \a target.
754 *
755 * If there are no TEXT coding instructions, always returns \p text.
756 *
757 * @param[in,out] text on input, a name possibly modified by any TEXT encoding
758 * instruction; on output, the actual component name
759 */
760void Type::target_of_text(string & text)
761{
762 for (size_t t = 0; t < xerattrib->num_text_; ++t) {
763 NamespaceSpecification& txt = xerattrib->text_[t];
764
765 if ((unsigned long)txt.prefix == 0
766 ||(unsigned long)txt.prefix == NamespaceSpecification::ALL) {
767 FATAL_ERROR("Type::target_of_text()");
768 continue;
769 }
770
771 string target(txt.target);
772
773 switch ((unsigned long)txt.new_text) {
774 case NamespaceSpecification::CAPITALIZED: // tARGET -> TARGET
775 target[0] = toupper(target[0]);
776 break;
777 case NamespaceSpecification::UNCAPITALIZED:
778 target[0] = tolower(target[0]); // TARGET -> tARGET
779 break;
780 case NamespaceSpecification::UPPERCASED:
781 for (int si = target.size() - 1; si >= 0; --si) {
782 target[si] = toupper(target[si]);
783 }
784 break;
785 case NamespaceSpecification::LOWERCASED:
786 for (int si = target.size() - 1; si >= 0; --si) {
787 target[si] = tolower(target[si]);
788 }
789 break;
790
791 case 0: // "text" not possible
792 FATAL_ERROR("Type::target_of_text() Text with no target and DFE");
793 break;
794
795 default: // it's a string, "text 'field' as 'string'"
796 target = txt.uri;
797 break;
798 } // switch new_text
799
800 if (target == text) {
801 text = txt.target; // we want the value before the change
802 break;
803 }
804 } // next text
805}
806
807// The suffix of the name of the variable which contains the D-F-E value.
808static const string dfe_suffix("_dfe");
809
810/** Construct a Value to represent defaultForEmpty
811 *
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
816 */
817Value *Type::new_value_for_dfe(Type *last, const char *dfe_str)
818{
819 string defaultstring(dfe_str);
820 switch (last->typetype) {
821 case T_CSTR:
822 case T_USTR:
823 case T_UTF8STRING:
824 return new Value(Common::Value::V_CSTR,
825 new string(defaultstring));
826
827 case T_INT:
828 case T_INT_A:
829 return new Value(Common::Value::V_INT,
830 new int_val_t(dfe_str, *this));
831
832 case T_REAL: {
833 const Real& rval = string2Real(dfe_str, *this);
834 return new Value(Value::V_REAL, rval);
835 }
836
837 case T_BOOL: {
838 if (!strcmp(dfe_str, "true")
839 ||!strcmp(dfe_str, "1")) {
840 return new Value(Value::V_BOOL, true);
841 }
842 else if (!strcmp(dfe_str, "false")
843 || !strcmp(dfe_str, "0")) {
844 return new Value(Value::V_BOOL, false);
845 }
846 else error("Invalid boolean default value");
847 break;
848 }
849
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).
853
854 target_of_text(defaultstring);
855
856 Identifier *val_id = new Identifier(Common::Identifier::ID_TTCN, // FIXME when ASN1 is supported
857 defaultstring);
858
859 if (!last->has_ei_withName(*val_id)) {
860 error("No enumeration item item '%s'", defaultstring.c_str());
861#ifndef NDEBUG
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());
864 }
865#endif
866 }
867
868 return new Value(Common::Value::V_ENUM, val_id);
869 }
870
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();
882 sorted[c].cf = cf;
883 sorted[c].top = cft;
884 sorted[c].last = cftlast;
885 sorted[c].lastt = cftlast->typetype;
886 }
887 qsort(sorted, num_comps, sizeof(CFCache), tcomp);
888
889 Value * retval = 0;
890 size_t c;
891 for (c = 0; c < num_comps && retval == 0; c++) {
892 CFCache &current = 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) {
896 case T_BOOL:
897 if (!strcmp(dfe_str, "true")
898 ||!strcmp(dfe_str, "1")) {
899 retval = new Value(Value::V_BOOL, true);
900 }
901 else if (!strcmp(dfe_str, "false")
902 || !strcmp(dfe_str, "0")) {
903 retval = new Value(Value::V_BOOL, false);
904 }
905 break;
906
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;
915
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);
920 }
921 break; }
922
923 case T_REAL: {
924 float f;
925 char tail[2];
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);
930 }
931 break; }
932
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);
938 }
939 break; }
940
941 case T_CSTR:
942 case T_USTR:
943 case T_UTF8STRING: {
944 retval = current.top->new_value_for_dfe(current.last, dfe_str);
945 break; }
946
947 default:
948 break;
949 } // switch
950 } // next c
951
952 if (retval != 0) {
953 c--;
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;
960 }
961
962 delete [] sorted;
963 return retval; }
964
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);
969 nvs->add_nv(nv);
970 xerattrib->defaultValue_ = new Value(Value::V_SEQ, nvs);
971 break; }
972 */
973
974 default: // complain later
975 break;
976 } // switch
977 return 0;
978}
979
980void Type::chk_xer_dfe()
981{
982 Type * const last = get_type_refd_last();
983
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
988 }
989
990 if (is_charenc() == Yes) {
991 xerattrib->defaultValue_ = new_value_for_dfe(last, xerattrib->defaultForEmpty_);
992
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);
997 }
998 else {
999 error("DEFAULT-FOR-EMPTY not supported for character-encodable type %s",
1000 last->get_stringRepr().c_str());
1001 }
1002 }
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();
1010 if (num_cf > 0) {
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();
1015
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);
1021 }
1022 else {
1023 error("DEFAULT-FOR-EMPTY not supported for fields of type %s",
1024 cft->get_stringRepr().c_str());
1025 }
1026 } // endif comps >0
1027 } // if SEQ/SET
1028 else {
1029 error("DEFAULT-FOR-EMPTY not applicable to type");
1030 }
1031}
1032
1033void Type::chk_xer_embed_values(int num_attributes)
1034{
1035 Type * const last = get_type_refd_last();
1036
3f84031e 1037 enum complaint_type { ALL_GOOD, HAVE_DEFAULT, UNTAGGED_EMBEDVAL,
970ed795
EL
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
1043 CompField *cf = 0;
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();
1047 if (num_cf == 0) {
1048 complaint = EMPTY_SEQUENCE; // must have a "first component"
1049 break;
1050 }
1051 CompField *cf0 = last->get_comp_byIndex(0);
1052 cf0t = cf0->get_type()->get_type_refd_last();
3f84031e 1053 if (cf0->has_default()) {
1054 complaint = HAVE_DEFAULT;
1055 break; // 25.2.1 first component cannot have default
970ed795
EL
1056 }
1057
1058 switch (cf0t->get_typetype()) { // check the first component
1059 case T_SEQOF: {
1060 Type *cfot = cf0t->get_ofType(); // embedded type
1061 switch (cfot->get_type_refd_last()->get_typetype()) {
1062 case T_UTF8STRING:
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
1067 break;
1068 }
1069
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;
1081 break;
1082 }
1083 break; } //acceptable
1084
1085 default: // 25.2.1
1086 complaint = SEQOF_NOT_STRING;
1087 break;
1088 } // switch
1089 break; }
1090
1091 default: // 25.2.1
1092 complaint = FIRST_NOT_SEQOF;
1093 break;
1094 } // switch(type of first component)
1095
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;
1101 break;
1102 }
1103 }
1104 break; } // case T_SEQ*
1105
1106 default:
1107 complaint = NOT_SEQUENCE;
1108 break;
1109 } // switch typetype
1110
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).
1117 break;
1118 case NOT_SEQUENCE:
1119 case EMPTY_SEQUENCE:
1120 case FIRST_NOT_SEQOF:
1121 case SEQOF_NOT_STRING:
3f84031e 1122 case HAVE_DEFAULT:
970ed795
EL
1123 error("A type with EMBED-VALUES must be a sequence type. "
1124 "The first component of the sequence shall be SEQUENCE OF UTF8String "
3f84031e 1125 "and shall not be marked DEFAULT");
970ed795
EL
1126 break;
1127 case SEQOF_BAD_LENGTH:
1128 cf0t->error("Wrong length of SEQUENCE-OF for EMBED-VALUES, should be %lu",
1129 (unsigned long)expected_length);
1130 break;
1131 case UNTAGGED_EMBEDVAL:
1132 error("Neither the SEQUENCE-OF supporting EMBED-VALUES,"
1133 "nor its component shall have UNTAGGED."); // 25.2.2
1134 break;
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
1138 break;
1139 } // switch(complaint)
1140 } // if complaint and embedValues
1141}
970ed795
EL
1142/** Wraps a C string but compares by contents, not by pointer */
1143class stringval {
1144 const char * str;
1145public:
1146 explicit stringval(const char *s = 0) : str(s) {}
1147 // no destructor
1148 bool operator<(const stringval& right) const {
1149 if ( str > (const char*)NamespaceSpecification::ALL
1150 && right.str > (const char*)NamespaceSpecification::ALL)
1151 {
1152 return strcmp(str, right.str) < 0;
1153 }
1154 else return str < right.str;
1155 }
1156 bool operator==(const stringval& right) const {
1157 if ( str > (const char*)NamespaceSpecification::ALL
1158 && right.str > (const char*)NamespaceSpecification::ALL)
1159 {
1160 return strcmp(str, right.str) == 0;
1161 }
1162 else return str == right.str;
1163 }
1164 //bool operator!() const { return str==0; }
1165 const char *c_str() const { return str; }
1166};
1167
1168
1169void Type::chk_xer_text()
1170{
1171 if (xerattrib->num_text_ == 0
1172 ||xerattrib->text_ == 0 ) FATAL_ERROR("Type::chk_xer_text()");
1173 Type * const last = get_type_refd_last();
1174 static const stringval empty; // NULL pointer
1175
1176 // Check the type and quit early if wrong
1177 switch (last->typetype) {
1178 case T_BOOL:
1179 break;
1180 case T_ENUM_A: // not yet
1181 error("No XER yet for ASN.1 enumerations");
1182 return;
1183 case T_ENUM_T:
1184 break;
1185 case T_BSTR_A: // ASN.1 bit string with named bits, not yet
1186 error("No XER yet for ASN.1 bit strings");
1187 return;
1188 case T_INT_A: // ASN.1 integer with named numbers, not yet
1189 error("No XER yet for ASN.1 named numbers");
1190 return;
1191 default:
1192 error("TEXT not allowed for type %s", get_typename().c_str());
1193 return;
1194 }
1195
1196 // Build a map to eliminate duplicates (new assignment to the same
1197 // enum item/field overwrites previous text).
1198 // Keys are the identifiers, values are the texts.
1199 typedef map<stringval, char> text_map_t;
1200 text_map_t text_map;
1201
1202 for (size_t t = 0; t < xerattrib->num_text_; ++t) {
1203 NamespaceSpecification & txt = xerattrib->text_[t];
1204 switch ((unsigned long)txt.target) {
1205 case 0: { // just "TEXT".
1206 // target=0 and new_text!=0 would have to come from "TEXT AS ..."
1207 // but that's not allowed by syntax, hence FATAL_ERROR.
1208 if (txt.new_text) FATAL_ERROR("Type::chk_xer_text");
1209 if (!text_map.has_key(empty)) {
1210 text_map.add(empty, txt.new_text);
1211 }
1212 if (last->typetype != T_BOOL) {
1213 error("Lone 'TEXT' only allowed for boolean"); // only in TTCN-3 !
1214 }
1215 break; }
1216
1217 case NamespaceSpecification::ALL: {// TEXT ALL AS ...
1218 switch (txt.keyword) {
1219 case NamespaceSpecification::NO_MANGLING:
1220 // Not possible due to syntax; there is no TTCN source from which
1221 // the bison parser would create such a NamespaceSpecification.
1222 FATAL_ERROR("Type::chk_xer_text");
1223 break;
1224 case NamespaceSpecification::CAPITALIZED:
1225 case NamespaceSpecification::UNCAPITALIZED:
1226 case NamespaceSpecification::LOWERCASED:
1227 case NamespaceSpecification::UPPERCASED:
1228 break; // OK
1229
1230 default: // TEXT ALL AS "some string" is not allowed
1231 error("text all as 'string' is not allowed");
1232 continue;
1233 } // switch(keyword)
1234
1235 // Expand the "all"
1236 switch (last->typetype) {
1237 case T_BOOL:
1238 text_map.add(stringval(mcopystr("true")), txt.new_text);
1239 text_map.add(stringval(mcopystr("false")), txt.new_text);
1240 break;
1241
1242 //case T_ENUM_A:
1243 case T_ENUM_T: {
1244 size_t n_eis = last->u.enums.eis->get_nof_eis();
1245 for (size_t i = 0; i < n_eis; ++i) {
1246 EnumItem *ei = last->u.enums.eis->get_ei_byIndex(i);
1247 const stringval enum_name(mcopystr(ei->get_name().get_ttcnname().c_str()));
1248 if (text_map.has_key(enum_name)) {
1249 // Duplicate enum name, flagged elsewhere as error.
1250 // Don't bother with: text_map[enum_name] = txt.new_text;
1251 Free(const_cast<char*>(enum_name.c_str()));
1252 }
1253 else text_map.add(enum_name, txt.new_text);
1254 }
1255 break; }
1256
1257 default:
1258 FATAL_ERROR("Type::chk_xer_text");
1259 break;
1260 } // switch (typetype)
1261 break;
1262 }
1263
1264 default: {// a string: TEXT 'member' AS ...
1265 if (txt.keyword == NamespaceSpecification::NO_MANGLING) {
1266 // Attribute syntax does not allow this combination
1267 FATAL_ERROR("Type::chk_xer_text");
1268 }
1269 // HR39956: empty string is disregarded
1270 if (txt.keyword>NamespaceSpecification::LOWERCASED && !strcmp(txt.new_text,""))
1271 {
1272 txt.new_text = (char*)Realloc(txt.new_text, sizeof(" "));
1273 strcpy(txt.new_text," ");
1274 }
1275 stringval ttarget(txt.target);
1276 if (text_map.has_key(ttarget)) {
1277 // Override the earlier TEXT instruction
1278 free_name_or_kw(text_map[ttarget]);
1279 text_map[ttarget] = txt.new_text;
1280 free_name_or_kw(txt.target);
1281 }
1282 else text_map.add(ttarget, txt.new_text);
1283 break; }
1284 } // switch(target)
1285 } // next text
1286
1287 xerattrib->text_ = (NamespaceSpecification*)Realloc(xerattrib->text_,
1288 text_map.size() * sizeof(NamespaceSpecification));
1289
1290 // Zero out the newly allocated part
1291 if (text_map.size() > xerattrib->num_text_) {
1292 memset(
1293 xerattrib->text_ + xerattrib->num_text_,
1294 0,
1295 (text_map.size() - xerattrib->num_text_) * sizeof(NamespaceSpecification)
1296 );
1297 }
1298
1299 xerattrib->num_text_ = text_map.size(); // accept the new size
1300
1301 // Another map, to check for duplicate text (decoding would be impossible)
1302 text_map_t map2;
1303
1304 // Reconstruct the TEXT structure from the map
1305 for (size_t t = 0; t < xerattrib->num_text_; ++t) {
1306 const stringval& k = text_map.get_nth_key(t);
1307 char * v = text_map.get_nth_elem(t);
1308 char * newstr = const_cast<char*>(k.c_str());
1309
1310 xerattrib->text_[t].target = newstr;
1311 xerattrib->text_[t].new_text = v;
1312
1313 stringval txtval(v); // somebody else owns v
1314 if (map2.has_key(txtval)) {
1315 switch (xerattrib->text_[t].keyword) {
1316 case NamespaceSpecification::NO_MANGLING:
1317 FATAL_ERROR("nope");
1318 break; // not possible
1319
1320 case NamespaceSpecification::CAPITALIZED:
1321 case NamespaceSpecification::UNCAPITALIZED:
1322 case NamespaceSpecification::LOWERCASED:
1323 case NamespaceSpecification::UPPERCASED:
1324 // Duplication may have been caused by expanding TEXT ALL ...
1325 break; // accept it
1326
1327 default: // string must be unique
1328 error("Duplicate text '%s'", v);
1329 break;
1330 }
1331 }
1332 else map2.add(txtval, newstr);
1333 }
1334 text_map.clear();
1335 map2.clear();
1336 // // //
1337 for (size_t t = 0; t < xerattrib->num_text_; ++t) {
1338 if (xerattrib->useNumber_) {
1339 error("USE-NUMBER and TEXT are incompatible");
1340 break;
1341 }
1342 NamespaceSpecification & txt = xerattrib->text_[t];
1343
1344 switch (last->typetype) {
1345 case T_BOOL:
1346 /* In ASN.1, Only Booleantype:ALL can have TEXT
1347 * Currently for TTCN, only the following three case are supported:
1348 * "text"
1349 * "text 'true' as '1'"
1350 * "text 'false' as '0'"
1351 * and we convert the last two to the first
1352 */
1353 switch ((unsigned long)txt.prefix) {
1354 case 0: // no Target (ok);
1355 if (txt.uri != 0) error("Only \"text\" implemented for boolean");
1356 break;
1357 case NamespaceSpecification::ALL: // Target = 'all' not allowed for boolean
1358 error("TEXT all not implemented for boolean");
1359 break;
1360 default: // a string, must be "true" or "false"
1361 if (!strcmp(txt.prefix, "true")) {
1362 // only "1" is allowed for "true"
1363 switch ((unsigned long)txt.uri) {
1364 default: // it's a string
1365 if (txt.uri[0] == '1' && txt.uri[1] == '\0') {
1366 // Free the strings to pretend it was a simple "text"
1367 Free(txt.prefix); txt.prefix = 0;
1368 Free(txt.uri); txt.uri = 0;
1369 // These should come in pairs, warn if not
1370 if (xerattrib->num_text_ == 1) warning("\"text 'false' as '0'\" was implied");
1371 break;
1372 }
1373 // else fall through
1374 case NamespaceSpecification::CAPITALIZED:
1375 case NamespaceSpecification::UNCAPITALIZED:
1376 case NamespaceSpecification::UPPERCASED:
1377 case NamespaceSpecification::LOWERCASED:
1378 error("Only '1' is supported for 'true'");
1379 break;
1380
1381 case 0: // "text 'true'" is not correct syntax, cannot get here
1382 FATAL_ERROR("Type::chk_xer_text()");
1383 } // switch uri
1384 }
1385 else if (!strcmp(txt.prefix, "false")) {
1386 // only "0" is allowed for "false"
1387 switch ((unsigned long)txt.uri) {
1388 default: // it's a string
1389 if (txt.uri[0] == '0' && txt.uri[1] == '\0') {
1390 // Free the strings to pretend it was a simple "text"
1391 Free(txt.prefix); txt.prefix = 0;
1392 Free(txt.uri); txt.uri = 0;
1393 // These should come in pairs, warn if not
1394 if (xerattrib->num_text_ == 1) warning("\"text 'true' as '1'\" was implied");
1395 break;
1396 }
1397 // else fall through
1398 case NamespaceSpecification::CAPITALIZED:
1399 case NamespaceSpecification::UNCAPITALIZED:
1400 case NamespaceSpecification::UPPERCASED:
1401 case NamespaceSpecification::LOWERCASED:
1402 error("Only '0' is supported for 'false'");
1403 break;
1404
1405 case 0: // "text 'false'" is not correct syntax, cannot get here
1406 FATAL_ERROR("Type::chk_xer_text()");
1407 } // switch uri
1408 } // if ("true")
1409 break;
1410 } // switch prefix
1411
1412 break;
1413
1414 //case T_ENUM_A: // fall through
1415 case T_ENUM_T: {
1416 switch ((unsigned long)txt.target) {
1417 case 0: // "text as ..."
1418 case NamespaceSpecification::ALL: { // "text all as ..."
1419 size_t neis = last->u.enums.eis->get_nof_eis();
1420 for (size_t i = 0; i < neis; ++i) {
1421 EnumItem *ei = last->u.enums.eis->get_ei_byIndex(i);
1422 string ei_name(ei->get_name().get_dispname()); // use the element's own name
1423 XerAttributes::NameChange chg;
1424 chg.nn_ = txt.uri;
1425 change_name(ei_name, chg);
1426 ei->set_text(ei_name);
1427 }
1428 break; }
1429
1430 default: { // target is member name, from "text 'member' as ..."
1431 // FIXME: ID_TTCN will not be right if we implement XER for ASN.1
1432 Common::Identifier id(Identifier::ID_TTCN, string(txt.prefix));
1433 if (last->u.enums.eis->get_nof_eis()==0) FATAL_ERROR("No enum items!");
1434 if (last->u.enums.eis->has_ei_withName(id)) {
1435 EnumItem *ei = last->u.enums.eis->get_ei_byName(id);
1436 string ei_name(id.get_dispname());
1437 XerAttributes::NameChange chg;
1438 chg.nn_ = txt.uri;
1439 change_name(ei_name, chg);
1440 ei->set_text(ei_name);
1441 }
1442 else {
1443 error("No enumeration item %s", txt.prefix);
1444 }
1445 break; }
1446 } // switch(target)
1447
1448 break; }
1449
1450 //case T_INT_A:
1451 /*
1452 if (last->u.namednums.nvs->get_nof_nvs()) {
1453 Common::Identifier id(Identifier::ID_TTCN, txt.uri);
1454 NamedValue *nv = last->u.namednums.nvs->get_nv_byName(id);
1455 if (nv != 0) {
1456 // good
1457 }
1458 else {
1459 error("No component %s in %s", txt.uri, fn);
1460 }
1461 }
1462 else {
1463 error("TEXT cannot be assigned to an integer without named numbers");
1464 }
1465 */
1466 //break;
1467
1468 default:
1469 FATAL_ERROR("Type::chk_xer_text");
1470 break;
1471 } // switch
1472 } // next type for TEXT
1473}
1474
1475void Type::chk_xer_untagged()
1476{
1477 Type * const last = get_type_refd_last();
1478 switch (parent_type ? parent_type->typetype :-0) {
1479 case 0: // "no parent" is acceptable
1480 // Do not nag ("UNTAGGED encoding attribute is ignored on top-level type");
1481 // do it in Def_ExtFunction::chk_function_type when the type is actually
1482 // used as input for an encoding function.
1483 // fall through
1484 case T_SEQ_A: case T_SEQ_T:
1485 case T_SET_A: case T_SET_T:
1486 case T_CHOICE_A: case T_CHOICE_T:
1487 case T_SEQOF: case T_SETOF:
1488 break; // acceptable
1489 default:
1490 error("UNTAGGED can only be applied to a member of sequence, set, "
1491 "choice, sequence-of, or set-of type"); // X.693amd1, 32.2.1
1492 break;
1493 }
1494
1495 if ( has_aa(xerattrib)
1496 || has_ae(xerattrib)
1497 || xerattrib->attribute_ || 0 != xerattrib->defaultForEmpty_
1498 || xerattrib->embedValues_ || xerattrib->useNil_
1499 || (xerattrib->useOrder_ && is_asn1()) || xerattrib->useType_) {
1500 error("A type with final encoding attribute UNTAGGED shall not have"
1501 " any of the final encoding instructions ANY-ATTRIBUTES, ANY-ELEMENT,"
1502 " ATTRIBUTE, DEFAULT-FOR-EMPTY, EMBED-VALUES, PI-OR-COMMENT,"
1503 " USE-NIL%s or USE-TYPE",
1504 is_asn1() ? ", USE-ORDER" : ""); // X.693amd1, 32.2.6
1505 }
1506
1507 bool can_become_empty= last->has_empty_xml();
1508 if (can_become_empty) { // checking 32.2.4
1509 switch (parent_type ? parent_type->typetype :-0) {
1510 case 0:
1511 break; // no parent, no problem
1512
1513 case T_SEQ_A: case T_SEQ_T:
1514 case T_SET_A: case T_SET_T: {
1515 // This type can not have OPTIONAL or DEFAULT, 32.2.4 a)
1516 // No get_comp_byType(); do a linear search.
1517 size_t num_fields = parent_type->get_nof_comps();
1518 for (size_t i = 0; i < num_fields; ++i) {
1519 CompField *cf = parent_type->get_comp_byIndex(i);
1520 if (cf->get_type() != this) continue;
1521 // found the component
1522 if (cf->get_is_optional() || cf->get_defval() != 0) {
1523 error("Type with final encoding attribute UNTAGGED"
3abe9331 1524 " shall not have OPTIONAL or DEFAULT");
970ed795
EL
1525 }
1526 break;
1527 }
1528 break; }
1529
1530 case T_SEQOF: case T_SETOF: // X.693amd1, 32.2.4 b)
1531 error("UNTAGGED type with possibly empty XML value can not be "
1532 "the member of a sequence-of or set-of"); // X.693amd1, 32.2.4 b)
1533 break;
1534
1535 case T_CHOICE_T: {
1536 size_t num_fields = parent_type->get_nof_comps();
1537 size_t num_empty = 0;
1538 for (size_t i = 0; i < num_fields; ++i) {
1539 CompField *cf = parent_type->get_comp_byIndex(i);
1540 Type *cft = cf->get_type();
1541 if (cft->has_empty_xml()) ++num_empty;
1542 }
1543 if (num_empty > 1) { // X.693amd1, 32.2.4 c)
1544 /* FIXME: this should be error */
1545 warning("More than one alternative can be empty and has UNTAGGED");
1546 }
1547 break; }
1548
1549 default: // do nothing
1550 break;
1551 }
1552 } // end if(can_become_empty)
1553}
1554
1555void Type::chk_xer_use_nil()
1556{
1557 Type * const last = get_type_refd_last();
1558
1559 enum complaint_type { ALL_GOOD, NO_CONTROLNS, NOT_SEQUENCE, EMPTY_SEQUENCE,
1560 UNTAGGED_USENIL, COMPONENT_NOT_ATTRIBUTE, LAST_IS_ATTRIBUTE,
3f84031e 1561 LAST_NOT_OPTIONAL, INCOMPATIBLE, WRONG_OPTIONAL_TYPE, EMBED_CHARENC,
1562 NOT_COMPATIBLE_WITH_USEORDER, BAD_ENUM, FIRST_OPTIONAL, NOTHING_TO_ORDER,
1563 FIRST_NOT_RECORD_OF_ENUM, ENUM_GAP };
970ed795
EL
1564 complaint_type complaint = ALL_GOOD;
1565 CompField *cf = 0;
1566 CompField *cf_last = 0;
1567 const char *ns, *prefix;
3f84031e 1568 Type *the_enum = 0;
970ed795
EL
1569 my_scope->get_scope_mod()->get_controlns(ns, prefix);
1570
1571 if (!prefix) complaint = NO_CONTROLNS; // don't bother checking further
1572 else switch (last->typetype) {
1573 default:
1574 complaint = NOT_SEQUENCE;
1575 break;
1576
1577 case T_SEQ_A:
1578 error("No XER yet for ASN.1 sequences");
1579 // no break
1580 case T_SEQ_T: {
1581 const size_t num_cf = last->get_nof_comps();
1582 if (num_cf == 0) { // 33.2.1 ...must have a component...
1583 complaint = EMPTY_SEQUENCE;
1584 break; // stop checking to prevent accessing non-existing components
1585 }
1586 if (xerattrib->untagged_) { // 33.2.2
1587 complaint = UNTAGGED_USENIL;
1588 break;
1589 }
1590
1591 // Skip components supporting USE-ORDER or EMBED-VALUES
1592 size_t i = (xerattrib->useOrder_) + (xerattrib->embedValues_);
1593 // 33.2.1 All the others except the last must be (any)attributes
1594 for (; i < num_cf-1; ++i) {
1595 cf = last->get_comp_byIndex(i);
1596 Type *cft = cf->get_type();
1597 if (! (cft->xerattrib
1598 && ( cft->xerattrib->attribute_ || has_aa(cft->xerattrib))))
1599 {
1600 complaint = COMPONENT_NOT_ATTRIBUTE;
1601 break;
1602 }
1603 }
1604 // 33.2.1 The last component must be an OPTIONAL non-attribute
1605 cf_last = last->get_comp_byIndex(num_cf-1);
1606 Type *cft = cf_last->get_type();
1607 if (!cf_last->get_is_optional()) {
1608 complaint = LAST_NOT_OPTIONAL;
1609 }
3f84031e 1610
1611 if(xerattrib->useOrder_ && cft->get_type_refd_last()->get_typetype() != T_SEQ_A
1612 && cft->get_type_refd_last()->get_typetype() != T_SEQ_T){
1613 complaint = NOT_COMPATIBLE_WITH_USEORDER;
1614 }else if(xerattrib->useOrder_) {
1615 //This check needed, because if the record that has useOrder only
1616 //has one field that is a sequence type, then the useNilPossible
1617 //would be always true, that would lead to incorrect code generation.
1618 Type * inner = cft->get_type_refd_last();
1619 size_t useorder_index = xerattrib->embedValues_;
1620 CompField *uo_field = last->get_comp_byIndex(useorder_index);
1621 Type *uot = uo_field->get_type();
1622 if (uot->get_type_refd_last()->typetype == T_SEQOF) {
1623 the_enum = uot->get_ofType()->get_type_refd_last();
1624 if(the_enum->typetype != T_ENUM_A && the_enum->typetype != T_ENUM_T){
1625 complaint = FIRST_NOT_RECORD_OF_ENUM;
1626 break;
1627 }else if (uo_field->get_is_optional() || uo_field->get_defval() != 0) {
1628 complaint = FIRST_OPTIONAL;
1629 break;
1630 }
1631
1632 size_t expected_enum_items = inner->get_nof_comps();
1633 size_t enum_index = 0;
1634 if (expected_enum_items == 0)
1635 complaint = NOTHING_TO_ORDER;
1636 else if (the_enum->u.enums.eis->get_nof_eis() != expected_enum_items)
1637 complaint = BAD_ENUM;
1638 else for (size_t i = 0; i < expected_enum_items; ++i) {
1639 CompField *inner_cf = inner->get_comp_byIndex(i);
1640 Type *inner_cft = inner_cf->get_type();
1641 if (inner_cft->xerattrib && inner_cft->xerattrib->attribute_) continue;
1642 // Found a non-attribute component. Its name must match an enumval
1643 const Identifier& field_name = inner_cf->get_name();
1644 const EnumItem *ei = the_enum->get_ei_byIndex(enum_index);
1645 const Identifier& enum_name = ei->get_name();
1646 if (field_name != enum_name) {// X.693amd1 35.2.2.1 and 35.2.2.2
1647 complaint = BAD_ENUM;
1648 break;
1649 }
1650 Value *v = ei->get_value();
1651 const int_val_t *ival = v->get_val_Int();
1652 const Int enumval = ival->get_val();
1653 if ((size_t)enumval != enum_index) {
1654 complaint = ENUM_GAP; // 35.2.2.3
1655 break;
1656 }
1657 ++enum_index;
1658 }
1659 }
1660 }
970ed795
EL
1661
1662 if (cft->xerattrib) {
1663 if ( cft->xerattrib->attribute_
1664 || has_aa(cft->xerattrib)) {
1665 complaint = LAST_IS_ATTRIBUTE;
1666 break;
1667 }
1668
1669 if (has_ae(cft->xerattrib)
1670 ||has_aa(cft->xerattrib)
3f84031e 1671 ||cft->xerattrib->defaultForEmpty_ != 0
1672 ||cft->xerattrib->untagged_
1673 ||cft->xerattrib->useNil_
1674 ||cft->xerattrib->useOrder_
970ed795
EL
1675 ||cft->xerattrib->useType_) { // or PI-OR-COMMENT
1676 complaint = INCOMPATIBLE; // 33.2.3
1677 }
1678 }
1679
1680 if (cft->is_charenc() == Yes) {
1681 // In a sequence EMBED-VALUES and USE-NIL, the optional component
1682 // supporting USE-NIL shall not be a character-encodable type.
1683 // So says OSS, and rightly so (there's no way to separate
1684 // the last field from the surrounding "embed" strings).
1685 if (xerattrib->embedValues_) complaint = EMBED_CHARENC;
1686 }
1687 else switch (cft->get_type_refd_last()->typetype) {
1688 case T_SEQ_T:
1689 // more checking
1690 case T_SEQ_A:
1691 case T_SET_T:
1692 case T_SET_A:
1693 case T_CHOICE_T:
1694 case T_CHOICE_A:
1695 case T_SEQOF:
1696 case T_SETOF:
1697 case T_OPENTYPE:
1698 // or an octetstring or bitstring with a contained "Type" and without ENCODED BY
1699 break; // acceptable
1700
1701 default:
1702 complaint = WRONG_OPTIONAL_TYPE;
1703 break;
1704 }
1705
1706 break;}
1707 } // else switch(last->typetype)
1708
1709 if (complaint == ALL_GOOD) use_nil_possible = true;
1710 else if (xerattrib->useNil_) {
1711 switch (complaint) {
1712 case ALL_GOOD: // Not possible because of the if.
1713 // Present so GCC checks that all enum values are handled (no default!)
1714 break;
1715 case NO_CONTROLNS:
1716 error("Type has USE-NIL, but the module has no control namespace set");
1717 break;
1718 case NOT_SEQUENCE:
1719 error("The target of an USE-NIL encoding instruction must be a record (SEQUENCE) or set type");
1720 break;
1721 case EMPTY_SEQUENCE:
1722 error("The target of an USE-NIL must have at least one component");
1723 break;
1724 case UNTAGGED_USENIL:
1725 error("The target of an USE-NIL encoding instruction shall not have"
1726 " a final UNTAGGED encoding instruction");
1727 break;
1728 case COMPONENT_NOT_ATTRIBUTE:
1729 cf->error("Component '%s' of USE-NIL not ATTRIBUTE", cf->get_name().get_name().c_str());
1730 break;
1731 case LAST_IS_ATTRIBUTE:
1732 cf_last->error("Last component of USE-NIL must not have ATTRIBUTE");
1733 break;
1734 case LAST_NOT_OPTIONAL:
1735 cf_last->error("Last component of USE-NIL must be OPTIONAL");
1736 break;
1737 case INCOMPATIBLE:
1738 cf_last->error("The OPTIONAL component of USE-NIL cannot have any of the "
1739 "following encoding instructions: ANY-ATTRIBUTES, ANY-ELEMENT, "
3f84031e 1740 "DEFAULT-FOR-EMPTY, PI-OR-COMMENT, UNTAGGED, "
970ed795
EL
1741 "USE-NIL, USE-ORDER, USE-TYPE.");
1742 break;
1743 case WRONG_OPTIONAL_TYPE:
1744 cf_last->error("The OPTIONAL component of USE-NIL must be "
1745 "a character-encodable type, or a sequence, set, choice, "
1746 "sequence-of, set-of or open type.");
1747 break;
1748 case EMBED_CHARENC:
1749 cf_last->error("In a sequence type with EMBED-VALUES and USE-NIL, "
1750 "the optional component supporting USE-NIL shall not be "
1751 "a character-encodable type.");
1752 break;
3f84031e 1753 case NOT_COMPATIBLE_WITH_USEORDER:
1754 cf_last->error("The OTIONAL component of USE-NIL must be "
1755 "a SEQUENCE/record when USE-ORDER is set for the parent type.");
1756 break;
1757 case BAD_ENUM:
1758 if (!the_enum) FATAL_ERROR("Type::chk_xer_use_order()");
1759 the_enum->error("Enumeration items should match the"
1760 " non-attribute components of the field %s",
1761 cf_last->get_name().get_dispname().c_str());
1762 break;
1763 case FIRST_OPTIONAL:
1764 error("The record-of for USE-ORDER shall not be marked"
1765 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1766 break;
1767 case NOTHING_TO_ORDER:
1768 error("The component (%s) should have at least one non-attribute"
1769 " component if USE-ORDER is present",
1770 cf_last->get_name().get_dispname().c_str());
1771 break;
1772 case FIRST_NOT_RECORD_OF_ENUM:
1773 error("The type with USE-ORDER should have a component "
1774 "which is a record-of enumerated");
1775 break;
1776 case ENUM_GAP:
1777 if (!the_enum) FATAL_ERROR("Type::chk_xer_use_order()");
1778 the_enum->error("Enumeration values must start at 0 and have no gaps");
1779 break;
970ed795
EL
1780 } // switch
1781 } // if USE-NIL
1782}
1783
1784void Type::chk_xer_use_order(int num_attributes)
1785{
1786 Type * const last = get_type_refd_last();
1787
1788 enum complaint_type { ALL_GOOD, NOT_SEQUENCE, NOT_ENOUGH_MEMBERS,
1789 FIRST_NOT_RECORD_OF, FIRST_NOT_RECORD_OF_ENUM, FIRST_OPTIONAL,
1790 LAST_NOT_RECORD, BAD_ENUM, ENUM_GAP, NOTHING_TO_ORDER };
1791 complaint_type complaint = ALL_GOOD;
1792 Type *the_enum = 0; // Well, it's supposed to be an enum.
1793 switch (last->typetype) {
1794 case T_SEQ_A: case T_SEQ_T: { // record/SEQUENCE acceptable
1795 size_t useorder_index = xerattrib->embedValues_;
1796 // The first (or second, if the first is taken by EMBED_VALUES)
1797 // member must be a record of enumerated
1798 if (useorder_index >= last->get_nof_comps()) {
1799 complaint = NOT_ENOUGH_MEMBERS;
1800 break;
1801 }
1802 CompField *uo_field = last->get_comp_byIndex(useorder_index);
1803 Type *uot = uo_field->get_type();
1804 if (uot->get_type_refd_last()->typetype == T_SEQOF) {
1805 the_enum = uot->get_ofType()->get_type_refd_last();
1806 switch (the_enum->typetype) {
1807 case T_ENUM_A: case T_ENUM_T: // acceptable
1808 if (uo_field->get_is_optional() || uo_field->get_defval() != 0) {
1809 complaint = FIRST_OPTIONAL;
1810 }
1811 break;
1812 default:
1813 complaint = FIRST_NOT_RECORD_OF_ENUM;
1814 goto complain2;
1815 } // switch enum type
1816 size_t ncomps = last->get_nof_comps();
1817 // the components of this sequence will have to match the enum
1818 Type *sequence_type = 0;
1819 size_t expected_enum_items, first_non_attr;
1820
1821 if (xerattrib->useNil_) { // useNil in addition to useOrder
1822 // This is an additional complication because USE-ORDER
1823 // will affect the optional component, rather than the type itself
3f84031e 1824 CompField *cf = last->get_comp_byIndex(ncomps-1);
970ed795
EL
1825 sequence_type = cf->get_type()->get_type_refd_last();
1826 if (sequence_type->typetype == T_SEQ_T
1827 ||sequence_type->typetype == T_SEQ_A) {
1828
1829 // No need to check that it has at least one component (35.2.1)
1830 // it can't match up with the enum which always has one
1831 ncomps = sequence_type->get_nof_comps();
1832 expected_enum_items = ncomps;
1833 first_non_attr = 0;
1834 }
1835 else { // Whoops, not a sequence type!
1836 complaint = LAST_NOT_RECORD;
1837 break; // the switch(typetype)
1838 }
1839 }
1840 else {
1841 sequence_type = last;
1842 first_non_attr = useorder_index+1+num_attributes;
1843 expected_enum_items = ncomps - first_non_attr;
1844 } // if (use-nil)
1845
1846 size_t enum_index = 0;
1847 if (expected_enum_items == 0)
1848 complaint = NOTHING_TO_ORDER;
1849 else if (the_enum->u.enums.eis->get_nof_eis() != expected_enum_items)
1850 complaint = BAD_ENUM;
1851 else for (size_t i = first_non_attr; i < ncomps; ++i) {
1852 CompField *cf = sequence_type->get_comp_byIndex(i);
1853 Type *cft = cf->get_type();
1854 if (cft->xerattrib && cft->xerattrib->attribute_) continue;
1855 // Found a non-attribute component. Its name must match an enumval
1856 const Identifier& field_name = cf->get_name();
1857 // don't use get_eis_index_byName(); fatal error if not found :(
1858 const EnumItem *ei = the_enum->get_ei_byIndex(enum_index);
1859 const Identifier& enum_name = ei->get_name();
1860 if (field_name != enum_name) {// X.693amd1 35.2.2.1 and 35.2.2.2
1861 complaint = BAD_ENUM;
1862 break;
1863 }
1864 Value *v = ei->get_value();
1865 const int_val_t *ival = v->get_val_Int();
1866 const Int enumval = ival->get_val();
1867 if ((size_t)enumval != enum_index) {
1868 complaint = ENUM_GAP; // 35.2.2.3
1869 break;
1870 }
1871 ++enum_index;
1872 } // next enum component
1873 }
1874 else {
1875 complaint = FIRST_NOT_RECORD_OF;
1876 complain2:;
1877 }
1878 break; }
1879 default:
1880 complaint = NOT_SEQUENCE;
1881 break;
1882 } // switch typetype
1883
1884 if (complaint == ALL_GOOD) use_order_possible = true;
1885 else if (xerattrib->useOrder_) {
1886 switch (complaint) {
1887 case ALL_GOOD: // Not possible; present in the switch so GCC checks
1888 // that all enum values are handled (make sure there's no default).
1889 break;
1890 case NOT_SEQUENCE:
1891 error("USE-ORDER can only be assigned to a SEQUENCE/record type.");
1892 break;
1893 case NOT_ENOUGH_MEMBERS:
1894 case FIRST_NOT_RECORD_OF:
1895 case FIRST_NOT_RECORD_OF_ENUM:
1896 error("The type with USE-ORDER should have a component "
1897 "which is a record-of enumerated");
1898 break;
1899 case FIRST_OPTIONAL:
1900 error("The record-of for USE-ORDER shall not be marked"
1901 " OPTIONAL or DEFAULT"); // X.693amd1 35.2.3
1902 break;
1903 case NOTHING_TO_ORDER:
1904 error("The type with USE-ORDER should have at least one "
1905 "non-attribute component");
1906 break;
1907 case LAST_NOT_RECORD:
1908 error("The OPTIONAL component supporting the USE-NIL "
1909 "encoding instruction should be a SEQUENCE/record");
1910 break;
1911 case BAD_ENUM:
1912 if (!the_enum) FATAL_ERROR("Type::chk_xer_use_order()");
1913 the_enum->error("Enumeration items should match the"
1914 " non-attribute components of the sequence");
1915 break;
1916 case ENUM_GAP:
1917 if (!the_enum) FATAL_ERROR("Type::chk_xer_use_order()");
1918 the_enum->error("Enumeration values must start at 0 and have no gaps");
1919 break;
1920 } //switch
1921 } // if USE-ORDER
1922}
1923
1924void Type::chk_xer_use_type()
1925{
1926 Type * const last = get_type_refd_last();
1927
1928 const char *ns, *prefix;
1929 my_scope->get_scope_mod()->get_controlns(ns, prefix);
1930 if (!prefix) error("Type has USE-TYPE, but the module has no control namespace set");
1931
1932 switch (last->typetype) {
1933 // USE-TYPE applied to anytype ? Just say no.
1934 case T_CHOICE_A: case T_CHOICE_T: { // must be CHOICE; 37.2.1
1935 if (xerattrib->untagged_ || xerattrib->useUnion_) { // 37.2.5
1936 error("A type with USE-TYPE encoding instruction shall not also have"
1937 " any of the final encoding instructions UNTAGGED or USE-UNION");
1938 }
1939 // Now check the alternatives.
1940 // iterating backwards calls get_nof_comps only once
1941 for (int i = last->get_nof_comps() - 1; i >= 0; --i) {
1942 CompField *cf = last->get_comp_byIndex(i);
1943 Type *cft = cf->get_type();
1944 if (cft->xerattrib && cft->xerattrib->untagged_) {
1945 cf->error("Alternative of a union with USE-TYPE should not have UNTAGGED"); // 37.2.2
1946 break;
1947 }
1948 switch (cft->typetype) {
1949 case T_CHOICE_A: case T_CHOICE_T:
1950 if (cft->xerattrib && cft->xerattrib->useType_) {
1951 cf->error("Alternative of a CHOICE type with USE-TYPE shall not be"
1952 " a CHOICE type with a USE-TYPE encoding instruction"); // 37.2.3
1953 }
1954 break;
1955 default:
1956 break;
1957 }
1958 }
1959 break; }
1960 default:
1961 error("USE-TYPE can only applied to a CHOICE/union type");
1962 break;
1963 } // switch
1964}
1965
1966void Type::chk_xer_use_union()
1967{
1968 Type * const last = get_type_refd_last();
1969 switch (last->typetype) {
1970 case T_CHOICE_A: case T_CHOICE_T: {
1971 // Now check the alternatives.
1972 // iterating backwards calls get_nof_comps only once
1973 for (int i = last->get_nof_comps() - 1; i >= 0; --i) {
1974 CompField *cf = last->get_comp_byIndex(i);
1975 Type *cft = cf->get_type();
1976 if (cft->is_charenc() && !(cft->xerattrib && cft->xerattrib->useType_) &&
1977 !(cft->xerattrib && cft->xerattrib->useQName_)) { // currently not supported
1978 if (cft->xerattrib && cft->xerattrib->useUnion_) // it must be a union
1979 cf->error("Alternative of a CHOICE/union with USE-UNION"
1980 " can not itself be a CHOICE/union with USE-UNION");
1981 }
1982 else cf->error("Alternative of a CHOICE/union with USE-UNION must be character-encodable");
1983 }
1984 break; }
1985 default:
1986 error("USE-UNION can only applied to a CHOICE/union type"); // 38.2.1
1987 break;
1988 }
1989
1990}
1991
1992static const char *xml98 = "http://www.w3.org/XML/1998/namespace";
1993
1994void Type::chk_xer() { // XERSTUFF semantic check
1995 // the type (and everything it contains) is fully checked now
1996
1997 if (xer_checked) return;
1998 xer_checked = true;
1999
2000 Type *last = get_type_refd_last();
2001
2002 // Check XER attributes if the type belongs to a type definition,
2003 // a field of a record/set/union, or is the embedded type of a record-of.
2004 if (ownertype==OT_TYPE_DEF
2005 ||ownertype==OT_COMP_FIELD
2006 ||ownertype==OT_RECORD_OF) {
2007 XerAttributes *newx = 0;
2008 if (is_ref()) {
2009 // Merge XER attributes from the referenced type.
2010 // This implements X.693amd1 clause 15.1.2
2011 newx = new XerAttributes;
2012 Type *t1 = get_type_refd();
2013 // chk_refd() (called by chk() for T_REFD) does not check
2014 // the referenced type; do it now. This makes it fully recursive.
2015 t1->chk();
2016
2017 size_t old_text = 0;
2018 if (t1->xerattrib && !t1->xerattrib->empty()) {
2019 old_text = t1->xerattrib->num_text_;
2020 *newx |= *t1->xerattrib; // get the ancestor's attributes, except...
2021 newx->attribute_ = false; // attribute is not inherited
2022 newx->element_ = false; // element is not inherited
2023
2024 if (ownertype == OT_TYPE_DEF
2025 ||ownertype == OT_COMP_FIELD) {
2026 // Name,Namespace is not inherited, X.693 amd1, 13.6
2027 // are you sure about the namespace?
2028 XerAttributes::FreeNameChange(newx->name_);
2029 //XerAttributes::FreeNamespace(newx->namespace_); // HR39678 bugfix beta
2030 }
2031 }
2032 // Now merge/override with our own attributes
2033 if (xerattrib && !xerattrib->empty()) {
2034 if (xerattrib->num_text_ > 0 && old_text > 0
2035 && (last->typetype == T_ENUM_T || last->typetype == T_ENUM_A)) {
2036 // Adding more TEXT attributes does not work right.
2037 error("Adding more TEXT attributes is not supported "
2038 "by the implementation.");
2039 }
2040 *newx |= *xerattrib;
2041 }
2042
2043 if (newx->empty()) delete newx;
2044 else { // something interesting was found
2045 delete xerattrib;
2046 xerattrib = newx;
2047
2048 if (xerattrib->attribute_
2049 && t1->xerattrib && t1->xerattrib->attribute_
2050 && t1->ownertype == OT_TYPE_DEF
2051 && !(xerattrib->form_ & XerAttributes::LOCALLY_SET) ) {
2052 // The referenced type came from a global XSD attribute.
2053 // This type's form will be qualified, unless it has an explicit
2054 // "form as ..." (which overrides everything).
2055 xerattrib->form_ |= XerAttributes::QUALIFIED;
2056 }
2057
2058 if (t1->xerattrib && t1->xerattrib->element_
2059 // The referenced type came from a global XSD element.
2060 && !(xerattrib->form_ & XerAttributes::LOCALLY_SET))
2061 { // and it doesn't have an explicit "form as ..."
2062 xerattrib->form_ |= XerAttributes::QUALIFIED;
2063 }
2064 }
2065 } // if is_ref
2066 } // if ownertype
2067
2068 if (!xerattrib) return;
2069
2070//const char *fn = get_fullname().c_str();
2071//printf("chk_xer(%s)\n", fn);
2072
2073 // In general, "last" should be used instead of "this" in the checks below
2074 // when accessing information about the type's characteristics, except
2075 // this->xerattrib MUST be used (and not last->xerattrib!).
2076
2077 switch (ownertype) {
2078 case OT_COMP_FIELD:
2079 case OT_TYPE_DEF:
2080 case OT_RECORD_OF:
2081 // acceptable
2082 break;
2083
2084 default:
2085 FATAL_ERROR("Unexpected ownertype %d", ownertype);
2086 }
2087
2088 int num_attributes = 0;
2089 switch (last->typetype) {
2090 case T_SEQ_A: case T_SEQ_T:
2091 case T_SET_A: case T_SET_T: {
2092 // Count attributes (ANY-ATTRIBUTES counts as one)
2093 const size_t num_cf = last->get_nof_comps();
2094 int specials = xerattrib->embedValues_ + xerattrib->useOrder_;
2095 int num_any_attributes = 0;
2096 for (int x = num_cf - 1; x >= specials; --x) {
2097 CompField *cf = last->get_comp_byIndex(x);
2098 Type *cft = cf->get_type() /* NOT get_type_refd_last() */;
2099 if (cft->xerattrib
2100 && (cft->xerattrib->attribute_ || has_aa(cft->xerattrib)))
2101 {
2102 if (cft->xerattrib->attribute_) ++num_attributes;
2103 else if (++num_any_attributes > 1) {
2104 cf->error("There can be at most one field with ANY-ATTRIBUTES");
2105 }
2106 }
2107 else if (num_attributes + num_any_attributes > 0) {
2108 // Found a non-attribute when there was an attribute after it
2109 cf->error("Non-attribute field before attribute not supported");
2110 }
2111 } // next
2112
2113 num_attributes += num_any_attributes;
2114 break; }
2115
2116 default:
2117 break;
2118 }
2119
2120 /* * * Check restrictions set out in X.693 amd1, clauses 18-39 * * */
2121
2122 if (has_aa(xerattrib)) {
2123 chk_xer_any_attributes();
2124 } // if ANY-ATTRIBUTES
2125
2126 if (has_ae(xerattrib)) {
2127 chk_xer_any_element();
2128 } // if ANY-ELEMENT
2129
2130 if (xerattrib->attribute_) {
2131 chk_xer_attribute();
2132 // It's an attribute, check for the attributeFormQualified bit
2133 // and transform it into unconditionally qualified.
2134 if (!(xerattrib->form_ & XerAttributes::LOCALLY_SET)
2135 && (xerattrib->form_ & XerAttributes::ATTRIBUTE_DEFAULT_QUALIFIED)) {
2136 xerattrib->form_ |= XerAttributes::QUALIFIED;
2137 }
2138 }
2139 else {
2140 // Element, check the elementFormQualified bit.
2141 if (!(xerattrib->form_ & XerAttributes::LOCALLY_SET)
2142 && (xerattrib->form_ & XerAttributes::ELEMENT_DEFAULT_QUALIFIED)) {
2143 xerattrib->form_ |= XerAttributes::QUALIFIED;
2144 }
2145 } // if ATTRIBUTE
2146
2147 if (xerattrib->base64_) {
2148 switch (last->typetype) {
2149 case T_OSTR: // OCTET STRING
2150 case T_HSTR: // hexstring
2151 case T_OPENTYPE:
2152 case T_BMPSTRING:
2153 case T_GENERALSTRING:
2154 case T_GRAPHICSTRING:
2155 case T_IA5STRING:
2156 // ISO646String ?
2157 case T_NUMERICSTRING:
2158 case T_PRINTABLESTRING:
2159 case T_TELETEXSTRING:
2160 // T61
2161 case T_UNIVERSALSTRING:
2162 case T_UTF8STRING:
2163 case T_VIDEOTEXSTRING:
2164 case T_VISIBLESTRING:
2165 // TTCN types
2166 case T_CSTR:
2167 case T_USTR:
2168 break; // acceptable
2169 default:
2170 error("BASE64 can only be applied to OCTET STRING, open type or "
2171 "restricted character string type");
2172 break;
2173 } // switch
2174
2175 if (has_ae(xerattrib) || xerattrib->whitespace_ != XerAttributes::PRESERVE) {
2176 error("A type with BASE64 shall not have any of the final "
2177 "encoding instructions ANY-ELEMENT or WHITESPACE");
2178 }
2179 } // if BASE64
2180
2181 if (xerattrib->decimal_) {
2182 if (last->typetype != T_REAL) {
2183 error("DECIMAL shall only be assigned to a real type");
2184 }
2185 } // if DECIMAL
2186
2187 if (xerattrib->defaultForEmpty_ != 0) {
2188 chk_xer_dfe();
2189 } // if defaultForEmpty
2190
2191 chk_xer_embed_values(num_attributes); // always
2192
2193 if (xerattrib->list_) {
2194 switch (last->typetype) {
2195 case T_SEQOF: case T_SETOF:
2196 break; // acceptable
2197 default:
2198 error("LIST can only be assigned to SEQUENCE-OF or SET-OF");// 27.2.1
2199 break;
2200 }
2201
2202 if (has_aa(xerattrib)) {
2203 error("A type with LIST shall not have ANY-ATTRIBUTES");// 27.2.3
2204 }
2205 } // if LIST
2206
2207 // NAME is handled later when generate_code_xerdescriptor call change_name
2208
2209 if ((unsigned long)xerattrib->namespace_.keyword
2210 > (unsigned long)NamespaceSpecification::LOWERCASED) {
2211 // Now both are proper non-NULL strings
2212 if (*xerattrib->namespace_.prefix != 0) { // there is a prefix, check it
2213 char first[4] = {0,0,0,0};
2214 strncpy(first, xerattrib->namespace_.prefix, 3);
2215 first[0] = toupper(first[0]);
2216 first[1] = toupper(first[1]);
2217 first[2] = toupper(first[2]);
2218 if (!memcmp(first, "XML", 3) // It _is_ "xml"
2219 // but the W3C XML namespace gets an exemption
2220 && strcmp(xerattrib->namespace_.uri, xml98)) error(
2221 "Prefix shall not commence with characters that"
2222 " when uppercased are 'XML'");
2223 // X.693 (11/2008), clause 29.1.7
2224 }
2225
2226 Common::Module::add_namespace(
2227 xerattrib->namespace_.uri, xerattrib->namespace_.prefix);
2228 }
2229 else xerattrib->namespace_.uri = NULL; // really no namespace
2230
2231 // PI-OR-COMMENT not supported
2232
2233 if (xerattrib->num_text_ > 0) {
2234 chk_xer_text();
2235 }
2236
2237 if (xerattrib->untagged_) {
2238 chk_xer_untagged();
2239 } // if UNTAGGED
2240
2241 chk_xer_use_nil(); // always
2242
2243 if (xerattrib->useNumber_) {
2244 switch (last->typetype) {
2245 case T_ENUM_A:
2246 error("No XER yet for ASN.1 enumerations");
2247 // no break
2248 case T_ENUM_T:
2249 break; // acceptable
2250 default:
2251 warning("USE-NUMBER ignored unless assigned to an enumerated type");
2252 xerattrib->useNumber_ = false;
2253 break;
2254 }
2255
2256 if (xerattrib->num_text_) {
2257 error("A type with USE-NUMBER shall not have TEXT");
2258 }
2259 } // if USE-NUMBER
2260
2261 chk_xer_use_order(num_attributes); //always
2262
2263 if (xerattrib->useQName_) {
2264 switch (last->typetype) {
2265 case T_SEQ_A: case T_SEQ_T: {
2266 if (last->get_nof_comps() != 2) goto complain;
2267 const CompField * cf = last->get_comp_byIndex(0);
2268 const Type * cft = cf->get_type()->get_type_refd_last();
2269 if (cft->typetype != T_USTR && cft->typetype != T_UTF8STRING)
2270 cft->error ("Both components must be UTF8String or universal charstring");
2271 if (!cf->get_is_optional()) cft->error(
2272 "The first component of a type with USE-QNAME must be optional");
2273
2274 cf = last->get_comp_byIndex(1);
2275 cft = cf->get_type()->get_type_refd_last();
2276 if (cft->typetype != T_USTR && cft->typetype != T_UTF8STRING)
2277 cft->error ("Both components must be UTF8String or universal charstring");
2278 if (cf->get_is_optional()) cft->error(
2279 "The second component of a type with USE-QNAME must NOT be optional");
2280 break; }
2281
2282 default:
2283 complain:
2284 error("A type with USE-QNAME must be a sequence type with exactly two components.");
2285 break;
2286 }
2287 if (xerattrib->useNil_) error("A type with USE-QNAME shall not have USE-NIL"); // 36.2.4
2288 }
2289
2290 if (xerattrib->useType_) {
2291 chk_xer_use_type();
2292 } // if USE-TYPE
2293
2294 if (xerattrib->useUnion_) {
2295 chk_xer_use_union();
2296 }
2297
2298 if (is_secho()) {
2299 CompFieldMap& cfm = *u.secho.cfm;
2300 const size_t ncomps = cfm.get_nof_comps();
2301 CompField *the_one = 0; // ...and only untagged character-encodable field
2302 map<int, CompField> empties; // potentially empties
2303
2304 for (size_t i=0; i < ncomps; ++i) {
2305 CompField * cf = cfm.get_comp_byIndex(i);
2306 Type *cft = cf->get_type();
2307
2308 if (cft->xerattrib && cft->xerattrib->untagged_) {
2309 /* This check could be in chk_xer_untagged(), but then we couldn't
2310 * access the CompField in the parent type. */
2311 if (cft->is_charenc() == Yes) {
2312 if (the_one) { // already has one
2313 cf->error("More than one UNTAGGED character-encodable field");
2314 // break? to report only once
2315 }
2316 else {
2317 the_one = cf; // this is used for further checks below
2318 u.secho.has_single_charenc = true; // used while generating code
2319 switch (typetype) {
2320 case T_SEQ_A: case T_SEQ_T:
2321 if (xerattrib->untagged_) {
2322 error("Enclosing type of an UNTAGGED character-encodable type "
2323 "must not be UNTAGGED");
2324 }
2325 break; // the small switch
2326 default:
2327 error("Enclosing type of an UNTAGGED character-encodable type "
2328 "is not record.");
2329 break;
2330 } // switch
2331 } // if (the_one)
2332 }
2333 else { // untagged, not charenc
2334 switch (cft->get_type_refd_last()->typetype) {
2335 case T_SEQ_A: case T_SEQ_T:
2336 case T_SET_A: case T_SET_T:
2337 case T_CHOICE_A: case T_CHOICE_T:
2338 case T_SEQOF:
2339 case T_SETOF:
2340 //case T_OSTR: with a contained type
2341 //case T_BSTR_A: with a contained type
2342 //case T_OPENTYPE:
2343 break; //ok
2344
2345 default: // 32.2.3 "If the type is not character-encodable..."
2346 cft->error("UNTAGGED type should be sequence, set, choice, sequence-of, or set-of type");
2347 break;
2348 }
2349 } // if(is_charenc)
2350 } // if untagged
2351
2352 if (cft->has_empty_xml()) {
2353 empties.add(i, cf);
2354 }
2355 } // next component
2356
2357 if (the_one) {
2358 if (the_one->get_is_optional() || the_one->has_default()) {
2359 the_one->error("UNTAGGED field should not be marked OPTIONAL or DEFAULT");
2360 }
2361 // Check the other compfields. They must all be (ANY)?ATTRIBUTE
2362 for (size_t i=0; i < ncomps; ++i) {
2363 CompField *cf = cfm.get_comp_byIndex(i);
2364 if (cf == the_one) continue;
2365
2366 Type *cft = cf->get_type();
2367 if ( !cft->xerattrib // cannot be attribute, error
2368 || (!cft->xerattrib->attribute_ && !has_aa(cft->xerattrib))) {
2369 the_one->note("Due to this UNTAGGED component");
2370 cf->error("All the other components should be ATTRIBUTE or ANY-ATTRIBUTE");
2371 // X.693 (2008) 32.2.2
2372 break;
2373 }
2374 } // next i
2375 } // if the_one
2376
2377 if (empties.size() > 1
2378 && (typetype==T_CHOICE_A || typetype==T_CHOICE_T)) {
2379 warning("More than one field can have empty XML. Decoding of empty"
2380 " XML is ambiguous, %s chosen arbitrarily.",
2381 empties.get_nth_elem(empties.size()-1)->get_name().get_name().c_str());
2382 }
2383 empties.clear();
2384 } // if secho
51fa56b9 2385
2386 if (xerattrib->abstract_ || xerattrib->block_) {
2387 switch (ownertype) {
2388 case OT_COMP_FIELD:
2389 if (parent_type->typetype == T_CHOICE_A ||
2390 parent_type->typetype == T_CHOICE_T) {
2391 if (parent_type->xerattrib != NULL && parent_type->xerattrib->useUnion_) {
2392 error("ABSTRACT and BLOCK cannot be used on fields of a union with "
2393 "attribute USE-UNION.");
2394 }
2395 break;
2396 }
2397 // else fall through
2398 case OT_RECORD_OF:
2399 case OT_TYPE_DEF:
2400 warning("ABSTRACT and BLOCK only affects union fields.");
2401 break;
2402 default:
2403 break;
2404 }
2405 }
970ed795
EL
2406
2407}
2408
2409
2410void Type::chk_Int_A()
2411{
2412 if(checked) return;
2413 checked=true;
2414 if(!u.namednums.block) return;
2415 parse_block_Int();
2416 if(typetype==T_ERROR) return;
2417 /* check named numbers */
2418 if(!u.namednums.nvs) return;
2419 map<Int, NamedValue> value_map;
2420 Error_Context cntxt(this, "In named numbers");
2421 u.namednums.nvs->chk_dupl_id();
2422 for (size_t i = 0; i < u.namednums.nvs->get_nof_nvs(); i++) {
2423 NamedValue *nv = u.namednums.nvs->get_nv_byIndex(i);
2424 Value *value = nv->get_value();
2425 Value *v = value->get_value_refd_last();
2426 switch (v->get_valuetype()) {
2427 case Value::V_INT: {
2428 const int_val_t *int_val_int = v->get_val_Int();
2429 if (*int_val_int > INT_MAX) {
2430 value->error("Integer value `%s' is too big to be used as a named "
2431 "number", (int_val_int->t_str()).c_str());
2432 } else {
2433 Int int_val = int_val_int->get_val();
2434 if (value_map.has_key(int_val)) {
2435 value->error("Duplicate number %s for name `%s'",
2436 Int2string(int_val).c_str(),
2437 nv->get_name().get_dispname().c_str());
2438 NamedValue *nv2 = value_map[int_val];
2439 nv2->note("Number %s is already assigned to name `%s'",
2440 Int2string(int_val).c_str(),
2441 nv2->get_name().get_dispname().c_str());
2442 } else {
2443 value_map.add(int_val, nv);
2444 }
2445 }
2446 break; }
2447 case Value::V_ERROR:
2448 break;
2449 default:
2450 nv->error("INTEGER value was expected for named number `%s'",
2451 nv->get_name().get_dispname().c_str());
2452 break;
2453 }
2454 }
2455 value_map.clear();
2456}
2457
2458void Type::chk_Enum_A()
2459{
2460 if(checked) return;
2461 if(!u.enums.block) return;
2462 parse_block_Enum();
2463 if(typetype==T_ERROR) return;
2464 /* checking enumerations */
2465 map<Int, EnumItem> value_map;
2466 /* checking values before the ellipsis */
2467 for (size_t i = 0; i < u.enums.eis1->get_nof_eis(); i++)
2468 chk_Enum_item(u.enums.eis1->get_ei_byIndex(i), false, value_map);
2469 /* assigning default values */
2470 Int& first_unused = u.enums.first_unused;
2471 for (first_unused = 0; value_map.has_key(first_unused); first_unused++) ;
2472 for (size_t i = 0; i < u.enums.eis1->get_nof_eis(); i++) {
2473 EnumItem *ei = u.enums.eis1->get_ei_byIndex(i);
2474 if (!ei->get_value()) {
2475 ei->set_value(new Value(Value::V_INT, first_unused));
2476 value_map.add(first_unused, ei);
2477 while (value_map.has_key(++first_unused)) ;
2478 }
2479 }
2480 /* checking values after the ellipsis */
2481 if(u.enums.eis2) {
2482 for(size_t i=0; i < u.enums.eis2->get_nof_eis(); i++)
2483 chk_Enum_item(u.enums.eis2->get_ei_byIndex(i), true, value_map);
2484 }
2485 /* determining the first two unused non-negative integer values
2486 * for code generation */
2487 for (first_unused = 0; value_map.has_key(first_unused); first_unused++) ;
2488 Int& second_unused = u.enums.second_unused;
2489 for (second_unused = first_unused + 1; value_map.has_key(second_unused);
2490 second_unused++) ;
2491 value_map.clear();
2492 u.enums.eis1->release_eis();
2493 delete u.enums.eis1;
2494 u.enums.eis1 = 0;
2495 if(u.enums.eis2) {
2496 u.enums.eis2->release_eis();
2497 delete u.enums.eis2;
2498 u.enums.eis2 = 0;
2499 }
2500}
2501
2502void Type::chk_Enum_item(EnumItem *ei, bool after_ellipsis,
2503 map<Int, EnumItem>& value_map)
2504{
2505 const Identifier& name = ei->get_name();
2506 const char *dispname_str = name.get_dispname().c_str();
2507 if (u.enums.eis->has_ei_withName(name)) {
2508 ei->error("Duplicate ENUMERATED identifier: `%s'", dispname_str);
2509 u.enums.eis->get_ei_byName(name)->note("Previous definition of `%s' "
2510 "is here", dispname_str);
2511 } else if (!name.get_has_valid(Identifier::ID_TTCN)) {
2512 ei->warning("The identifier `%s' is not reachable from TTCN-3",
2513 dispname_str);
2514 }
2515 u.enums.eis->add_ei(ei);
2516 Int& first_unused=u.enums.first_unused;
2517 Value *value = ei->get_value();
2518 if (value) {
2519 Value *v;
2520 {
2521 Error_Context cntxt(ei, "In enumeration `%s'", dispname_str);
2522 v = value->get_value_refd_last();
2523 }
2524 switch (v->get_valuetype()) {
2525 case Value::V_INT:
2526 break;
2527 case Value::V_ERROR:
2528 return;
2529 default:
2530 value->error("INTEGER value was expected for enumeration `%s'",
2531 dispname_str);
2532 return;
2533 }
2534 Int enum_value = v->get_val_Int()->get_val();
2535 if (static_cast<Int>(static_cast<int>(enum_value)) != enum_value) {
2536 value->error("The numeric value of enumeration `%s' (%s) is too "
2537 "large for being represented in memory", dispname_str,
2538 Int2string(enum_value).c_str());
2539 }
2540 if (after_ellipsis) {
2541 if (enum_value >= first_unused) {
2542 value_map.add(enum_value, ei);
2543 for (first_unused = enum_value + 1; value_map.has_key(first_unused);
2544 first_unused++) ;
2545 } else {
2546 value->error("ENUMERATED values shall be monotonically growing after "
2547 "the ellipsis: the value of `%s' must be at least %s instead of %s",
2548 dispname_str, Int2string(first_unused).c_str(),
2549 Int2string(enum_value).c_str());
2550 }
2551 } else {
2552 if (value_map.has_key(enum_value)) {
2553 value->error("Duplicate numeric value %s for enumeration `%s'",
2554 Int2string(enum_value).c_str(), dispname_str);
2555 EnumItem *ei2 = value_map[enum_value];
2556 ei2->note("Value %s is already assigned to `%s'",
2557 Int2string(enum_value).c_str(),
2558 ei2->get_name().get_dispname().c_str());
2559 } else value_map.add(enum_value, ei);
2560 }
2561 } else { // the item has no value
2562 if (after_ellipsis) {
2563 ei->set_value(new Value(Value::V_INT, first_unused));
2564 value_map.add(first_unused, ei);
2565 while (value_map.has_key(++first_unused)) ;
2566 }
2567 }
2568}
2569
2570void Type::chk_Enum_T()
2571{
2572 if(checked) return;
2573 map<Int, EnumItem> value_map;
2574 map<string, EnumItem> name_map;
2575 bool error_flag = false;
2576 /* checking the uniqueness of identifiers and values */
2577 size_t nof_eis = u.enums.eis->get_nof_eis();
2578 for(size_t i = 0; i < nof_eis; i++) {
2579 EnumItem *ei = u.enums.eis->get_ei_byIndex(i);
2580 const Identifier& id = ei->get_name();
2581 const string& name = id.get_name();
2582 if (name_map.has_key(name)) {
2583 const char *dispname_str = id.get_dispname().c_str();
2584 ei->error("Duplicate enumeration identifier `%s'", dispname_str);
2585 name_map[name]->note("Previous definition of `%s' is here",
2586 dispname_str);
2587 error_flag = true;
2588 } else {
2589 name_map.add(name, ei);
2590 }
2591 Value *value = ei->get_value();
2592 if (value) {
2593 /* Handle the error node created by the parser. */
2594 if (value->get_valuetype() == Value::V_ERROR) {
2595 value->error("INTEGER value was expected for enumeration `%s'",
2596 id.get_dispname().c_str());
2597 error_flag = true;
2598 } else {
2599 const int_val_t *enum_value_int = value->get_val_Int();
2600 // It used to be the same check.
2601 if (*enum_value_int > INT_MAX ||
2602 static_cast<Int>(static_cast<int>(enum_value_int->get_val()))
2603 != enum_value_int->get_val()) {
2604 value->error("The numeric value of enumeration `%s' (%s) is "
2605 "too large for being represented in memory",
2606 id.get_dispname().c_str(), (enum_value_int->t_str()).c_str());
2607 error_flag = true;
2608 } else {
2609 Int enum_value = enum_value_int->get_val();
2610 if (value_map.has_key(enum_value)) {
2611 const char *dispname_str = id.get_dispname().c_str();
2612 value->error("Duplicate numeric value %s for enumeration `%s'",
2613 Int2string(enum_value).c_str(), dispname_str);
2614 EnumItem *ei2 = value_map[enum_value];
2615 ei2->note("Value %s is already assigned to `%s'",
2616 Int2string(enum_value).c_str(),
2617 ei2->get_name().get_dispname().c_str());
2618 error_flag = true;
2619 } else {
2620 value_map.add(enum_value, ei);
2621 }
2622 }
2623 }
2624 }
2625 }
2626 if (!error_flag) {
2627 /* assigning default values */
2628 Int& first_unused=u.enums.first_unused;
2629 for(first_unused=0; value_map.has_key(first_unused); first_unused++) ;
2630 for(size_t i = 0; i < nof_eis; i++) {
2631 EnumItem *ei = u.enums.eis->get_ei_byIndex(i);
2632 if(!ei->get_value()) {
2633 ei->set_value(new Value(Value::V_INT, first_unused));
2634 value_map.add(first_unused, ei);
2635 while (value_map.has_key(++first_unused)) ;
2636 }
2637 }
2638 Int& second_unused = u.enums.second_unused;
2639 for (second_unused = first_unused + 1; value_map.has_key(second_unused);
2640 second_unused++) ;
2641 }
2642 value_map.clear();
2643 name_map.clear();
2644}
2645
2646void Type::chk_BStr_A()
2647{
2648 if(!u.namednums.block) return;
2649 parse_block_BStr();
2650 if(typetype==T_ERROR) return;
2651 if(u.namednums.nvs) {
2652 /* check named bits */
2653 map<Int, NamedValue> value_map;
2654 {
2655 Error_Context cntxt(this, "In named bits");
2656 u.namednums.nvs->chk_dupl_id();
2657 }
2658 for(size_t i = 0; i < u.namednums.nvs->get_nof_nvs(); i++) {
2659 NamedValue *nv = u.namednums.nvs->get_nv_byIndex(i);
2660 const char *dispname_str = nv->get_name().get_dispname().c_str();
2661 Value *value = nv->get_value();
2662 Value *v;
2663 {
2664 Error_Context cntxt(this, "In named bit `%s'", dispname_str);
2665 v = value->get_value_refd_last();
2666 }
2667 switch (v->get_valuetype()) {
2668 case Value::V_INT:
2669 break;
2670 case Value::V_ERROR:
2671 continue;
2672 default:
2673 v->error("INTEGER value was expected for named bit `%s'",
2674 dispname_str);
2675 continue;
2676 }
2677 const int_val_t *int_val_int = v->get_val_Int();
2678 if (*int_val_int > INT_MAX) {
2679 value->error("An INTEGER value less than `%d' was expected for "
2680 "named bit `%s' instead of %s", INT_MAX, dispname_str,
2681 (int_val_int->t_str()).c_str());
2682 continue;
2683 }
2684 Int int_val = int_val_int->get_val();
2685 if(int_val < 0) {
2686 value->error("A non-negative INTEGER value was expected for named "
2687 "bit `%s' instead of %s", dispname_str,
2688 Int2string(int_val).c_str());
2689 continue;
2690 }
2691 if (value_map.has_key(int_val)) {
2692 value->error("Duplicate value %s for named bit `%s'",
2693 Int2string(int_val).c_str(), dispname_str);
2694 NamedValue *nv2 = value_map[int_val];
2695 nv2->note("Bit %s is already assigned to name `%s'",
2696 Int2string(int_val).c_str(),
2697 nv2->get_name().get_dispname().c_str());
2698 } else value_map.add(int_val, nv);
2699 }
2700 value_map.clear();
2701 }
2702}
2703
2704void Type::chk_SeCho_T()
2705{
2706 u.secho.cfm->set_my_type(this);
2707 checked = true;
2708 u.secho.cfm->chk();
2709 u.secho.component_internal = false;
2710 size_t nof_comps = u.secho.cfm->get_nof_comps();
2711 for (size_t i=0; i<nof_comps; i++) {
2712 Type* cft = u.secho.cfm->get_comp_byIndex(i)->get_type();
2713 if (cft && cft->is_component_internal()) {
2714 u.secho.component_internal = true;
2715 break;
2716 }
2717 }
2718}
2719
2720void Type::chk_Choice_A()
2721{
2722 if(u.secho.block) parse_block_Choice();
2723 if(typetype==T_ERROR) return;
2724 checked=true;
2725 if(u.secho.ctss->needs_auto_tags())
2726 u.secho.ctss->add_auto_tags();
2727 u.secho.ctss->chk();
2728 if (u.secho.ctss->get_nof_comps() <= 0)
2729 FATAL_ERROR("CHOICE type must have at least one alternative");
2730 u.secho.ctss->chk_tags();
2731}
2732
2733void Type::chk_Se_A()
2734{
2735 if(u.secho.block) parse_block_Se();
2736 if(typetype==T_ERROR) return;
2737 checked=true;
2738 tr_compsof();
2739 u.secho.ctss->chk();
2740 u.secho.ctss->chk_tags();
2741}
2742
2743void Type::chk_SeOf()
2744{
2745 u.seof.ofType->set_genname(get_genname_own(), string('0'));
2746 u.seof.ofType->set_parent_type(this);
2747 checked=true;
2748 const char *type_name;
2749 bool asn1 = is_asn1();
2750 switch (typetype) {
2751 case T_SEQOF:
2752 type_name = asn1 ? "SEQUENCE OF" : "record of";
2753 break;
2754 case T_SETOF:
2755 type_name = asn1 ? "SET OF" : "set of";
2756 break;
2757 default:
2758 type_name = "<unknown>";
2759 break;
2760 }
2761 Error_Context cntxt(this, "In embedded type of %s", type_name);
2762 u.seof.ofType->chk();
2763 if (!asn1) u.seof.ofType->chk_embedded(true, "embedded into another type");
2764 u.seof.component_internal = u.seof.ofType->is_component_internal();
2765}
2766
2767void Type::chk_refd()
2768{
2769 checked=true;
2770 ReferenceChain refch(this, "While checking referenced type");
2771 Type* t_last = get_type_refd_last(&refch);
2772 u.ref.component_internal = t_last->is_component_internal();
2773}
2774
2775void Type::chk_seltype()
2776{
2777 checked=true;
2778 u.seltype.type->set_genname(get_genname_own(), string('0'));
2779 ReferenceChain refch(this, "In selection type");
2780 get_type_refd_last(&refch);
2781 if(typetype==T_ERROR) return;
2782 u.seltype.type->chk();
2783}
2784
2785void Type::chk_Array()
2786{
2787 u.array.element_type->set_genname(get_genname_own(), string('0'));
2788 u.array.element_type->set_parent_type(this);
2789 checked = true;
2790 {
2791 Error_Context cntxt(this, "In element type of array");
2792 u.array.element_type->chk();
2793 u.array.element_type->chk_embedded(true, "embedded into an array type");
2794 }
2795 u.array.dimension->chk();
2796 u.array.component_internal = u.array.element_type->is_component_internal();
2797}
2798
2799void Type::chk_Signature()
2800{
2801 checked = true;
2802 u.signature.component_internal = false;
2803 if (u.signature.parameters) {
2804 u.signature.parameters->chk(this);
2805 size_t nof_params = u.signature.parameters->get_nof_params();
2806 for (size_t i=0; i<nof_params; i++) {
2807 Type* spt = u.signature.parameters->get_param_byIndex(i)->get_type();
2808 if (spt && spt->is_component_internal()) {
2809 u.signature.component_internal = true;
2810 break;
2811 }
2812 }
2813 }
2814 if (u.signature.return_type) {
2815 Error_Context cntxt(u.signature.return_type, "In return type");
2816 u.signature.return_type->set_genname(get_genname_own(), string('0'));
2817 u.signature.return_type->set_parent_type(this);
2818 u.signature.return_type->chk();
2819 u.signature.return_type->chk_embedded(false,
2820 "the return type of a signature");
2821 if (!u.signature.component_internal &&
2822 u.signature.return_type->is_component_internal())
2823 u.signature.component_internal = true;
2824 }
2825 if (u.signature.exceptions) {
2826 u.signature.exceptions->chk(this);
2827 if (!u.signature.component_internal) {
2828 size_t nof_types = u.signature.exceptions->get_nof_types();
2829 for (size_t i=0; i<nof_types; i++) {
2830 if (u.signature.exceptions->get_type_byIndex(i)->
2831 is_component_internal()) {
2832 u.signature.component_internal = true;
2833 break;
2834 }
2835 }
2836 }
2837 }
2838}
2839
2840void Type::chk_Fat()
2841{
2842 if(checked) return;
2843 checked = true;
2844 Scope *parlist_scope = my_scope;
2845 // the runs on clause must be checked before the formal parameter list
2846 // in order to determine the right scope
2847 if (u.fatref.runs_on.ref) {
2848 if (typetype == T_FUNCTION) u.fatref.is_startable = true;
2849 Error_Context cntxt2(u.fatref.runs_on.ref, "In `runs on' clause");
2850 u.fatref.runs_on.type = u.fatref.runs_on.ref->chk_comptype_ref();
2851 if(u.fatref.runs_on.type) {
2852 Ttcn::Module *my_module =
2853 dynamic_cast<Ttcn::Module*>(my_scope->get_scope_mod());
2854 if (!my_module) FATAL_ERROR("Type::chk_Fat()");
2855 parlist_scope = my_module->get_runs_on_scope(u.fatref.runs_on.type);
2856 }
2857 }
2858 u.fatref.fp_list->set_my_scope(parlist_scope);
2859 switch (typetype) {
2860 case T_FUNCTION:
2861 u.fatref.fp_list->chk(Ttcn::Definition::A_FUNCTION);
2862 u.fatref.fp_list->chk_noLazyParams();
2863 if (u.fatref.is_startable && !u.fatref.fp_list->get_startability())
2864 u.fatref.is_startable = false;
2865 if (u.fatref.return_type) {
2866 Error_Context cntxt2(u.fatref.return_type, "In return type");
2867 u.fatref.return_type->chk();
2868 u.fatref.return_type->chk_as_return_type(!u.fatref.returns_template,
2869 "function type");
2870 if (u.fatref.is_startable && u.fatref.return_type->get_type_refd_last()
2871 ->get_typetype() == T_DEFAULT) u.fatref.is_startable = false;
2872
2873 }
2874 break;
2875 case T_ALTSTEP:
2876 u.fatref.fp_list->chk(Ttcn::Definition::A_ALTSTEP);
2877 u.fatref.fp_list->chk_noLazyParams();
2878 break;
2879 case T_TESTCASE:
2880 u.fatref.fp_list->chk(Ttcn::Definition::A_TESTCASE);
2881 u.fatref.fp_list->chk_noLazyParams();
2882 if (u.fatref.system.ref) {
2883 Error_Context cntxt2(u.fatref.runs_on.ref, "In `system' clause");
2884 u.fatref.system.type = u.fatref.system.ref->chk_comptype_ref();
2885 }
2886 break;
2887 default:
2888 FATAL_ERROR("Type::chk_Fat()");
2889 }
2890 if (!semantic_check_only)
2891 u.fatref.fp_list->set_genname(get_genname_own());
2892}
2893
2894void Type::chk_address()
2895{
2896 Type *t = get_type_refd_last();
2897 switch (t->typetype) {
2898 case T_PORT:
2899 error("Port type `%s' cannot be the address type",
2900 t->get_typename().c_str());
2901 break;
2902 case T_COMPONENT:
2903 error("Component type `%s' cannot be the address type",
2904 t->get_typename().c_str());
2905 break;
2906 case T_SIGNATURE:
2907 error("Signature `%s' cannot be the address type",
2908 t->get_typename().c_str());
2909 break;
2910 case T_DEFAULT:
2911 error("Default type cannot be the address type");
2912 break;
2913 case T_ANYTYPE:
2914 error("TTCN-3 anytype cannot be the address type");
2915 break;
2916 default:
2917 return;
2918 }
2919 clean_up();
2920}
2921
2922void Type::chk_embedded(bool default_allowed, const char *error_msg)
2923{
2924 Type *t=get_type_refd_last();
2925 switch (t->typetype) {
2926 case T_PORT:
2927 error("Port type `%s' cannot be %s", t->get_typename().c_str(),
2928 error_msg);
2929 break;
2930 case T_SIGNATURE:
2931 error("Signature `%s' cannot be %s", t->get_typename().c_str(),
2932 error_msg);
2933 break;
2934 case T_DEFAULT:
2935 if (!default_allowed) error("Default type cannot be %s", error_msg);
2936 break;
2937 default:
2938 break;
2939 }
2940}
2941
2942void Type::chk_recursions(ReferenceChain& refch)
2943{
2944 if (recurs_checked) return;
2945 Type *t = this;
2946 for ( ; ; ) {
2947 if (!refch.add(t->get_fullname())) {
2948 // an error has been found (and reported by refch.add)
2949 recurs_checked = true;
2950 return;
2951 }
2952 if (!t->is_ref()) break;
2953 t = t->get_type_refd();
2954 }
2955 switch (t->typetype) {
2956 case T_SEQ_A:
2957 case T_SEQ_T:
2958 case T_SET_A:
2959 case T_SET_T:
2960 for(size_t i = 0; i < t->get_nof_comps(); i++) {
2961 CompField *cf = t->get_comp_byIndex(i);
2962 if(!cf->get_is_optional()) {
2963 refch.mark_state();
2964 cf->get_type()->chk_recursions(refch);
2965 refch.prev_state();
2966 }
2967 // an optional field can "stop" the recursion
2968 } // for i
2969 break;
2970 case T_CHOICE_A:
2971 case T_CHOICE_T: {
2972 refch.set_error_reporting(false);
2973 refch.mark_error_state();
2974 for (size_t i = 0; i < t->get_nof_comps(); ++i) {
2975 refch.mark_state();
2976 CompField* cf = t->get_comp_byIndex(i);
2977 cf->get_type()->chk_recursions(refch);
2978 refch.prev_state();
2979 }
2980
2981 if (refch.nof_errors() == t->get_nof_comps()) {
2982 refch.report_errors();
2983 }
2984
2985 refch.prev_error_state();
2986 refch.set_error_reporting(true);
2987 break;
2988 }
2989 case T_ANYTYPE:
2990 case T_OPENTYPE:
2991 if(t->get_nof_comps()==1)
2992 t->get_comp_byIndex(0)->get_type()->chk_recursions(refch);
2993 break;
2994 case T_ARRAY:
2995 t->get_ofType()->chk_recursions(refch);
2996 break;
2997 default:
2998 break;
2999 }
3000 recurs_checked = true;
3001}
3002
3003void Type::chk_constructor_name(const Identifier& p_id)
3004{
3005 switch (typetype) {
3006 case T_SEQ_T:
3007 case T_SEQ_A:
3008 case T_SET_T:
3009 case T_SET_A:
3010 case T_CHOICE_T:
3011 case T_CHOICE_A:
3012 case T_OPENTYPE:
3013 // T_ANYTYPE can not have a field of type anytype, no need to check.
3014 if (has_comp_withName(p_id)) {
3015 // HL26011: a field has the same name as the typedef.
3016 // Titan can't generate valid C++ code; better report an error.
3017 get_comp_byName(p_id)->error("Field name clashes with type name");
3018 }
3019 break;
3020 default: // can't have fields
3021 break;
3022 }
3023}
3024
3025bool Type::chk_startability()
3026{
3027 if(typetype != T_FUNCTION) FATAL_ERROR("Type::chk_startable()");
3028 if(!checked) chk_Fat();
3029 if(u.fatref.is_startable) return true;
3030 if (!u.fatref.runs_on.ref) error("Functions of type `%s' cannot be started "
3031 "on a parallel test component because the type does not have `runs on' "
3032 "clause", get_typename().c_str());
3033 u.fatref.fp_list->chk_startability("Functions of type",
3034 get_typename().c_str());
3035 if (u.fatref.return_type && u.fatref.return_type->is_component_internal()) {
3036 map<Type*,void> type_chain;
3037 char* err_str = mprintf("the return type or embedded in the return type "
3038 "of function type `%s' if it is started on a parallel test component",
3039 get_typename().c_str());
3040 u.fatref.return_type->chk_component_internal(type_chain, err_str);
3041 Free(err_str);
3042 }
3043 return false;
3044}
3045
3046void Type::chk_as_return_type(bool as_value, const char* what)
3047{
3048 Type *t = get_type_refd_last();
3049 switch(t->get_typetype()) {
3050 case Type::T_PORT:
3051 error("Port type `%s' cannot be the return type of a %s"
3052 , t->get_fullname().c_str(), what);
3053 break;
3054 case Type::T_SIGNATURE:
3055 if(as_value) error("A value of signature `%s' cannot be the "
3056 "return type of a %s", t->get_fullname().c_str(), what);
3057 break;
3058 default:
3059 break;
3060 }
3061}
3062
3063void Type::chk_this_value_ref(Value *value)
3064{
3065 switch (value->get_valuetype()) {
3066 case Value::V_UNDEF_LOWERID:
3067 switch(typetype) {
3068 case T_INT_A:
3069 if(value->is_asn1()) {
3070 chk_Int_A();
3071 if(u.namednums.nvs
3072 && u.namednums.nvs->has_nv_withName(*value->get_val_id())) {
3073 value->set_valuetype(Value::V_NAMEDINT);
3074 value->set_my_governor(this);
3075 return;
3076 }
3077 }
3078 break;
3079 case T_ENUM_A:
3080 case T_ENUM_T:
3081 if (has_ei_withName(*value->get_val_id())) {
3082 value->set_valuetype(Value::V_ENUM);
3083 value->set_my_governor(this);
3084 return;
3085 }
3086 break;
3087 case T_REFD:
3088 case T_SELTYPE:
3089 case T_REFDSPEC:
3090 case T_OCFT:
3091 get_type_refd()->chk_this_value_ref(value);
3092 return;
3093 default:
3094 break;
3095 } // switch
3096 /* default behavior: interpret as reference */
3097 value->set_valuetype(Value::V_REFD);
3098 break;
3099 default:
3100 break;
3101 }
3102}
3103
3104bool Type::chk_this_value(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
3105 namedbool incomplete_allowed, namedbool omit_allowed,
3106 namedbool sub_chk, namedbool implicit_omit, namedbool is_str_elem)
3107{
3108 bool self_ref = false;
3109 chk();
3110 Value *v_last = value->get_value_refd_last(0, expected_value);
3111 if (v_last->get_valuetype() == Value::V_OMIT) {
3112 if (!omit_allowed) {
3113 value->error("`omit' value is not allowed in this context");
3114 value->set_valuetype(Value::V_ERROR);
3115 }
3116 return false;
3117 }
3118
3119 switch (value->get_valuetype()) {
3120 case Value::V_ERROR:
3121 return false;
3122 case Value::V_REFD:
3123 return chk_this_refd_value(value, lhs, expected_value, 0, is_str_elem);
3124 case Value::V_INVOKE:
3125 chk_this_invoked_value(value, lhs, expected_value);
3126 return false; // assumes no self-ref in invoke
3127 case Value::V_EXPR:
3128 if (lhs) self_ref = value->chk_expr_self_ref(lhs);
3129 // no break
3130 case Value::V_MACRO:
3131 if (value->is_unfoldable(0, expected_value)) {
3132 typetype_t tt = value->get_expr_returntype(expected_value);
3133 if (!is_compatible_tt(tt, value->is_asn1())) {
3134 value->error("Incompatible value: `%s' value was expected",
3135 get_typename().c_str());
3136 value->set_valuetype(Value::V_ERROR);
3137 }
3138 return self_ref;
3139 }
3140 break;
3141 default:
3142 break;
3143 }
3144
3145 switch(typetype) {
3146 case T_ERROR:
3147 break;
3148 case T_NULL:
3149 chk_this_value_Null(value);
3150 break;
3151 case T_BOOL:
3152 chk_this_value_Bool(value);
3153 break;
3154 case T_INT:
3155 chk_this_value_Int(value);
3156 break;
3157 case T_INT_A:
3158 chk_this_value_Int_A(value);
3159 break;
3160 case T_REAL:
3161 chk_this_value_Real(value);
3162 break;
3163 case T_ENUM_A:
3164 case T_ENUM_T:
3165 chk_this_value_Enum(value);
3166 break;
3167 case T_BSTR:
3168 chk_this_value_BStr(value);
3169 break;
3170 case T_BSTR_A:
3171 chk_this_value_BStr_A(value);
3172 break;
3173 case T_HSTR:
3174 chk_this_value_HStr(value);
3175 break;
3176 case T_OSTR:
3177 chk_this_value_OStr(value);
3178 break;
3179 case T_CSTR:
3180 case T_USTR:
3181 case T_UTF8STRING:
3182 case T_NUMERICSTRING:
3183 case T_PRINTABLESTRING:
3184 case T_TELETEXSTRING:
3185 case T_VIDEOTEXSTRING:
3186 case T_IA5STRING:
3187 case T_GRAPHICSTRING:
3188 case T_VISIBLESTRING:
3189 case T_GENERALSTRING:
3190 case T_UNIVERSALSTRING:
3191 case T_BMPSTRING:
3192 case T_UTCTIME:
3193 case T_GENERALIZEDTIME:
3194 case T_OBJECTDESCRIPTOR:
3195 chk_this_value_CStr(value);
3196 break;
3197 case T_OID:
3198 chk_this_value_OID(value);
3199 break;
3200 case T_ROID:
3201 chk_this_value_ROID(value);
3202 break;
3203 case T_ANY:
3204 chk_this_value_Any(value);
3205 break;
3206 case T_CHOICE_A:
3207 case T_CHOICE_T:
3208 case T_OPENTYPE:
3209 case T_ANYTYPE:
3210 self_ref = chk_this_value_Choice(value, lhs, expected_value, incomplete_allowed,
3211 implicit_omit);
3212 break;
3213 case T_SEQ_T:
3214 case T_SET_T:
3215 case T_SEQ_A:
3216 case T_SET_A:
3217 self_ref = chk_this_value_Se(value, lhs, expected_value, incomplete_allowed,
3218 implicit_omit);
3219 break;
3220 case T_SEQOF:
3221 case T_SETOF:
3222 self_ref = chk_this_value_SeOf(value, lhs, expected_value, incomplete_allowed,
3223 implicit_omit);
3224 break;
3225 case T_REFD:
3226 self_ref = get_type_refd()->chk_this_value(value, lhs, expected_value,
3227 incomplete_allowed, omit_allowed, NO_SUB_CHK, implicit_omit, is_str_elem);
3228 break;
3229 case T_UNRESTRICTEDSTRING:
3230 case T_OCFT:
3231 case T_EXTERNAL:
3232 case T_EMBEDDED_PDV:
3233 case T_REFDSPEC:
3234 case T_SELTYPE:
3235 case T_ADDRESS:
3236 self_ref = get_type_refd()->chk_this_value(value, lhs, expected_value,
3237 incomplete_allowed, omit_allowed, NO_SUB_CHK, NOT_IMPLICIT_OMIT, is_str_elem);
3238 break;
3239 case T_VERDICT:
3240 chk_this_value_Verdict(value);
3241 break;
3242 case T_DEFAULT:
3243 chk_this_value_Default(value);
3244 break;
3245 case T_ARRAY:
3246 self_ref = chk_this_value_Array(value, lhs, expected_value, incomplete_allowed, implicit_omit);
3247 break;
3248 case T_PORT:
3249 // Remain silent. The error has already been reported in the definition
3250 // that the value belongs to.
3251 break;
3252 case T_SIGNATURE:
3253 self_ref = chk_this_value_Signature(value, lhs, expected_value, incomplete_allowed);
3254 break;
3255 case T_COMPONENT:
3256 chk_this_value_Component(value);
3257 break;
3258 case T_FUNCTION:
3259 case T_ALTSTEP:
3260 case T_TESTCASE:
3261 chk_this_value_FAT(value);
3262 break;
3263 default:
3264 FATAL_ERROR("Type::chk_this_value()");
3265 } // switch
3266
3267 // check value against subtype
3268 if(sub_chk && (sub_type!=NULL)) sub_type->chk_this_value(value);
3269
3270 return self_ref;
3271}
3272
3273bool Type::chk_this_refd_value(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
3274 ReferenceChain* refch, namedbool str_elem)
3275{
3276 Reference *ref = value->get_reference();
3277 Assignment *ass = ref->get_refd_assignment();
3278 if (!ass) {
3279 value->set_valuetype(Value::V_ERROR);
3280 return false;
3281 }
3282
3283 ass->chk();
3284 bool self_ref = (ass == lhs);
3285
3286 // Exit immediately in case of infinite recursion.
3287 if (value->get_valuetype() != Value::V_REFD) return self_ref;
3288 bool is_const = false, error_flag = false, chk_runs_on = false;
3289 Type *governor = NULL;
3290 switch (ass->get_asstype()) {
3291 case Assignment::A_ERROR:
3292 value->set_valuetype(Value::V_ERROR);
3293 return self_ref;
3294 case Assignment::A_CONST:
3295 is_const = true;
3296 break;
3297 case Assignment::A_OBJECT:
3298 case Assignment::A_OS: {
3299 Setting *setting = ref->get_refd_setting();
3300 if (!setting || setting->get_st() == Setting::S_ERROR) {
3301 value->set_valuetype(Value::V_ERROR);
3302 return self_ref;
3303 }
3304 if (setting->get_st() != Setting::S_V) {
3305 ref->error("This InformationFromObjects construct does not refer to "
3306 "a value: `%s'", value->get_fullname().c_str());
3307 value->set_valuetype(Value::V_ERROR);
3308 return self_ref;
3309 }
3310 governor = dynamic_cast<Value*>(setting)->get_my_governor();
3311 if (!governor) FATAL_ERROR("Type::chk_this_refd_value()");
3312 is_const = true;
3313 break; }
3314 case Assignment::A_MODULEPAR:
3315#ifdef MINGW
3316 break;
3317#endif
3318 case Assignment::A_EXT_CONST:
3319 if (expected_value == EXPECTED_CONSTANT) {
51fa56b9 3320 value->error("Reference to an (evaluable) constant value was "
970ed795
EL
3321 "expected instead of %s",
3322 ass->get_description().c_str());
3323 error_flag = true;
3324 }
3325 break;
3326 case Assignment::A_VAR:
3327 case Assignment::A_PAR_VAL:
3328 case Assignment::A_PAR_VAL_IN:
3329 case Assignment::A_PAR_VAL_OUT:
3330 case Assignment::A_PAR_VAL_INOUT:
3331 switch (expected_value) {
3332 case EXPECTED_CONSTANT:
3333 value->error("Reference to a constant value was expected instead of "
3334 "%s", ass->get_description().c_str());
3335 error_flag = true;
3336 break;
3337 case EXPECTED_STATIC_VALUE:
3338 value->error("Reference to a static value was expected instead of %s",
3339 ass->get_description().c_str());
3340 error_flag = true;
3341 break;
3342 default:
3343 break;
3344 }
3345 break;
3346 case Assignment::A_MODULEPAR_TEMP:
3347 case Assignment::A_TEMPLATE:
3348 case Assignment::A_VAR_TEMPLATE:
3349 case Assignment::A_PAR_TEMPL_IN:
3350 case Assignment::A_PAR_TEMPL_OUT:
3351 case Assignment::A_PAR_TEMPL_INOUT:
3352 if (expected_value != EXPECTED_TEMPLATE) {
3353 value->error("Reference to a value was expected instead of %s",
3354 ass->get_description().c_str());
3355 error_flag = true;
3356 }
3357 break;
3358 case Assignment::A_FUNCTION_RVAL:
3359 chk_runs_on = true;
3360 // No break
3361 case Assignment::A_EXT_FUNCTION_RVAL:
3362 switch (expected_value) {
3363 case EXPECTED_CONSTANT:
3364 value->error("Reference to a constant value was expected instead of "
3365 "the return value of %s",
3366 ass->get_description().c_str());
3367 error_flag = true;
3368 break;
3369 case EXPECTED_STATIC_VALUE:
3370 value->error("Reference to a static value was expected instead of "
3371 "the return value of %s",
3372 ass->get_description().c_str());
3373 error_flag = true;
3374 break;
3375 default:
3376 break;
3377 }
3378 break;
3379 case Assignment::A_FUNCTION_RTEMP:
3380 chk_runs_on = true;
3381 // No break
3382 case Assignment::A_EXT_FUNCTION_RTEMP:
3383 if (expected_value != EXPECTED_TEMPLATE) {
3384 value->error("Reference to a value was expected instead of a call of "
3385 "%s, which returns a template",
3386 ass->get_description().c_str());
3387 error_flag = true;
3388 }
3389 break;
3390 case Assignment::A_FUNCTION:
3391 case Assignment::A_EXT_FUNCTION:
3392 value->error("Reference to a %s was expected instead of a call of %s, "
3393 "which does not have return type",
3394 expected_value == EXPECTED_TEMPLATE
3395 ? "value or template" : "value",
3396 ass->get_description().c_str());
3397 value->set_valuetype(Value::V_ERROR);
3398 return self_ref;
3399 default:
3400 value->error("Reference to a %s was expected instead of %s",
3401 expected_value == EXPECTED_TEMPLATE
3402 ? "value or template" : "value",
3403 ass->get_description().c_str());
3404 value->set_valuetype(Value::V_ERROR);
3405 return self_ref;
3406 } // switch ass->get_asstype()
3407 if (chk_runs_on)
3408 ref->get_my_scope()->chk_runs_on_clause(ass, *ref, "call");
3409 if (!governor)
3410 governor = ass->get_Type()->get_field_type(ref->get_subrefs(),
3411 expected_value);
3412 if (!governor) {
3413 value->set_valuetype(Value::V_ERROR);
3414 return self_ref;
3415 }
3416 TypeCompatInfo info(value->get_my_scope()->get_scope_mod(), this,
3417 governor, true, false);
3418 info.set_str1_elem(str_elem);
3419 if (ref->get_subrefs()) info.set_str2_elem(ref->get_subrefs()->refers_to_string_element());
3420 TypeChain l_chain;
3421 TypeChain r_chain;
3422 if (!is_compatible(governor, &info, &l_chain, &r_chain)) {
3423 // Port or signature values do not exist at all. These errors are
3424 // already reported at those definitions. Extra errors should not be
3425 // reported here.
3426 Type *t = get_type_refd_last();
3427 switch (t->typetype) {
3428 case T_PORT:
3429 // Neither port values nor templates exist.
3430 break;
3431 case T_SIGNATURE:
3432 // Only signature templates may exist.
3433 if (expected_value == EXPECTED_TEMPLATE)
3434 value->error("Type mismatch: a signature template of type `%s' was "
3435 "expected instead of `%s'", get_typename().c_str(),
3436 governor->get_typename().c_str());
3437 break;
3438 default:
3439 if (info.is_subtype_error()) {
3440 value->error("%s", info.get_subtype_error().c_str());
3441 } else if (!info.is_erroneous()) {
3442 value->error("Type mismatch: a %s of type `%s' was expected "
3443 "instead of `%s'", expected_value == EXPECTED_TEMPLATE
3444 ? "value or template" : "value",
3445 get_typename().c_str(),
3446 governor->get_typename().c_str());
3447 } else {
3448 // The semantic error was found by the new code. It was better to
3449 // do the assembly inside TypeCompatInfo.
3450 value->error("%s", info.get_error_str_str().c_str());
3451 }
3452 break;
3453 }
3454 error_flag = true;
3455 } else {
3456 if (info.needs_conversion()) value->set_needs_conversion();
3457 }
3458
3459 if (error_flag) {
3460 value->set_valuetype(Value::V_ERROR);
3461 return self_ref;
3462 }
3463 // Checking for circular references.
3464 Value *v_last = value->get_value_refd_last(refch, expected_value);
3465 if (is_const && v_last->get_valuetype() != Value::V_ERROR) {
3466 // If a referenced universal charstring value points to a literal
3467 // charstring then drop the reference and create a literal ustring to
3468 // avoid run-time conversion.
3469 if (v_last->get_valuetype() == Value::V_CSTR
3470 && get_typetype_ttcn3(get_type_refd_last()->typetype) == T_USTR)
3471 value->set_valuetype(Value::V_USTR);
3472 // Check v_last against the subtype constraints.
3473 if (sub_type!=NULL) sub_type->chk_this_value(value);
3474 }
3475
3476 return self_ref;
3477}
3478
3479void Type::chk_this_invoked_value(Value *value, Common::Assignment *,
3480 expected_value_t expected_value)
3481{
3482 value->get_value_refd_last(NULL, expected_value);
3483 if (value->get_valuetype() == Value::V_ERROR) return;
3484 Type *invoked_t = value->get_invoked_type(expected_value);
3485 if (invoked_t->get_typetype() == T_ERROR) return;
3486 invoked_t = invoked_t->get_type_refd_last();
3487 Type *t = 0;
3488 switch (invoked_t->get_typetype()) {
3489 case Type::T_FUNCTION:
3490 t = invoked_t->get_function_return_type();
3491 break;
3492 default:
3493 FATAL_ERROR("Type::chk_this_invoked_value()");
3494 break;
3495 }
3496 if (!t)
3497 value->error("The type `%s' has no return type, `%s' expected",
3498 invoked_t->get_typename().c_str(), get_typename().c_str());
3499 else if (!is_compatible(t, NULL)) {
3500 value->error("Incompatible value: `%s' value was expected",
3501 get_typename().c_str());
3502 }
3503}
3504
3505void Type::chk_this_value_Null(Value *value)
3506{
3507 Value *v=value->get_value_refd_last();
3508 switch(v->get_valuetype()) {
3509 case Value::V_NULL:
3510 break;
3511 default:
3512 value->error("NULL value was expected");
3513 value->set_valuetype(Value::V_ERROR);
3514 break;
3515 }
3516}
3517
3518void Type::chk_this_value_Bool(Value *value)
3519{
3520 Value *v=value->get_value_refd_last();
3521 switch(v->get_valuetype()) {
3522 case Value::V_BOOL:
3523 break;
3524 default:
3525 value->error("%s value was expected",
3526 value->is_asn1() ? "BOOLEAN" : "boolean");
3527 value->set_valuetype(Value::V_ERROR);
3528 break;
3529 }
3530}
3531
3532void Type::chk_this_value_Int(Value *value)
3533{
3534 Value *v=value->get_value_refd_last();
3535 switch(v->get_valuetype()) {
3536 case Value::V_INT:
3537 break;
3538 default:
3539 value->error("integer value was expected");
3540 value->set_valuetype(Value::V_ERROR);
3541 break;
3542 }
3543 return;
3544}
3545
3546void Type::chk_this_value_Int_A(Value *value)
3547{
3548 Value *v=value->get_value_refd_last();
3549 switch(v->get_valuetype()) {
3550 case Value::V_INT:
3551 break;
3552 case Value::V_NAMEDINT:
3553 if(!u.namednums.nvs)
3554 FATAL_ERROR("Type::chk_this_value_Int_A()");
3555 v->set_valuetype
3556 (Value::V_INT, u.namednums.nvs->
3557 get_nv_byName(*v->get_val_id())->get_value()->get_val_Int()->get_val());
3558 break;
3559 default:
3560 value->error("INTEGER value was expected");
3561 value->set_valuetype(Value::V_ERROR);
3562 break;
3563 }
3564}
3565
3566void Type::chk_this_value_Real(Value *value)
3567{
3568 Value *v = value->get_value_refd_last();
3569 if (value->is_asn1()) {
3570 if (value->is_ref()) {
3571 Type *t = v->get_my_governor()->get_type_refd_last();
3572 if (t->get_typetype() != T_REAL) {
3573 value->error("REAL value was expected");
3574 value->set_valuetype(Value::V_ERROR);
3575 return;
3576 }
3577 }
3578 switch (v->get_valuetype()) {
3579 case Value::V_REAL:
3580 break;
3581 case Value::V_UNDEF_BLOCK:{
3582 v->set_valuetype(Value::V_SEQ);
3583 Identifier t_id(Identifier::ID_ASN, string("REAL"));
3584 bool self_ref = get_my_scope()->get_scope_asss()->get_local_ass_byId(t_id)
3585 ->get_Type()->chk_this_value(v, 0, EXPECTED_CONSTANT, INCOMPLETE_NOT_ALLOWED,
3586 OMIT_NOT_ALLOWED, SUB_CHK);
3587 (void)self_ref;
3588 v->set_valuetype(Value::V_REAL);
3589 break;}
3590 case Value::V_INT:
3591 v->set_valuetype(Value::V_REAL);
3592 break;
3593 default:
3594 value->error("REAL value was expected");
3595 value->set_valuetype(Value::V_ERROR);
3596 break;
3597 }
3598 } else {
3599 switch(v->get_valuetype()) {
3600 case Value::V_REAL:
3601 break;
3602 default:
3603 value->error("float value was expected");
3604 value->set_valuetype(Value::V_ERROR);
3605 break;
3606 }
3607 }
3608}
3609
3610void Type::chk_this_value_Enum(Value *value)
3611{
3612 switch(value->get_valuetype()) {
3613 case Value::V_ENUM:
3614 break;
3615 default:
3616 value->error("%s value was expected",
3617 value->is_asn1() ? "ENUMERATED" : "enumerated");
3618 value->set_valuetype(Value::V_ERROR);
3619 break;
3620 }
3621}
3622
3623void Type::chk_this_value_BStr(Value *value)
3624{
3625 Value *v = value->get_value_refd_last();
3626 switch(v->get_valuetype()) {
3627 case Value::V_BSTR:
3628 break;
3629 default:
3630 value->error("bitstring value was expected");
3631 value->set_valuetype(Value::V_ERROR);
3632 break;
3633 }
3634}
3635
3636void Type::chk_this_value_namedbits(Value *value)
3637{
3638 if (!value) FATAL_ERROR("Type::chk_this_value_namedbits()");
3639 value->set_valuetype(Value::V_NAMEDBITS);
3640 if(!u.namednums.nvs) {
3641 value->error("No named bits are defined in type `%s'",
3642 get_typename().c_str());
3643 value->set_valuetype(Value::V_ERROR);
3644 return;
3645 }
3646 string *bstring = new string("");
3647 for(size_t i=0; i < value->get_nof_ids(); i++) {
3648 Identifier *id = value->get_id_byIndex(i);
3649 if(!u.namednums.nvs->has_nv_withName(*id)) {
3650 delete bstring;
3651 error("No named bit with name `%s' is defined in type `%s'",
3652 id->get_dispname().c_str(), get_typename().c_str());
3653 value->set_valuetype(Value::V_ERROR);
3654 return;
3655 }
3656 size_t bitnum = static_cast<size_t>
3657 (u.namednums.nvs->get_nv_byName(*id)->get_value()->get_val_Int()
3658 ->get_val());
3659 if(bstring->size() < bitnum + 1) bstring->resize(bitnum + 1, '0');
3660 (*bstring)[bitnum] = '1';
3661 }
3662 value->set_valuetype(Value::V_BSTR, bstring);
3663}
3664
3665void Type::chk_this_value_BStr_A(Value *value)
3666{
3667 Value *v = value->get_value_refd_last();
3668 if (value->is_asn1()) {
3669 if(value->is_ref()) {
3670 Type *t = v->get_my_governor()->get_type_refd_last();
3671 if(t->get_typetype()!=T_BSTR_A && t->get_typetype()!=T_BSTR) {
3672 value->error("(reference to) BIT STRING value was expected");
3673 value->set_valuetype(Value::V_ERROR);
3674 return;
3675 }
3676 }
3677 switch(v->get_valuetype()) {
3678 case Value::V_BSTR:
3679 break;
3680 case Value::V_HSTR:
3681 if (v != value) FATAL_ERROR("Common::Type::chk_this_value_BStr_A()");
3682 v->set_valuetype(Value::V_BSTR);
3683 break;
3684 case Value::V_UNDEF_BLOCK:
3685 if (v != value) FATAL_ERROR("Type::chk_this_value_BStr_A()");
3686 chk_this_value_namedbits(v);
3687 break;
3688 default:
3689 value->error("BIT STRING value was expected");
3690 value->set_valuetype(Value::V_ERROR);
3691 return;
3692 }
3693 } else {
3694 switch(v->get_valuetype()) {
3695 case Value::V_BSTR:
3696 break;
3697 default:
3698 value->error("bitstring value was expected");
3699 value->set_valuetype(Value::V_ERROR);
3700 break;
3701 }
3702 }
3703}
3704
3705void Type::chk_this_value_HStr(Value *value)
3706{
3707 Value *v = value->get_value_refd_last();
3708 switch (v->get_valuetype()) {
3709 case Value::V_HSTR:
3710 break;
3711 default:
3712 value->error("hexstring value was expected");
3713 value->set_valuetype(Value::V_ERROR);
3714 break;
3715 }
3716}
3717
3718void Type::chk_this_value_OStr(Value *value)
3719{
3720 Value *v = value->get_value_refd_last();
3721 if (value->is_asn1()) {
3722 if (value->is_ref()) {
3723 Type *t = v->get_my_governor()->get_type_refd_last();
3724 if(t->get_typetype() != T_OSTR) {
3725 value->error("(reference to) OCTET STRING value was expected");
3726 value->set_valuetype(Value::V_ERROR);
3727 return;
3728 }
3729 }
3730 switch(v->get_valuetype()) {
3731 case Value::V_OSTR:
3732 break;
3733 case Value::V_BSTR:
3734 case Value::V_HSTR:
3735 if (v != value) FATAL_ERROR("Type::chk_this_value_OStr()");
3736 v->set_valuetype(Value::V_OSTR);
3737 break;
3738 default:
3739 value->error("OCTET STRING value was expected");
3740 value->set_valuetype(Value::V_ERROR);
3741 break;
3742 }
3743 } else {
3744 switch(v->get_valuetype()) {
3745 case Value::V_OSTR:
3746 break;
3747 default:
3748 value->error("octetstring value was expected");
3749 value->set_valuetype(Value::V_ERROR);
3750 break;
3751 }
3752 }
3753}
3754
3755/** \todo enhance */
3756void Type::chk_this_value_CStr(Value *value)
3757{
3758
3759 switch(value->get_valuetype()) {
3760 case Value::V_UNDEF_BLOCK:
3761 value->set_valuetype(Value::V_CHARSYMS);
3762 if (value->get_valuetype() == Value::V_ERROR) return;
3763 // no break
3764 case Value::V_CHARSYMS:
3765 switch (typetype) {
3766 case T_USTR:
3767 case T_UTF8STRING:
3768 case T_BMPSTRING:
3769 case T_UNIVERSALSTRING:
3770 value->set_valuetype(Value::V_USTR);
3771 break;
3772 case T_TELETEXSTRING:
3773 case T_VIDEOTEXSTRING:
3774 case T_GRAPHICSTRING:
3775 case T_OBJECTDESCRIPTOR:
3776 case T_GENERALSTRING:
3777 value->set_valuetype(Value::V_ISO2022STR);
3778 break;
3779 case T_CSTR:
3780 case T_NUMERICSTRING:
3781 case T_PRINTABLESTRING:
3782 case T_IA5STRING:
3783 case T_VISIBLESTRING:
3784 case T_UTCTIME:
3785 case T_GENERALIZEDTIME:
3786 value->set_valuetype(Value::V_CSTR);
3787 break;
3788 default:
3789 FATAL_ERROR("chk_this_value_CStr()");
3790 } // switch
3791 break;
3792 case Value::V_USTR:
3793 switch (typetype) {
3794 case T_USTR:
3795 case T_UTF8STRING:
3796 case T_BMPSTRING:
3797 case T_UNIVERSALSTRING:
3798 break;
3799 case T_TELETEXSTRING:
3800 case T_VIDEOTEXSTRING:
3801 case T_GRAPHICSTRING:
3802 case T_OBJECTDESCRIPTOR:
3803 case T_GENERALSTRING:
3804 // accept it
3805 /*
3806 if(value->get_val_ustr().is_cstr()) {
3807 value->warning("ISO-2022 string value was expected (converting"
3808 " simple ISO-10646 string).");
3809 value->set_valuetype(Value::V_CSTR);
3810 }
3811 else {
3812 value->error("ISO-2022 string value was expected (instead of"
3813 " ISO-10646 string).");
3814 value->set_valuetype(Value::V_ERROR);
3815 }
3816 */
3817 break;
3818 case T_CSTR:
3819 case T_NUMERICSTRING:
3820 case T_PRINTABLESTRING:
3821 case T_IA5STRING:
3822 case T_VISIBLESTRING:
3823 case T_UTCTIME:
3824 case T_GENERALIZEDTIME:
3825 value->set_valuetype(Value::V_CSTR);
3826 break;
3827 default:
3828 FATAL_ERROR("Type::chk_this_value_CStr()");
3829 } // switch
3830 break;
3831 case Value::V_CSTR:
3832 switch (typetype) {
3833 case T_USTR:
3834 case T_UTF8STRING:
3835 case T_BMPSTRING:
3836 case T_UNIVERSALSTRING:
3837 value->set_valuetype(Value::V_USTR);
3838 break;
3839 case T_TELETEXSTRING:
3840 case T_VIDEOTEXSTRING:
3841 case T_GRAPHICSTRING:
3842 case T_OBJECTDESCRIPTOR:
3843 case T_GENERALSTRING:
3844 value->set_valuetype(Value::V_ISO2022STR);
3845 break;
3846 case T_CSTR:
3847 case T_NUMERICSTRING:
3848 case T_PRINTABLESTRING:
3849 case T_IA5STRING:
3850 case T_VISIBLESTRING:
3851 case T_UTCTIME:
3852 case T_GENERALIZEDTIME:
3853 break;
3854 default:
3855 FATAL_ERROR("chk_this_value_CStr()");
3856 } // switch
3857 break;
3858 case Value::V_ISO2022STR:
3859 switch (typetype) {
3860 case T_USTR:
3861 case T_UTF8STRING:
3862 case T_BMPSTRING:
3863 case T_UNIVERSALSTRING:
3864 value->error("ISO-10646 string value was expected (instead of"
3865 " ISO-2022 string).");
3866 value->set_valuetype(Value::V_ERROR);
3867 break;
3868 case T_TELETEXSTRING:
3869 case T_VIDEOTEXSTRING:
3870 case T_GRAPHICSTRING:
3871 case T_OBJECTDESCRIPTOR:
3872 case T_GENERALSTRING:
3873 break;
3874 case T_CSTR:
3875 case T_NUMERICSTRING:
3876 case T_PRINTABLESTRING:
3877 case T_IA5STRING:
3878 case T_VISIBLESTRING:
3879 case T_UTCTIME:
3880 case T_GENERALIZEDTIME:
3881 value->set_valuetype(Value::V_ISO2022STR);
3882 break;
3883 default:
3884 FATAL_ERROR("chk_this_value_CStr()");
3885 } // switch
3886 break;
3887 default:
3888 value->error("character string value was expected");
3889 value->set_valuetype(Value::V_ERROR);
3890 break;
3891 }
3892}
3893
3894void Type::chk_this_value_OID(Value *value)
3895{
3896 Value *v = value->get_value_refd_last();
3897 if (value->is_asn1()) {
3898 if (value->is_ref()) {
3899 Type *t = v->get_my_governor()->get_type_refd_last();
3900 if (t->get_typetype() != T_OID) {
3901 value->error("(reference to) OBJECT IDENTIFIER value was "
3902 "expected");
3903 value->set_valuetype(Value::V_ERROR);
3904 return;
3905 }
3906 }
3907 switch (v->get_valuetype()) {
3908 case Value::V_OID:
3909 break;
3910 case Value::V_UNDEF_BLOCK:
3911 if (v != value) FATAL_ERROR("Type::chk_this_value_OID()");
3912 v->set_valuetype(Value::V_OID);
3913 v->chk();
3914 break;
3915 default:
3916 value->error("OBJECT IDENTIFIER value was expected");
3917 value->set_valuetype(Value::V_ERROR);
3918 break;
3919 }
3920 } else {
3921 switch (v->get_valuetype()) {
3922 case Value::V_OID:
3923 v->chk();
3924 break;
3925 default:
3926 value->error("objid value was expected");
3927 value->set_valuetype(Value::V_ERROR);
3928 break;
3929 }
3930 }
3931}
3932
3933void Type::chk_this_value_ROID(Value *value)
3934{
3935 Value *v = value->get_value_refd_last();
3936 if(value->is_ref()) {
3937 Type *t = v->get_my_governor()->get_type_refd_last();
3938 if (t->get_typetype() != T_ROID) {
3939 value->error("(reference to) RELATIVE-OID value was expected");
3940 value->set_valuetype(Value::V_ERROR);
3941 return;
3942 }
3943 }
3944 switch(v->get_valuetype()) {
3945 case Value::V_ROID:
3946 break;
3947 case Value::V_UNDEF_BLOCK:
3948 if (v != value) FATAL_ERROR("Type::chk_this_value_ROID()");
3949 v->set_valuetype(Value::V_ROID);
3950 v->chk();
3951 break;
3952 default:
3953 value->error("RELATIVE-OID value was expected");
3954 value->set_valuetype(Value::V_ERROR);
3955 break;
3956 }
3957}
3958
3959void Type::chk_this_value_Any(Value *value)
3960{
3961 Value *v = value->get_value_refd_last();
3962 if (value->is_asn1()) {
3963 if (value->is_ref()) {
3964 Type *t = v->get_my_governor()->get_type_refd_last();
3965 if(t->get_typetype()!=T_ANY && t->get_typetype()!=T_OSTR) {
3966 value->error("(reference to) OCTET STRING or ANY type value"
3967 " was expected");
3968 value->set_valuetype(Value::V_ERROR);
3969 return;
3970 }
3971 }
3972 switch(v->get_valuetype()) {
3973 case Value::V_OSTR:
3974 break;
3975 case Value::V_HSTR:
3976 if (v!=value) FATAL_ERROR("Type::chk_this_value_Any()");
3977 v->set_valuetype(Value::V_OSTR);
3978 break;
3979 default:
3980 value->error("ANY (OCTET STRING) value was expected");
3981 value->set_valuetype(Value::V_ERROR);
3982 break;
3983 }
3984 }
3985 else { // is ttcn
3986 switch(v->get_valuetype()) {
3987 case Value::V_OSTR:
3988 break;
3989 default:
3990 value->error("octetstring value was expected for ASN ANY type");
3991 value->set_valuetype(Value::V_ERROR);
3992 break;
3993 }
3994 }
3995}
3996
3997/** Return a string containing the names of existing fields (components).
3998 *
3999 * @param t a Type object
4000 * @return a string (l-value, temporary)
4001 * @pre t must be a sequence, choice, set, anytype, open type
4002 */
4003static string actual_fields(Type& t) // alas, not even get_nof_comps() is const
4004{
4005 static const string has_no(" has no ");
4006 size_t ncomps = t.get_nof_comps();
4007 const string fields_or_comps(t.is_asn1() ? "components" : "fields");
4008 if (ncomps) {
4009 string msg("Valid ");
4010 msg += fields_or_comps;
4011 msg += ": ";
4012 msg += t.get_comp_byIndex(0)->get_name().get_dispname();
4013 for (size_t ci=1; ci < ncomps; ++ci) {
4014 msg += ',';
4015 msg += t.get_comp_byIndex(ci)->get_name().get_dispname();
4016 }
4017 return msg;
4018 }
4019 else return t.get_fullname() + has_no + fields_or_comps;
4020}
4021
4022
4023bool Type::chk_this_value_Choice(Value *value, Common::Assignment *lhs,
4024 expected_value_t expected_value, namedbool incomplete_allowed, namedbool implicit_omit)
4025{
4026 bool self_ref = false;
4027 switch(value->get_valuetype()) {
4028 case Value::V_SEQ:
4029 if (value->is_asn1()) {
4030 value->error("CHOICE value was expected for type `%s'",
4031 get_fullname().c_str());
4032 value->set_valuetype(Value::V_ERROR);
4033 break;
4034 } else {
4035 // the valuetype can be ERROR if the value has no fields at all
4036 if (value->get_valuetype() == Value::V_ERROR) return false;
4037 // The value notation for TTCN record/union types
4038 // cannot be distinguished during parsing. Now we know it's a union.
4039 value->set_valuetype(Value::V_CHOICE);
4040 }
4041 // no break
4042 case Value::V_CHOICE: {
3abe9331 4043 if (!value->is_asn1() && typetype == T_OPENTYPE) {
4044 // allow the alternatives of open types as both lower and upper identifiers
4045 value->set_alt_name_to_lowercase();
4046 }
970ed795
EL
4047 const Identifier& alt_name = value->get_alt_name();
4048 if(!has_comp_withName(alt_name)) {
4049 if (value->is_asn1()) {
4050 value->error("Reference to non-existent alternative `%s' in CHOICE"
4051 " value for type `%s'",
4052 alt_name.get_dispname().c_str(),
4053 get_fullname().c_str());
4054 } else {
4055 value->error("Reference to non-existent field `%s' in union "
4056 "value for type `%s'",
4057 alt_name.get_dispname().c_str(),
4058 get_fullname().c_str());
4059 }
4060 value->set_valuetype(Value::V_ERROR);
4061 value->note("%s", actual_fields(*this).c_str());
4062 return self_ref;
4063 }
4064 Type *alt_type = get_comp_byName(alt_name)->get_type();
4065 Value *alt_value = value->get_alt_value();
4066 Error_Context cntxt(value, "In value for %s `%s'",
4067 value->is_asn1() ? "alternative" : "union field",
4068 alt_name.get_dispname().c_str());
4069 alt_value->set_my_governor(alt_type);
4070 alt_type->chk_this_value_ref(alt_value);
4071 self_ref |= alt_type->chk_this_value(alt_value, lhs, expected_value,
4072 incomplete_allowed, OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4073 break;}
4074 default:
4075 value->error("%s value was expected for type `%s'",
4076 value->is_asn1() ? "CHOICE" : "union",
4077 get_fullname().c_str());
4078 value->set_valuetype(Value::V_ERROR);
4079 break;
4080 }
4081 return self_ref;
4082}
4083
4084bool Type::chk_this_value_Se(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4085 namedbool incomplete_allowed, namedbool implicit_omit)
4086{
4087 if (value->is_asn1())
4088 return chk_this_value_Se_A(value, lhs, expected_value, implicit_omit);
4089 else
4090 return chk_this_value_Se_T(value, lhs, expected_value, incomplete_allowed,
4091 implicit_omit);
4092}
4093
4094bool Type::chk_this_value_Se_T(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4095 namedbool incomplete_allowed, namedbool implicit_omit)
4096{
4097 switch (value->get_valuetype()) {
4098 case Value::V_SEQ:
4099 if (typetype == T_SET_A || typetype == T_SET_T) {
4100 value->set_valuetype(Value::V_SET);
4101 return chk_this_value_Set_T(value, lhs, expected_value, incomplete_allowed,
4102 implicit_omit);
4103 } else {
4104 return chk_this_value_Seq_T(value, lhs, expected_value, incomplete_allowed,
4105 implicit_omit);
4106 }
4107 break;
4108 case Value::V_SEQOF:
4109 if (typetype == T_SET_A || typetype == T_SET_T) {
4110 if (value->get_nof_comps() == 0) {
4111 if (get_nof_comps() == 0) {
4112 value->set_valuetype(Value::V_SET);
4113 } else {
4114 value->error("A non-empty set value was expected for type `%s'",
4115 get_fullname().c_str());
4116 value->set_valuetype(Value::V_ERROR);
4117 }
4118 } else {
4119 // This will catch the indexed assignment notation as well.
4120 value->error("Value list notation cannot be used for "
4121 "%s type `%s'", typetype == T_SET_A ? "SET" : "set",
4122 get_fullname().c_str());
4123 value->set_valuetype(Value::V_ERROR);
4124 }
4125 } else {
4126 if (value->is_indexed()) {
4127 value->error("Indexed assignment notation cannot be used for %s "
4128 "type `%s'", typetype == T_SEQ_A
4129 ? "SEQUENCE" : "record",
4130 get_fullname().c_str());
4131 value->set_valuetype(Value::V_ERROR);
4132 } else {
4133 value->set_valuetype(Value::V_SEQ);
4134 return chk_this_value_Seq_T(value, lhs, expected_value, incomplete_allowed,
4135 implicit_omit);
4136 }
4137 }
4138 break;
4139 default:
4140 value->error("%s value was expected for type `%s'",
4141 typetype == T_SEQ_T ? "Record" : "Set",
4142 get_fullname().c_str());
4143 value->set_valuetype(Value::V_ERROR);
4144 break;
4145 }
4146 return false;
4147}
4148
4149bool Type::chk_this_value_Seq_T(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4150 namedbool incomplete_allowed, namedbool implicit_omit)
4151{
4152 bool self_ref = false;
4153 map<string, NamedValue> comp_map;
4154 // it is set to false if we have lost the ordering
4155 bool in_synch = true;
4156 const size_t n_type_comps = get_nof_comps();
4157 size_t n_value_comps = value->get_nof_comps();
4158 // for incomplete values
4159 CompField *last_cf = 0;
4160 size_t next_index = 0;
4161 size_t seq_index = 0;
4162 for (size_t v_i = 0; v_i < n_value_comps; v_i++, seq_index++) {
4163 NamedValue *nv = value->get_se_comp_byIndex(v_i);
4164 const Identifier& value_id = nv->get_name();
4165 const string& value_name = value_id.get_name();
4166 const char *value_dispname_str = value_id.get_dispname().c_str();
4167 if (!has_comp_withName(value_id)) {
4168 nv->error("Reference to non-existent field `%s' in record value for "
4169 "type `%s'", value_dispname_str, get_typename().c_str());
4170 nv->note("%s", actual_fields(*this).c_str());
4171 in_synch = false;
4172 continue;
4173 } else if (comp_map.has_key(value_name)) {
4174 nv->error("Duplicate record field `%s'", value_dispname_str);
4175 comp_map[value_name]->note("Field `%s' is already given here",
4176 value_dispname_str);
4177 in_synch = false;
4178 } else comp_map.add(value_name, nv);
4179 CompField *cf = get_comp_byName(value_id);
4180 // check the ordering of fields
4181 if (in_synch) {
4182 if (incomplete_allowed) {
4183 bool found = false;
4184 for (size_t i = next_index; i < n_type_comps; i++) {
4185 CompField *cf2 = get_comp_byIndex(i);
4186 if (value_name == cf2->get_name().get_name()) {
4187 last_cf = cf2;
4188 next_index = i + 1;
4189 found = true;
4190 break;
4191 }
4192 }
4193 if (!found) {
4194 nv->error("Field `%s' cannot appear after field `%s' in record "
4195 "value", value_dispname_str,
4196 last_cf->get_name().get_dispname().c_str());
4197 in_synch = false;
4198 }
4199 } else {
4200 // the value must be complete unless implicit omit is set
4201 CompField *cf2 = get_comp_byIndex(seq_index);
4202 CompField *cf2_orig = cf2;
4203 while (implicit_omit && seq_index < n_type_comps && cf2 != cf &&
4204 cf2->get_is_optional())
4205 cf2 = get_comp_byIndex(++seq_index);
4206 if (seq_index >= n_type_comps || cf2 != cf) {
4207 nv->error("Unexpected field `%s' in record value, "
4208 "expecting `%s'", value_dispname_str,
4209 cf2_orig->get_name().get_dispname().c_str());
4210 in_synch = false;
4211 }
4212 }
4213 }
4214 Type *type = cf->get_type();
4215 Value *comp_value = nv->get_value();
4216 comp_value->set_my_governor(type);
4217 if (comp_value->get_valuetype() == Value::V_NOTUSED) {
4218 if (implicit_omit) {
4219 comp_value->set_valuetype(Value::V_OMIT);
4220 } else {
4221 continue;
4222 }
4223 }
4224 Error_Context cntxt(nv, "In value for record field `%s'",
4225 value_dispname_str);
4226 type->chk_this_value_ref(comp_value);
4227 self_ref |= type->chk_this_value(comp_value, lhs, expected_value, incomplete_allowed,
4228 cf->get_is_optional() ? OMIT_ALLOWED : OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4229 }
4230 if (!incomplete_allowed || implicit_omit) {
4231 for (size_t i = 0; i < n_type_comps; i++) {
4232 const Identifier& id = get_comp_byIndex(i)->get_name();
4233 if (!comp_map.has_key(id.get_name())) {
4234 if (get_comp_byIndex(i)->get_is_optional() && implicit_omit)
4235 value->add_se_comp(new NamedValue(new Identifier(id),
4236 new Value(Value::V_OMIT)));
4237 else if (!incomplete_allowed)
4238 value->error("Field `%s' is missing from record value",
4239 id.get_dispname().c_str());
4240 }
4241 }
4242 }
4243 comp_map.clear();
4244 return self_ref;
4245}
4246
4247bool Type::chk_this_value_Set_T(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4248 namedbool incomplete_allowed, namedbool implicit_omit)
4249{
4250 bool self_ref = false;
4251 map<string, NamedValue> comp_map;
4252 size_t n_type_comps = get_nof_comps();
4253 size_t n_value_comps = value->get_nof_comps();
4254 for(size_t v_i = 0; v_i < n_value_comps; v_i++) {
4255 NamedValue *nv = value->get_se_comp_byIndex(v_i);
4256 const Identifier& value_id = nv->get_name();
4257 const string& value_name = value_id.get_name();
4258 const char *value_dispname_str = value_id.get_dispname().c_str();
4259 if (!has_comp_withName(value_id)) {
4260 nv->error("Reference to non-existent field `%s' in set value for "
4261 "type `%s'", value_dispname_str, get_typename().c_str());
4262 nv->note("%s", actual_fields(*this).c_str());
4263 continue;
4264 } else if (comp_map.has_key(value_name)) {
4265 nv->error("Duplicate set field `%s'", value_dispname_str);
4266 comp_map[value_name]->note("Field `%s' is already given here",
4267 value_dispname_str);
4268 } else comp_map.add(value_name, nv);
4269 CompField *cf = get_comp_byName(value_id);
4270 Type *type = cf->get_type();
4271 Value *comp_value = nv->get_value();
4272 comp_value->set_my_governor(type);
4273 if (comp_value->get_valuetype() == Value::V_NOTUSED) {
4274 if (implicit_omit) {
4275 comp_value->set_valuetype(Value::V_OMIT);
4276 } else {
4277 continue;
4278 }
4279 }
4280 Error_Context cntxt(nv, "In value for set field `%s'",
4281 value_dispname_str);
4282 type->chk_this_value_ref(comp_value);
4283 self_ref |= type->chk_this_value(comp_value, lhs, expected_value, incomplete_allowed,
4284 cf->get_is_optional() ? OMIT_ALLOWED : OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4285 }
4286 if (!incomplete_allowed || implicit_omit) {
4287 for (size_t i = 0; i < n_type_comps; i++) {
4288 const Identifier& id = get_comp_byIndex(i)->get_name();
4289 if(!comp_map.has_key(id.get_name())) {
4290 if (get_comp_byIndex(i)->get_is_optional() && implicit_omit)
4291 value->add_se_comp(new NamedValue(new Identifier(id),
4292 new Value(Value::V_OMIT)));
4293 else if (!incomplete_allowed)
4294 value->error("Field `%s' is missing from set value %s",
4295 id.get_dispname().c_str(), implicit_omit ? "yes" : "no");
4296 }
4297 }
4298 }
4299 comp_map.clear();
4300 return self_ref;
4301}
4302
4303bool Type::chk_this_value_Se_A(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4304 namedbool implicit_omit)
4305{
4306 if(value->get_valuetype()==Value::V_UNDEF_BLOCK) {
4307 if(typetype == T_SEQ_A) value->set_valuetype(Value::V_SEQ);
4308 else value->set_valuetype(Value::V_SET);
4309 } // if V_UNDEF
4310 switch(value->get_valuetype()) {
4311 case Value::V_SEQ:
4312 return chk_this_value_Seq_A(value, lhs, expected_value, implicit_omit);
4313 case Value::V_SET:
4314 return chk_this_value_Set_A(value, lhs, expected_value, implicit_omit);
4315 default:
4316 value->error("%s value was expected",
4317 typetype == T_SEQ_A ? "SEQUENCE" : "SET");
4318 value->set_valuetype(Value::V_ERROR);
4319 break;
4320 }
4321 return false;
4322}
4323
4324bool Type::chk_this_value_Seq_A(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4325 namedbool implicit_omit)
4326{
4327 bool self_ref = false;
4328 map<string, NamedValue> comp_map;
4329 // it is set to false if we have lost the ordering
4330 bool in_synch = true;
4331 size_t n_type_comps = u.secho.ctss->get_nof_comps();
4332 size_t n_value_comps = value->get_nof_comps();
4333 size_t t_i = 0;
4334 for (size_t v_i = 0; v_i < n_value_comps; v_i++) {
4335 NamedValue *nv = value->get_se_comp_byIndex(v_i);
4336 const Identifier& value_id = nv->get_name();
4337 const string& value_name = value_id.get_name();
4338 const char *value_dispname_str = value_id.get_dispname().c_str();
4339 if (!u.secho.ctss->has_comp_withName(value_id)) {
4340 nv->error("Reference to non-existent component `%s' of SEQUENCE "
4341 "type `%s'", value_dispname_str, get_typename().c_str());
4342 nv->note("%s", actual_fields(*this).c_str());
4343 in_synch = false;
4344 continue;
4345 } else if (comp_map.has_key(value_name)) {
4346 nv->error("Duplicate SEQUENCE component `%s'", value_dispname_str);
4347 comp_map[value_name]->note("Component `%s' is already given here",
4348 value_dispname_str);
4349 in_synch = false;
4350 } else comp_map.add(value_name, nv);
4351 CompField *cf = u.secho.ctss->get_comp_byName(value_id);
4352 if (in_synch) {
4353 CompField *cf2 = 0;
4354 for ( ; t_i < n_type_comps; t_i++) {
4355 cf2 = u.secho.ctss->get_comp_byIndex(t_i);
4356 if (cf2 == cf || (!cf2->get_is_optional() && !cf2->has_default() &&
4357 !implicit_omit))
4358 break;
4359 }
4360 if (cf2 != cf) {
4361 if (t_i < n_type_comps) {
4362 nv->error("Unexpected component `%s' in SEQUENCE value, "
4363 "expecting `%s'", value_dispname_str,
4364 cf2->get_name().get_dispname().c_str());
4365 } else {
4366 nv->error("Unexpected component `%s' in SEQUENCE value",
4367 value_dispname_str);
4368 }
4369 in_synch = false;
4370 } else t_i++;
4371 }
4372 Type *type = cf->get_type();
4373 Error_Context cntxt(nv, "In value for SEQUENCE component `%s'",
4374 value_dispname_str);
4375 Value *comp_value = nv->get_value();
4376 comp_value->set_my_governor(type);
4377 type->chk_this_value_ref(comp_value);
4378 self_ref |= type->chk_this_value(comp_value, lhs, expected_value,
4379 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4380 }
4381 for (size_t i = 0; i < n_type_comps; i++) {
4382 CompField *cf = u.secho.ctss->get_comp_byIndex(i);
4383 const Identifier& id = cf->get_name();
4384 if (!comp_map.has_key(id.get_name())) {
4385 if (!cf->get_is_optional() && !cf->has_default())
4386 value->error("Mandatory component `%s' is missing from SEQUENCE value",
4387 id.get_dispname().c_str());
4388 else if (cf->get_is_optional() && implicit_omit)
4389 value->add_se_comp(new NamedValue(new Identifier(id),
4390 new Value(Value::V_OMIT)));
4391 }
4392 }
4393 comp_map.clear();
4394 return self_ref;
4395}
4396
4397bool Type::chk_this_value_Set_A(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4398 namedbool implicit_omit)
4399{
4400 bool self_ref = false;
4401 map<string, NamedValue> comp_map;
4402 size_t n_type_comps = u.secho.ctss->get_nof_comps();
4403 size_t n_value_comps = value->get_nof_comps();
4404 for(size_t v_i = 0; v_i < n_value_comps; v_i++) {
4405 NamedValue *nv = value->get_se_comp_byIndex(v_i);
4406 const Identifier& value_id = nv->get_name();
4407 const string& value_name = value_id.get_name();
4408 const char *value_dispname_str = value_id.get_dispname().c_str();
4409 if (!u.secho.ctss->has_comp_withName(value_id)) {
4410 value->error("Reference to non-existent component `%s' of SET type "
4411 "`%s'", value_dispname_str, get_typename().c_str());
4412 nv->note("%s", actual_fields(*this).c_str());
4413 continue;
4414 } else if (comp_map.has_key(value_name)) {
4415 nv->error("Duplicate SET component `%s'", value_dispname_str);
4416 comp_map[value_name]->note("Component `%s' is already given here",
4417 value_dispname_str);
4418 } else comp_map.add(value_name, nv);
4419 Type *type =
4420 u.secho.ctss->get_comp_byName(value_id)->get_type();
4421 Value *comp_value = nv->get_value();
4422 Error_Context cntxt(nv, "In value for SET component `%s'",
4423 value_dispname_str);
4424 comp_value->set_my_governor(type);
4425 type->chk_this_value_ref(comp_value);
4426 self_ref |= type->chk_this_value(comp_value, lhs, expected_value,
4427 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4428 }
4429 for (size_t i = 0; i < n_type_comps; i++) {
4430 CompField *cf = u.secho.ctss->get_comp_byIndex(i);
4431 const Identifier& id = cf->get_name();
4432 if (!comp_map.has_key(id.get_name())) {
4433 if (!cf->get_is_optional() && !cf->has_default())
4434 value->error("Mandatory component `%s' is missing from SET value",
4435 id.get_dispname().c_str());
4436 else if (cf->get_is_optional() && implicit_omit)
4437 value->add_se_comp(new NamedValue(new Identifier(id),
4438 new Value(Value::V_OMIT)));
4439 }
4440 }
4441 comp_map.clear();
4442 return self_ref;
4443}
4444
4445bool Type::chk_this_value_SeOf(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4446 namedbool incomplete_allowed, namedbool implicit_omit)
4447{
4448 bool self_ref = false;
4449 const char *valuetypename;
4450 if (value->is_asn1()) {
4451 if (typetype == T_SEQOF) valuetypename = "SEQUENCE OF";
4452 else valuetypename = "SET OF";
4453 } else {
4454 if (typetype == T_SEQOF) valuetypename = "record of";
4455 else valuetypename = "set of";
4456 }
4457 if (value->get_valuetype() == Value::V_UNDEF_BLOCK) {
4458 if (typetype == T_SEQOF) value->set_valuetype(Value::V_SEQOF);
4459 else value->set_valuetype(Value::V_SETOF);
4460 } // if V_UNDEF
4461 switch (value->get_valuetype()) {
4462 case Value::V_SEQOF:
4463 if (typetype == T_SETOF) value->set_valuetype(Value::V_SETOF);
4464 // no break
4465 case Value::V_SETOF: {
4466 if (!value->is_indexed()) {
4467 for (size_t i = 0; i < value->get_nof_comps(); i++) {
4468 Value *v_comp = value->get_comp_byIndex(i);
4469 Error_Context cntxt(v_comp, "In component #%lu",
4470 (unsigned long)(i + 1));
4471 v_comp->set_my_governor(u.seof.ofType);
4472 if (v_comp->get_valuetype() == Value::V_NOTUSED) {
4473 if (!incomplete_allowed)
4474 v_comp->error("Not used symbol `-' is not allowed in this "
4475 "context");
4476 } else {
4477 u.seof.ofType->chk_this_value_ref(v_comp);
4478 self_ref |= u.seof.ofType->chk_this_value(v_comp, lhs, expected_value,
4479 incomplete_allowed, OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4480 }
4481 }
4482 } else {
4483 // Only constant values with constant indicies can be checked at
4484 // compile time. Constant expressions evaluated.
4485 bool check_holes = expected_value == EXPECTED_CONSTANT;
4486 Int max_index = -1;
4487 map<Int, Int> index_map;
4488 for (size_t i = 0; i < value->get_nof_comps(); i++) {
4489 Error_Context cntxt(this, "In component #%lu",
4490 (unsigned long)(i + 1));
4491 Value *val = value->get_comp_byIndex(i);
4492 Value *index = value->get_index_byIndex(i);
4493 index->chk_expr_int(expected_value);
4494 if (index->get_valuetype() != Value::V_ERROR &&
4495 index->get_value_refd_last()->get_valuetype() == Value::V_INT) {
4496 const int_val_t *index_int = index->get_value_refd_last()
4497 ->get_val_Int();
4498 if (*index_int > INT_MAX) {
4499 index->error("An integer value less than `%d' was expected for "
4500 "indexing type `%s' instead of `%s'", INT_MAX,
4501 get_typename().c_str(),
4502 (index_int->t_str()).c_str());
4503 index->set_valuetype(Value::V_ERROR);
4504 check_holes = false;
4505 } else {
4506 Int index_val = index_int->get_val();
4507 if (index_val < 0) {
4508 index->error("A non-negative integer value was expected for "
4509 "indexing type `%s' instead of `%s'",
4510 get_typename().c_str(),
4511 Int2string(index_val).c_str());
4512 index->set_valuetype(Value::V_ERROR);
4513 check_holes = false;
4514 } else if (index_map.has_key(index_val)) {
4515 index->error("Duplicate index value `%s' for components `%s' "
4516 "and `%s'", Int2string(index_val).c_str(),
4517 Int2string((Int)i + 1).c_str(),
4518 Int2string(*index_map[index_val]).c_str());
4519 index->set_valuetype(Value::V_ERROR);
4520 check_holes = false;
4521 } else {
4522 index_map.add(index_val, new Int((Int)i + 1));
4523 if (max_index < index_val)
4524 max_index = index_val;
4525 }
4526 }
4527 } else {
4528 // The index cannot be determined.
4529 check_holes = false;
4530 }
4531 val->set_my_governor(u.seof.ofType);
4532 u.seof.ofType->chk_this_value_ref(val);
4533 self_ref |= u.seof.ofType->chk_this_value(val, lhs, expected_value,
4534 incomplete_allowed, OMIT_NOT_ALLOWED, SUB_CHK);
4535 }
4536 if (check_holes) {
4537 if ((size_t)max_index != index_map.size() - 1) {
4538 value->error("It's not allowed to create hole(s) in constant "
4539 "values");
4540 value->set_valuetype(Value::V_ERROR);
4541 }
4542 }
4543 for (size_t i = 0; i < index_map.size(); i++)
4544 delete index_map.get_nth_elem(i);
4545 index_map.clear();
4546 }
4547 break; }
4548 default:
4549 value->error("%s value was expected", valuetypename);
4550 value->set_valuetype(Value::V_ERROR);
4551 break;
4552 }
4553 return self_ref;
4554}
4555
4556void Type::chk_this_value_Verdict(Value *value)
4557{
4558 Value *v = value->get_value_refd_last();
4559 switch (v->get_valuetype()) {
4560 case Value::V_VERDICT:
4561 break;
4562 default:
4563 value->error("verdict value was expected");
4564 value->set_valuetype(Value::V_ERROR);
4565 break;
4566 }
4567}
4568
4569/** \todo enhance to handle activate */
4570void Type::chk_this_value_Default(Value *value)
4571{
4572 switch (value->get_valuetype()) {
4573 case Value::V_TTCN3_NULL:
4574 value->set_valuetype(Value::V_DEFAULT_NULL);
4575 break;
4576 default:
4577 value->error("default value was expected");
4578 value->set_valuetype(Value::V_ERROR);
4579 break;
4580 }
4581}
4582
4583bool Type::chk_this_value_Array(Value *value, Common::Assignment *lhs, expected_value_t expected_value,
4584 namedbool incomplete_allowed, namedbool implicit_omit)
4585{
4586 bool self_ref = false;
4587 switch (value->get_valuetype()) {
4588 case Value::V_SEQOF:
4589 value->set_valuetype(Value::V_ARRAY);
4590 // no break
4591 case Value::V_ARRAY: {
4592 size_t n_value_comps = value->get_nof_comps();
4593 Ttcn::ArrayDimension *dim = u.array.dimension;
4594 if (!value->is_indexed()) {
4595 // Value-list notation.
4596 if (!dim->get_has_error()) {
4597 size_t array_size = dim->get_size();
4598 if (array_size != n_value_comps)
4599 value->error("Too %s elements in the array value: %lu was "
4600 "expected instead of %lu",
4601 array_size > n_value_comps ? "few" : "many",
4602 (unsigned long)array_size,
4603 (unsigned long)n_value_comps);
4604 }
4605 for (size_t i = 0; i < n_value_comps; i++) {
4606 Error_Context cntxt(this, "In array element %lu",
4607 (unsigned long)(i + 1));
4608 Value *v_comp = value->get_comp_byIndex(i);
4609 v_comp->set_my_governor(u.array.element_type);
4610 if (v_comp->get_valuetype() == Value::V_NOTUSED) {
4611 if (!incomplete_allowed)
4612 v_comp->error("Not used symbol `-' is not allowed in this "
4613 "context");
4614 } else {
4615 u.array.element_type->chk_this_value_ref(v_comp);
4616 self_ref |= u.array.element_type->chk_this_value(v_comp, lhs,
4617 expected_value, incomplete_allowed, OMIT_NOT_ALLOWED, SUB_CHK,
4618 implicit_omit);
4619 }
4620 }
4621 } else {
4622 // Indexed-list notation.
4623 bool array_size_known = !dim->get_has_error();
4624 bool check_holes = array_size_known
4625 && expected_value == EXPECTED_CONSTANT;
4626 size_t array_size = 0;
4627 if (array_size_known) array_size = dim->get_size();
4628 map<Int, Int> index_map;
4629 for (size_t i = 0; i < n_value_comps; i++) {
4630 Error_Context cntxt(this, "In array element #%lu",
4631 (unsigned long)(i + 1));
4632 Value *val = value->get_comp_byIndex(i);
4633 Value *index = value->get_index_byIndex(i);
4634 dim->chk_index(index, expected_value);
4635 if (index->get_value_refd_last()->get_valuetype() == Value::V_INT) {
4636 const int_val_t *index_int = index->get_value_refd_last()
4637 ->get_val_Int();
4638 if (*index_int > INT_MAX) {
4639 index->error("An integer value less than `%d' was expected for "
4640 "indexing type `%s' instead of `%s'", INT_MAX,
4641 get_typename().c_str(),
4642 (index_int->t_str()).c_str());
4643 index->set_valuetype(Value::V_ERROR);
4644 check_holes = false;
4645 } else {
4646 // Index overflows/underflows are already checked by
4647 // ArrayDimensions::chk_index() at this point. The only thing
4648 // we need to check is the uniqueness of constant index values.
4649 Int index_val = index_int->get_val();
4650 if (index_map.has_key(index_val)) {
4651 index->error("Duplicate index value `%s' for components `%s' "
4652 "and `%s'", Int2string(index_val).c_str(),
4653 Int2string((Int)i + 1).c_str(),
4654 Int2string(*index_map[index_val]).c_str());
4655 index->set_valuetype(Value::V_ERROR);
4656 check_holes = false;
4657 } else {
4658 index_map.add(index_val, new Int((Int)i + 1));
4659 }
4660 }
4661 } else {
4662 check_holes = false;
4663 }
4664 val->set_my_governor(u.array.element_type);
4665 u.array.element_type->chk_this_value_ref(val);
4666 self_ref |= u.array.element_type->chk_this_value(val, lhs, expected_value,
4667 incomplete_allowed, OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit);
4668 }
4669 if (check_holes) {
4670 if (index_map.size() < array_size) {
4671 // It's a constant array assigned with constant index values. The
4672 // # of constant index values doesn't reach the size of the array.
4673 value->error("It's not allowed to create hole(s) in constant "
4674 "values");
4675 value->set_valuetype(Value::V_ERROR);
4676 }
4677 }
4678 for (size_t i = 0; i < index_map.size(); i++)
4679 delete index_map.get_nth_elem(i);
4680 index_map.clear();
4681 }
4682 break; }
4683 default:
4684 value->error("array value was expected");
4685 value->set_valuetype(Value::V_ERROR);
4686 break;
4687 }
4688
4689 return self_ref;
4690}
4691
4692bool Type::chk_this_value_Signature(Value *value, Common::Assignment *lhs,
4693 expected_value_t expected_value,
4694 namedbool incomplete_allowed)
4695{
4696 bool self_ref = false;
4697 switch(value->get_valuetype()) {
4698 case Value::V_SEQOF:
4699 value->set_valuetype(Value::V_SEQ);
4700 // no break
4701 case Value::V_SEQ:{
4702 map<string, NamedValue> comp_map;
4703 // it is set to false if we have lost the ordering
4704 bool in_synch = true;
4705 size_t n_type_comps = get_nof_comps();
4706 size_t n_value_comps = value->get_nof_comps();
4707 // for incomplete values
4708 CompField *last_cf = 0;
4709 size_t next_index = 0;
4710 for (size_t v_i = 0; v_i < n_value_comps; v_i++) {
4711 NamedValue *nv = value->get_se_comp_byIndex(v_i);
4712 const Identifier& value_id = nv->get_name();
4713 const string& value_name = value_id.get_name();
4714 const char *value_dispname_str = value_id.get_dispname().c_str();
4715 if (!has_comp_withName(value_id)) {
4716 nv->error("Reference to non-existent parameter `%s' in signature value for "
4717 "type `%s'", value_dispname_str, get_typename().c_str());
4718 in_synch = false;
4719 continue;
4720 } else if (comp_map.has_key(value_name)) {
4721 nv->error("Duplicate signature parameter `%s'", value_dispname_str);
4722 comp_map[value_name]->note("Parameter `%s' is already given here",
4723 value_dispname_str);
4724 in_synch = false;
4725 } else comp_map.add(value_name, nv);
4726 CompField *cf = get_comp_byName(value_id);
4727 // check the ordering of fields
4728 if (in_synch) {
4729 if (incomplete_allowed) {
4730 bool found = false;
4731 for (size_t i = next_index; i < n_type_comps; i++) {
4732 CompField *cf2 = get_comp_byIndex(i);
4733 if (value_name == cf2->get_name().get_name()) {
4734 last_cf = cf2;
4735 next_index = i + 1;
4736 found = true;
4737 break;
4738 }
4739 }
4740 if (!found) {
4741 nv->error("Field `%s' cannot appear after parameter `%s' in signature "
4742 "value", value_dispname_str,
4743 last_cf->get_name().get_dispname().c_str());
4744 in_synch = false;
4745 }
4746 } else {
4747 // the value must be complete
4748 CompField *cf2 = get_comp_byIndex(v_i);
4749 if (cf2 != cf) {
4750 nv->error("Unexpected field `%s' in record value, "
4751 "expecting `%s'", value_dispname_str,
4752 cf2->get_name().get_dispname().c_str());
4753 in_synch = false;
4754 }
4755 }
4756 }
4757 Type *type = cf->get_type();
4758 Value *comp_value = nv->get_value();
4759 comp_value->set_my_governor(type);
4760 Error_Context cntxt(nv, "In value for signature parameter `%s'",
4761 value_dispname_str);
4762 type->chk_this_value_ref(comp_value);
4763 self_ref |= type->chk_this_value(comp_value, lhs, expected_value,
4764 INCOMPLETE_NOT_ALLOWED,
4765 cf->get_is_optional() ? OMIT_ALLOWED : OMIT_NOT_ALLOWED, SUB_CHK);
4766 }
4767 if (!incomplete_allowed) {
4768 for (size_t i = 0; i < u.signature.parameters->get_nof_in_params(); i++) {
4769 const Identifier& id = get_comp_byIndex(i)->get_name(); //u.signature.parameters->get_param_byIndex(n)
4770 if (!comp_map.has_key(id.get_name()) && SignatureParam::PARAM_OUT != u.signature.parameters->get_in_param_byIndex(i)->get_direction()) {
4771 value->error("Field `%s' is missing from signature value",
4772 id.get_dispname().c_str());
4773 }
4774 }
4775 }
4776 comp_map.clear();
4777 break;}
4778 default:
4779 value->error("Signature value was expected for type `%s'",
4780 get_fullname().c_str());
4781 value->set_valuetype(Value::V_ERROR);
4782 break;
4783 }
4784
4785 return self_ref;
4786}
4787
4788/** \todo enhance to handle mtc, system, etc. */
4789void Type::chk_this_value_Component(Value *value)
4790{
4791 switch (value->get_valuetype()) {
4792 case Value::V_TTCN3_NULL:
4793 value->set_valuetype_COMP_NULL();
4794 break;
4795 case Value::V_EXPR:
4796 if (value->get_optype() == Value::OPTYPE_COMP_NULL)
4797 break; // set_valuetype_COMP_NULL was called already
4798 // no break
4799 default:
4800 value->error("component reference value was expected");
4801 value->set_valuetype(Value::V_ERROR);
4802 break;
4803 }
4804}
4805
4806void Type::chk_this_value_FAT(Value *value)
4807{
4808 switch (value->get_valuetype()) {
4809 case Value::V_TTCN3_NULL:
4810 value->set_valuetype(Value::V_FAT_NULL);
4811 return;
4812 case Value::V_REFER:
4813 // see later
4814 break;
4815 case Value::V_FUNCTION:
4816 case Value::V_ALTSTEP:
4817 case Value::V_TESTCASE:
4818 case Value::V_FAT_NULL:
4819 // This function (chk_this_value_FAT) might have transformed the value
4820 // from V_REFER or V_TTCN3_NULL to one of these. Return now,
4821 // otherwise spurious errors are generated.
4822 return;
4823 default:
4824 switch (typetype) {
4825 case T_FUNCTION:
4826 value->error("Reference to a function or external function was "
4827 "expected");
4828 break;
4829 case T_ALTSTEP:
4830 value->error("Reference to an altstep was expected");
4831 break;
4832 case T_TESTCASE:
4833 value->error("Reference to a testcase was expected");
4834 break;
4835 default:
4836 FATAL_ERROR("Type::chk_this_value_FAT()");
4837 }
4838 value->set_valuetype(Value::V_ERROR);
4839 return;
4840 } // switch valuetype
4841
4842 // Here value->valuetype is V_REFER
4843 Assignment *t_ass = value->get_refered()->get_refd_assignment(false);
4844 if (!t_ass) {
4845 value->set_valuetype(Value::V_ERROR);
4846 return;
4847 }
4848 t_ass->chk();
4849 // check whether refers() points to the right definition
4850 Assignment::asstype_t t_asstype = t_ass->get_asstype();
4851 switch (typetype) {
4852 case T_FUNCTION:
4853 switch (t_asstype) {
4854 case Assignment::A_FUNCTION:
4855 case Assignment::A_FUNCTION_RVAL:
4856 case Assignment::A_FUNCTION_RTEMP:
4857 case Assignment::A_EXT_FUNCTION:
4858 case Assignment::A_EXT_FUNCTION_RVAL:
4859 case Assignment::A_EXT_FUNCTION_RTEMP:
4860 value->set_valuetype(Value::V_FUNCTION, t_ass);
4861 break;
4862 default:
4863 value->error("Reference to a function or external function was "
4864 "expected instead of %s", t_ass->get_description().c_str());
4865 value->set_valuetype(Value::V_ERROR);
4866 return;
4867 }
4868 break;
4869 case T_ALTSTEP:
4870 if (t_ass->get_asstype() == Assignment::A_ALTSTEP) {
4871 value->set_valuetype(Value::V_ALTSTEP, t_ass);
4872 break;
4873 } else {
4874 value->error("Reference to an altstep was expected instead of %s",
4875 t_ass->get_description().c_str());
4876 value->set_valuetype(Value::V_ERROR);
4877 return;
4878 }
4879 case T_TESTCASE:
4880 if (t_ass->get_asstype() == Assignment::A_TESTCASE) {
4881 value->set_valuetype(Value::V_TESTCASE, t_ass);
4882 break;
4883 } else {
4884 value->error("Reference to a testcase was expected instead of %s",
4885 t_ass->get_description().c_str());
4886 value->set_valuetype(Value::V_ERROR);
4887 return;
4888 }
4889 default:
4890 FATAL_ERROR("Type::chk_this_value_FAT()");
4891 }
4892 // comparison of formal parameter lists
4893 {
4894 Error_Context cntxt(value, "In comparing formal parameter lists of "
4895 "type `%s' and %s", get_typename().c_str(),
4896 t_ass->get_description().c_str());
4897 u.fatref.fp_list->chk_compatibility(t_ass->get_FormalParList(),
4898 get_typename().c_str());
4899 }
4900 // comparison of 'runs on' clauses
4901 Type *t_runs_on_type = t_ass->get_RunsOnType();
4902 if (t_runs_on_type) {
4903 if (u.fatref.runs_on.self) {
4904 if (u.fatref.runs_on.ref) {
4905 FATAL_ERROR("Type::chk_this_value_FAT()");
4906 } else { // "runs on self" case
4907 // check against the runs on component type of the scope of the value
4908 Scope* value_scope = value->get_my_scope();
4909 if (!value_scope) FATAL_ERROR("Type::chk_this_value_FAT()");
4910 Ttcn::RunsOnScope *t_ros = value_scope->get_scope_runs_on();
4911 if (t_ros) {
4912 Type *scope_comptype = t_ros->get_component_type();
4913 if (!t_runs_on_type->is_compatible(scope_comptype, NULL)) {
4914 value->error("Runs on clause mismatch: type `%s' has a "
4915 "'runs on self' clause and the current scope expects component "
4916 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4917 scope_comptype->get_typename().c_str(),
4918 t_ass->get_description().c_str(),
4919 t_runs_on_type->get_typename().c_str());
4920 }
4921 } else { // does not have 'runs on' clause
4922 // if the value's scope is a component body then check the runs on
4923 // compatibility using this component type as the scope
4924 ComponentTypeBody* ct_body =
4925 dynamic_cast<ComponentTypeBody*>(value_scope);
4926 if (ct_body) {
4927 if (!t_runs_on_type->is_compatible(ct_body->get_my_type(), NULL)) {
4928 value->error("Runs on clause mismatch: type `%s' has a "
4929 "'runs on self' clause and the current component definition "
4930 "is of type `%s', but %s runs on `%s'",
4931 get_typename().c_str(),
4932 ct_body->get_my_type()->get_typename().c_str(),
4933 t_ass->get_description().c_str(),
4934 t_runs_on_type->get_typename().c_str());
4935 }
4936 } else {
4937 value->error("Type `%s' has a 'runs on self' clause and the "
4938 "current scope does not have a 'runs on' clause, "
4939 "but %s runs on `%s'", get_typename().c_str(),
4940 t_ass->get_description().c_str(),
4941 t_runs_on_type->get_typename().c_str());
4942 }
4943 }
4944 }
4945 } else {
4946 if (u.fatref.runs_on.ref) {
4947 if (u.fatref.runs_on.type &&
4948 !t_runs_on_type->is_compatible(u.fatref.runs_on.type, NULL)) {
4949 value->error("Runs on clause mismatch: type `%s' expects component "
4950 "type `%s', but %s runs on `%s'", get_typename().c_str(),
4951 u.fatref.runs_on.type->get_typename().c_str(),
4952 t_ass->get_description().c_str(),
4953 t_runs_on_type->get_typename().c_str());
4954 }
4955 } else {
4956 value->error("Type `%s' does not have 'runs on' clause, but %s runs "
4957 "on `%s'", get_typename().c_str(), t_ass->get_description().c_str(),
4958 t_runs_on_type->get_typename().c_str());
4959 }
4960 }
4961 }
4962 if (typetype == T_TESTCASE) {
4963 // comparison of system clauses
4964 Ttcn::Def_Testcase *t_testcase = dynamic_cast<Ttcn::Def_Testcase*>(t_ass);
4965 if (!t_testcase) FATAL_ERROR("Type::chk_this_value_FAT()");
4966 Type *t_system_type = t_testcase->get_SystemType();
4967 // if the system clause is missing we shall examine the component type
4968 // that is given in the 'runs on' clause
4969 if (!t_system_type) t_system_type = t_runs_on_type;
4970 Type *my_system_type =
4971 u.fatref.system.ref ? u.fatref.system.type : u.fatref.runs_on.type;
4972 if (t_system_type && my_system_type &&
4973 !t_system_type->is_compatible(my_system_type, NULL)) {
4974 value->error("System clause mismatch: testcase type `%s' expects "
4975 "component type `%s', but %s has `%s'", get_typename().c_str(),
4976 my_system_type->get_typename().c_str(),
4977 t_ass->get_description().c_str(),
4978 t_system_type->get_typename().c_str());
4979 }
4980 } else if (typetype == T_FUNCTION) {
4981 // comparison of return types
4982 bool t_returns_template = false;
4983 switch (t_asstype) {
4984 case Assignment::A_FUNCTION:
4985 case Assignment::A_EXT_FUNCTION:
4986 if (u.fatref.return_type) {
4987 value->error("Type `%s' expects a function or external function "
4988 "that returns a %s of type `%s', but %s does not have return type",
4989 get_typename().c_str(),
4990 u.fatref.returns_template ? "template" : "value",
4991 u.fatref.return_type->get_typename().c_str(),
4992 t_ass->get_description().c_str());
4993 }
4994 break;
4995 case Assignment::A_FUNCTION_RTEMP:
4996 case Assignment::A_EXT_FUNCTION_RTEMP: {
4997 // comparison of template restrictions
4998 Ttcn::Def_Function_Base* dfb =
4999 dynamic_cast<Ttcn::Def_Function_Base*>(t_ass);
5000 if (!dfb) FATAL_ERROR("Type::chk_this_value_FAT()");
5001 template_restriction_t refd_tr = dfb->get_template_restriction();
5002 if (refd_tr!=u.fatref.template_restriction) {
5003 value->error("Type `%s' expects a function or external function "
5004 "that returns a template with %s restriction, "
5005 "but %s returns a template with %s restriction",
5006 get_typename().c_str(),
5007 u.fatref.template_restriction==TR_NONE ? "no" :
5008 Template::get_restriction_name(u.fatref.template_restriction),
5009 t_ass->get_description().c_str(),
5010 refd_tr==TR_NONE ? "no" : Template::get_restriction_name(refd_tr));
5011 }
5012 }
5013 t_returns_template = true;
5014 // no break
5015 case Assignment::A_FUNCTION_RVAL:
5016 case Assignment::A_EXT_FUNCTION_RVAL:
5017 if (u.fatref.return_type) {
5018 Type *t_return_type = t_ass->get_Type();
5019 if (!u.fatref.return_type->is_identical(t_return_type)) {
5020 value->error("Return type mismatch: type `%s' expects a function "
5021 "or external function that returns a %s of type `%s', but %s "
5022 "returns a %s of type `%s'", get_typename().c_str(),
5023 u.fatref.returns_template ? "template" : "value",
5024 u.fatref.return_type->get_typename().c_str(),
5025 t_ass->get_description().c_str(),
5026 t_returns_template ? "template" : "value",
5027 t_return_type->get_typename().c_str());
5028 } else if (u.fatref.return_type->get_sub_type() && t_return_type->get_sub_type() &&
5029 (u.fatref.return_type->get_sub_type()->get_subtypetype()==t_return_type->get_sub_type()->get_subtypetype()) &&
5030 (!u.fatref.return_type->get_sub_type()->is_compatible(t_return_type->get_sub_type()))) {
5031 // TODO: maybe equivalence should be checked, or maybe that is too strict
5032 value->error("Return type subtype mismatch: subtype %s has no common value with subtype %s",
5033 u.fatref.return_type->get_sub_type()->to_string().c_str(),
5034 t_return_type->get_sub_type()->to_string().c_str());
5035 } else if (u.fatref.returns_template != t_returns_template) {
5036 value->error("Type `%s' expects a function or external function "
5037 "that returns a %s of type `%s', but %s returns a %s",
5038 get_typename().c_str(),
5039 u.fatref.returns_template ? "template" : "value",
5040 u.fatref.return_type->get_typename().c_str(),
5041 t_ass->get_description().c_str(),
5042 t_returns_template ? "template" : "value");
5043 }
5044 } else {
5045 value->error("Type `%s' expects a function or external function "
5046 "without return type, but %s returns a %s of type `%s'",
5047 get_typename().c_str(), t_ass->get_description().c_str(),
5048 t_returns_template ? "template" : "value",
5049 t_ass->get_Type()->get_typename().c_str());
5050 }
5051 break;
5052 default:
5053 FATAL_ERROR("Type::chk_this_value_FAT()");
5054 }
5055 }
5056}
5057
5058void Type::chk_this_template_length_restriction(Template *t)
5059{
5060 Ttcn::LengthRestriction *lr = t->get_length_restriction();
5061 if (!lr) FATAL_ERROR("Type::chk_this_template_length_restriction()");
5062 // first check the length restriction itself
5063 lr->chk(EXPECTED_DYNAMIC_VALUE);
5064 if (is_ref()) {
5065 /** \todo check lr against the length subtype constraint of this */
5066 get_type_refd()->chk_this_template_length_restriction(t);
5067 return;
5068 }
5069 typetype_t tt = get_typetype_ttcn3(typetype);
5070 switch (tt) {
5071 case T_ERROR:
5072 case T_PORT:
5073 // return silently, the type of the template is erroneous anyway
5074 return;
5075 case T_ARRAY:
5076 lr->chk_array_size(u.array.dimension);
5077 /* no break */
5078 case T_BSTR:
5079 case T_HSTR:
5080 case T_OSTR:
5081 case T_CSTR:
5082 case T_USTR:
5083 case T_SETOF:
5084 case T_SEQOF:
5085 // length restriction is allowed for these types
5086 break;
5087 default:
5088 lr->error("Length restriction cannot be used in a template of type `%s'",
5089 get_typename().c_str());
5090 return;
5091 }
5092 // check whether the number of elements in t is in accordance with lr
5093 Template *t_last = t->get_template_refd_last();
5094 switch (t_last->get_templatetype()) {
5095 case Ttcn::Template::OMIT_VALUE:
5096 lr->error("Length restriction cannot be used with omit value");
5097 break;
5098 case Ttcn::Template::SPECIFIC_VALUE: {
5099 Value *v_last = t_last->get_specific_value()->get_value_refd_last();
5100 switch (v_last->get_valuetype()) {
5101 case Value::V_BSTR:
5102 if (tt == T_BSTR)
5103 lr->chk_nof_elements(v_last->get_val_strlen(), false, *t, "string");
5104 break;
5105 case Value::V_HSTR:
5106 if (tt == T_HSTR)
5107 lr->chk_nof_elements(v_last->get_val_strlen(), false, *t, "string");
5108 break;
5109 case Value::V_OSTR:
5110 if (tt == T_OSTR)
5111 lr->chk_nof_elements(v_last->get_val_strlen(), false, *t, "string");
5112 break;
5113 case Value::V_CSTR:
5114 if (tt == T_CSTR || tt == T_USTR)
5115 lr->chk_nof_elements(v_last->get_val_strlen(), false, *t, "string");
5116 break;
5117 case Value::V_USTR:
5118 if (tt == T_USTR)
5119 lr->chk_nof_elements(v_last->get_val_strlen(), false, *t, "string");
5120 break;
5121 case Value::V_SEQOF:
5122 if (tt == T_SEQOF)
5123 lr->chk_nof_elements(v_last->get_nof_comps(), false, *t, "value");
5124 break;
5125 case Value::V_SETOF:
5126 if (tt == T_SETOF)
5127 lr->chk_nof_elements(v_last->get_nof_comps(), false, *t, "value");
5128 break;
5129 // note: do not check array values
5130 // they are already verified against the array size
5131 case Value::V_OMIT:
5132 lr->error("Length restriction cannot be used with omit value");
5133 default:
5134 // we cannot verify anything on other value types
5135 // they are either correct or not applicable to the type
5136 break;
5137 }
5138 break; }
5139 case Ttcn::Template::TEMPLATE_LIST:
5140 if (tt == T_SEQOF || tt == T_SETOF)
5141 lr->chk_nof_elements(t_last->get_nof_comps_not_anyornone(),
5142 t_last->temps_contains_anyornone_symbol(), *t, "template");
5143 // note: do not check array templates
5144 // they are already verified against the array size
5145 break;
5146 case Ttcn::Template::SUPERSET_MATCH:
5147 if (tt == T_SETOF)
5148 lr->chk_nof_elements(t_last->get_nof_comps_not_anyornone(), true,
5149 *t, "template");
5150 break;
5151 case Ttcn::Template::BSTR_PATTERN:
5152 if (tt == T_BSTR)
5153 lr->chk_nof_elements(t_last->get_min_length_of_pattern(),
5154 t_last->pattern_contains_anyornone_symbol(), *t, "string");
5155 break;
5156 case Ttcn::Template::HSTR_PATTERN:
5157 if (tt == T_HSTR)
5158 lr->chk_nof_elements(t_last->get_min_length_of_pattern(),
5159 t_last->pattern_contains_anyornone_symbol(), *t, "string");
5160 break;
5161 case Ttcn::Template::OSTR_PATTERN:
5162 if (tt == T_OSTR)
5163 lr->chk_nof_elements(t_last->get_min_length_of_pattern(),
5164 t_last->pattern_contains_anyornone_symbol(), *t, "string");
5165 break;
5166 case Ttcn::Template::CSTR_PATTERN:
5167 if (tt == T_CSTR || tt == T_USTR)
5168 lr->chk_nof_elements(t_last->get_min_length_of_pattern(),
5169 t_last->pattern_contains_anyornone_symbol(), *t, "string");
5170 break;
5171 default:
5172 // We cannot verify anything on other matching mechanisms.
5173 // They are either correct or not applicable to the type.
5174 break;
5175 }
5176}
5177
5178void Type::chk_this_template_ref(Template *t)
5179{
5180 switch (t->get_templatetype()) {
5181 case Ttcn::Template::SPECIFIC_VALUE: {
5182// if (t->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE) return;
5183 Value *v = t->get_specific_value();
5184 chk_this_value_ref(v);
5185 switch (v->get_valuetype()) {
5186 case Value::V_REFD: {
5187 // Do not check the actual parameter list of the reference yet to avoid
5188 // endless recursion in case of embedded circular references.
5189 // The parameter lists will be verified later.
5190 Assignment *ass = v->get_reference()->get_refd_assignment(false);
5191 if (ass) {
5192 switch (ass->get_asstype()) {
5193 case Assignment::A_VAR_TEMPLATE: {
5194 Type* type = ass->get_Type();
5195 switch (type->typetype) {
5196 case T_BSTR:
5197 case T_BSTR_A:
5198 case T_HSTR:
5199 case T_OSTR:
5200 case T_CSTR:
5201 case T_USTR:
5202 case T_UTF8STRING:
5203 case T_NUMERICSTRING:
5204 case T_PRINTABLESTRING:
5205 case T_TELETEXSTRING:
5206 case T_VIDEOTEXSTRING:
5207 case T_IA5STRING:
5208 case T_GRAPHICSTRING:
5209 case T_VISIBLESTRING:
5210 case T_GENERALSTRING:
5211 case T_UNIVERSALSTRING:
5212 case T_BMPSTRING:
5213 case T_UTCTIME:
5214 case T_GENERALIZEDTIME:
5215 case T_OBJECTDESCRIPTOR: {
5216 // TR 921 (indexing of template strings)
5217 Ttcn::FieldOrArrayRefs *subrefs = v->get_reference()
5218 ->get_subrefs();
5219 if (!subrefs) break;
5220 size_t nof_subrefs = subrefs->get_nof_refs();
5221 if (nof_subrefs > 0) {
5222 Ttcn::FieldOrArrayRef *last_ref = subrefs
5223 ->get_ref(nof_subrefs - 1);
5224 if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
5225 t->error("Reference to %s can not be indexed",
5226 (ass->get_description()).c_str());
5227 t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5228 return;
5229 }
5230 }
5231 break; }
5232 default:
5233 break;
5234 }
5235 }
5236 case Assignment::A_MODULEPAR_TEMP:
5237 case Assignment::A_TEMPLATE:
5238 case Assignment::A_PAR_TEMPL_IN:
5239 case Assignment::A_PAR_TEMPL_OUT:
5240 case Assignment::A_PAR_TEMPL_INOUT:
5241 case Assignment::A_FUNCTION_RTEMP:
5242 case Assignment::A_EXT_FUNCTION_RTEMP:
5243 t->set_templatetype(Ttcn::Template::TEMPLATE_REFD);
5244 default:
5245 break;
5246 }
5247 } else t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5248 break; }
5249 case Value::V_INVOKE: {
5250 Type *t2 = v->get_invoked_type(Type::EXPECTED_TEMPLATE);
5251 if(t2 && t2->get_type_refd_last()->get_returns_template())
5252 t->set_templatetype(Ttcn::Template::TEMPLATE_INVOKE);
5253 break; }
5254 default:
5255 break;
5256 }
5257 break;
5258 }
5259 case Ttcn::Template::TEMPLATE_REFD: {
5260 // Do not check the actual parameter list of the reference yet to avoid
5261 // endless recursion in case of embedded circular references.
5262 // The parameter lists will be verified later.
5263 Assignment *ass = t->get_reference()->get_refd_assignment(false);
5264 if (ass) {
5265 switch (ass->get_asstype()) {
5266 case Assignment::A_VAR_TEMPLATE: {
5267 Type* type = ass->get_Type();
5268 switch (type->typetype) {
5269 case T_BSTR:
5270 case T_BSTR_A:
5271 case T_HSTR:
5272 case T_OSTR:
5273 case T_CSTR:
5274 case T_USTR:
5275 case T_UTF8STRING:
5276 case T_NUMERICSTRING:
5277 case T_PRINTABLESTRING:
5278 case T_TELETEXSTRING:
5279 case T_VIDEOTEXSTRING:
5280 case T_IA5STRING:
5281 case T_GRAPHICSTRING:
5282 case T_VISIBLESTRING:
5283 case T_GENERALSTRING:
5284 case T_UNIVERSALSTRING:
5285 case T_BMPSTRING:
5286 case T_UTCTIME:
5287 case T_GENERALIZEDTIME:
5288 case T_OBJECTDESCRIPTOR: {
5289 // TR 921 (indexing of template strings)
5290 Ttcn::FieldOrArrayRefs *subrefs = t->get_reference()
5291 ->get_subrefs();
5292 if (!subrefs) break;
5293 size_t nof_subrefs = subrefs->get_nof_refs();
5294 if (nof_subrefs > 0) {
5295 Ttcn::FieldOrArrayRef *last_ref = subrefs
5296 ->get_ref(nof_subrefs - 1);
5297 if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) {
5298 t->error("Reference to %s can not be indexed",
5299 (ass->get_description()).c_str());
5300 t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5301 return;
5302 }
5303 }
5304 break; }
5305 default:
5306 break;
5307 }
5308 }
5309 case Assignment::A_MODULEPAR_TEMP:
5310 case Assignment::A_TEMPLATE:
5311 case Assignment::A_PAR_TEMPL_IN:
5312 case Assignment::A_PAR_TEMPL_OUT:
5313 case Assignment::A_PAR_TEMPL_INOUT:
5314 case Assignment::A_FUNCTION_RTEMP:
5315 case Assignment::A_EXT_FUNCTION_RTEMP:
5316 t->set_templatetype(Ttcn::Template::TEMPLATE_REFD);
5317 default:
5318 break;
5319 }
5320 } else t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5321 }
5322 break;
5323 default:
5324 return;
5325 }
5326}
5327
5328bool Type::chk_this_template_ref_pard(Ttcn::Ref_pard* ref_pard, Common::Assignment* lhs)
5329{
5330 // Check if the reference on the left hand side of the assignment can be found
5331 // among the parameters
5332 Ttcn::ActualParList* par_list = ref_pard->get_parlist();
5333 if (par_list) {
5334 size_t nof_pars = par_list->get_nof_pars();
5335 for (size_t i = 0; i < nof_pars; ++i) {
5336 Ttcn::ActualPar* par = par_list->get_par(i);
5337 Ttcn::Ref_base* par_ref = 0;
5338 switch(par->get_selection()) {
5339 case Ttcn::ActualPar::AP_TEMPLATE: {
5340 Ttcn::TemplateInstance* temp_ins = par->get_TemplateInstance();
5341 Ttcn::Template* temp = temp_ins->get_Template();
5342 if (temp->get_templatetype() == Ttcn::Template::TEMPLATE_REFD) {
5343 par_ref = temp->get_reference();
5344 }
5345 break;
5346 }
5347 case Ttcn::ActualPar::AP_REF: {
5348 par_ref = par->get_Ref();
5349 break;
5350 }
5351 default:
5352 break;
5353 }
5354
5355 if (par_ref != 0) {
5356 Common::Assignment* ass = par_ref->get_refd_assignment(true); // also check parameters if there are any
5357 if (ass == lhs)
5358 return true;
5359
5360 // In case a parameter is another function call / parametrised template
5361 // check their parameters as well
5362 if (ass->get_asstype() == Assignment::A_FUNCTION_RTEMP ||
5363 ass->get_asstype() == Assignment::A_EXT_FUNCTION_RTEMP ||
5364 ass->get_asstype() == Assignment::A_TEMPLATE) {
5365 ref_pard = dynamic_cast<Ttcn::Ref_pard*>(par_ref);
5366 if (ref_pard && chk_this_template_ref_pard(ref_pard, lhs))
5367 return true;
5368 }
5369 }
5370 }
5371 }
5372 return false;
5373}
5374
5375bool Type::chk_this_template_generic(Template *t, namedbool incomplete_allowed,
5376 namedbool allow_omit, namedbool allow_any_or_omit, namedbool sub_chk,
5377 namedbool implicit_omit, Common::Assignment *lhs)
5378{
5379 bool self_ref = false;
5380 if (!allow_omit && t->get_template_refd_last()->get_templatetype() ==
5381 Ttcn::Template::OMIT_VALUE) {
5382 t->error("`omit' value is not allowed in this context");
5383 }
5384 if (!allow_any_or_omit && t->get_template_refd_last()->get_templatetype() ==
5385 Ttcn::Template::ANY_OR_OMIT) {
5386 t->warning("Using `*' for mandatory field");
5387 }
5388
5389 Ttcn::Template::templatetype_t temptype = t->get_templatetype();
5390 switch(temptype) {
5391 case Ttcn::Template::TEMPLATE_ERROR:
5392 break;
5393 case Ttcn::Template::TEMPLATE_NOTUSED:
5394 case Ttcn::Template::OMIT_VALUE:
5395 case Ttcn::Template::ANY_VALUE:
5396 case Ttcn::Template::ANY_OR_OMIT: {
5397 Type *type=get_type_refd_last();
5398 if (type->get_typetype() == T_SIGNATURE)
5399 t->error("Generic wildcard `%s' cannot be used for signature `%s'",
5400 t->get_templatetype_str(), type->get_fullname().c_str());
5401 break;}
5402 case Ttcn::Template::VALUE_LIST_ALL_FROM:
5403 case Ttcn::Template::ALL_FROM: {
5404 Ttcn::Template *af = t->get_all_from();
5405 switch (af->get_templatetype()) {
5406 case Ttcn::Template::SPECIFIC_VALUE: {
5407 Value *v = af->get_specific_value();
5408 v->set_lowerid_to_ref();
5409 Reference *ref = v->get_reference();
5410 Assignment *ass = ref->get_refd_assignment(true); // also check parameters if there are any
5411 if (!ass) break; // probably erroneous
5412 //warning("asstype %d", ass->get_asstype());
5413
5414 switch (ass->get_asstype()) {
5415 case Assignment::A_VAR:
5416 case Assignment::A_PAR_VAL_IN:
5417 case Assignment::A_PAR_VAL_INOUT:
5418 case Assignment::A_MODULEPAR:
5419 case Assignment::A_CONST:
5420 case Assignment::A_MODULEPAR_TEMP:
5421 break; // acceptable
5422 case Assignment::A_VAR_TEMPLATE:
5423 case Assignment::A_PAR_TEMPL_IN:
5424 case Assignment::A_PAR_TEMPL_INOUT:
5425 if (ass == lhs)
5426 self_ref = true;
5427 break; // acceptable
5428 case Assignment::A_FUNCTION_RVAL:
5429 case Assignment::A_EXT_FUNCTION_RVAL:
5430 case Assignment::A_FUNCTION_RTEMP:
5431 case Assignment::A_EXT_FUNCTION_RTEMP:
5432 case Assignment::A_TEMPLATE: {
5433 Ttcn::Ref_pard* ref_pard = dynamic_cast<Ttcn::Ref_pard*>(ref);
5434 if (ref_pard)
5435 self_ref |= chk_this_template_ref_pard(ref_pard, lhs);
5436 break; // acceptable
5437 }
5438 default:
5439 error("A %s cannot be used as the target of `all from'",
5440 ass->get_assname());
5441 break;
5442 }
5443 //self_ref |= chk_this_value(v, lhs, EXPECTED_TEMPLATE, incomplete_allowed,
5444 // allow_omit, sub_chk, implicit_omit, NOT_STR_ELEM /* ?? */);
5445 break; }
5446
5447 default:
5448 error("The target of an 'all from' must be a specific value template, not a %s",
5449 af->get_templatetype_str());
5450 break;
5451 }
5452
5453 break; }
5454 case Ttcn::Template::VALUE_LIST:
5455 case Ttcn::Template::COMPLEMENTED_LIST: {
5456 size_t nof_comps = t->get_nof_comps();
5457 for (size_t i = 0; i < nof_comps; i++) {
5458 Template* t_comp = t->get_temp_byIndex(i);
5459 Error_Context cntxt(t, "In list item %lu", (unsigned long) (i + 1));
5460 t_comp->set_my_governor(this);
5461 chk_this_template_ref(t_comp);
5462 self_ref |= chk_this_template_generic(t_comp, INCOMPLETE_NOT_ALLOWED,
3abe9331 5463 omit_in_value_list ? OMIT_ALLOWED : OMIT_NOT_ALLOWED,
5464 ANY_OR_OMIT_ALLOWED, sub_chk, implicit_omit, lhs);
970ed795
EL
5465 if(temptype==Ttcn::Template::COMPLEMENTED_LIST &&
5466 t_comp->get_template_refd_last()->get_templatetype() ==
5467 Ttcn::Template::ANY_OR_OMIT)
5468 t_comp->warning("`*' in complemented list."
5469 " This template will not match anything");
5470 }
5471 break;}
5472 case Ttcn::Template::SPECIFIC_VALUE: {
5473 Value *v = t->get_specific_value();
5474 v->set_my_governor(this);
5475 self_ref |= chk_this_value(v, lhs, EXPECTED_TEMPLATE, incomplete_allowed,
5476 allow_omit, SUB_CHK);
5477 break; }
5478 case Ttcn::Template::TEMPLATE_INVOKE: {
5479 t->chk_invoke();
5480 Type *governor = t->get_expr_governor(EXPECTED_DYNAMIC_VALUE);
5481 if(!governor)
5482 t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5483 else if (!is_compatible(governor, NULL)) {
5484 t->error("Type mismatch: a value or template of type `%s' was "
5485 "expected instead of `%s'", get_typename().c_str(),
5486 governor->get_typename().c_str());
5487 t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5488 }
5489 break; }
5490 case Ttcn::Template::TEMPLATE_REFD:
5491 self_ref = chk_this_refd_template(t, lhs);
5492 break;
5493 default:
5494 self_ref = chk_this_template(t, incomplete_allowed, sub_chk, implicit_omit, lhs);
5495 break;
5496 }
5497 if (t->get_length_restriction()) chk_this_template_length_restriction(t);
5498 if (!allow_omit && t->get_ifpresent())
5499 t->error("`ifpresent' is not allowed here");
5500 if(sub_chk && temptype != Ttcn::Template::PERMUTATION_MATCH) {
5501 /* Note: A "permuation" itself has no type - it is just a fragment. */
5502 if(sub_type!=NULL) sub_type->chk_this_template_generic(t);
5503 }
5504
5505 return self_ref;
5506}
5507
5508bool Type::chk_this_refd_template(Template *t, Common::Assignment *lhs)
5509{
5510 if (t->get_templatetype() != Template::TEMPLATE_REFD) return false;
5511 Reference *ref = t->get_reference();
5512 Assignment *ass = ref->get_refd_assignment();
5513 if (!ass) FATAL_ERROR("Type::chk_this_refd_template()");
5514 ass->chk();
5515
5516 Type *governor = ass->get_Type()
5517 ->get_field_type(ref->get_subrefs(), EXPECTED_DYNAMIC_VALUE);
5518 if (!governor) {
5519 t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5520 } else {
5521 TypeCompatInfo info(t->get_my_scope()->get_scope_mod(), this, governor,
5522 true, false, true);
5523 if (ref->get_subrefs()) info.set_str2_elem(ref->get_subrefs()->refers_to_string_element());
5524 TypeChain l_chain;
5525 TypeChain r_chain;
5526 if (!is_compatible(governor, &info, &l_chain, &r_chain)) {
5527 Type *type = get_type_refd_last();
5528 switch (type->typetype) {
5529 case T_PORT:
5530 // Port templates do not exist, remain silent.
5531 break;
5532 case T_SIGNATURE:
5533 t->error("Type mismatch: a signature template of type `%s' was "
5534 "expected instead of `%s'", get_typename().c_str(),
5535 governor->get_typename().c_str());
5536 break;
5537 default:
5538 if (info.is_subtype_error()) {
5539 t->error("%s", info.get_subtype_error().c_str());
5540 } else if (!info.is_erroneous()) {
5541 t->error("Type mismatch: a value or template of type `%s' was "
5542 "expected instead of `%s'", get_typename().c_str(),
5543 governor->get_typename().c_str());
5544 } else {
5545 t->error("%s", info.get_error_str_str().c_str());
5546 }
5547 break;
5548 }
5549 t->set_templatetype(Ttcn::Template::TEMPLATE_ERROR);
5550 } else {
5551 // Detect circular references.
5552 t->get_template_refd_last();
5553
5554 if (info.needs_conversion()) t->set_needs_conversion();
5555 }
5556 }
5557 return (lhs == ass);
5558}
5559
5560bool Type::chk_this_template(Template *t, namedbool is_modified, namedbool,
5561 namedbool implicit_omit, Common::Assignment *lhs)
5562{
5563 bool self_ref = false;
5564 Type *t_last = get_type_refd_last();
5565 t->set_my_governor(t_last);
5566
5567 switch(t_last->typetype) {
5568 case T_ERROR:
5569 break;
5570 case T_NULL:
5571 case T_BOOL:
5572 case T_OID:
5573 case T_ROID:
5574 case T_ANY:
5575 case T_VERDICT:
5576 case T_COMPONENT:
5577 case T_DEFAULT:
5578 t_last->chk_this_template_builtin(t);
5579 break;
5580 case T_BSTR_A:
5581 case T_BSTR:
5582 case T_HSTR:
5583 case T_OSTR:
5584 case T_CSTR:
5585 case T_USTR:
5586 case T_UTF8STRING:
5587 case T_NUMERICSTRING:
5588 case T_PRINTABLESTRING:
5589 case T_TELETEXSTRING:
5590 case T_VIDEOTEXSTRING:
5591 case T_IA5STRING:
5592 case T_GRAPHICSTRING:
5593 case T_VISIBLESTRING:
5594 case T_GENERALSTRING:
5595 case T_UNIVERSALSTRING:
5596 case T_BMPSTRING:
5597 case T_UTCTIME:
5598 case T_GENERALIZEDTIME:
5599 case T_OBJECTDESCRIPTOR:
5600 t_last->chk_this_template_Str(t);
5601 break;
5602 case T_INT:
5603 case T_INT_A:
5604 case T_REAL:
5605 t_last->chk_this_template_Int_Real(t);
5606 break;
5607 case T_ENUM_A:
5608 case T_ENUM_T:
5609 t_last->chk_this_template_Enum(t);
5610 break;
5611 case T_CHOICE_A:
5612 case T_CHOICE_T:
5613 case T_OPENTYPE:
5614 case T_ANYTYPE:
5615 self_ref = t_last->chk_this_template_Choice(t, is_modified, implicit_omit, lhs);
5616 break;
5617 case T_SEQ_A:
5618 case T_SEQ_T:
5619 self_ref = t_last->chk_this_template_Seq(t, is_modified, implicit_omit, lhs);
5620 break;
5621 case T_SET_A:
5622 case T_SET_T:
5623 self_ref = t_last->chk_this_template_Set(t, is_modified, implicit_omit, lhs);
5624 break;
5625 case T_SEQOF:
5626 self_ref = t_last->chk_this_template_SeqOf(t, is_modified, implicit_omit, lhs);
5627 break;
5628 case T_SETOF:
5629 self_ref = t_last->chk_this_template_SetOf(t, is_modified, implicit_omit, lhs);
5630 break;
5631 case T_ARRAY:
5632 self_ref = t_last->chk_this_template_array(t, is_modified, implicit_omit, lhs);
5633 break;
5634 case T_PORT:
5635 t->error("Template cannot be defined for port type `%s'",
5636 get_fullname().c_str());
5637 break;
5638 case T_SIGNATURE:
5639 t_last->chk_this_template_Signature(t, is_modified);
5640 break;
5641 case T_FUNCTION:
5642 case T_ALTSTEP:
5643 case T_TESTCASE:
5644 t_last->chk_this_template_Fat(t);
5645 break;
5646 default:
5647 FATAL_ERROR("Type::chk_this_template()");
5648 } // switch
5649 return self_ref;
5650}
5651
5652void Type::chk_this_template_Str(Template *t)
5653{
5654 typetype_t tt = get_typetype_ttcn3(typetype);
5655 bool report_error = false;
5656 switch (t->get_templatetype()) {
5657 case Ttcn::Template::VALUE_RANGE:
5658 if (tt == T_CSTR || tt == T_USTR) {
5659 Error_Context cntxt(t, "In value range");
5660 Ttcn::ValueRange *vr = t->get_value_range();
5661 Value *v_lower = chk_range_boundary(vr->get_min_v(), "lower", *t);
5662 Value *v_upper = chk_range_boundary(vr->get_max_v(), "upper", *t);
5663 if (v_lower && v_upper) {
5664 // both boundaries are available and have correct type
5665 if (tt == T_CSTR) {
5666 if (v_lower->get_val_str() > v_upper->get_val_str())
5667 t->error("The lower boundary has higher character code than the "
5668 "upper boundary");
5669 } else {
5670 if (v_lower->get_val_ustr() > v_upper->get_val_ustr())
5671 t->error("The lower boundary has higher character code than the "
5672 "upper boundary");
5673 }
5674 }
5675 } else report_error = true;
5676 break;
5677 case Ttcn::Template::BSTR_PATTERN:
5678 if (tt != T_BSTR) report_error = true;
5679 break;
5680 case Ttcn::Template::HSTR_PATTERN:
5681 if (tt != T_HSTR) report_error = true;
5682 break;
5683 case Ttcn::Template::OSTR_PATTERN:
5684 if (tt != T_OSTR) report_error = true;
5685 break;
5686 case Ttcn::Template::CSTR_PATTERN:
5687 if (tt == T_CSTR) {
5688 Ttcn::PatternString *pstr = t->get_cstr_pattern();
5689 Error_Context cntxt(t, "In character string pattern");
5690 pstr->chk_refs();
5691 pstr->join_strings();
5692 if (!pstr->has_refs()) pstr->chk_pattern();
5693 break;
5694 } else if (tt == T_USTR) {
5695 t->set_templatetype(Template::USTR_PATTERN);
5696 t->get_ustr_pattern()
5697 ->set_pattern_type(Ttcn::PatternString::USTR_PATTERN);
5698 // fall through
5699 } else {
5700 report_error = true;
5701 break;
5702 }
5703 // no break
5704 case Ttcn::Template::USTR_PATTERN:
5705 if (tt == T_USTR) {
5706 Ttcn::PatternString *pstr = t->get_ustr_pattern();
5707 Error_Context cntxt(t, "In universal string pattern");
5708 pstr->chk_refs();
5709 pstr->join_strings();
5710 if (!pstr->has_refs()) pstr->chk_pattern();
5711 } else report_error = true;
5712 break;
5713 default:
5714 report_error = true;
5715 break;
5716 }
5717 if (report_error) {
5718 t->error("%s cannot be used for type `%s'", t->get_templatetype_str(),
5719 get_typename().c_str());
5720 }
5721}
5722
af710487 5723void Type::chk_range_boundary_infinity(Value *v, bool is_upper)
5724{
5725 if (v) {
5726 v->set_my_governor(this);
5727 {
5728 Error_Context cntxt2(v, "In %s boundary", is_upper ? "upper" : "lower");
5729 chk_this_value_ref(v);
5730 Value *v_last = v->get_value_refd_last(0, EXPECTED_STATIC_VALUE);
5731 if (v_last->get_valuetype() == Value::V_OMIT) {
5732 v->error("`omit' value is not allowed in this context");
5733 v->set_valuetype(Value::V_ERROR);
5734 return;
5735 }
5736 if (sub_type != NULL) {
5737 if (is_upper) {
5738 if (!sub_type->get_root()->is_upper_limit_infinity()) {
5739 v->error("Infinity is not a valid value for type '%s' which has subtype %s",
5740 asString(), sub_type->to_string().c_str());
5741 }
5742 }
5743 else {
5744 if (!sub_type->get_root()->is_lower_limit_infinity()) {
5745 v->error("Infinity is not a valid value for type '%s' which has subtype %s",
5746 asString(), sub_type->to_string().c_str());
5747 }
5748 }
5749 }
5750 }
5751 }
5752}
5753
970ed795
EL
5754Value *Type::chk_range_boundary(Value *v, const char *which,
5755 const Location& loc)
5756{
5757 typetype_t tt = get_typetype_ttcn3(typetype);
5758 Value *ret_val;
5759 if (v) {
5760 v->set_my_governor(this);
5761 {
5762 Error_Context cntxt2(v, "In %s boundary", which);
5763 chk_this_value_ref(v);
5764 chk_this_value(v, 0, EXPECTED_DYNAMIC_VALUE, INCOMPLETE_NOT_ALLOWED,
5765 OMIT_NOT_ALLOWED, SUB_CHK);
5766 }
5767 ret_val = v->get_value_refd_last();
5768 switch (ret_val->get_valuetype()) {
5769 case Value::V_INT:
5770 if (tt != T_INT) ret_val = 0;
5771 break;
5772 case Value::V_REAL:
5773 if (tt != T_REAL) ret_val = 0;
5774 break;
5775 case Value::V_CSTR:
5776 if (tt != T_CSTR) ret_val = 0;
5777 break;
5778 case Value::V_USTR:
5779 if (tt != T_USTR) ret_val = 0;
5780 break;
5781 default:
5782 // unfoldable or erroneous
5783 ret_val = 0;
5784 break;
5785 }
5786 if ((tt == T_CSTR || tt == T_USTR) && ret_val &&
5787 ret_val->get_val_strlen() != 1) {
5788 v->error("The %s boundary must be a %scharstring value containing a "
5789 "single character", which, tt == T_USTR ? "universal ": "");
5790 ret_val = 0;
5791 }
5792 } else {
5793 // the boundary is + or - infinity
5794 if (tt == T_CSTR || tt == T_USTR) {
5795 loc.error("The %s boundary must be a %scharstring value", which,
5796 tt == T_USTR ? "universal ": "");
5797 }
5798 ret_val = 0;
5799 }
5800 return ret_val;
5801}
5802
5803void Type::chk_this_template_builtin(Template *t)
5804{
5805 t->error("%s cannot be used for type `%s'", t->get_templatetype_str(),
5806 get_typename().c_str());
5807 if (t->get_length_restriction()) t->error("Length restriction is not "
5808 "allowed for type `%s'", get_typename().c_str());
5809}
5810
5811void Type::chk_this_template_Int_Real(Template *t)
5812{
5813 switch (t->get_templatetype()) {
5814 case Ttcn::Template::VALUE_RANGE: {
5815 Error_Context cntxt(t, "In value range");
5816 Ttcn::ValueRange *vr = t->get_value_range();
5817 Value *v_lower = chk_range_boundary(vr->get_min_v(), "lower", *t);
5818 Value *v_upper = chk_range_boundary(vr->get_max_v(), "upper", *t);
5819 if (v_lower && v_upper) {
5820 // both boundaries are available and have correct type
5821 switch (get_typetype_ttcn3(typetype)) {
5822 case T_INT: {
5823 if (*v_lower->get_val_Int() > *v_upper->get_val_Int())
5824 t->error("The lower boundary is higher than the upper boundary");
5825 break; }
5826 case T_REAL:
5827 if (v_lower->get_val_Real() > v_upper->get_val_Real())
5828 t->error("The lower boundary is higher than the upper boundary");
5829 break;
5830 default:
5831 FATAL_ERROR("Type::chk_this_template_Int_Real()");
5832 }
5833 }
3abe9331 5834 if (v_lower && !vr->get_max_v()) {
af710487 5835 chk_range_boundary_infinity(v_lower, true);
5836 }
3abe9331 5837 if (!vr->get_min_v() && v_upper) {
af710487 5838 chk_range_boundary_infinity(v_upper, false);
5839 }
970ed795
EL
5840 break;}
5841 default:
5842 t->error("%s cannot be used for type `%s'", t->get_templatetype_str(),
5843 get_typename().c_str());
5844 break;
5845 }
5846 if (t->get_length_restriction()) t->error("Length restriction is not "
5847 "allowed for type `%s'", get_typename().c_str());
5848}
5849
5850void Type::chk_this_template_Enum(Template *t)
5851{
5852 t->error("%s cannot be used for enumerated type `%s'",
5853 t->get_templatetype_str(), get_typename().c_str());
5854 if (t->get_length_restriction()) t->error("Length restriction is not "
5855 "allowed for enumerated type `%s'", get_typename().c_str());
5856}
5857
5858bool Type::chk_this_template_Choice(Template *t, namedbool is_modified,
5859 namedbool implicit_omit, Common::Assignment *lhs)
5860{
5861 bool self_ref = false;
5862 switch (t->get_templatetype()) {
5863 case Ttcn::Template::NAMED_TEMPLATE_LIST: {
5864 size_t nof_nts = t->get_nof_comps();
5865 if (nof_nts != 1) t->error("A template for union type must contain "
5866 "exactly one selected field");
5867 // We check all named templates, even though it is an error
5868 // to have more than one here.
5869 for (size_t i = 0; i < nof_nts; i++) {
5870 Ttcn::NamedTemplate *nt = t->get_namedtemp_byIndex(i);
3abe9331 5871 if (typetype == T_OPENTYPE) {
5872 // allow the alternatives of open types as both lower and upper identifiers
5873 nt->set_name_to_lowercase();
5874 }
970ed795
EL
5875 const Identifier& nt_name = nt->get_name();
5876
5877 if (!has_comp_withName(nt_name)) {
5878 nt->error("Reference to non-existent field `%s' in union "
5879 "template for type `%s'", nt_name.get_dispname().c_str(),
5880 get_fullname().c_str());
5881 nt->note("%s", actual_fields(*this).c_str());
5882 continue;
5883 }
5884
5885 Type *field_type = get_comp_byName(nt_name)->get_type();
5886 Template *nt_templ = nt->get_template();
5887
5888 Error_Context cntxt(nt_templ, "In template for union field `%s'",
5889 nt_name.get_dispname().c_str());
5890
5891 nt_templ->set_my_governor(field_type);
5892 field_type->chk_this_template_ref(nt_templ);
5893 bool incompl_ok = t->get_completeness_condition_choice(is_modified, nt_name) ==
5894 Ttcn::Template::C_MAY_INCOMPLETE;
5895 self_ref |= field_type->chk_this_template_generic(nt_templ,
5896 (incompl_ok ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED),
5897 OMIT_NOT_ALLOWED, ANY_OR_OMIT_NOT_ALLOWED, SUB_CHK, implicit_omit, lhs);
5898 }
5899 break;}
5900 default:
5901 t->error("%s cannot be used for union type `%s'",
5902 t->get_templatetype_str(), get_typename().c_str());
5903 break;
5904 }
5905 if (t->get_length_restriction()) t->error("Length restriction is not "
5906 "allowed for union type `%s'", get_typename().c_str());
5907
5908 return self_ref;
5909}
5910
5911bool Type::chk_this_template_Seq(Template *t, namedbool is_modified,
5912 namedbool implicit_omit, Common::Assignment *lhs)
5913{
5914 bool self_ref = false;
5915 size_t n_type_comps = get_nof_comps();
5916 switch (t->get_templatetype()) {
5917 case Ttcn::Template::TEMPLATE_LIST:
5918 // conversion: value list -> assignment notation
5919 t->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST);
5920 // no break
5921 case Ttcn::Template::NAMED_TEMPLATE_LIST: {
5922 map<string, Ttcn::NamedTemplate> comp_map;
5923 // it is set to false if we have lost the ordering
5924 bool in_synch = true;
5925 size_t n_template_comps = t->get_nof_comps();
5926 // the two variables below are used for modified templates only
5927 CompField *last_cf = 0;
5928 size_t next_index = 0;
5929 for (size_t i = 0; i < n_template_comps; i++) {
5930 Ttcn::NamedTemplate *namedtemp = t->get_namedtemp_byIndex(i);
5931 const Identifier& temp_id = namedtemp->get_name();
5932 const string& temp_name = temp_id.get_name();
5933 const char *temp_dispname_str = temp_id.get_dispname().c_str();
5934 if (!has_comp_withName(temp_id)) {
5935 namedtemp->error("Reference to non-existent field `%s' in record "
5936 "template for type `%s'", temp_dispname_str,
5937 get_typename().c_str());
5938 namedtemp->note("%s", actual_fields(*this).c_str());
5939 in_synch = false;
5940 continue;
5941 } else if (comp_map.has_key(temp_name)) {
5942 namedtemp->error("Duplicate record field `%s' in template",
5943 temp_dispname_str);
5944 comp_map[temp_name]->note("Field `%s' is already given here",
5945 temp_dispname_str);
5946 in_synch = false;
5947 } else comp_map.add(temp_name, namedtemp);
5948
5949 CompField *cf = get_comp_byName(temp_id);
5950 if (in_synch) {
5951 if (is_modified) {
5952 // missing fields are allowed, but take care of ordering
5953 bool found = false;
5954 for (size_t j = next_index; j < n_type_comps; j++) {
5955 CompField *cf2 = get_comp_byIndex(j);
5956 if (temp_name == cf2->get_name().get_name()) {
5957 last_cf = cf2;
5958 next_index = j + 1;
5959 found = true;
5960 break;
5961 }
5962 }
5963 if (!found) {
5964 namedtemp->error("Field `%s' cannot appear after field `%s' in "
5965 "a template for record type `%s'", temp_dispname_str,
5966 last_cf->get_name().get_dispname().c_str(),
5967 get_fullname().c_str());
5968 in_synch = false;
5969 }
5970 } else {
5971 // the template must be complete
5972 CompField *cf2 = get_comp_byIndex(i);
5973 if (cf2 != cf) {
5974 if (!cf2->get_is_optional() || !implicit_omit) {
5975 namedtemp->error("Unexpected field `%s' in record template, "
5976 "expecting `%s'", temp_dispname_str,
5977 cf2->get_name().get_dispname().c_str());
5978 in_synch = false;
5979 }
5980 }
5981 }
5982 }
5983 Type *type = cf->get_type();
5984 Template *comp_t = namedtemp->get_template();
5985 Error_Context cntxt(comp_t, "In template for record field `%s'",
5986 temp_dispname_str);
5987 comp_t->set_my_governor(type);
5988 type->chk_this_template_ref(comp_t);
5989 bool is_optional = cf->get_is_optional(); // || cf->has_default()
5990 self_ref |= type->chk_this_template_generic(comp_t, is_modified,
5991 (is_optional ? OMIT_ALLOWED : OMIT_NOT_ALLOWED),
5992 (is_optional ? ANY_OR_OMIT_ALLOWED : ANY_OR_OMIT_NOT_ALLOWED),
5993 SUB_CHK, implicit_omit, lhs);
5994 }
5995 if (!is_modified || implicit_omit) {
5996 // check missing fields
5997 for (size_t i = 0; i < n_type_comps; i++) {
5998 const Identifier& id = get_comp_byIndex(i)->get_name();
5999 if (!comp_map.has_key(id.get_name())) {
6000 if (implicit_omit && get_comp_byIndex(i)->get_is_optional()) {
6001 // do not overwrite base fields
6002 if (!t->get_base_template())
6003 t->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id),
6004 new Template(Template::OMIT_VALUE)));
6005 } else if (!is_modified) {
6006 t->error("Field `%s' is missing from template for record type `%s'",
6007 id.get_dispname().c_str(), get_typename().c_str());
6008 }
6009 }
6010 }
6011 }
6012 comp_map.clear();
6013 break; }
6014 default:
6015 t->error("%s cannot be used for record type `%s'",
6016 t->get_templatetype_str(), get_typename().c_str());
6017 break;
6018 }
6019 if (t->get_length_restriction()) t->error("Length restriction is not "
6020 "allowed for record type `%s'", get_typename().c_str());
6021 return self_ref;
6022}
6023
6024bool Type::chk_this_template_Set(Template *t,
6025 namedbool is_modified, namedbool implicit_omit, Common::Assignment *lhs)
6026{
6027 bool self_ref = false;
6028 size_t n_type_comps = get_nof_comps();
6029 switch (t->get_templatetype()) {
6030 case Ttcn::Template::TEMPLATE_LIST:
6031 if (t->get_nof_comps() > 0) {
6032 t->error("Value list notation is not allowed for set type `%s'",
6033 get_fullname().c_str());
6034 break;
6035 } else if (n_type_comps > 0) {
6036 t->error("A non-empty set template was expected for type `%s'",
6037 get_fullname().c_str());
6038 break;
6039 }
6040 t->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST);
6041 // no break
6042 case Ttcn::Template::NAMED_TEMPLATE_LIST: {
6043 map<string, Ttcn::NamedTemplate> comp_map;
6044 size_t n_template_comps = t->get_nof_comps();
6045 for (size_t i = 0; i < n_template_comps; i++) {
6046 Ttcn::NamedTemplate *namedtemp = t->get_namedtemp_byIndex(i);
6047 const Identifier& temp_id=namedtemp->get_name();
6048 const string& temp_name = temp_id.get_name();
6049 const char *temp_dispname_str = temp_id.get_dispname().c_str();
6050 if (!has_comp_withName(temp_id)) {
6051 namedtemp->error("Reference to non-existent field `%s' in a "
6052 "template for set type `%s'", temp_dispname_str,
6053 get_typename().c_str());
6054 namedtemp->note("%s", actual_fields(*this).c_str());
6055 continue;
6056 } else if (comp_map.has_key(temp_name)) {
6057 namedtemp->error("Duplicate set field `%s' in template",
6058 temp_dispname_str);
6059 comp_map[temp_name]->note("Field `%s' is already given here",
6060 temp_dispname_str);
6061 } else comp_map.add(temp_name, namedtemp);
6062 CompField *cf = get_comp_byName(temp_id);
6063 Type *type = cf->get_type();
6064 Template *comp_t = namedtemp->get_template();
6065 Error_Context cntxt(comp_t, "In template for set field `%s'",
6066 temp_dispname_str);
6067 comp_t->set_my_governor(type);
6068 type->chk_this_template_ref(comp_t);
6069 bool is_optional = cf->get_is_optional();
6070 self_ref |= type->chk_this_template_generic(comp_t,
6071 (is_modified ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED),
6072 (is_optional ? OMIT_ALLOWED : OMIT_NOT_ALLOWED),
6073 (is_optional ? ANY_OR_OMIT_ALLOWED : ANY_OR_OMIT_NOT_ALLOWED),
6074 SUB_CHK, implicit_omit, lhs);
6075 }
6076 if (!is_modified || implicit_omit) {
6077 // check missing fields
6078 for (size_t i = 0; i < n_type_comps; i++) {
6079 const Identifier& id = get_comp_byIndex(i)->get_name();
6080 if (!comp_map.has_key(id.get_name())) {
6081 if (get_comp_byIndex(i)->get_is_optional() && implicit_omit) {
6082 // do not overwrite base fields
6083 if (!t->get_base_template())
6084 t->add_named_temp(new Ttcn::NamedTemplate(new Identifier(id),
6085 new Template(Template::OMIT_VALUE)));
6086 } else if (!is_modified) {
6087 t->error("Field `%s' is missing from template for set type `%s'",
6088 id.get_dispname().c_str(), get_typename().c_str());
6089 }
6090 }
6091 }
6092 }
6093 comp_map.clear();
6094 break; }
6095 default:
6096 t->error("%s cannot be used for set type `%s'",
6097 t->get_templatetype_str(), get_typename().c_str());
6098 break;
6099 }
6100 if (t->get_length_restriction()) t->error("Length restriction is not "
6101 "allowed for set type `%s'", get_typename().c_str());
6102 return self_ref;
6103}
6104
6105bool Type::chk_this_template_SeqOf(Template *t, namedbool is_modified,
6106 namedbool implicit_omit, Common::Assignment *lhs)
6107{
6108 bool self_ref = false;
6109 switch(t->get_templatetype()) {
6110 case Ttcn::Template::OMIT_VALUE:
6111 if(t->get_length_restriction())
6112 t->warning("Redundant usage of length restriction with `omit'");
6113 break;
6114 case Ttcn::Template::PERMUTATION_MATCH: {
6115 size_t nof_comps = t->get_nof_comps();
6116 for (size_t i = 0; i < nof_comps; i++) {
6117 Template *t_comp = t->get_temp_byIndex(i);
6118 Error_Context cntxt(t_comp, "In element %lu of permutation",
6119 (unsigned long) (i + 1));
6120 t_comp->set_my_governor(u.seof.ofType);
6121 u.seof.ofType->chk_this_template_ref(t_comp);
6122 // the elements of permutation must be always complete
6123 self_ref |= u.seof.ofType->chk_this_template_generic(t_comp,
6124 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK,
6125 NOT_IMPLICIT_OMIT, lhs);
6126 }
6127 break; }
6128 case Ttcn::Template::TEMPLATE_LIST: {
6129 Ttcn::Template::completeness_t c =
6130 t->get_completeness_condition_seof(is_modified);
6131 Template *t_base;
6132 size_t nof_base_comps;
6133 if (c == Ttcn::Template::C_PARTIAL) {
6134 t_base = t->get_base_template()->get_template_refd_last();
6135 // it is sure that t_base is a TEMPLATE_LIST
6136 nof_base_comps = t_base->get_nof_comps();
6137 } else {
6138 t_base = 0;
6139 nof_base_comps = 0;
6140 }
6141 size_t nof_comps = t->get_nof_comps();
6142 for(size_t i = 0; i < nof_comps; i++) {
6143 Template *t_comp = t->get_temp_byIndex(i);
6144 Error_Context cntxt(t_comp, "In component %lu", (unsigned long)(i+1));
6145 t_comp->set_my_governor(u.seof.ofType);
6146 if (t_base && i < nof_base_comps)
6147 t_comp->set_base_template(t_base->get_temp_byIndex(i));
6148 u.seof.ofType->chk_this_template_ref(t_comp);
6149 switch (t_comp->get_templatetype()) {
6150 case Ttcn::Template::PERMUTATION_MATCH:
6151 // the elements of permutation has to be checked by u.seof.ofType
6152 // the templates within the permutation always have to be complete
6153 self_ref |= chk_this_template_generic(t_comp, INCOMPLETE_NOT_ALLOWED,
6154 OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK,
6155 implicit_omit, lhs);
6156 break;
6157 case Ttcn::Template::TEMPLATE_NOTUSED:
6158 if (c == Ttcn::Template::C_MUST_COMPLETE) {
6159 t_comp->error("Not used symbol `-' is not allowed in this context");
6160 } else if (c == Ttcn::Template::C_PARTIAL && i >= nof_base_comps) {
6161 t_comp->error("Not used symbol `-' cannot be used here because "
6162 "there is no corresponding element in the base template");
6163 }
6164 break;
6165 default:
6166 bool embedded_modified = (c == Ttcn::Template::C_MAY_INCOMPLETE) ||
6167 (c == Ttcn::Template::C_PARTIAL && i < nof_base_comps);
6168 self_ref |= u.seof.ofType->chk_this_template_generic(t_comp,
6169 (embedded_modified ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED),
6170 OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs);
6171 break;
6172 }
6173 }
6174 break; }
6175 case Ttcn::Template::INDEXED_TEMPLATE_LIST: {
6176 map<Int, Int> index_map;
6177 for (size_t i = 0; i < t->get_nof_comps(); i++) {
6178 Ttcn::IndexedTemplate *it = t->get_indexedtemp_byIndex(i);
6179 Value *index_value = (it->get_index()).get_val();
6180 // The index value must be Type::EXPECTED_DYNAMIC_VALUE integer, but
6181 // it's not required to be known at compile time.
6182 index_value->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE);
6183 Template *it_comp = it->get_template();
6184 Error_Context cntxt(it_comp, "In component %lu",
6185 (unsigned long)(i + 1));
6186 if (index_value->get_value_refd_last()->get_valuetype() == Value::V_INT) {
6187 const int_val_t *index_int = index_value->get_value_refd_last()
6188 ->get_val_Int();
6189 if (*index_int > INT_MAX) {
6190 index_value->error("An integer value less than `%d' was expected "
6191 "for indexing type `%s' instead of `%s'", INT_MAX,
6192 get_typename().c_str(), (index_int->t_str()).c_str());
6193 index_value->set_valuetype(Value::V_ERROR);
6194 } else {
6195 Int index = index_int->get_val();
6196 if (index < 0) {
6197 index_value->error("A non-negative integer value was expected "
6198 "for indexing type `%s' instead of `%s'",
6199 get_typename().c_str(), Int2string(index).c_str());
6200 index_value->set_valuetype(Value::V_ERROR);
6201 } else if (index_map.has_key(index)) {
6202 index_value->error("Duplicate index value `%s' for components "
6203 "`%s' and `%s'", Int2string(index).c_str(),
6204 Int2string((Int)i + 1).c_str(),
6205 Int2string(*index_map[index]).c_str());
6206 index_value->set_valuetype(Value::V_ERROR);
6207 } else {
6208 index_map.add(index, new Int((Int)i + 1));
6209 }
6210 }
6211 }
6212 it_comp->set_my_governor(u.seof.ofType);
6213 u.seof.ofType->chk_this_template_ref(it_comp);
6214 self_ref |= u.seof.ofType->chk_this_template_generic(it_comp,
6215 INCOMPLETE_ALLOWED, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED,
6216 SUB_CHK, implicit_omit, lhs);
6217 }
6218 for (size_t i = 0; i < index_map.size(); i++)
6219 delete index_map.get_nth_elem(i);
6220 index_map.clear();
6221 break; }
6222 default:
6223 t->error("%s cannot be used for `record of' type `%s'",
6224 t->get_templatetype_str(), get_typename().c_str());
6225 break;
6226 }
6227 return self_ref;
6228}
6229
6230bool Type::chk_this_template_SetOf(Template *t, namedbool is_modified,
6231 namedbool implicit_omit, Common::Assignment *lhs)
6232{
6233 bool self_ref = false;
6234 Ttcn::Template::templatetype_t temptype = t->get_templatetype();
6235 switch (temptype) {
6236 case Ttcn::Template::OMIT_VALUE:
6237 if(t->get_length_restriction())
6238 t->warning("Redundant usage of length restriction with `omit'");
6239 break;
6240 case Ttcn::Template::SUPERSET_MATCH:
6241 case Ttcn::Template::SUBSET_MATCH: {
6242 const char *settype = temptype == Ttcn::Template::SUPERSET_MATCH ?
6243 "superset" : "subset";
6244 size_t nof_comps = t->get_nof_comps();
6245 for (size_t i = 0; i < nof_comps; i++) {
6246 Template *t_comp = t->get_temp_byIndex(i);
6247 Error_Context cntxt(t_comp, "In element %lu of %s",
6248 (unsigned long) (i + 1), settype);
6249 t_comp->set_my_governor(u.seof.ofType);
6250 u.seof.ofType->chk_this_template_ref(t_comp);
6251 // the elements of sets must be always complete
6252 self_ref |= u.seof.ofType->chk_this_template_generic(t_comp,
6253 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED,
6254 SUB_CHK, implicit_omit, lhs);
6255 if (t_comp->get_template_refd_last()->get_templatetype() ==
6256 Ttcn::Template::ANY_OR_OMIT) {
6257 if (temptype == Ttcn::Template::SUPERSET_MATCH)
6258 t_comp->warning("`*' in superset has no effect during matching");
6259 else t_comp->warning("`*' in subset. This template will match "
6260 "everything");
6261 }
6262 }
6263 break;}
6264 case Ttcn::Template::TEMPLATE_LIST: {
6265 Ttcn::Template::completeness_t c =
6266 t->get_completeness_condition_seof(is_modified);
6267 Template *t_base;
6268 size_t nof_base_comps;
6269 if (c == Ttcn::Template::C_PARTIAL) {
6270 t_base = t->get_base_template()->get_template_refd_last();
6271 // it is sure that t_base is a TEMPLATE_LIST
6272 nof_base_comps = t_base->get_nof_comps();
6273 } else {
6274 t_base = 0;
6275 nof_base_comps = 0;
6276 }
6277 size_t nof_comps = t->get_nof_comps();
6278 for(size_t i = 0; i < nof_comps; i++) {
6279 Template *t_comp = t->get_temp_byIndex(i);
6280 Error_Context cntxt(t_comp, "In component %lu", (unsigned long)(i+1));
6281 t_comp->set_my_governor(u.seof.ofType);
6282 if (t_base && i < nof_base_comps)
6283 t_comp->set_base_template(t_base->get_temp_byIndex(i));
6284 u.seof.ofType->chk_this_template_ref(t_comp);
6285 switch (t_comp->get_templatetype()) {
6286 case Ttcn::Template::PERMUTATION_MATCH:
6287 t_comp->error("%s cannot be used for `set of' type `%s'",
6288 t_comp->get_templatetype_str(), get_typename().c_str());
6289 break;
6290 case Ttcn::Template::TEMPLATE_NOTUSED:
6291 if (c == Ttcn::Template::C_MUST_COMPLETE) {
6292 t_comp->error("Not used symbol `-' is not allowed in this context");
6293 } else if (c == Ttcn::Template::C_PARTIAL && i >= nof_base_comps) {
6294 t_comp->error("Not used symbol `-' cannot be used here because "
6295 "there is no corresponding element in the base template");
6296 }
6297 break;
6298 default:
6299 bool embedded_modified = (c == Ttcn::Template::C_MAY_INCOMPLETE) ||
6300 (c == Ttcn::Template::C_PARTIAL && i < nof_base_comps);
6301 self_ref |= u.seof.ofType->chk_this_template_generic(t_comp,
6302 (embedded_modified ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED),
6303 OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs);
6304 break;
6305 }
6306 }
6307 break; }
6308 case Ttcn::Template::INDEXED_TEMPLATE_LIST: {
6309 map<Int, Int> index_map;
6310 for (size_t i = 0; i < t->get_nof_comps(); i++) {
6311 Ttcn::IndexedTemplate *it = t->get_indexedtemp_byIndex(i);
6312 Value *index_value = (it->get_index()).get_val();
6313 index_value->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE);
6314 Template *it_comp = it->get_template();
6315 Error_Context cntxt(it_comp, "In component %lu",
6316 (unsigned long)(i + 1));
6317 if (index_value->get_value_refd_last()->get_valuetype() == Value::V_INT) {
6318 const int_val_t *index_int = index_value->get_value_refd_last()
6319 ->get_val_Int();
6320 if (*index_int > INT_MAX) {
6321 index_value->error("An integer value less than `%d' was expected "
6322 "for indexing type `%s' instead of `%s'", INT_MAX,
6323 get_typename().c_str(), (index_int->t_str()).c_str());
6324 index_value->set_valuetype(Value::V_ERROR);
6325 } else {
6326 Int index = index_int->get_val();
6327 if (index < 0) {
6328 index_value->error("A non-negative integer value was expected "
6329 "for indexing type `%s' instead of `%s'",
6330 get_typename().c_str(), Int2string(index).c_str());
6331 index_value->set_valuetype(Value::V_ERROR);
6332 } else if (index_map.has_key(index)) {
6333 index_value->error("Duplicate index value `%s' for components "
6334 "`%s' and `%s'", Int2string(index).c_str(),
6335 Int2string((Int)i + 1).c_str(),
6336 Int2string(*index_map[index]).c_str());
6337 index_value->set_valuetype(Value::V_ERROR);
6338 } else {
6339 index_map.add(index, new Int((Int)i + 1));
6340 }
6341 }
6342 }
6343 it_comp->set_my_governor(u.seof.ofType);
6344 u.seof.ofType->chk_this_template_ref(it_comp);
6345 self_ref |= u.seof.ofType->chk_this_template_generic(it_comp,
6346 INCOMPLETE_ALLOWED, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED,
6347 SUB_CHK, implicit_omit, lhs);
6348 }
6349 for (size_t i = 0; i < index_map.size(); i++)
6350 delete index_map.get_nth_elem(i);
6351 index_map.clear();
6352 break; }
6353 default:
6354 t->error("%s cannot be used for `set of' type `%s'",
6355 t->get_templatetype_str(), get_typename().c_str());
6356 break;
6357 }
6358 return self_ref;
6359}
6360
6361bool Type::chk_this_template_array(Template *t, namedbool is_modified,
6362 namedbool implicit_omit, Common::Assignment *lhs)
6363{
6364 bool self_ref = false;
6365 switch (t->get_templatetype()) {
6366 case Ttcn::Template::OMIT_VALUE:
6367 if (t->get_length_restriction())
6368 t->warning("Redundant usage of length restriction with `omit'");
6369 break;
6370 case Ttcn::Template::PERMUTATION_MATCH: {
6371 size_t nof_comps = t->get_nof_comps();
6372 for (size_t i = 0; i < nof_comps; i++) {
6373 Template *t_comp = t->get_temp_byIndex(i);
6374 Error_Context cntxt(t_comp, "In element %lu of permutation",
6375 (unsigned long) (i + 1));
6376 t_comp->set_my_governor(u.array.element_type);
6377 u.array.element_type->chk_this_template_ref(t_comp);
6378 // the elements of permutation must be always complete
6379 self_ref |= u.array.element_type->chk_this_template_generic(t_comp,
6380 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK,
6381 NOT_IMPLICIT_OMIT, lhs);
6382 }
6383 break; }
6384 case Ttcn::Template::TEMPLATE_LIST: {
6385 Template *t_base = t->get_base_template();
6386 size_t nof_base_comps = 0;
6387 if (t_base) {
6388 t_base = t_base->get_template_refd_last();
6389 if (t_base->get_templatetype() == Ttcn::Template::TEMPLATE_LIST)
6390 nof_base_comps = t_base->get_nof_comps();
6391 else t_base = 0; // error recovery
6392 }
6393 if (!u.array.dimension->get_has_error()) {
6394 size_t array_size = u.array.dimension->get_size();
6395 size_t template_size = t->get_nof_listitems();
6396 if (array_size != template_size) {
6397 if (t->is_flattened()){
6398 t->error("Too %s elements in the array template: %lu was expected "
6399 "instead of %lu",
6400 array_size > template_size ? "few" : "many",
6401 (unsigned long)array_size, (unsigned long)template_size);
6402 }
6403 else {
6404 t->warning("The size of template cannot be resolved "
6405 "so it could not be compared to the array size");
6406 }
6407 }
6408 }
6409 size_t nof_comps = t->get_nof_comps();
6410 for (size_t i = 0; i < nof_comps; i++) {
6411 Template *t_comp = t->get_temp_byIndex(i);
6412 Error_Context cntxt(t_comp, "In array element %lu",
6413 (unsigned long)(i + 1));
6414 t_comp->set_my_governor(u.array.element_type);
6415 if (t_base && i < nof_base_comps)
6416 t_comp->set_base_template(t_base->get_temp_byIndex(i));
6417 u.array.element_type->chk_this_template_ref(t_comp);
6418 switch (t_comp->get_templatetype()) {
6419 case Ttcn::Template::PERMUTATION_MATCH:
6420 // the elements of permutation has to be checked by u.seof.ofType
6421 // the templates within the permutation always have to be complete
6422 self_ref |= chk_this_template_generic(t_comp, INCOMPLETE_NOT_ALLOWED,
6423 OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK,
6424 implicit_omit, lhs);
6425 break;
6426 case Ttcn::Template::TEMPLATE_NOTUSED:
6427 if (!is_modified)
6428 t_comp->error("Not used symbol `-' is not allowed in this "
6429 "context");
6430 break;
6431 default:
6432 self_ref |= u.array.element_type->chk_this_template_generic(t_comp,
6433 is_modified, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs);
6434 break;
6435 }
6436 }
6437 break; }
6438 case Ttcn::Template::INDEXED_TEMPLATE_LIST: {
6439 map<Int, Int> index_map;
6440 for (size_t i = 0; i < t->get_nof_comps(); i++) {
6441 Ttcn::IndexedTemplate *it = t->get_indexedtemp_byIndex(i);
6442 Value *index_value = (it->get_index()).get_val();
6443 u.array.dimension->chk_index(index_value,
6444 Type::EXPECTED_DYNAMIC_VALUE);
6445 Template *it_comp = it->get_template();
6446 Error_Context cntxt(it_comp, "In component %lu",
6447 (unsigned long)(i + 1));
6448 if (index_value->get_value_refd_last()
6449 ->get_valuetype() == Value::V_INT) {
6450 const int_val_t *index_int = index_value->get_value_refd_last()
6451 ->get_val_Int();
6452 if (*index_int > INT_MAX) {
6453 index_value->error("An integer value less than `%d' was expected "
6454 "for indexing type `%s' instead of `%s'",
6455 INT_MAX, get_typename().c_str(),
6456 (index_int->t_str()).c_str());
6457 index_value->set_valuetype(Value::V_ERROR);
6458 } else {
6459 Int index = index_int->get_val();
6460 if (index_map.has_key(index)) {
6461 index_value->error("Duplicate index value `%s' for components "
6462 "`%s' and `%s'", Int2string(index).c_str(),
6463 Int2string((Int)i + 1).c_str(),
6464 Int2string(*index_map[index]).c_str());
6465 index_value->set_valuetype(Value::V_ERROR);
6466 } else {
6467 index_map.add(index, new Int((Int)i + 1));
6468 }
6469 }
6470 }
6471 it_comp->set_my_governor(u.array.element_type);
6472 u.array.element_type->chk_this_template_ref(it_comp);
6473 self_ref |= u.array.element_type->chk_this_template_generic(it_comp,
6474 is_modified, OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs);
6475 }
6476 for (size_t i = 0; i < index_map.size(); i++)
6477 delete index_map.get_nth_elem(i);
6478 index_map.clear();
6479 break; }
6480 default:
6481 t->error("%s cannot be used for array type `%s'",
6482 t->get_templatetype_str(), get_typename().c_str());
6483 break;
6484 }
6485 return self_ref;
6486}
6487
6488void Type::chk_this_template_Fat(Template *t)
6489{
6490 t->error("%s cannot be used for type `%s'",t->get_templatetype_str(),
6491 get_typename().c_str());
6492 if(t->get_length_restriction()) t->error("Length restriction is not "
6493 "allowed for type `%s'", get_typename().c_str());
6494}
6495
6496void Type::chk_this_template_Signature(Template *t, namedbool is_modified)
6497{
6498 bool self_ref = false;
6499 size_t n_type_params = get_nof_comps();
6500 switch (t->get_templatetype()) {
6501 case Ttcn::Template::TEMPLATE_LIST:
6502 // conversion: value list -> assignment notation
6503 t->set_templatetype(Ttcn::Template::NAMED_TEMPLATE_LIST);
6504 // no break
6505 case Ttcn::Template::NAMED_TEMPLATE_LIST: {
6506 map<string, Ttcn::NamedTemplate> comp_map;
6507 // it is set to false if we have lost the ordering
6508 bool in_synch = true;
6509 size_t n_template_comps = t->get_nof_comps();
6510 size_t t_i = 0;
6511 for (size_t v_i = 0; v_i < n_template_comps; v_i++) {
6512 Ttcn::NamedTemplate *nt = t->get_namedtemp_byIndex(v_i);
6513 const Identifier& temp_id = nt->get_name();
6514 const string& temp_name = temp_id.get_name();
6515 const char *temp_dispname_str = temp_id.get_dispname().c_str();
6516 if (!has_comp_withName(temp_id)) {
6517 nt->error("Reference to non-existent parameter `%s' in template "
6518 "for signature `%s'", temp_dispname_str, get_typename().c_str());
6519 in_synch = false;
6520 continue;
6521 } else if (comp_map.has_key(temp_name)) {
6522 nt->error("Duplicate parameter `%s' in template for signature `%s'",
6523 temp_dispname_str, get_typename().c_str());
6524 comp_map[temp_name]->note("Parameter `%s' is already given here",
6525 temp_dispname_str);
6526 in_synch = false;
6527 } else comp_map.add(temp_name, nt);
6528 const SignatureParam *par =
6529 u.signature.parameters->get_param_byName(temp_id);
6530 if (in_synch) {
6531 SignatureParam *par2 = 0;
6532 for ( ; t_i < n_type_params; t_i++) {
6533 par2 = u.signature.parameters->get_param_byIndex(t_i);
6534 if (par2 == par) break;
6535 }
6536 if (par2 != par) {
6537 nt->error("Unexpected parameter `%s' in signature template",
6538 temp_dispname_str);
6539 in_synch = false;
6540 } else t_i++;
6541 }
6542 Type *type = par->get_type();
6543 Template *comp_t = nt->get_template();
6544 Error_Context cntxt(comp_t, "In template for signature parameter `%s'",
6545 temp_dispname_str);
6546 comp_t->set_my_governor(type);
6547 type->chk_this_template_ref(comp_t);
6548 self_ref |= type->chk_this_template_generic(comp_t, is_modified, OMIT_NOT_ALLOWED, ANY_OR_OMIT_NOT_ALLOWED,
6549 SUB_CHK, NOT_IMPLICIT_OMIT, NULL);
6550 }
6551 if(!is_modified) {
6552 SignatureParam *first_undef_in = NULL,
6553 *first_undef_out = NULL;
6554 for (size_t i = 0; i < n_type_params; i++) {
6555 SignatureParam *par = u.signature.parameters->get_param_byIndex(i);
6556 const Identifier& id = par->get_id();
6557 if (!comp_map.has_key(id.get_name()) ||
6558 comp_map[id.get_name()]->get_template()->get_templatetype() ==
6559 Template::TEMPLATE_NOTUSED) {
6560 switch(par->get_direction()) {
6561 case SignatureParam::PARAM_IN:
6562 if(!first_undef_in) first_undef_in = par;
6563 break;
6564 case SignatureParam::PARAM_OUT:
6565 if(!first_undef_out) first_undef_out = par;
6566 break;
6567 default: //inout
6568 t->error("Signature template is incomplete, because the inout "
6569 "parameter `%s' is missing", id.get_dispname().c_str());
6570 }
6571 }
6572 }
6573 if(first_undef_in!=NULL && first_undef_out!=NULL)
6574 t->error("Signature template is incomplete, because the in parameter "
6575 "`%s' and the out parameter `%s' is missing",
6576 first_undef_in->get_id().get_dispname().c_str(),
6577 first_undef_out->get_id().get_dispname().c_str());
6578 }
6579 comp_map.clear();
6580 break;}
6581 default:
6582 t->error("%s cannot be used for signature `%s'",
6583 t->get_templatetype_str(), get_typename().c_str());
6584 break;
6585 }
6586 if (t->get_length_restriction())
6587 t->error("Length restriction is not allowed in a template for "
6588 "signature `%s'", get_typename().c_str());
6589}
6590
6591} // namespace Common
This page took 0.265585 seconds and 5 git commands to generate.