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