Merge github.com:eclipse/titan.core
[deliverable/titan.core.git] / compiler2 / asn1 / Tag.cc
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 * Cserveni, Akos
11 * Forstner, Matyas
12 * Gecse, Roland
13 * Kovacs, Ferenc
14 * Raduly, Csaba
15 * Szabo, Janos Zoltan – initial implementation
16 *
17 ******************************************************************************/
18 #include "Tag.hh"
19 #include "../Type.hh"
20 #include "../Value.hh"
21 #include <limits.h>
22
23 namespace Asn {
24
25 // =================================
26 // ===== Tag
27 // =================================
28
29 Tag::Tag(tagplicit_t p_plicit, tagclass_t p_tagclass, Value *p_tagvalue)
30 : Node(), Location(),
31 plicit(p_plicit), tagclass(p_tagclass), tagvalue(p_tagvalue),
32 is_auto(false)
33 {
34 if(!p_tagvalue)
35 FATAL_ERROR("NULL parameter: Asn::Tag::Tag()");
36 }
37
38 Tag::Tag(tagplicit_t p_plicit, tagclass_t p_tagclass, Int p_tagval)
39 : Node(), Location(),
40 plicit(p_plicit), tagclass(p_tagclass), tagvalue(0),
41 tagval(p_tagval), is_auto(false)
42 {
43 if(tagval<0) FATAL_ERROR("Asn::Tag::Tag(): negative value");
44 }
45
46 Tag::Tag(const Tag& p)
47 : Node(p), Location(p),
48 plicit(p.plicit), tagclass(p.tagclass),
49 is_auto(p.is_auto)
50 {
51 if (p.tagvalue) tagvalue = p.tagvalue->clone();
52 else {
53 tagvalue = NULL;
54 tagval = p.tagval;
55 }
56 }
57
58 Tag::~Tag()
59 {
60 delete tagvalue;
61 }
62
63 Tag& Tag::operator=(const Tag& p)
64 {
65 if (&p != this) {
66 delete tagvalue;
67 plicit = p.plicit;
68 tagclass = p.tagclass;
69 if (p.tagvalue) tagvalue = p.tagvalue->clone();
70 else {
71 tagvalue = NULL;
72 tagval = p.tagval;
73 }
74 is_auto = p.is_auto;
75 }
76 return *this;
77 }
78
79 bool Tag::operator==(const Tag& p) const
80 {
81 if (tagvalue || p.tagvalue) FATAL_ERROR("Comparison of unchecked tags.");
82 return tagclass == p.tagclass && tagval == p.tagval;
83 }
84
85 bool Tag::operator<(const Tag& p) const
86 {
87 if (tagvalue || p.tagvalue) FATAL_ERROR("Comparison of unchecked tags.");
88 if (tagclass < p.tagclass) return true;
89 else if (tagclass > p.tagclass) return false;
90 else return tagval < p.tagval;
91 }
92
93 const char *Tag::get_tagclass_str() const
94 {
95 switch (tagclass) {
96 case TAG_UNIVERSAL:
97 return "ASN_TAG_UNIV";
98 case TAG_APPLICATION:
99 return "ASN_TAG_APPL";
100 case TAG_CONTEXT:
101 return "ASN_TAG_CONT";
102 case TAG_PRIVATE:
103 return "ASN_TAG_PRIV";
104 default:
105 FATAL_ERROR("Tag::get_tagclass_str()");
106 return NULL;
107 }
108 }
109
110 Int Tag::get_tagvalue()
111 {
112 chk();
113 return tagval;
114 }
115
116 void Tag::set_tagvalue(const Int& p_tagval)
117 {
118 if(tagvalue) {delete tagvalue; tagvalue=0;}
119 tagval=p_tagval;
120 }
121
122 void Tag::set_my_scope(Scope *p_scope)
123 {
124 if (tagvalue) tagvalue->set_my_scope(p_scope);
125 }
126
127 void Tag::chk()
128 {
129 if (!tagvalue) return;
130 Error_Context cntxt(this, "In tag");
131 Value *v = tagvalue->get_value_refd_last();
132 switch (v->get_valuetype()) {
133 case Value::V_INT: {
134 const int_val_t *tagval_int = tagvalue->get_val_Int();
135 if (*tagval_int < 0 || *tagval_int > INT_MAX) {
136 error("Integer value in range 0..%d was expected instead of `%s' "
137 "for tag value", INT_MAX, (tagval_int->t_str()).c_str());
138 goto error;
139 }
140 tagval = tagval_int->get_val();
141 break; }
142 case Value::V_ERROR:
143 goto error;
144 break;
145 default:
146 error("INTEGER value was expected for tag value");
147 goto error;
148 }
149 goto end;
150 error:
151 tagclass=TAG_ERROR;
152 tagval=0;
153 end:
154 delete tagvalue;
155 tagvalue = 0;
156 }
157
158 void Tag::dump(unsigned level) const
159 {
160 string s('[');
161 switch(tagclass) {
162 case TAG_ERROR:
163 s+="<ERROR> "; break;
164 case TAG_NONE:
165 s+="<NONE> "; break;
166 case TAG_ALL:
167 s+="<ALL> "; break;
168 case TAG_UNIVERSAL:
169 s+="UNIVERSAL "; break;
170 case TAG_APPLICATION:
171 s+="APPLICATION "; break;
172 case TAG_CONTEXT:
173 break;
174 case TAG_PRIVATE:
175 s+="PRIVATE "; break;
176 default:
177 s+=" <UNKNOWN CLASS>"; break;
178 } // switch tagclass
179 if(!tagvalue) s+=Int2string(tagval);
180 else s+="<value>";
181 s+="]";
182 switch(plicit) {
183 case TAG_DEFPLICIT:
184 break;
185 case TAG_EXPLICIT:
186 s+=" EXPLICIT"; break;
187 case TAG_IMPLICIT:
188 s+=" IMPLICIT"; break;
189 default:
190 s+=" <UNKNOWN PLICIT>"; break;
191 } // switch plicit
192 if(is_auto) s+=" (auto)";
193 DEBUG(level, "Tag: %s", s.c_str());
194 if(tagvalue) tagvalue->dump(level+1);
195 }
196
197 // =================================
198 // ===== Tags
199 // =================================
200
201 Tags::Tags() : Node()
202 {
203 set_fullname(string("<tags>"));
204 my_scope=0;
205 }
206
207 Tags::Tags(const Tags& p) : Node(p)
208 {
209 for(size_t i=0; i<p.tags.size(); i++)
210 add_tag(p.tags[i]->clone());
211 my_scope=0;
212 }
213
214 Tags::~Tags()
215 {
216 for(size_t i=0; i<tags.size(); i++) delete tags[i];
217 tags.clear();
218 }
219
220 void Tags::set_fullname(const string& p_fullname)
221 {
222 Node::set_fullname(p_fullname);
223 for(size_t i=0; i<tags.size(); i++)
224 tags[i]->set_fullname(get_fullname()+"."+Int2string(i));
225 }
226
227 void Tags::set_my_scope(Scope *p_scope)
228 {
229 my_scope=p_scope;
230 for(size_t i=0; i<tags.size(); i++)
231 tags[i]->set_my_scope(p_scope);
232 }
233
234 void Tags::add_tag(Tag *p_tag)
235 {
236 if(!p_tag)
237 FATAL_ERROR("NULL parameter: Asn::Tags::add_tag()");
238 tags.add(p_tag);
239 p_tag->set_fullname(get_fullname()+"."+Int2string(tags.size()));
240 p_tag->set_my_scope(my_scope);
241 }
242
243 void Tags::chk()
244 {
245 for(size_t i=0; i<tags.size(); i++)
246 tags[i]->chk();
247 }
248
249 void Tags::set_plicit(Type *p_type)
250 {
251 if (!p_type) FATAL_ERROR("NULL parameter: Asn::Tags::set_plicit()");
252 Asn::Module *m = dynamic_cast<Asn::Module*>
253 (p_type->get_my_scope()->get_scope_mod());
254 if (!m) FATAL_ERROR("Asn::Tags::set_plicit()");
255 bool type_needs_explicit = p_type->needs_explicit_tag();
256 bool module_uses_explicit = (m->get_tagdef() == TagDefault::EXPLICIT);
257 Tag *innermost = tags[0];
258 switch (innermost->get_plicit()) {
259 case Tag::TAG_DEFPLICIT:
260 if (module_uses_explicit || type_needs_explicit)
261 innermost->set_plicit(Tag::TAG_EXPLICIT);
262 else innermost->set_plicit(Tag::TAG_IMPLICIT);
263 break;
264 case Tag::TAG_IMPLICIT:
265 if (type_needs_explicit) {
266 p_type->error("Type cannot have IMPLICIT tag");
267 innermost->set_plicit(Tag::TAG_EXPLICIT);
268 }
269 default:
270 break;
271 }
272 for (size_t i = 1; i < tags.size(); i++) {
273 Tag *tag = tags[i];
274 if (tag->get_plicit() == Tag::TAG_DEFPLICIT) {
275 if (module_uses_explicit) tag->set_plicit(Tag::TAG_EXPLICIT);
276 else tag->set_plicit(Tag::TAG_IMPLICIT);
277 }
278 }
279 }
280
281 void Tags::cut_auto_tags()
282 {
283 size_t i = 0;
284 while (i < tags.size()) {
285 Tag *tag = tags[i];
286 if (tag->is_automatic()) {
287 delete tag;
288 tags.replace(i, 1, NULL);
289 } else i++;
290 }
291 }
292
293 void Tags::dump(unsigned level) const
294 {
295 for(size_t i=0; i<tags.size(); i++)
296 tags[i]->dump(level);
297 }
298
299 // =================================
300 // ===== TagCollection
301 // =================================
302
303 TagCollection::TagCollection()
304 : has_all(NULL), is_extensible(false)
305 {
306 }
307
308 TagCollection::TagCollection(const TagCollection& p)
309 : Node(p), Location(p),
310 has_all(p.has_all), is_extensible(p.is_extensible)
311 {
312 for (size_t i = 0; i < p.tag_map.size(); i++)
313 tag_map.add(p.tag_map.get_nth_key(i), 0);
314 }
315
316 TagCollection::~TagCollection()
317 {
318 tag_map.clear();
319 }
320
321 void TagCollection::addTag(const Tag *p_tag)
322 {
323 if (!p_tag)
324 FATAL_ERROR("Asn::TagCollection::addTag()");
325 if (p_tag->get_tagclass() == Tag::TAG_ALL) {
326 if (has_all)
327 FATAL_ERROR("Asn::TagCollection::addTag(): tag 'all'");
328 has_all = p_tag;
329 }
330 else if(p_tag->get_tagclass() == Tag::TAG_ERROR)
331 return;
332 else if(!tag_map.has_key(*p_tag))
333 tag_map.add(*p_tag, 0);
334 else
335 FATAL_ERROR("Asn::TagCollection::addTag(): tag is already in collection");
336 }
337
338 bool TagCollection::hasTag(const Tag *p_tag) const
339 {
340 if (!p_tag) FATAL_ERROR("NULL parameter: Asn::TagCollection::hasTag()");
341 if (has_all) return true;
342 else if (p_tag->get_tagclass() == Tag::TAG_ALL) return !tag_map.empty();
343 else if (p_tag->get_tagclass() == Tag::TAG_ERROR) return false;
344 else return tag_map.has_key(*p_tag);
345 }
346
347 void TagCollection::addTags(const TagCollection *p_tags)
348 {
349 if (!p_tags) FATAL_ERROR("NULL parameter: Asn::TagCollection::addTags()");
350 if (p_tags->is_extensible) setExtensible();
351 if (p_tags->has_all) {
352 if (has_all) FATAL_ERROR("Asn::TagCollection::addTags(): tag 'all'");
353 has_all = p_tags->has_all;
354 }
355 for (size_t i = 0; i < p_tags->tag_map.size(); i++) {
356 const Tag& tag = p_tags->tag_map.get_nth_key(i);
357 if (!tag_map.has_key(tag)) tag_map.add(tag, 0);
358 else FATAL_ERROR("Asn::TagCollection::addTags(): tag is already in collection");
359 }
360 }
361
362 bool TagCollection::hasTags(const TagCollection *p_tags) const
363 {
364 if (!p_tags) FATAL_ERROR("NULL parameter: Asn::TagCollection::hasTags()");
365 if (has_all) return !p_tags->isEmpty();
366 else if (p_tags->has_all) return !isEmpty();
367 for (size_t i = 0; i < p_tags->tag_map.size(); i++)
368 if (tag_map.has_key(p_tags->tag_map.get_nth_key(i))) return true;
369 return false;
370 }
371
372 bool TagCollection::greaterTags(const TagCollection *p_tags) const
373 {
374 if (!p_tags)
375 FATAL_ERROR("NULL parameter: Asn::TagCollection::greaterTags()");
376 if (has_all) return !p_tags->isEmpty();
377 else if (p_tags->has_all) return !isEmpty();
378 else if (tag_map.empty() || p_tags->tag_map.empty()) return true;
379 else return tag_map.get_nth_key(tag_map.size() - 1) <
380 p_tags->tag_map.get_nth_key(0);
381 }
382
383 const Tag *TagCollection::getSmallestTag() const
384 {
385 if (has_all) return has_all;
386 if (tag_map.empty()) FATAL_ERROR("TagCollection::getSmallestTag()");
387 return &tag_map.get_nth_key(0);
388 }
389
390 const Tag *TagCollection::getGreatestTag() const
391 {
392 if (has_all) return has_all;
393 if (tag_map.empty()) FATAL_ERROR("TagCollection::getGreatestTag()");
394 return &tag_map.get_nth_key(tag_map.size() - 1);
395 }
396
397 void TagCollection::setExtensible()
398 {
399 if(is_extensible)
400 error("Illegal use of extensibility notation (possible tag conflict)");
401 else is_extensible=true;
402 }
403
404 bool TagCollection::isEmpty() const
405 {
406 if (has_all || is_extensible) return false;
407 else return tag_map.empty();
408 }
409
410 void TagCollection::clear()
411 {
412 tag_map.clear();
413 has_all = NULL;
414 is_extensible = false;
415 }
416
417 } // namespace Asn
This page took 0.039398 seconds and 6 git commands to generate.