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