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