16485b86e1e46a57bab37200b87f33de9bdeb8f7
[deliverable/titan.core.git] / compiler2 / ttcn3 / Attributes.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 * Baranyi, Botond
11 * Delic, Adam
12 * Feher, Csaba
13 * Raduly, Csaba
14 * Szabados, Kristof
15 * Szabo, Janos Zoltan – initial implementation
16 * Zalanyi, Balazs Andor
17 *
18 ******************************************************************************/
19 #include "Attributes.hh"
20 #include "../map.hh"
21 #include "../CompilerError.hh"
22 #include "../Type.hh"
23 #include "TtcnTemplate.hh"
24
25 namespace Ttcn {
26
27 // ==== Qualifier ====
28
29 Qualifier* Qualifier::clone() const
30 {
31 return new Qualifier(*this);
32 }
33
34 const Identifier* Qualifier::get_identifier(size_t p_index) const
35 {
36 FieldOrArrayRef* ref = get_ref(p_index);
37 return (ref->get_type()==FieldOrArrayRef::FIELD_REF) ?
38 ref->get_id() :
39 &underscore_zero ;
40 }
41
42 Qualifier* Qualifier::get_qualifier_without_first_id() const
43 {
44 Qualifier* temp = this->clone();
45 temp->remove_refs(1);
46 return temp;
47 }
48
49 string Qualifier::get_stringRepr() const
50 {
51 string str_repr;
52 append_stringRepr(str_repr);
53 if (str_repr[0]=='.') str_repr.replace(0, 1, ""); // remove leading dot if present
54 return str_repr;
55 }
56
57 void Qualifier::dump(unsigned level) const
58 {
59 const string& rep = get_stringRepr();
60 DEBUG(level, "(%s)", rep.c_str());
61 }
62
63 // ==== Qualifiers ====
64
65 Qualifiers::~Qualifiers()
66 {
67 for(size_t i = 0; i < qualifiers.size(); i++)
68 {
69 delete qualifiers[i];
70 }
71 qualifiers.clear();
72 }
73
74 Qualifiers::Qualifiers(const Qualifiers& p)
75 : Node(p)
76 {
77 for(size_t i = 0; i < p.get_nof_qualifiers(); i++)
78 {
79 qualifiers.add(p.get_qualifier(i)->clone());
80 }
81 }
82
83 void Qualifiers::add_qualifier(Qualifier* p_qualifier)
84 {
85 if(p_qualifier->get_nof_identifiers() > 0)
86 qualifiers.add(p_qualifier);
87 else
88 delete p_qualifier;
89 }
90
91 void Qualifiers::delete_qualifier(size_t p_index)
92 {
93 delete qualifiers[p_index];
94 qualifiers.replace(p_index,1,NULL);
95 }
96
97 const Qualifier* Qualifiers::get_qualifier(size_t p_index) const
98 {
99 return qualifiers[p_index];
100 }
101
102 Qualifiers* Qualifiers::clone() const
103 {
104 return new Qualifiers(*this);
105 }
106
107 void Qualifiers::set_fullname(const string& p_fullname)
108 {
109 Node::set_fullname(p_fullname);
110 for(size_t i = 0; i < qualifiers.size(); i++)
111 {
112 qualifiers[i]->set_fullname(p_fullname + ".<qualifier "
113 + Int2string(i) + ">");
114 }
115 }
116
117 bool Qualifiers::has_qualifier(Qualifier* p_qualifier) const
118 {
119 bool result = false;
120 size_t index;
121 bool same;
122 for(size_t i = 0; i < qualifiers.size() && !result; i++)
123 {
124 if(qualifiers[i]->get_nof_identifiers()
125 ==p_qualifier->get_nof_identifiers())
126 {
127 index = 0;
128 same = true;
129 while(index < p_qualifier->get_nof_identifiers() && same)
130 {
131 same = (*qualifiers[i]->get_identifier(index)
132 == *p_qualifier->get_identifier(index));
133 index++;
134 }
135
136 result |= same;
137 }
138 }
139 return result;
140 }
141
142 void Qualifiers::dump(unsigned level) const
143 {
144 DEBUG(level, "has %lu qualifiers",
145 (unsigned long)get_nof_qualifiers());
146 for(size_t i = 0; i < qualifiers.size(); i++)
147 qualifiers[i]->dump(level);
148 }
149
150 // ==== ErroneousDescriptor ====
151
152 ErroneousDescriptor::~ErroneousDescriptor()
153 {
154 for (size_t i=0; i<descr_m.size(); i++) delete descr_m.get_nth_elem(i);
155 descr_m.clear();
156 for (size_t i=0; i<values_m.size(); i++) delete values_m.get_nth_elem(i);
157 values_m.clear();
158 }
159
160 // ==== ErroneousAttributeSpec ====
161
162 ErroneousAttributeSpec::ErroneousAttributeSpec(bool p_is_raw, indicator_t p_indicator, TemplateInstance* p_tmpl_inst, bool p_has_all_keyword):
163 is_raw(p_is_raw), has_all_keyword(p_has_all_keyword), indicator(p_indicator),
164 tmpl_inst(p_tmpl_inst), type(0), value(0)
165 {
166 if (!tmpl_inst) FATAL_ERROR("ErroneousAttributeSpec::ErroneousAttributeSpec()");
167 }
168
169 ErroneousAttributeSpec::ErroneousAttributeSpec(const ErroneousAttributeSpec& p)
170 : Node(p), Location(p), is_raw(p.is_raw), has_all_keyword(p.has_all_keyword),
171 indicator(p.indicator), type(0), value(0)
172 {
173 tmpl_inst = p.tmpl_inst ? tmpl_inst->clone() : 0;
174 }
175
176 ErroneousAttributeSpec::~ErroneousAttributeSpec()
177 {
178 delete tmpl_inst;
179 delete value;
180 }
181
182 ErroneousAttributeSpec* ErroneousAttributeSpec::clone() const
183 {
184 return new ErroneousAttributeSpec(*this);
185 }
186
187 void ErroneousAttributeSpec::set_fullname(const string& p_fullname)
188 {
189 Node::set_fullname(p_fullname);
190 tmpl_inst->set_fullname(p_fullname+".<template_instance>");
191 }
192
193 void ErroneousAttributeSpec::set_my_scope(Scope *p_scope)
194 {
195 tmpl_inst->set_my_scope(p_scope);
196 }
197
198 void ErroneousAttributeSpec::dump(unsigned level) const
199 {
200 DEBUG(level, "raw: %s", is_raw ? "yes" : "no");
201 DEBUG(level, "indicator:");
202 switch (indicator) {
203 case I_BEFORE:
204 DEBUG(level+1, "before");
205 break;
206 case I_VALUE:
207 DEBUG(level+1, "value");
208 break;
209 case I_AFTER:
210 DEBUG(level+1, "after");
211 break;
212 case I_INVALID:
213 DEBUG(level+1, "<invalid>");
214 break;
215 default:
216 FATAL_ERROR("ErroneousAttributeSpec::dump()");
217 }
218 DEBUG(level, "template instance:");
219 tmpl_inst->dump(level+1);
220 }
221
222 bool ErroneousAttributeSpec::get_is_omit() const
223 {
224 return (tmpl_inst->get_Template()->get_templatetype()==Template::OMIT_VALUE);
225 }
226
227 void ErroneousAttributeSpec::chk()
228 {
229 if (get_is_omit()) { // special case, no type needed
230 if ((indicator==I_BEFORE)||(indicator==I_AFTER)) {
231 if (!has_all_keyword) {
232 tmpl_inst->error(
233 "Keyword `all' is expected after `omit' when omitting all fields %s the specified field",
234 get_indicator_str(indicator));
235 }
236 } else {
237 if (has_all_keyword) {
238 tmpl_inst->error(
239 "Unexpected `all' keyword after `omit' when omitting one field");
240 }
241 }
242 type = 0;
243 return;
244 }
245 if (has_all_keyword) {
246 tmpl_inst->error(
247 "Unexpected `all' keyword after the in-line template");
248 }
249
250 // determine the type of the tmpl_inst
251 type = tmpl_inst->get_expr_governor(Type::EXPECTED_TEMPLATE);
252 if (!type) {
253 tmpl_inst->get_Template()->set_lowerid_to_ref();
254 type = tmpl_inst->get_expr_governor(Type::EXPECTED_TEMPLATE);
255 }
256 if (!type) {
257 tmpl_inst->error("Cannot determine the type of the in-line template");
258 return;
259 }
260 type->chk();
261 Type* type_last = type->get_type_refd_last();
262 if (!type_last || type_last->get_typetype()==Type::T_ERROR) {
263 type = 0;
264 return;
265 }
266 if (is_raw) {
267 switch (type_last->get_typetype_ttcn3()) {
268 case Type::T_BSTR:
269 case Type::T_OSTR:
270 case Type::T_CSTR:
271 case Type::T_USTR:
272 break;
273 default:
274 tmpl_inst->error("An in-line template of type `%s' cannot be used as a `raw' erroneous value",
275 type_last->get_typename().c_str());
276 }
277 }
278
279 if (tmpl_inst->get_DerivedRef()) {
280 tmpl_inst->error("Reference to a constant value was expected instead of an in-line modified template");
281 type = 0;
282 return;
283 }
284
285 Template* templ = tmpl_inst->get_Template();
286
287 if (templ->is_Value()) {
288 value = templ->get_Value();
289 value->set_my_governor(type);
290 type->chk_this_value_ref(value);
291 type->chk_this_value(value, 0, Type::EXPECTED_CONSTANT,
292 INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
293 //{ FIXME: make this work
294 // ReferenceChain refch(type, "While checking embedded recursions");
295 // value->chk_recursions(refch);
296 //}
297 value->set_code_section(GovernedSimple::CS_PRE_INIT);
298 } else {
299 tmpl_inst->error("A specific value without matching symbols was expected");
300 type = 0;
301 return;
302 }
303 }
304
305 const char* ErroneousAttributeSpec::get_indicator_str(indicator_t i)
306 {
307 switch (i) {
308 case I_BEFORE: return "before";
309 case I_VALUE: return "value";
310 case I_AFTER: return "after";
311 default: FATAL_ERROR("ErroneousAttributeSpec::get_indicator_str()");
312 }
313 return "";
314 }
315
316 char* ErroneousAttributeSpec::generate_code_str(char *str, string genname)
317 {
318 if (get_is_omit()) return str;
319 if (!type) FATAL_ERROR("ErroneousAttributeSpec::generate_code_str()");
320 if (!value) FATAL_ERROR("ErroneousAttributeSpec::generate_code_str()");
321 if (first_genname.empty()) { // this is the first use
322 str = mputprintf(str, "static %s %s;\n",
323 type->get_genname_value(value->get_my_scope()).c_str(), genname.c_str());
324 first_genname = genname;
325 } else {
326 str = mputprintf(str, "static %s& %s = %s;\n",
327 type->get_genname_value(value->get_my_scope()).c_str(),
328 genname.c_str(), first_genname.c_str());
329 }
330 return str;
331 }
332
333 char* ErroneousAttributeSpec::generate_code_init_str(char *str, string genname)
334 {
335 if (get_is_omit()) return str;
336 if (!type) FATAL_ERROR("ErroneousAttributeSpec::generate_code_init_str()");
337 if (!value) FATAL_ERROR("ErroneousAttributeSpec::generate_code_init_str()");
338 str = value->generate_code_init(str, genname.c_str());
339 return str;
340 }
341
342 string ErroneousAttributeSpec::get_typedescriptor_str()
343 {
344 if (get_is_omit() || is_raw) return string("NULL");
345 if (!type) FATAL_ERROR("ErroneousAttributeSpec::get_typedescriptor_str()");
346 if (!value) FATAL_ERROR("ErroneousAttributeSpec::generate_code_ti_str()");
347 return ( "&" + type->get_genname_typedescriptor(value->get_my_scope()) + "_descr_" );
348 }
349
350 void ErroneousAttributeSpec::chk_recursions(ReferenceChain& refch)
351 {
352 if (value) {
353 refch.mark_state();
354 value->chk_recursions(refch);
355 refch.prev_state();
356 }
357 }
358
359 // ==== ErroneousValues ====
360
361 char* ErroneousValues::generate_code_embedded_str(char *str, string genname)
362 {
363 if (before) str = generate_code_embedded_str(str, genname+"_before", before);
364 if (value) str = generate_code_embedded_str(str, genname+"_value", value);
365 if (after) str = generate_code_embedded_str(str, genname+"_after", after);
366 return str;
367 }
368
369 char* ErroneousValues::generate_code_embedded_str(char *str, string genname, ErroneousAttributeSpec* attr_spec)
370 {
371 str = attr_spec->generate_code_str(str, genname+"_errval");
372 str = mputprintf(str, "static Erroneous_value_t %s = { %s, %s, %s };\n", genname.c_str(),
373 attr_spec->get_is_raw() ? "true" : "false",
374 attr_spec->get_is_omit() ? "NULL" : ("&"+genname+"_errval").c_str(),
375 attr_spec->get_typedescriptor_str().c_str());
376 return str;
377 }
378
379 char* ErroneousValues::generate_code_init_str(char *str, string genname)
380 {
381 if (before) str = before->generate_code_init_str(str, genname+"_before_errval");
382 if (value) str = value->generate_code_init_str(str, genname+"_value_errval");
383 if (after) str = after->generate_code_init_str(str, genname+"_after_errval");
384 return str;
385 }
386
387 char* ErroneousValues::generate_code_struct_str(char *str, string genname, int field_index)
388 {
389 str = mputprintf(str, "{ %d, %s, %s, %s, %s }", field_index,
390 ("\""+field_name+"\"").c_str(),
391 before ? ("&"+genname+"_before").c_str() : "NULL",
392 value ? ("&"+genname+"_value").c_str() : "NULL",
393 after ? ("&"+genname+"_after").c_str() : "NULL");
394 return str;
395 }
396
397 void ErroneousValues::chk_recursions(ReferenceChain& refch)
398 {
399 if (before) before->chk_recursions(refch);
400 if (value) value->chk_recursions(refch);
401 if (after) after->chk_recursions(refch);
402 }
403
404 // ==== ErroneousDescriptor ====
405
406 char* ErroneousDescriptor::generate_code_embedded_str(char *str, string genname)
407 {
408 // values
409 for (size_t i=0; i<values_m.size(); i++) {
410 str = values_m.get_nth_elem(i)->generate_code_embedded_str(str, genname+"_v"+Int2string((int)values_m.get_nth_key(i)));
411 }
412 // embedded descriptors
413 for (size_t i=0; i<descr_m.size(); i++) {
414 str = descr_m.get_nth_elem(i)->generate_code_embedded_str(str, genname+"_d"+Int2string((int)descr_m.get_nth_key(i)));
415 }
416 // values vector
417 if (values_m.size()>0) {
418 str = mputprintf(str, "static Erroneous_values_t %s_valsvec[%d] = { ", genname.c_str(), (int)values_m.size());
419 for (size_t i=0; i<values_m.size(); i++) {
420 if (i>0) str = mputstr(str, ", ");
421 int key_i = (int)values_m.get_nth_key(i);
422 str = values_m.get_nth_elem(i)->generate_code_struct_str(str, genname+"_v"+Int2string(key_i), key_i);
423 }
424 str = mputstr(str, " };\n");
425 }
426 // embedded descriptor vector
427 if (descr_m.size()>0) {
428 str = mputprintf(str, "static Erroneous_descriptor_t %s_embvec[%d] = { ", genname.c_str(), (int)descr_m.size());
429 for (size_t i=0; i<descr_m.size(); i++) {
430 if (i>0) str = mputstr(str, ", ");
431 int key_i = (int)descr_m.get_nth_key(i);
432 str = descr_m.get_nth_elem(i)->generate_code_struct_str(str, genname+"_d"+Int2string(key_i), key_i);
433 }
434 str = mputstr(str, " };\n");
435 }
436 return str;
437 }
438
439 char* ErroneousDescriptor::generate_code_init_str(char *str, string genname)
440 {
441 for (size_t i=0; i<values_m.size(); i++) {
442 str = values_m.get_nth_elem(i)->generate_code_init_str(str, genname+"_v"+Int2string((int)values_m.get_nth_key(i)));
443 }
444 for (size_t i=0; i<descr_m.size(); i++) {
445 str = descr_m.get_nth_elem(i)->generate_code_init_str(str, genname+"_d"+Int2string((int)descr_m.get_nth_key(i)));
446 }
447 return str;
448 }
449
450 char* ErroneousDescriptor::generate_code_struct_str(char *str, string genname, int field_index)
451 {
452 string genname_values_vec = genname + "_valsvec";
453 string genname_embedded_vec = genname + "_embvec";
454 str = mputprintf(str, "{ %d, %d, %s, %d, %s, %d, %s, %d, %s }",
455 field_index,
456 omit_before, (omit_before==-1)?"NULL":("\""+omit_before_name+"\"").c_str(),
457 omit_after, (omit_after==-1)?"NULL":("\""+omit_after_name+"\"").c_str(),
458 (int)values_m.size(), (values_m.size()>0) ? genname_values_vec.c_str(): "NULL",
459 (int)descr_m.size(), (descr_m.size()>0) ? genname_embedded_vec.c_str(): "NULL");
460 return str;
461 }
462
463 void ErroneousDescriptor::chk_recursions(ReferenceChain& refch)
464 {
465 for (size_t i=0; i<values_m.size(); i++) {
466 values_m.get_nth_elem(i)->chk_recursions(refch);
467 }
468 for (size_t i=0; i<descr_m.size(); i++) {
469 descr_m.get_nth_elem(i)->chk_recursions(refch);
470 }
471 }
472
473 char* ErroneousDescriptor::generate_code_str(char *str, string genname)
474 {
475 genname += "_err_descr";
476 str = generate_code_embedded_str(str, genname);
477 str = mputprintf(str, "static Erroneous_descriptor_t %s = ", genname.c_str());
478 str = generate_code_struct_str(str, genname, -1);
479 str = mputstr(str, ";\n");
480 return str;
481 }
482
483 // ==== ErroneousAttributes ====
484
485 ErroneousAttributes::ErroneousAttributes(Type* p_type):
486 type(p_type), err_descr_tree(NULL)
487 {
488 if (!type) FATAL_ERROR("ErroneousAttributes::ErroneousAttributes()");
489 }
490
491 ErroneousAttributes::~ErroneousAttributes()
492 {
493 for (size_t i=0; i<spec_vec.size(); i++) {
494 delete spec_vec[i];
495 }
496 spec_vec.clear();
497 if (err_descr_tree) delete err_descr_tree;
498 }
499
500 ErroneousAttributes::ErroneousAttributes(const ErroneousAttributes& p)
501 : Node(p), type(p.type), err_descr_tree(NULL)
502 {
503 }
504
505 ErroneousAttributes* ErroneousAttributes::clone() const
506 {
507 return new ErroneousAttributes(*this);
508 }
509
510 void ErroneousAttributes::set_fullname(const string& p_fullname)
511 {
512 Node::set_fullname(p_fullname);
513 for (size_t i=0; i<spec_vec.size(); i++) {
514 spec_vec[i]->set_fullname(p_fullname+".<erroneous_attr_spec_"+Int2string(i)+">");
515 }
516 }
517
518 void ErroneousAttributes::dump(unsigned level) const
519 {
520 DEBUG(level, "erroneous attributes:");
521 for (size_t i=0; i<spec_vec.size(); i++) {
522 spec_vec[i]->dump(level+1);
523 }
524 }
525
526 void ErroneousAttributes::add_spec(ErroneousAttributeSpec* err_attr_spec)
527 {
528 if (!err_attr_spec) FATAL_ERROR("ErroneousAttributes::add_spec()");
529 spec_vec.add(err_attr_spec);
530 }
531
532 void ErroneousAttributes::add_pair(const Qualifier* qualifier, ErroneousAttributeSpec* err_attr_spec)
533 {
534 if (!qualifier || !err_attr_spec) FATAL_ERROR("ErroneousAttributes::add()");
535 field_err_t f;
536 f.qualifier = qualifier;
537 f.err_attr = err_attr_spec;
538 field_array.add(f);
539 }
540
541 void ErroneousAttributes::chk()
542 {
543 // check that encodings of erroneous type and templateinstance type match
544 for (size_t i=0; i<spec_vec.size(); i++) {
545 ErroneousAttributeSpec* act_attr = spec_vec[i];
546 Type* ti_type = act_attr->get_type();
547 if ((act_attr->get_indicator()!=ErroneousAttributeSpec::I_INVALID) && ti_type) {
548 if (act_attr->get_is_raw()) {
549 switch (ti_type->get_typetype_ttcn3()) {
550 case Type::T_BSTR:
551 if (!type->has_encoding(Type::CT_PER) && !type->has_encoding(Type::CT_RAW)) {
552 act_attr->error("A `raw' %s value was used for erroneous type `%s' which has no RAW or PER encodings.",
553 ti_type->get_typename().c_str(), type->get_typename().c_str());
554 }
555 break;
556 case Type::T_CSTR:
557 if (!type->has_encoding(Type::CT_TEXT) && !type->has_encoding(Type::CT_XER) &&
558 !type->has_encoding(Type::CT_JSON)) {
559 act_attr->error("A `raw' %s value was used for erroneous type `%s' which has no TEXT, XER or JSON encodings.",
560 ti_type->get_typename().c_str(), type->get_typename().c_str());
561 }
562 break;
563 case Type::T_USTR:
564 if (!type->has_encoding(Type::CT_XER) && !type->has_encoding(Type::CT_JSON)) {
565 act_attr->error("A `raw' %s value was used for erroneous type `%s' which has no XER or JSON encoding.",
566 ti_type->get_typename().c_str(), type->get_typename().c_str());
567 }
568 break;
569 default:
570 break;
571 }
572 } else {
573 // the two types must have at least one common encoding
574 if (!((type->has_encoding(Type::CT_BER)&&ti_type->has_encoding(Type::CT_BER)) ||
575 (type->has_encoding(Type::CT_PER)&&ti_type->has_encoding(Type::CT_PER)) ||
576 (type->has_encoding(Type::CT_RAW)&&ti_type->has_encoding(Type::CT_RAW)) ||
577 (type->has_encoding(Type::CT_TEXT)&&ti_type->has_encoding(Type::CT_TEXT)) ||
578 (type->has_encoding(Type::CT_XER)&&ti_type->has_encoding(Type::CT_XER)) ||
579 (type->has_encoding(Type::CT_JSON)&&ti_type->has_encoding(Type::CT_JSON)))) {
580 act_attr->error("Type `%s' and type `%s' have no common encoding",
581 ti_type->get_typename().c_str(), type->get_typename().c_str());
582 }
583 }
584 }
585 }
586
587 // for every erroneous field calculate the corresponding index and type arrays
588 // for example: x[5].z -> [3,5,2] and [MyRec,MyRecOf,MyUnion]
589 // MyRec.x field has index 3, etc.
590 for (size_t i=0; i<field_array.size(); i++) {
591 bool b = type->get_subrefs_as_array(field_array[i].qualifier, field_array[i].subrefs_array, field_array[i].type_array);
592 if (!b) FATAL_ERROR("ErroneousAttributes::chk()");
593 }
594 // check the qualifiers and build the tree
595 err_descr_tree = build_descr_tree(field_array);
596 }
597
598 ErroneousDescriptor* ErroneousAttributes::build_descr_tree(dynamic_array<field_err_t>& fld_array)
599 {
600 ErroneousDescriptor* err_descr = new ErroneousDescriptor();
601 const Qualifier * omit_before_qual = NULL, * omit_after_qual = NULL;
602 map< size_t, dynamic_array<field_err_t> > embedded_fld_array_m; // used for recursive calls
603 for (size_t i=0; i<fld_array.size(); i++) {
604 field_err_t& act_field_err = fld_array[i];
605 ErroneousAttributeSpec::indicator_t act_indicator = act_field_err.err_attr->get_indicator();
606 bool is_omit = act_field_err.err_attr->get_is_omit();
607 if (act_field_err.subrefs_array.size()<1) FATAL_ERROR("ErroneousAttributes::build_descr_tree()");
608 size_t fld_idx = act_field_err.subrefs_array[0];
609 if (omit_before_qual && (err_descr->omit_before!=-1) && (err_descr->omit_before>(int)fld_idx)) {
610 act_field_err.qualifier->error(
611 "Field `%s' cannot be referenced because all fields before field `%s' have been omitted",
612 act_field_err.qualifier->get_stringRepr().c_str(), omit_before_qual->get_stringRepr().c_str());
613 continue;
614 }
615 if (omit_after_qual && (err_descr->omit_after!=-1) && (err_descr->omit_after<(int)fld_idx)) {
616 act_field_err.qualifier->error(
617 "Field `%s' cannot be referenced because all fields after field `%s' have been omitted",
618 act_field_err.qualifier->get_stringRepr().c_str(), omit_after_qual->get_stringRepr().c_str());
619 continue;
620 }
621 if (act_field_err.subrefs_array.size()==1) { // erroneous value
622 if (act_field_err.type_array.size()!=1) FATAL_ERROR("ErroneousAttributes::build_descr_tree()");
623 if ((act_field_err.type_array[0]->get_typetype()==Type::T_SET_A) &&
624 is_omit && (act_indicator!=ErroneousAttributeSpec::I_VALUE)) {
625 act_field_err.qualifier->error(
626 "Cannot omit all fields %s `%s' which is a field of an ASN.1 SET type",
627 ErroneousAttributeSpec::get_indicator_str(act_indicator), act_field_err.qualifier->get_stringRepr().c_str());
628 act_field_err.qualifier->note(
629 "The order of fields in ASN.1 SET types changes depending on tagging (see X.690 9.3). "
630 "Fields can be omitted individually, independently of the field order which depends on tagging");
631 continue;
632 }
633 switch (act_field_err.type_array[0]->get_typetype_ttcn3()) {
634 case Type::T_CHOICE_T:
635 if (act_indicator!=ErroneousAttributeSpec::I_VALUE) {
636 act_field_err.qualifier->error(
637 "Indicator `%s' cannot be used with reference `%s' which points to a field of a union type",
638 ErroneousAttributeSpec::get_indicator_str(act_indicator), act_field_err.qualifier->get_stringRepr().c_str());
639 continue;
640 }
641 break;
642 case Type::T_SEQ_T:
643 case Type::T_SET_T:
644 if (is_omit && (act_indicator==ErroneousAttributeSpec::I_AFTER) &&
645 (fld_idx==act_field_err.type_array[0]->get_nof_comps()-1)) {
646 act_field_err.qualifier->error(
647 "There is nothing to omit after the last field (%s) of a record/set type",
648 act_field_err.qualifier->get_stringRepr().c_str());
649 continue;
650 }
651 // no break
652 case Type::T_SEQOF:
653 case Type::T_SETOF:
654 if (is_omit && (act_indicator==ErroneousAttributeSpec::I_BEFORE) &&
655 (fld_idx==0)) {
656 act_field_err.qualifier->error(
657 "There is nothing to omit before the first field (%s)",
658 act_field_err.qualifier->get_stringRepr().c_str());
659 continue;
660 }
661 break;
662 default:
663 break;
664 }
665 // check for duplicate value+indicator
666 if (err_descr->values_m.has_key(fld_idx)) {
667 ErroneousValues* evs = err_descr->values_m[fld_idx];
668 if ( (evs->before && (act_indicator==ErroneousAttributeSpec::I_BEFORE)) ||
669 (evs->value && (act_indicator==ErroneousAttributeSpec::I_VALUE)) ||
670 (evs->after && (act_indicator==ErroneousAttributeSpec::I_AFTER)) ) {
671 act_field_err.qualifier->error(
672 "Duplicate reference to field `%s' with indicator `%s'",
673 act_field_err.qualifier->get_stringRepr().c_str(), ErroneousAttributeSpec::get_indicator_str(act_indicator));
674 continue;
675 }
676 }
677 // when overwriting a value check if embedded values were used
678 if ((act_indicator==ErroneousAttributeSpec::I_VALUE) && embedded_fld_array_m.has_key(fld_idx)) {
679 act_field_err.qualifier->error(
680 "Reference to field `%s' with indicator `value' would invalidate previously specified erroneous data",
681 act_field_err.qualifier->get_stringRepr().c_str());
682 continue;
683 }
684 // if before/after omit then check that no references to omitted regions and no duplication of omit before/after rule
685 if ((act_indicator==ErroneousAttributeSpec::I_BEFORE) && is_omit) {
686 if (omit_before_qual && (err_descr->omit_before!=-1)) {
687 act_field_err.qualifier->error(
688 "Duplicate rule for omitting all fields before the specified field. Used on field `%s' but previously already used on field `%s'",
689 act_field_err.qualifier->get_stringRepr().c_str(), omit_before_qual->get_stringRepr().c_str());
690 continue;
691 }
692 bool is_invalid = false;
693 for (size_t j=0; j<err_descr->values_m.size(); j++) {
694 if (err_descr->values_m.get_nth_key(j)<fld_idx) {
695 is_invalid = true;
696 break;
697 }
698 }
699 if (!is_invalid) {
700 for (size_t j=0; j<embedded_fld_array_m.size(); j++) {
701 if (embedded_fld_array_m.get_nth_key(j)<fld_idx) {
702 is_invalid = true;
703 break;
704 }
705 }
706 }
707 if (is_invalid) {
708 act_field_err.qualifier->error(
709 "Omitting fields before field `%s' would invalidate previously specified erroneous data",
710 act_field_err.qualifier->get_stringRepr().c_str());
711 continue;
712 }
713 // save valid omit before data
714 omit_before_qual = act_field_err.qualifier;
715 err_descr->omit_before = fld_idx;
716 err_descr->omit_before_name = omit_before_qual->get_stringRepr();
717 continue;
718 }
719 if ((act_indicator==ErroneousAttributeSpec::I_AFTER) && is_omit) {
720 if (omit_after_qual && (err_descr->omit_after!=-1)) {
721 act_field_err.qualifier->error(
722 "Duplicate rule for omitting all fields after the specified field. Used on field `%s' but previously already used on field `%s'",
723 act_field_err.qualifier->get_stringRepr().c_str(), omit_after_qual->get_stringRepr().c_str());
724 continue;
725 }
726 bool is_invalid = false;
727 for (size_t j=0; j<err_descr->values_m.size(); j++) {
728 if (err_descr->values_m.get_nth_key(j)>fld_idx) {
729 is_invalid = true;
730 break;
731 }
732 }
733 if (!is_invalid) {
734 for (size_t j=0; j<embedded_fld_array_m.size(); j++) {
735 if (embedded_fld_array_m.get_nth_key(j)>fld_idx) {
736 is_invalid = true;
737 break;
738 }
739 }
740 }
741 if (is_invalid) {
742 act_field_err.qualifier->error(
743 "Omitting fields after field `%s' would invalidate previously specified erroneous data",
744 act_field_err.qualifier->get_stringRepr().c_str());
745 continue;
746 }
747 // save valid omit after data
748 omit_after_qual = act_field_err.qualifier;
749 err_descr->omit_after = fld_idx;
750 err_descr->omit_after_name = omit_after_qual->get_stringRepr();
751 continue;
752 }
753 // if not before/after omit then save this into values_m
754 bool has_key = err_descr->values_m.has_key(fld_idx);
755 ErroneousValues* evs = has_key ? err_descr->values_m[fld_idx] : new ErroneousValues(act_field_err.qualifier->get_stringRepr());
756 switch (act_indicator) {
757 case ErroneousAttributeSpec::I_BEFORE: evs->before = act_field_err.err_attr; break;
758 case ErroneousAttributeSpec::I_VALUE: evs->value = act_field_err.err_attr; break;
759 case ErroneousAttributeSpec::I_AFTER: evs->after = act_field_err.err_attr; break;
760 default: FATAL_ERROR("ErroneousAttributes::build_descr_tree()");
761 }
762 if (!has_key) {
763 err_descr->values_m.add(fld_idx, evs);
764 }
765 } else { // embedded err.value
766 if ((err_descr->values_m.has_key(fld_idx)) && (err_descr->values_m[fld_idx]->value)) {
767 act_field_err.qualifier->error(
768 "Field `%s' is embedded into a field which was previously overwritten or omitted",
769 act_field_err.qualifier->get_stringRepr().c_str());
770 continue;
771 }
772 // add the embedded field to the map
773 bool has_idx = embedded_fld_array_m.has_key(fld_idx);
774 dynamic_array<field_err_t>* emb_fld_array = has_idx ? embedded_fld_array_m[fld_idx] : new dynamic_array<field_err_t>();
775 field_err_t emb_field_err = act_field_err;
776 emb_field_err.subrefs_array.remove(0); // remove the first reference
777 emb_field_err.type_array.remove(0);
778 emb_fld_array->add(emb_field_err);
779 if (!has_idx) {
780 embedded_fld_array_m.add(fld_idx, emb_fld_array);
781 }
782 }
783 }
784 // recursive calls to create embedded descriptors
785 for (size_t i=0; i<embedded_fld_array_m.size(); i++) {
786 dynamic_array<field_err_t>* emb_fld_array = embedded_fld_array_m.get_nth_elem(i);
787 err_descr->descr_m.add(embedded_fld_array_m.get_nth_key(i), build_descr_tree(*emb_fld_array));
788 delete emb_fld_array;
789 }
790 embedded_fld_array_m.clear();
791 return err_descr;
792 }
793
794 // ==== AttributeSpec ====
795
796 AttributeSpec* AttributeSpec::clone() const
797 {
798 return new AttributeSpec(*this);
799 }
800
801 void AttributeSpec::set_fullname(const string& p_fullname)
802 {
803 Node::set_fullname(p_fullname);
804 }
805
806 void AttributeSpec::dump(unsigned level) const
807 {
808 DEBUG(level,"spec: %s", spec.c_str());
809 }
810
811 // ==== SingleWithAttrib ====
812
813 SingleWithAttrib::SingleWithAttrib(const SingleWithAttrib& p)
814 : Node(p), Location(p), attribKeyword(p.attribKeyword),
815 hasOverride(p.hasOverride)
816 {
817 attribQualifiers = p.attribQualifiers ? p.attribQualifiers->clone() : 0;
818 attribSpec = p.attribSpec->clone();
819 }
820
821 SingleWithAttrib::SingleWithAttrib(
822 attribtype_t p_attribKeyword, bool p_hasOverride,
823 Qualifiers *p_attribQualifiers, AttributeSpec* p_attribSpec)
824 : Node(), Location(), attribKeyword(p_attribKeyword),
825 hasOverride(p_hasOverride), attribQualifiers(p_attribQualifiers),
826 attribSpec(p_attribSpec)
827 {
828 if(!p_attribSpec)
829 FATAL_ERROR("SingleWithAttrib::SingleWithAttrib()");
830 }
831
832 SingleWithAttrib::~SingleWithAttrib()
833 {
834 delete attribQualifiers;
835 delete attribSpec;
836 }
837
838 SingleWithAttrib* SingleWithAttrib::clone() const
839 {
840 return new SingleWithAttrib(*this);
841 }
842
843 void SingleWithAttrib::set_fullname(const string& p_fullname)
844 {
845 Node::set_fullname(p_fullname);
846 if(attribQualifiers)
847 attribQualifiers->set_fullname(p_fullname + ".<attribute qualifiers>");
848 attribSpec->set_fullname(p_fullname + ".<attribute specification>");
849 }
850
851 void SingleWithAttrib::dump(unsigned level) const
852 {
853 DEBUG(level,"attribute");
854 switch(attribKeyword)
855 {
856 case AT_ENCODE:
857 DEBUG(level + 1,"keyword: encode");
858 break;
859 case AT_VARIANT:
860 DEBUG(level + 1,"keyword: variant");
861 break;
862 case AT_DISPLAY:
863 DEBUG(level + 1,"keyword: display");
864 break;
865 case AT_EXTENSION:
866 DEBUG(level + 1,"keyword: extension");
867 break;
868 case AT_OPTIONAL:
869 DEBUG(level + 1,"keyword: optional");
870 break;
871 case AT_ERRONEOUS:
872 DEBUG(level+1, "keyword: erroneous");
873 break;
874 case AT_INVALID:
875 DEBUG(level+1, "invalid keyword");
876 break;
877 default:
878 FATAL_ERROR("SingleWithAttrib::dump()");
879 }
880
881 DEBUG(level + 1, hasOverride ? "has override" : "hasn't got override");
882
883 if(attribSpec)
884 attribSpec->dump(level + 1);
885 if(attribQualifiers)
886 attribQualifiers->dump(level + 1);
887 }
888
889 // ==== MultiWithAttrib ====
890
891 MultiWithAttrib::MultiWithAttrib(const MultiWithAttrib& p)
892 : Node(p), Location(p)
893 {
894 for(size_t i = 0; i < p.get_nof_elements(); i++)
895 {
896 elements.add(p.get_element(i)->clone());
897 }
898 }
899
900 MultiWithAttrib* MultiWithAttrib::clone() const
901 {
902 return new MultiWithAttrib(*this);
903 }
904
905 void MultiWithAttrib::set_fullname(const string& p_fullname)
906 {
907 Node::set_fullname(p_fullname);
908 for(size_t i = 0; i < elements.size(); i++)
909 {
910 elements[i]->set_fullname(p_fullname + ".<singlewithattribute "
911 + Int2string(i) + ">");
912 }
913 }
914
915 MultiWithAttrib::~MultiWithAttrib()
916 {
917 for(size_t i = 0; i < elements.size(); i++)
918 {
919 delete elements[i];
920 }
921 elements.clear();
922 }
923
924 const SingleWithAttrib* MultiWithAttrib::get_element(size_t p_index) const
925 {
926 return elements[p_index];
927 }
928
929 SingleWithAttrib* MultiWithAttrib::get_element_for_modification(
930 size_t p_index)
931 {
932 return elements[p_index];
933 }
934
935 void MultiWithAttrib::delete_element(size_t p_index)
936 {
937 delete elements[p_index];
938 elements.replace(p_index,1,NULL);
939 }
940
941 void MultiWithAttrib::dump(unsigned level) const
942 {
943 DEBUG(level,"with attrib parameters (%lu pcs)",
944 (unsigned long) elements.size());
945 for(size_t i = 0; i < elements.size(); i++)
946 {
947 elements[i]->dump(level + 1);
948 }
949 }
950
951 // ==== WithAttribPath ====
952
953 WithAttribPath::WithAttribPath(const WithAttribPath& p)
954 : Node(p), had_global_variants(false), attributes_checked(false),
955 cached(false), s_o_encode(false), parent(p.parent)
956 {
957 m_w_attrib = p.m_w_attrib ? p.m_w_attrib->clone() : 0;
958 }
959
960 WithAttribPath::~WithAttribPath()
961 {
962 delete m_w_attrib;
963 cache.clear();
964 }
965
966 WithAttribPath* WithAttribPath::clone() const
967 {
968 return new WithAttribPath(*this);
969 }
970
971 void WithAttribPath::set_fullname(const string& p_fullname)
972 {
973 Node::set_fullname(p_fullname);
974 if (m_w_attrib) m_w_attrib->set_fullname(p_fullname
975 + ".<multiwithattribute>");
976 }
977
978 void WithAttribPath::chk_no_qualif()
979 {
980 if(attributes_checked)
981 return;
982
983 if(!m_w_attrib)
984 return;
985
986 const SingleWithAttrib *swa;
987 for(int i = m_w_attrib->get_nof_elements() - 1; i >= 0; i--)
988 {
989 swa = m_w_attrib->get_element(i);
990 if( swa->get_attribQualifiers()
991 && swa->get_attribQualifiers()->get_nof_qualifiers() != 0)
992 {
993 swa->error("field qualifiers are only allowed"
994 " for record, set and union types");
995 m_w_attrib->delete_element(i);
996 }
997 }
998
999 attributes_checked = true;
1000 }
1001
1002 void WithAttribPath::dump(unsigned int level) const
1003 {
1004 DEBUG(level, "WithAttribPath");
1005 if (!m_w_attrib) return;
1006 DEBUG(level+1, "%lu elements",
1007 (unsigned long)m_w_attrib->get_nof_elements());
1008 for (size_t i=0; i < m_w_attrib->get_nof_elements(); ++i) {
1009 const SingleWithAttrib* a = m_w_attrib->get_element(i);
1010 if (!a) continue;
1011 a->dump(level+1);
1012 }
1013 }
1014
1015 /**
1016 * Checks whether there is inconsistency among global attributes or not.
1017 * Only the last encode can have effect so we can throw out the others.
1018 * This is because encode is not an attribute, but a "context".
1019 * If there is an overriding variant/display/extension then the
1020 * following attributes from the same type should be omitted.
1021 */
1022 void WithAttribPath::chk_global_attrib(bool erroneous_allowed)
1023 {
1024 if(!m_w_attrib)
1025 return;
1026
1027 if (!erroneous_allowed) {
1028 for(size_t i = m_w_attrib->get_nof_elements(); i > 0; i--) {
1029 const SingleWithAttrib* const temp_attrib =
1030 m_w_attrib->get_element(i-1);
1031 if (temp_attrib->get_attribKeyword()==SingleWithAttrib::AT_ERRONEOUS) {
1032 temp_attrib->error("The `erroneous' attribute can be used only on "
1033 "template and constant definitions");
1034 }
1035 }
1036 }
1037
1038 bool has_encode = false;
1039 bool has_override_variant = false;
1040 bool has_override_display = false;
1041 bool has_override_extension = false;
1042 bool has_override_optional = false;
1043 for(size_t i = m_w_attrib->get_nof_elements(); i > 0; i--)
1044 {
1045 const SingleWithAttrib* const temp_attrib =
1046 m_w_attrib->get_element(i-1);
1047 switch(temp_attrib->get_attribKeyword())
1048 {
1049 case SingleWithAttrib::AT_ENCODE:
1050 {
1051 if(has_encode)
1052 {
1053 temp_attrib->warning("Only the last encode "
1054 "of the with statement will have effect");
1055 m_w_attrib->delete_element(i-1);
1056 }else{
1057 has_encode = true;
1058 }
1059 }
1060 break;
1061 case SingleWithAttrib::AT_ERRONEOUS:
1062 {
1063 if (temp_attrib->has_override()) {
1064 temp_attrib->error("Override cannot be used with erroneous");
1065 }
1066 }
1067 break;
1068 default:
1069 break;
1070 }
1071 }
1072
1073 for(size_t i = 0; i < m_w_attrib->get_nof_elements();)
1074 {
1075 const SingleWithAttrib* const temp_attrib = m_w_attrib->get_element(i);
1076 switch(temp_attrib->get_attribKeyword())
1077 {
1078 case SingleWithAttrib::AT_VARIANT:
1079 {
1080 if(has_override_variant)
1081 {
1082 temp_attrib->warning("Only the first override"
1083 " variant of the with statement will have effect");
1084 m_w_attrib->delete_element(i);
1085 }else{
1086 if(temp_attrib->has_override())
1087 has_override_variant = true;
1088 i++;
1089 }
1090 }
1091 break;
1092 case SingleWithAttrib::AT_DISPLAY:
1093 {
1094 if(has_override_display)
1095 {
1096 temp_attrib->warning("Only the first override"
1097 " display of the with statement will have effect");
1098 m_w_attrib->delete_element(i);
1099 }else{
1100 if(temp_attrib->has_override())
1101 has_override_display = true;
1102 i++;
1103 }
1104 }
1105 break;
1106 case SingleWithAttrib::AT_EXTENSION:
1107 {
1108 if(has_override_extension)
1109 {
1110 temp_attrib->warning("Only the first override"
1111 " extension of the with statement will have effect");
1112 m_w_attrib->delete_element(i);
1113 }else{
1114 if(temp_attrib->has_override())
1115 has_override_extension = true;
1116 i++;
1117 }
1118 }
1119 break;
1120 case SingleWithAttrib::AT_OPTIONAL:
1121 {
1122 if ("implicit omit" != temp_attrib->get_attribSpec().get_spec() &&
1123 "explicit omit" != temp_attrib->get_attribSpec().get_spec()) {
1124 temp_attrib->error("Value of optional attribute can only be "
1125 "either 'explicit omit' or 'implicit omit' not '%s'",
1126 temp_attrib->get_attribSpec().get_spec().c_str());
1127 }
1128 if(has_override_optional)
1129 {
1130 temp_attrib->warning("Only the first override"
1131 " optional of the with statement will have effect");
1132 m_w_attrib->delete_element(i);
1133 }else{
1134 if(temp_attrib->has_override())
1135 has_override_optional = true;
1136 i++;
1137 }
1138 }
1139 break;
1140 default:
1141 i++;
1142 break;
1143 } // switch
1144 } // next i
1145 }
1146
1147 void WithAttribPath::set_with_attr(MultiWithAttrib* p_m_w_attr)
1148 {
1149 if(m_w_attrib) FATAL_ERROR("WithAttribPath::set_with_attr()");
1150 m_w_attrib = p_m_w_attr;
1151 attributes_checked = false;
1152 }
1153
1154 /**
1155 * Finds the real attributes checking the inherited ones with its own.
1156 * Only qualifierless attributes are handled.
1157 * The stepped_over_encode is needed because it can happen that we
1158 * override an encode and later (inner) find variants without encode.
1159 * As those were the overridden encode's variants we can not add them to
1160 * our list.
1161 */
1162 void WithAttribPath::qualifierless_attrib_finder(
1163 vector<SingleWithAttrib>& p_result,
1164 bool& stepped_over_encode)
1165 {
1166 if(cached)
1167 {
1168 for(size_t i = 0; i < cache.size(); i++)
1169 {
1170 p_result.add(cache[i]);
1171 }
1172 stepped_over_encode = s_o_encode;
1173 return;
1174 }
1175
1176 if(parent)
1177 parent->qualifierless_attrib_finder(p_result,stepped_over_encode);
1178 else
1179 stepped_over_encode = false;
1180
1181 if(m_w_attrib)
1182 {
1183 // These two refer only to the attributes of this type
1184 int self_encode_index = -1; // the index of the "encode" attribute
1185 bool self_has_variant = false; // flag for the presence of a "variant"
1186 // The following refer to all the attributes, including those collected
1187 // from the parent and all the ancestors.
1188 bool par_has_override_encode = false;
1189 bool par_has_encode = false;
1190 // True if there is an encode attribute in the local attribute list,
1191 // it differs from the parents encode
1192 // and the parent does not overwrite it.
1193 bool new_local_encode_context = false;
1194 bool par_has_override_variant = false;
1195 bool par_has_override_display = false;
1196 bool par_has_override_extension = false;
1197 bool par_has_override_optional = false;
1198
1199 //checking the owned attributes
1200 const SingleWithAttrib* act_single;
1201 const Qualifiers* act_qualifiers;
1202 const size_t m_w_attrib_nof_elements = m_w_attrib->get_nof_elements();
1203 for(size_t i = 0; i < m_w_attrib_nof_elements;i++)
1204 {
1205 act_single = m_w_attrib->get_element(i);
1206 act_qualifiers = act_single->get_attribQualifiers();
1207
1208 //global attribute
1209 if(!act_qualifiers || act_qualifiers->get_nof_qualifiers() == 0)
1210 {
1211 switch(act_single->get_attribKeyword())
1212 {
1213 case SingleWithAttrib::AT_ENCODE:
1214 self_encode_index = i;
1215 break;
1216
1217 case SingleWithAttrib::AT_VARIANT: {
1218 // Ignore JSON variants, these should not produce warnings
1219 const string& spec = act_single->get_attribSpec().get_spec();
1220 size_t i2 = 0;
1221 while (i2 < spec.size()) {
1222 if (spec[i2] != ' ' && spec[i2] != '\t') {
1223 break;
1224 }
1225 ++i2;
1226 }
1227 if (i2 == spec.size() || spec.find("JSON", i2) != i2) {
1228 self_has_variant = true;
1229 }
1230 break; }
1231
1232 case SingleWithAttrib::AT_DISPLAY:
1233 case SingleWithAttrib::AT_EXTENSION:
1234 case SingleWithAttrib::AT_OPTIONAL:
1235 case SingleWithAttrib::AT_ERRONEOUS:
1236 case SingleWithAttrib::AT_INVALID:
1237 break;
1238
1239 default:
1240 FATAL_ERROR("WithAttribPath::attrib_finder()");
1241 }
1242 } // if global
1243 } // next i
1244
1245 // Here p_result contains attributes collected from outer scopes only.
1246 size_t p_result_size = p_result.size();
1247 // gather information on the attributes collected from the parents
1248 for(size_t i = 0; i < p_result_size; i++)
1249 {
1250 act_single = p_result[i];
1251
1252 switch(act_single->get_attribKeyword())
1253 {
1254 case SingleWithAttrib::AT_ENCODE:
1255 par_has_encode = true;
1256 par_has_override_encode |= act_single->has_override();
1257 if(self_encode_index != -1)
1258 {
1259 // We also have an encode. See if they differ.
1260 new_local_encode_context = (act_single->get_attribSpec().get_spec()
1261 != m_w_attrib->get_element(self_encode_index)->
1262 get_attribSpec().get_spec());
1263 }
1264 break;
1265
1266 case SingleWithAttrib::AT_VARIANT:
1267 par_has_override_variant |= act_single->has_override();
1268 break;
1269 case SingleWithAttrib::AT_DISPLAY:
1270 par_has_override_display |= act_single->has_override();
1271 break;
1272 case SingleWithAttrib::AT_EXTENSION:
1273 par_has_override_extension |= act_single->has_override();
1274 break;
1275 case SingleWithAttrib::AT_OPTIONAL:
1276 par_has_override_optional |= act_single->has_override();
1277 break;
1278 case SingleWithAttrib::AT_ERRONEOUS:
1279 case SingleWithAttrib::AT_INVALID:
1280 // ignore
1281 break;
1282 default:
1283 FATAL_ERROR("WithAttribPath::attrib_finder()");
1284 }
1285 }
1286
1287 if(!par_has_encode && self_encode_index == -1 && self_has_variant)
1288 {
1289 // There is no encode, but there is at least one variant.
1290 // Find them and issue warnings.
1291 for(size_t i = 0; i < m_w_attrib_nof_elements; i++)
1292 {
1293 act_single = m_w_attrib->get_element(i);
1294 if(act_single->get_attribKeyword() == SingleWithAttrib::AT_VARIANT)
1295 act_single->warning("This variant does not belong to an encode");
1296 }
1297 }
1298
1299 // If we have an encode (self_encode_index != -1) and it differs from
1300 // the outer encode (new_local_encode_context) and the outer wasn't
1301 // an "override encode" (!par_has_override_encode),
1302 // remove the outer encode and all the variants that belong to it.
1303 for(size_t i = p_result.size(); i > 0; i--)
1304 {
1305 switch(p_result[i-1]->get_attribKeyword())
1306 {
1307 case SingleWithAttrib::AT_ENCODE:
1308 case SingleWithAttrib::AT_VARIANT:
1309 if (self_encode_index != -1 && new_local_encode_context
1310 && !par_has_override_encode)
1311 p_result.replace(i-1,1,NULL);
1312 break;
1313 case SingleWithAttrib::AT_DISPLAY:
1314 case SingleWithAttrib::AT_EXTENSION:
1315 case SingleWithAttrib::AT_OPTIONAL:
1316 case SingleWithAttrib::AT_ERRONEOUS:
1317 case SingleWithAttrib::AT_INVALID:
1318 break;
1319 }
1320 }
1321
1322 //adding the right ones from the local attributes
1323 for(size_t i = 0; i < m_w_attrib_nof_elements; i++)
1324 {
1325 act_single = m_w_attrib->get_element(i);
1326 act_qualifiers = act_single->get_attribQualifiers();
1327 if(!act_qualifiers || act_qualifiers->get_nof_qualifiers() == 0)
1328 {
1329 switch(act_single->get_attribKeyword())
1330 {
1331 case SingleWithAttrib::AT_ENCODE:
1332 if((par_has_encode && !par_has_override_encode
1333 && new_local_encode_context)
1334 || (!par_has_encode))
1335 {
1336 p_result.add_front(m_w_attrib->get_element_for_modification(i));
1337 stepped_over_encode = false;
1338 }else if(new_local_encode_context){
1339 //par_has_encode && par_has_override_encode
1340 stepped_over_encode = true;
1341 }else{
1342 stepped_over_encode = false;
1343 }
1344 break;
1345 case SingleWithAttrib::AT_VARIANT:
1346 if((!par_has_encode && !par_has_override_variant)
1347 || (par_has_encode && self_encode_index == -1
1348 && !stepped_over_encode && !par_has_override_variant)
1349 || (par_has_encode && self_encode_index != -1
1350 && !par_has_override_encode && !par_has_override_variant)
1351 || (!par_has_encode && self_encode_index != -1))
1352 p_result.add(m_w_attrib->get_element_for_modification(i));
1353 break;
1354 case SingleWithAttrib::AT_DISPLAY:
1355 if(!par_has_override_display)
1356 p_result.add(m_w_attrib->get_element_for_modification(i));
1357 break;
1358 case SingleWithAttrib::AT_EXTENSION:
1359 if(!par_has_override_extension)
1360 p_result.add(m_w_attrib->get_element_for_modification(i));
1361 break;
1362 case SingleWithAttrib::AT_OPTIONAL:
1363 if (!par_has_override_optional)
1364 p_result.add(m_w_attrib->get_element_for_modification(i));
1365 break;
1366 case SingleWithAttrib::AT_ERRONEOUS:
1367 case SingleWithAttrib::AT_INVALID:
1368 // ignore
1369 break;
1370 }
1371 }
1372 }
1373 }
1374 }
1375
1376 /*
1377 * Be very cautious this function gives back only the qualifierless attributes.
1378 * Because of types giving back all the attribs, so that they are already
1379 * in their final encode context would mean that attributes coming from
1380 * the parent path would need to be cloned and qualified as many times
1381 * as many components the type has.
1382 */
1383 const vector<SingleWithAttrib>& WithAttribPath::get_real_attrib()
1384 {
1385 if (!cached) {
1386 qualifierless_attrib_finder(cache,s_o_encode);
1387 cached = true;
1388 }
1389 return cache;
1390 }
1391
1392 bool WithAttribPath::has_attribs()
1393 {
1394 if (had_global_variants) return true;
1395 else if (get_real_attrib().size() > 0) return true;
1396 else if (m_w_attrib) {
1397 for (size_t i = 0; i < m_w_attrib->get_nof_elements(); i++) {
1398 const Qualifiers *qualifiers =
1399 m_w_attrib->get_element(i)->get_attribQualifiers();
1400 if (qualifiers && qualifiers->get_nof_qualifiers() > 0) return true;
1401 }
1402 }
1403 return false;
1404 }
1405
1406 }
This page took 0.060446 seconds and 4 git commands to generate.