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