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