Commit | Line | Data |
---|---|---|
970ed795 EL |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (c) 2000-2014 Ericsson Telecom AB | |
3 | // All rights reserved. This program and the accompanying materials | |
4 | // are made available under the terms of the Eclipse Public License v1.0 | |
5 | // which accompanies this distribution, and is available at | |
6 | // http://www.eclipse.org/legal/epl-v10.html | |
7 | /////////////////////////////////////////////////////////////////////////////// | |
8 | #include "../common/dbgnew.hh" | |
9 | #include "Type.hh" | |
10 | #include <ctype.h> | |
11 | #include "Typestuff.hh" // FIXME CTs | |
12 | #include "CompType.hh" | |
13 | #include "TypeCompat.hh" | |
14 | #include "CompField.hh" | |
15 | #include "SigParam.hh" | |
16 | #include "EnumItem.hh" | |
17 | ||
18 | #include "Valuestuff.hh" | |
19 | #include "ttcn3/ArrayDimensions.hh" | |
20 | #include "asn1/Tag.hh" | |
21 | #include "asn1/Block.hh" | |
22 | #include "asn1/Ref.hh" | |
23 | #include "Constraint.hh" | |
24 | #include "main.hh" | |
25 | #include "../common/pattern.hh" | |
26 | #include "ttcn3/Attributes.hh" | |
27 | #include "XerAttributes.hh" | |
28 | #include "ttcn3/Ttcnstuff.hh" | |
29 | #include "ttcn3/TtcnTemplate.hh" | |
30 | #include "ttcn3/Templatestuff.hh" | |
31 | ||
32 | #include "../common/static_check.h" | |
33 | #include "PredefFunc.hh" | |
34 | ||
35 | // implemented in coding_attrib_p.y | |
36 | extern Ttcn::ExtensionAttributes * parse_extattributes( | |
37 | Ttcn::WithAttribPath *w_attrib_path); | |
38 | ||
39 | namespace Common { | |
40 | ||
41 | using Ttcn::MultiWithAttrib; | |
42 | using Ttcn::SingleWithAttrib; | |
43 | using Ttcn::WithAttribPath; | |
44 | ||
45 | const char* Type::type_as_string[] = { | |
46 | "undefined", // T_UNDEF | |
47 | "erroneous", // T_ERROR | |
48 | "null(ASN)", // T_NULL | |
49 | "boolean", // T_BOOL | |
50 | "integer", // T_INT | |
51 | "integer(ASN.1)", // T_INT_A | |
52 | "real/float", // T_REAL | |
53 | "enumerated(ASN.1)", // T_ENUM_A | |
54 | "enumerated(TTCN-3)", // T_ENUM_T | |
55 | "bitstring", // T_BSTR | |
56 | "bitstring(ASN)", // T_BSTR_A | |
57 | "hexstring(TTCN-3)", // T_HSTR | |
58 | "octetstring", // T_OSTR | |
59 | "charstring (TTCN-3)", // T_CSTR | |
60 | "universal charstring(TTCN-3)", // T_USTR | |
61 | "UTF8String(ASN.1)", // T_UTF8STRING | |
62 | "NumericString(ASN.1)", // T_NUMERICSTRING | |
63 | "PrintableString(ASN.1)", // T_PRINTABLESTRING | |
64 | "TeletexString(ASN.1)", //T_TELETEXSTRING | |
65 | "VideotexString(ASN.1)", // T_VIDEOTEXSTRING | |
66 | "IA5String(ASN.1)", // T_IA5STRING | |
67 | "GraphicString(ASN.1)", // T_GRAPHICSTRING, | |
68 | "VisibleString(ASN.1)", // T_VISIBLESTRING | |
69 | "GeneralString (ASN.1)", // T_GENERALSTRING | |
70 | "UniversalString (ASN.1)", // T_UNIVERSALSTRING | |
71 | "BMPString (ASN.1)", // T_BMPSTRING | |
72 | "UnrestrictedCharacterString(ASN.1)", // T_UNRESTRICTEDSTRING | |
73 | "UTCTime(ASN.1)", // T_UTCTIME | |
74 | "GeneralizedTime(ASN.1)", // T_GENERALIZEDTIME | |
75 | "Object descriptor, a kind of string (ASN.1)", // T_OBJECTDESCRIPTOR | |
76 | "object identifier", // T_OID | |
77 | "relative OID(ASN.1)", // T_ROID | |
78 | "choice(ASN-1)", // T_CHOICE_A | |
79 | "union(TTCN-3)", // T_CHOICE_T | |
80 | "sequence (record) of", // T_SEQOF | |
81 | "set of", // T_SETOF | |
82 | "sequence(ASN-1)", // T_SEQ_A | |
83 | "record(TTCN-3)", // T_SEQ_T | |
84 | "set(ASN.1)", // T_SET_A | |
85 | "set(TTCN-3)", // T_SET_T | |
86 | "ObjectClassFieldType(ASN.1)", // T_OCFT | |
87 | "open type(ASN.1)", // T_OPENTYPE | |
88 | "ANY(deprecated ASN.1)", // T_ANY | |
89 | "external(ASN.1)", // T_EXTERNAL | |
90 | "embedded PDV(ASN.1)", // T_EMBEDDED_PDV | |
91 | "referenced", // T_REFD | |
92 | "special referenced(by pointer, not by name)", // T_REFDSPEC | |
93 | "selection type(ASN.1)", // T_SELTYPE | |
94 | "verdict type(TTCN-3)", // T_VERDICT | |
95 | "port type(TTCN-3)", // T_PORT | |
96 | "component type(TTCN-3)", // T_COMPONENT | |
97 | "address type(TTCN-3)", // T_ADDRESS | |
98 | "default type (TTCN-3)", // T_DEFAULT | |
99 | "array(TTCN-3)", // T_ARRAY | |
100 | "signature(TTCN-3)", // T_SIGNATURE | |
101 | "function reference(TTCN-3)", // T_FUNCTION | |
102 | "altstep reference(TTCN-3)", // T_ALTSTEP | |
103 | "testcase reference(TTCN-3)", // T_TESTCASE | |
104 | "anytype(TTCN-3)", // T_ANYTYPE | |
105 | }; | |
106 | ||
107 | // ================================= | |
108 | // ===== Type | |
109 | // ================================= | |
110 | const char* Type::asString() const { | |
111 | if (this->get_typetype() < Type::T_LAST && Type::T_UNDEF < this->get_typetype()) { | |
112 | return type_as_string[this->get_typetype()]; | |
113 | } | |
114 | else { | |
115 | return type_as_string[Type::T_UNDEF]; | |
116 | } | |
117 | } | |
118 | ||
119 | const char* Type::asString(Type::typetype_t type) { | |
120 | if (type < Type::T_LAST && Type::T_UNDEF < type) { | |
121 | return type_as_string[type]; | |
122 | } | |
123 | else { | |
124 | return type_as_string[Type::T_UNDEF]; | |
125 | } | |
126 | } | |
127 | ||
128 | // Used by dump() for user-readable messages, by Def_ExtFunction::generate_* | |
129 | // The text returned must match the case label without the "CT_" ! | |
130 | const char *Type::get_encoding_name(MessageEncodingType_t encoding_type) | |
131 | { | |
132 | ENSURE_EQUAL(Type::T_UNDEF, 0); | |
133 | ENSURE_EQUAL(Type::OT_UNKNOWN, 0); | |
134 | switch (encoding_type) { | |
135 | case CT_BER: | |
136 | return "BER"; | |
137 | case CT_PER: | |
138 | return "PER"; | |
139 | case CT_XER: | |
140 | return "XER"; | |
141 | case CT_RAW: | |
142 | return "RAW"; | |
143 | case CT_TEXT: | |
144 | return "TEXT"; | |
145 | case CT_JSON: | |
146 | return "JSON"; | |
147 | default: | |
148 | return "<unknown encoding>"; | |
149 | } | |
150 | } | |
151 | ||
152 | Type *Type::get_stream_type(MessageEncodingType_t encoding_type) | |
153 | { | |
154 | switch (encoding_type) { | |
155 | case CT_BER: | |
156 | case CT_PER: | |
157 | case CT_RAW: | |
158 | case CT_XER: // UTF-8 doesn't fit into charstring and universal is wasteful | |
159 | case CT_JSON: | |
160 | return get_pooltype(T_OSTR); | |
161 | case CT_TEXT: | |
162 | return get_pooltype(T_CSTR); | |
163 | default: | |
164 | FATAL_ERROR("Type::get_stream_type()"); | |
165 | return 0; | |
166 | } | |
167 | } | |
168 | ||
169 | map<Type::typetype_t, Type> *Type::pooltypes = 0; | |
170 | ||
171 | Type* Type::get_pooltype(typetype_t p_typetype) | |
172 | { | |
173 | p_typetype=get_typetype_ttcn3(p_typetype); | |
174 | switch(p_typetype) { | |
175 | case T_NULL: | |
176 | case T_BOOL: | |
177 | case T_INT: | |
178 | case T_REAL: | |
179 | case T_BSTR: | |
180 | case T_HSTR: | |
181 | case T_OSTR: | |
182 | case T_CSTR: | |
183 | case T_USTR: | |
184 | case T_OID: | |
185 | case T_ERROR: | |
186 | case T_VERDICT: | |
187 | case T_COMPONENT: | |
188 | case T_DEFAULT: | |
189 | break; // we have a pool type | |
190 | default: | |
191 | return 0; // no pool type for you! | |
192 | } // switch | |
193 | if (!pooltypes) pooltypes = new map<typetype_t, Type>; // lazy init | |
194 | else if (pooltypes->has_key(p_typetype)) return (*pooltypes)[p_typetype]; | |
195 | Type *t; | |
196 | if (p_typetype == T_COMPONENT) | |
197 | t = new Type(T_COMPONENT, new ComponentTypeBody()); | |
198 | else t = new Type(p_typetype); | |
199 | t->ownertype = OT_POOL; | |
200 | pooltypes->add(p_typetype, t); | |
201 | return t; | |
202 | } | |
203 | ||
204 | void Type::destroy_pooltypes() | |
205 | { | |
206 | if(pooltypes) { | |
207 | for(size_t i=0; i<pooltypes->size(); i++) | |
208 | delete pooltypes->get_nth_elem(i); | |
209 | pooltypes->clear(); | |
210 | delete pooltypes; | |
211 | pooltypes=0; | |
212 | } | |
213 | } | |
214 | ||
215 | Tag *Type::get_default_tag() | |
216 | { | |
217 | typetype_t t_typetype; | |
218 | switch (typetype) { | |
219 | case T_INT: | |
220 | t_typetype = T_INT_A; | |
221 | break; | |
222 | case T_BSTR: | |
223 | t_typetype = T_BSTR_A; | |
224 | break; | |
225 | case T_ENUM_T: | |
226 | t_typetype = T_ENUM_A; | |
227 | break; | |
228 | case T_SEQ_T: | |
229 | case T_SEQOF: | |
230 | t_typetype = T_SEQ_A; | |
231 | break; | |
232 | case T_SET_T: | |
233 | case T_SETOF: | |
234 | t_typetype = T_SET_A; | |
235 | break; | |
236 | case T_OPENTYPE: | |
237 | t_typetype = T_ANY; | |
238 | break; | |
239 | case T_REFD: | |
240 | case T_REFDSPEC: | |
241 | case T_SELTYPE: | |
242 | case T_OCFT: | |
243 | return get_type_refd()->get_tag(); | |
244 | default: | |
245 | t_typetype = typetype; | |
246 | break; | |
247 | } | |
248 | if (!default_tags) default_tags = new map<typetype_t, Tag>; | |
249 | else if (default_tags->has_key(t_typetype)) | |
250 | return (*default_tags)[t_typetype]; | |
251 | Tag *tag; | |
252 | switch (t_typetype) { | |
253 | case T_ANY: | |
254 | tag = new Tag(Tag::TAG_EXPLICIT, Tag::TAG_ALL, (Int)0); | |
255 | break; | |
256 | case T_ERROR: | |
257 | tag = new Tag(Tag::TAG_EXPLICIT, Tag::TAG_ERROR, (Int)0); | |
258 | break; | |
259 | default: { | |
260 | int tagnumber = get_default_tagnumber(t_typetype); | |
261 | if (tagnumber < 0) FATAL_ERROR ("Type::get_default_tag():type `%s' " | |
262 | "does not have default tag", get_typename().c_str()); | |
263 | tag = new Tag(Tag::TAG_EXPLICIT, Tag::TAG_UNIVERSAL, Int(tagnumber)); | |
264 | break; } | |
265 | } | |
266 | default_tags->add(t_typetype, tag); | |
267 | return tag; | |
268 | } | |
269 | ||
270 | int Type::get_default_tagnumber(typetype_t p_tt) | |
271 | { | |
272 | switch (p_tt) { | |
273 | // note: tag number 0 is reserved for internal use | |
274 | case T_BOOL: | |
275 | return 1; | |
276 | case T_INT_A: | |
277 | return 2; | |
278 | case T_BSTR_A: | |
279 | return 3; | |
280 | case T_OSTR: | |
281 | return 4; | |
282 | case T_NULL: | |
283 | return 5; | |
284 | case T_OID: | |
285 | return 6; | |
286 | case T_OBJECTDESCRIPTOR: | |
287 | return 7; | |
288 | case T_EXTERNAL: | |
289 | return 8; | |
290 | case T_REAL: | |
291 | return 9; | |
292 | case T_ENUM_A: | |
293 | return 10; | |
294 | case T_EMBEDDED_PDV: | |
295 | return 11; | |
296 | case T_UTF8STRING: | |
297 | return 12; | |
298 | case T_ROID: | |
299 | return 13; | |
300 | // note: tag numbers 14 and 15 are reserved for future use | |
301 | case T_SEQ_A: | |
302 | return 16; | |
303 | case T_SET_A: | |
304 | return 17; | |
305 | case T_NUMERICSTRING: | |
306 | return 18; | |
307 | case T_PRINTABLESTRING: | |
308 | return 19; | |
309 | case T_TELETEXSTRING: | |
310 | return 20; | |
311 | case T_VIDEOTEXSTRING: | |
312 | return 21; | |
313 | case T_IA5STRING: | |
314 | return 22; | |
315 | case T_UTCTIME: | |
316 | return 23; | |
317 | case T_GENERALIZEDTIME: | |
318 | return 24; | |
319 | case T_GRAPHICSTRING: | |
320 | return 25; | |
321 | case T_VISIBLESTRING: | |
322 | return 26; | |
323 | case T_GENERALSTRING: | |
324 | return 27; | |
325 | case T_UNIVERSALSTRING: | |
326 | return 28; | |
327 | case T_UNRESTRICTEDSTRING: | |
328 | return 29; | |
329 | case T_BMPSTRING: | |
330 | return 30; | |
331 | default: | |
332 | return -1; | |
333 | } | |
334 | } | |
335 | ||
336 | map<Type::typetype_t, Tag> *Type::default_tags = 0; | |
337 | ||
338 | void Type::destroy_default_tags() | |
339 | { | |
340 | if (default_tags) { | |
341 | size_t nof_tags = default_tags->size(); | |
342 | for (size_t i = 0; i < nof_tags; i++) | |
343 | delete default_tags->get_nth_elem(i); | |
344 | default_tags->clear(); | |
345 | delete default_tags; | |
346 | default_tags = 0; | |
347 | } | |
348 | } | |
349 | ||
350 | Type::Type(const Type& p) | |
351 | : Governor(p), typetype(p.typetype) | |
352 | { | |
353 | init(); | |
354 | if (p.w_attrib_path != NULL) FATAL_ERROR("Type::Type()"); | |
355 | tags=p.tags?p.tags->clone():0; | |
356 | if(p.constraints) { | |
357 | constraints=p.constraints->clone(); | |
358 | constraints->set_my_type(this); | |
359 | } | |
360 | else constraints=0; | |
361 | if(p.parsed_restr!=NULL) { | |
362 | parsed_restr=new vector<SubTypeParse>; | |
363 | for(size_t i=0;i<p.parsed_restr->size();i++) { | |
364 | SubTypeParse *stp = 0; | |
365 | switch((*p.parsed_restr)[i]->get_selection()) { | |
366 | case SubTypeParse::STP_SINGLE: | |
367 | stp=new SubTypeParse((*p.parsed_restr)[i]->Single()); | |
368 | break; | |
369 | case SubTypeParse::STP_RANGE: | |
370 | stp=new SubTypeParse((*p.parsed_restr)[i]->Min(), | |
371 | (*p.parsed_restr)[i]->MinExclusive(), | |
372 | (*p.parsed_restr)[i]->Max(), | |
373 | (*p.parsed_restr)[i]->MaxExclusive()); | |
374 | break; | |
375 | case SubTypeParse::STP_LENGTH: | |
376 | FATAL_ERROR("Type::Type(Type&): STP_LENGTH"); | |
377 | break; | |
378 | default: FATAL_ERROR("Type::Type()"); | |
379 | } | |
380 | parsed_restr->add(stp); | |
381 | } | |
382 | } | |
383 | else parsed_restr=0; | |
384 | switch(typetype) { | |
385 | case T_ERROR: | |
386 | case T_NULL: | |
387 | case T_BOOL: | |
388 | case T_INT: | |
389 | case T_REAL: | |
390 | case T_BSTR: | |
391 | case T_HSTR: | |
392 | case T_OSTR: | |
393 | case T_CSTR: | |
394 | case T_USTR: | |
395 | case T_UTF8STRING: | |
396 | case T_NUMERICSTRING: | |
397 | case T_PRINTABLESTRING: | |
398 | case T_TELETEXSTRING: | |
399 | case T_VIDEOTEXSTRING: | |
400 | case T_IA5STRING: | |
401 | case T_GRAPHICSTRING: | |
402 | case T_VISIBLESTRING: | |
403 | case T_GENERALSTRING: | |
404 | case T_UNIVERSALSTRING: | |
405 | case T_BMPSTRING: | |
406 | case T_UTCTIME: | |
407 | case T_GENERALIZEDTIME: | |
408 | case T_OBJECTDESCRIPTOR: | |
409 | case T_OID: | |
410 | case T_ROID: | |
411 | case T_ANY: | |
412 | case T_EXTERNAL: | |
413 | case T_EMBEDDED_PDV: | |
414 | case T_UNRESTRICTEDSTRING: | |
415 | case T_VERDICT: | |
416 | case T_DEFAULT: | |
417 | break; | |
418 | case T_INT_A: | |
419 | case T_BSTR_A: | |
420 | u.namednums.block=p.u.namednums.block?p.u.namednums.block->clone():0; | |
421 | u.namednums.nvs=p.u.namednums.nvs?p.u.namednums.nvs->clone():0; | |
422 | break; | |
423 | case T_ENUM_A: | |
424 | u.enums.block=p.u.enums.block?p.u.enums.block->clone():0; | |
425 | u.enums.eis1=p.u.enums.eis1?p.u.enums.eis1->clone():0; | |
426 | u.enums.ellipsis=p.u.enums.ellipsis; | |
427 | u.enums.excSpec=p.u.enums.excSpec?p.u.enums.excSpec->clone():0; | |
428 | u.enums.eis2=p.u.enums.eis2?p.u.enums.eis2->clone():0; | |
429 | // no break | |
430 | case T_ENUM_T: | |
431 | u.enums.eis=p.u.enums.eis->clone(); | |
432 | u.enums.eis_by_name=0; | |
433 | break; | |
434 | case T_CHOICE_T: | |
435 | case T_SEQ_T: | |
436 | case T_SET_T: | |
437 | case T_ANYTYPE: | |
438 | u.secho.cfm=p.u.secho.cfm->clone(); | |
439 | u.secho.field_by_name = 0; | |
440 | u.secho.component_internal = false; | |
441 | u.secho.has_single_charenc = false; | |
442 | break; | |
443 | case T_SEQ_A: | |
444 | case T_SET_A: | |
445 | u.secho.tr_compsof_ready=p.u.secho.tr_compsof_ready; | |
446 | // no break | |
447 | case T_CHOICE_A: | |
448 | u.secho.cfm = 0; | |
449 | u.secho.block=p.u.secho.block?p.u.secho.block->clone():0; | |
450 | u.secho.ctss=p.u.secho.ctss?p.u.secho.ctss->clone():0; | |
451 | u.secho.field_by_name = 0; | |
452 | u.secho.component_internal = false; | |
453 | u.secho.has_single_charenc = false; | |
454 | break; | |
455 | case T_SEQOF: | |
456 | case T_SETOF: | |
457 | u.seof.ofType=p.u.seof.ofType->clone(); | |
458 | u.seof.component_internal = false; | |
459 | break; | |
460 | case T_REFD: | |
461 | u.ref.ref=p.u.ref.ref->clone(); | |
462 | u.ref.type_refd=0; | |
463 | u.ref.component_internal = false; | |
464 | break; | |
465 | case T_OCFT: | |
466 | u.ref.oc_defn=p.u.ref.oc_defn; | |
467 | u.ref.oc_fieldname=p.u.ref.oc_fieldname; | |
468 | // no break | |
469 | case T_REFDSPEC: | |
470 | u.ref.type_refd=p.u.ref.type_refd; | |
471 | u.ref.component_internal = false; | |
472 | break; | |
473 | case T_SELTYPE: | |
474 | u.seltype.id=p.u.seltype.id->clone(); | |
475 | u.seltype.type=p.u.seltype.type->clone(); | |
476 | u.seltype.type_refd=0; | |
477 | break; | |
478 | case T_OPENTYPE: | |
479 | u.secho.cfm=new CompFieldMap(); | |
480 | u.secho.cfm->set_my_type(this); | |
481 | u.secho.oc_defn=p.u.secho.oc_defn; | |
482 | u.secho.oc_fieldname=p.u.secho.oc_fieldname; | |
483 | u.secho.my_tableconstraint=0; | |
484 | u.secho.field_by_name = 0; | |
485 | u.secho.component_internal = false; | |
486 | u.secho.has_single_charenc = false; | |
487 | break; | |
488 | case T_ARRAY: | |
489 | u.array.element_type=p.u.array.element_type->clone(); | |
490 | u.array.dimension = p.u.array.dimension->clone(); | |
491 | u.array.in_typedef = p.u.array.in_typedef; | |
492 | u.array.component_internal = false; | |
493 | break; | |
494 | case T_PORT: | |
495 | u.port = p.u.port->clone(); | |
496 | break; | |
497 | case T_COMPONENT: | |
498 | u.component = p.u.component->clone(); | |
499 | break; | |
500 | case T_ADDRESS: | |
501 | u.address = 0; | |
502 | break; | |
503 | case T_SIGNATURE: | |
504 | u.signature.parameters = p.u.signature.parameters ? | |
505 | p.u.signature.parameters->clone() : 0; | |
506 | u.signature.return_type = p.u.signature.return_type ? | |
507 | p.u.signature.return_type->clone() : 0; | |
508 | u.signature.no_block = p.u.signature.no_block; | |
509 | u.signature.exceptions = p.u.signature.exceptions ? | |
510 | p.u.signature.exceptions->clone() : 0; | |
511 | u.signature.component_internal = false; | |
512 | break; | |
513 | case T_FUNCTION: | |
514 | case T_ALTSTEP: | |
515 | u.fatref.fp_list = p.u.fatref.fp_list->clone(); | |
516 | u.fatref.runs_on.ref = p.u.fatref.runs_on.ref ? | |
517 | p.u.fatref.runs_on.ref->clone() : 0; | |
518 | u.fatref.runs_on.self = p.u.fatref.runs_on.self; | |
519 | u.fatref.runs_on.type = 0; | |
520 | u.fatref.return_type = p.u.fatref.return_type ? | |
521 | p.u.fatref.return_type->clone() : 0; | |
522 | u.fatref.is_startable = false; | |
523 | u.fatref.returns_template = p.u.fatref.returns_template; | |
524 | u.fatref.template_restriction = p.u.fatref.template_restriction; | |
525 | break; | |
526 | case T_TESTCASE: | |
527 | u.fatref.fp_list = p.u.fatref.fp_list->clone(); | |
528 | u.fatref.runs_on.ref = p.u.fatref.runs_on.ref ? | |
529 | p.u.fatref.runs_on.ref->clone() : 0; | |
530 | u.fatref.runs_on.self = false; | |
531 | u.fatref.runs_on.type = 0; | |
532 | u.fatref.system.ref = p.u.fatref.system.ref ? | |
533 | p.u.fatref.system.ref->clone() : 0; | |
534 | u.fatref.system.type = 0; | |
535 | u.fatref.is_startable = false; | |
536 | u.fatref.returns_template = false; | |
537 | u.fatref.template_restriction = TR_NONE; | |
538 | break; | |
539 | default: | |
540 | FATAL_ERROR("Type::Type()"); | |
541 | } // switch | |
542 | } | |
543 | ||
544 | void Type::init() | |
545 | { | |
546 | tags_checked = false; | |
547 | tbl_cons_checked = false; | |
548 | text_checked = false; | |
549 | json_checked = false; | |
550 | raw_parsed = false; | |
551 | raw_checked = false; | |
552 | xer_checked = false; | |
553 | raw_length_calculated = false; | |
554 | has_opentypes = false; | |
555 | opentype_outermost = false; | |
556 | code_generated = false; | |
557 | embed_values_possible = false; | |
558 | use_nil_possible = false; | |
559 | use_order_possible = false; | |
560 | raw_length = -1; | |
561 | parent_type = 0; | |
562 | tags = 0; | |
563 | constraints = 0; | |
564 | w_attrib_path = 0; | |
565 | encode_attrib_path = 0; | |
566 | rawattrib = 0; | |
567 | textattrib = 0; | |
568 | xerattrib = 0; | |
569 | berattrib = 0; | |
570 | jsonattrib = 0; | |
571 | sub_type = 0; | |
572 | parsed_restr = 0; | |
573 | ownertype = OT_UNKNOWN; | |
574 | owner = 0; | |
575 | chk_finished = false; | |
af710487 | 576 | pard_type_instance = false; |
970ed795 EL |
577 | } |
578 | ||
579 | void Type::clean_up() | |
580 | { | |
581 | switch (typetype) { | |
582 | case T_ERROR: | |
583 | case T_NULL: | |
584 | case T_BOOL: | |
585 | case T_INT: | |
586 | case T_REAL: | |
587 | case T_BSTR: | |
588 | case T_HSTR: | |
589 | case T_OSTR: | |
590 | case T_CSTR: | |
591 | case T_USTR: | |
592 | case T_UTF8STRING: | |
593 | case T_NUMERICSTRING: | |
594 | case T_PRINTABLESTRING: | |
595 | case T_TELETEXSTRING: | |
596 | case T_VIDEOTEXSTRING: | |
597 | case T_IA5STRING: | |
598 | case T_GRAPHICSTRING: | |
599 | case T_VISIBLESTRING: | |
600 | case T_GENERALSTRING: | |
601 | case T_UNIVERSALSTRING: | |
602 | case T_BMPSTRING: | |
603 | case T_UTCTIME: | |
604 | case T_GENERALIZEDTIME: | |
605 | case T_OBJECTDESCRIPTOR: | |
606 | case T_OID: | |
607 | case T_ROID: | |
608 | case T_ANY: | |
609 | case T_EXTERNAL: | |
610 | case T_EMBEDDED_PDV: | |
611 | case T_UNRESTRICTEDSTRING: | |
612 | case T_REFDSPEC: | |
613 | case T_OCFT: | |
614 | case T_VERDICT: | |
615 | case T_ADDRESS: | |
616 | case T_DEFAULT: | |
617 | break; | |
618 | case T_INT_A: | |
619 | case T_BSTR_A: | |
620 | delete u.namednums.block; | |
621 | delete u.namednums.nvs; | |
622 | break; | |
623 | case T_ENUM_A: | |
624 | delete u.enums.block; | |
625 | if(u.enums.eis1) { | |
626 | u.enums.eis1->release_eis(); | |
627 | delete u.enums.eis1; | |
628 | } | |
629 | if(u.enums.eis2) { | |
630 | u.enums.eis2->release_eis(); | |
631 | delete u.enums.eis2; | |
632 | } | |
633 | /* no break */ | |
634 | case T_ENUM_T: | |
635 | delete u.enums.eis; | |
636 | if (u.enums.eis_by_name) { | |
637 | for (size_t a = 0; a < u.enums.eis_by_name->size(); a++) { | |
638 | delete u.enums.eis_by_name->get_nth_elem(a); | |
639 | } | |
640 | u.enums.eis_by_name->clear(); | |
641 | delete u.enums.eis_by_name; | |
642 | } | |
643 | break; | |
644 | case T_CHOICE_A: | |
645 | case T_SEQ_A: | |
646 | case T_SET_A: | |
647 | delete u.secho.block; | |
648 | delete u.secho.ctss; | |
649 | /* no break */ | |
650 | case T_ANYTYPE: | |
651 | case T_CHOICE_T: | |
652 | case T_SEQ_T: | |
653 | case T_SET_T: | |
654 | case T_OPENTYPE: | |
655 | delete u.secho.cfm; | |
656 | if (u.secho.field_by_name) { | |
657 | for(size_t a = 0; a < u.secho.field_by_name->size(); a++) { | |
658 | delete u.secho.field_by_name->get_nth_elem(a); | |
659 | } | |
660 | u.secho.field_by_name->clear(); | |
661 | delete u.secho.field_by_name; | |
662 | } | |
663 | break; | |
664 | case T_SEQOF: | |
665 | case T_SETOF: | |
666 | delete u.seof.ofType; | |
667 | break; | |
668 | case T_REFD: | |
669 | delete u.ref.ref; | |
670 | break; | |
671 | case T_SELTYPE: | |
672 | delete u.seltype.id; | |
673 | delete u.seltype.type; | |
674 | break; | |
675 | case T_ARRAY: | |
676 | delete u.array.element_type; | |
677 | delete u.array.dimension; | |
678 | break; | |
679 | case T_PORT: | |
680 | delete u.port; | |
681 | break; | |
682 | case T_COMPONENT: | |
683 | delete u.component; | |
684 | break; | |
685 | case T_SIGNATURE: | |
686 | delete u.signature.parameters; | |
687 | delete u.signature.return_type; | |
688 | delete u.signature.exceptions; | |
689 | break; | |
690 | case T_FUNCTION: | |
691 | case T_ALTSTEP: | |
692 | delete u.fatref.fp_list; | |
693 | delete u.fatref.runs_on.ref; | |
694 | delete u.fatref.return_type; | |
695 | break; | |
696 | case T_TESTCASE: | |
697 | delete u.fatref.fp_list; | |
698 | delete u.fatref.runs_on.ref; | |
699 | delete u.fatref.system.ref; | |
700 | break; | |
701 | default: | |
702 | FATAL_ERROR("Type::clean_up()"); | |
703 | } // switch | |
704 | typetype = T_ERROR; | |
705 | delete tags; | |
706 | tags = 0; | |
707 | delete constraints; | |
708 | constraints = 0; | |
709 | delete rawattrib; | |
710 | rawattrib = 0; | |
711 | delete textattrib; | |
712 | textattrib = 0; | |
713 | delete xerattrib; | |
714 | xerattrib = 0; | |
715 | delete sub_type; | |
716 | sub_type = 0; | |
717 | delete berattrib; | |
718 | berattrib = 0; | |
719 | delete jsonattrib; | |
720 | jsonattrib = 0; | |
721 | if (parsed_restr) { | |
722 | for (size_t i = 0; i < parsed_restr->size(); i++) | |
723 | delete (*parsed_restr)[i]; | |
724 | parsed_restr->clear(); | |
725 | delete parsed_restr; | |
726 | parsed_restr = 0; | |
727 | } | |
728 | delete w_attrib_path; | |
729 | w_attrib_path = 0; | |
730 | delete encode_attrib_path; | |
731 | encode_attrib_path = 0; | |
732 | } | |
733 | ||
734 | Type::Type(typetype_t p_tt) | |
735 | : Governor(S_T), typetype(p_tt) | |
736 | { | |
737 | init(); | |
738 | switch(p_tt) { | |
739 | case T_ERROR: | |
740 | case T_NULL: | |
741 | case T_BOOL: | |
742 | case T_INT: | |
743 | case T_REAL: | |
744 | case T_BSTR: | |
745 | case T_HSTR: | |
746 | case T_OSTR: | |
747 | case T_CSTR: | |
748 | case T_USTR: | |
749 | case T_UTF8STRING: | |
750 | case T_NUMERICSTRING: | |
751 | case T_PRINTABLESTRING: | |
752 | case T_TELETEXSTRING: | |
753 | case T_VIDEOTEXSTRING: | |
754 | case T_IA5STRING: | |
755 | case T_GRAPHICSTRING: | |
756 | case T_VISIBLESTRING: | |
757 | case T_GENERALSTRING: | |
758 | case T_UNIVERSALSTRING: | |
759 | case T_BMPSTRING: | |
760 | case T_UTCTIME: | |
761 | case T_GENERALIZEDTIME: | |
762 | case T_OBJECTDESCRIPTOR: | |
763 | case T_OID: | |
764 | case T_ROID: | |
765 | case T_ANY: | |
766 | case T_EXTERNAL: | |
767 | case T_EMBEDDED_PDV: | |
768 | case T_UNRESTRICTEDSTRING: | |
769 | case T_VERDICT: | |
770 | case T_DEFAULT: | |
771 | break; | |
772 | case T_ANYTYPE: { | |
773 | u.secho.cfm = new CompFieldMap; | |
774 | u.secho.cfm->set_my_type(this); | |
775 | u.secho.block=0; | |
776 | u.secho.ctss=0; | |
777 | u.secho.field_by_name = 0; | |
778 | u.secho.component_internal = false; | |
779 | u.secho.has_single_charenc = false; | |
780 | break; } | |
781 | case T_INT_A: | |
782 | case T_BSTR_A: | |
783 | u.namednums.block=0; | |
784 | u.namednums.nvs=0; | |
785 | break; | |
786 | case T_ADDRESS: | |
787 | u.address = 0; | |
788 | break; | |
789 | default: | |
790 | FATAL_ERROR("Type::Type()"); | |
791 | } // switch | |
792 | } | |
793 | ||
794 | Type::Type(typetype_t p_tt, EnumItems *p_eis) | |
795 | : Governor(S_T), typetype(p_tt) | |
796 | { | |
797 | if (p_tt != T_ENUM_T || !p_eis) FATAL_ERROR("Type::Type()"); | |
798 | init(); | |
799 | u.enums.eis=p_eis; | |
800 | u.enums.eis_by_name=0; | |
801 | } | |
802 | ||
803 | Type::Type(typetype_t p_tt, Block *p_block) | |
804 | : Governor(S_T), typetype(p_tt) | |
805 | { | |
806 | if (!p_block) FATAL_ERROR("NULL parameter"); | |
807 | init(); | |
808 | switch(p_tt) { | |
809 | case T_INT_A: | |
810 | case T_BSTR_A: | |
811 | u.namednums.block=p_block; | |
812 | u.namednums.nvs=0; | |
813 | break; | |
814 | case T_ENUM_A: | |
815 | u.enums.eis=new EnumItems(); | |
816 | u.enums.block=p_block; | |
817 | u.enums.eis1=0; | |
818 | u.enums.ellipsis=false; | |
819 | u.enums.excSpec=0; | |
820 | u.enums.eis2=0; | |
821 | u.enums.eis_by_name=0; | |
822 | break; | |
823 | case T_SEQ_A: | |
824 | case T_SET_A: | |
825 | u.secho.tr_compsof_ready=false; | |
826 | // no break | |
827 | case T_CHOICE_A: | |
828 | u.secho.cfm = 0; | |
829 | u.secho.block=p_block; | |
830 | u.secho.ctss=0; | |
831 | u.secho.field_by_name = 0; | |
832 | u.secho.component_internal = false; | |
833 | u.secho.has_single_charenc = false; | |
834 | break; | |
835 | default: | |
836 | FATAL_ERROR("Type::Type()"); | |
837 | } // switch | |
838 | } | |
839 | ||
840 | Type::Type(typetype_t p_tt, | |
841 | EnumItems *p_eis1, bool p_ellipsis, EnumItems *p_eis2) | |
842 | : Governor(S_T), typetype(p_tt) | |
843 | { | |
844 | if (p_tt != T_ENUM_A || !p_eis1) FATAL_ERROR("Type::Type()"); | |
845 | init(); | |
846 | u.enums.eis=new EnumItems(); | |
847 | u.enums.block=0; | |
848 | u.enums.eis1=p_eis1; | |
849 | u.enums.ellipsis=p_ellipsis; | |
850 | u.enums.eis2=p_eis2; | |
851 | u.enums.eis_by_name=0; | |
852 | } | |
853 | ||
854 | Type::Type(typetype_t p_tt, CompFieldMap *p_cfm) | |
855 | : Governor(S_T), typetype(p_tt) | |
856 | { | |
857 | if (!p_cfm) FATAL_ERROR("NULL parameter"); | |
858 | init(); | |
859 | switch (p_tt) { | |
860 | case T_CHOICE_T: | |
861 | case T_SEQ_T: | |
862 | case T_SET_T: | |
863 | u.secho.cfm=p_cfm; | |
864 | u.secho.field_by_name = 0; | |
865 | u.secho.component_internal = false; | |
866 | u.secho.has_single_charenc = false; | |
867 | break; | |
868 | default: | |
869 | FATAL_ERROR("Type::Type()"); | |
870 | } // switch | |
871 | } | |
872 | ||
873 | Type::Type(typetype_t p_tt, Type *p_type) | |
874 | : Governor(S_T), typetype(p_tt) | |
875 | { | |
876 | if (!p_type) FATAL_ERROR("NULL parameter"); | |
877 | init(); | |
878 | switch (p_tt) { | |
879 | case T_SEQOF: | |
880 | case T_SETOF: | |
881 | u.seof.ofType=p_type; | |
882 | u.seof.ofType->set_ownertype(OT_RECORD_OF, this); | |
883 | u.seof.component_internal = false; | |
884 | break; | |
885 | case T_REFDSPEC: | |
886 | u.ref.type_refd=p_type; | |
887 | u.ref.type_refd->set_ownertype(OT_REF_SPEC, this); | |
888 | u.ref.component_internal = false; | |
889 | break; | |
890 | default: | |
891 | FATAL_ERROR("Type::Type()"); | |
892 | } // switch | |
893 | } | |
894 | ||
895 | Type::Type(typetype_t p_tt, Identifier *p_id, Type *p_type) | |
896 | : Governor(S_T), typetype(p_tt) | |
897 | { | |
898 | if (p_tt != T_SELTYPE || !p_id || !p_type) FATAL_ERROR("Type::Type()"); | |
899 | init(); | |
900 | u.seltype.id=p_id; | |
901 | u.seltype.type=p_type; | |
902 | u.seltype.type->set_ownertype(OT_SELTYPE, this); | |
903 | u.seltype.type_refd=0; | |
904 | } | |
905 | ||
906 | Type::Type(typetype_t p_tt, Type *p_type, Ttcn::ArrayDimension *p_dim, | |
907 | bool p_in_typedef) | |
908 | : Governor(S_T), typetype(p_tt) | |
909 | { | |
910 | if (p_tt != T_ARRAY || !p_type || !p_dim) FATAL_ERROR("Type::Type()"); | |
911 | init(); | |
912 | u.array.element_type = p_type; | |
913 | u.array.element_type->set_ownertype(OT_ARRAY, this); | |
914 | u.array.dimension = p_dim; | |
915 | u.array.in_typedef = p_in_typedef; | |
916 | u.array.component_internal = false; | |
917 | } | |
918 | ||
919 | Type::Type(typetype_t p_tt, Type *p_type, OC_defn *p_oc_defn, | |
920 | const Identifier *p_id) | |
921 | : Governor(S_T), typetype(p_tt) | |
922 | { | |
923 | if (p_tt != T_OCFT || !p_type ||!p_oc_defn || !p_id) | |
924 | FATAL_ERROR("Type::Type()"); | |
925 | init(); | |
926 | u.ref.type_refd=p_type; | |
927 | u.ref.type_refd->set_ownertype(OT_OCFT, this); | |
928 | u.ref.oc_defn=p_oc_defn; | |
929 | u.ref.oc_fieldname=p_id; | |
930 | u.ref.component_internal = false; | |
931 | } | |
932 | ||
933 | Type::Type(typetype_t p_tt, OC_defn *p_oc_defn, | |
934 | const Identifier *p_id) | |
935 | : Governor(S_T), typetype(p_tt) | |
936 | { | |
937 | if (p_tt != T_OPENTYPE || !p_oc_defn || !p_id) FATAL_ERROR("Type::Type()"); | |
938 | init(); | |
939 | has_opentypes=true; | |
940 | u.secho.cfm=new CompFieldMap(); | |
941 | u.secho.cfm->set_my_type(this); | |
942 | u.secho.oc_defn=p_oc_defn; | |
943 | u.secho.oc_fieldname=p_id; | |
944 | u.secho.my_tableconstraint=0; | |
945 | u.secho.field_by_name = 0; | |
946 | u.secho.component_internal = false; | |
947 | u.secho.has_single_charenc = false; | |
948 | } | |
949 | ||
950 | Type::Type(typetype_t p_tt, Reference *p_ref) | |
951 | : Governor(S_T), typetype(p_tt) | |
952 | { | |
953 | if (p_tt != T_REFD || !p_ref) FATAL_ERROR("Type::Type()"); | |
954 | init(); | |
955 | u.ref.ref=p_ref; | |
956 | u.ref.type_refd=0; | |
957 | u.ref.component_internal = false; | |
958 | } | |
959 | ||
960 | Type::Type(typetype_t p_tt, Ttcn::PortTypeBody *p_pb) | |
961 | : Governor(S_T), typetype(p_tt) | |
962 | { | |
963 | if (p_tt != T_PORT || !p_pb) FATAL_ERROR("Type::Type()"); | |
964 | init(); | |
965 | u.port = p_pb; | |
966 | p_pb->set_my_type(this); | |
967 | } | |
968 | ||
969 | Type::Type(typetype_t p_tt, ComponentTypeBody *p_cb) | |
970 | : Governor(S_T), typetype(p_tt) | |
971 | { | |
972 | if (p_tt != T_COMPONENT || !p_cb) FATAL_ERROR("Type::Type()"); | |
973 | init(); | |
974 | u.component = p_cb; | |
975 | p_cb->set_my_type(this); | |
976 | } | |
977 | ||
978 | Type::Type(typetype_t p_tt, SignatureParamList *p_params, Type *p_returntype, | |
979 | bool p_noblock, SignatureExceptions *p_exceptions) | |
980 | : Governor(S_T), typetype(p_tt) | |
981 | { | |
982 | if (p_tt != T_SIGNATURE || (p_returntype && p_noblock)) | |
983 | FATAL_ERROR("Type::Type()"); | |
984 | init(); | |
985 | u.signature.parameters = p_params; | |
986 | if ((u.signature.return_type = p_returntype)) { // check assignment for 0 | |
987 | u.signature.return_type->set_ownertype(OT_SIGNATURE, this); | |
988 | } | |
989 | u.signature.no_block = p_noblock; | |
990 | u.signature.exceptions = p_exceptions; | |
991 | u.signature.component_internal = false; | |
992 | } | |
993 | ||
994 | Type::Type(typetype_t p_tt,Ttcn::FormalParList *p_params, | |
995 | Ttcn::Reference* p_runs_on_ref, bool p_runs_on_self, | |
996 | Type *p_returntype, bool p_returns_template, | |
997 | template_restriction_t p_template_restriction) | |
998 | : Governor(S_T), typetype(p_tt) | |
999 | { | |
1000 | if (p_tt != T_FUNCTION || !p_params || (!p_returntype && p_returns_template) | |
1001 | || (p_runs_on_ref && p_runs_on_self)) FATAL_ERROR("Type::Type()"); | |
1002 | init(); | |
1003 | u.fatref.fp_list = p_params; | |
1004 | u.fatref.runs_on.ref = p_runs_on_ref; | |
1005 | u.fatref.runs_on.self = p_runs_on_self; | |
1006 | u.fatref.runs_on.type = 0; | |
1007 | if ((u.fatref.return_type = p_returntype)) { // check assignment for 0 | |
1008 | u.fatref.return_type->set_ownertype(OT_FUNCTION, this); | |
1009 | } | |
1010 | u.fatref.is_startable = false; | |
1011 | u.fatref.returns_template = p_returns_template; | |
1012 | u.fatref.template_restriction = p_template_restriction; | |
1013 | } | |
1014 | ||
1015 | Type::Type(typetype_t p_tt,Ttcn::FormalParList *p_params, | |
1016 | Ttcn::Reference* p_runs_on_ref, bool p_runs_on_self) | |
1017 | : Governor(S_T), typetype(p_tt) | |
1018 | { | |
1019 | if(p_tt != T_ALTSTEP || !p_params || (p_runs_on_ref && p_runs_on_self)) | |
1020 | FATAL_ERROR("Type::Type()"); | |
1021 | init(); | |
1022 | u.fatref.fp_list = p_params; | |
1023 | u.fatref.runs_on.ref = p_runs_on_ref; | |
1024 | u.fatref.runs_on.self = p_runs_on_self; | |
1025 | u.fatref.runs_on.type = 0; | |
1026 | u.fatref.return_type = 0; | |
1027 | u.fatref.is_startable = false; | |
1028 | u.fatref.returns_template = false; | |
1029 | u.fatref.template_restriction = TR_NONE; | |
1030 | } | |
1031 | ||
1032 | Type::Type(typetype_t p_tt,Ttcn::FormalParList *p_params, | |
1033 | Ttcn::Reference* p_runs_on_ref, Ttcn::Reference *p_system_ref) | |
1034 | : Governor(S_T), typetype(p_tt) | |
1035 | { | |
1036 | if(p_tt != T_TESTCASE || !p_params || !p_runs_on_ref) | |
1037 | FATAL_ERROR("Type::Type()"); | |
1038 | init(); | |
1039 | u.fatref.fp_list = p_params; | |
1040 | u.fatref.runs_on.ref = p_runs_on_ref; | |
1041 | u.fatref.runs_on.self = false; | |
1042 | u.fatref.runs_on.type = 0; | |
1043 | u.fatref.system.ref = p_system_ref; | |
1044 | u.fatref.system.type = 0; | |
1045 | u.fatref.is_startable = false; | |
1046 | u.fatref.returns_template = false; | |
1047 | u.fatref.template_restriction = TR_NONE; | |
1048 | } | |
1049 | ||
1050 | Type::~Type() | |
1051 | { | |
1052 | clean_up(); | |
1053 | } | |
1054 | ||
1055 | void Type::free_pools() | |
1056 | { | |
1057 | destroy_default_tags();// Additionally: R&S license warning | |
1058 | destroy_pooltypes();// Additionally: R&S license checkin/disconnect/shutdown | |
1059 | } | |
1060 | ||
1061 | Type *Type::clone() const | |
1062 | { | |
1063 | return new Type(*this); | |
1064 | } | |
1065 | ||
1066 | Type::typetype_t Type::get_typetype_ttcn3(typetype_t p_tt) | |
1067 | { | |
1068 | switch (p_tt) { | |
1069 | case T_INT_A: | |
1070 | return T_INT; | |
1071 | case T_ENUM_A: | |
1072 | return T_ENUM_T; | |
1073 | case T_BSTR_A: | |
1074 | return T_BSTR; | |
1075 | case T_UTF8STRING: | |
1076 | case T_BMPSTRING: | |
1077 | case T_UNIVERSALSTRING: | |
1078 | return T_USTR; | |
1079 | case T_TELETEXSTRING: | |
1080 | case T_VIDEOTEXSTRING: | |
1081 | case T_GRAPHICSTRING: | |
1082 | case T_OBJECTDESCRIPTOR: | |
1083 | case T_GENERALSTRING: | |
1084 | // iso2022str | |
1085 | case T_NUMERICSTRING: | |
1086 | case T_PRINTABLESTRING: | |
1087 | case T_IA5STRING: | |
1088 | case T_VISIBLESTRING: | |
1089 | case T_UTCTIME: | |
1090 | case T_GENERALIZEDTIME: | |
1091 | return T_CSTR; | |
1092 | case T_ROID: | |
1093 | return T_OID; | |
1094 | case T_ANY: | |
1095 | return T_OSTR; | |
1096 | case T_CHOICE_A: | |
1097 | case T_OPENTYPE: | |
1098 | return T_CHOICE_T; | |
1099 | case T_SEQ_A: | |
1100 | case T_EXTERNAL: | |
1101 | case T_EMBEDDED_PDV: | |
1102 | case T_UNRESTRICTEDSTRING: | |
1103 | return T_SEQ_T; | |
1104 | case T_SET_A: | |
1105 | return T_SET_T; | |
1106 | default: | |
1107 | return p_tt; | |
1108 | } // switch typetype | |
1109 | } | |
1110 | ||
1111 | bool Type::is_asn1() const | |
1112 | { | |
1113 | if (my_scope) return Setting::is_asn1(); | |
1114 | // the type might be a pool type, which is considered to be a TTCN-3 type | |
1115 | typetype_t t_typetype = get_typetype_ttcn3(typetype); | |
1116 | if (pooltypes && pooltypes->has_key(t_typetype) && | |
1117 | (*pooltypes)[t_typetype] == this) return false; | |
1118 | else FATAL_ERROR("Type::is_asn1()"); | |
1119 | } | |
1120 | ||
1121 | bool Type::is_ref() const | |
1122 | { | |
1123 | switch(typetype) { | |
1124 | case T_UNRESTRICTEDSTRING: | |
1125 | case T_OCFT: | |
1126 | case T_EXTERNAL: | |
1127 | case T_EMBEDDED_PDV: | |
1128 | case T_REFD: | |
1129 | case T_REFDSPEC: | |
1130 | case T_SELTYPE: | |
1131 | case T_ADDRESS: | |
1132 | return true; | |
1133 | default: | |
1134 | return false; | |
1135 | } // switch | |
1136 | } | |
1137 | ||
1138 | bool Type::is_secho() const | |
1139 | { | |
1140 | switch(typetype) { | |
1141 | case T_ANYTYPE: | |
1142 | case T_CHOICE_A: | |
1143 | case T_CHOICE_T: | |
1144 | case T_OPENTYPE: | |
1145 | case T_SEQ_A: | |
1146 | case T_SEQ_T: | |
1147 | case T_SET_A: | |
1148 | case T_SET_T: | |
1149 | return true; | |
1150 | default: | |
1151 | return false; | |
1152 | } // switch | |
1153 | } | |
1154 | ||
1155 | Type::truth Type::is_charenc() | |
1156 | { | |
1157 | switch(typetype) { | |
1158 | case T_CHOICE_A: | |
1159 | case T_CHOICE_T: | |
1160 | { | |
1161 | bool possible = true; | |
1162 | size_t ncomp = u.secho.cfm->get_nof_comps(); | |
1163 | for (size_t i=0; i<ncomp; ++i) { | |
1164 | CompField * cf = u.secho.cfm->get_comp_byIndex(i); | |
1165 | if (cf->get_type()->is_charenc() == No) { | |
1166 | possible = false; break; | |
1167 | } | |
1168 | } // next i | |
1169 | if (possible) { | |
1170 | return (xerattrib && (xerattrib->useUnion_ || xerattrib->useType_)) ? Yes : No; | |
1171 | } | |
1172 | } | |
1173 | // no break | |
1174 | case T_SEQ_A: | |
1175 | case T_SEQ_T: | |
1176 | case T_SET_A: | |
1177 | case T_SET_T: | |
1178 | case T_OPENTYPE: | |
1179 | // UNTAGGED cannot be used to make a type character-encodable! | |
1180 | // But USE-QNAME can! | |
1181 | return (xerattrib && xerattrib->useQName_) ? Yes : No; | |
1182 | ||
1183 | case T_SEQOF: // A record-of is character-encodable if it has the "list" | |
1184 | case T_SETOF: // attribute and its element is character-encodable. | |
1185 | return (xerattrib && xerattrib->list_ && (u.seof.ofType->is_charenc()==Yes)) | |
1186 | ? Yes : No; | |
1187 | ||
1188 | case T_ENUM_A: | |
1189 | case T_ENUM_T: | |
1190 | case T_VERDICT: | |
1191 | return Yes; | |
1192 | ||
1193 | default: | |
1194 | if (is_ref()) { | |
1195 | truth retval = get_type_refd_last()->is_charenc(); | |
1196 | if (retval == Yes) return Yes; | |
1197 | else if (retval == Maybe) { | |
1198 | if (xerattrib && xerattrib->useUnion_) return Yes; | |
1199 | } | |
1200 | // else fall through to No | |
1201 | } | |
1202 | return No; | |
1203 | ||
1204 | case T_BSTR: | |
1205 | case T_OSTR: | |
1206 | case T_HSTR: | |
1207 | case T_CSTR: | |
1208 | case T_USTR: | |
1209 | case T_UTF8STRING: | |
1210 | // TODO ASN.1 restricted character string types when (if) ASN.1 gets XER | |
1211 | // TODO check subtype; strings must be restricted to not contain | |
1212 | // control characters (0..0x1F except 9,0x0A,0x0D) | |
1213 | case T_INT_A: | |
1214 | case T_INT: | |
1215 | case T_BOOL: | |
1216 | case T_REAL: | |
1217 | // TODO more types | |
1218 | /* FIXME : this kind of check should be applied to elements of secho, | |
1219 | * not to the type of the element ! */ | |
1220 | return Yes; | |
1221 | } | |
1222 | } | |
1223 | ||
1224 | bool Type::has_empty_xml() { | |
1225 | bool answer = false; | |
1226 | switch (typetype) { | |
1227 | case T_SEQ_A: case T_SEQ_T: | |
1228 | case T_SET_A: case T_SET_T: { | |
1229 | answer = true; // If all components are optional. | |
1230 | size_t n_comps = get_nof_comps(); | |
1231 | for (size_t i = 0; i < n_comps; ++i) { | |
1232 | CompField* cf = get_comp_byIndex(i); | |
1233 | if (!cf->get_is_optional()) { | |
1234 | answer = false; | |
1235 | break; // the loop | |
1236 | } | |
1237 | } | |
1238 | break; } | |
1239 | case T_SEQOF: case T_SETOF: | |
1240 | // _If_ there is a length restriction, 0 length must be allowed. | |
1241 | // By this time parsed_restr has been absorbed into sub_type. | |
1242 | answer = (sub_type==0) || sub_type->zero_length_allowed(); | |
1243 | break; | |
1244 | default: | |
1245 | break; | |
1246 | } // switch | |
1247 | return answer; | |
1248 | } | |
1249 | ||
1250 | void Type::set_fullname(const string& p_fullname) | |
1251 | { | |
1252 | Governor::set_fullname(p_fullname); | |
1253 | switch(typetype) { | |
1254 | case T_INT_A: | |
1255 | case T_BSTR_A: | |
1256 | if(u.namednums.block) u.namednums.block->set_fullname(p_fullname); | |
1257 | if(u.namednums.nvs) | |
1258 | u.namednums.nvs->set_fullname(p_fullname+".<namedvalues>"); | |
1259 | break; | |
1260 | case T_ENUM_A: | |
1261 | if(u.enums.eis1) u.enums.eis1->set_fullname(p_fullname); | |
1262 | if(u.enums.eis2) u.enums.eis2->set_fullname(p_fullname); | |
1263 | // no break | |
1264 | case T_ENUM_T: | |
1265 | u.enums.eis->set_fullname(p_fullname); | |
1266 | break; | |
1267 | case T_ANYTYPE: | |
1268 | case T_CHOICE_T: | |
1269 | case T_SEQ_T: | |
1270 | case T_SET_T: | |
1271 | case T_OPENTYPE: | |
1272 | u.secho.cfm->set_fullname(p_fullname); | |
1273 | break; | |
1274 | case T_SEQ_A: | |
1275 | case T_SET_A: | |
1276 | case T_CHOICE_A: | |
1277 | if (u.secho.ctss) u.secho.ctss->set_fullname(p_fullname); | |
1278 | break; | |
1279 | case T_SEQOF: | |
1280 | case T_SETOF: { | |
1281 | string subtypename(".<oftype>"); | |
1282 | Type * t = u.seof.ofType; | |
1283 | /* Do NOT call get_type_refd_last() or else fatal_error ! | |
1284 | * The AST is not fully set up. */ | |
1285 | ||
1286 | /* XER will use these strings */ | |
1287 | switch (t->typetype) | |
1288 | { | |
1289 | case T_EMBEDDED_PDV: case T_EXTERNAL: | |
1290 | case T_SEQ_A: case T_SEQ_T: | |
1291 | subtypename = ".SEQUENCE"; | |
1292 | break; | |
1293 | ||
1294 | case T_SET_A: case T_SET_T: | |
1295 | subtypename = ".SET"; | |
1296 | break; | |
1297 | ||
1298 | case T_SEQOF: | |
1299 | subtypename = ".SEQUENCE_OF"; | |
1300 | break; | |
1301 | ||
1302 | case T_SETOF: | |
1303 | subtypename = ".SET_OF"; | |
1304 | break; | |
1305 | ||
1306 | case T_BSTR_A: | |
1307 | subtypename = ".BITSTRING"; | |
1308 | break; | |
1309 | ||
1310 | case T_BOOL: | |
1311 | subtypename = ".BOOLEAN"; | |
1312 | break; | |
1313 | ||
1314 | case T_CHOICE_A: case T_CHOICE_T: | |
1315 | subtypename = ".CHOICE"; | |
1316 | break; | |
1317 | ||
1318 | case T_ENUM_A: case T_ENUM_T: | |
1319 | subtypename = ".ENUMERATED"; | |
1320 | break; | |
1321 | ||
1322 | case T_INT_A: case T_INT: | |
1323 | subtypename = ".INTEGER"; | |
1324 | break; | |
1325 | ||
1326 | default: | |
1327 | break; | |
1328 | } | |
1329 | u.seof.ofType->set_fullname(p_fullname+subtypename); | |
1330 | break; } | |
1331 | case T_REFD: | |
1332 | u.ref.ref->set_fullname(p_fullname); | |
1333 | break; | |
1334 | case T_SELTYPE: | |
1335 | u.seltype.type->set_fullname(p_fullname+".<selection>"); | |
1336 | break; | |
1337 | case T_PORT: | |
1338 | u.port->set_fullname(p_fullname); | |
1339 | break; | |
1340 | case T_COMPONENT: | |
1341 | u.component->set_fullname(p_fullname); | |
1342 | break; | |
1343 | case T_ARRAY: | |
1344 | u.array.element_type->set_fullname(p_fullname + ".<element_type>"); | |
1345 | u.array.dimension->set_fullname(p_fullname + ".<dimension>"); | |
1346 | break; | |
1347 | case T_SIGNATURE: | |
1348 | if (u.signature.parameters) | |
1349 | u.signature.parameters->set_fullname(p_fullname); | |
1350 | if (u.signature.return_type) | |
1351 | u.signature.return_type->set_fullname(p_fullname + ".<return_type>"); | |
1352 | if (u.signature.exceptions) | |
1353 | u.signature.exceptions->set_fullname(p_fullname + ".<exception_list>"); | |
1354 | break; | |
1355 | case T_FUNCTION: | |
1356 | case T_ALTSTEP: | |
1357 | u.fatref.fp_list->set_fullname(p_fullname + "<formal_par_list>"); | |
1358 | if (u.fatref.runs_on.ref) | |
1359 | u.fatref.runs_on.ref->set_fullname(p_fullname + "<runs_on_type>"); | |
1360 | if (u.fatref.return_type) | |
1361 | u.fatref.return_type->set_fullname(p_fullname + "<return type>"); | |
1362 | break; | |
1363 | case T_TESTCASE: | |
1364 | u.fatref.fp_list->set_fullname(p_fullname + ".<formal_par_list>"); | |
1365 | if (u.fatref.runs_on.ref) | |
1366 | u.fatref.runs_on.ref->set_fullname(p_fullname+".<runs_on_type>"); | |
1367 | if (u.fatref.system.ref) | |
1368 | u.fatref.system.ref->set_fullname(p_fullname + ".<system_type>"); | |
1369 | break; | |
1370 | default: | |
1371 | break; | |
1372 | } // switch | |
1373 | } | |
1374 | ||
1375 | void Type::set_my_scope(Scope *p_scope) | |
1376 | { | |
1377 | Governor::set_my_scope(p_scope); | |
1378 | if(tags) tags->set_my_scope(p_scope); | |
1379 | switch(typetype) { | |
1380 | case T_INT_A: | |
1381 | case T_BSTR_A: | |
1382 | if(u.namednums.nvs) u.namednums.nvs->set_my_scope(p_scope); | |
1383 | break; | |
1384 | case T_ENUM_A: | |
1385 | if(u.enums.eis1) u.enums.eis1->set_my_scope(p_scope); | |
1386 | if(u.enums.eis2) u.enums.eis2->set_my_scope(p_scope); | |
1387 | // no break | |
1388 | case T_ENUM_T: | |
1389 | u.enums.eis->set_my_scope(p_scope); | |
1390 | break; | |
1391 | case T_CHOICE_T: | |
1392 | case T_SEQ_T: | |
1393 | case T_SET_T: | |
1394 | case T_OPENTYPE: | |
1395 | case T_ANYTYPE: | |
1396 | u.secho.cfm->set_my_scope(p_scope); | |
1397 | break; | |
1398 | case T_SEQ_A: | |
1399 | case T_SET_A: | |
1400 | case T_CHOICE_A: | |
1401 | if(u.secho.ctss) u.secho.ctss->set_my_scope(p_scope); | |
1402 | break; | |
1403 | case T_SEQOF: | |
1404 | case T_SETOF: | |
1405 | u.seof.ofType->set_my_scope(p_scope); | |
1406 | break; | |
1407 | case T_REFD: | |
1408 | u.ref.ref->set_my_scope(p_scope); | |
1409 | break; | |
1410 | case T_SELTYPE: | |
1411 | u.seltype.type->set_my_scope(p_scope); | |
1412 | break; | |
1413 | case T_ARRAY: | |
1414 | u.array.element_type->set_my_scope(p_scope); | |
1415 | u.array.dimension->set_my_scope(p_scope); | |
1416 | break; | |
1417 | case T_PORT: | |
1418 | u.port->set_my_scope(p_scope); | |
1419 | break; | |
1420 | case T_SIGNATURE: | |
1421 | if (u.signature.parameters) | |
1422 | u.signature.parameters->set_my_scope(p_scope); | |
1423 | if (u.signature.return_type) | |
1424 | u.signature.return_type->set_my_scope(p_scope); | |
1425 | if (u.signature.exceptions) | |
1426 | u.signature.exceptions->set_my_scope(p_scope); | |
1427 | break; | |
1428 | case T_COMPONENT: | |
1429 | u.component->set_my_scope(p_scope); | |
1430 | break; | |
1431 | case T_FUNCTION: | |
1432 | case T_ALTSTEP: | |
1433 | // the scope of parameter list is set later in chk_Fat() | |
1434 | if (u.fatref.runs_on.ref) | |
1435 | u.fatref.runs_on.ref->set_my_scope(p_scope); | |
1436 | if (u.fatref.return_type) | |
1437 | u.fatref.return_type->set_my_scope(p_scope); | |
1438 | break; | |
1439 | case T_TESTCASE: | |
1440 | // the scope of parameter list is set later in chk_Fat() | |
1441 | if (u.fatref.runs_on.ref) | |
1442 | u.fatref.runs_on.ref->set_my_scope(p_scope); | |
1443 | if (u.fatref.system.ref) | |
1444 | u.fatref.system.ref->set_my_scope(p_scope); | |
1445 | break; | |
1446 | default: | |
1447 | break; | |
1448 | } // switch | |
1449 | } | |
1450 | ||
1451 | Type* Type::get_type_refd(ReferenceChain *refch) | |
1452 | { | |
1453 | switch(typetype) { | |
1454 | case T_REFD: { | |
1455 | if(refch && !refch->add(get_fullname())) goto error; | |
1456 | if(!u.ref.type_refd) { | |
1457 | Assignment *ass = u.ref.ref->get_refd_assignment(); | |
1458 | if (!ass) goto error; // The referenced assignment is not found | |
1459 | switch (ass->get_asstype()) { | |
1460 | case Assignment::A_ERROR: | |
1461 | goto error; | |
1462 | case Assignment::A_TYPE: | |
1463 | case Assignment::A_VS: | |
1464 | u.ref.type_refd = ass->get_Type()->get_field_type( | |
1465 | u.ref.ref->get_subrefs(), EXPECTED_DYNAMIC_VALUE, refch); | |
1466 | if (!u.ref.type_refd) goto error; | |
1467 | break; | |
1468 | //case Assignment::A_VS: | |
1469 | //u.ref.type_refd = ass->get_Type(); | |
1470 | // if(!u.ref.type_refd) goto error; | |
1471 | //break; | |
1472 | case Assignment::A_OC: | |
1473 | case Assignment::A_OBJECT: | |
1474 | case Assignment::A_OS: { | |
1475 | Setting *setting = u.ref.ref->get_refd_setting(); | |
1476 | if (!setting || setting->get_st() == Setting::S_ERROR) goto error; | |
1477 | /* valueset? */ | |
1478 | u.ref.type_refd = dynamic_cast<Type*>(setting); | |
1479 | if(!u.ref.type_refd) { | |
1480 | error("`%s' is not a reference to a type", | |
1481 | u.ref.ref->get_dispname().c_str()); | |
1482 | goto error; | |
1483 | } | |
1484 | ||
1485 | if (u.ref.type_refd->ownertype == OT_UNKNOWN) { | |
1486 | u.ref.type_refd->set_ownertype(OT_REF, this); | |
1487 | } | |
1488 | ||
1489 | break;} | |
1490 | default: | |
1491 | error("`%s' is not a reference to a type", | |
1492 | u.ref.ref->get_dispname().c_str()); | |
1493 | goto error; | |
1494 | } // switch | |
1495 | if(!u.ref.type_refd->get_my_scope()) { | |
1496 | // opentype or OCFT | |
1497 | u.ref.type_refd->set_my_scope(get_my_scope()); | |
1498 | u.ref.type_refd->set_parent_type(get_parent_type()); | |
1499 | u.ref.type_refd->set_genname(get_genname_own(), string("type")); | |
1500 | u.ref.type_refd->set_fullname(get_fullname()+".type"); | |
1501 | } | |
1502 | if (u.ref.type_refd->typetype == T_OPENTYPE && !constraints) | |
1503 | warning("An open type without table constraint is useless in TTCN-3"); | |
1504 | } | |
1505 | return u.ref.type_refd; | |
1506 | break;} | |
1507 | case T_SELTYPE: { | |
1508 | if(refch && !refch->add(get_fullname())) goto error; | |
1509 | if(!u.seltype.type_refd) { | |
1510 | Type *t=u.seltype.type->get_type_refd_last(refch); | |
1511 | if(t->typetype==T_ERROR) goto error; | |
1512 | if(t->typetype!=T_CHOICE_A) { | |
1513 | error("(Reference to) a CHOICE type was expected" | |
1514 | " in selection type."); | |
1515 | goto error; | |
1516 | } | |
1517 | if(!t->has_comp_withName(*u.seltype.id)) { | |
1518 | error("No alternative with name `%s' in the given type `%s'.", | |
1519 | u.seltype.id->get_dispname().c_str(), | |
1520 | t->get_fullname().c_str()); | |
1521 | goto error; | |
1522 | } | |
1523 | u.seltype.type_refd=t->get_comp_byName(*u.seltype.id)->get_type(); | |
1524 | } | |
1525 | return u.seltype.type_refd; | |
1526 | break;} | |
1527 | case T_REFDSPEC: | |
1528 | case T_OCFT: | |
1529 | if(refch && !refch->add(get_fullname())) goto error; | |
1530 | return u.ref.type_refd; | |
1531 | break; | |
1532 | case T_EXTERNAL: { | |
1533 | if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); | |
1534 | Identifier t_id(Identifier::ID_ASN, string("EXTERNAL")); | |
1535 | return my_scope->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); } | |
1536 | case T_EMBEDDED_PDV: { | |
1537 | if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); | |
1538 | Identifier t_id(Identifier::ID_ASN, string("EMBEDDED PDV")); | |
1539 | return my_scope->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); } | |
1540 | case T_UNRESTRICTEDSTRING: { | |
1541 | if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); | |
1542 | Identifier t_id(Identifier::ID_ASN, string("CHARACTER STRING")); | |
1543 | return my_scope->get_scope_asss()->get_local_ass_byId(t_id)->get_Type(); } | |
1544 | case T_ADDRESS: | |
1545 | if (refch && !refch->add(get_fullname())) goto error; | |
1546 | if (u.address) return u.address; | |
1547 | if (!my_scope) FATAL_ERROR("Type::get_type_refd()"); | |
1548 | u.address = my_scope->get_scope_mod()->get_address_type(); | |
1549 | if (!u.address) { | |
1550 | error("Type `address' is not defined in this module"); | |
1551 | goto error; | |
1552 | } | |
1553 | return u.address; | |
1554 | default: | |
1555 | FATAL_ERROR("Type::get_type_refd()"); | |
1556 | return 0; | |
1557 | } // switch | |
1558 | error: | |
1559 | clean_up(); | |
1560 | return this; | |
1561 | } | |
1562 | ||
1563 | Type* Type::get_type_refd_last(ReferenceChain *refch) | |
1564 | { | |
1565 | Type *t=this; | |
1566 | while(t->is_ref()) t=t->get_type_refd(refch); | |
1567 | return t; | |
1568 | } | |
1569 | ||
1570 | Type *Type::get_field_type(Ttcn::FieldOrArrayRefs *subrefs, | |
1571 | expected_value_t expected_index, ReferenceChain *refch, | |
1572 | bool interrupt_if_optional) | |
1573 | { | |
1574 | if (!subrefs) return this; | |
1575 | Type *t = this; | |
1576 | if (expected_index == EXPECTED_TEMPLATE) | |
1577 | expected_index = EXPECTED_DYNAMIC_VALUE; | |
1578 | size_t nof_refs = subrefs->get_nof_refs(); | |
1579 | subrefs->clear_string_element_ref(); | |
1580 | for (size_t i = 0; i < nof_refs; i++) { | |
1581 | if (refch) refch->mark_state(); | |
1582 | t = t->get_type_refd_last(refch); | |
1583 | if (refch) refch->prev_state(); | |
1584 | // stop immediately if current type t is erroneous | |
1585 | // (e.g. because of circular reference) | |
1586 | if (t->typetype == T_ERROR) return 0; | |
1587 | Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); | |
1588 | switch (ref->get_type()) { | |
1589 | case Ttcn::FieldOrArrayRef::FIELD_REF: { | |
1590 | const Identifier& id = *ref->get_id(); | |
1591 | switch (t->typetype) { | |
1592 | case T_CHOICE_A: | |
1593 | case T_CHOICE_T: | |
1594 | case T_OPENTYPE: | |
1595 | case T_SEQ_A: | |
1596 | case T_SEQ_T: | |
1597 | case T_SET_A: | |
1598 | case T_SET_T: | |
1599 | case T_ANYTYPE: | |
1600 | break; | |
1601 | default: | |
1602 | ref->error("Invalid field reference `%s': type `%s' " | |
1603 | "does not have fields", id.get_dispname().c_str(), | |
1604 | t->get_typename().c_str()); | |
1605 | return 0; | |
1606 | } | |
1607 | if (!t->has_comp_withName(id)) { | |
1608 | ref->error("Reference to non-existent field `%s' in type `%s'", | |
1609 | id.get_dispname().c_str(), | |
1610 | t->get_typename().c_str()); | |
1611 | return 0; | |
1612 | } | |
1613 | CompField* cf = t->get_comp_byName(id); | |
1614 | if (interrupt_if_optional && cf->get_is_optional()) return 0; | |
1615 | t = cf->get_type(); | |
1616 | break; } | |
1617 | case Ttcn::FieldOrArrayRef::ARRAY_REF: { | |
1618 | Type *embedded_type = 0; | |
1619 | switch (t->typetype) { | |
1620 | case T_SEQOF: | |
1621 | case T_SETOF: | |
1622 | embedded_type = t->u.seof.ofType; | |
1623 | break; | |
1624 | case T_ARRAY: | |
1625 | embedded_type = t->u.array.element_type; | |
1626 | break; | |
1627 | case T_BSTR: | |
1628 | case T_BSTR_A: | |
1629 | case T_HSTR: | |
1630 | case T_OSTR: | |
1631 | case T_CSTR: | |
1632 | case T_USTR: | |
1633 | case T_UTF8STRING: | |
1634 | case T_NUMERICSTRING: | |
1635 | case T_PRINTABLESTRING: | |
1636 | case T_TELETEXSTRING: | |
1637 | case T_VIDEOTEXSTRING: | |
1638 | case T_IA5STRING: | |
1639 | case T_GRAPHICSTRING: | |
1640 | case T_VISIBLESTRING: | |
1641 | case T_GENERALSTRING: | |
1642 | case T_UNIVERSALSTRING: | |
1643 | case T_BMPSTRING: | |
1644 | case T_UTCTIME: | |
1645 | case T_GENERALIZEDTIME: | |
1646 | case T_OBJECTDESCRIPTOR: | |
1647 | if (subrefs->refers_to_string_element()) { | |
1648 | ref->error("A string element of type `%s' cannot be indexed", | |
1649 | t->get_typename().c_str()); | |
1650 | return 0; | |
1651 | } else { | |
1652 | subrefs->set_string_element_ref(); | |
1653 | // string elements have the same type as the string itself | |
1654 | embedded_type = t; | |
1655 | break; | |
1656 | } | |
1657 | default: | |
1658 | ref->error("Type `%s' cannot be indexed", | |
1659 | t->get_typename().c_str()); | |
1660 | return 0; | |
1661 | } | |
1662 | // check the index value | |
1663 | Value *index_value = ref->get_val(); | |
1664 | if (t->typetype == T_ARRAY) { | |
1665 | // checking of array index is performed by the array dimension | |
1666 | t->u.array.dimension->chk_index(index_value, expected_index); | |
1667 | } else { | |
1668 | // perform a generic index check for other types | |
1669 | if (refch == 0 // variable assignment | |
1670 | || index_value->get_valuetype() != Value::V_NOTUSED) { | |
1671 | Error_Context cntxt(index_value, "In index value"); | |
1672 | index_value->chk_expr_int(expected_index); | |
1673 | } | |
1674 | Value *v_last = index_value->get_value_refd_last(); | |
1675 | if (v_last->get_valuetype() == Value::V_INT) { | |
1676 | const int_val_t *index_int = v_last->get_val_Int(); | |
1677 | if (*index_int > INT_MAX) { | |
1678 | index_value->error("Integer value `%s' is too big for indexing " | |
1679 | "type `%s'", (index_int->t_str()).c_str(), | |
1680 | (t->get_typename()).c_str()); | |
1681 | index_value->set_valuetype(Value::V_ERROR); | |
1682 | } else { | |
1683 | if (*index_int < 0) { | |
1684 | index_value->error("A non-negative integer value was " | |
1685 | "expected for indexing type `%s' instead of `%s'", | |
1686 | t->get_typename().c_str(), (index_int->t_str()).c_str()); | |
1687 | index_value->set_valuetype(Value::V_ERROR); | |
1688 | } | |
1689 | } | |
1690 | } | |
1691 | } | |
1692 | // change t to the embedded type | |
1693 | t = embedded_type; | |
1694 | break; } | |
1695 | default: | |
1696 | FATAL_ERROR("Type::get_field_type(): invalid reference type"); | |
1697 | } | |
1698 | } | |
1699 | return t; | |
1700 | } | |
1701 | ||
1702 | bool Type::get_subrefs_as_array(const Ttcn::FieldOrArrayRefs *subrefs, dynamic_array<size_t>& subrefs_array, dynamic_array<Type*>& type_array) | |
1703 | { | |
1704 | if (!subrefs) FATAL_ERROR("Type::get_subrefs_as_array()"); | |
1705 | Type *t = this; | |
1706 | size_t nof_refs = subrefs->get_nof_refs(); | |
1707 | for (size_t i = 0; i < nof_refs; i++) { | |
1708 | t = t->get_type_refd_last(); | |
1709 | type_array.add(t); | |
1710 | if (t->typetype == T_ERROR) FATAL_ERROR("Type::get_subrefs_as_array()"); | |
1711 | Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); | |
1712 | size_t field_index=0; | |
1713 | switch (ref->get_type()) { | |
1714 | case Ttcn::FieldOrArrayRef::FIELD_REF: { | |
1715 | const Identifier& id = *ref->get_id(); | |
1716 | if (!t->has_comp_withName(id)) FATAL_ERROR("Type::get_subrefs_as_array()"); | |
1717 | CompField* cf = t->get_comp_byName(id); | |
1718 | field_index = t->get_comp_index_byName(id); | |
1719 | field_index = t->get_codegen_index(field_index); | |
1720 | t = cf->get_type(); | |
1721 | break; } | |
1722 | case Ttcn::FieldOrArrayRef::ARRAY_REF: { | |
1723 | Value *index_value = ref->get_val(); | |
1724 | Value *v_last = index_value->get_value_refd_last(); | |
1725 | if (v_last->get_valuetype()!=Value::V_INT) { | |
1726 | // workaround: get_field_type() does not return NULL if the index | |
1727 | // value is invalid, this function returns false in this case | |
1728 | return false; | |
1729 | } | |
1730 | const int_val_t *index_int = v_last->get_val_Int(); | |
1731 | if (!index_int->is_native() || index_int->is_negative()) { | |
1732 | return false; | |
1733 | } | |
1734 | field_index = (size_t)index_int->get_val(); | |
1735 | Type *embedded_type = 0; | |
1736 | switch (t->typetype) { | |
1737 | case T_SEQOF: | |
1738 | case T_SETOF: | |
1739 | embedded_type = t->u.seof.ofType; | |
1740 | break; | |
1741 | case T_ARRAY: | |
1742 | embedded_type = t->u.array.element_type; | |
1743 | break; | |
1744 | default: | |
1745 | embedded_type = t; | |
1746 | break; | |
1747 | } | |
1748 | // change t to the embedded type | |
1749 | t = embedded_type; | |
1750 | break; } | |
1751 | default: | |
1752 | FATAL_ERROR("Type::get_subrefs_as_array()"); | |
1753 | } | |
1754 | subrefs_array.add(field_index); | |
1755 | } | |
1756 | return true; | |
1757 | } | |
1758 | ||
1759 | bool Type::is_optional_field() const { | |
1760 | if (ownertype == OT_COMP_FIELD) { | |
1761 | const CompField* const myOwner = (CompField*) owner; | |
1762 | return myOwner && myOwner->get_is_optional(); | |
1763 | } | |
1764 | return false; | |
1765 | } | |
1766 | ||
1767 | bool Type::field_is_optional(Ttcn::FieldOrArrayRefs *subrefs) | |
1768 | { | |
1769 | // handling trivial cases | |
1770 | if (!subrefs) return false; | |
1771 | size_t nof_subrefs = subrefs->get_nof_refs(); | |
1772 | if (nof_subrefs < 1) return false; | |
1773 | Ttcn::FieldOrArrayRef *last_ref = subrefs->get_ref(nof_subrefs - 1); | |
1774 | if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) return false; | |
1775 | // following the embedded types | |
1776 | Type *t=get_type_refd_last(); | |
1777 | for (size_t i = 0; i < nof_subrefs - 1; i++) { | |
1778 | Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); | |
1779 | if (ref->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF) | |
1780 | t = t->get_comp_byName(*ref->get_id())->get_type(); | |
1781 | else t = t->get_ofType(); | |
1782 | t=t->get_type_refd_last(); | |
1783 | } | |
1784 | // now last_ref refers to a field of t | |
1785 | return t->get_comp_byName(*last_ref->get_id())->get_is_optional(); | |
1786 | } | |
1787 | ||
1788 | bool Type::is_root_basic(){ | |
1789 | Type *t=get_type_refd_last(); | |
1790 | switch(t->typetype){ | |
1791 | case T_INT: | |
1792 | case T_BOOL: | |
1793 | case T_BSTR: | |
1794 | case T_HSTR: | |
1795 | case T_OSTR: | |
1796 | case T_CSTR: | |
1797 | return true; | |
1798 | break; | |
1799 | default: | |
1800 | break; | |
1801 | } | |
1802 | return false; | |
1803 | } | |
1804 | ||
1805 | int Type::get_raw_length(){ | |
1806 | if(!raw_checked) FATAL_ERROR("Type::get_raw_length()"); | |
1807 | if(raw_length_calculated) return raw_length; | |
1808 | raw_length_calculated=true; | |
1809 | switch(typetype) { | |
1810 | case T_REFD: | |
1811 | raw_length=get_type_refd()->get_raw_length(); | |
1812 | break; | |
1813 | case T_INT: | |
1814 | if(rawattrib) raw_length=rawattrib->fieldlength; | |
1815 | else raw_length=8; | |
1816 | break; | |
1817 | case T_BOOL: | |
1818 | if(rawattrib) raw_length=rawattrib->fieldlength; | |
1819 | else raw_length=1; | |
1820 | break; | |
1821 | case T_BSTR: | |
1822 | case T_HSTR: | |
1823 | case T_OSTR: | |
1824 | case T_CSTR: | |
1825 | if(rawattrib && rawattrib->fieldlength) raw_length=rawattrib->fieldlength; | |
1826 | else raw_length=-1; | |
1827 | break; | |
1828 | case T_ENUM_T: | |
1829 | if(rawattrib && rawattrib->fieldlength) raw_length=rawattrib->fieldlength; | |
1830 | else{ | |
1831 | int min_bits=0; | |
1832 | int max_val=u.enums.first_unused; | |
1833 | for(size_t a=0;a<u.enums.eis->get_nof_eis();a++){ | |
1834 | int val=u.enums.eis->get_ei_byIndex(a)->get_value()->get_val_Int() | |
1835 | ->get_val(); | |
1836 | if((max_val<0?-max_val:max_val)<(val<0?-val:val)) max_val=val; | |
1837 | } | |
1838 | if(max_val<0){ min_bits=1;max_val=-max_val;} | |
1839 | while(max_val){ min_bits++; max_val/=2;} | |
1840 | raw_length=min_bits; | |
1841 | } | |
1842 | break; | |
1843 | case T_SEQ_T: | |
1844 | case T_SET_T: | |
1845 | raw_length=0; | |
1846 | for(size_t i = 0; i < get_nof_comps(); i++){ | |
1847 | int l=0; | |
1848 | CompField* cf=get_comp_byIndex(i); | |
1849 | if(cf->get_is_optional()){ | |
1850 | raw_length=-1; | |
1851 | return raw_length; | |
1852 | } | |
1853 | l=cf->get_type()->get_raw_length(); | |
1854 | if(l==-1){ | |
1855 | raw_length=-1; | |
1856 | return raw_length; | |
1857 | } | |
1858 | if(cf->get_type()->rawattrib | |
1859 | && (cf->get_type()->rawattrib->pointerto | |
1860 | || cf->get_type()->rawattrib->lengthto_num)){ | |
1861 | raw_length=-1; | |
1862 | return raw_length; | |
1863 | } | |
1864 | raw_length+=l; | |
1865 | } | |
1866 | break; | |
1867 | // TODO: case T_ANYTYPE: for get_raw_length needed ? | |
1868 | case T_CHOICE_T: | |
1869 | for(size_t i = 0; i < get_nof_comps(); i++){ | |
1870 | CompField *cf=get_comp_byIndex(i); | |
1871 | int l=0; | |
1872 | l=cf->get_type()->get_raw_length(); | |
1873 | if(l==-1){ | |
1874 | raw_length=-1; | |
1875 | return raw_length; | |
1876 | } | |
1877 | if(i){ | |
1878 | if(raw_length!=l){ | |
1879 | raw_length=-1; | |
1880 | return raw_length; | |
1881 | } | |
1882 | } | |
1883 | else raw_length=l; | |
1884 | } | |
1885 | break; | |
1886 | default: | |
1887 | raw_length=-1; | |
1888 | break; | |
1889 | } | |
1890 | return raw_length; | |
1891 | } | |
1892 | ||
1893 | /** \todo: add extra checks and warnings for unsupported attributes | |
1894 | * e.g. when TAG refers to a record/set field which has union type */ | |
1895 | void Type::chk_raw() | |
1896 | { | |
1897 | bool self_ref = false; | |
1898 | if (raw_checked) return; | |
1899 | raw_checked = true; | |
1900 | if (!enable_raw()) return; | |
1901 | int restrlength=-1; | |
1902 | if(sub_type) | |
1903 | restrlength=(int)sub_type->get_length_restriction(); | |
1904 | if(restrlength!=-1){ | |
1905 | if(!rawattrib){ | |
1906 | Type *t=get_type_refd_last(); | |
1907 | typetype_t basic_type=t->typetype; | |
1908 | rawattrib=new RawAST(basic_type==T_INT); | |
1909 | if(basic_type==T_REAL) rawattrib->fieldlength=64; | |
1910 | } | |
1911 | rawattrib->length_restrition=restrlength; | |
1912 | } | |
1913 | if(!rawattrib) return; | |
1914 | switch(typetype) { | |
1915 | case T_REFD: | |
1916 | get_type_refd()->force_raw(); | |
1917 | if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ | |
1918 | typetype_t basic_type=get_type_refd_last()->typetype; | |
1919 | switch(basic_type){ | |
1920 | case T_BSTR: | |
1921 | rawattrib->fieldlength=rawattrib->length_restrition; | |
1922 | rawattrib->length_restrition=-1; | |
1923 | break; | |
1924 | case T_HSTR: | |
1925 | rawattrib->fieldlength=rawattrib->length_restrition*4; | |
1926 | rawattrib->length_restrition=-1; | |
1927 | break; | |
1928 | case T_OSTR: | |
1929 | rawattrib->fieldlength=rawattrib->length_restrition*8; | |
1930 | rawattrib->length_restrition=-1; | |
1931 | break; | |
1932 | case T_CSTR: | |
1933 | rawattrib->fieldlength=rawattrib->length_restrition*8; | |
1934 | rawattrib->length_restrition=-1; | |
1935 | break; | |
1936 | case T_SEQOF: | |
1937 | case T_SETOF: | |
1938 | rawattrib->fieldlength=rawattrib->length_restrition; | |
1939 | rawattrib->length_restrition=-1; | |
1940 | break; | |
1941 | default: | |
1942 | break; | |
1943 | } | |
1944 | } | |
1945 | break; | |
1946 | case T_CHOICE_T: | |
1947 | if(rawattrib){ | |
1948 | size_t nof_comps = get_nof_comps(); | |
1949 | for (size_t i = 0; i < nof_comps; i++) | |
1950 | get_comp_byIndex(i)->get_type()->force_raw(); | |
1951 | for(int c=0;c<rawattrib->taglist.nElements;c++){ | |
1952 | Identifier *idf=rawattrib->taglist.tag[c].fieldName; | |
1953 | if(!has_comp_withName(*idf)){ | |
1954 | error("Invalid field name `%s' in RAW parameter TAG for type `%s'", | |
1955 | idf->get_dispname().c_str(), get_typename().c_str()); | |
1956 | continue; | |
1957 | } | |
1958 | size_t fieldnum = get_comp_index_byName(*idf); | |
1959 | for(int a=0;a<rawattrib->taglist.tag[c].nElements;a++){ | |
1960 | bool hiba=false; | |
1961 | CompField *cf=get_comp_byIndex(fieldnum); | |
1962 | Type *t=cf->get_type()->get_type_refd_last(); | |
1963 | for(int b=0;b<rawattrib->taglist.tag[c].keyList[a]. | |
1964 | keyField->nElements;b++){ | |
1965 | Identifier *idf2= | |
1966 | rawattrib->taglist.tag[c].keyList[a].keyField->names[b]; | |
1967 | if(!t->is_secho()){ | |
1968 | error("Invalid fieldmember type in RAW parameter TAG" | |
1969 | " for field %s." | |
1970 | ,cf->get_name().get_dispname().c_str()); | |
1971 | hiba=true; | |
1972 | break; | |
1973 | } | |
1974 | if(!t->has_comp_withName(*idf2)){ | |
1975 | error("Invalid field member name `%s' in RAW parameter TAG " | |
1976 | "for field `%s'", idf2->get_dispname().c_str(), | |
1977 | cf->get_name().get_dispname().c_str()); | |
1978 | hiba=true; | |
1979 | break; | |
1980 | } | |
1981 | size_t comp_index=t->get_comp_index_byName(*idf2); | |
1982 | CompField *cf2=t->get_comp_byIndex(comp_index); | |
1983 | t=cf2->get_type()->get_type_refd_last(); | |
1984 | } | |
1985 | if(!hiba){ | |
1986 | Error_Context cntx(this, "In Raw parmeter TAG"); | |
1987 | Value *v = rawattrib->taglist.tag[c].keyList[a].v_value; | |
1988 | v->set_my_scope(get_my_scope()); | |
1989 | v->set_my_governor(t); | |
1990 | t->chk_this_value_ref(v); | |
1991 | self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, | |
1992 | INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); | |
1993 | Value::valuetype_t vt = v->get_valuetype(); | |
1994 | if (vt == Value::V_ENUM || vt == Value::V_REFD) { | |
1995 | Free(rawattrib->taglist.tag[c].keyList[a].value); | |
1996 | rawattrib->taglist.tag[c].keyList[a].value = | |
1997 | mcopystr(v->get_single_expr().c_str()); | |
1998 | } | |
1999 | } | |
2000 | } | |
2001 | } | |
2002 | } | |
2003 | break; | |
2004 | case T_SEQ_T: | |
2005 | case T_SET_T: | |
2006 | if(rawattrib){ | |
2007 | size_t fieldnum; | |
2008 | for(int c=0;c<rawattrib->taglist.nElements;c++) { // check TAG | |
2009 | Identifier *idf=rawattrib->taglist.tag[c].fieldName; | |
2010 | if(!has_comp_withName(*idf)){ | |
2011 | error("Invalid field name `%s' in RAW parameter TAG " | |
2012 | "for type `%s'", idf->get_dispname().c_str(), | |
2013 | get_typename().c_str()); | |
2014 | continue; | |
2015 | } | |
2016 | fieldnum=get_comp_index_byName(*idf); | |
2017 | for(int a=0;a<rawattrib->taglist.tag[c].nElements;a++){ | |
2018 | bool hiba=false; | |
2019 | CompField *cf=get_comp_byIndex(fieldnum); | |
2020 | Type *t=cf->get_type()->get_type_refd_last(); | |
2021 | for(int b=0;b<rawattrib->taglist.tag[c].keyList[a]. | |
2022 | keyField->nElements;b++){ | |
2023 | Identifier *idf2= | |
2024 | rawattrib->taglist.tag[c].keyList[a].keyField->names[b]; | |
2025 | if(!t->is_secho()){ | |
2026 | error("Invalid fieldmember type in RAW parameter TAG" | |
2027 | " for field %s." | |
2028 | ,cf->get_name().get_dispname().c_str()); | |
2029 | hiba=true; | |
2030 | break; | |
2031 | } | |
2032 | if(!t->has_comp_withName(*idf2)){ | |
2033 | error("Invalid field member name `%s' in RAW parameter TAG " | |
2034 | "for field `%s'", idf2->get_dispname().c_str(), | |
2035 | cf->get_name().get_dispname().c_str()); | |
2036 | hiba=true; | |
2037 | break; | |
2038 | } | |
2039 | size_t comp_index=t->get_comp_index_byName(*idf2); | |
2040 | CompField *cf2=t->get_comp_byIndex(comp_index); | |
2041 | t=cf2->get_type()->get_type_refd_last(); | |
2042 | } | |
2043 | if(!hiba){ | |
2044 | Error_Context cntx(this, "In Raw parmeter TAG"); | |
2045 | Value *v = rawattrib->taglist.tag[c].keyList[a].v_value; | |
2046 | v->set_my_scope(get_my_scope()); | |
2047 | v->set_my_governor(t); | |
2048 | t->chk_this_value_ref(v); | |
2049 | self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, | |
2050 | INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); | |
2051 | Value::valuetype_t vt = v->get_valuetype(); | |
2052 | if (vt == Value::V_ENUM || vt == Value::V_REFD) { | |
2053 | Free(rawattrib->taglist.tag[c].keyList[a].value); | |
2054 | rawattrib->taglist.tag[c].keyList[a].value = | |
2055 | mcopystr(v->get_single_expr().c_str()); | |
2056 | } | |
2057 | } | |
2058 | } | |
2059 | } | |
2060 | for(int a=0; a<rawattrib->ext_bit_goup_num;a++){ // EXTENSION_BIT_GROUP | |
2061 | Identifier *idf=rawattrib->ext_bit_groups[a].from; | |
2062 | Identifier *idf2=rawattrib->ext_bit_groups[a].to; | |
2063 | bool hiba=false; | |
2064 | if(!has_comp_withName(*idf)){ | |
2065 | error("Invalid field name `%s' in RAW parameter " | |
2066 | "EXTENSION_BIT_GROUP for type `%s'", | |
2067 | idf->get_dispname().c_str(), get_typename().c_str()); | |
2068 | hiba=true; | |
2069 | } | |
2070 | if(!has_comp_withName(*idf2)){ | |
2071 | error("Invalid field name `%s' in RAW parameter " | |
2072 | "EXTENSION_BIT_GROUP for type `%s'", | |
2073 | idf2->get_dispname().c_str(), get_typename().c_str()); | |
2074 | hiba=true; | |
2075 | } | |
2076 | if(!hiba){ | |
2077 | size_t kezd=get_comp_index_byName(*idf); | |
2078 | size_t veg=get_comp_index_byName(*idf2); | |
2079 | if(kezd>veg){ | |
2080 | error("Invalid field order in RAW parameter " | |
2081 | "EXTENSION_BIT_GROUP for type `%s': `%s', `%s'", | |
2082 | get_typename().c_str(), idf->get_dispname().c_str(), | |
2083 | idf2->get_dispname().c_str()); | |
2084 | hiba=true; | |
2085 | } | |
2086 | } | |
2087 | } | |
2088 | if(rawattrib->paddall!=XDEFDEFAULT){ // PADDALL | |
2089 | for(size_t i = 0; i < get_nof_comps(); i++) { | |
2090 | CompField *cfield=get_comp_byIndex(i); | |
2091 | RawAST *field_rawattr=cfield->get_type()->rawattrib; | |
2092 | if(field_rawattr==NULL){ | |
2093 | Type *t=cfield->get_type()->get_type_refd_last(); | |
2094 | typetype_t basic_type=t->typetype; | |
2095 | t=cfield->get_type(); | |
2096 | if(t->is_ref()) t=t->get_type_refd(); | |
2097 | while(!t->rawattrib && t->is_ref()) t=t->get_type_refd(); | |
2098 | field_rawattr= new RawAST(t->rawattrib,basic_type==T_INT); | |
2099 | if(!t->rawattrib && basic_type==T_REAL) field_rawattr->fieldlength=64; | |
2100 | cfield->get_type()->rawattrib=field_rawattr; | |
2101 | } | |
2102 | if(field_rawattr->padding==0) | |
2103 | field_rawattr->padding=rawattrib->padding; | |
2104 | if(field_rawattr->prepadding==0) | |
2105 | field_rawattr->prepadding=rawattrib->prepadding; | |
2106 | if (field_rawattr->padding_pattern_length == 0 && | |
2107 | rawattrib->padding_pattern_length > 0) { | |
2108 | Free(field_rawattr->padding_pattern); | |
2109 | field_rawattr->padding_pattern = | |
2110 | mcopystr(rawattrib->padding_pattern); | |
2111 | field_rawattr->padding_pattern_length = | |
2112 | rawattrib->padding_pattern_length; | |
2113 | } | |
2114 | } | |
2115 | } | |
2116 | if(rawattrib->fieldorder!=XDEFDEFAULT){ // FIELDORDER | |
2117 | for(size_t i = 0; i < get_nof_comps(); i++) { | |
2118 | CompField *cfield=get_comp_byIndex(i); | |
2119 | RawAST *field_rawattr=cfield->get_type()->rawattrib; | |
2120 | if(field_rawattr==NULL){ | |
2121 | Type *t=cfield->get_type()->get_type_refd_last(); | |
2122 | typetype_t basic_type=t->typetype; | |
2123 | t=cfield->get_type(); | |
2124 | if(t->is_ref()) t=t->get_type_refd(); | |
2125 | while(!t->rawattrib && t->is_ref()) t=t->get_type_refd(); | |
2126 | field_rawattr= new RawAST(t->rawattrib,basic_type==T_INT); | |
2127 | if(!t->rawattrib && basic_type==T_REAL) field_rawattr->fieldlength=64; | |
2128 | cfield->get_type()->rawattrib=field_rawattr; | |
2129 | } | |
2130 | if(field_rawattr->fieldorder==XDEFDEFAULT) | |
2131 | field_rawattr->fieldorder=rawattrib->fieldorder; | |
2132 | } | |
2133 | } | |
2134 | } | |
2135 | for(int a=0;a<rawattrib->presence.nElements;a++){ //PRESENCE | |
2136 | Type *t=this; | |
2137 | bool hiba=false; | |
2138 | for(int b=0;b<rawattrib->presence.keyList[a].keyField->nElements;b++){ | |
2139 | Identifier *idf=rawattrib->presence.keyList[a].keyField->names[b]; | |
2140 | if(!t->is_secho()){ | |
2141 | error("Invalid fieldmember type in RAW parameter PRESENCE" | |
2142 | " for the record %s." | |
2143 | ,get_typename().c_str()); | |
2144 | hiba=true; | |
2145 | break; | |
2146 | } | |
2147 | if(!t->has_comp_withName(*idf)){ | |
2148 | error("Invalid fieldname in RAW parameter" | |
2149 | " PRESENCE for the record %s: %s" | |
2150 | ,get_typename().c_str() | |
2151 | ,rawattrib->presence.keyList[a].keyField->names[b] | |
2152 | ->get_dispname().c_str()); | |
2153 | hiba=true; | |
2154 | break; | |
2155 | } | |
2156 | t=t->get_comp_byName(*idf)->get_type()->get_type_refd_last(); | |
2157 | } | |
2158 | if(!hiba){ | |
2159 | Error_Context cntx(this, "In Raw parameter PRESENCE"); | |
2160 | Value *v = rawattrib->presence.keyList[a].v_value; | |
2161 | v->set_my_scope(get_my_scope()); | |
2162 | v->set_my_governor(t); | |
2163 | t->chk_this_value_ref(v); | |
2164 | self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, | |
2165 | INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); | |
2166 | Value::valuetype_t vt = v->get_valuetype(); | |
2167 | if (vt == Value::V_ENUM || vt == Value::V_REFD) { | |
2168 | Free(rawattrib->presence.keyList[a].value); | |
2169 | rawattrib->presence.keyList[a].value = | |
2170 | mcopystr(v->get_single_expr().c_str()); | |
2171 | } | |
2172 | } | |
2173 | } | |
2174 | for(size_t i = 0; i < get_nof_comps(); i++) { // field attributes | |
2175 | CompField *cf = get_comp_byIndex(i); | |
2176 | const Identifier& field_id = cf->get_name(); | |
2177 | Type *field_type = cf->get_type(); | |
2178 | Type *field_type_last = field_type->get_type_refd_last(); | |
2179 | field_type->force_raw(); | |
2180 | RawAST *rawpar = field_type->rawattrib; | |
2181 | if (rawpar) { | |
2182 | for (int j = 0; j < rawpar->lengthto_num; j++) { // LENGTHTO | |
2183 | Identifier *idf = rawpar->lengthto[j]; | |
2184 | if (!has_comp_withName(*idf)) { | |
2185 | error("Invalid fieldname in RAW parameter " | |
2186 | "LENGTHTO for field %s: %s", | |
2187 | field_id.get_dispname().c_str(), | |
2188 | rawpar->lengthto[j]->get_dispname().c_str()); | |
2189 | } | |
2190 | } | |
2191 | if (rawpar->lengthto_num) { | |
2192 | Type *ft = field_type; | |
2193 | if (ft->get_typetype() == T_REFD) ft = ft->get_type_refd_last(); | |
2194 | typetype_t ftt = ft->get_typetype(); | |
2195 | switch (ftt) { | |
2196 | case T_INT: | |
2197 | case T_INT_A: | |
2198 | break; | |
2199 | case T_CHOICE_T: | |
2200 | case T_CHOICE_A: | |
2201 | for (size_t fi = 0; fi < ft->get_nof_comps(); fi++) { | |
2202 | typetype_t uftt = ft->get_comp_byIndex(fi)->get_type() | |
2203 | ->get_typetype(); | |
2204 | if (uftt != T_INT && uftt != T_INT_A) | |
2205 | error("The union type LENGTHTO field must contain only " | |
2206 | "integer fields"); | |
2207 | } | |
2208 | break; | |
2209 | case T_ANYTYPE: | |
2210 | case T_OPENTYPE: | |
2211 | case T_SEQ_A: | |
2212 | case T_SEQ_T: | |
2213 | case T_SET_A: | |
2214 | case T_SET_T: | |
2215 | if (rawpar->lengthindex) break; // Will be checked in the next step. | |
2216 | // Else continue with default. | |
2217 | default: | |
2218 | error("The LENGTHTO field must be an integer or union type " | |
2219 | "instead of `%s'", ft->get_typename().c_str()); | |
2220 | break; | |
2221 | } | |
2222 | } | |
2223 | if(rawpar->lengthto_num && rawpar->lengthindex){ // LENGTHINDEX | |
2224 | Identifier *idf=rawpar->lengthindex->names[0]; | |
2225 | if(!field_type_last->is_secho()){ | |
2226 | error("Invalid fieldmember type in RAW parameter LENGTHINDEX" | |
2227 | " for field %s." | |
2228 | ,field_id.get_dispname().c_str()); | |
2229 | break; | |
2230 | } | |
2231 | if(!field_type_last->has_comp_withName(*idf)) | |
2232 | error("Invalid fieldname in RAW parameter" | |
2233 | " LENGTHINDEX for field %s: %s" | |
2234 | ,field_id.get_dispname().c_str() | |
2235 | ,rawpar->lengthindex->names[0]->get_dispname().c_str()); | |
2236 | } | |
2237 | if(rawpar->pointerto){ // POINTERTO | |
2238 | Identifier *idf=rawpar->pointerto; | |
2239 | bool hiba=false; | |
2240 | size_t pointed=0; | |
2241 | if(!has_comp_withName(*idf)){ | |
2242 | error("Invalid fieldname in RAW" | |
2243 | " parameter POINTERTO for field %s: %s" | |
2244 | ,field_id.get_dispname().c_str() | |
2245 | ,rawpar->pointerto->get_dispname().c_str()); | |
2246 | hiba=true; | |
2247 | } | |
2248 | if(!hiba && (pointed=get_comp_index_byName(*idf))<=i){ | |
2249 | error("Pointer must precede the pointed field. Incorrect field " | |
2250 | "name `%s' in RAW parameter POINTERTO for field `%s'", | |
2251 | rawpar->pointerto->get_dispname().c_str(), | |
2252 | field_id.get_dispname().c_str()); | |
2253 | hiba=true; | |
2254 | } | |
2255 | if(!hiba && rawpar->ptrbase){ // POINTERTO | |
2256 | Identifier *idf2=rawpar->ptrbase; | |
2257 | if(!has_comp_withName(*idf2)){ | |
2258 | error("Invalid field name `%s' in RAW parameter PTROFFSET for " | |
2259 | "field `%s'", rawpar->ptrbase->get_dispname().c_str(), | |
2260 | field_id.get_dispname().c_str()); | |
2261 | hiba=true; | |
2262 | } | |
2263 | if(!hiba && get_comp_index_byName(*idf2)>pointed){ | |
2264 | error("Pointer base must precede the pointed field. Incorrect " | |
2265 | "field name `%s' in RAW parameter PTROFFSET for field " | |
2266 | "`%s'", rawpar->ptrbase->get_dispname().c_str(), | |
2267 | field_id.get_dispname().c_str()); | |
2268 | } | |
2269 | } | |
2270 | } | |
2271 | for(int a=0;a<rawpar->presence.nElements;a++){ //PRESENCE | |
2272 | Type *t=this; | |
2273 | bool hiba=false; | |
2274 | for(int b=0;b<rawpar->presence.keyList[a].keyField->nElements;b++){ | |
2275 | Identifier *idf=rawpar->presence.keyList[a].keyField->names[b]; | |
2276 | if(!t->is_secho()){ | |
2277 | error("Invalid fieldmember type in RAW parameter PRESENCE" | |
2278 | " for field %s." | |
2279 | ,field_id.get_dispname().c_str()); | |
2280 | hiba=true; | |
2281 | break; | |
2282 | } | |
2283 | if(!t->has_comp_withName(*idf)){ | |
2284 | error("Invalid fieldname `%s' in RAW parameter PRESENCE for " | |
2285 | "field `%s'", rawpar->presence.keyList[a].keyField | |
2286 | ->names[b]->get_dispname().c_str(), | |
2287 | field_id.get_dispname().c_str()); | |
2288 | hiba=true; | |
2289 | break; | |
2290 | } | |
2291 | if(b==0 && !(get_comp_index_byName(*rawpar->presence.keyList[a] | |
2292 | .keyField->names[0])<i)){ | |
2293 | error("The PRESENCE field `%s' must precede the optional field " | |
2294 | "in RAW parameter PRESENCE for field `%s'" | |
2295 | ,rawpar->presence.keyList[a].keyField->names[0] | |
2296 | ->get_dispname().c_str() | |
2297 | ,field_id.get_dispname().c_str()); | |
2298 | hiba=true; | |
2299 | break; | |
2300 | } | |
2301 | t=t->get_comp_byName(*idf)->get_type()->get_type_refd_last(); | |
2302 | } | |
2303 | if(!hiba){ | |
2304 | Error_Context cntx(this, "In Raw parmeter PRESENCE"); | |
2305 | Value *v = rawpar->presence.keyList[a].v_value; | |
2306 | v->set_my_scope(get_my_scope()); | |
2307 | v->set_my_governor(t); | |
2308 | t->chk_this_value_ref(v); | |
2309 | self_ref = t->chk_this_value(v, 0, EXPECTED_CONSTANT, | |
2310 | INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); | |
2311 | Value::valuetype_t vt = v->get_valuetype(); | |
2312 | if (vt == Value::V_ENUM || vt == Value::V_REFD) { | |
2313 | Free(rawpar->presence.keyList[a].value); | |
2314 | rawpar->presence.keyList[a].value = | |
2315 | mcopystr(v->get_single_expr().c_str()); | |
2316 | } | |
2317 | } | |
2318 | } | |
2319 | for(int c=0;c<rawpar->crosstaglist.nElements;c++) { // CROSSTAG | |
2320 | Identifier *idf=rawpar->crosstaglist.tag[c].fieldName; | |
2321 | if(!field_type_last->is_secho()){ | |
2322 | error("Invalid fieldmember type in RAW parameter CROSSTAG" | |
2323 | " for field %s." | |
2324 | ,field_id.get_dispname().c_str()); | |
2325 | break; | |
2326 | } | |
2327 | if(!field_type_last->has_comp_withName(*idf)){ | |
2328 | error("Invalid fieldmember name in RAW parameter CROSSTAG" | |
2329 | " for field %s: %s" | |
2330 | ,field_id.get_dispname().c_str() | |
2331 | ,rawpar->crosstaglist.tag[c].fieldName | |
2332 | ->get_dispname().c_str()); | |
2333 | break; | |
2334 | } | |
2335 | for(int a=0;a<rawpar->crosstaglist.tag[c].nElements;a++){ | |
2336 | Type *t2=this; | |
2337 | bool hiba=false; | |
2338 | bool allow_omit = false; | |
2339 | for(int b=0; | |
2340 | b<rawpar->crosstaglist.tag[c].keyList[a].keyField->nElements;b++){ | |
2341 | Identifier *idf2= | |
2342 | rawpar->crosstaglist.tag[c].keyList[a].keyField->names[b]; | |
2343 | if(!t2->is_secho()){ | |
2344 | error("Invalid fieldmember type in RAW parameter CROSSTAG" | |
2345 | " for field %s." | |
2346 | ,field_id.get_dispname().c_str()); | |
2347 | hiba=true; | |
2348 | break; | |
2349 | } | |
2350 | if(!t2->has_comp_withName(*idf2)){ | |
2351 | error("Invalid fieldname in RAW parameter CROSSTAG" | |
2352 | " for field %s: %s" | |
2353 | ,field_id.get_dispname().c_str() | |
2354 | ,idf2->get_dispname().c_str()); | |
2355 | hiba=true; | |
2356 | break; | |
2357 | } | |
2358 | if (b == 0) { | |
2359 | size_t field_idx = get_comp_index_byName(*idf2); | |
2360 | if (field_idx == i) { | |
2361 | error("RAW parameter CROSSTAG for field `%s' cannot refer " | |
2362 | "to the field itself", idf2->get_dispname().c_str()); | |
2363 | } else if (field_idx > i) { | |
2364 | if (cf->get_is_optional() || | |
2365 | field_type->get_raw_length() < 0) | |
2366 | error("Field `%s' that CROSSTAG refers to must precede " | |
2367 | "field `%s' or field `%s' must be mandatory with " | |
2368 | "fixed length", idf2->get_dispname().c_str(), | |
2369 | field_id.get_dispname().c_str(), | |
2370 | field_id.get_dispname().c_str()); | |
2371 | } | |
2372 | } | |
2373 | CompField *cf2=t2->get_comp_byName(*idf2); | |
2374 | t2=cf2->get_type()->get_type_refd_last(); | |
2375 | if (b == rawpar->crosstaglist.tag[c].keyList[a].keyField | |
2376 | ->nElements - 1 && cf2->get_is_optional()) | |
2377 | allow_omit = true; | |
2378 | } | |
2379 | if(!hiba){ | |
2380 | Error_Context cntx(this, "In Raw parmeter CROSSTAG"); | |
2381 | Value *v = rawpar->crosstaglist.tag[c].keyList[a].v_value; | |
2382 | v->set_my_scope(get_my_scope()); | |
2383 | v->set_my_governor(t2); | |
2384 | t2->chk_this_value_ref(v); | |
2385 | self_ref = t2->chk_this_value(v, 0, EXPECTED_CONSTANT, | |
2386 | INCOMPLETE_NOT_ALLOWED, | |
2387 | (allow_omit ? OMIT_ALLOWED : OMIT_NOT_ALLOWED), SUB_CHK); | |
2388 | Value::valuetype_t vt = v->get_valuetype(); | |
2389 | if (vt == Value::V_ENUM || vt == Value::V_REFD) { | |
2390 | Free(rawpar->crosstaglist.tag[c].keyList[a].value); | |
2391 | rawpar->crosstaglist.tag[c].keyList[a].value = | |
2392 | mcopystr(v->get_single_expr().c_str()); | |
2393 | } | |
2394 | } | |
2395 | } | |
2396 | } | |
2397 | } | |
2398 | } | |
2399 | break; | |
2400 | case T_BSTR: | |
2401 | if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ | |
2402 | rawattrib->fieldlength=rawattrib->length_restrition; | |
2403 | rawattrib->length_restrition=-1; | |
2404 | } | |
2405 | break; | |
2406 | case T_HSTR: | |
2407 | if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ | |
2408 | rawattrib->fieldlength=rawattrib->length_restrition*4; | |
2409 | rawattrib->length_restrition=-1; | |
2410 | } | |
2411 | break; | |
2412 | case T_OSTR: | |
2413 | if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ | |
2414 | rawattrib->fieldlength=rawattrib->length_restrition*8; | |
2415 | rawattrib->length_restrition=-1; | |
2416 | } | |
2417 | break; | |
2418 | case T_CSTR: | |
2419 | if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ | |
2420 | rawattrib->fieldlength=rawattrib->length_restrition*8; | |
2421 | rawattrib->length_restrition=-1; | |
2422 | } | |
2423 | break; | |
2424 | case T_SEQOF: | |
2425 | case T_SETOF: | |
2426 | get_ofType()->force_raw(); | |
2427 | if(rawattrib->fieldlength==0 && rawattrib->length_restrition!=-1){ | |
2428 | rawattrib->fieldlength=rawattrib->length_restrition; | |
2429 | rawattrib->length_restrition=-1; | |
2430 | } | |
2431 | if(rawattrib->length_restrition!=-1 && | |
2432 | rawattrib->length_restrition!=rawattrib->fieldlength){ | |
2433 | error("Invalid length specified in parameter FIELDLENGTH for %s of " | |
2434 | "type `%s'. The FIELDLENGTH must be equal to specified length " | |
2435 | "restriction", typetype == T_SEQOF ? "record" : "set", | |
2436 | get_fullname().c_str()); | |
2437 | } | |
2438 | break; | |
2439 | case T_REAL: | |
2440 | if(rawattrib->fieldlength!=64 && rawattrib->fieldlength!=32){ | |
2441 | error("Invalid length (%d) specified in parameter FIELDLENGTH for " | |
2442 | "float type `%s'. The FIELDLENGTH must be single (32) or double " | |
2443 | "(64)", rawattrib->fieldlength, get_fullname().c_str()); | |
2444 | } | |
2445 | break; | |
2446 | case T_ENUM_T: | |
2447 | case T_INT: | |
2448 | case T_BOOL: | |
2449 | default: | |
2450 | // nothing to do, ASN1 types or types without defined raw attribute | |
2451 | break; | |
2452 | } // switch | |
2453 | ||
2454 | (void)self_ref; | |
2455 | } | |
2456 | ||
2457 | void Type::force_raw() | |
2458 | { | |
2459 | if (!rawattrib) | |
2460 | { | |
2461 | switch (typetype) { | |
2462 | case T_SEQOF: | |
2463 | case T_SETOF: | |
2464 | case T_CHOICE_T: | |
2465 | // TODO case T_ANYTYPE: for force_raw ? | |
2466 | case T_ENUM_T: | |
2467 | case T_SEQ_T: | |
2468 | case T_SET_T: | |
2469 | rawattrib = new RawAST(false); | |
2470 | break; | |
2471 | default: | |
2472 | if (is_ref()) get_type_refd()->force_raw(); | |
2473 | break; | |
2474 | } | |
2475 | } | |
2476 | ||
2477 | // Don't run chk_raw() on unchecked types | |
2478 | if (chk_finished) | |
2479 | chk_raw(); | |
2480 | } | |
2481 | ||
2482 | void Type::chk_text() | |
2483 | { | |
2484 | if (text_checked) return; | |
2485 | text_checked = true; | |
2486 | if (!textattrib || !enable_text()) return; | |
2487 | //textattrib->print_TextAST(); | |
2488 | ||
2489 | chk_text_matching_values(textattrib->begin_val, "BEGIN"); | |
2490 | chk_text_matching_values(textattrib->end_val, "END"); | |
2491 | chk_text_matching_values(textattrib->separator_val, "SEPARATOR"); | |
2492 | ||
2493 | switch (typetype) { | |
2494 | case T_ANYTYPE: | |
2495 | case T_CHOICE_T: | |
2496 | case T_SEQ_T: | |
2497 | case T_SET_T: { | |
2498 | size_t nof_comps = get_nof_comps(); | |
2499 | for (size_t i = 0; i < nof_comps; i++) | |
2500 | get_comp_byIndex(i)->get_type()->force_text(); | |
2501 | break; } | |
2502 | case T_SEQOF: | |
2503 | case T_SETOF: | |
2504 | get_ofType()->force_text(); | |
2505 | break; | |
2506 | default: | |
2507 | if (is_ref()) get_type_refd()->force_text(); | |
2508 | break; | |
2509 | } | |
2510 | ||
2511 | switch (get_type_refd_last()->typetype) { | |
2512 | case T_BOOL: | |
2513 | chk_text_matching_values(textattrib->true_params, "true value"); | |
2514 | chk_text_matching_values(textattrib->false_params, "false value"); | |
2515 | break; | |
2516 | case T_ENUM_T: | |
2517 | if(textattrib->nof_field_params){ | |
2518 | Type *t=get_type_refd_last(); | |
2519 | size_t nof_comps = t->u.enums.eis->get_nof_eis(); | |
2520 | textAST_enum_def **params=(textAST_enum_def**) | |
2521 | Malloc(nof_comps*sizeof(textAST_enum_def*)); | |
2522 | memset(params,0,nof_comps*sizeof(textAST_enum_def*)); | |
2523 | for (int a = 0; a < textattrib->nof_field_params; a++) { | |
2524 | const Identifier& id = *textattrib->field_params[a]->name; | |
2525 | if (t->u.enums.eis->has_ei_withName(id)) { | |
2526 | int index = t->get_eis_index_byName(id); | |
2527 | if (params[index]) FATAL_ERROR("Type::chk_text(): duplicate " \ | |
2528 | "attribute for enum `%s'", id.get_dispname().c_str()); | |
2529 | params[index] = textattrib->field_params[a]; | |
2530 | char *attrib_name = mprintf("enumerated value `%s'", | |
2531 | id.get_dispname().c_str()); | |
2532 | chk_text_matching_values(¶ms[index]->value, attrib_name); | |
2533 | Free(attrib_name); | |
2534 | } else { | |
2535 | error("Coding attribute refers to non-existent enumerated value " | |
2536 | "`%s'", id.get_dispname().c_str()); | |
2537 | Free(textattrib->field_params[a]->value.encode_token); | |
2538 | Free(textattrib->field_params[a]->value.decode_token); | |
2539 | delete textattrib->field_params[a]->name; | |
2540 | Free(textattrib->field_params[a]); | |
2541 | } | |
2542 | } | |
2543 | Free(textattrib->field_params); | |
2544 | textattrib->field_params=params; | |
2545 | textattrib->nof_field_params=nof_comps; | |
2546 | } | |
2547 | break; | |
2548 | case T_OSTR: | |
2549 | case T_CSTR: | |
2550 | case T_INT: | |
2551 | if (textattrib->decode_token) { | |
2552 | char *tmp = textattrib->decode_token; | |
2553 | textattrib->decode_token = process_decode_token(tmp, *this); | |
2554 | Free(tmp); | |
2555 | tmp = TTCN_pattern_to_regexp(textattrib->decode_token); | |
2556 | if (tmp) Free(tmp); | |
2557 | else { | |
2558 | error("Incorrect select token expression: `%s'", | |
2559 | textattrib->decode_token); | |
2560 | } | |
2561 | } | |
2562 | break; | |
2563 | default: | |
2564 | break; | |
2565 | } | |
2566 | //textattrib->print_TextAST(); | |
2567 | } | |
2568 | ||
2569 | void Type::chk_text_matching_values(textAST_matching_values *matching_values, | |
2570 | const char *attrib_name) | |
2571 | { | |
2572 | if (!matching_values) return; | |
2573 | if (matching_values->decode_token) { | |
2574 | // check whether decode token is a correct TTCN-3 pattern | |
2575 | char *tmp = matching_values->decode_token; | |
2576 | matching_values->decode_token = process_decode_token(tmp, *this); | |
2577 | Free(tmp); | |
2578 | tmp = TTCN_pattern_to_regexp(matching_values->decode_token); | |
2579 | if (tmp) Free(tmp); | |
2580 | else { | |
2581 | error("Incorrect matching expression for %s: `%s'", attrib_name, | |
2582 | matching_values->decode_token); | |
2583 | } | |
2584 | } else if (matching_values->encode_token) { | |
2585 | // the decode token is not present, but there is an encode token | |
2586 | // derive the decode token from the encode token | |
2587 | matching_values->generated_decode_token = true; | |
2588 | matching_values->decode_token = | |
2589 | convert_charstring_to_pattern(matching_values->encode_token); | |
2590 | } | |
2591 | } | |
2592 | ||
2593 | void Type::force_text() | |
2594 | { | |
2595 | if (!textattrib) | |
2596 | { | |
2597 | switch (typetype) { | |
2598 | case T_SEQOF: | |
2599 | case T_SETOF: | |
2600 | case T_CHOICE_T: | |
2601 | // TODO case T_ANYTYPE: for force_text ? | |
2602 | case T_ENUM_T: | |
2603 | case T_SEQ_T: | |
2604 | case T_SET_T: | |
2605 | textattrib = new TextAST; | |
2606 | break; | |
2607 | default: | |
2608 | if (is_ref()) get_type_refd()->force_text(); | |
2609 | break; | |
2610 | } | |
2611 | } | |
2612 | if (chk_finished) | |
2613 | chk_text(); | |
2614 | } | |
2615 | ||
2616 | void Type::chk_json() | |
2617 | { | |
2618 | if (json_checked) return; | |
2619 | json_checked = true; | |
2620 | if ((NULL == jsonattrib && !hasEncodeAttr(CT_JSON)) || !enable_json()) return; | |
2621 | ||
2622 | switch (typetype) { | |
2623 | case T_ANYTYPE: | |
2624 | case T_CHOICE_T: | |
2625 | case T_CHOICE_A: | |
2626 | case T_SEQ_T: | |
2627 | case T_SEQ_A: | |
2628 | case T_SET_T: | |
2629 | case T_SET_A: { | |
2630 | size_t nof_comps = get_nof_comps(); | |
2631 | for (size_t i = 0; i < nof_comps; i++) | |
2632 | get_comp_byIndex(i)->get_type()->force_json(); | |
2633 | break; } | |
2634 | case T_SEQOF: | |
2635 | case T_SETOF: | |
2636 | get_ofType()->force_json(); | |
2637 | break; | |
2638 | default: | |
2639 | if (is_ref()) get_type_refd()->force_json(); | |
2640 | break; | |
2641 | } | |
2642 | ||
2643 | if (NULL != jsonattrib) { | |
2644 | if (jsonattrib->omit_as_null && !is_optional_field()) { | |
2645 | error("Invalid attribute, 'omit as null' requires optional " | |
2646 | "field of a record or set."); | |
2647 | } | |
2648 | ||
2649 | if (jsonattrib->as_value && T_CHOICE_T != get_type_refd_last()->typetype) { | |
2650 | error("Invalid attribute, 'as value' is only allowed for unions"); | |
2651 | } | |
2652 | ||
2653 | if (NULL != jsonattrib->alias) { | |
2654 | Type* parent = get_parent_type(); | |
2655 | if (NULL == parent || (T_SEQ_T != parent->typetype && | |
2656 | T_SET_T != parent->typetype && T_CHOICE_T != parent->typetype)) { | |
2657 | error("Invalid attribute, 'name as ...' requires field of a " | |
2658 | "record, set or union."); | |
2659 | } | |
2660 | if (NULL != parent && NULL != parent->jsonattrib && | |
2661 | T_CHOICE_T == parent->typetype && parent->jsonattrib->as_value) { | |
2662 | warning("Attribute 'name as ...' will be ignored, because parent union " | |
2663 | "is encoded without field names."); | |
2664 | } | |
2665 | } | |
2666 | ||
2667 | if (NULL != jsonattrib->default_value) { | |
2668 | chk_json_default(); | |
2669 | } | |
2670 | } | |
2671 | } | |
2672 | ||
2673 | void Type::chk_json_default() | |
2674 | { | |
2675 | const char* dval = jsonattrib->default_value; | |
2676 | const size_t dval_len = strlen(dval); | |
2677 | Type *last = get_type_refd_last(); | |
2678 | bool err = false; | |
2679 | switch (last->typetype) { | |
2680 | case T_BOOL: | |
2681 | if (strcmp(dval, "true") != 0 && strcmp(dval, "false") != 0) { | |
2682 | err = true; | |
2683 | } | |
2684 | break; | |
2685 | case T_INT: | |
2686 | for (size_t i = (dval[0] == '-') ? 1 : 0; i < dval_len; ++i) { | |
2687 | if (dval[i] < '0' || dval[i] > '9') { | |
2688 | err = true; | |
2689 | break; // from the loop | |
2690 | } | |
2691 | } | |
2692 | break; | |
2693 | case T_REAL: { | |
2694 | if (strcmp(dval, "infinity") == 0 || strcmp(dval, "-infinity") == 0 || | |
2695 | strcmp(dval, "not_a_number") == 0) { | |
2696 | // special float values => skip the rest of the check | |
2697 | break; | |
2698 | } | |
2699 | ||
2700 | boolean first_digit = false; // first non-zero digit reached | |
2701 | boolean zero = false; // first zero digit reached | |
2702 | boolean decimal_point = false; // decimal point (.) reached | |
2703 | boolean exponent_mark = false; // exponential mark (e or E) reached | |
2704 | boolean exponent_sign = false; // sign of the exponential (- or +) reached | |
2705 | ||
2706 | size_t i = (dval[0] == '-') ? 1 : 0; | |
2707 | while(!err && i < dval_len) { | |
2708 | switch (dval[i]) { | |
2709 | case '.': | |
2710 | if (decimal_point || exponent_mark || (!first_digit && !zero)) { | |
2711 | err = true; | |
2712 | } | |
2713 | decimal_point = true; | |
2714 | first_digit = false; | |
2715 | zero = false; | |
2716 | break; | |
2717 | case 'e': | |
2718 | case 'E': | |
2719 | if (exponent_mark || (!first_digit && !zero)) { | |
2720 | err = true; | |
2721 | } | |
2722 | exponent_mark = true; | |
2723 | first_digit = false; | |
2724 | zero = false; | |
2725 | break; | |
2726 | case '0': | |
2727 | if (!first_digit && (exponent_mark || (!decimal_point && zero))) { | |
2728 | err = true; | |
2729 | } | |
2730 | zero = true; | |
2731 | break; | |
2732 | case '1': | |
2733 | case '2': | |
2734 | case '3': | |
2735 | case '4': | |
2736 | case '5': | |
2737 | case '6': | |
2738 | case '7': | |
2739 | case '8': | |
2740 | case '9': | |
2741 | if (!first_digit && zero && (!decimal_point || exponent_mark)) { | |
2742 | err = true; | |
2743 | } | |
2744 | first_digit = true; | |
2745 | break; | |
2746 | case '-': | |
2747 | case '+': | |
2748 | if (exponent_sign || !exponent_mark || zero || first_digit) { | |
2749 | err = true; | |
2750 | } | |
2751 | exponent_sign = true; | |
2752 | break; | |
2753 | default: | |
2754 | err = true; | |
2755 | } | |
2756 | ++i; | |
2757 | } | |
2758 | err = !first_digit && !zero; | |
2759 | break; } | |
2760 | case T_BSTR: | |
2761 | for (size_t i = 0; i < dval_len; ++i) { | |
2762 | if (dval[i] < '0' || dval[i] > '1') { | |
2763 | err = true; | |
2764 | break; // from the loop | |
2765 | } | |
2766 | } | |
2767 | break; | |
2768 | case T_OSTR: | |
2769 | if (dval_len % 2 != 0) { | |
2770 | err = true; | |
2771 | break; | |
2772 | } | |
2773 | // no break | |
2774 | case T_HSTR: | |
2775 | for (size_t i = 0; i < dval_len; ++i) { | |
2776 | if ((dval[i] < '0' || dval[i] > '9') && (dval[i] < 'a' || dval[i] > 'f') && | |
2777 | (dval[i] < 'A' || dval[i] > 'F')) { | |
2778 | err = true; | |
2779 | break; // from the loop | |
2780 | } | |
2781 | } | |
2782 | break; | |
2783 | case T_CSTR: | |
2784 | case T_USTR: { | |
2785 | size_t i = 0; | |
2786 | while(!err && i < dval_len) { | |
2787 | if (dval[i] < 0 && last->typetype == T_CSTR) { | |
2788 | err = true; | |
2789 | } | |
2790 | else if (dval[i] == '\\') { | |
2791 | if (i == dval_len - 1) { | |
2792 | err = true; | |
2793 | } else { | |
2794 | ++i; | |
2795 | switch (dval[i]) { | |
2796 | case '\\': | |
2797 | case '\"': | |
2798 | case 'n': | |
2799 | case 't': | |
2800 | case 'r': | |
2801 | case 'f': | |
2802 | case 'b': | |
2803 | case '/': | |
2804 | break; // these are OK | |
2805 | case 'u': { | |
2806 | if (i + 4 >= dval_len) { | |
2807 | err = true; | |
2808 | } else if (last->typetype == T_CSTR && | |
2809 | (dval[i + 1] != '0' || dval[i + 2] != '0' || | |
2810 | dval[i + 3] < '0' || dval[i + 3] > '7')) { | |
2811 | err = true; | |
2812 | } else { | |
2813 | for (size_t j = (last->typetype == T_CSTR) ? 4 : 1; j <= 4; ++j) { | |
2814 | if ((dval[i + j] < '0' || dval[i + j] > '9') && | |
2815 | (dval[i + j] < 'a' || dval[i + j] > 'f') && | |
2816 | (dval[i + j] < 'A' || dval[i + j] > 'F')) { | |
2817 | err = true; | |
2818 | break; // from the loop | |
2819 | } | |
2820 | } | |
2821 | } | |
2822 | i += 4; | |
2823 | break; } | |
2824 | default: | |
2825 | err = true; | |
2826 | break; | |
2827 | } | |
2828 | } | |
2829 | } | |
2830 | ++i; | |
2831 | } | |
2832 | break; } | |
2833 | case T_ENUM_T: { | |
2834 | Common::Identifier id(Identifier::ID_TTCN, string(dval)); | |
2835 | if (!last->has_ei_withName(id)) { | |
2836 | err = true; | |
2837 | } | |
2838 | break; } | |
2839 | case T_VERDICT: | |
2840 | if (strcmp(dval, "none") != 0 && strcmp(dval, "pass") != 0 && | |
2841 | strcmp(dval, "inconc") != 0 && strcmp(dval, "fail") != 0 && | |
2842 | strcmp(dval, "error") != 0) { | |
2843 | err = true; | |
2844 | } | |
2845 | break; | |
2846 | default: | |
2847 | error("JSON default values are not available for type `%s'", | |
2848 | last->get_stringRepr().c_str()); | |
2849 | return; | |
2850 | } | |
2851 | ||
2852 | if (err) { | |
2853 | if (last->typetype == T_ENUM_T) { | |
2854 | error("Invalid JSON default value for enumerated type `%s'", | |
2855 | last->get_stringRepr().c_str()); | |
2856 | } else { | |
2857 | error("Invalid %s JSON default value", get_typename_builtin(last->typetype)); | |
2858 | } | |
2859 | } | |
2860 | } | |
2861 | ||
2862 | void Type::force_json() | |
2863 | { | |
2864 | if (!jsonattrib) | |
2865 | { | |
2866 | switch (typetype) { | |
2867 | case T_SEQOF: | |
2868 | case T_SETOF: | |
2869 | case T_CHOICE_T: | |
2870 | case T_CHOICE_A: | |
2871 | case T_ENUM_T: | |
2872 | case T_ENUM_A: | |
2873 | case T_SEQ_T: | |
2874 | case T_SEQ_A: | |
2875 | case T_SET_T: | |
2876 | case T_SET_A: | |
2877 | jsonattrib = new JsonAST; | |
2878 | break; | |
2879 | default: | |
2880 | if (is_ref()) get_type_refd()->force_json(); | |
2881 | break; | |
2882 | } | |
2883 | } | |
2884 | if (chk_finished) | |
2885 | chk_json(); | |
2886 | } | |
2887 | ||
2888 | ||
2889 | int Type::get_length_multiplier() | |
2890 | { | |
2891 | switch(typetype) { | |
2892 | case T_REFD: | |
2893 | return get_type_refd()->get_length_multiplier(); | |
2894 | break; | |
2895 | case T_HSTR: | |
2896 | return 4; | |
2897 | break; | |
2898 | case T_OSTR: | |
2899 | case T_CSTR: | |
2900 | return 8; | |
2901 | default: | |
2902 | return 1; | |
2903 | break; | |
2904 | } | |
2905 | return 1; | |
2906 | } | |
2907 | ||
2908 | /** \todo review, especially the string types... */ | |
2909 | bool Type::is_compatible_tt_tt(typetype_t p_tt1, typetype_t p_tt2, | |
2910 | bool p_is_asn11, bool p_is_asn12) | |
2911 | { | |
2912 | if (p_tt2 == T_ERROR) return true; | |
2913 | switch (p_tt1) { | |
2914 | // error type is compatible with everything | |
2915 | case T_ERROR: | |
2916 | return true; | |
2917 | // unambiguous built-in types | |
2918 | case T_NULL: | |
2919 | case T_BOOL: | |
2920 | case T_REAL: | |
2921 | case T_HSTR: | |
2922 | case T_SEQOF: | |
2923 | case T_SETOF: | |
2924 | case T_VERDICT: | |
2925 | case T_DEFAULT: | |
2926 | case T_COMPONENT: | |
2927 | case T_SIGNATURE: | |
2928 | case T_PORT: | |
2929 | case T_ARRAY: | |
2930 | case T_FUNCTION: | |
2931 | case T_ALTSTEP: | |
2932 | case T_TESTCASE: | |
2933 | return p_tt1 == p_tt2; | |
2934 | case T_OSTR: | |
2935 | return p_tt2==T_OSTR || (!p_is_asn11 && p_tt2==T_ANY); | |
2936 | case T_USTR: | |
2937 | switch (p_tt2) { | |
2938 | case T_USTR: | |
2939 | case T_UTF8STRING: | |
2940 | case T_BMPSTRING: | |
2941 | case T_UNIVERSALSTRING: | |
2942 | case T_TELETEXSTRING: | |
2943 | case T_VIDEOTEXSTRING: | |
2944 | case T_GRAPHICSTRING: | |
2945 | case T_OBJECTDESCRIPTOR: | |
2946 | case T_GENERALSTRING: | |
2947 | case T_CSTR: | |
2948 | case T_NUMERICSTRING: | |
2949 | case T_PRINTABLESTRING: | |
2950 | case T_IA5STRING: | |
2951 | case T_VISIBLESTRING: | |
2952 | case T_UTCTIME: | |
2953 | case T_GENERALIZEDTIME: | |
2954 | return true; | |
2955 | default: | |
2956 | return false; | |
2957 | } | |
2958 | // character string group 1 | |
2959 | case T_UTF8STRING: | |
2960 | case T_BMPSTRING: | |
2961 | case T_UNIVERSALSTRING: | |
2962 | switch (p_tt2) { | |
2963 | case T_USTR: | |
2964 | case T_UTF8STRING: | |
2965 | case T_BMPSTRING: | |
2966 | case T_UNIVERSALSTRING: | |
2967 | case T_CSTR: | |
2968 | case T_NUMERICSTRING: | |
2969 | case T_PRINTABLESTRING: | |
2970 | case T_IA5STRING: | |
2971 | case T_VISIBLESTRING: | |
2972 | case T_UTCTIME: | |
2973 | case T_GENERALIZEDTIME: | |
2974 | return true; | |
2975 | default: | |
2976 | return false; | |
2977 | } | |
2978 | // character string group 2 | |
2979 | case T_TELETEXSTRING: | |
2980 | case T_VIDEOTEXSTRING: | |
2981 | case T_GRAPHICSTRING: | |
2982 | case T_OBJECTDESCRIPTOR: | |
2983 | case T_GENERALSTRING: | |
2984 | switch (p_tt2) { | |
2985 | case T_TELETEXSTRING: | |
2986 | case T_VIDEOTEXSTRING: | |
2987 | case T_GRAPHICSTRING: | |
2988 | case T_OBJECTDESCRIPTOR: | |
2989 | case T_GENERALSTRING: | |
2990 | case T_CSTR: | |
2991 | case T_NUMERICSTRING: | |
2992 | case T_PRINTABLESTRING: | |
2993 | case T_IA5STRING: | |
2994 | case T_VISIBLESTRING: | |
2995 | case T_UTCTIME: | |
2996 | case T_GENERALIZEDTIME: | |
2997 | return true; | |
2998 | case T_USTR: | |
2999 | // maybe :) is ustr.is_cstr() | |
3000 | return true; | |
3001 | default: | |
3002 | return false; | |
3003 | } | |
3004 | // character string group 3 | |
3005 | case T_CSTR: | |
3006 | case T_NUMERICSTRING: | |
3007 | case T_PRINTABLESTRING: | |
3008 | case T_IA5STRING: | |
3009 | case T_VISIBLESTRING: | |
3010 | case T_UTCTIME: | |
3011 | case T_GENERALIZEDTIME: | |
3012 | switch (p_tt2) { | |
3013 | case T_CSTR: | |
3014 | case T_NUMERICSTRING: | |
3015 | case T_PRINTABLESTRING: | |
3016 | case T_IA5STRING: | |
3017 | case T_VISIBLESTRING: | |
3018 | case T_UTCTIME: | |
3019 | case T_GENERALIZEDTIME: | |
3020 | return true; | |
3021 | default: | |
3022 | return false; | |
3023 | } | |
3024 | // polymorphic built-in types | |
3025 | case T_BSTR: | |
3026 | case T_BSTR_A: | |
3027 | return p_tt2 == T_BSTR || p_tt2 == T_BSTR_A; | |
3028 | case T_INT: | |
3029 | case T_INT_A: | |
3030 | return p_tt2 == T_INT || p_tt2 == T_INT_A; | |
3031 | // ROID is visible as OID from TTCN-3 | |
3032 | case T_OID: | |
3033 | return p_tt2 == T_OID || | |
3034 | (!p_is_asn11 && p_tt2 == T_ROID); | |
3035 | case T_ROID: | |
3036 | return p_tt2 == T_ROID || | |
3037 | (!p_is_asn12 && p_tt2 == T_OID); | |
3038 | case T_ENUM_A: | |
3039 | case T_ENUM_T: | |
3040 | return p_tt2==T_ENUM_A || p_tt2==T_ENUM_T; | |
3041 | case T_CHOICE_T: | |
3042 | case T_CHOICE_A: | |
3043 | case T_OPENTYPE: | |
3044 | return p_tt2==T_CHOICE_T || p_tt2==T_CHOICE_A || p_tt2==T_OPENTYPE; | |
3045 | case T_SEQ_A: | |
3046 | case T_SEQ_T: | |
3047 | return p_tt2==T_SEQ_A || p_tt2==T_SEQ_T; | |
3048 | case T_SET_A: | |
3049 | case T_SET_T: | |
3050 | return p_tt2==T_SET_A || p_tt2==T_SET_T; | |
3051 | case T_ANY: | |
3052 | return p_tt2 == T_ANY || p_tt2 == T_OSTR; | |
3053 | // these should never appear? | |
3054 | case T_REFD: | |
3055 | case T_REFDSPEC: | |
3056 | case T_OCFT: | |
3057 | case T_ADDRESS: | |
3058 | return false; | |
3059 | default: | |
3060 | FATAL_ERROR("Type::is_compatible_tt_tt()"); | |
3061 | return false; | |
3062 | } | |
3063 | } | |
3064 | ||
3065 | bool Type::is_compatible_tt(typetype_t p_tt, bool p_is_asn1) | |
3066 | { | |
3067 | chk(); | |
3068 | Type *t1=get_type_refd_last(); | |
3069 | if (p_tt == T_ERROR) return true; | |
3070 | switch (t1->typetype) { | |
3071 | // these should never appear | |
3072 | case T_REFD: | |
3073 | case T_REFDSPEC: | |
3074 | case T_OCFT: | |
3075 | case T_ADDRESS: | |
3076 | FATAL_ERROR("Type::is_compatible_tt()"); | |
3077 | return false; | |
3078 | default: | |
3079 | return is_compatible_tt_tt(t1->typetype, p_tt, is_asn1(), p_is_asn1); | |
3080 | } | |
3081 | } | |
3082 | ||
3083 | bool Type::is_compatible(Type *p_type, TypeCompatInfo *p_info, | |
3084 | TypeChain *p_left_chain, TypeChain *p_right_chain) | |
3085 | { | |
3086 | chk(); | |
3087 | p_type->chk(); | |
3088 | Type *t1 = get_type_refd_last(); | |
3089 | Type *t2 = p_type->get_type_refd_last(); | |
3090 | // Error type is compatible with everything. | |
3091 | if (t1->typetype == T_ERROR || t2->typetype == T_ERROR) return true; | |
3092 | bool is_type_comp; | |
3093 | switch (t1->typetype) { | |
3094 | // Unambiguous built-in types. | |
3095 | case T_NULL: | |
3096 | case T_BOOL: | |
3097 | case T_REAL: | |
3098 | case T_HSTR: | |
3099 | case T_VERDICT: | |
3100 | case T_DEFAULT: | |
3101 | is_type_comp = (t1->typetype == t2->typetype); | |
3102 | break; | |
3103 | case T_OSTR: | |
3104 | is_type_comp = ( t2->typetype==T_OSTR || (!is_asn1() && t2->typetype==T_ANY) ); | |
3105 | break; | |
3106 | case T_USTR: | |
3107 | switch (t2->typetype) { | |
3108 | case T_USTR: | |
3109 | case T_UTF8STRING: | |
3110 | case T_BMPSTRING: | |
3111 | case T_UNIVERSALSTRING: | |
3112 | case T_TELETEXSTRING: | |
3113 | case T_VIDEOTEXSTRING: | |
3114 | case T_GRAPHICSTRING: | |
3115 | case T_OBJECTDESCRIPTOR: | |
3116 | case T_GENERALSTRING: | |
3117 | case T_CSTR: | |
3118 | case T_NUMERICSTRING: | |
3119 | case T_PRINTABLESTRING: | |
3120 | case T_IA5STRING: | |
3121 | case T_VISIBLESTRING: | |
3122 | case T_UTCTIME: | |
3123 | case T_GENERALIZEDTIME: | |
3124 | is_type_comp = true; | |
3125 | break; | |
3126 | default: | |
3127 | is_type_comp = false; | |
3128 | break; | |
3129 | } | |
3130 | break; | |
3131 | // Character string group 1. | |
3132 | case T_UTF8STRING: | |
3133 | case T_BMPSTRING: | |
3134 | case T_UNIVERSALSTRING: | |
3135 | switch (t2->typetype) { | |
3136 | case T_USTR: | |
3137 | case T_UTF8STRING: | |
3138 | case T_BMPSTRING: | |
3139 | case T_UNIVERSALSTRING: | |
3140 | case T_CSTR: | |
3141 | case T_NUMERICSTRING: | |
3142 | case T_PRINTABLESTRING: | |
3143 | case T_IA5STRING: | |
3144 | case T_VISIBLESTRING: | |
3145 | case T_UTCTIME: | |
3146 | case T_GENERALIZEDTIME: | |
3147 | is_type_comp = true; | |
3148 | break; | |
3149 | default: | |
3150 | is_type_comp = false; | |
3151 | break; | |
3152 | } | |
3153 | break; | |
3154 | // Character string group 2. | |
3155 | case T_TELETEXSTRING: | |
3156 | case T_VIDEOTEXSTRING: | |
3157 | case T_GRAPHICSTRING: | |
3158 | case T_OBJECTDESCRIPTOR: | |
3159 | case T_GENERALSTRING: | |
3160 | switch (t2->typetype) { | |
3161 | case T_TELETEXSTRING: | |
3162 | case T_VIDEOTEXSTRING: | |
3163 | case T_GRAPHICSTRING: | |
3164 | case T_OBJECTDESCRIPTOR: | |
3165 | case T_GENERALSTRING: | |
3166 | case T_CSTR: | |
3167 | case T_NUMERICSTRING: | |
3168 | case T_PRINTABLESTRING: | |
3169 | case T_IA5STRING: | |
3170 | case T_VISIBLESTRING: | |
3171 | case T_UTCTIME: | |
3172 | case T_GENERALIZEDTIME: | |
3173 | is_type_comp = true; | |
3174 | break; | |
3175 | case T_USTR: | |
3176 | // Maybe :) is ustr.is_cstr(). | |
3177 | is_type_comp = true; | |
3178 | break; | |
3179 | default: | |
3180 | is_type_comp = false; | |
3181 | break; | |
3182 | } | |
3183 | break; | |
3184 | // Character string group 3. | |
3185 | case T_CSTR: | |
3186 | case T_NUMERICSTRING: | |
3187 | case T_PRINTABLESTRING: | |
3188 | case T_IA5STRING: | |
3189 | case T_VISIBLESTRING: | |
3190 | case T_UTCTIME: | |
3191 | case T_GENERALIZEDTIME: | |
3192 | switch (t2->typetype) { | |
3193 | case T_CSTR: | |
3194 | case T_NUMERICSTRING: | |
3195 | case T_PRINTABLESTRING: | |
3196 | case T_IA5STRING: | |
3197 | case T_VISIBLESTRING: | |
3198 | case T_UTCTIME: | |
3199 | case T_GENERALIZEDTIME: | |
3200 | is_type_comp = true; | |
3201 | break; | |
3202 | default: | |
3203 | is_type_comp = false; | |
3204 | break; | |
3205 | } | |
3206 | break; | |
3207 | // Polymorphic built-in types. | |
3208 | case T_BSTR: | |
3209 | case T_BSTR_A: | |
3210 | is_type_comp = ( t2->typetype == T_BSTR || t2->typetype == T_BSTR_A ); | |
3211 | break; | |
3212 | case T_INT: | |
3213 | case T_INT_A: | |
3214 | is_type_comp = ( t2->typetype == T_INT || t2->typetype == T_INT_A ); | |
3215 | break; | |
3216 | // ROID is visible as OID from TTCN-3. | |
3217 | case T_OID: | |
3218 | is_type_comp = ( t2->typetype == T_OID || (!is_asn1() && t2->typetype == T_ROID) ); | |
3219 | break; | |
3220 | case T_ROID: | |
3221 | is_type_comp = ( t2->typetype == T_ROID || (!p_type->is_asn1() && t2->typetype == T_OID) ); | |
3222 | break; | |
3223 | case T_COMPONENT: | |
3224 | is_type_comp = ( t2->typetype == T_COMPONENT && t1->u.component->is_compatible(t2->u.component) ); | |
3225 | break; | |
3226 | case T_SEQ_A: | |
3227 | case T_SEQ_T: | |
3228 | is_type_comp = t1->is_compatible_record(t2, p_info, p_left_chain, p_right_chain); | |
3229 | break; | |
3230 | case T_SEQOF: | |
3231 | is_type_comp = t1->is_compatible_record_of(t2, p_info, p_left_chain, p_right_chain); | |
3232 | break; | |
3233 | case T_SET_A: | |
3234 | case T_SET_T: | |
3235 | is_type_comp = t1->is_compatible_set(t2, p_info, p_left_chain, p_right_chain); | |
3236 | break; | |
3237 | case T_SETOF: | |
3238 | is_type_comp = t1->is_compatible_set_of(t2, p_info, p_left_chain, p_right_chain); | |
3239 | break; | |
3240 | case T_ARRAY: | |
3241 | is_type_comp = t1->is_compatible_array(t2, p_info, p_left_chain, p_right_chain); | |
3242 | break; | |
3243 | case T_CHOICE_T: | |
3244 | case T_CHOICE_A: | |
3245 | case T_ANYTYPE: | |
3246 | is_type_comp = t1->is_compatible_choice_anytype(t2, p_info, p_left_chain, p_right_chain); | |
3247 | break; | |
3248 | case T_ENUM_A: | |
3249 | case T_ENUM_T: | |
3250 | case T_SIGNATURE: | |
3251 | case T_PORT: | |
3252 | case T_OPENTYPE: | |
3253 | is_type_comp = ( t1 == t2 ); | |
3254 | break; | |
3255 | case T_FUNCTION: | |
3256 | case T_ALTSTEP: | |
3257 | case T_TESTCASE: | |
3258 | // TODO: Compatibility. | |
3259 | is_type_comp = ( t1 == t2 ); | |
3260 | break; | |
3261 | case T_ANY: | |
3262 | is_type_comp = ( t2->typetype == T_ANY || t2->typetype == T_OSTR ); | |
3263 | break; | |
3264 | default: | |
3265 | FATAL_ERROR("Type::is_compatible()"); | |
3266 | } | |
3267 | // if types are compatible then check subtype compatibility | |
3268 | // skip check if p_info is NULL | |
3269 | if ((p_info!=NULL) && is_type_comp && (sub_type!=NULL) && (p_type->sub_type!=NULL) && | |
3270 | (sub_type->get_subtypetype()==p_type->sub_type->get_subtypetype())) | |
3271 | { | |
3272 | if (p_info->get_str1_elem()) { | |
3273 | if (p_info->get_str2_elem()) { | |
3274 | // both are string elements -> nothing to do | |
3275 | } else { | |
3276 | // char <-> string | |
3277 | if (!p_type->sub_type->is_compatible_with_elem()) { | |
3278 | is_type_comp = false; | |
3279 | p_info->set_subtype_error( | |
3280 | string("Subtype mismatch: string element has no common value with subtype ")+ | |
3281 | p_type->sub_type->to_string()); | |
3282 | } | |
3283 | } | |
3284 | } else { | |
3285 | if (p_info->get_str2_elem()) { | |
3286 | // string <-> char | |
3287 | if (!sub_type->is_compatible_with_elem()) { | |
3288 | is_type_comp = false; | |
3289 | p_info->set_subtype_error(string("Subtype mismatch: subtype ")+ | |
3290 | sub_type->to_string()+string(" has no common value with a string element")); | |
3291 | } | |
3292 | } else { | |
3293 | // string <-> string | |
3294 | if (!sub_type->is_compatible(p_type->sub_type)) { | |
3295 | is_type_comp = false; | |
3296 | p_info->set_subtype_error(string("Subtype mismatch: subtype ")+ | |
3297 | sub_type->to_string()+string(" has no common value with subtype ")+ | |
3298 | p_type->sub_type->to_string()); | |
3299 | } | |
3300 | } | |
3301 | } | |
3302 | } | |
3303 | return is_type_comp; | |
3304 | } | |
3305 | ||
3306 | bool Type::is_structured_type() const | |
3307 | { | |
3308 | switch (typetype) { | |
3309 | case T_SEQ_A: | |
3310 | case T_SEQ_T: | |
3311 | case T_SEQOF: | |
3312 | case T_ARRAY: | |
3313 | case T_CHOICE_A: | |
3314 | case T_CHOICE_T: | |
3315 | case T_ANYTYPE: | |
3316 | case T_SET_A: | |
3317 | case T_SET_T: | |
3318 | case T_SETOF: | |
3319 | return true; | |
3320 | default: | |
3321 | return false; | |
3322 | } | |
3323 | } | |
3324 | ||
3325 | bool Type::is_subtype_length_compatible(Type *p_type) | |
3326 | { | |
3327 | if (typetype != T_SEQOF && typetype != T_SETOF) | |
3328 | FATAL_ERROR("Type::is_subtype_length_compatible()"); | |
3329 | if (!sub_type) return true; | |
3330 | SubtypeConstraint::subtype_t st_t = typetype == T_SEQOF ? | |
3331 | SubtypeConstraint::ST_RECORDOF : SubtypeConstraint::ST_SETOF; | |
3332 | switch (p_type->typetype) { | |
3333 | case T_SEQ_A: | |
3334 | case T_SEQ_T: | |
3335 | case T_SET_A: | |
3336 | case T_SET_T: { | |
3337 | vector<SubTypeParse> p_stp_v; | |
3338 | Value *p_nof_comps = new Value(Value::V_INT, | |
3339 | new int_val_t(p_type->get_nof_comps())); | |
3340 | p_stp_v.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps))); | |
3341 | SubType p_st(st_t, this, NULL, &p_stp_v, NULL); | |
3342 | p_st.chk(); | |
3343 | delete p_stp_v[0]; | |
3344 | p_stp_v.clear(); | |
3345 | return sub_type->is_length_compatible(&p_st); } | |
3346 | case T_SEQOF: | |
3347 | case T_SETOF: | |
3348 | if (!p_type->sub_type) return true; | |
3349 | else return sub_type->is_length_compatible(p_type->sub_type); | |
3350 | case T_ARRAY: { | |
3351 | if (p_type->u.array.dimension->get_has_error()) return false; | |
3352 | vector<SubTypeParse> p_stp_v; | |
3353 | Value *p_nof_comps | |
3354 | = new Value(Value::V_INT, | |
3355 | new int_val_t(p_type->u.array.dimension->get_size())); | |
3356 | p_stp_v.add(new SubTypeParse(new Ttcn::LengthRestriction(p_nof_comps))); | |
3357 | SubType p_st(st_t, this, NULL, &p_stp_v, NULL); | |
3358 | p_st.chk(); // Convert SubTypeParse to SubType. | |
3359 | delete p_stp_v[0]; | |
3360 | p_stp_v.clear(); | |
3361 | return sub_type->is_length_compatible(&p_st); } | |
3362 | default: | |
3363 | FATAL_ERROR("Type::is_subtype_length_compatible()"); | |
3364 | } | |
3365 | } | |
3366 | ||
3367 | // Errors and warnings are reported in an upper level. We just make a | |
3368 | // simple decision here. | |
3369 | bool Type::is_compatible_record(Type *p_type, TypeCompatInfo *p_info, | |
3370 | TypeChain *p_left_chain, | |
3371 | TypeChain *p_right_chain) | |
3372 | { | |
3373 | if (typetype != T_SEQ_A && typetype != T_SEQ_T) | |
3374 | FATAL_ERROR("Type::is_compatible_record()"); | |
3375 | // The get_type_refd_last() was called for both Types at this point. All | |
3376 | // this code runs in both run-times. | |
3377 | if (this == p_type) return true; | |
3378 | else if (!use_runtime_2 || !p_info | |
3379 | || (p_info && p_info->is_strict())) return false; | |
3380 | size_t nof_comps = get_nof_comps(); | |
3381 | switch (p_type->typetype) { | |
3382 | case T_SEQ_A: | |
3383 | case T_SEQ_T: { | |
3384 | // According to 6.3.2.2 the # of fields and the optionality must be | |
3385 | // the same for record types. It's good news for compile-time checks. | |
3386 | // Conversion is always from "p_type -> this". | |
3387 | size_t p_nof_comps = p_type->get_nof_comps(); | |
3388 | if (nof_comps != p_nof_comps) { | |
3389 | p_info->set_is_erroneous(this, p_type, string("The number of fields in " | |
3390 | "record/SEQUENCE types must be the same")); | |
3391 | return false; | |
3392 | } | |
3393 | // If p_info is present we have the chains as well. | |
3394 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3395 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3396 | for (size_t i = 0; i < nof_comps; i++) { | |
3397 | CompField *cf = get_comp_byIndex(i); | |
3398 | CompField *p_cf = p_type->get_comp_byIndex(i); | |
3399 | Type *cf_type = cf->get_type()->get_type_refd_last(); | |
3400 | Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); | |
3401 | string cf_name = cf->get_name().get_dispname(); | |
3402 | string p_cf_name = p_cf->get_name().get_dispname(); | |
3403 | if (cf->get_is_optional() != p_cf->get_is_optional()) { | |
3404 | p_info->append_ref_str(0, "." + cf_name); | |
3405 | p_info->append_ref_str(1, "." + p_cf_name); | |
3406 | p_info->set_is_erroneous(cf_type, p_cf_type, string("The optionality of " | |
3407 | "fields in record/SEQUENCE types must be " | |
3408 | "the same")); | |
3409 | return false; | |
3410 | } | |
3411 | TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_cf_type, | |
3412 | false, false); | |
3413 | p_left_chain->mark_state(); | |
3414 | p_right_chain->mark_state(); | |
3415 | p_left_chain->add(cf_type); | |
3416 | p_right_chain->add(p_cf_type); | |
3417 | if (cf_type != p_cf_type | |
3418 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3419 | && !cf_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, | |
3420 | p_right_chain)) { | |
3421 | p_info->append_ref_str(0, "." + cf_name + info_tmp.get_ref_str(0)); | |
3422 | p_info->append_ref_str(1, "." + p_cf_name + info_tmp.get_ref_str(1)); | |
3423 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3424 | info_tmp.get_error_str()); | |
3425 | p_left_chain->previous_state(); | |
3426 | p_right_chain->previous_state(); | |
3427 | return false; | |
3428 | } | |
3429 | p_left_chain->previous_state(); | |
3430 | p_right_chain->previous_state(); | |
3431 | } | |
3432 | p_info->set_needs_conversion(true); | |
3433 | p_info->add_type_conversion(p_type, this); | |
3434 | return true; } | |
3435 | case T_SEQOF: | |
3436 | if (!p_type->is_subtype_length_compatible(this)) { | |
3437 | p_info->set_is_erroneous(this, p_type, string("Incompatible record of/SEQUENCE " | |
3438 | "OF subtypes")); | |
3439 | return false; | |
3440 | } | |
3441 | // no break | |
3442 | case T_ARRAY: { | |
3443 | Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); | |
3444 | if (p_type->typetype == T_ARRAY) { | |
3445 | if (p_of_type->get_typetype() == T_ARRAY) { | |
3446 | p_info->set_is_erroneous(this, p_type, string("record/SEQUENCE types are " | |
3447 | "compatible only with single-dimension " | |
3448 | "arrays")); | |
3449 | return false; | |
3450 | } | |
3451 | size_t nof_opt_fields = 0; | |
3452 | for (size_t i = 0; i < nof_comps; i++) | |
3453 | if (get_comp_byIndex(i)->get_is_optional()) nof_opt_fields++; | |
3454 | if (p_type->u.array.dimension->get_size() | |
3455 | < nof_comps - nof_opt_fields) { | |
3456 | p_info->set_is_erroneous(this, p_type, string("The dimension of the array " | |
3457 | "must be >= than the number of mandatory " | |
3458 | "fields in the record/SEQUENCE type")); | |
3459 | return false; | |
3460 | } | |
3461 | } | |
3462 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3463 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3464 | for (size_t i = 0; i < nof_comps; i++) { | |
3465 | Type *cf_type = get_comp_byIndex(i)->get_type()->get_type_refd_last(); | |
3466 | TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_of_type, | |
3467 | false, false); | |
3468 | p_left_chain->mark_state(); | |
3469 | p_right_chain->mark_state(); | |
3470 | p_left_chain->add(cf_type); | |
3471 | p_right_chain->add(p_of_type); | |
3472 | if (cf_type != p_of_type | |
3473 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3474 | && !cf_type->is_compatible(p_of_type, &info_tmp, p_left_chain, | |
3475 | p_right_chain)) { | |
3476 | p_info->append_ref_str(0, "." + get_comp_byIndex(i) | |
3477 | ->get_name().get_dispname() + info_tmp.get_ref_str(0)); | |
3478 | p_info->append_ref_str(1, "[]" + info_tmp.get_ref_str(1)); | |
3479 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3480 | info_tmp.get_error_str()); | |
3481 | p_left_chain->previous_state(); | |
3482 | p_right_chain->previous_state(); | |
3483 | return false; | |
3484 | } | |
3485 | p_left_chain->previous_state(); | |
3486 | p_right_chain->previous_state(); | |
3487 | } | |
3488 | p_info->set_needs_conversion(true); | |
3489 | p_info->add_type_conversion(p_type, this); | |
3490 | return true; } | |
3491 | case T_CHOICE_A: | |
3492 | case T_CHOICE_T: | |
3493 | case T_ANYTYPE: | |
3494 | // 6.3.2.4 makes our job very easy... | |
3495 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " | |
3496 | "compatible only with other " | |
3497 | "union/CHOICE/anytype types")); | |
3498 | return false; | |
3499 | case T_SET_A: | |
3500 | case T_SET_T: | |
3501 | case T_SETOF: | |
3502 | // Only set/set of types are compatible with other set/set of types. | |
3503 | // 6.3.2.3 is a little bit unclear about set of types, but we treat them | |
3504 | // this way. Otherwise, it would be possible to use compatibility with | |
3505 | // a "middle-man" set of variable between record/set types: | |
3506 | // type set S { integer f1, integer f2 } | |
3507 | // type record { integer f1, integer f2 } | |
3508 | // type set of integer SO | |
3509 | // var S s := { 1, 2 } | |
3510 | // var R r := { 1, 2 } | |
3511 | // var SO so | |
3512 | // so := s | |
3513 | // if (r == s) { ... } // Not allowed. | |
3514 | // if (r == so) { ... } // Not allowed. (?) | |
3515 | // Seems to be a fair decision. If we would want compatibility between | |
3516 | // variables of record/set types, we should allow it directly. | |
3517 | p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " | |
3518 | "types are compatible only with other set/SET " | |
3519 | "set of/SET OF types")); | |
3520 | return false; | |
3521 | default: | |
3522 | return false; | |
3523 | } | |
3524 | } | |
3525 | ||
3526 | bool Type::is_compatible_record_of(Type *p_type, TypeCompatInfo *p_info, | |
3527 | TypeChain *p_left_chain, | |
3528 | TypeChain *p_right_chain) | |
3529 | { | |
3530 | if (typetype != T_SEQOF) FATAL_ERROR("Type::is_compatible_record_of()"); | |
3531 | if (this == p_type) return true; | |
3532 | else if (!use_runtime_2 || !p_info | |
3533 | || (p_info && p_info->is_strict())) return false; | |
3534 | switch (p_type->typetype) { | |
3535 | case T_SEQ_A: | |
3536 | case T_SEQ_T: { | |
3537 | if (!is_subtype_length_compatible(p_type)) { | |
3538 | p_info->set_is_erroneous(this, p_type, string("Incompatible " | |
3539 | "record of/SEQUENCE OF subtypes")); | |
3540 | return false; | |
3541 | } | |
3542 | Type *of_type = get_ofType()->get_type_refd_last(); | |
3543 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3544 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3545 | for (size_t i = 0; i < p_type->get_nof_comps(); i++) { | |
3546 | CompField *p_cf = p_type->get_comp_byIndex(i); | |
3547 | Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); | |
3548 | TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_cf_type, | |
3549 | false, false); | |
3550 | p_left_chain->mark_state(); | |
3551 | p_right_chain->mark_state(); | |
3552 | p_left_chain->add(of_type); | |
3553 | p_right_chain->add(p_cf_type); | |
3554 | if (of_type != p_cf_type | |
3555 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3556 | && !of_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, | |
3557 | p_right_chain)) { | |
3558 | p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); | |
3559 | p_info->append_ref_str(1, "." + p_cf->get_name().get_dispname() + | |
3560 | info_tmp.get_ref_str(1)); | |
3561 | p_info->set_is_erroneous(info_tmp.get_type(0), | |
3562 | info_tmp.get_type(1), | |
3563 | info_tmp.get_error_str()); | |
3564 | p_left_chain->previous_state(); | |
3565 | p_right_chain->previous_state(); | |
3566 | return false; | |
3567 | } | |
3568 | p_left_chain->previous_state(); | |
3569 | p_right_chain->previous_state(); | |
3570 | } | |
3571 | p_info->set_needs_conversion(true); | |
3572 | p_info->add_type_conversion(p_type, this); | |
3573 | return true; } | |
3574 | case T_SEQOF: | |
3575 | case T_ARRAY: { | |
3576 | if (!is_subtype_length_compatible(p_type)) { | |
3577 | p_info->set_is_erroneous(this, p_type, string("Incompatible " | |
3578 | "record of/SEQUENCE OF subtypes")); | |
3579 | return false; | |
3580 | } | |
3581 | Type *of_type = get_ofType()->get_type_refd_last(); | |
3582 | Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); | |
3583 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3584 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3585 | TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_of_type, | |
3586 | false, false); | |
3587 | p_left_chain->mark_state(); | |
3588 | p_right_chain->mark_state(); | |
3589 | p_left_chain->add(of_type); | |
3590 | p_right_chain->add(p_of_type); | |
3591 | if (of_type == p_of_type | |
3592 | || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3593 | || of_type->is_compatible(p_of_type, &info_tmp, p_left_chain, | |
3594 | p_right_chain)) { | |
3595 | p_info->set_needs_conversion(true); | |
3596 | p_info->add_type_conversion(p_type, this); | |
3597 | p_left_chain->previous_state(); | |
3598 | p_right_chain->previous_state(); | |
3599 | return true; | |
3600 | } | |
3601 | p_left_chain->previous_state(); | |
3602 | p_right_chain->previous_state(); | |
3603 | p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); | |
3604 | // Arrays already have the "[]" in their names. | |
3605 | if (p_type->get_typetype() != T_ARRAY) p_info->append_ref_str(1, string("[]")); | |
3606 | p_info->append_ref_str(1, info_tmp.get_ref_str(1)); | |
3607 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3608 | info_tmp.get_error_str()); | |
3609 | return false; } | |
3610 | case T_CHOICE_A: | |
3611 | case T_CHOICE_T: | |
3612 | case T_ANYTYPE: | |
3613 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " | |
3614 | "compatible only with other " | |
3615 | "union/CHOICE/anytype types")); | |
3616 | return false; | |
3617 | case T_SET_A: | |
3618 | case T_SET_T: | |
3619 | case T_SETOF: | |
3620 | p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " | |
3621 | "types are compatible only with other set/SET " | |
3622 | "set of/SET OF types")); | |
3623 | return false; | |
3624 | default: | |
3625 | return false; | |
3626 | } | |
3627 | } | |
3628 | ||
3629 | bool Type::is_compatible_array(Type *p_type, TypeCompatInfo *p_info, | |
3630 | TypeChain *p_left_chain, | |
3631 | TypeChain *p_right_chain) | |
3632 | { | |
3633 | if (typetype != T_ARRAY) FATAL_ERROR("Type::is_compatible_array()"); | |
3634 | // Copied from the original checker code. The type of the elements and | |
3635 | // the dimension of the array must be the same. | |
3636 | if (this == p_type) return true; | |
3637 | if (p_type->typetype == T_ARRAY && u.array.element_type | |
3638 | ->is_compatible(p_type->u.array.element_type, NULL) | |
3639 | && u.array.dimension->is_identical(p_type->u.array.dimension)) | |
3640 | return true; | |
3641 | else if (!use_runtime_2 || !p_info | |
3642 | || (p_info && p_info->is_strict())) return false; | |
3643 | Type *of_type = get_ofType()->get_type_refd_last(); | |
3644 | switch (p_type->get_typetype()) { | |
3645 | case T_SEQ_A: | |
3646 | case T_SEQ_T: { | |
3647 | if (of_type->get_typetype() == T_ARRAY) { | |
3648 | p_info->set_is_erroneous(this, p_type, string("record/SEQUENCE types are " | |
3649 | "compatible only with single-dimension " | |
3650 | "arrays")); | |
3651 | return false; | |
3652 | } | |
3653 | size_t p_nof_comps = p_type->get_nof_comps(); | |
3654 | size_t p_nof_opt_fields = 0; | |
3655 | for (size_t i = 0; i < p_nof_comps; i++) | |
3656 | if (p_type->get_comp_byIndex(i)->get_is_optional()) | |
3657 | p_nof_opt_fields++; | |
3658 | if (u.array.dimension->get_size() < p_nof_comps - p_nof_opt_fields) { | |
3659 | p_info->set_is_erroneous(this, p_type, string("The dimension of the array " | |
3660 | "must be >= than the number of mandatory " | |
3661 | "fields in the record/SEQUENCE type")); | |
3662 | return false; | |
3663 | } | |
3664 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3665 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3666 | for (size_t i = 0; i < p_nof_comps; ++i) { | |
3667 | CompField *p_cf = p_type->get_comp_byIndex(i); | |
3668 | Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); | |
3669 | string p_cf_name = p_cf->get_name().get_dispname(); | |
3670 | TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_cf_type, | |
3671 | false, false); | |
3672 | p_left_chain->mark_state(); | |
3673 | p_right_chain->mark_state(); | |
3674 | p_left_chain->add(of_type); | |
3675 | p_right_chain->add(p_cf_type); | |
3676 | if (of_type != p_cf_type | |
3677 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3678 | && !of_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, | |
3679 | p_right_chain)) { | |
3680 | p_info->append_ref_str(0, info_tmp.get_ref_str(0)); | |
3681 | p_info->append_ref_str(1, "." + p_cf->get_name().get_dispname() + | |
3682 | info_tmp.get_ref_str(1)); | |
3683 | p_info->set_is_erroneous(info_tmp.get_type(0), | |
3684 | info_tmp.get_type(1), | |
3685 | info_tmp.get_error_str()); | |
3686 | p_left_chain->previous_state(); | |
3687 | p_right_chain->previous_state(); | |
3688 | return false; | |
3689 | } | |
3690 | p_left_chain->previous_state(); | |
3691 | p_right_chain->previous_state(); | |
3692 | } | |
3693 | p_info->set_needs_conversion(true); | |
3694 | p_info->add_type_conversion(p_type, this); | |
3695 | return true; } | |
3696 | case T_SEQOF: | |
3697 | if (!p_type->is_subtype_length_compatible(this)) { | |
3698 | p_info->set_is_erroneous(this, p_type, string("Incompatible " | |
3699 | "record of/SEQUENCE OF subtypes")); | |
3700 | return false; | |
3701 | } // Don't break. | |
3702 | case T_ARRAY: { | |
3703 | if (p_type->get_typetype() == T_ARRAY | |
3704 | && !u.array.dimension->is_identical(p_type->u.array.dimension)) { | |
3705 | p_info->set_is_erroneous(this, p_type, string("Array types should have " | |
3706 | "the same dimension")); | |
3707 | return false; | |
3708 | } | |
3709 | Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); | |
3710 | TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_of_type, | |
3711 | false, false); | |
3712 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3713 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3714 | p_left_chain->mark_state(); | |
3715 | p_right_chain->mark_state(); | |
3716 | p_left_chain->add(of_type); | |
3717 | p_right_chain->add(p_of_type); | |
3718 | if (of_type == p_of_type | |
3719 | || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3720 | || of_type->is_compatible(p_of_type, &info_tmp, p_left_chain, | |
3721 | p_right_chain)) { | |
3722 | p_info->set_needs_conversion(true); | |
3723 | p_info->add_type_conversion(p_type, this); | |
3724 | p_left_chain->previous_state(); | |
3725 | p_right_chain->previous_state(); | |
3726 | return true; | |
3727 | } | |
3728 | p_left_chain->previous_state(); | |
3729 | p_right_chain->previous_state(); | |
3730 | p_info->append_ref_str(0, info_tmp.get_ref_str(0)); | |
3731 | if (p_type->get_typetype() != T_ARRAY) p_info->append_ref_str(1, string("[]")); | |
3732 | p_info->append_ref_str(1, info_tmp.get_ref_str(1)); | |
3733 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3734 | info_tmp.get_error_str()); | |
3735 | return false; } | |
3736 | case T_CHOICE_A: | |
3737 | case T_CHOICE_T: | |
3738 | case T_ANYTYPE: | |
3739 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " | |
3740 | "compatible only with other " | |
3741 | "union/CHOICE/anytype types")); | |
3742 | return false; | |
3743 | case T_SET_A: | |
3744 | case T_SET_T: | |
3745 | case T_SETOF: | |
3746 | p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " | |
3747 | "types are compatible only with other set/SET " | |
3748 | "set of/SET OF types")); | |
3749 | return false; | |
3750 | default: | |
3751 | return false; | |
3752 | } | |
3753 | } | |
3754 | ||
3755 | bool Type::is_compatible_set(Type *p_type, TypeCompatInfo *p_info, | |
3756 | TypeChain *p_left_chain, | |
3757 | TypeChain *p_right_chain) | |
3758 | { | |
3759 | if (typetype != T_SET_A && typetype != T_SET_T) | |
3760 | FATAL_ERROR("Type::is_compatible_set()"); | |
3761 | if (this == p_type) return true; | |
3762 | else if (!use_runtime_2 || !p_info | |
3763 | || (p_info && p_info->is_strict())) return false; | |
3764 | size_t nof_comps = get_nof_comps(); | |
3765 | switch (p_type->typetype) { | |
3766 | case T_SET_A: | |
3767 | case T_SET_T: { | |
3768 | // The standard is very generous. We don't need to check for a possible | |
3769 | // combination of compatible fields. According to 6.3.2.3, simply do | |
3770 | // the same thing as for T_SEQ_{A,T} types. The fields are in their | |
3771 | // textual order. | |
3772 | size_t p_nof_comps = p_type->get_nof_comps(); | |
3773 | if (nof_comps != p_nof_comps) { | |
3774 | p_info->set_is_erroneous(this, p_type, string("The number of fields in " | |
3775 | "set/SET types must be the same")); | |
3776 | return false; | |
3777 | } | |
3778 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3779 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3780 | for (size_t i = 0; i < nof_comps; i++) { | |
3781 | CompField *cf = get_comp_byIndex(i); | |
3782 | CompField *p_cf = p_type->get_comp_byIndex(i); | |
3783 | Type *cf_type = cf->get_type()->get_type_refd_last(); | |
3784 | Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); | |
3785 | string cf_name = cf->get_name().get_dispname(); | |
3786 | string p_cf_name = p_cf->get_name().get_dispname(); | |
3787 | if (cf->get_is_optional() != p_cf->get_is_optional()) { | |
3788 | p_info->append_ref_str(0, "." + cf_name); | |
3789 | p_info->append_ref_str(1, "." + p_cf_name); | |
3790 | p_info->set_is_erroneous(cf_type, p_cf_type, string("The optionality of " | |
3791 | "fields in set/SET types must be the " | |
3792 | "same")); | |
3793 | return false; | |
3794 | } | |
3795 | TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_cf_type, | |
3796 | false, false); | |
3797 | p_left_chain->mark_state(); | |
3798 | p_right_chain->mark_state(); | |
3799 | p_left_chain->add(cf_type); | |
3800 | p_right_chain->add(p_cf_type); | |
3801 | if (cf_type != p_cf_type | |
3802 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3803 | && !cf_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, | |
3804 | p_right_chain)) { | |
3805 | p_info->append_ref_str(0, "." + cf_name + info_tmp.get_ref_str(0)); | |
3806 | p_info->append_ref_str(1, "." + p_cf_name + info_tmp.get_ref_str(1)); | |
3807 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3808 | info_tmp.get_error_str()); | |
3809 | p_left_chain->previous_state(); | |
3810 | p_right_chain->previous_state(); | |
3811 | return false; | |
3812 | } | |
3813 | p_left_chain->previous_state(); | |
3814 | p_right_chain->previous_state(); | |
3815 | } | |
3816 | p_info->set_needs_conversion(true); | |
3817 | p_info->add_type_conversion(p_type, this); | |
3818 | return true; } | |
3819 | case T_SETOF: { | |
3820 | if (!p_type->is_subtype_length_compatible(this)) { | |
3821 | p_info->set_is_erroneous(this, p_type, string("Incompatible set of/SET OF " | |
3822 | "subtypes")); | |
3823 | return false; | |
3824 | } | |
3825 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3826 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3827 | Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); | |
3828 | for (size_t i = 0; i < nof_comps; i++) { | |
3829 | Type *cf_type = get_comp_byIndex(i)->get_type()->get_type_refd_last(); | |
3830 | TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_of_type, | |
3831 | false, false); | |
3832 | p_left_chain->mark_state(); | |
3833 | p_right_chain->mark_state(); | |
3834 | p_left_chain->add(cf_type); | |
3835 | p_right_chain->add(p_of_type); | |
3836 | if (cf_type != p_of_type | |
3837 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3838 | && !cf_type->is_compatible(p_of_type, &info_tmp, p_left_chain, | |
3839 | p_right_chain)) { | |
3840 | p_info->append_ref_str(0, "." + get_comp_byIndex(i) | |
3841 | ->get_name().get_dispname() + info_tmp.get_ref_str(0)); | |
3842 | p_info->append_ref_str(1, "[]" + info_tmp.get_ref_str(1)); | |
3843 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3844 | info_tmp.get_error_str()); | |
3845 | p_left_chain->previous_state(); | |
3846 | p_right_chain->previous_state(); | |
3847 | return false; | |
3848 | } | |
3849 | p_left_chain->previous_state(); | |
3850 | p_right_chain->previous_state(); | |
3851 | } | |
3852 | p_info->set_needs_conversion(true); | |
3853 | p_info->add_type_conversion(p_type, this); | |
3854 | return true; } | |
3855 | case T_CHOICE_A: | |
3856 | case T_CHOICE_T: | |
3857 | case T_ANYTYPE: | |
3858 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " | |
3859 | "compatible only with other " | |
3860 | "union/CHOICE/anytype types")); | |
3861 | return false; | |
3862 | case T_SEQ_A: | |
3863 | case T_SEQ_T: | |
3864 | case T_SEQOF: | |
3865 | case T_ARRAY: | |
3866 | p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " | |
3867 | "types are compatible only with other set/SET " | |
3868 | "set of/SET OF types")); | |
3869 | return false; | |
3870 | default: | |
3871 | return false; | |
3872 | } | |
3873 | } | |
3874 | ||
3875 | bool Type::is_compatible_set_of(Type *p_type, TypeCompatInfo *p_info, | |
3876 | TypeChain *p_left_chain, | |
3877 | TypeChain *p_right_chain) | |
3878 | { | |
3879 | if (typetype != T_SETOF) FATAL_ERROR("Type::is_compatible_set_of()"); | |
3880 | if (this == p_type) return true; | |
3881 | else if (!use_runtime_2 || !p_info | |
3882 | || (p_info && p_info->is_strict())) return false; | |
3883 | Type *of_type = get_ofType(); | |
3884 | switch (p_type->get_typetype()) { | |
3885 | case T_SET_A: | |
3886 | case T_SET_T: { | |
3887 | if (!is_subtype_length_compatible(p_type)) { | |
3888 | p_info->set_is_erroneous(this, p_type, string("Incompatible set of/SET OF " | |
3889 | "subtypes")); | |
3890 | return false; | |
3891 | } | |
3892 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3893 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3894 | for (size_t i = 0; i < p_type->get_nof_comps(); i++) { | |
3895 | CompField *p_cf = p_type->get_comp_byIndex(i); | |
3896 | Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); | |
3897 | TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_cf_type, | |
3898 | false, false); | |
3899 | p_left_chain->mark_state(); | |
3900 | p_right_chain->mark_state(); | |
3901 | p_left_chain->add(of_type); | |
3902 | p_right_chain->add(p_cf_type); | |
3903 | if (of_type != p_cf_type | |
3904 | && !(p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3905 | && !of_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, | |
3906 | p_right_chain)) { | |
3907 | p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); | |
3908 | p_info->append_ref_str(1, "." + p_cf->get_name().get_dispname() + | |
3909 | info_tmp.get_ref_str(1)); | |
3910 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3911 | info_tmp.get_error_str()); | |
3912 | p_left_chain->previous_state(); | |
3913 | p_right_chain->previous_state(); | |
3914 | return false; | |
3915 | } | |
3916 | p_left_chain->previous_state(); | |
3917 | p_right_chain->previous_state(); | |
3918 | } | |
3919 | p_info->set_needs_conversion(true); | |
3920 | p_info->add_type_conversion(p_type, this); | |
3921 | return true; } | |
3922 | case T_SETOF: { | |
3923 | if (!is_subtype_length_compatible(p_type)) { | |
3924 | p_info->set_is_erroneous(this, p_type, string("Incompatible set of/SET OF " | |
3925 | "subtypes")); | |
3926 | return false; | |
3927 | } | |
3928 | if (p_left_chain->empty()) p_left_chain->add(this); | |
3929 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
3930 | Type *p_of_type = p_type->get_ofType()->get_type_refd_last(); | |
3931 | TypeCompatInfo info_tmp(p_info->get_my_module(), of_type, p_of_type, | |
3932 | false, false); | |
3933 | p_left_chain->mark_state(); | |
3934 | p_right_chain->mark_state(); | |
3935 | p_left_chain->add(of_type); | |
3936 | p_right_chain->add(p_of_type); | |
3937 | if (of_type == p_of_type | |
3938 | || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
3939 | || of_type->is_compatible(p_of_type, &info_tmp, p_left_chain, | |
3940 | p_right_chain)) { | |
3941 | p_info->set_needs_conversion(true); | |
3942 | p_info->add_type_conversion(p_type, this); | |
3943 | p_left_chain->previous_state(); | |
3944 | p_right_chain->previous_state(); | |
3945 | return true; | |
3946 | } | |
3947 | p_info->append_ref_str(0, "[]" + info_tmp.get_ref_str(0)); | |
3948 | p_info->append_ref_str(1, "[]" + info_tmp.get_ref_str(1)); | |
3949 | p_info->set_is_erroneous(info_tmp.get_type(0), info_tmp.get_type(1), | |
3950 | info_tmp.get_error_str()); | |
3951 | p_left_chain->previous_state(); | |
3952 | p_right_chain->previous_state(); | |
3953 | return false; } | |
3954 | case T_CHOICE_A: | |
3955 | case T_CHOICE_T: | |
3956 | case T_ANYTYPE: | |
3957 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype " | |
3958 | "types are compatible only with other " | |
3959 | "union/CHOICE/anytype types")); | |
3960 | return false; | |
3961 | case T_SEQ_A: | |
3962 | case T_SEQ_T: | |
3963 | case T_SEQOF: | |
3964 | case T_ARRAY: | |
3965 | p_info->set_is_erroneous(this, p_type, string("set/SET and set of/SET OF " | |
3966 | "types are compatible only with other set/SET " | |
3967 | "set of/SET OF types")); | |
3968 | return false; | |
3969 | default: | |
3970 | return false; | |
3971 | } | |
3972 | } | |
3973 | ||
3974 | bool Type::is_compatible_choice_anytype(Type *p_type, | |
3975 | TypeCompatInfo *p_info, | |
3976 | TypeChain *p_left_chain, | |
3977 | TypeChain *p_right_chain) | |
3978 | { | |
3979 | if (typetype != T_ANYTYPE && typetype != T_CHOICE_A | |
3980 | && typetype != T_CHOICE_T) | |
3981 | FATAL_ERROR("Type::is_compatible_choice_anytype()"); | |
3982 | if (this == p_type) return true; // Original "true" leaf... | |
3983 | else if (!use_runtime_2 || !p_info | |
3984 | || (p_info && p_info->is_strict())) return false; // ...and "false". | |
3985 | if ((typetype == T_ANYTYPE && p_type->get_typetype() != T_ANYTYPE) | |
3986 | || (p_type->get_typetype() == T_ANYTYPE && typetype != T_ANYTYPE)) { | |
3987 | p_info->set_is_erroneous(this, p_type, string("Type anytype is compatible only " | |
3988 | "with other anytype types")); | |
3989 | return false; | |
3990 | } | |
3991 | switch (p_type->get_typetype()) { | |
3992 | case T_SEQ_A: | |
3993 | case T_SEQ_T: | |
3994 | case T_SEQOF: | |
3995 | case T_ARRAY: | |
3996 | case T_SET_A: | |
3997 | case T_SET_T: | |
3998 | case T_SETOF: | |
3999 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE/anytype types are " | |
4000 | "compatible only with other union/CHOICE/anytype " | |
4001 | "types")); | |
4002 | return false; | |
4003 | case T_CHOICE_A: | |
4004 | case T_CHOICE_T: | |
4005 | if (typetype != T_CHOICE_A && typetype != T_CHOICE_T) { | |
4006 | p_info->set_is_erroneous(this, p_type, string("union/CHOICE types are " | |
4007 | "compatible only with other union/CHOICE " | |
4008 | "types")); | |
4009 | return false; | |
4010 | } | |
4011 | // no break | |
4012 | case T_ANYTYPE: { | |
4013 | if (p_left_chain->empty()) p_left_chain->add(this); | |
4014 | if (p_right_chain->empty()) p_right_chain->add(p_type); | |
4015 | // Find a field with the same name and with compatible type. There can | |
4016 | // be more alternatives, we need to generate all conversion functions. | |
4017 | // The same field types must be avoided. (For anytypes the "field | |
4018 | // name = module name + field name".) | |
4019 | bool alles_okay = false; | |
4020 | for (size_t i = 0; i < get_nof_comps(); i++) { | |
4021 | CompField *cf = get_comp_byIndex(i); | |
4022 | Type *cf_type = cf->get_type()->get_type_refd_last(); | |
4023 | for (size_t j = 0; j < p_type->get_nof_comps(); ++j) { | |
4024 | CompField *p_cf = p_type->get_comp_byIndex(j); | |
4025 | Type *p_cf_type = p_cf->get_type()->get_type_refd_last(); | |
4026 | if (cf->get_name().get_name() != p_cf->get_name().get_name()) | |
4027 | continue; | |
4028 | // Don't report errors for each incompatible field, it would be a | |
4029 | // complete mess. Use this temporary for all fields. And forget | |
4030 | // the contents. | |
4031 | TypeCompatInfo info_tmp(p_info->get_my_module(), cf_type, p_cf_type, | |
4032 | false, false); | |
4033 | p_left_chain->mark_state(); | |
4034 | p_right_chain->mark_state(); | |
4035 | p_left_chain->add(cf_type); | |
4036 | p_right_chain->add(p_cf_type); | |
4037 | if (cf_type == p_cf_type | |
4038 | || (p_left_chain->has_recursion() && p_right_chain->has_recursion()) | |
4039 | || cf_type->is_compatible(p_cf_type, &info_tmp, p_left_chain, | |
4040 | p_right_chain)) { | |
4041 | if (cf_type != p_cf_type && cf_type->is_structured_type() | |
4042 | && p_cf_type->is_structured_type()) { | |
4043 | if (typetype == T_ANYTYPE && cf_type->get_my_scope() | |
4044 | ->get_scope_mod() != p_cf_type->get_my_scope() | |
4045 | ->get_scope_mod()) { | |
4046 | p_left_chain->previous_state(); | |
4047 | p_right_chain->previous_state(); | |
4048 | continue; | |
4049 | } | |
4050 | p_info->add_type_conversion(p_cf_type, cf_type); | |
4051 | } | |
4052 | alles_okay = true; | |
4053 | } | |
4054 | p_left_chain->previous_state(); | |
4055 | p_right_chain->previous_state(); | |
4056 | } | |
4057 | } | |
4058 | if (alles_okay) { | |
4059 | p_info->set_needs_conversion(true); | |
4060 | p_info->add_type_conversion(p_type, this); | |
4061 | return true; | |
4062 | } | |
4063 | p_info->set_is_erroneous(this, p_type, string("No compatible " | |
4064 | "union/CHOICE/anytype field found")); | |
4065 | return false; | |
4066 | } | |
4067 | default: | |
4068 | return false; | |
4069 | } | |
4070 | } | |
4071 | ||
4072 | /** \todo consider subtype constraints */ | |
4073 | bool Type::is_identical(Type *p_type) | |
4074 | { | |
4075 | chk(); | |
4076 | p_type->chk(); | |
4077 | Type *t1 = get_type_refd_last(); | |
4078 | Type *t2 = p_type->get_type_refd_last(); | |
4079 | if (t2->typetype == T_ERROR) return true; | |
4080 | switch (t1->typetype) { | |
4081 | case T_ERROR: | |
4082 | // error type is identical to everything | |
4083 | return true; | |
4084 | case T_ENUM_A: | |
4085 | case T_ENUM_T: | |
4086 | case T_CHOICE_T: | |
4087 | case T_CHOICE_A: | |
4088 | case T_ANYTYPE: | |
4089 | case T_SEQOF: | |
4090 | case T_SETOF: | |
4091 | case T_SEQ_A: | |
4092 | case T_SEQ_T: | |
4093 | case T_SET_A: | |
4094 | case T_SET_T: | |
4095 | case T_SIGNATURE: | |
4096 | case T_PORT: | |
4097 | case T_COMPONENT: | |
4098 | case T_OPENTYPE: | |
4099 | case T_FUNCTION: | |
4100 | case T_ALTSTEP: | |
4101 | case T_TESTCASE: | |
4102 | // user-defined structured types must be identical | |
4103 | return t1 == t2; | |
4104 | case T_ARRAY: | |
4105 | // the embedded type and the dimension must be identical in case of arrays | |
4106 | return t2->typetype == T_ARRAY && | |
4107 | t1->u.array.element_type->is_identical(t2->u.array.element_type) && | |
4108 | t1->u.array.dimension->is_identical(t2->u.array.dimension); | |
4109 | default: | |
4110 | // in case of built-in types the TTCN-3 view of typetype must be the same | |
4111 | return get_typetype_ttcn3(t1->typetype) == | |
4112 | get_typetype_ttcn3(t2->typetype); | |
4113 | } | |
4114 | } | |
4115 | ||
4116 | void Type::tr_compsof(ReferenceChain *refch) | |
4117 | { | |
4118 | if (typetype!=T_SEQ_A && typetype!=T_SET_A) | |
4119 | FATAL_ERROR("Type::tr_compsof()"); | |
4120 | if (u.secho.tr_compsof_ready) return; | |
4121 | if (u.secho.block) parse_block_Se(); | |
4122 | bool auto_tagging=u.secho.ctss->needs_auto_tags(); | |
4123 | if (refch) { | |
4124 | refch->mark_state(); | |
4125 | if (refch->add(get_fullname())) u.secho.ctss->tr_compsof(refch, false); | |
4126 | refch->prev_state(); | |
4127 | u.secho.tr_compsof_ready = true; | |
4128 | u.secho.ctss->tr_compsof(0, true); | |
4129 | } else { | |
4130 | ReferenceChain refch2(this, "While resolving COMPONENTS OF"); | |
4131 | refch2.add(get_fullname()); | |
4132 | Error_Context cntxt(this, "While resolving COMPONENTS OF"); | |
4133 | u.secho.ctss->tr_compsof(&refch2, false); | |
4134 | u.secho.tr_compsof_ready = true; | |
4135 | u.secho.ctss->tr_compsof(0, true); | |
4136 | } | |
4137 | if(auto_tagging) u.secho.ctss->add_auto_tags(); | |
4138 | } | |
4139 | ||
4140 | bool Type::is_startable() | |
4141 | { | |
4142 | if(typetype != T_FUNCTION) | |
4143 | FATAL_ERROR("Type::is_startable()"); | |
4144 | if(!checked) chk(); | |
4145 | return u.fatref.is_startable; | |
4146 | } | |
4147 | ||
4148 | bool Type::is_list_type(bool allow_array) | |
4149 | { | |
4150 | switch (get_type_refd_last()->get_typetype_ttcn3()) { | |
4151 | case Type::T_ARRAY: | |
4152 | return allow_array; | |
4153 | case Type::T_CSTR: | |
4154 | case Type::T_USTR: | |
4155 | case Type::T_BSTR: | |
4156 | case Type::T_HSTR: | |
4157 | case Type::T_OSTR: | |
4158 | case Type::T_SEQOF: | |
4159 | case Type::T_SETOF: | |
4160 | return true; | |
4161 | default: | |
4162 | return false; | |
4163 | } | |
4164 | } | |
4165 | ||
4166 | void Type::chk_coding(bool encode) { | |
4167 | string& coding_str = encode ? encoding_str : decoding_str; | |
4168 | if (!coding_str.empty()) | |
4169 | return; | |
4170 | coding_by_function = false; | |
4171 | ||
4172 | if (!w_attrib_path) { | |
4173 | error("No coding rule specified for type '%s'", get_typename().c_str()); | |
4174 | return; | |
4175 | } | |
4176 | Type::MessageEncodingType_t coding = CT_UNDEF; | |
4177 | ||
4178 | // Checking extension attributes | |
4179 | Ttcn::ExtensionAttributes * extatrs = parse_extattributes(w_attrib_path); | |
4180 | if (extatrs != 0) { // NULL means parsing error | |
4181 | for (size_t k = 0; k < extatrs->size(); ++k) { | |
4182 | Ttcn::ExtensionAttribute &ea = extatrs->get(k); | |
4183 | Ttcn::TypeMappings *inmaps = 0, *maps = 0; | |
4184 | Ttcn::TypeMapping* mapping = 0; | |
4185 | Ttcn::TypeMappingTarget* target = 0; | |
4186 | Type* t = 0; | |
4187 | switch (ea.get_type()) { | |
4188 | case Ttcn::ExtensionAttribute::ENCDECVALUE: | |
4189 | ea.get_encdecvalue_mappings(inmaps, maps); | |
4190 | maps = encode ? maps : inmaps; | |
4191 | maps->set_my_scope(this->get_my_scope()); | |
4192 | maps->chk(); | |
4193 | // look for coding settings | |
4194 | t = encode ? this : Type::get_pooltype(T_BSTR); | |
4195 | mapping = maps->get_mapping_byType(t); | |
4196 | if (mapping->get_nof_targets() == 0) | |
4197 | goto end_ext; | |
4198 | else { | |
4199 | for (size_t ind = 0; ind < mapping->get_nof_targets(); ind++) { | |
4200 | target = mapping->get_target_byIndex(ind); | |
4201 | t = target->get_target_type(); | |
4202 | if ((encode && (t->get_typetype() == T_BSTR)) || | |
4203 | (!encode && (t->get_typename() == this->get_typename()))) | |
4204 | { | |
4205 | if (target->get_mapping_type() == | |
4206 | Ttcn::TypeMappingTarget::TM_FUNCTION) { | |
4207 | if (!coding_str.empty()) | |
4208 | target->error("Multiple definition of this target"); | |
4209 | coding_str = target->get_function()-> | |
4210 | get_genname_from_scope(my_scope); | |
4211 | coding_by_function = true; | |
4212 | } else { | |
4213 | target->error("Only function is supported to do this mapping"); | |
4214 | } | |
4215 | } | |
4216 | } | |
4217 | if (coding_str.empty()) { | |
4218 | ea.warning("Extension attribute is found for %s but without " | |
4219 | "typemappings", encode ? "encvalue" : "decvalue"); | |
4220 | } | |
4221 | } | |
4222 | break; | |
4223 | ||
4224 | case Ttcn::ExtensionAttribute::ANYTYPELIST: | |
4225 | break; // ignore (may be inherited from the module) | |
4226 | ||
4227 | case Ttcn::ExtensionAttribute::NONE: | |
4228 | break; // ignore erroneous attribute | |
4229 | ||
4230 | default: | |
4231 | ea.error("A type can only have type mapping extension attribute: " | |
4232 | "in(...) or out(...)"); | |
4233 | break; | |
4234 | } | |
4235 | } | |
4236 | delete extatrs; | |
4237 | } | |
4238 | ||
4239 | if (!coding_str.empty()) | |
4240 | return; | |
4241 | end_ext: | |
4242 | ||
4243 | const vector<SingleWithAttrib>& real_attribs | |
4244 | = w_attrib_path->get_real_attrib(); | |
4245 | bool found = false; | |
4246 | for (size_t i = real_attribs.size(); i > 0 && !found; i--) { | |
4247 | if (real_attribs[i-1]->get_attribKeyword() | |
4248 | == SingleWithAttrib::AT_ENCODE) { | |
4249 | found = true; | |
4250 | coding = get_enc_type(*real_attribs[i-1]); | |
4251 | if (coding == CT_UNDEF) { | |
4252 | // "encode" attribute found, but the spec didn't match any known encodings | |
4253 | error("Unknown encoding '%s'", real_attribs[i-1]->get_attribSpec().get_spec().c_str()); | |
4254 | return; | |
4255 | } | |
4256 | } | |
4257 | } | |
4258 | if (coding == CT_UNDEF) { | |
4259 | // no "encode" attribute found | |
4260 | error("No coding rule specified for type '%s'", get_typename().c_str()); | |
4261 | return; | |
4262 | } | |
4263 | if (!has_encoding(coding)) { | |
4264 | error("Type '%s' cannot be coded with the selected method '%s'", | |
4265 | get_typename().c_str(), | |
4266 | get_encoding_name(coding)); | |
4267 | return; | |
4268 | } | |
4269 | switch (coding) { | |
4270 | case CT_RAW: | |
4271 | coding_str = "RAW"; | |
4272 | break; | |
4273 | case CT_TEXT: | |
4274 | coding_str = "TEXT"; | |
4275 | break; | |
4276 | case CT_PER: | |
4277 | coding_str = "PER"; | |
4278 | break; | |
4279 | case CT_XER: | |
4280 | coding_str = "XER, XER_EXTENDED"; // TODO: fine tuning this parameter | |
4281 | break; | |
4282 | case CT_JSON: | |
4283 | coding_str = "JSON"; | |
4284 | break; | |
4285 | case CT_BER: { | |
4286 | coding_str = "BER, "; | |
4287 | BerAST* ber = berattrib; | |
4288 | if (!ber) // use default settings if attributes are not specified | |
4289 | ber = new BerAST; | |
4290 | if (encode) | |
4291 | coding_str += ber->get_encode_str(); | |
4292 | else | |
4293 | coding_str += ber->get_decode_str(); | |
4294 | if (!berattrib) | |
4295 | delete ber; | |
4296 | break; } | |
4297 | default: | |
4298 | error("Unknown coding selected for type '%s'", get_typename().c_str()); | |
4299 | break; | |
4300 | } | |
4301 | coding_by_function = false; | |
4302 | } | |
4303 | ||
4304 | bool Type::is_coding_by_function() const { | |
4305 | return coding_by_function; | |
4306 | } | |
4307 | ||
4308 | const string& Type::get_coding(bool encode) const { | |
4309 | if (encode) | |
4310 | return encoding_str; | |
4311 | else | |
4312 | return decoding_str; | |
4313 | } | |
4314 | ||
4315 | namespace { // unnamed | |
4316 | const string ex_emm_ell("XML"), ex_ee_arr("XER"); | |
4317 | } | |
4318 | ||
4319 | Type::MessageEncodingType_t Type::get_enc_type(const SingleWithAttrib& atr) { | |
4320 | const string& enc = atr.get_attribSpec().get_spec(); | |
4321 | if (enc == "RAW") | |
4322 | return CT_RAW; | |
4323 | else if (enc == "TEXT") | |
4324 | return CT_TEXT; | |
4325 | else if (enc == "JSON") | |
4326 | return CT_JSON; | |
4327 | else if (enc == "BER:2002" || enc == "CER:2002" || enc == "DER:2002") | |
4328 | return CT_BER; | |
4329 | else if (enc == ex_emm_ell) | |
4330 | return CT_XER; | |
4331 | else if (enc == ex_ee_arr) { | |
4332 | atr.warning("The correct name of the encoding is ''XML''"); | |
4333 | return CT_XER; | |
4334 | } | |
4335 | else if (enc == "PER") | |
4336 | return CT_PER; | |
4337 | else | |
4338 | return CT_UNDEF; | |
4339 | } | |
4340 | bool Type::has_ei_withName(const Identifier& p_id) const | |
4341 | { | |
4342 | switch (typetype) { | |
4343 | case T_ENUM_T: | |
4344 | case T_ENUM_A: | |
4345 | if (checked) break; | |
4346 | // no break | |
4347 | default: | |
4348 | FATAL_ERROR("Type::has_ei_withName()"); | |
4349 | } | |
4350 | return u.enums.eis->has_ei_withName(p_id); | |
4351 | } | |
4352 | ||
4353 | EnumItem *Type::get_ei_byName(const Identifier& p_id) const | |
4354 | { | |
4355 | switch (typetype) { | |
4356 | case T_ENUM_T: | |
4357 | case T_ENUM_A: | |
4358 | if (checked) break; | |
4359 | // no break | |
4360 | default: | |
4361 | FATAL_ERROR("Type::get_ei_byName()"); | |
4362 | } | |
4363 | return u.enums.eis->get_ei_byName(p_id); | |
4364 | } | |
4365 | ||
4366 | EnumItem *Type::get_ei_byIndex(size_t n) const | |
4367 | { | |
4368 | switch (typetype) { | |
4369 | case T_ENUM_T: | |
4370 | case T_ENUM_A: | |
4371 | if (checked) break; | |
4372 | // no break | |
4373 | default: | |
4374 | FATAL_ERROR("Type::get_ei_byIndex()"); | |
4375 | } | |
4376 | return u.enums.eis->get_ei_byIndex(n); | |
4377 | } | |
4378 | ||
4379 | size_t Type::get_nof_comps() | |
4380 | { | |
4381 | switch(typetype) { | |
4382 | case T_ANYTYPE: | |
4383 | case T_CHOICE_T: | |
4384 | case T_SEQ_T: | |
4385 | case T_SET_T: | |
4386 | case T_OPENTYPE: | |
4387 | return u.secho.cfm->get_nof_comps(); | |
4388 | case T_SEQ_A: | |
4389 | case T_SET_A: | |
4390 | if(u.secho.block) parse_block_Se(); | |
4391 | return u.secho.ctss->get_nof_comps(); | |
4392 | case T_CHOICE_A: | |
4393 | if(u.secho.block) parse_block_Choice(); | |
4394 | return u.secho.ctss->get_nof_comps(); | |
4395 | case T_ARRAY: | |
4396 | return u.array.dimension->get_size(); | |
4397 | case T_SIGNATURE: | |
4398 | if (u.signature.parameters) | |
4399 | return u.signature.parameters->get_nof_params(); | |
4400 | else return 0; | |
4401 | default: | |
4402 | FATAL_ERROR("Type::get_nof_comps(%d)", typetype); | |
4403 | return 0; | |
4404 | } // switch | |
4405 | } | |
4406 | ||
4407 | const Identifier& Type::get_comp_id_byIndex(size_t n) | |
4408 | { | |
4409 | switch (typetype) { | |
4410 | case T_ANYTYPE: | |
4411 | case T_CHOICE_T: | |
4412 | case T_SEQ_T: | |
4413 | case T_SET_T: | |
4414 | case T_OPENTYPE: | |
4415 | return u.secho.cfm->get_comp_byIndex(n)->get_name(); | |
4416 | case T_SEQ_A: | |
4417 | case T_SET_A: | |
4418 | if(u.secho.block) parse_block_Se(); | |
4419 | return u.secho.ctss->get_comp_byIndex(n)->get_name(); | |
4420 | case T_CHOICE_A: | |
4421 | if(u.secho.block) parse_block_Choice(); | |
4422 | return u.secho.ctss->get_comp_byIndex(n)->get_name(); | |
4423 | case T_SIGNATURE: | |
4424 | return u.signature.parameters->get_param_byIndex(n)->get_id(); | |
4425 | default: | |
4426 | FATAL_ERROR("Type::get_comp_id_byIndex()"); | |
4427 | } // switch | |
4428 | // to avoid warnings | |
4429 | const Identifier *fake = 0; | |
4430 | return *fake; | |
4431 | } | |
4432 | ||
4433 | CompField* Type::get_comp_byIndex(size_t n) | |
4434 | { | |
4435 | switch(typetype) { | |
4436 | case T_ANYTYPE: | |
4437 | case T_CHOICE_T: | |
4438 | case T_SEQ_T: | |
4439 | case T_SET_T: | |
4440 | case T_OPENTYPE: | |
4441 | return u.secho.cfm->get_comp_byIndex(n); | |
4442 | case T_SEQ_A: | |
4443 | case T_SET_A: | |
4444 | if(u.secho.block) parse_block_Se(); | |
4445 | return u.secho.ctss->get_comp_byIndex(n); | |
4446 | case T_CHOICE_A: | |
4447 | if(u.secho.block) parse_block_Choice(); | |
4448 | return u.secho.ctss->get_comp_byIndex(n); | |
4449 | default: | |
4450 | FATAL_ERROR("Type::get_comp_byIndex()"); | |
4451 | return 0; | |
4452 | } // switch | |
4453 | } | |
4454 | ||
4455 | size_t Type::get_comp_index_byName(const Identifier& p_name) | |
4456 | { | |
4457 | Type *t = get_type_refd_last(); | |
4458 | if (!t->is_secho()) | |
4459 | FATAL_ERROR("Type::get_comp_index_byName()"); | |
4460 | if (!t->u.secho.field_by_name) { | |
4461 | t->u.secho.field_by_name = new map<string, size_t>; | |
4462 | size_t nof_comps = t->get_nof_comps(); | |
4463 | for (size_t i = 0; i < nof_comps; i++) { | |
4464 | const string& field_name = | |
4465 | t->get_comp_byIndex(i)->get_name().get_name(); | |
4466 | if (!t->u.secho.field_by_name->has_key(field_name)) | |
4467 | t->u.secho.field_by_name->add(field_name, new size_t(i)); | |
4468 | } | |
4469 | } | |
4470 | return *(*t->u.secho.field_by_name)[p_name.get_name()]; | |
4471 | } | |
4472 | ||
4473 | size_t Type::get_eis_index_byName(const Identifier& p_name) | |
4474 | { | |
4475 | Type *t = get_type_refd_last(); | |
4476 | switch (t->typetype) { | |
4477 | case T_ENUM_A: | |
4478 | case T_ENUM_T: | |
4479 | break; | |
4480 | default: | |
4481 | FATAL_ERROR("Type::get_eis_index_byName()"); | |
4482 | } | |
4483 | if (!t->u.enums.eis_by_name) { | |
4484 | t->u.enums.eis_by_name = new map<string, size_t>; | |
4485 | size_t nof_eis = t->u.enums.eis->get_nof_eis(); | |
4486 | for (size_t i = 0; i < nof_eis; i++) { | |
4487 | const string& enum_name = | |
4488 | t->u.enums.eis->get_ei_byIndex(i)->get_name().get_name(); | |
4489 | if (!t->u.enums.eis_by_name->has_key(enum_name)) | |
4490 | t->u.enums.eis_by_name->add(enum_name, new size_t(i)); | |
4491 | } | |
4492 | } | |
4493 | return *(*t->u.enums.eis_by_name)[p_name.get_name()]; | |
4494 | } | |
4495 | ||
4496 | const Int& Type::get_enum_val_byId(const Identifier& p_name) | |
4497 | { | |
4498 | if(!checked) FATAL_ERROR("Type::get_enum_val_byId(): Not checked."); | |
4499 | switch(typetype) { | |
4500 | case T_ENUM_T: | |
4501 | case T_ENUM_A: | |
4502 | break; | |
4503 | default: | |
4504 | FATAL_ERROR("Type::get_enum_val_byId()"); | |
4505 | } | |
4506 | return u.enums.eis->get_ei_byName(p_name)->get_value() | |
4507 | ->get_value_refd_last()->get_val_Int()->get_val(); | |
4508 | } | |
4509 | ||
4510 | size_t Type::get_nof_root_comps() | |
4511 | { | |
4512 | switch(typetype) { | |
4513 | case T_SEQ_A: | |
4514 | case T_SET_A: | |
4515 | if(u.secho.block) parse_block_Se(); | |
4516 | return u.secho.ctss->get_nof_root_comps(); | |
4517 | break; | |
4518 | default: | |
4519 | FATAL_ERROR("Type::get_nof_root_comps()"); | |
4520 | return 0; | |
4521 | } // switch | |
4522 | } | |
4523 | ||
4524 | CompField* Type::get_root_comp_byIndex(size_t n) | |
4525 | { | |
4526 | switch(typetype) { | |
4527 | case T_SEQ_A: | |
4528 | case T_SET_A: | |
4529 | if(u.secho.block) parse_block_Se(); | |
4530 | return u.secho.ctss->get_root_comp_byIndex(n); | |
4531 | break; | |
4532 | default: | |
4533 | FATAL_ERROR("Type::get_root_comp_byIndex()"); | |
4534 | return 0; | |
4535 | } // switch | |
4536 | } | |
4537 | ||
4538 | bool Type::has_comp_withName(const Identifier& p_name) | |
4539 | { | |
4540 | Type *t = get_type_refd_last(); | |
4541 | switch (t->typetype) { | |
4542 | case T_CHOICE_T: | |
4543 | case T_SEQ_T: | |
4544 | case T_SET_T: | |
4545 | case T_OPENTYPE: | |
4546 | case T_ANYTYPE: | |
4547 | return t->u.secho.cfm->has_comp_withName(p_name); | |
4548 | case T_SEQ_A: | |
4549 | case T_SET_A: | |
4550 | if (t->u.secho.block) t->parse_block_Se(); | |
4551 | return t->u.secho.ctss->has_comp_withName(p_name); | |
4552 | case T_CHOICE_A: | |
4553 | if (t->u.secho.block) t->parse_block_Choice(); | |
4554 | return t->u.secho.ctss->has_comp_withName(p_name); | |
4555 | case T_SIGNATURE: | |
4556 | if (t->u.signature.parameters) | |
4557 | return t->u.signature.parameters->has_param_withName(p_name); | |
4558 | else return false; | |
4559 | default: | |
4560 | FATAL_ERROR("Type::has_comp_withName()"); | |
4561 | return 0; | |
4562 | } // switch | |
4563 | } | |
4564 | ||
4565 | CompField* Type::get_comp_byName(const Identifier& p_name) | |
4566 | { | |
4567 | Type *t = get_type_refd_last(); | |
4568 | switch (t->typetype) { | |
4569 | case T_CHOICE_T: | |
4570 | case T_SEQ_T: | |
4571 | case T_SET_T: | |
4572 | case T_OPENTYPE: | |
4573 | case T_ANYTYPE: | |
4574 | return t->u.secho.cfm->get_comp_byName(p_name); | |
4575 | case T_SEQ_A: | |
4576 | case T_SET_A: | |
4577 | if (t->u.secho.block) t->parse_block_Se(); | |
4578 | return t->u.secho.ctss->get_comp_byName(p_name); | |
4579 | case T_CHOICE_A: | |
4580 | if(t->u.secho.block) t->parse_block_Choice(); | |
4581 | return t->u.secho.ctss->get_comp_byName(p_name); | |
4582 | default: | |
4583 | FATAL_ERROR("Type::get_comp_byName()"); | |
4584 | return 0; | |
4585 | } // switch | |
4586 | } | |
4587 | ||
4588 | void Type::add_comp(CompField *p_cf) | |
4589 | { | |
4590 | switch(typetype) { | |
4591 | case T_CHOICE_T: | |
4592 | case T_SEQ_T: | |
4593 | case T_SET_T: | |
4594 | case T_OPENTYPE: | |
4595 | case T_ANYTYPE: | |
4596 | u.secho.cfm->add_comp(p_cf); | |
4597 | break; | |
4598 | default: | |
4599 | FATAL_ERROR("Type::add_comp()"); | |
4600 | } // switch | |
4601 | } | |
4602 | ||
4603 | Type *Type::get_ofType() | |
4604 | { | |
4605 | Type *t=get_type_refd_last(); | |
4606 | switch (t->typetype) { | |
4607 | case T_SEQOF: | |
4608 | case T_SETOF: | |
4609 | return t->u.seof.ofType; | |
4610 | case T_ARRAY: | |
4611 | return t->u.array.element_type; | |
4612 | default: | |
4613 | FATAL_ERROR("Type::get_ofType()"); | |
4614 | return 0; | |
4615 | } | |
4616 | } | |
4617 | ||
4618 | OC_defn* Type::get_my_oc() | |
4619 | { | |
4620 | switch(typetype) { | |
4621 | case T_OCFT: | |
4622 | return u.ref.oc_defn; | |
4623 | break; | |
4624 | case T_OPENTYPE: | |
4625 | return u.secho.oc_defn; | |
4626 | break; | |
4627 | default: | |
4628 | FATAL_ERROR("Type::get_my_oc()"); | |
4629 | return 0; | |
4630 | } // switch | |
4631 | } | |
4632 | ||
4633 | const Identifier& Type::get_oc_fieldname() | |
4634 | { | |
4635 | switch(typetype) { | |
4636 | case T_OCFT: | |
4637 | return *u.ref.oc_fieldname; | |
4638 | break; | |
4639 | case T_OPENTYPE: | |
4640 | return *u.secho.oc_fieldname; | |
4641 | break; | |
4642 | default: | |
4643 | FATAL_ERROR("Type::get_oc_fieldname()"); | |
4644 | // to avoid warning... | |
4645 | return *u.secho.oc_fieldname; | |
4646 | } // switch | |
4647 | } | |
4648 | ||
4649 | void Type::set_my_tableconstraint(const TableConstraint *p_tc) | |
4650 | { | |
4651 | switch(typetype) { | |
4652 | case T_OPENTYPE: | |
4653 | u.secho.my_tableconstraint=p_tc; | |
4654 | break; | |
4655 | default: | |
4656 | FATAL_ERROR("Type::set_my_tableconstraint()"); | |
4657 | } // switch | |
4658 | } | |
4659 | ||
4660 | const TableConstraint* Type::get_my_tableconstraint() | |
4661 | { | |
4662 | switch(typetype) { | |
4663 | case T_OPENTYPE: | |
4664 | return u.secho.my_tableconstraint; | |
4665 | break; | |
4666 | default: | |
4667 | FATAL_ERROR("Type::get_my_tableconstraint()"); | |
4668 | return 0; | |
4669 | } // switch | |
4670 | } | |
4671 | ||
4672 | Ttcn::ArrayDimension *Type::get_dimension() const | |
4673 | { | |
4674 | if (typetype != T_ARRAY) FATAL_ERROR("Type::get_dimension()"); | |
4675 | return u.array.dimension; | |
4676 | } | |
4677 | ||
4678 | Ttcn::PortTypeBody *Type::get_PortBody() const | |
4679 | { | |
4680 | if (typetype != T_PORT) FATAL_ERROR("Type::get_PortBody()"); | |
4681 | return u.port; | |
4682 | } | |
4683 | ||
4684 | ComponentTypeBody *Type::get_CompBody() const | |
4685 | { | |
4686 | if (typetype != T_COMPONENT) FATAL_ERROR("Type::get_CompBody()"); | |
4687 | return u.component; | |
4688 | } | |
4689 | ||
4690 | SignatureParamList *Type::get_signature_parameters() const | |
4691 | { | |
4692 | if (typetype != T_SIGNATURE || !checked) | |
4693 | FATAL_ERROR("Type::get_signature_parameters()"); | |
4694 | return u.signature.parameters; | |
4695 | } | |
4696 | ||
4697 | SignatureExceptions *Type::get_signature_exceptions() const | |
4698 | { | |
4699 | if (typetype != T_SIGNATURE || !checked) | |
4700 | FATAL_ERROR("Type::get_signature_exceptions()"); | |
4701 | return u.signature.exceptions; | |
4702 | } | |
4703 | ||
4704 | Type *Type::get_signature_return_type() const | |
4705 | { | |
4706 | if (typetype != T_SIGNATURE || !checked) | |
4707 | FATAL_ERROR("Type::get_signature_return_type()"); | |
4708 | return u.signature.return_type; | |
4709 | } | |
4710 | ||
4711 | bool Type::is_nonblocking_signature() const | |
4712 | { | |
4713 | if (typetype != T_SIGNATURE || !checked) | |
4714 | FATAL_ERROR("Type::is_nonblocking_signature()"); | |
4715 | return u.signature.no_block; | |
4716 | } | |
4717 | ||
4718 | Ttcn::FormalParList *Type::get_fat_parameters() | |
4719 | { | |
4720 | if(!checked) FATAL_ERROR("Type::get_fat_parameteres()"); | |
4721 | switch(typetype) { | |
4722 | case T_FUNCTION: | |
4723 | case T_ALTSTEP: | |
4724 | case T_TESTCASE: | |
4725 | return u.fatref.fp_list; | |
4726 | default: | |
4727 | FATAL_ERROR("Type::get_fat_parameteres()"); | |
4728 | return 0; | |
4729 | } | |
4730 | } | |
4731 | ||
4732 | Type *Type::get_function_return_type() | |
4733 | { | |
4734 | if(!checked) FATAL_ERROR("Type::get_function_return_type()"); | |
4735 | switch(typetype) { | |
4736 | case T_FUNCTION: | |
4737 | return u.fatref.return_type; | |
4738 | default: | |
4739 | FATAL_ERROR("Type::get_function_return_type()"); | |
4740 | return 0; | |
4741 | } | |
4742 | } | |
4743 | ||
4744 | Type *Type::get_fat_runs_on_type() | |
4745 | { | |
4746 | if(!checked) FATAL_ERROR("Type::get_fat_runs_on_type()"); | |
4747 | switch(typetype) { | |
4748 | case T_FUNCTION: | |
4749 | case T_ALTSTEP: | |
4750 | case T_TESTCASE: | |
4751 | return u.fatref.runs_on.type; | |
4752 | default: | |
4753 | FATAL_ERROR("Type::get_fat_runs_on_type()"); | |
4754 | return 0; | |
4755 | } | |
4756 | } | |
4757 | ||
4758 | bool Type::get_fat_runs_on_self() | |
4759 | { | |
4760 | if(!checked) FATAL_ERROR("Type::get_fat_runs_on_self()"); | |
4761 | switch(typetype) { | |
4762 | case T_FUNCTION: | |
4763 | case T_ALTSTEP: | |
4764 | case T_TESTCASE: | |
4765 | return u.fatref.runs_on.self; | |
4766 | default: | |
4767 | FATAL_ERROR("Type::get_fat_runs_on_self()"); | |
4768 | return false; | |
4769 | } | |
4770 | } | |
4771 | ||
4772 | bool Type::get_returns_template() | |
4773 | { | |
4774 | if (!checked || typetype != T_FUNCTION) | |
4775 | FATAL_ERROR("Type::Returns_template()"); | |
4776 | return u.fatref.returns_template; | |
4777 | } | |
4778 | ||
4779 | void Type::add_tag(Tag *p_tag) | |
4780 | { | |
4781 | if(!tags) tags=new Tags(); | |
4782 | tags->add_tag(p_tag); | |
4783 | } | |
4784 | ||
4785 | void Type::add_constraints(Constraints *p_constraints) | |
4786 | { | |
4787 | if(!p_constraints) return; | |
4788 | if(constraints) | |
4789 | FATAL_ERROR("This type already has its constraints"); | |
4790 | constraints=p_constraints; | |
4791 | constraints->set_my_type(this); | |
4792 | } | |
4793 | ||
4794 | Reference* Type::get_Reference() | |
4795 | { | |
4796 | return u.ref.ref; | |
4797 | } | |
4798 | ||
4799 | void Type::chk_table_constraints() | |
4800 | { | |
4801 | if(!tbl_cons_checked) { | |
4802 | tbl_cons_checked=true; | |
4803 | if (constraints) constraints->chk_table(); | |
4804 | switch (typetype) { | |
4805 | case T_CHOICE_A: | |
4806 | case T_CHOICE_T: | |
4807 | case T_SEQ_A: | |
4808 | case T_SEQ_T: | |
4809 | case T_SET_A: | |
4810 | case T_SET_T: | |
4811 | case T_OPENTYPE: | |
4812 | for(size_t i=0; i<get_nof_comps(); i++) | |
4813 | get_comp_byIndex(i)->get_type()->chk_table_constraints(); | |
4814 | break; | |
4815 | case T_SEQOF: | |
4816 | case T_SETOF: | |
4817 | u.seof.ofType->chk_table_constraints(); | |
4818 | break; | |
4819 | default: | |
4820 | break; | |
4821 | } | |
4822 | } | |
4823 | } | |
4824 | ||
4825 | void Type::check_subtype_constraints() | |
4826 | { | |
4827 | if (sub_type!=NULL) FATAL_ERROR("Type::check_subtype_constraints()"); | |
4828 | ||
4829 | // get parent subtype or NULL if it doesn't exist | |
4830 | SubType* parent_subtype = NULL; | |
4831 | if (is_ref()) parent_subtype = get_type_refd()->sub_type; | |
4832 | ||
4833 | // if the parent subtype is erroneous then ignore it, the error was already | |
4834 | // reported there | |
4835 | if ( (parent_subtype!=NULL) && | |
4836 | (parent_subtype->get_subtypetype()==SubtypeConstraint::ST_ERROR) ) | |
4837 | parent_subtype = NULL; | |
4838 | ||
4839 | // return if there are neither inherited nor own constraints | |
4840 | if ( (parent_subtype==NULL) && (parsed_restr==NULL) && (constraints==NULL) | |
4841 | && (SubtypeConstraint::get_asn_type_constraint(this)==NULL) ) return; | |
4842 | ||
4843 | // the subtype type is determined by the type of this type | |
4844 | if (get_type_refd_last()->get_typetype()==T_ERROR) return; | |
4845 | SubtypeConstraint::subtype_t s_t = get_subtype_type(); | |
4846 | if (s_t==SubtypeConstraint::ST_ERROR) { | |
4847 | error("Subtype constraints are not applicable to type `%s'", | |
4848 | get_typename().c_str()); | |
4849 | return; | |
4850 | } | |
4851 | ||
4852 | // create the aggregate subtype for this type | |
4853 | sub_type = new SubType(s_t, this, parent_subtype, parsed_restr, constraints); | |
4854 | sub_type->chk(); | |
4855 | } | |
4856 | ||
4857 | bool Type::has_multiple_tags() | |
4858 | { | |
4859 | if (tags) return false; | |
4860 | switch (typetype) { | |
4861 | case T_CHOICE_A: | |
4862 | case T_CHOICE_T: | |
4863 | return true; | |
4864 | case T_REFD: | |
4865 | case T_SELTYPE: | |
4866 | case T_REFDSPEC: | |
4867 | case T_OCFT: | |
4868 | return get_type_refd()->has_multiple_tags(); | |
4869 | default: | |
4870 | return false; | |
4871 | } | |
4872 | } | |
4873 | ||
4874 | Tag *Type::get_tag() | |
4875 | { | |
4876 | if (tags) { | |
4877 | Tag *tag=tags->get_tag_byIndex(tags->get_nof_tags()-1); | |
4878 | tag->chk(); | |
4879 | return tag; | |
4880 | } | |
4881 | else return get_default_tag(); | |
4882 | } | |
4883 | ||
4884 | void Type::get_tags(TagCollection& coll, map<Type*, void>& chain) | |
4885 | { | |
4886 | if(typetype!=T_CHOICE_A) | |
4887 | FATAL_ERROR("Type::get_tags()"); | |
4888 | if (chain.has_key(this)) return; | |
4889 | chain.add(this, 0); | |
4890 | if(u.secho.block) parse_block_Choice(); | |
4891 | size_t n_alts = u.secho.ctss->get_nof_comps(); | |
4892 | for(size_t i=0; i<n_alts; i++) { | |
4893 | CompField *cf = u.secho.ctss->get_comp_byIndex(i); | |
4894 | Type *type = cf->get_type(); | |
4895 | if(type->has_multiple_tags()) { | |
4896 | type=type->get_type_refd_last(); | |
4897 | type->get_tags(coll, chain); | |
4898 | } | |
4899 | else { | |
4900 | const Tag *tag=type->get_tag(); | |
4901 | if(coll.hasTag(tag)) | |
4902 | error("Alternative `%s' in CHOICE has non-distinct tag", | |
4903 | cf->get_name().get_dispname().c_str()); | |
4904 | else coll.addTag(tag); | |
4905 | } | |
4906 | } // for i | |
4907 | if(u.secho.ctss->has_ellipsis()) coll.setExtensible(); | |
4908 | } | |
4909 | ||
4910 | Tag *Type::get_smallest_tag() | |
4911 | { | |
4912 | if(!has_multiple_tags()) return get_tag()->clone(); | |
4913 | Type *t=get_type_refd_last(); | |
4914 | TagCollection tagcoll; | |
4915 | map<Type*, void> chain; | |
4916 | t->get_tags(tagcoll, chain); | |
4917 | chain.clear(); | |
4918 | return tagcoll.getSmallestTag()->clone(); | |
4919 | } | |
4920 | ||
4921 | bool Type::needs_explicit_tag() | |
4922 | { | |
4923 | switch (typetype) { | |
4924 | case T_CHOICE_A: | |
4925 | case T_CHOICE_T: | |
4926 | case T_ANY: | |
4927 | case T_OPENTYPE: | |
4928 | return true; | |
4929 | case T_REFD: { | |
4930 | if(!dynamic_cast<Asn::Ref_pard*>(u.ref.ref)) { | |
4931 | Scope *s=u.ref.ref->get_refd_assignment()->get_my_scope(); | |
4932 | if(s->get_parent_scope()!=s->get_scope_mod()) { | |
4933 | // Not in the module scope, so it is a dummyreference (X.680 | |
4934 | // 30.6c) | |
4935 | /* | |
4936 | WARNING("%s is a dummyreference, i give him an explicit tag :)", | |
4937 | get_fullname().c_str()); | |
4938 | WARNING("0: %s", s->get_scope_name().c_str()); | |
4939 | WARNING("1: %s", s->get_parent_scope()->get_scope_name().c_str()); | |
4940 | WARNING("2: %s", s->get_scope_mod()->get_scope_name().c_str()); | |
4941 | */ | |
4942 | return true; | |
4943 | } | |
4944 | } | |
4945 | // no break; | |
4946 | } // case T_REFD | |
4947 | case T_SELTYPE: | |
4948 | case T_REFDSPEC: | |
4949 | case T_OCFT: { | |
4950 | Type *t = get_type_refd(); | |
4951 | if(t->is_tagged()) return false; | |
4952 | else return t->needs_explicit_tag(); | |
4953 | break;} | |
4954 | default: | |
4955 | // T_ANYTYPE probably does not need explicit tagging | |
4956 | return false; | |
4957 | } | |
4958 | } | |
4959 | ||
4960 | void Type::cut_auto_tags() | |
4961 | { | |
4962 | if (tags) { | |
4963 | tags->cut_auto_tags(); | |
4964 | if (tags->get_nof_tags() == 0) { | |
4965 | delete tags; | |
4966 | tags = 0; | |
4967 | } | |
4968 | } | |
4969 | } | |
4970 | ||
4971 | /** | |
4972 | * I suppose in this function that tags->chk() and | |
4973 | * tags->set_plicit() are already done. | |
4974 | */ | |
4975 | Tags* Type::build_tags_joined(Tags *p_tags) | |
4976 | { | |
4977 | if(!p_tags) p_tags=new Tags(); | |
4978 | switch(typetype) { | |
4979 | // is_ref() true: | |
4980 | case T_REFD: | |
4981 | case T_SELTYPE: | |
4982 | case T_REFDSPEC: | |
4983 | case T_OCFT: | |
4984 | get_type_refd()->build_tags_joined(p_tags); | |
4985 | break; | |
4986 | case T_CHOICE_A: | |
4987 | case T_CHOICE_T: | |
4988 | //TODO case T_ANYTYPE: for build_tags_joined ? | |
4989 | case T_OPENTYPE: | |
4990 | case T_ANY: | |
4991 | break; | |
4992 | default: | |
4993 | p_tags->add_tag(get_default_tag()->clone()); | |
4994 | break; | |
4995 | } // switch | |
4996 | if(tags) { | |
4997 | for(size_t i=0; i<tags->get_nof_tags(); i++) { | |
4998 | Tag *tag=tags->get_tag_byIndex(i); | |
4999 | switch(tag->get_plicit()) { | |
5000 | case Tag::TAG_EXPLICIT: | |
5001 | p_tags->add_tag(tag->clone()); | |
5002 | break; | |
5003 | case Tag::TAG_IMPLICIT: { | |
5004 | Tag *t_p_tag=p_tags->get_tag_byIndex(p_tags->get_nof_tags()-1); | |
5005 | t_p_tag->set_tagclass(tag->get_tagclass()); | |
5006 | t_p_tag->set_tagvalue(tag->get_tagvalue()); | |
5007 | break;} | |
5008 | default: | |
5009 | FATAL_ERROR("Type::build_tags_joined()"); | |
5010 | } // switch | |
5011 | } // for | |
5012 | } // if tags | |
5013 | return p_tags; | |
5014 | } | |
5015 | ||
5016 | void Type::set_with_attr(Ttcn::MultiWithAttrib* p_attrib) | |
5017 | { | |
5018 | if(!w_attrib_path) | |
5019 | { | |
5020 | w_attrib_path = new WithAttribPath(); | |
5021 | } | |
5022 | ||
5023 | w_attrib_path->set_with_attr(p_attrib); | |
5024 | } | |
5025 | ||
5026 | void Type::set_parent_path(WithAttribPath* p_path) | |
5027 | { | |
5028 | if(!w_attrib_path) | |
5029 | { | |
5030 | w_attrib_path = new WithAttribPath(); | |
5031 | } | |
5032 | w_attrib_path->set_parent(p_path); | |
5033 | if (typetype == T_COMPONENT) | |
5034 | u.component->set_parent_path(w_attrib_path); | |
5035 | } | |
5036 | ||
5037 | WithAttribPath* Type::get_attrib_path() const | |
5038 | { | |
5039 | return w_attrib_path; | |
5040 | } | |
5041 | ||
5042 | bool Type::hasRawAttrs() | |
5043 | { | |
5044 | if(rawattrib) return true; | |
5045 | ||
5046 | if(w_attrib_path) | |
5047 | { | |
5048 | if(w_attrib_path->get_had_global_variants()) return true; | |
5049 | ||
5050 | vector<SingleWithAttrib> const &real_attribs | |
5051 | = w_attrib_path->get_real_attrib(); | |
5052 | ||
5053 | for (size_t i = 0; i < real_attribs.size(); i++) | |
5054 | if (real_attribs[i]->get_attribKeyword() | |
5055 | == SingleWithAttrib::AT_VARIANT) | |
5056 | { | |
5057 | return true; | |
5058 | } | |
5059 | ||
5060 | MultiWithAttrib* temp_attrib = w_attrib_path->get_with_attr(); | |
5061 | if(temp_attrib) | |
5062 | for(size_t i = 0; i < temp_attrib->get_nof_elements(); i++) | |
5063 | if(temp_attrib->get_element(i)->get_attribKeyword() | |
5064 | == SingleWithAttrib::AT_VARIANT | |
5065 | && (!temp_attrib->get_element(i)->get_attribQualifiers() | |
5066 | || temp_attrib->get_element(i)->get_attribQualifiers() | |
5067 | ->get_nof_qualifiers() == 0)) | |
5068 | { | |
5069 | w_attrib_path->set_had_global_variants( true ); | |
5070 | return true; | |
5071 | } | |
5072 | } | |
5073 | ||
5074 | return false; | |
5075 | } | |
5076 | ||
5077 | bool Type::hasNeedofRawAttrs() | |
5078 | { | |
5079 | if(rawattrib) return true; | |
5080 | size_t nof_comps; | |
5081 | switch(typetype){ | |
5082 | case T_CHOICE_T: | |
5083 | case T_ANYTYPE: | |
5084 | case T_SEQ_T: | |
5085 | case T_SET_T: | |
5086 | nof_comps = get_nof_comps(); | |
5087 | for(size_t i=0; i < nof_comps; i++) | |
5088 | { | |
5089 | if(get_comp_byIndex(i)->get_type()->hasNeedofRawAttrs()) | |
5090 | { | |
5091 | return true; | |
5092 | } | |
5093 | } | |
5094 | break; | |
5095 | default: | |
5096 | break; | |
5097 | } | |
5098 | return false; | |
5099 | } | |
5100 | ||
5101 | bool Type::hasNeedofTextAttrs() | |
5102 | { | |
5103 | if(textattrib) return true; | |
5104 | size_t nof_comps; | |
5105 | switch(typetype){ | |
5106 | case T_CHOICE_T: | |
5107 | case T_ANYTYPE: | |
5108 | case T_SEQ_T: | |
5109 | case T_SET_T: | |
5110 | nof_comps = get_nof_comps(); | |
5111 | for(size_t i=0; i < nof_comps; i++) | |
5112 | { | |
5113 | if(get_comp_byIndex(i)->get_type()->hasNeedofTextAttrs()) | |
5114 | { | |
5115 | return true; | |
5116 | } | |
5117 | } | |
5118 | break; | |
5119 | default: | |
5120 | break; | |
5121 | } | |
5122 | return false; | |
5123 | } | |
5124 | ||
5125 | bool Type::hasNeedofJsonAttrs() | |
5126 | { | |
5127 | if(jsonattrib) return true; | |
5128 | size_t nof_comps; | |
5129 | switch(typetype) { | |
5130 | case T_CHOICE_T: | |
5131 | case T_ANYTYPE: | |
5132 | case T_SEQ_T: | |
5133 | case T_SET_T: | |
5134 | nof_comps = get_nof_comps(); | |
5135 | for (size_t i = 0; i < nof_comps; ++i) | |
5136 | { | |
5137 | if (get_comp_byIndex(i)->get_type()->hasNeedofJsonAttrs()) | |
5138 | { | |
5139 | return true; | |
5140 | } | |
5141 | } | |
5142 | break; | |
5143 | default: | |
5144 | break; | |
5145 | } | |
5146 | return false; | |
5147 | } | |
5148 | ||
5149 | bool Type::hasNeedofXerAttrs() | |
5150 | { | |
5151 | if(xerattrib && !xerattrib->empty()) return true; | |
5152 | size_t nof_comps; | |
5153 | switch(typetype){ | |
5154 | case T_CHOICE_T: | |
5155 | case T_ANYTYPE: | |
5156 | case T_SEQ_T: | |
5157 | case T_SET_T: | |
5158 | nof_comps = get_nof_comps(); | |
5159 | for(size_t i=0; i < nof_comps; i++) | |
5160 | { | |
5161 | if(get_comp_byIndex(i)->get_type()->hasNeedofXerAttrs()) | |
5162 | { | |
5163 | return true; | |
5164 | } | |
5165 | } | |
5166 | break; | |
5167 | default: | |
5168 | break; | |
5169 | } | |
5170 | return false; | |
5171 | } | |
5172 | ||
5173 | bool Type::hasVariantAttrs() | |
5174 | { | |
5175 | if(w_attrib_path) | |
5176 | { | |
5177 | if(w_attrib_path->get_had_global_variants()) return true; | |
5178 | ||
5179 | vector<SingleWithAttrib> const &real_attribs | |
5180 | = w_attrib_path->get_real_attrib(); | |
5181 | ||
5182 | for (size_t i = 0; i < real_attribs.size(); i++) | |
5183 | if (real_attribs[i]->get_attribKeyword() | |
5184 | == SingleWithAttrib::AT_VARIANT) | |
5185 | { | |
5186 | return true; | |
5187 | } | |
5188 | ||
5189 | MultiWithAttrib* temp_attrib = w_attrib_path->get_with_attr(); | |
5190 | if(temp_attrib) | |
5191 | for(size_t i = 0; i < temp_attrib->get_nof_elements(); i++) | |
5192 | if(temp_attrib->get_element(i)->get_attribKeyword() | |
5193 | == SingleWithAttrib::AT_VARIANT | |
5194 | && (!temp_attrib->get_element(i)->get_attribQualifiers() | |
5195 | || temp_attrib->get_element(i)->get_attribQualifiers() | |
5196 | ->get_nof_qualifiers() != 0)) | |
5197 | { | |
5198 | w_attrib_path->set_had_global_variants( true ); | |
5199 | return true; | |
5200 | } | |
5201 | } | |
5202 | ||
5203 | return false; | |
5204 | } | |
5205 | ||
5206 | bool Type::hasEncodeAttr(const MessageEncodingType_t encoding_type) | |
5207 | { | |
af710487 | 5208 | if (CT_JSON == encoding_type && (implicit_json_encoding |
5209 | || is_asn1() || (is_ref() && get_type_refd()->is_asn1()))) { | |
970ed795 EL |
5210 | // ASN.1 types automatically support JSON encoding |
5211 | return true; | |
5212 | } | |
5213 | // Check the type itself first, then the root type | |
5214 | WithAttribPath *aps[2] = { 0, 0 }; | |
5215 | size_t num_aps = ((aps[0] = get_attrib_path()) != 0); | |
5216 | // assign, compare, then add 0 or 1 | |
5217 | if (is_ref()) { | |
5218 | num_aps += ((aps[num_aps] = get_type_refd()->get_attrib_path()) != 0); | |
5219 | } | |
5220 | for (size_t a = 0; a < num_aps; ++a) { | |
5221 | const vector<SingleWithAttrib>& real = aps[a]->get_real_attrib(); | |
5222 | const size_t num_atr = real.size(); | |
5223 | for (size_t i = 0; i < num_atr; ++i) { | |
5224 | const SingleWithAttrib& s = *real[i]; | |
5225 | if (s.get_attribKeyword() == SingleWithAttrib::AT_ENCODE) { | |
5226 | const string& spec = s.get_attribSpec().get_spec(); | |
5227 | if (spec == get_encoding_name(encoding_type)) { | |
5228 | return true; | |
5229 | } else { | |
5230 | // if it has an encode other than the one we're looking for, quit now | |
5231 | return false; | |
5232 | } | |
5233 | } // if ENCODE | |
5234 | } // for | |
5235 | } // next a | |
5236 | return false; | |
5237 | } | |
5238 | ||
5239 | namespace { // unnamed | |
5240 | ||
5241 | enum state { PROCESSING = -1, ANSWER_NO, ANSWER_YES }; | |
5242 | ||
5243 | struct memoizer : private map<Type*, state> { | |
5244 | memoizer() : map<Type*, state>() {} | |
5245 | ||
5246 | ~memoizer() { | |
5247 | for (int i = size()-1; i >= 0; --i) { | |
5248 | delete get_nth_elem(i); | |
5249 | } | |
5250 | clear(); | |
5251 | } | |
5252 | ||
5253 | bool remember (Type *t, state s) { | |
5254 | if (has_key(t)) { | |
5255 | *operator[](t) = s; | |
5256 | } | |
5257 | else { | |
5258 | add(t, new state(s)); | |
5259 | } | |
5260 | return s == ANSWER_YES; | |
5261 | } | |
5262 | ||
5263 | bool has_key(Type *t) { | |
5264 | return map<Type*, state>::has_key(t); | |
5265 | } | |
5266 | ||
5267 | state* get(Type *t) { | |
5268 | return operator [](t); | |
5269 | } | |
5270 | }; | |
5271 | ||
5272 | } | |
5273 | ||
5274 | bool Type::has_encoding(MessageEncodingType_t encoding_type) | |
5275 | { | |
5276 | static memoizer memory; | |
5277 | static memoizer json_mem; | |
5278 | Type *t = this; | |
5279 | switch (encoding_type) { | |
5280 | case CT_BER: | |
5281 | case CT_PER: | |
5282 | for ( ; ; ) { | |
5283 | if (t->is_asn1()) return true; | |
5284 | else if (t->is_ref()) t = t->get_type_refd(); | |
5285 | else { | |
5286 | switch (t->typetype) { | |
5287 | case T_ERROR: | |
5288 | case T_BOOL: | |
5289 | case T_INT: | |
5290 | case T_REAL: | |
5291 | case T_BSTR: | |
5292 | case T_OSTR: | |
5293 | case T_OID: | |
5294 | // these basic TTCN-3 types have ASN.1 equivalents | |
5295 | return true; | |
5296 | default: | |
5297 | return false; | |
5298 | } | |
5299 | } | |
5300 | } | |
5301 | ||
5302 | case CT_XER: { | |
5303 | if (memory.has_key(this)) { | |
5304 | state *s = memory.get(this); | |
5305 | switch (*s){ | |
5306 | case PROCESSING: | |
5307 | break; | |
5308 | case ANSWER_NO: | |
5309 | return false; | |
5310 | case ANSWER_YES: | |
5311 | return true; | |
5312 | } | |
5313 | } | |
5314 | ||
5315 | for (;;) { | |
5316 | // For ASN.1 types, the answer depends solely on the -a switch. | |
5317 | // They are all considered to have Basic (i.e. useless) XER, | |
5318 | // unless the -a switch says removes XER from all ASN.1 types. | |
5319 | if (t->is_asn1()) return memory.remember(t, | |
5320 | asn1_xer ? ANSWER_YES : ANSWER_NO); | |
5321 | else if (t->is_ref()) t = t->get_type_refd(); | |
5322 | else { // at the end of the ref. chain | |
5323 | switch (t->typetype) { | |
5324 | case T_BOOL: | |
5325 | case T_INT: | |
5326 | case T_REAL: | |
5327 | case T_BSTR: | |
5328 | case T_OSTR: | |
5329 | // The octetstring type can always be encoded in XER. | |
5330 | // XSD:base64Binary is only needed for Type::is_charenc() | |
5331 | case T_OID: | |
5332 | case T_HSTR: // TTCN-3 hexstring | |
5333 | case T_VERDICT: // TTCN-3 verdict | |
5334 | case T_CSTR: // TTCN3 charstring | |
5335 | case T_USTR: // TTCN3 universal charstring | |
5336 | return memory.remember(t, ANSWER_YES); | |
5337 | ||
5338 | case T_ENUM_T: | |
5339 | break; // the switch; skip to checking if it has encode "XML"; | |
5340 | ||
5341 | case T_PORT: // TTCN-3 port (the list of in's, out's, inout's) | |
5342 | case T_COMPONENT: // TTCN-3 comp. type (extends, and { ... }) | |
5343 | case T_DEFAULT: // TTCN-3 | |
5344 | case T_SIGNATURE: // TTCN-3 | |
5345 | case T_FUNCTION: // TTCN-3 | |
5346 | case T_ALTSTEP: // TTCN-3 | |
5347 | case T_TESTCASE: // TTCN-3 | |
5348 | case T_ANYTYPE: // TTCN-3 anytype | |
5349 | return memory.remember(t, ANSWER_NO); | |
5350 | ||
5351 | case T_UNDEF: | |
5352 | case T_ERROR: | |
5353 | case T_REFDSPEC: | |
5354 | return false; // why don't we remember these ? | |
5355 | ||
5356 | case T_SEQ_T: | |
5357 | case T_SET_T: | |
5358 | case T_CHOICE_T: { | |
5359 | // No field may reject XER | |
5360 | size_t ncomp = t->get_nof_comps(); | |
5361 | for (size_t i = 0; i < ncomp; ++i) { | |
5362 | Type *t2 = t->get_comp_byIndex(i)->get_type(); | |
5363 | bool subresult = false; | |
5364 | if (memory.has_key(t2)) { | |
5365 | switch (*memory.get(t2)) { | |
5366 | case PROCESSING: | |
5367 | // This type contains itself and is in the process | |
5368 | // of being checked. Pretend it doesn't exist. | |
5369 | // The answer will be determined by the other fields, | |
5370 | // and it will propagate back up. | |
5371 | // Avoids infinite recursion for self-referencing types. | |
5372 | continue; | |
5373 | case ANSWER_NO: | |
5374 | subresult = false; | |
5375 | break; | |
5376 | case ANSWER_YES: | |
5377 | subresult = true; | |
5378 | break; | |
5379 | } | |
5380 | } | |
5381 | else { | |
5382 | memory.remember(t2, PROCESSING); | |
5383 | subresult = t2->has_encoding(CT_XER); | |
5384 | } | |
5385 | ||
5386 | if (subresult) memory.remember(t2, ANSWER_YES); | |
5387 | else return memory.remember(t2, ANSWER_NO); | |
5388 | // Note: return only if the answer (false) is known. | |
5389 | // If the answer is true, keep checking. | |
5390 | } // next i | |
5391 | // Empty record, or all fields supported XER: answer maybe yes. | |
5392 | break; } | |
5393 | ||
5394 | case T_SEQOF: | |
5395 | case T_SETOF: { | |
5396 | bool subresult = false; | |
5397 | Type *t2 = t->u.seof.ofType; | |
5398 | if (memory.has_key(t2)) { | |
5399 | switch (*memory.get(t2)) { | |
5400 | case PROCESSING: | |
5401 | // Recursive record-of. This is OK because the recursion | |
5402 | // can always be broken with an empty record-of. | |
5403 | subresult = true; | |
5404 | break; | |
5405 | case ANSWER_NO: | |
5406 | subresult = false; | |
5407 | break; | |
5408 | case ANSWER_YES: | |
5409 | subresult = true; | |
5410 | break; | |
5411 | } | |
5412 | } | |
5413 | else { | |
5414 | memory.remember(t2, PROCESSING); | |
5415 | // Check the contained type | |
5416 | subresult = t2->has_encoding(CT_XER); | |
5417 | } | |
5418 | if (subresult) break; // continue checking | |
5419 | else return memory.remember(t, ANSWER_NO); // No means no. | |
5420 | } | |
5421 | ||
5422 | case T_NULL: // ASN.1 null | |
5423 | case T_INT_A: // ASN.1 integer | |
5424 | case T_ENUM_A:// ASN.1 enum | |
5425 | case T_BSTR_A:// ASN.1 bitstring | |
5426 | case T_UTF8STRING: // ASN.1 | |
5427 | case T_NUMERICSTRING: | |
5428 | case T_PRINTABLESTRING: | |
5429 | case T_TELETEXSTRING: | |
5430 | case T_VIDEOTEXSTRING: | |
5431 | case T_IA5STRING: | |
5432 | case T_GRAPHICSTRING: | |
5433 | case T_VISIBLESTRING: | |
5434 | case T_GENERALSTRING: | |
5435 | case T_UNIVERSALSTRING: | |
5436 | case T_BMPSTRING: | |
5437 | case T_UNRESTRICTEDSTRING: // still ASN.1 | |
5438 | case T_UTCTIME: // ASN.1 string | |
5439 | case T_GENERALIZEDTIME: // ASN.1 string | |
5440 | case T_OBJECTDESCRIPTOR: // ASN.1 string | |
5441 | case T_ROID: // relative OID (ASN.1) | |
5442 | ||
5443 | case T_CHOICE_A: // | |
5444 | case T_SEQ_A: // ASN.1 versions of choice,sequence,set | |
5445 | case T_SET_A: // | |
5446 | ||
5447 | case T_OCFT: // ObjectClassFieldType (ASN.1) | |
5448 | case T_OPENTYPE: // ASN.1 open type | |
5449 | case T_ANY: // deprecated ASN.1 ANY | |
5450 | ||
5451 | case T_EXTERNAL: // ASN.1 external | |
5452 | case T_EMBEDDED_PDV: // ASN.1 embedded pdv | |
5453 | case T_SELTYPE: // selection type (ASN.1) | |
5454 | FATAL_ERROR("Type::has_encoding(): typetype %d should be asn1", | |
5455 | t->typetype); | |
5456 | break; // not reached | |
5457 | ||
5458 | case T_REFD: // reference to another type | |
5459 | case T_ADDRESS: // TTCN-3 address type | |
5460 | case T_ARRAY: // TTCN-3 array | |
5461 | default: // FIXME: if compiling with -Wswitch, the default should be removed | |
5462 | return memory.remember(t, ANSWER_NO); | |
5463 | } // switch t->typetype | |
5464 | ||
5465 | // Check to see if it has an encode "XML"; first the type itself, | |
5466 | // then the root type. | |
5467 | WithAttribPath *aps[2] = {0,0}; | |
5468 | size_t num_aps = ((aps[0] = this->get_attrib_path()) != 0); | |
5469 | // assign, compare, then add 0 or 1 | |
5470 | if (this != t) { | |
5471 | num_aps += ((aps[num_aps] = t->get_attrib_path()) != 0); | |
5472 | } | |
5473 | for (size_t a = 0; a < num_aps; ++a) { | |
5474 | const vector<SingleWithAttrib>& real = aps[a]->get_real_attrib(); | |
5475 | const size_t num_atr = real.size(); | |
5476 | for (size_t i = 0; i < num_atr; ++i) { | |
5477 | const SingleWithAttrib& s = *real[i]; | |
5478 | if (s.get_attribKeyword() == SingleWithAttrib::AT_ENCODE) { | |
5479 | const string& spec = s.get_attribSpec().get_spec(); | |
5480 | if (spec == ex_emm_ell // the right answer | |
5481 | ||spec == ex_ee_arr) // the acceptable answer | |
5482 | return memory.remember(t, ANSWER_YES); | |
5483 | else // if it has an encode other than XER, quit now | |
5484 | return memory.remember(t, ANSWER_NO); | |
5485 | } // if ENCODE | |
5486 | } // for | |
5487 | } // next a | |
5488 | return memory.remember(t, ANSWER_NO); // no encode XER | |
5489 | } // if(!asn1) | |
5490 | } // for(ever) | |
5491 | return memory.remember(t, ANSWER_NO); } | |
5492 | ||
5493 | case CT_RAW: | |
5494 | for ( ; ; ) { | |
5495 | if (t->rawattrib) return true; | |
5496 | else if (t->is_ref()) t = t->get_type_refd(); | |
5497 | else { | |
5498 | switch (t->typetype) { | |
5499 | case T_ERROR: | |
5500 | case T_BOOL: | |
5501 | case T_INT: | |
5502 | case T_REAL: | |
5503 | case T_BSTR: | |
5504 | case T_HSTR: | |
5505 | case T_OSTR: | |
5506 | case T_CSTR: | |
5507 | // these basic types support RAW encoding by default | |
5508 | return true; | |
5509 | default: | |
5510 | return false; | |
5511 | } | |
5512 | } | |
5513 | } | |
5514 | ||
5515 | case CT_TEXT: | |
5516 | for ( ; ; ) { | |
5517 | if (t->textattrib) return true; | |
5518 | else if (t->is_ref()) t = t->get_type_refd(); | |
5519 | else { | |
5520 | switch (t->typetype) { | |
5521 | case T_ERROR: | |
5522 | case T_BOOL: | |
5523 | case T_INT: | |
5524 | case T_OSTR: | |
5525 | case T_CSTR: | |
5526 | // these basic types support TEXT encoding by default | |
5527 | return true; | |
5528 | default: | |
5529 | return false; | |
5530 | } | |
5531 | } | |
5532 | } | |
5533 | ||
5534 | case CT_JSON: | |
5535 | while (true) { | |
5536 | if (json_mem.has_key(t)) { | |
5537 | switch (*json_mem.get(t)) { | |
5538 | case PROCESSING: | |
5539 | break; | |
5540 | case ANSWER_NO: | |
5541 | return false; | |
5542 | case ANSWER_YES: | |
5543 | return true; | |
5544 | } | |
5545 | } | |
5546 | if (t->jsonattrib) { | |
5547 | return json_mem.remember(t, ANSWER_YES); | |
5548 | } | |
5549 | if (t->is_ref()) { | |
5550 | t = t->get_type_refd(); | |
5551 | } | |
5552 | else { | |
5553 | switch (t->typetype) { | |
5554 | case T_ERROR: | |
5555 | case T_BOOL: | |
5556 | case T_INT: | |
5557 | case T_INT_A: | |
5558 | case T_REAL: | |
5559 | case T_BSTR: | |
5560 | case T_BSTR_A: | |
5561 | case T_HSTR: | |
5562 | case T_OSTR: | |
5563 | case T_CSTR: | |
5564 | case T_USTR: | |
5565 | case T_UTF8STRING: | |
5566 | case T_NUMERICSTRING: | |
5567 | case T_PRINTABLESTRING: | |
5568 | case T_TELETEXSTRING: | |
5569 | case T_VIDEOTEXSTRING: | |
5570 | case T_IA5STRING: | |
5571 | case T_GRAPHICSTRING: | |
5572 | case T_VISIBLESTRING: | |
5573 | case T_GENERALSTRING: | |
5574 | case T_UNIVERSALSTRING: | |
5575 | case T_BMPSTRING: | |
5576 | case T_VERDICT: | |
af710487 | 5577 | case T_NULL: |
5578 | case T_OID: | |
5579 | case T_ROID: | |
5580 | case T_ANY: | |
970ed795 EL |
5581 | // these basic types support JSON encoding by default |
5582 | return json_mem.remember(t, ANSWER_YES); | |
5583 | case T_SEQ_T: | |
5584 | case T_SEQ_A: | |
af710487 | 5585 | case T_OPENTYPE: |
970ed795 EL |
5586 | case T_SET_T: |
5587 | case T_SET_A: | |
5588 | case T_CHOICE_T: | |
5589 | case T_CHOICE_A: | |
5590 | case T_ANYTYPE: { | |
5591 | // all fields must also support JSON encoding | |
5592 | size_t ncomp = t->get_nof_comps(); | |
5593 | for (size_t i = 0; i < ncomp; ++i) { | |
5594 | Type *t2 = t->get_comp_byIndex(i)->get_type(); | |
5595 | if (json_mem.has_key(t2)) { | |
5596 | switch (*json_mem.get(t2)) { | |
5597 | case ANSWER_YES: | |
5598 | // This field is OK, but we still need to check the others | |
5599 | case PROCESSING: | |
5600 | // This type contains itself and is in the process | |
5601 | // of being checked. Pretend it doesn't exist. | |
5602 | // The answer will be determined by the other fields, | |
5603 | // and it will propagate back up. | |
5604 | // Avoids infinite recursion for self-referencing types. | |
5605 | continue; | |
5606 | case ANSWER_NO: | |
5607 | // One field is not OK => the structure is not OK | |
5608 | return json_mem.remember(t, ANSWER_NO); | |
5609 | } | |
5610 | } | |
5611 | else { | |
5612 | json_mem.remember(t2, PROCESSING); | |
5613 | bool enabled = t2->has_encoding(CT_JSON); | |
5614 | json_mem.remember(t2, enabled ? ANSWER_YES : ANSWER_NO); | |
5615 | if (!enabled) { | |
5616 | // One field is not OK => the structure is not OK | |
5617 | return json_mem.remember(t, ANSWER_NO); | |
5618 | } | |
5619 | } | |
5620 | } | |
5621 | break; // check for an encode attribute | |
5622 | } | |
5623 | case T_SEQOF: | |
5624 | case T_SETOF: | |
5625 | case T_ARRAY: { | |
5626 | Type *t2 = t->u.seof.ofType; | |
5627 | if (json_mem.has_key(t2)) { | |
5628 | switch (*json_mem.get(t2)) { | |
5629 | case ANSWER_YES: | |
5630 | // Continue checking | |
5631 | case PROCESSING: | |
5632 | // Recursive record-of. This is OK because the recursion | |
5633 | // can always be broken with an empty record-of. | |
5634 | break; | |
5635 | case ANSWER_NO: | |
5636 | return json_mem.remember(t, ANSWER_NO); | |
5637 | break; | |
5638 | } | |
5639 | } | |
5640 | else { | |
5641 | json_mem.remember(t2, PROCESSING); | |
5642 | bool enabled = t2->has_encoding(CT_JSON); | |
5643 | json_mem.remember(t2, enabled ? ANSWER_YES : ANSWER_NO); | |
5644 | if (!enabled) { | |
5645 | // One field is not OK => the structure is not OK | |
5646 | return json_mem.remember(t, ANSWER_NO); | |
5647 | } | |
5648 | } | |
5649 | break; // check for an encode attribute | |
5650 | } | |
5651 | case T_ENUM_T: | |
5652 | case T_ENUM_A: | |
5653 | break; // check for an encode attribute | |
af710487 | 5654 | default: |
970ed795 EL |
5655 | return json_mem.remember(t, ANSWER_NO); |
5656 | } // switch | |
5657 | return json_mem.remember(t, hasEncodeAttr(CT_JSON) ? ANSWER_YES : ANSWER_NO); | |
5658 | } // else | |
5659 | } // while | |
5660 | ||
5661 | default: | |
5662 | FATAL_ERROR("Type::has_encoding()"); | |
5663 | return false; | |
5664 | } | |
5665 | } | |
5666 | ||
5667 | ||
5668 | bool Type::is_pure_refd() | |
5669 | { | |
5670 | switch (typetype) { | |
5671 | case T_REFD: | |
5672 | // ASN.1 parameterized references are not pure :) | |
5673 | if(dynamic_cast<Asn::Ref_pard*>(u.ref.ref)) return false; | |
5674 | // no break; | |
5675 | case T_REFDSPEC: | |
5676 | case T_SELTYPE: | |
5677 | case T_OCFT: | |
5678 | if (sub_type || constraints) return false; | |
5679 | else if (tags && enable_ber()) return false; | |
5680 | else if (rawattrib && enable_raw()) return false; | |
5681 | else if (textattrib && enable_text()) return false; | |
5682 | else if (enable_xer()) return false; | |
5683 | else if (jsonattrib && enable_json()) return false; | |
5684 | else return true; | |
5685 | default: | |
5686 | return false; | |
5687 | } | |
5688 | } | |
5689 | ||
5690 | string Type::create_stringRepr() | |
5691 | { | |
5692 | if(is_tagged() || hasRawAttrs()) | |
5693 | return get_genname_own(); | |
5694 | switch(typetype) { | |
5695 | case T_NULL: | |
5696 | return string("NULL"); | |
5697 | case T_BOOL: | |
5698 | return string("BOOLEAN"); | |
5699 | case T_INT: | |
5700 | case T_INT_A: | |
5701 | return string("INTEGER"); | |
5702 | case T_REAL: | |
5703 | return string("REAL"); | |
5704 | case T_BSTR: | |
5705 | case T_BSTR_A: | |
5706 | return string("BIT__STRING"); | |
5707 | case T_HSTR: | |
5708 | return string("HEX__STRING"); | |
5709 | case T_OSTR: | |
5710 | return string("OCTET__STRING"); | |
5711 | case T_CSTR: | |
5712 | return string("CHAR__STRING"); | |
5713 | case T_USTR: | |
5714 | return string("UNIVERSAL__CHARSTRING"); | |
5715 | case T_UTF8STRING: | |
5716 | return string("UTF8String"); | |
5717 | case T_NUMERICSTRING: | |
5718 | return string("NumericString"); | |
5719 | case T_PRINTABLESTRING: | |
5720 | return string("PrintableString"); | |
5721 | case T_TELETEXSTRING: | |
5722 | return string("TeletexString"); | |
5723 | case T_VIDEOTEXSTRING: | |
5724 | return string("VideotexString"); | |
5725 | case T_IA5STRING: | |
5726 | return string("IA5String"); | |
5727 | case T_GRAPHICSTRING: | |
5728 | return string("GraphicString"); | |
5729 | case T_VISIBLESTRING: | |
5730 | return string("VisibleString"); | |
5731 | case T_GENERALSTRING: | |
5732 | return string("GeneralString"); | |
5733 | case T_UNIVERSALSTRING: | |
5734 | return string("UniversalString"); | |
5735 | case T_BMPSTRING: | |
5736 | return string("BMPString"); | |
5737 | case T_UNRESTRICTEDSTRING: | |
5738 | return string("CHARACTER__STRING"); | |
5739 | case T_UTCTIME: | |
5740 | return string("UTCTime"); | |
5741 | case T_GENERALIZEDTIME: | |
5742 | return string("GeneralizedTime"); | |
5743 | case T_OBJECTDESCRIPTOR: | |
5744 | return string("ObjectDescriptor"); | |
5745 | case T_OID: | |
5746 | return string("OBJECT__IDENTIFIER"); | |
5747 | case T_ROID: | |
5748 | return string("RELATIVE__OID"); | |
5749 | case T_ANY: | |
5750 | return string("ANY"); | |
5751 | case T_REFD: | |
5752 | case T_SELTYPE: | |
5753 | case T_REFDSPEC: | |
5754 | case T_OCFT: | |
5755 | if (tags || constraints || | |
5756 | (w_attrib_path && w_attrib_path->has_attribs())) | |
5757 | return get_genname_own(); | |
5758 | else return get_type_refd()->get_stringRepr(); | |
5759 | case T_ERROR: | |
5760 | return string("<Error_type>"); | |
5761 | default: | |
5762 | return get_genname_own(); | |
5763 | } // switch | |
5764 | } | |
5765 | ||
5766 | Identifier Type::get_otaltname(bool& is_strange) | |
5767 | { | |
5768 | string s; | |
5769 | if (is_tagged() || is_constrained() || hasRawAttrs()) { | |
5770 | s = get_genname_own(); | |
5771 | is_strange = true; | |
5772 | } else if (typetype == T_REFD) { | |
5773 | Ref_simple* t_ref=dynamic_cast<Ref_simple*>(u.ref.ref); | |
5774 | if (t_ref) { | |
5775 | const Identifier *id = t_ref->get_id(); | |
5776 | const string& dispname = id->get_dispname(); | |
5777 | if (dispname.find('.') < dispname.size()) { | |
5778 | // id is not regular because t_ref is a parameterized reference | |
5779 | // use that id anyway | |
5780 | s += id->get_name(); | |
5781 | is_strange = true; | |
5782 | } else { | |
5783 | Scope *ass_scope = t_ref->get_refd_assignment()->get_my_scope(); | |
5784 | if (ass_scope->get_parent_scope() == ass_scope->get_scope_mod()) { | |
5785 | // t_ref points to an assignment at module scope | |
5786 | // use the simple id of the reference (in lowercase) | |
5787 | s = id->get_name(); | |
5788 | is_strange = false; | |
5789 | } else { | |
5790 | // t_ref is a dummy reference in a parameterized assignment | |
5791 | // (i.e. it points to a parameter assignment of an instantiation) | |
5792 | // perform the same examination recursively on the referenced type | |
5793 | // (which is the actual parameter) | |
5794 | return get_type_refd()->get_otaltname(is_strange); | |
5795 | } | |
5796 | } | |
5797 | } else { | |
5798 | // the type comes from an information object [class] | |
5799 | // examine the referenced type recursively | |
5800 | return get_type_refd()->get_otaltname(is_strange); | |
5801 | } | |
5802 | } else { | |
5803 | s = get_stringRepr(); | |
5804 | // throw away the leading @ if this is an instantiated type | |
5805 | // (e.g. an in-line SEQUENCE from a parameterized reference) | |
5806 | if (!strncmp(s.c_str(), "_root_", 6)) s.replace(0, 6, ""); | |
5807 | // the name is strange if it contains a single underscore | |
5808 | string s2(s); | |
5809 | // transform "__" -> "-" | |
5810 | for (size_t pos = 0; ; ) { | |
5811 | pos = s2.find("__", pos); | |
5812 | if (pos < s2.size()) { | |
5813 | s2.replace(pos, 2, "-"); | |
5814 | pos++; | |
5815 | } else break; | |
5816 | } | |
5817 | is_strange = s2.find('_') < s2.size(); | |
5818 | } | |
5819 | /* | |
5820 | size_t pos=s.find_if(0, s.size(), isupper); | |
5821 | if(pos==s.size()) FATAL_ERROR("Type::get_otaltname() (`%s')", s.c_str()); | |
5822 | s[pos]=tolower(s[pos]); | |
5823 | */ | |
5824 | s[0]=tolower(s[0]); | |
5825 | Identifier tmp_id(Identifier::ID_NAME, s, true); | |
5826 | /* This is because the origin of the returned ID must be ASN. */ | |
5827 | return Identifier(Identifier::ID_ASN, tmp_id.get_asnname()); | |
5828 | } | |
5829 | ||
5830 | string Type::get_genname_value(Scope *p_scope) | |
5831 | { | |
5832 | Type *t = get_type_refd_last(); | |
5833 | switch (t->typetype) { | |
5834 | case T_UNDEF: | |
5835 | case T_ERROR: | |
5836 | case T_UNRESTRICTEDSTRING: | |
5837 | case T_OCFT: | |
5838 | case T_EXTERNAL: | |
5839 | case T_EMBEDDED_PDV: | |
5840 | case T_REFD: | |
5841 | case T_REFDSPEC: | |
5842 | case T_SELTYPE: | |
5843 | FATAL_ERROR("Type::get_genname_value()"); | |
5844 | case T_NULL: | |
5845 | return string("ASN_NULL"); | |
5846 | case T_BOOL: | |
5847 | return string("BOOLEAN"); | |
5848 | case T_INT: | |
5849 | case T_INT_A: | |
5850 | return string("INTEGER"); | |
5851 | case T_REAL: | |
5852 | return string("FLOAT"); | |
5853 | case T_BSTR: | |
5854 | case T_BSTR_A: | |
5855 | return string("BITSTRING"); | |
5856 | case T_HSTR: | |
5857 | return string("HEXSTRING"); | |
5858 | case T_OSTR: | |
5859 | return string("OCTETSTRING"); | |
5860 | case T_CSTR: | |
5861 | case T_NUMERICSTRING: | |
5862 | case T_PRINTABLESTRING: | |
5863 | case T_IA5STRING: | |
5864 | case T_VISIBLESTRING: | |
5865 | case T_UTCTIME: | |
5866 | case T_GENERALIZEDTIME: | |
5867 | return string("CHARSTRING"); | |
5868 | case T_USTR: // ttcn3 universal charstring | |
5869 | case T_UTF8STRING: | |
5870 | case T_TELETEXSTRING: | |
5871 | case T_VIDEOTEXSTRING: | |
5872 | case T_GRAPHICSTRING: | |
5873 | case T_GENERALSTRING: | |
5874 | case T_UNIVERSALSTRING: | |
5875 | case T_BMPSTRING: | |
5876 | case T_OBJECTDESCRIPTOR: | |
5877 | return string("UNIVERSAL_CHARSTRING"); | |
5878 | case T_OID: | |
5879 | case T_ROID: | |
5880 | return string("OBJID"); | |
5881 | case T_ANY: | |
5882 | return string("ASN_ANY"); | |
5883 | case T_VERDICT: | |
5884 | return string("VERDICTTYPE"); | |
5885 | case T_COMPONENT: | |
5886 | return string("COMPONENT"); | |
5887 | case T_DEFAULT: | |
5888 | return string("DEFAULT"); | |
5889 | case T_ARRAY: | |
5890 | if (!t->u.array.in_typedef) | |
5891 | return t->u.array.dimension->get_value_type(t->u.array.element_type, | |
5892 | p_scope); | |
5893 | // no break | |
5894 | default: | |
5895 | return t->get_genname_own(p_scope); | |
5896 | } // switch | |
5897 | } | |
5898 | ||
5899 | string Type::get_genname_template(Scope *p_scope) | |
5900 | { | |
5901 | Type *t = get_type_refd_last(); | |
5902 | string ret_val; | |
5903 | switch (t->typetype) { | |
5904 | case T_ERROR: | |
5905 | case T_PORT: | |
5906 | // template classes do not exist for these types | |
5907 | FATAL_ERROR("Type::get_genname_template()"); | |
5908 | case T_ARRAY: | |
5909 | // a template class has to be instantiated in case of arrays | |
5910 | // outside type definitions | |
5911 | if (!t->u.array.in_typedef) { | |
5912 | ret_val = t->u.array.dimension->get_template_type( | |
5913 | t->u.array.element_type, p_scope); | |
5914 | break; | |
5915 | } | |
5916 | // no break | |
5917 | default: | |
5918 | // in case of other types the name of the template class is derived | |
5919 | // from the value class by appending a suffix | |
5920 | ret_val = t->get_genname_value(p_scope); | |
5921 | ret_val += "_template"; | |
5922 | break; | |
5923 | } | |
5924 | return ret_val; | |
5925 | } | |
5926 | ||
5927 | string Type::get_genname_altname() | |
5928 | { | |
5929 | Type *t_last = get_type_refd_last(); | |
5930 | Scope *t_scope = t_last->get_my_scope(); | |
5931 | switch (t_last->typetype) { | |
5932 | case T_UNDEF: | |
5933 | case T_ERROR: | |
5934 | case T_UNRESTRICTEDSTRING: | |
5935 | case T_OCFT: | |
5936 | case T_EXTERNAL: | |
5937 | case T_EMBEDDED_PDV: | |
5938 | case T_REFD: | |
5939 | case T_REFDSPEC: | |
5940 | case T_SELTYPE: | |
5941 | FATAL_ERROR("Type::get_genname_altname()"); | |
5942 | case T_ENUM_A: | |
5943 | case T_ENUM_T: | |
5944 | case T_CHOICE_A: | |
5945 | case T_CHOICE_T: | |
5946 | case T_SEQOF: | |
5947 | case T_SETOF: | |
5948 | case T_SEQ_A: | |
5949 | case T_SEQ_T: | |
5950 | case T_SET_A: | |
5951 | case T_SET_T: | |
5952 | case T_OPENTYPE: | |
5953 | case T_ANYTYPE: // FIXME this does not yet work | |
5954 | case T_PORT: | |
5955 | case T_COMPONENT: | |
5956 | case T_ARRAY: | |
5957 | case T_SIGNATURE: | |
5958 | case T_FUNCTION: | |
5959 | case T_ALTSTEP: | |
5960 | case T_TESTCASE: { | |
5961 | // user-defined types | |
5962 | // always use the qualified name (including module identifier) | |
5963 | string ret_val(t_scope->get_scope_mod_gen()->get_modid().get_name()); | |
5964 | ret_val += '_'; | |
5965 | ret_val += t_last->get_genname_own(); | |
5966 | return ret_val; } | |
5967 | default: | |
5968 | // built-in types | |
5969 | // use the simple class name from the base library | |
5970 | return t_last->get_genname_value(t_scope); | |
5971 | } | |
5972 | } | |
5973 | ||
5974 | string Type::get_typename() | |
5975 | { | |
5976 | Type *t = get_type_refd_last(); | |
5977 | const char* tn = get_typename_builtin(t->typetype); | |
5978 | if (tn != 0) return string(tn); | |
5979 | switch (t->typetype) { | |
5980 | case T_COMPONENT: | |
5981 | case T_SIGNATURE: | |
5982 | case T_CHOICE_A: | |
5983 | case T_CHOICE_T: | |
5984 | case T_ANYTYPE: | |
5985 | case T_SEQ_A: | |
5986 | case T_SEQ_T: | |
5987 | case T_SET_A: | |
5988 | case T_SET_T: | |
5989 | case T_SEQOF: | |
5990 | case T_SETOF: | |
5991 | case T_ENUM_A: | |
5992 | case T_ENUM_T: | |
5993 | case T_PORT: | |
5994 | case T_FUNCTION: | |
5995 | case T_ALTSTEP: | |
5996 | case T_TESTCASE: | |
5997 | return t->get_fullname(); | |
5998 | case T_ARRAY: { | |
5999 | string dimensions(t->u.array.dimension->get_stringRepr()); | |
6000 | t = t->u.array.element_type; | |
6001 | while (t->typetype == T_ARRAY) { | |
6002 | dimensions += t->u.array.dimension->get_stringRepr(); | |
6003 | t = t->u.array.element_type; | |
6004 | } | |
6005 | return t->get_typename() + dimensions; } | |
6006 | default: | |
6007 | FATAL_ERROR("Type::get_typename()"); | |
6008 | return string(); | |
6009 | } // switch | |
6010 | } | |
6011 | ||
6012 | // static | |
6013 | const char* Type::get_typename_builtin(typetype_t tt) | |
6014 | { | |
6015 | switch (tt) { | |
6016 | case T_ERROR: | |
6017 | return "Erroneous type"; | |
6018 | case T_NULL: | |
6019 | return "NULL"; | |
6020 | case T_BOOL: | |
6021 | return "boolean"; | |
6022 | case T_INT: | |
6023 | case T_INT_A: | |
6024 | return "integer"; | |
6025 | case T_REAL: | |
6026 | return "float"; | |
6027 | case T_BSTR: | |
6028 | case T_BSTR_A: | |
6029 | return "bitstring"; | |
6030 | case T_HSTR: | |
6031 | return "hexstring"; | |
6032 | case T_OSTR: | |
6033 | return "octetstring"; | |
6034 | case T_CSTR: | |
6035 | return "charstring"; | |
6036 | case T_USTR: | |
6037 | return "universal charstring"; | |
6038 | case T_UTF8STRING: | |
6039 | return "UTF8String"; | |
6040 | case T_NUMERICSTRING: | |
6041 | return "NumericString"; | |
6042 | case T_PRINTABLESTRING: | |
6043 | return "PrintableString"; | |
6044 | case T_TELETEXSTRING: | |
6045 | return "TeletexString"; | |
6046 | case T_VIDEOTEXSTRING: | |
6047 | return "VideotexString"; | |
6048 | case T_IA5STRING: | |
6049 | return "IA5String"; | |
6050 | case T_GRAPHICSTRING: | |
6051 | return "GraphicString"; | |
6052 | case T_VISIBLESTRING: | |
6053 | return "VisibleString"; | |
6054 | case T_GENERALSTRING: | |
6055 | return "GeneralString"; | |
6056 | case T_UNIVERSALSTRING: | |
6057 | return "UniversalString"; | |
6058 | case T_BMPSTRING: | |
6059 | return "BMPString"; | |
6060 | case T_UTCTIME: | |
6061 | return "UTCTime"; | |
6062 | case T_GENERALIZEDTIME: | |
6063 | return "GeneralizedTime"; | |
6064 | case T_OBJECTDESCRIPTOR: | |
6065 | return "ObjectDescriptor"; | |
6066 | case T_OID: | |
6067 | case T_ROID: | |
6068 | return "objid"; | |
6069 | case T_ANY: | |
6070 | return "ANY"; | |
6071 | case T_VERDICT: | |
6072 | return "verdicttype"; | |
6073 | case T_DEFAULT: | |
6074 | return "default"; | |
6075 | case T_EXTERNAL: | |
6076 | return "EXTERNAL"; | |
6077 | case T_EMBEDDED_PDV: | |
6078 | return "EMBEDDED PDV"; | |
6079 | case T_UNRESTRICTEDSTRING: | |
6080 | return "CHARACTER STRING"; | |
6081 | case T_OPENTYPE: | |
6082 | return "open type"; | |
6083 | case T_ADDRESS: | |
6084 | return "address"; | |
6085 | default: | |
6086 | return 0; | |
6087 | } | |
6088 | } | |
6089 | ||
6090 | string Type::get_genname_typedescriptor(Scope *p_scope) | |
6091 | { | |
6092 | Type *t = this; | |
6093 | for ( ; ; ) { | |
6094 | /* If it has tags or encoding attributes, then its encoding may be | |
6095 | * different from the other "equivalent" types and needs to have its own | |
6096 | * descriptor. | |
6097 | */ | |
6098 | if (t->is_tagged() || t->rawattrib || t->textattrib || t->jsonattrib || | |
6099 | (t->xerattrib && !t->xerattrib->empty() )) | |
6100 | { | |
6101 | return t->get_genname_own(p_scope); | |
6102 | } | |
6103 | else if (t->is_ref()) { | |
6104 | if (t->has_encoding(CT_XER)) { | |
6105 | // just fetch the referenced type and return | |
6106 | return t->get_type_refd()->get_genname_own(p_scope); | |
6107 | } | |
6108 | else | |
6109 | { // follow the white rabbit | |
6110 | t = t->get_type_refd(); | |
6111 | } | |
6112 | } | |
6113 | else break; | |
6114 | } | |
6115 | return t->get_genname_typename(p_scope); | |
6116 | } | |
6117 | ||
6118 | string Type::get_genname_typename(Scope *p_scope) | |
6119 | { | |
6120 | Type *t = get_type_refd_last(); | |
6121 | switch (t->typetype) { | |
6122 | case T_UTF8STRING: | |
6123 | return string("UTF8String"); | |
6124 | case T_NUMERICSTRING: | |
6125 | return string("NumericString"); | |
6126 | case T_PRINTABLESTRING: | |
6127 | return string("PrintableString"); | |
6128 | case T_TELETEXSTRING: | |
6129 | return string("TeletexString"); | |
6130 | case T_VIDEOTEXSTRING: | |
6131 | return string("VideotexString"); | |
6132 | case T_IA5STRING: | |
6133 | return string("IA5String"); | |
6134 | case T_GRAPHICSTRING: | |
6135 | return string("GraphicString"); | |
6136 | case T_VISIBLESTRING: | |
6137 | return string("VisibleString"); | |
6138 | case T_GENERALSTRING: | |
6139 | return string("GeneralString"); | |
6140 | case T_UNIVERSALSTRING: | |
6141 | return string("UniversalString"); | |
6142 | case T_BMPSTRING: | |
6143 | return string("BMPString"); | |
6144 | case T_UTCTIME: | |
6145 | return string("ASN_UTCTime"); | |
6146 | case T_GENERALIZEDTIME: | |
6147 | return string("ASN_GeneralizedTime"); | |
6148 | case T_OBJECTDESCRIPTOR: | |
6149 | return string("ObjectDescriptor"); | |
6150 | case T_ROID: | |
6151 | return string("ASN_ROID"); | |
6152 | default: | |
6153 | return t->get_genname_value(p_scope); | |
6154 | } // switch | |
6155 | } | |
6156 | ||
6157 | string Type::get_genname_berdescriptor() | |
6158 | { | |
6159 | Type *t = this; | |
6160 | for ( ; ; ) { | |
6161 | if (t->is_tagged()) return t->get_genname_own(my_scope); | |
6162 | else if (t->is_ref()) t = t->get_type_refd(); | |
6163 | else break; | |
6164 | } | |
6165 | switch (t->typetype) { | |
6166 | case T_ENUM_A: | |
6167 | case T_ENUM_T: | |
6168 | return string("ENUMERATED"); | |
6169 | case T_CHOICE_A: | |
6170 | case T_CHOICE_T: | |
6171 | case T_OPENTYPE: | |
6172 | return string("CHOICE"); | |
6173 | case T_SEQ_A: | |
6174 | case T_SEQ_T: | |
6175 | case T_SEQOF: | |
6176 | return string("SEQUENCE"); | |
6177 | case T_SET_A: | |
6178 | case T_SET_T: | |
6179 | case T_SETOF: | |
6180 | return string("SET"); | |
6181 | default: | |
6182 | return t->get_genname_typename(my_scope); | |
6183 | } // switch | |
6184 | } | |
6185 | ||
6186 | string Type::get_genname_rawdescriptor() | |
6187 | { | |
6188 | Type *t = this; | |
6189 | for ( ; ; ) { | |
6190 | if (t->rawattrib) return t->get_genname_own(my_scope); | |
6191 | else if (t->is_ref()) t = t->get_type_refd(); | |
6192 | else break; | |
6193 | } | |
6194 | return t->get_genname_typename(my_scope); | |
6195 | } | |
6196 | ||
6197 | string Type::get_genname_textdescriptor() | |
6198 | { | |
6199 | Type *t = this; | |
6200 | for ( ; ; ) { | |
6201 | if (t->textattrib) return t->get_genname_own(my_scope); | |
6202 | else if (t->is_ref()) t = t->get_type_refd(); | |
6203 | else break; | |
6204 | } | |
6205 | return t->get_genname_typename(my_scope); | |
6206 | } | |
6207 | ||
6208 | string Type::get_genname_xerdescriptor() | |
6209 | { | |
6210 | if (T_REFDSPEC == typetype) { | |
6211 | return get_genname_typedescriptor(my_scope); | |
6212 | } | |
6213 | else return genname; | |
6214 | } | |
6215 | ||
6216 | string Type::get_genname_jsondescriptor() | |
6217 | { | |
6218 | Type *t = this; | |
6219 | while (true) { | |
6220 | if (t->jsonattrib) return t->get_genname_own(my_scope); | |
6221 | else if (t->is_ref()) t = t->get_type_refd(); | |
6222 | else break; | |
6223 | } | |
6224 | return t->get_genname_typename(my_scope); | |
6225 | } | |
6226 | ||
6227 | const char* Type::get_genname_typedescr_asnbasetype() | |
6228 | { | |
6229 | switch (get_type_refd_last()->typetype) { | |
6230 | case T_BMPSTRING: | |
6231 | return "BMPSTRING"; | |
6232 | case T_UNIVERSALSTRING: | |
6233 | return "UNIVERSALSTRING"; | |
6234 | case T_UTF8STRING: | |
6235 | return "UTF8STRING"; | |
6236 | case T_TELETEXSTRING: | |
6237 | return "TELETEXSTRING"; | |
6238 | case T_VIDEOTEXSTRING: | |
6239 | return "VIDEOTEXSTRING"; | |
6240 | case T_OBJECTDESCRIPTOR: | |
6241 | case T_GRAPHICSTRING: | |
6242 | return "GRAPHICSTRING"; | |
6243 | case T_GENERALSTRING: | |
6244 | return "GENERALSTRING"; | |
6245 | case T_OID: | |
6246 | return "OBJID"; | |
6247 | case T_ROID: | |
6248 | return "ROID"; | |
6249 | default: | |
6250 | return "DONTCARE"; | |
6251 | } // switch | |
6252 | } | |
6253 | ||
6254 | void Type::dump(unsigned level) const | |
6255 | { | |
6256 | DEBUG(level, "Type @ %p, '%s'", (const void*)this, get_fullname().c_str()); | |
6257 | switch(typetype) { | |
6258 | case T_ERROR: | |
6259 | DEBUG(level, "Type: <erroneous>"); | |
6260 | break; | |
6261 | case T_NULL: | |
6262 | DEBUG(level, "Type: NULL"); | |
6263 | break; | |
6264 | case T_BOOL: | |
6265 | DEBUG(level, "Type: boolean"); | |
6266 | break; | |
6267 | case T_INT: | |
6268 | DEBUG(level, "Type: integer"); | |
6269 | break; | |
6270 | case T_INT_A: | |
6271 | DEBUG(level, "Type: INTEGER"); | |
6272 | if(u.namednums.block) | |
6273 | DEBUG(level, "with unparsed block"); | |
6274 | if(u.namednums.nvs) { | |
6275 | DEBUG(level, "with named numbers (%lu pcs.)", | |
6276 | (unsigned long) u.namednums.nvs->get_nof_nvs()); | |
6277 | u.namednums.nvs->dump(level+1); | |
6278 | } | |
6279 | break; | |
6280 | case T_REAL: | |
6281 | DEBUG(level, "Type: float/REAL"); | |
6282 | break; | |
6283 | case T_ENUM_A: | |
6284 | case T_ENUM_T: | |
6285 | DEBUG(level, "Type: enumerated"); | |
6286 | u.enums.eis->dump(level+1); | |
6287 | break; | |
6288 | case T_BSTR: | |
6289 | DEBUG(level, "Type: bitstring"); | |
6290 | break; | |
6291 | case T_BSTR_A: | |
6292 | DEBUG(level, "Type: BIT STRING"); | |
6293 | if(u.namednums.block) | |
6294 | DEBUG(level, "with unparsed block"); | |
6295 | if(u.namednums.nvs) { | |
6296 | DEBUG(level, "with named numbers (%lu pcs.)", | |
6297 | (unsigned long) u.namednums.nvs->get_nof_nvs()); | |
6298 | u.namednums.nvs->dump(level+1); | |
6299 | } | |
6300 | break; | |
6301 | case T_HSTR: | |
6302 | DEBUG(level, "Type: hexstring"); | |
6303 | break; | |
6304 | case T_OSTR: | |
6305 | DEBUG(level, "Type: octetstring"); | |
6306 | break; | |
6307 | case T_CSTR: | |
6308 | DEBUG(level, "Type: charstring"); | |
6309 | break; | |
6310 | case T_USTR: | |
6311 | DEBUG(level, "Type: universal charstring"); | |
6312 | break; | |
6313 | case T_UTF8STRING: | |
6314 | DEBUG(level, "Type: UTF8String"); | |
6315 | break; | |
6316 | case T_NUMERICSTRING: | |
6317 | DEBUG(level, "Type: NumericString"); | |
6318 | break; | |
6319 | case T_PRINTABLESTRING: | |
6320 | DEBUG(level, "Type: PrintableString"); | |
6321 | break; | |
6322 | case T_TELETEXSTRING: | |
6323 | DEBUG(level, "Type: TeletexString"); | |
6324 | break; | |
6325 | case T_VIDEOTEXSTRING: | |
6326 | DEBUG(level, "Type: VideotexString"); | |
6327 | break; | |
6328 | case T_IA5STRING: | |
6329 | DEBUG(level, "Type: IA5String"); | |
6330 | break; | |
6331 | case T_GRAPHICSTRING: | |
6332 | DEBUG(level, "Type: GraphicString"); | |
6333 | break; | |
6334 | case T_VISIBLESTRING: | |
6335 | DEBUG(level, "Type: VisibleString"); | |
6336 | break; | |
6337 | case T_GENERALSTRING: | |
6338 | DEBUG(level, "Type: GeneralString"); | |
6339 | break; | |
6340 | case T_UNIVERSALSTRING: | |
6341 | DEBUG(level, "Type: UniversalString"); | |
6342 | break; | |
6343 | case T_BMPSTRING: | |
6344 | DEBUG(level, "Type: BMPString"); | |
6345 | break; | |
6346 | case T_UNRESTRICTEDSTRING: | |
6347 | DEBUG(level, "Type: CHARACTER STRING"); | |
6348 | break; | |
6349 | case T_UTCTIME: | |
6350 | DEBUG(level, "Type: UTCTime"); | |
6351 | break; | |
6352 | case T_GENERALIZEDTIME: | |
6353 | DEBUG(level, "Type: GeneralizedTime"); | |
6354 | break; | |
6355 | case T_OBJECTDESCRIPTOR: | |
6356 | DEBUG(level, "Type: OBJECT DESCRIPTOR"); | |
6357 | break; | |
6358 | case T_OID: | |
6359 | DEBUG(level, "Type: objid/OBJECT IDENTIFIER"); | |
6360 | break; | |
6361 | case T_ROID: | |
6362 | DEBUG(level, "Type: RELATIVE-OID"); | |
6363 | break; | |
6364 | case T_ANYTYPE: | |
6365 | DEBUG(level, "Type: anytype!!!"); | |
6366 | u.secho.cfm->dump(level+1); | |
6367 | break; | |
6368 | case T_CHOICE_T: | |
6369 | DEBUG(level, "Type: union"); | |
6370 | u.secho.cfm->dump(level+1); | |
6371 | break; | |
6372 | case T_CHOICE_A: | |
6373 | DEBUG(level, "Type: CHOICE"); | |
6374 | if(u.secho.block) | |
6375 | DEBUG(level, "with unparsed block"); | |
6376 | if(u.secho.ctss) { | |
6377 | DEBUG(level, "with alternatives (%lu pcs.)", | |
6378 | (unsigned long) u.secho.ctss->get_nof_comps()); | |
6379 | u.secho.ctss->dump(level+1); | |
6380 | } | |
6381 | break; | |
6382 | case T_SEQOF: | |
6383 | DEBUG(level, "Type: record of/SEQUENCE OF"); | |
6384 | DEBUG(level+1, "of type:"); | |
6385 | u.seof.ofType->dump(level+2); | |
6386 | break; | |
6387 | case T_SETOF: | |
6388 | DEBUG(level, "Type: set of/SET OF"); | |
6389 | DEBUG(level+1, "of type:"); | |
6390 | u.seof.ofType->dump(level+2); | |
6391 | break; | |
6392 | case T_SEQ_T: | |
6393 | DEBUG(level, "Type: record"); | |
6394 | u.secho.cfm->dump(level+1); | |
6395 | break; | |
6396 | case T_SET_T: | |
6397 | DEBUG(level, "Type: set"); | |
6398 | u.secho.cfm->dump(level+1); | |
6399 | break; | |
6400 | case T_SEQ_A: | |
6401 | DEBUG(level, "Type: SEQUENCE"); | |
6402 | if(u.secho.block) | |
6403 | DEBUG(level, "with unparsed block"); | |
6404 | if(u.secho.ctss) { | |
6405 | DEBUG(level, "with components (%lu pcs.)", | |
6406 | (unsigned long) u.secho.ctss->get_nof_comps()); | |
6407 | u.secho.ctss->dump(level+1); | |
6408 | } | |
6409 | break; | |
6410 | case T_SET_A: | |
6411 | DEBUG(level, "Type: SET"); | |
6412 | if(u.secho.block) | |
6413 | DEBUG(level, "with unparsed block"); | |
6414 | if(u.secho.ctss) { | |
6415 | DEBUG(level, "with components (%lu pcs.)", | |
6416 | (unsigned long) u.secho.ctss->get_nof_comps()); | |
6417 | u.secho.ctss->dump(level+1); | |
6418 | } | |
6419 | break; | |
6420 | case T_OCFT: | |
6421 | DEBUG(level, "Type: ObjectClassFieldType (%s)", | |
6422 | const_cast<Type*>(this)->get_type_refd()->get_stringRepr().c_str()); | |
6423 | break; | |
6424 | case T_OPENTYPE: | |
6425 | DEBUG(level, "Type: opentype (mapped to CHOICE)"); | |
6426 | u.secho.cfm->dump(level+1); | |
6427 | break; | |
6428 | case T_ANY: | |
6429 | DEBUG(level, "Type: ANY"); | |
6430 | break; | |
6431 | case T_EXTERNAL: | |
6432 | DEBUG(level, "Type: EXTERNAL"); | |
6433 | break; | |
6434 | case T_EMBEDDED_PDV: | |
6435 | DEBUG(level, "Type: EMBEDDED PDV"); | |
6436 | break; | |
6437 | case T_REFD: | |
6438 | DEBUG(level, "Type: reference"); | |
6439 | u.ref.ref->dump(level+1); | |
6440 | if(u.ref.type_refd && u.ref.type_refd->typetype==T_OPENTYPE) | |
6441 | u.ref.type_refd->dump(level+1); | |
6442 | break; | |
6443 | case T_REFDSPEC: | |
6444 | DEBUG(level, "Type: reference (spec) to %s:", | |
6445 | u.ref.type_refd->get_fullname().c_str()); | |
6446 | u.ref.type_refd->dump(level + 1); | |
6447 | break; | |
6448 | case T_SELTYPE: | |
6449 | DEBUG(level, "Type: selection type"); | |
6450 | DEBUG(level+1, "`%s' <", u.seltype.id->get_dispname().c_str()); | |
6451 | u.seltype.type->dump(level+1); | |
6452 | break; | |
6453 | case T_VERDICT: | |
6454 | DEBUG(level, "Type: verdicttype"); | |
6455 | break; | |
6456 | case T_PORT: | |
6457 | DEBUG(level, "Type: port"); | |
6458 | u.port->dump(level + 1); | |
6459 | break; | |
6460 | case T_COMPONENT: | |
6461 | DEBUG(level, "Type: component"); | |
6462 | u.component->dump(level + 1); | |
6463 | break; | |
6464 | case T_ADDRESS: | |
6465 | DEBUG(level, "Type: address"); | |
6466 | break; | |
6467 | case T_DEFAULT: | |
6468 | DEBUG(level, "Type: default"); | |
6469 | break; | |
6470 | case T_ARRAY: | |
6471 | DEBUG(level, "Type: array"); | |
6472 | DEBUG(level + 1, "element type:"); | |
6473 | u.array.element_type->dump(level + 2); | |
6474 | DEBUG(level + 1, "dimension:"); | |
6475 | u.array.dimension->dump(level + 2); | |
6476 | break; | |
6477 | case T_SIGNATURE: | |
6478 | DEBUG(level, "Type: signature"); | |
6479 | if (u.signature.parameters) { | |
6480 | DEBUG(level+1,"parameter(s):"); | |
6481 | u.signature.parameters->dump(level+2); | |
6482 | } | |
6483 | if (u.signature.return_type) { | |
6484 | DEBUG(level+1,"return type"); | |
6485 | u.signature.return_type->dump(level+2); | |
6486 | } | |
6487 | if (u.signature.no_block) DEBUG(level+1,"no block"); | |
6488 | if (u.signature.exceptions) { | |
6489 | DEBUG(level+1,"exception(s):"); | |
6490 | u.signature.exceptions->dump(level+2); | |
6491 | } | |
6492 | break; | |
6493 | case T_FUNCTION: | |
6494 | DEBUG(level, "Type: function"); | |
6495 | DEBUG(level+1, "Parameters:"); | |
6496 | u.fatref.fp_list->dump(level+2); | |
6497 | if (u.fatref.return_type) { | |
6498 | if (!u.fatref.returns_template) { | |
6499 | DEBUG(level+1, "Return type:"); | |
6500 | } else { | |
6501 | if (u.fatref.template_restriction==TR_OMIT) | |
6502 | DEBUG(level+1, "Returns template of type:"); | |
6503 | else | |
6504 | DEBUG(level+1, "Returns template(%s) of type:", | |
6505 | Template::get_restriction_name(u.fatref.template_restriction)); | |
6506 | } | |
6507 | u.fatref.return_type->dump(level+2); | |
6508 | } | |
6509 | if(u.fatref.runs_on.ref) { | |
6510 | DEBUG(level+1, "Runs on clause:"); | |
6511 | u.fatref.runs_on.ref->dump(level+2); | |
6512 | } else { | |
6513 | if (u.fatref.runs_on.self) DEBUG(level+1, "Runs on self"); | |
6514 | } | |
6515 | break; | |
6516 | case T_ALTSTEP: | |
6517 | DEBUG(level, "Type: altstep"); | |
6518 | DEBUG(level+1, "Parameters:"); | |
6519 | u.fatref.fp_list->dump(level+2); | |
6520 | if(u.fatref.runs_on.ref) { | |
6521 | DEBUG(level+1, "Runs on clause:"); | |
6522 | u.fatref.runs_on.ref->dump(level+2); | |
6523 | } else { | |
6524 | if (u.fatref.runs_on.self) DEBUG(level+1, "Runs on self"); | |
6525 | } | |
6526 | break; | |
6527 | case T_TESTCASE: | |
6528 | DEBUG(level, "Type: testcase"); | |
6529 | DEBUG(level+1, "Parameters:"); | |
6530 | u.fatref.fp_list->dump(level+2); | |
6531 | if(u.fatref.runs_on.ref) { | |
6532 | DEBUG(level+1, "Runs on clause:"); | |
6533 | u.fatref.runs_on.ref->dump(level+2); | |
6534 | } | |
6535 | if(u.fatref.system.ref) { | |
6536 | DEBUG(level+1, "System clause:"); | |
6537 | u.fatref.system.ref->dump(level+2); | |
6538 | } | |
6539 | break; | |
6540 | default: | |
6541 | DEBUG(level, "type (%d - %s)", typetype, const_cast<Type*>(this)->get_stringRepr().c_str()); | |
6542 | } // switch | |
6543 | DEBUG(level, "ownertype %2d", ownertype); | |
6544 | if(sub_type!=NULL) { | |
6545 | DEBUG(level, "with subtype"); | |
6546 | sub_type->dump(level+1); | |
6547 | } | |
6548 | if(tags) { | |
6549 | DEBUG(level, "with tags"); | |
6550 | tags->dump(level+1); | |
6551 | } | |
6552 | ||
6553 | if(w_attrib_path && w_attrib_path->get_with_attr()) | |
6554 | { | |
6555 | DEBUG(level, "Attributes"); | |
6556 | w_attrib_path->dump(level); | |
6557 | //w_attrib_path->get_with_attr()->dump(level); | |
6558 | } | |
6559 | ||
6560 | if (xerattrib) { | |
6561 | xerattrib->print(get_fullname().c_str()); | |
6562 | } | |
6563 | } | |
6564 | ||
6565 | SubtypeConstraint::subtype_t Type::get_subtype_type() | |
6566 | { | |
6567 | Type* t = get_type_refd_last(); | |
6568 | switch (t->get_typetype()) { | |
6569 | case T_INT: | |
6570 | case T_INT_A: | |
6571 | return SubtypeConstraint::ST_INTEGER; | |
6572 | case T_REAL: | |
6573 | return SubtypeConstraint::ST_FLOAT; | |
6574 | case T_BOOL: | |
6575 | return SubtypeConstraint::ST_BOOLEAN; | |
6576 | case T_VERDICT: | |
6577 | return SubtypeConstraint::ST_VERDICTTYPE; | |
6578 | case T_OID: | |
6579 | case T_ROID: | |
6580 | return SubtypeConstraint::ST_OBJID; | |
6581 | case T_BSTR: | |
6582 | case T_BSTR_A: | |
6583 | return SubtypeConstraint::ST_BITSTRING; | |
6584 | case T_HSTR: | |
6585 | return SubtypeConstraint::ST_HEXSTRING; | |
6586 | case T_OSTR: | |
6587 | return SubtypeConstraint::ST_OCTETSTRING; | |
6588 | case T_TELETEXSTRING: | |
6589 | case T_VIDEOTEXSTRING: | |
6590 | case T_GRAPHICSTRING: | |
6591 | case T_GENERALSTRING: | |
6592 | case T_OBJECTDESCRIPTOR: | |
6593 | // iso2022str | |
6594 | case T_CSTR: | |
6595 | case T_NUMERICSTRING: | |
6596 | case T_PRINTABLESTRING: | |
6597 | case T_IA5STRING: | |
6598 | case T_VISIBLESTRING: | |
6599 | case T_UTCTIME: | |
6600 | case T_GENERALIZEDTIME: | |
6601 | return SubtypeConstraint::ST_CHARSTRING; | |
6602 | case T_USTR: | |
6603 | case T_UTF8STRING: | |
6604 | case T_UNIVERSALSTRING: | |
6605 | case T_BMPSTRING: | |
6606 | return SubtypeConstraint::ST_UNIVERSAL_CHARSTRING; | |
6607 | case T_ENUM_T: | |
6608 | case T_ENUM_A: | |
6609 | case T_NULL: // FIXME: this should have it's own ST_NULL case | |
6610 | return SubtypeConstraint::ST_ENUM; | |
6611 | case T_CHOICE_T: | |
6612 | case T_CHOICE_A: | |
6613 | case T_ANYTYPE: // (titan's hacked anytype is a choice) | |
6614 | case T_OPENTYPE: | |
6615 | return SubtypeConstraint::ST_UNION; | |
6616 | case T_SEQOF: | |
6617 | return SubtypeConstraint::ST_RECORDOF; | |
6618 | case T_SETOF: | |
6619 | return SubtypeConstraint::ST_SETOF; | |
6620 | case T_SEQ_T: | |
6621 | case T_SEQ_A: | |
6622 | case T_EXTERNAL: // associated ASN.1 type is a SEQUENCE | |
6623 | case T_EMBEDDED_PDV: // associated ASN.1 type is a SEQUENCE | |
6624 | case T_UNRESTRICTEDSTRING: // associated ASN.1 type is a SEQUENCE | |
6625 | return SubtypeConstraint::ST_RECORD; | |
6626 | case T_SET_T: | |
6627 | case T_SET_A: | |
6628 | return SubtypeConstraint::ST_SET; | |
6629 | case T_FUNCTION: | |
6630 | return SubtypeConstraint::ST_FUNCTION; | |
6631 | case T_ALTSTEP: | |
6632 | return SubtypeConstraint::ST_ALTSTEP; | |
6633 | case T_TESTCASE: | |
6634 | return SubtypeConstraint::ST_TESTCASE; | |
6635 | default: | |
6636 | return SubtypeConstraint::ST_ERROR; | |
6637 | } | |
6638 | } | |
6639 | ||
6640 | void Type::set_parsed_restrictions(vector<SubTypeParse> *stp) | |
6641 | { | |
6642 | if(!parsed_restr)parsed_restr=stp; | |
6643 | else FATAL_ERROR("Type::set_parsed_restrictions(): restrictions " | |
6644 | "are already set."); | |
6645 | } | |
6646 | ||
6647 | bool Type::is_component_internal() | |
6648 | { | |
6649 | if (!checked) chk(); | |
6650 | switch (typetype) { | |
6651 | case T_DEFAULT: | |
6652 | case T_PORT: | |
6653 | return true; | |
6654 | case T_FUNCTION: | |
6655 | case T_ALTSTEP: | |
6656 | return u.fatref.runs_on.self; | |
6657 | case T_CHOICE_T: | |
6658 | case T_SEQ_T: | |
6659 | case T_SET_T: | |
6660 | return u.secho.component_internal; | |
6661 | case T_SEQOF: | |
6662 | case T_SETOF: | |
6663 | return u.seof.component_internal; | |
6664 | case T_ARRAY: | |
6665 | return u.array.component_internal; | |
6666 | case T_SIGNATURE: | |
6667 | return u.signature.component_internal; | |
6668 | case T_REFD: | |
6669 | case T_REFDSPEC: | |
6670 | return u.ref.component_internal; | |
6671 | default: | |
6672 | return false; | |
6673 | } //switch | |
6674 | } | |
6675 | ||
6676 | void Type::chk_component_internal(map<Type*,void>& type_chain, | |
6677 | const char* p_what) | |
6678 | { | |
6679 | Type* t_last = get_type_refd_last(); | |
6680 | switch (t_last->typetype) { | |
6681 | // types that cannot be sent | |
6682 | case T_DEFAULT: | |
6683 | error("Default type cannot be %s", p_what); | |
6684 | break; | |
6685 | case T_PORT: | |
6686 | error("Port type `%s' cannot be %s", t_last->get_typename().c_str(), | |
6687 | p_what); | |
6688 | break; | |
6689 | case T_FUNCTION: | |
6690 | if (t_last->u.fatref.runs_on.self) { | |
6691 | error("Function type `%s' with 'runs on self' clause cannot be %s", | |
6692 | t_last->get_typename().c_str(), p_what); | |
6693 | } | |
6694 | break; | |
6695 | case T_ALTSTEP: | |
6696 | if (t_last->u.fatref.runs_on.self) { | |
6697 | error("Altstep type `%s' with 'runs on self' clause cannot be %s", | |
6698 | t_last->get_typename().c_str(), p_what); | |
6699 | } | |
6700 | break; | |
6701 | // structured types that may contain types that cannot be sent | |
6702 | case T_CHOICE_T: | |
6703 | case T_SEQ_T: | |
6704 | case T_SET_T: | |
6705 | case T_SEQOF: | |
6706 | case T_SETOF: | |
6707 | case T_ARRAY: | |
6708 | case T_SIGNATURE: { | |
6709 | if (type_chain.has_key(t_last)) break; | |
6710 | type_chain.add(t_last, 0); | |
6711 | Error_Context cntxt(this, "In type `%s'", get_typename().c_str()); | |
6712 | switch (t_last->typetype) { | |
6713 | case T_CHOICE_T: | |
6714 | case T_SEQ_T: | |
6715 | case T_SET_T: { | |
6716 | size_t nof_comps = t_last->get_nof_comps(); | |
6717 | for (size_t i=0; i<nof_comps; i++) { | |
6718 | Type* t = t_last->get_comp_byIndex(i)->get_type(); | |
6719 | if (t->is_component_internal()) | |
6720 | t->chk_component_internal(type_chain, p_what); | |
6721 | } | |
6722 | } break; | |
6723 | case T_SEQOF: | |
6724 | case T_SETOF: | |
6725 | if (t_last->u.seof.ofType->is_component_internal()) | |
6726 | t_last->u.seof.ofType->chk_component_internal(type_chain, p_what); | |
6727 | break; | |
6728 | case T_ARRAY: | |
6729 | if (t_last->u.array.element_type->is_component_internal()) | |
6730 | t_last->u.array.element_type->chk_component_internal(type_chain, | |
6731 | p_what); | |
6732 | break; | |
6733 | case T_SIGNATURE: | |
6734 | if (t_last->u.signature.parameters) { | |
6735 | size_t nof_params = t_last->u.signature.parameters->get_nof_params(); | |
6736 | for (size_t i=0; i<nof_params; i++) { | |
6737 | Type* t = t_last->u.signature.parameters-> | |
6738 | get_param_byIndex(i)->get_type(); | |
6739 | if (t->is_component_internal()) | |
6740 | t->chk_component_internal(type_chain, p_what); | |
6741 | } | |
6742 | } | |
6743 | if (t_last->u.signature.return_type && | |
6744 | t_last->u.signature.return_type->is_component_internal()) { | |
6745 | t_last->u.signature.return_type->chk_component_internal(type_chain, | |
6746 | p_what); | |
6747 | } | |
6748 | if (t_last->u.signature.exceptions) { | |
6749 | size_t nof_types = t_last->u.signature.exceptions->get_nof_types(); | |
6750 | for (size_t i=0; i<nof_types; i++) { | |
6751 | Type* t = t_last->u.signature.exceptions->get_type_byIndex(i); | |
6752 | if (t->is_component_internal()) | |
6753 | t->chk_component_internal(type_chain, p_what); | |
6754 | } | |
6755 | } | |
6756 | break; | |
6757 | default: | |
6758 | FATAL_ERROR("Type::chk_component_internal()"); | |
6759 | } | |
6760 | type_chain.erase(t_last); | |
6761 | } break; | |
6762 | default: //all other types are Ok. | |
6763 | break; | |
6764 | } // switch | |
6765 | } | |
6766 | ||
6767 | Type::typetype_t Type::search_for_not_allowed_type(map<Type*,void>& type_chain, | |
6768 | map<typetype_t, void>& not_allowed) | |
6769 | { | |
6770 | if (!checked) chk(); | |
6771 | Type* t_last = get_type_refd_last(); | |
6772 | Type::typetype_t ret = t_last->typetype; | |
6773 | ||
6774 | if (not_allowed.has_key(t_last->typetype)) { | |
6775 | return ret; | |
6776 | } | |
6777 | ||
6778 | switch (t_last->typetype) { | |
6779 | case T_CHOICE_T: | |
6780 | case T_SEQ_T: | |
6781 | case T_SET_T: | |
6782 | case T_SEQOF: | |
6783 | case T_SETOF: | |
6784 | case T_ARRAY: { | |
6785 | if (type_chain.has_key(t_last)) { | |
6786 | break; | |
6787 | } | |
6788 | type_chain.add(t_last, 0); | |
6789 | switch (t_last->typetype) { | |
6790 | case T_CHOICE_T: | |
6791 | case T_SEQ_T: | |
6792 | case T_SET_T: { | |
6793 | size_t nof_comps = t_last->get_nof_comps(); | |
6794 | for (size_t i = 0; i < nof_comps; ++i) { | |
6795 | Type* t = t_last->get_comp_byIndex(i)->get_type(); | |
6796 | ret = t->search_for_not_allowed_type(type_chain, not_allowed); | |
6797 | if (not_allowed.has_key(ret)) { | |
6798 | return ret; | |
6799 | } | |
6800 | } | |
6801 | } break; | |
6802 | case T_SEQOF: | |
6803 | case T_SETOF: | |
6804 | case T_ARRAY: | |
6805 | ret = t_last->get_ofType()->search_for_not_allowed_type(type_chain, not_allowed); | |
6806 | if (not_allowed.has_key(ret)) { | |
6807 | return ret; | |
6808 | } | |
6809 | break; | |
6810 | default: | |
6811 | break; | |
6812 | } | |
6813 | type_chain.erase(t_last); | |
6814 | } | |
6815 | break; | |
6816 | default: | |
6817 | break; | |
6818 | } | |
6819 | return t_last->typetype; | |
6820 | } | |
6821 | ||
6822 | string Type::get_dispname() const | |
6823 | { | |
970ed795 EL |
6824 | string dispname = genname; |
6825 | size_t pos = 0; | |
6826 | while(pos < dispname.size()) { | |
6827 | pos = dispname.find("__", pos); | |
6828 | if (pos == dispname.size()) { | |
6829 | break; | |
6830 | } | |
6831 | dispname.replace(pos, 1, ""); | |
6832 | ++pos; | |
6833 | } | |
6834 | return dispname; | |
6835 | } | |
6836 | ||
6837 | } // namespace Common | |
6838 |