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 | * Balasko, Jeno | |
10 | * Delic, Adam | |
11 | * Feher, Csaba | |
12 | * Forstner, Matyas | |
13 | * Gecse, Roland | |
14 | * Kovacs, Ferenc | |
15 | * Raduly, Csaba | |
16 | * Szabados, Kristof | |
17 | * Szabo, Janos Zoltan – initial implementation | |
18 | * Szalai, Gabor | |
19 | * Tatarka, Gabor | |
20 | * Zalanyi, Balazs Andor | |
21 | * | |
22 | ******************************************************************************/ | |
970ed795 EL |
23 | #include "Typestuff.hh" |
24 | #include "CompField.hh" | |
25 | #include "asn1/Tag.hh" | |
26 | #include "main.hh" | |
27 | ||
28 | namespace Common { | |
29 | ||
30 | using Asn::TagDefault; | |
31 | ||
32 | // ================================= | |
33 | // ===== ExcSpec | |
34 | // ================================= | |
35 | ||
36 | ExcSpec::ExcSpec(Type *p_type, Value *p_value) | |
37 | : Node() | |
38 | { | |
39 | if(!p_value) | |
40 | FATAL_ERROR("NULL parameter: Asn::ExcSpec::ExcSpec()"); | |
41 | type=p_type?p_type:new Type(Type::T_INT); | |
42 | type->set_ownertype(Type::OT_EXC_SPEC, this); | |
43 | value=p_value; | |
44 | } | |
45 | ||
46 | ExcSpec::ExcSpec(const ExcSpec& p) | |
47 | : Node(p) | |
48 | { | |
49 | type=p.type->clone(); | |
50 | value=p.value->clone(); | |
51 | } | |
52 | ||
53 | ExcSpec::~ExcSpec() | |
54 | { | |
55 | delete type; | |
56 | delete value; | |
57 | } | |
58 | ||
59 | ExcSpec *ExcSpec::clone() const | |
60 | { | |
61 | return new ExcSpec(*this); | |
62 | } | |
63 | ||
64 | void ExcSpec::set_my_scope(Scope *p_scope) | |
65 | { | |
66 | type->set_my_scope(p_scope); | |
67 | value->set_my_scope(p_scope); | |
68 | } | |
69 | ||
70 | void ExcSpec::set_fullname(const string& p_fullname) | |
71 | { | |
72 | Node::set_fullname(p_fullname); | |
73 | type->set_fullname(p_fullname); | |
74 | value->set_fullname(p_fullname); | |
75 | } | |
76 | ||
77 | // ================================= | |
78 | // ===== CTs | |
79 | // ================================= | |
80 | ||
81 | CTs::~CTs() | |
82 | { | |
83 | for(size_t i=0; i<cts.size(); i++) delete cts[i]; | |
84 | cts.clear(); | |
85 | } | |
86 | ||
87 | CTs::CTs(const CTs& p) | |
88 | : Node(p) | |
89 | { | |
90 | for(size_t i=0; i<p.cts.size(); i++) | |
91 | cts.add(p.cts[i]->clone()); | |
92 | } | |
93 | ||
94 | CTs *CTs::clone() const | |
95 | { | |
96 | return new CTs(*this); | |
97 | } | |
98 | ||
99 | void CTs::set_fullname(const string& p_fullname) | |
100 | { | |
101 | Node::set_fullname(p_fullname); | |
102 | for(size_t i=0; i<cts.size(); i++) | |
103 | // cts[i]->set_fullname(get_fullname()+"."+Int2string(i+1)); | |
104 | cts[i]->set_fullname(get_fullname()); | |
105 | } | |
106 | ||
107 | void CTs::set_my_scope(Scope *p_scope) | |
108 | { | |
109 | for(size_t i=0; i<cts.size(); i++) | |
110 | cts[i]->set_my_scope(p_scope); | |
111 | } | |
112 | ||
113 | size_t CTs::get_nof_comps() const | |
114 | { | |
115 | size_t n=0; | |
116 | for(size_t i=0; i<cts.size(); i++) | |
117 | n+=cts[i]->get_nof_comps(); | |
118 | return n; | |
119 | } | |
120 | ||
121 | CompField* CTs::get_comp_byIndex(size_t n) const | |
122 | { | |
123 | size_t offset = n; | |
124 | for(size_t i = 0; i < cts.size(); i++) { | |
125 | size_t size = cts[i]->get_nof_comps(); | |
126 | if (offset < size) return cts[i]->get_comp_byIndex(offset); | |
127 | else offset -= size; | |
128 | } | |
129 | FATAL_ERROR("%s: Requested index %lu does not exist.", \ | |
130 | get_fullname().c_str(), (unsigned long) n); | |
131 | return 0; | |
132 | } | |
133 | ||
134 | bool CTs::has_comp_withName(const Identifier& p_name) const | |
135 | { | |
136 | for(size_t i=0; i<cts.size(); i++) | |
137 | if(cts[i]->has_comp_withName(p_name)) return true; | |
138 | return false; | |
139 | } | |
140 | ||
141 | CompField* CTs::get_comp_byName(const Identifier& p_name) const | |
142 | { | |
143 | for(size_t i=0; i<cts.size(); i++) | |
144 | if(cts[i]->has_comp_withName(p_name)) | |
145 | return cts[i]->get_comp_byName(p_name); | |
146 | FATAL_ERROR("`%s': No component with name `%s'", \ | |
147 | get_fullname().c_str(), p_name.get_dispname().c_str()); | |
148 | return 0; | |
149 | } | |
150 | ||
151 | void CTs::tr_compsof(ReferenceChain *refch, bool is_set) | |
152 | { | |
153 | for(size_t i = 0; i < cts.size(); i++) | |
154 | cts[i]->tr_compsof(refch, is_set); | |
155 | } | |
156 | ||
157 | void CTs::add_ct(CT* p_ct) | |
158 | { | |
159 | if(!p_ct) | |
160 | FATAL_ERROR("NULL parameter: Asn::CTs::add_ct()"); | |
161 | cts.add(p_ct); | |
162 | } | |
163 | ||
164 | void CTs::dump(unsigned level) const | |
165 | { | |
166 | for(size_t i=0; i<cts.size(); i++) | |
167 | cts[i]->dump(level); | |
168 | } | |
169 | ||
170 | // ================================= | |
171 | // ===== CTs_EE_CTs | |
172 | // ================================= | |
173 | ||
174 | CTs_EE_CTs::CTs_EE_CTs(CTs *p_cts1, ExtAndExc *p_ee, CTs *p_cts2) | |
175 | : Node(), my_type(0), checked(false) | |
176 | { | |
177 | cts1 = p_cts1? p_cts1 : new CTs; | |
178 | ee = p_ee; | |
179 | cts2 = p_cts2 ? p_cts2 : new CTs; | |
180 | } | |
181 | ||
182 | CTs_EE_CTs::~CTs_EE_CTs() | |
183 | { | |
184 | delete cts1; | |
185 | delete ee; | |
186 | delete cts2; | |
187 | comps_v.clear(); | |
188 | comps_m.clear(); | |
189 | } | |
190 | ||
191 | CTs_EE_CTs::CTs_EE_CTs(const CTs_EE_CTs& p) | |
192 | : Node(p), my_type(p.my_type), checked(false) | |
193 | { | |
194 | cts1 = p.cts1->clone(); | |
195 | ee = p.ee ? p.ee->clone() : 0; | |
196 | cts2 = p.cts2->clone(); | |
197 | } | |
198 | ||
199 | CTs_EE_CTs *CTs_EE_CTs::clone() const | |
200 | { | |
201 | return new CTs_EE_CTs(*this); | |
202 | } | |
203 | ||
204 | void CTs_EE_CTs::set_fullname(const string& p_fullname) | |
205 | { | |
206 | Node::set_fullname(p_fullname); | |
207 | cts1->set_fullname(p_fullname); | |
208 | if (ee) ee->set_fullname(p_fullname); | |
209 | cts2->set_fullname(p_fullname); | |
210 | } | |
211 | ||
212 | void CTs_EE_CTs::set_my_scope(Scope *p_scope) | |
213 | { | |
214 | cts1->set_my_scope(p_scope); | |
215 | if (ee) ee->set_my_scope(p_scope); | |
216 | cts2->set_my_scope(p_scope); | |
217 | } | |
218 | ||
219 | size_t CTs_EE_CTs::get_nof_comps() | |
220 | { | |
221 | if (!checked) chk(); | |
222 | return comps_v.size(); | |
223 | } | |
224 | ||
225 | size_t CTs_EE_CTs::get_nof_root_comps() | |
226 | { | |
227 | return cts1->get_nof_comps() + cts2->get_nof_comps(); | |
228 | } | |
229 | ||
230 | CompField* CTs_EE_CTs::get_comp_byIndex(size_t n) | |
231 | { | |
232 | if (!checked) chk(); | |
233 | return comps_v[n]; | |
234 | } | |
235 | ||
236 | CompField* CTs_EE_CTs::get_root_comp_byIndex(size_t n) | |
237 | { | |
238 | size_t cts1_size = cts1->get_nof_comps(); | |
239 | if (n < cts1_size) return cts1->get_comp_byIndex(n); | |
240 | else return cts2->get_comp_byIndex(n - cts1_size); | |
241 | } | |
242 | ||
243 | bool CTs_EE_CTs::has_comp_withName(const Identifier& p_name) | |
244 | { | |
245 | if (!checked) chk(); | |
246 | return comps_m.has_key(p_name.get_name()); | |
247 | } | |
248 | ||
249 | CompField* CTs_EE_CTs::get_comp_byName(const Identifier& p_name) | |
250 | { | |
251 | if (!checked) chk(); | |
252 | return comps_m[p_name.get_name()]; | |
253 | } | |
254 | ||
255 | void CTs_EE_CTs::tr_compsof(ReferenceChain *refch, bool in_ellipsis) | |
256 | { | |
257 | if (!my_type) FATAL_ERROR("NULL parameter: CTs_EE_CTs::tr_compsof()"); | |
258 | bool is_set = my_type->get_typetype() == Type::T_SET_A; | |
259 | if (in_ellipsis) { | |
260 | if (ee) ee->tr_compsof(refch, is_set); | |
261 | } else { | |
262 | cts1->tr_compsof(refch, is_set); | |
263 | cts2->tr_compsof(refch, is_set); | |
264 | } | |
265 | } | |
266 | ||
267 | bool CTs_EE_CTs::needs_auto_tags() | |
268 | { | |
269 | if (!my_type) FATAL_ERROR("NULL parameter: CTs_EE_CTs::needs_auto_tags()"); | |
270 | Asn::Module *m = dynamic_cast<Asn::Module*> | |
271 | (my_type->get_my_scope()->get_scope_mod()); | |
272 | if (!m) FATAL_ERROR("CTs_EE_CTs::needs_auto_tags()"); | |
273 | if (m->get_tagdef() != TagDefault::AUTOMATIC) return false; | |
274 | for (size_t i = 0; i < cts1->get_nof_comps(); i++) { | |
275 | if (cts1->get_comp_byIndex(i)->get_type()->is_tagged()) | |
276 | return false; | |
277 | } | |
278 | for (size_t i = 0; i < cts2->get_nof_comps(); i++) { | |
279 | if (cts2->get_comp_byIndex(i)->get_type()->is_tagged()) | |
280 | return false; | |
281 | } | |
282 | if (ee) { | |
283 | bool error_flag = false; | |
284 | for (size_t i = 0; i < ee->get_nof_comps(); i++) { | |
285 | CompField *cf = ee->get_comp_byIndex(i); | |
286 | Type *type = cf->get_type(); | |
287 | if (type->is_tagged()) { | |
288 | type->error("Extension addition `%s' cannot have tags because " | |
289 | "the extension root has no tags", | |
290 | cf->get_name().get_dispname().c_str()); | |
291 | error_flag = true; | |
292 | } | |
293 | } | |
294 | if (error_flag) return false; | |
295 | } | |
296 | return true; | |
297 | } | |
298 | ||
299 | void CTs_EE_CTs::add_auto_tags() | |
300 | { | |
301 | Int tagvalue = 0; | |
302 | for (size_t i = 0; i < cts1->get_nof_comps(); i++) { | |
303 | Tag *tag = new Tag(Tag::TAG_DEFPLICIT, Tag::TAG_CONTEXT, tagvalue++); | |
304 | tag->set_automatic(); | |
305 | cts1->get_comp_byIndex(i)->get_type()->add_tag(tag); | |
306 | } | |
307 | for (size_t i = 0; i < cts2->get_nof_comps(); i++) { | |
308 | Tag *tag = new Tag(Tag::TAG_DEFPLICIT, Tag::TAG_CONTEXT, tagvalue++); | |
309 | tag->set_automatic(); | |
310 | cts2->get_comp_byIndex(i)->get_type()->add_tag(tag); | |
311 | } | |
312 | if (ee) { | |
313 | for (size_t i = 0; i < ee->get_nof_comps(); i++) { | |
314 | Tag *tag = new Tag(Tag::TAG_DEFPLICIT, Tag::TAG_CONTEXT, tagvalue++); | |
315 | tag->set_automatic(); | |
316 | ee->get_comp_byIndex(i)->get_type()->add_tag(tag); | |
317 | } | |
318 | } | |
319 | } | |
320 | ||
321 | void CTs_EE_CTs::chk() | |
322 | { | |
323 | // Hack: for COMPONENTS OF transformation | |
324 | // Type::chk() should not be called until the transformation is finished, | |
325 | // but Type::get_type_refd() calls it from CT_CompsOf::tr_compsof(). | |
326 | // if (checked) return; | |
327 | if (!my_type) FATAL_ERROR("CTs_EE_CTs::chk()"); | |
328 | checked = true; | |
329 | comps_v.clear(); | |
330 | comps_m.clear(); | |
331 | const char *type_name; | |
332 | const char *comp_name; | |
333 | switch (my_type->get_typetype()) { | |
334 | case Type::T_SEQ_A: | |
335 | type_name = "SEQUENCE"; | |
336 | comp_name = "component"; | |
337 | break; | |
338 | case Type::T_SET_A: | |
339 | type_name = "SET"; | |
340 | comp_name = "component"; | |
341 | break; | |
342 | case Type::T_CHOICE_A: | |
343 | type_name = "CHOICE"; | |
344 | comp_name = "alternative"; | |
345 | break; | |
346 | default: | |
347 | type_name = "<unknown>"; | |
348 | comp_name = "component"; | |
349 | break; | |
350 | } | |
351 | size_t cts1_size = cts1->get_nof_comps(); | |
352 | for (size_t i = 0; i < cts1_size; i++) { | |
353 | chk_comp_field(cts1->get_comp_byIndex(i), type_name, comp_name); | |
354 | } | |
355 | if (ee) { | |
356 | size_t ee_size = ee->get_nof_comps(); | |
357 | for (size_t i = 0; i < ee_size; i++) { | |
358 | chk_comp_field(ee->get_comp_byIndex(i), type_name, comp_name); | |
359 | } | |
360 | } | |
361 | size_t cts2_size = cts2->get_nof_comps(); | |
362 | for (size_t i = 0; i < cts2_size; i++) { | |
363 | chk_comp_field(cts2->get_comp_byIndex(i), type_name, comp_name); | |
364 | } | |
365 | for (size_t i=0; i<comps_v.size(); i++) { | |
366 | CompField *cf=comps_v[i]; | |
367 | const Identifier& id = cf->get_name(); | |
368 | const char *dispname = id.get_dispname().c_str(); | |
369 | Type *type=cf->get_type(); | |
370 | type->set_genname(my_type->get_genname_own(), id.get_name()); | |
371 | type->set_parent_type(my_type); | |
372 | { | |
373 | Error_Context cntxt(cf, "In type of %s %s `%s'", | |
374 | type_name, comp_name, dispname); | |
375 | type->chk(); | |
376 | } | |
377 | if(cf->has_default()) { | |
378 | Value* defval=cf->get_defval(); | |
379 | defval->set_my_governor(type); | |
380 | Error_Context cntxt(cf, "In default value of %s %s `%s'", type_name, | |
381 | comp_name, dispname); | |
382 | type->chk_this_value_ref(defval); | |
383 | type->chk_this_value(defval, 0, Type::EXPECTED_CONSTANT, | |
384 | INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK); | |
385 | if (!semantic_check_only) { | |
386 | defval->set_genname_prefix("const_"); | |
387 | defval->set_genname_recursive(string(type->get_genname_own()) + | |
388 | "_defval_"); | |
389 | defval->set_code_section(GovernedSimple::CS_PRE_INIT); | |
390 | } | |
391 | } | |
392 | } | |
393 | } | |
394 | ||
395 | void CTs_EE_CTs::chk_tags() | |
396 | { | |
397 | if (!my_type) FATAL_ERROR("NULL parameter: CTs_EE_CTs::chk_tags()"); | |
398 | switch (my_type->get_typetype()) { | |
399 | case Type::T_CHOICE_A: | |
400 | chk_tags_choice(); | |
401 | break; | |
402 | case Type::T_SEQ_A: | |
403 | case Type::T_SEQ_T: | |
404 | chk_tags_seq(); | |
405 | break; | |
406 | case Type::T_SET_A: | |
407 | case Type::T_SET_T: | |
408 | chk_tags_set(); | |
409 | break; | |
410 | default: | |
411 | FATAL_ERROR("CTs_EE_CTs::chk_tags(): invalid typetype"); | |
412 | } | |
413 | } | |
414 | ||
415 | void CTs_EE_CTs::chk_comp_field(CompField *cf, | |
416 | const char *type_name, | |
417 | const char *comp_name) | |
418 | { | |
419 | const Identifier& id = cf->get_name(); | |
420 | const string& name = id.get_name(); | |
421 | if(comps_m.has_key(name)) { | |
422 | const char *dispname_str = id.get_dispname().c_str(); | |
423 | cf->error("Duplicate %s identifier in %s: `%s'", comp_name, type_name, | |
424 | dispname_str); | |
425 | comps_m[name]->note("%s `%s' is already defined here", comp_name, | |
426 | dispname_str); | |
427 | } else { | |
428 | comps_m.add(name, cf); | |
429 | comps_v.add(cf); | |
430 | if(!id.get_has_valid(Identifier::ID_TTCN)) | |
431 | cf->warning("The identifier `%s' is not reachable from TTCN-3", | |
432 | id.get_dispname().c_str()); | |
433 | ||
434 | } | |
435 | } | |
436 | ||
437 | void CTs_EE_CTs::chk_tags_choice() | |
438 | { | |
439 | TagCollection collection; | |
440 | collection.set_location(*my_type); | |
441 | for (size_t i = 0; i < cts1->get_nof_comps(); i++) { | |
442 | CompField *cf = cts1->get_comp_byIndex(i); | |
443 | Type *type = cf->get_type(); | |
444 | if (type->has_multiple_tags()) { | |
445 | Error_Context cntxt(type, "In tags of alternative `%s'", | |
446 | cf->get_name().get_dispname().c_str()); | |
447 | get_multiple_tags(collection, type); | |
448 | } | |
449 | else { | |
450 | const Tag *tag = type->get_tag(); | |
451 | if (collection.hasTag(tag)) | |
452 | type->error("Alternative `%s' in CHOICE has non-distinct tag", | |
453 | cf->get_name().get_dispname().c_str()); | |
454 | else collection.addTag(tag); | |
455 | } | |
456 | } | |
457 | if (cts2->get_nof_comps() > 0) | |
458 | FATAL_ERROR("CTs_EE_CTs::chk_tags_choice(): cts2 is not empty"); | |
459 | if (ee) { | |
460 | collection.setExtensible(); | |
461 | Tag greatest_tag(Tag::TAG_EXPLICIT, Tag::TAG_NONE, (Int)0); | |
462 | for (size_t i = 0; i < ee->get_nof_comps(); i++) { | |
463 | CompField *cf = ee->get_comp_byIndex(i); | |
464 | Type *type = cf->get_type(); | |
465 | if (type->has_multiple_tags()) { | |
466 | TagCollection coll2; | |
467 | coll2.set_location(*type); | |
468 | get_multiple_tags(coll2, type); | |
469 | if (!coll2.isEmpty()) { | |
470 | if (collection.hasTags(&coll2)) | |
471 | type->error | |
472 | ("Alternative `%s' in CHOICE has non-distinct tag(s)", | |
473 | cf->get_name().get_dispname().c_str()); | |
474 | else collection.addTags(&coll2); | |
475 | if (greatest_tag < *coll2.getSmallestTag()) | |
476 | greatest_tag = *coll2.getGreatestTag(); | |
477 | else type->error | |
478 | ("Alternative `%s' must have canonically greater tag(s)" | |
479 | " than all previously added extension alternatives", | |
480 | cf->get_name().get_dispname().c_str()); | |
481 | } | |
482 | } else { | |
483 | const Tag *tag = type->get_tag(); | |
484 | if (collection.hasTag(tag)) | |
485 | type->error("Alternative `%s' in CHOICE has non-distinct tag", | |
486 | cf->get_name().get_dispname().c_str()); | |
487 | else collection.addTag(tag); | |
488 | if (greatest_tag < *tag) greatest_tag = *tag; | |
489 | else type->error | |
490 | ("Alternative `%s' must have canonically greater tag" | |
491 | " than all previously added extension alternatives", | |
492 | cf->get_name().get_dispname().c_str()); | |
493 | } | |
494 | } | |
495 | } | |
496 | } | |
497 | ||
498 | void CTs_EE_CTs::chk_tags_seq() | |
499 | { | |
500 | TagCollection forbidden_tags; | |
501 | forbidden_tags.set_location(*my_type); | |
502 | for (size_t i = 0; i < cts1->get_nof_comps(); i++) { | |
503 | CompField *cf = cts1->get_comp_byIndex(i); | |
504 | bool mandatory = !cf->get_is_optional() && !cf->has_default(); | |
505 | chk_tags_seq_comp(forbidden_tags, cf, mandatory); | |
506 | } | |
507 | size_t j = 0; | |
508 | if (ee) { | |
509 | forbidden_tags.setExtensible(); | |
510 | TagCollection forbidden_tags2; | |
511 | forbidden_tags2.set_location(*my_type); | |
512 | forbidden_tags2.setExtensible(); | |
513 | for ( ; j < cts2->get_nof_comps(); j++) { | |
514 | CompField *cf = cts2->get_comp_byIndex(j); | |
515 | bool mandatory = !cf->get_is_optional() && !cf->has_default(); | |
516 | chk_tags_seq_comp(forbidden_tags, cf, false); | |
517 | chk_tags_seq_comp(forbidden_tags2, cf, false); | |
518 | if (mandatory) { | |
519 | j++; | |
520 | break; | |
521 | } | |
522 | } | |
523 | for (size_t i = 0; i < ee->get_nof_comps(); i++) { | |
524 | CompField *cf = ee->get_comp_byIndex(i); | |
525 | bool mandatory = !cf->get_is_optional() && !cf->has_default(); | |
526 | chk_tags_seq_comp(forbidden_tags, cf, mandatory); | |
527 | if (mandatory) { | |
528 | forbidden_tags.clear(); | |
529 | forbidden_tags.addTags(&forbidden_tags2); | |
530 | } | |
531 | } | |
532 | } | |
533 | forbidden_tags.clear(); | |
534 | for ( ; j < cts2->get_nof_comps(); j++) { | |
535 | CompField *cf = cts2->get_comp_byIndex(j); | |
536 | bool mandatory = !cf->get_is_optional() && !cf->has_default(); | |
537 | chk_tags_seq_comp(forbidden_tags, cf, mandatory); | |
538 | } | |
539 | } | |
540 | ||
541 | void CTs_EE_CTs::chk_tags_seq_comp(TagCollection& coll, CompField *cf, | |
542 | bool is_mandatory) | |
543 | { | |
544 | Type *type = cf->get_type(); | |
545 | bool is_empty = coll.isEmpty(); | |
546 | if (!is_mandatory || !is_empty) { | |
547 | if (type->has_multiple_tags()) { | |
548 | Error_Context cntxt(type, "While checking tags of component `%s'", | |
549 | cf->get_name().get_dispname().c_str()); | |
550 | get_multiple_tags(coll, type); | |
551 | } | |
552 | else { | |
553 | const Tag *tag = type->get_tag(); | |
554 | if(coll.hasTag(tag)) | |
555 | type->error("Tag of component `%s' is not allowed " | |
556 | "in this context of SEQUENCE type", | |
557 | cf->get_name().get_dispname().c_str()); | |
558 | else coll.addTag(tag); | |
559 | } | |
560 | } | |
561 | if (is_mandatory && !is_empty) coll.clear(); | |
562 | } | |
563 | ||
564 | void CTs_EE_CTs::chk_tags_set() | |
565 | { | |
566 | TagCollection collection; | |
567 | collection.set_location(*my_type); | |
568 | for (size_t i = 0; i < cts1->get_nof_comps(); i++) { | |
569 | CompField *cf = cts1->get_comp_byIndex(i); | |
570 | Type *type = cf->get_type(); | |
571 | if (type->has_multiple_tags()) { | |
572 | Error_Context cntxt(type, "While checking tags of component `%s'", | |
573 | cf->get_name().get_dispname().c_str()); | |
574 | get_multiple_tags(collection, type); | |
575 | } | |
576 | else { | |
577 | const Tag *tag = type->get_tag(); | |
578 | if (collection.hasTag(tag)) | |
579 | type->error("Component `%s' in SET has non-distinct tag", | |
580 | cf->get_name().get_dispname().c_str()); | |
581 | else collection.addTag(tag); | |
582 | } | |
583 | } | |
584 | for (size_t i = 0; i < cts2->get_nof_comps(); i++) { | |
585 | CompField *cf = cts2->get_comp_byIndex(i); | |
586 | Type *type = cf->get_type(); | |
587 | if (type->has_multiple_tags()) { | |
588 | Error_Context cntxt(type, "While checking tags of component `%s'", | |
589 | cf->get_name().get_dispname().c_str()); | |
590 | get_multiple_tags(collection, type); | |
591 | } | |
592 | else { | |
593 | const Tag *tag = type->get_tag(); | |
594 | if (collection.hasTag(tag)) | |
595 | type->error("Component `%s' in SET has non-distinct tag", | |
596 | cf->get_name().get_dispname().c_str()); | |
597 | else collection.addTag(tag); | |
598 | } | |
599 | } | |
600 | if (ee) { | |
601 | collection.setExtensible(); | |
602 | Tag greatest_tag(Tag::TAG_EXPLICIT, Tag::TAG_NONE, (Int)0); | |
603 | for (size_t i = 0; i < ee->get_nof_comps(); i++) { | |
604 | CompField *cf = ee->get_comp_byIndex(i); | |
605 | Type *type = cf->get_type(); | |
606 | if (type->has_multiple_tags()) { | |
607 | TagCollection coll2; | |
608 | coll2.set_location(*type); | |
609 | get_multiple_tags(coll2, type); | |
610 | if (!coll2.isEmpty()) { | |
611 | if (collection.hasTags(&coll2)) | |
612 | type->error("Component `%s' in SET has non-distinct tag(s)", | |
613 | cf->get_name().get_dispname().c_str()); | |
614 | else collection.addTags(&coll2); | |
615 | if (greatest_tag < *coll2.getSmallestTag()) | |
616 | greatest_tag = *coll2.getGreatestTag(); | |
617 | else type->error | |
618 | ("Component `%s' must have " | |
619 | "canonically greater tag(s) than all previously added " | |
620 | "extension components", | |
621 | cf->get_name().get_dispname().c_str()); | |
622 | } | |
623 | } else { | |
624 | const Tag *tag = type->get_tag(); | |
625 | if (collection.hasTag(tag)) | |
626 | type->error("Component `%s' in SET has non-distinct tag", | |
627 | cf->get_name().get_dispname().c_str()); | |
628 | else collection.addTag(tag); | |
629 | if (greatest_tag < *tag) greatest_tag = *tag; | |
630 | else type->error | |
631 | ("Component `%s' must have canonically greater " | |
632 | "tag than all previously added extension components", | |
633 | cf->get_name().get_dispname().c_str()); | |
634 | } | |
635 | } | |
636 | } | |
637 | } | |
638 | ||
639 | /** \todo revise */ | |
640 | void CTs_EE_CTs::get_multiple_tags(TagCollection& coll, Type *type) | |
641 | { | |
642 | Type *t=type->get_type_refd_last(); | |
643 | if(t->get_typetype()!=Type::T_CHOICE_A) | |
644 | FATAL_ERROR("CTs_EE_CTs::get_multiple_tags()"); | |
645 | map<Type*, void> chain; | |
646 | if(my_type->get_typetype()==Type::T_CHOICE_A) | |
647 | chain.add(my_type, 0); | |
648 | t->get_tags(coll, chain); | |
649 | chain.clear(); | |
650 | } | |
651 | ||
652 | void CTs_EE_CTs::dump(unsigned level) const | |
653 | { | |
654 | if(cts1) cts1->dump(level); | |
655 | if(ee) ee->dump(level); | |
656 | if(cts2) cts2->dump(level); | |
657 | } | |
658 | ||
659 | // ================================= | |
660 | // ===== ExtAdd | |
661 | // ================================= | |
662 | ||
663 | // ================================= | |
664 | // ===== ExtAdds | |
665 | // ================================= | |
666 | ||
667 | ExtAdds::~ExtAdds() | |
668 | { | |
669 | for(size_t i=0; i<eas.size(); i++) delete eas[i]; | |
670 | eas.clear(); | |
671 | } | |
672 | ||
673 | ExtAdds *ExtAdds::clone() const | |
674 | { | |
675 | FATAL_ERROR("ExtAdds::clone"); | |
676 | } | |
677 | ||
678 | void ExtAdds::set_fullname(const string& p_fullname) | |
679 | { | |
680 | Node::set_fullname(p_fullname); | |
681 | for(size_t i=0; i<eas.size(); i++) | |
682 | // eas[i]->set_fullname(get_fullname()+"."+Int2string(i+1)); | |
683 | eas[i]->set_fullname(get_fullname()); | |
684 | } | |
685 | ||
686 | void ExtAdds::set_my_scope(Scope *p_scope) | |
687 | { | |
688 | for(size_t i=0; i<eas.size(); i++) | |
689 | eas[i]->set_my_scope(p_scope); | |
690 | } | |
691 | ||
692 | size_t ExtAdds::get_nof_comps() const | |
693 | { | |
694 | size_t n=0; | |
695 | for(size_t i=0; i<eas.size(); i++) | |
696 | n+=eas[i]->get_nof_comps(); | |
697 | return n; | |
698 | } | |
699 | ||
700 | CompField* ExtAdds::get_comp_byIndex(size_t n) const | |
701 | { | |
702 | size_t offset = n; | |
703 | for(size_t i = 0; i < eas.size(); i++) { | |
704 | size_t size = eas[i]->get_nof_comps(); | |
705 | if (offset < size) return eas[i]->get_comp_byIndex(offset); | |
706 | else offset -= size; | |
707 | } | |
708 | FATAL_ERROR("%s: Requested index %lu does not exist.", \ | |
709 | get_fullname().c_str(), (unsigned long) n); | |
710 | return 0; | |
711 | } | |
712 | ||
713 | bool ExtAdds::has_comp_withName(const Identifier& p_name) const | |
714 | { | |
715 | for(size_t i=0; i<eas.size(); i++) | |
716 | if(eas[i]->has_comp_withName(p_name)) return true; | |
717 | return false; | |
718 | } | |
719 | ||
720 | CompField* ExtAdds::get_comp_byName(const Identifier& p_name) const | |
721 | { | |
722 | for(size_t i=0; i<eas.size(); i++) | |
723 | if(eas[i]->has_comp_withName(p_name)) | |
724 | return eas[i]->get_comp_byName(p_name); | |
725 | FATAL_ERROR("%s: No component with name `%s'", \ | |
726 | get_fullname().c_str(), p_name.get_dispname().c_str()); | |
727 | return 0; | |
728 | } | |
729 | ||
730 | void ExtAdds::tr_compsof(ReferenceChain *refch, bool is_set) | |
731 | { | |
732 | for(size_t i = 0; i < eas.size(); i++) | |
733 | eas[i]->tr_compsof(refch, is_set); | |
734 | } | |
735 | ||
736 | void ExtAdds::add_ea(ExtAdd* p_ea) | |
737 | { | |
738 | if(!p_ea) | |
739 | FATAL_ERROR("NULL parameter: Asn::ExtAdds::add_ea()"); | |
740 | eas.add(p_ea); | |
741 | } | |
742 | ||
743 | void ExtAdds::dump(unsigned level) const | |
744 | { | |
745 | for(size_t i=0; i<eas.size(); i++) | |
746 | eas[i]->dump(level); | |
747 | } | |
748 | ||
749 | // ================================= | |
750 | // ===== ExtAndExc | |
751 | // ================================= | |
752 | ||
753 | ExtAndExc::ExtAndExc(ExcSpec *p_excSpec, ExtAdds *p_eas) | |
754 | : Node() | |
755 | { | |
756 | excSpec=p_excSpec; | |
757 | eas=p_eas?p_eas:new ExtAdds(); | |
758 | } | |
759 | ||
760 | ExtAndExc::~ExtAndExc() | |
761 | { | |
762 | delete excSpec; | |
763 | delete eas; | |
764 | } | |
765 | ||
766 | ExtAndExc *ExtAndExc::clone() const | |
767 | { | |
768 | FATAL_ERROR("ExtAndExc::clone"); | |
769 | } | |
770 | ||
771 | void ExtAndExc::set_fullname(const string& p_fullname) | |
772 | { | |
773 | Node::set_fullname(p_fullname); | |
774 | if(excSpec) excSpec->set_fullname(p_fullname+".<exc>"); | |
775 | // eas->set_fullname(p_fullname+".<ext>"); | |
776 | eas->set_fullname(p_fullname); | |
777 | } | |
778 | ||
779 | void ExtAndExc::set_my_scope(Scope *p_scope) | |
780 | { | |
781 | if(excSpec) excSpec->set_my_scope(p_scope); | |
782 | eas->set_my_scope(p_scope); | |
783 | } | |
784 | ||
785 | void ExtAndExc::set_eas(ExtAdds *p_eas) | |
786 | { | |
787 | delete eas; | |
788 | eas=p_eas; | |
789 | } | |
790 | ||
791 | void ExtAndExc::dump(unsigned level) const | |
792 | { | |
793 | DEBUG(level, "...%s", excSpec?" !":""); | |
794 | if(eas) eas->dump(level); | |
795 | DEBUG(level, "..."); | |
796 | } | |
797 | ||
798 | // ================================= | |
799 | // ===== ExtAddGrp | |
800 | // ================================= | |
801 | ||
802 | ExtAddGrp::ExtAddGrp(Value* p_versionnumber, CTs *p_cts) | |
803 | : ExtAdd() | |
804 | { | |
805 | if(!p_cts) | |
806 | FATAL_ERROR("NULL parameter: Asn::ExtAddGrp::ExtAddGrp()"); | |
807 | versionnumber=p_versionnumber; | |
808 | cts=p_cts; | |
809 | } | |
810 | ||
811 | ExtAddGrp::~ExtAddGrp() | |
812 | { | |
813 | delete versionnumber; | |
814 | delete cts; | |
815 | } | |
816 | ||
817 | ExtAddGrp *ExtAddGrp::clone() const | |
818 | { | |
819 | FATAL_ERROR("ExtAddGrp::clone"); | |
820 | } | |
821 | ||
822 | void ExtAddGrp::set_fullname(const string& p_fullname) | |
823 | { | |
824 | ExtAdd::set_fullname(p_fullname); | |
825 | if(versionnumber) versionnumber->set_fullname(p_fullname | |
826 | +".<versionnumber>"); | |
827 | cts->set_fullname(p_fullname); | |
828 | } | |
829 | ||
830 | void ExtAddGrp::set_my_scope(Scope *p_scope) | |
831 | { | |
832 | if(versionnumber) versionnumber->set_my_scope(p_scope); | |
833 | cts->set_my_scope(p_scope); | |
834 | } | |
835 | ||
836 | size_t ExtAddGrp::get_nof_comps() const | |
837 | { | |
838 | return cts->get_nof_comps(); | |
839 | } | |
840 | ||
841 | CompField* ExtAddGrp::get_comp_byIndex(size_t n) const | |
842 | { | |
843 | return cts->get_comp_byIndex(n); | |
844 | } | |
845 | ||
846 | bool ExtAddGrp::has_comp_withName(const Identifier& p_name) const | |
847 | { | |
848 | return cts->has_comp_withName(p_name); | |
849 | } | |
850 | ||
851 | CompField* ExtAddGrp::get_comp_byName(const Identifier& p_name) const | |
852 | { | |
853 | return cts->get_comp_byName(p_name); | |
854 | } | |
855 | ||
856 | void ExtAddGrp::tr_compsof(ReferenceChain *refch, bool is_set) | |
857 | { | |
858 | cts->tr_compsof(refch, is_set); | |
859 | } | |
860 | ||
861 | void ExtAddGrp::dump(unsigned level) const | |
862 | { | |
863 | DEBUG(level, "[["); | |
864 | cts->dump(level); | |
865 | DEBUG(level, "]]"); | |
866 | } | |
867 | ||
868 | // ================================= | |
869 | // ===== CT | |
870 | // ================================= | |
871 | ||
872 | // ================================= | |
873 | // ===== CT_reg | |
874 | // ================================= | |
875 | ||
876 | CT_reg::CT_reg(CompField *p_comp) | |
877 | : CT() | |
878 | { | |
879 | if(!p_comp) | |
880 | FATAL_ERROR("NULL parameter: Asn::CT_reg::CT_reg()"); | |
881 | comp=p_comp; | |
882 | } | |
883 | ||
884 | CT_reg::~CT_reg() | |
885 | { | |
886 | delete comp; | |
887 | } | |
888 | ||
889 | CT_reg *CT_reg::clone() const | |
890 | { | |
891 | FATAL_ERROR("CT_reg::clone"); | |
892 | } | |
893 | ||
894 | void CT_reg::set_fullname(const string& p_fullname) | |
895 | { | |
896 | comp->set_fullname(p_fullname); | |
897 | } | |
898 | ||
899 | void CT_reg::set_my_scope(Scope *p_scope) | |
900 | { | |
901 | comp->set_my_scope(p_scope); | |
902 | } | |
903 | ||
904 | size_t CT_reg::get_nof_comps() const | |
905 | { | |
906 | return 1; | |
907 | } | |
908 | ||
909 | CompField *CT_reg::get_comp_byIndex(size_t n) const | |
910 | { | |
911 | if (n == 0) return comp; | |
912 | FATAL_ERROR("%s: Requested index %lu does not exist.", \ | |
913 | get_fullname().c_str(), (unsigned long) n); | |
914 | return 0; | |
915 | } | |
916 | ||
917 | bool CT_reg::has_comp_withName(const Identifier& p_name) const | |
918 | { | |
919 | return comp->get_name() == p_name; | |
920 | } | |
921 | ||
922 | CompField *CT_reg::get_comp_byName(const Identifier& p_name) const | |
923 | { | |
924 | if (comp->get_name() == p_name) | |
925 | return comp; | |
926 | FATAL_ERROR("`%s': No component with name `%s'", \ | |
927 | get_fullname().c_str(), p_name.get_dispname().c_str()); | |
928 | return 0; | |
929 | } | |
930 | ||
931 | void CT_reg::tr_compsof(ReferenceChain *, bool) | |
932 | { | |
933 | } | |
934 | ||
935 | void CT_reg::dump(unsigned level) const | |
936 | { | |
937 | comp->dump(level); | |
938 | } | |
939 | ||
940 | ||
941 | // ================================= | |
942 | // ===== CT_CompsOf | |
943 | // ================================= | |
944 | ||
945 | CT_CompsOf::CT_CompsOf(Type *p_compsoftype) | |
946 | : CT(), compsoftype(p_compsoftype), tr_compsof_ready(false), cts(0) | |
947 | { | |
948 | if(!p_compsoftype) | |
949 | FATAL_ERROR("NULL parameter: Asn::CT_CompsOf::CT_CompsOf()"); | |
950 | compsoftype->set_ownertype(Type::OT_COMPS_OF, this); | |
951 | } | |
952 | ||
953 | CT_CompsOf::~CT_CompsOf() | |
954 | { | |
955 | delete compsoftype; | |
956 | delete cts; | |
957 | } | |
958 | ||
959 | CT_CompsOf *CT_CompsOf::clone() const | |
960 | { | |
961 | FATAL_ERROR("CT_CompsOf::clone"); | |
962 | } | |
963 | ||
964 | void CT_CompsOf::set_fullname(const string& p_fullname) | |
965 | { | |
966 | ExtAdd::set_fullname(p_fullname); | |
967 | if(compsoftype) compsoftype->set_fullname(p_fullname+".<CompsOfType>"); | |
968 | if(cts) cts->set_fullname(p_fullname); | |
969 | } | |
970 | ||
971 | void CT_CompsOf::set_my_scope(Scope *p_scope) | |
972 | { | |
973 | if (compsoftype) compsoftype->set_my_scope(p_scope); | |
974 | if (cts) cts->set_my_scope(p_scope); | |
975 | } | |
976 | ||
977 | size_t CT_CompsOf::get_nof_comps() const | |
978 | { | |
979 | if (cts) return cts->get_nof_comps(); | |
980 | else return 0; | |
981 | } | |
982 | ||
983 | CompField* CT_CompsOf::get_comp_byIndex(size_t n) const | |
984 | { | |
985 | if (!cts) FATAL_ERROR("CT_CompsOf::get_comp_byIndex()"); | |
986 | return cts->get_comp_byIndex(n); | |
987 | } | |
988 | ||
989 | bool CT_CompsOf::has_comp_withName(const Identifier& p_name) const | |
990 | { | |
991 | if (cts) return cts->has_comp_withName(p_name); | |
992 | else return false; | |
993 | } | |
994 | ||
995 | CompField* CT_CompsOf::get_comp_byName(const Identifier& p_name) const | |
996 | { | |
997 | if (!cts) FATAL_ERROR("CT_CompsOf::get_comp_byName()"); | |
998 | return cts->get_comp_byName(p_name); | |
999 | } | |
1000 | ||
1001 | void CT_CompsOf::tr_compsof(ReferenceChain *refch, bool is_set) | |
1002 | { | |
1003 | if (tr_compsof_ready) return; | |
1004 | compsoftype->set_genname(string("<dummy>")); | |
1005 | Type *t=compsoftype->get_type_refd_last(); | |
1006 | // to avoid re-entering in case of infinite recursion | |
1007 | if (tr_compsof_ready) return; | |
1008 | bool error_flag = true; | |
1009 | if(is_set) { | |
1010 | switch (t->get_typetype()) { | |
1011 | case Type::T_SET_A: | |
1012 | error_flag = false; | |
1013 | break; | |
1014 | case Type::T_ERROR: | |
1015 | break; | |
1016 | case Type::T_SEQ_A: | |
1017 | error_flag = false; | |
1018 | // no break | |
1019 | default: | |
1020 | t->error("COMPONENTS OF in a SET type shall refer to another SET type" | |
1021 | " instead of `%s'", t->get_fullname().c_str()); | |
1022 | break; | |
1023 | } | |
1024 | } else { | |
1025 | switch (t->get_typetype()) { | |
1026 | case Type::T_SEQ_A: | |
1027 | error_flag = false; | |
1028 | break; | |
1029 | case Type::T_ERROR: | |
1030 | break; | |
1031 | case Type::T_SET_A: | |
1032 | error_flag = false; | |
1033 | // no break | |
1034 | default: | |
1035 | t->error("COMPONENTS OF in a SEQUENCE type shall refer to another" | |
1036 | " SEQUENCE type instead of `%s'", t->get_fullname().c_str()); | |
1037 | break; | |
1038 | } | |
1039 | } | |
1040 | if (error_flag) { | |
1041 | tr_compsof_ready = true; | |
1042 | return; | |
1043 | } | |
1044 | t->tr_compsof(refch); | |
1045 | // another emergency exit for the case of infinite recursion | |
1046 | if (tr_compsof_ready) return; | |
1047 | cts=new CTs; | |
1048 | size_t n_comps=t->get_nof_root_comps(); | |
1049 | for(size_t i=0; i<n_comps; i++) { | |
1050 | CompField *cf=t->get_root_comp_byIndex(i)->clone(); | |
1051 | cf->get_type()->cut_auto_tags(); | |
1052 | cf->set_location(*this); | |
1053 | cts->add_ct(new CT_reg(cf)); | |
1054 | } | |
1055 | cts->set_my_scope(compsoftype->get_my_scope()); | |
1056 | cts->set_fullname(get_fullname()); | |
1057 | tr_compsof_ready=true; | |
1058 | // compsoftype must not be deleted because the above t->get_type_refd() | |
1059 | // call may modify it in case of infinite recursion | |
1060 | } | |
1061 | ||
1062 | void CT_CompsOf::dump(unsigned level) const | |
1063 | { | |
1064 | if(compsoftype) { | |
1065 | DEBUG(level, "COMPONENTS OF"); | |
1066 | compsoftype->dump(level+1); | |
1067 | } | |
1068 | if(cts) cts->dump(level); | |
1069 | } | |
1070 | ||
1071 | } // namespace Common |