Sync with 5.3.0
[deliverable/titan.core.git] / compiler2 / Setting.cc
CommitLineData
970ed795
EL
1///////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2000-2014 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#include "../common/dbgnew.hh"
9#include "Setting.hh"
10#include <stdio.h>
11#include <stdarg.h>
12#include "map.hh"
13#include "Identifier.hh"
14#include "CompilerError.hh"
15#include "AST.hh"
16#include "asn1/AST_asn1.hh"
17#include "ttcn3/AST_ttcn3.hh"
18#include "Value.hh"
19#include "Int.hh"
20#include "main.hh"
a38c6d4c 21#include "ttcn3/profiler.h"
970ed795
EL
22
23namespace Common {
24
25 // =================================
26 // ===== Location
27 // =================================
28
29 map<string,void> *Location::source_file_names = NULL;
30 bool Location::transparency = false;
31
32 const char* Location::add_source_file_name(const string& file_name)
33 {
34 if (source_file_names==NULL)
35 source_file_names = new map<string,void>();
36 if (!source_file_names->has_key(file_name))
37 source_file_names->add(file_name, NULL);
38 return source_file_names->get_key(file_name).c_str();
39 }
40
41 void Location::delete_source_file_names()
42 {
43 if (source_file_names!=NULL)
44 {
45 source_file_names->clear();
46 delete source_file_names;
47 source_file_names = NULL;
48 }
49 }
50
51 Location::Location()
52 {
53 filename = NULL;
54 yyloc.first_line = 0;
55 yyloc.last_line = 0;
56 yyloc.first_column = 0;
57 yyloc.last_column = 0;
58 }
59
60 void Location::set_location(const char *p_filename, int p_lineno)
61 {
62 filename = p_filename;
63 yyloc.first_line = p_lineno;
64 yyloc.first_column = 0;
65 yyloc.last_line = p_lineno;
66 yyloc.last_column = 0;
67 }
68
69 void Location::set_location(const char *p_filename, const YYLTYPE& p_yyloc)
70 {
71 filename = p_filename;
72 yyloc = p_yyloc;
73 }
74
75 void Location::set_location(const char *p_filename, const YYLTYPE& p_firstloc,
76 const YYLTYPE& p_lastloc)
77 {
78 filename = p_filename;
79 yyloc.first_line = p_firstloc.first_line;
80 yyloc.first_column = p_firstloc.first_column;
81 yyloc.last_line = p_lastloc.last_line;
82 yyloc.last_column = p_lastloc.last_column;
83 }
84
85 void Location::set_location(const char *p_filename, int p_first_line,
86 int p_first_column, int p_last_line, int p_last_column)
87 {
88 filename = p_filename;
89 yyloc.first_line = p_first_line;
90 yyloc.first_column = p_first_column;
91 yyloc.last_line = p_last_line;
92 yyloc.last_column = p_last_column;
93 }
94
95 void Location::join_location(const Location& p)
96 {
97 // do nothing if this and p refer to different files
98 if (filename) {
99 if (!p.filename) return;
100 else if (strcmp(filename, p.filename)) return;
101 } else if (p.filename) return;
102 if (yyloc.last_line < p.yyloc.first_line ||
103 (yyloc.last_line == p.yyloc.first_line &&
104 yyloc.last_column <= p.yyloc.first_column)) {
105 // p is after this
106 yyloc.last_line = p.yyloc.last_line;
107 yyloc.last_column = p.yyloc.last_column;
108 } else if (yyloc.first_line > p.yyloc.last_line ||
109 (yyloc.first_line == p.yyloc.last_line &&
110 yyloc.first_column >= p.yyloc.last_column)) {
111 // p is before this
112 yyloc.first_line = p.yyloc.first_line;
113 yyloc.first_column = p.yyloc.first_column;
114 }
115 }
116
117 void Location::print_line_info(FILE *fp) const
118 {
119 if (yyloc.first_line > 0) {
120 // at least partial line/column information is available
121 if (output_only_linenum || (yyloc.first_line == yyloc.last_line &&
122 yyloc.first_column <= 0 && yyloc.last_column <= 0)) {
123 // print only the first line
124 fprintf(fp, "%d", yyloc.first_line);
125 } else if (yyloc.last_line > yyloc.first_line) {
126 // multi-line area
127 if (yyloc.first_column >= 0 && yyloc.last_column >= 0) {
128 // all line/column fields are valid
129 if (gcc_compat) {
130 fprintf(fp, "%d:%d", yyloc.first_line, yyloc.first_column + 1);
131 }
132 else {
133 fprintf(fp, "%d.%d-%d.%d", yyloc.first_line,
134 yyloc.first_column + 1, yyloc.last_line, yyloc.last_column);
135 }
136 } else {
137 // only the line numbers are valid
138 if (gcc_compat) {
139 fprintf(fp, "%d", yyloc.first_line);
140 }
141 else {
142 fprintf(fp, "%d-%d", yyloc.first_line, yyloc.last_line);
143 }
144 }
145 } else if (yyloc.first_line == yyloc.last_line) {
146 // single line area
147 if (yyloc.first_column >= 0 && yyloc.last_column > yyloc.first_column) {
148 if (gcc_compat) {
149 fprintf(fp, "%d:%d", yyloc.first_line, yyloc.first_column + 1);
150 }
151 else {
152 if (yyloc.last_column > yyloc.first_column + 1) {
153 // more characters are covered
154 fprintf(fp, "%d.%d-%d", yyloc.first_line, yyloc.first_column + 1,
155 yyloc.last_column);
156 } else {
157 // only a single character is covered
158 fprintf(fp, "%d.%d", yyloc.first_line, yyloc.first_column + 1);
159 }
160 }
161 } else {
162 // the column information is invalid, print the line number only
163 fprintf(fp, "%d", yyloc.first_line);
164 }
165 } else {
166 // the last line is smaller than the first line
167 // print only the first line
168 fprintf(fp, "%d", yyloc.first_line);
169 }
170 } else {
171 // line information is not available
172 fputs("<unknown>", fp);
173 }
174 }
175
176 void Location::print_location(FILE *fp) const
177 {
178 if (filename) {
179 fputs(filename, fp);
180 if (yyloc.first_line > 0) {
181 // print the line information only if it is available
182 putc(':', fp);
183 print_line_info(fp);
184 }
185 fputs(": ", fp);
186 }
187 // do not print anything if the file name is unknown
188 }
189
190 void Location::error(const char *fmt, ...) const
191 {
192 va_list args;
193 va_start(args, fmt);
194 Error_Context::report_error(this, fmt, args);
195 va_end(args);
196 }
197
198 void Location::warning(const char *fmt, ...) const
199 {
200 va_list args;
201 va_start(args, fmt);
202 Error_Context::report_warning(this, fmt, args);
203 va_end(args);
204 }
205
206 void Location::note(const char *fmt, ...) const
207 {
208 va_list args;
209 va_start(args, fmt);
210 Error_Context::report_note(this, fmt, args);
211 va_end(args);
212 }
213
214 char *Location::create_location_object(char *str, const char *entitytype,
215 const char *entityname) const
216 {
217 if (!filename || yyloc.first_line <= 0)
218 FATAL_ERROR("Location::create_location_object()");
219 if (include_location_info && !transparency) {
220 bool tcov_enabled = tcov_file_name && in_tcov_files(get_filename());
221 str = mputstr(str,
222 !tcov_enabled ? "TTCN_Location current_location(\""
223 : "TTCN_Location_Statistics current_location(\"");
224 str = Code::translate_string(str, filename);
225 str = mputprintf(str,
226 !tcov_enabled ? "\", %d, TTCN_Location::LOCATION_%s, \"%s\");\n"
227 : "\", %d, TTCN_Location_Statistics::LOCATION_%s, \"%s\");\n", yyloc.first_line, entitytype, entityname);
228 if (tcov_enabled) {
229 effective_module_lines =
230 mputprintf(effective_module_lines, "%s%d",
231 (effective_module_lines ? ", " : ""), yyloc.first_line);
232 effective_module_functions =
233 mputprintf(effective_module_functions, "%s\"%s\"",
234 (effective_module_functions ? ", " : ""), entityname);
235 }
a38c6d4c 236 if (is_file_profiled(filename)) {
237 // .ttcnpp -> .ttcn
238 size_t file_name_len = strlen(filename);
239 if ('p' == filename[file_name_len - 1] && 'p' == filename[file_name_len - 2]) {
240 file_name_len -= 2;
241 }
242 char* file_name2 = mcopystrn(filename, file_name_len);
af710487 243 str = mputprintf(str,
244 "TTCN3_Stack_Depth stack_depth;\n"
a38c6d4c 245 "ttcn3_prof.enter_function(\"%s\", %d);\n", file_name2, yyloc.first_line);
246 insert_profiler_code_line(file_name2,
247 (0 == strcmp(entitytype, "CONTROLPART") ? "control" : entityname),
248 yyloc.first_line);
249 Free(file_name2);
af710487 250 }
970ed795
EL
251 }
252 return str;
253 }
254
255 char *Location::update_location_object(char *str) const
256 {
257 if (filename && yyloc.first_line > 0) {
258 if (include_location_info && !transparency) {
259 str = mputprintf(str, "current_location.update_lineno(%d);\n",
260 yyloc.first_line);
a38c6d4c 261 const char* file_name = get_filename();
262 if (is_file_profiled(file_name)) {
263 // .ttcnpp -> .ttcn
264 size_t file_name_len = strlen(file_name);
265 if ('p' == file_name[file_name_len - 1] && 'p' == file_name[file_name_len - 2]) {
266 file_name_len -= 2;
267 }
268 char* file_name2 = mcopystrn(file_name, file_name_len);
af710487 269 str = mputprintf(str, "ttcn3_prof.execute_line(\"%s\", %d);\n",
a38c6d4c 270 file_name2, yyloc.first_line);
271 insert_profiler_code_line(file_name2, NULL, yyloc.first_line);
272 Free(file_name2);
af710487 273 }
a38c6d4c 274 if (tcov_file_name && in_tcov_files(file_name)) {
970ed795
EL
275 effective_module_lines =
276 mputprintf(effective_module_lines, "%s%d",
277 (effective_module_lines ? ", " : ""), yyloc.first_line);
278 }
279 }
280
281 if (include_line_info)
282 str = mputprintf(str, "#line %d \"%s\"\n", yyloc.first_line, filename);
283 else str = mputprintf(str, "/* %s, line %d */\n", filename,
284 yyloc.first_line);
285 }
286 return str;
287 }
288
289 // =================================
290 // ===== Node
291 // =================================
292
293 int Node::counter=0;
294#ifdef MEMORY_DEBUG
295 static Node *list_head = 0, *list_tail = 0;
296#endif
297
298 Node::Node()
299 {
300#ifdef MEMORY_DEBUG
301 prev_node = list_tail;
302 next_node = 0;
303 if (list_tail) list_tail->next_node = this;
304 else list_head = this;
305 list_tail = this;
306#endif
307 counter++;
308 }
309
310 Node::Node(const Node&)
311 : fullname()
312 {
313#ifdef MEMORY_DEBUG
314 prev_node = list_tail;
315 next_node = 0;
316 if (list_tail) list_tail->next_node = this;
317 else list_head = this;
318 list_tail = this;
319#endif
320 counter++;
321 }
322
323 Node::~Node()
324 {
325 counter--;
326#ifdef MEMORY_DEBUG
327 if (prev_node) prev_node->next_node = next_node;
328 else list_head = next_node;
329 if (next_node) next_node->prev_node = prev_node;
330 else list_tail = prev_node;
331#endif
332 }
333
334
335 void Node::chk_counter()
336 {
337 DEBUG(1, "Node::counter is %d", counter);
338 if(counter)
339 WARNING("%d nodes were not deleted."
340 " Please send a bug report including"
341 " the current input file(s).", counter);
342#ifdef MEMORY_DEBUG
343 for (Node *iter = list_head; iter; iter = iter->next_node) {
344 fprintf(stderr, "Undeleted node: `%s' (address %p).\n",
345 iter->get_fullname().c_str(), static_cast<void*>(iter));
346 }
347 list_head = 0;
348 list_tail = 0;
349#endif
350 }
351
352 void Node::set_fullname(const string& p_fullname)
353 {
354 fullname = p_fullname;
355 }
356
357 void Node::set_my_scope(Scope *)
358 {
359 }
360
361 void Node::dump(unsigned level) const
362 {
363 DEBUG(level, "Node: %s", fullname.c_str());
364 }
365
366 // =================================
367 // ===== Setting
368 // =================================
369
370 Setting::Setting(settingtype_t p_st)
371 : Node(), Location(),
372 st(p_st), my_scope(0), checked(false), recurs_checked(false)
373 {
374 }
375
376 void Setting::set_my_scope(Scope *p_scope)
377 {
378 my_scope = p_scope;
379 }
380
381 bool Setting::is_asn1() const
382 {
383 if (!my_scope) FATAL_ERROR("Setting::is_asn1()");
384 return my_scope->get_scope_mod()->get_moduletype() == Module::MOD_ASN;
385 }
386
387 string Setting::get_temporary_id() const
388 {
389 if (!my_scope) FATAL_ERROR("Setting::get_temporary_id()");
390 return my_scope->get_scope_mod_gen()->get_temporary_id();
391 }
392
393 void Setting::set_genname(const string& p_genname)
394 {
395 if (p_genname.empty()) FATAL_ERROR("Setting::set_genname()");
396 genname = p_genname;
397 }
398
399 void Setting::set_genname(const string& p_prefix, const string& p_suffix)
400 {
401 if (p_prefix.empty() || p_suffix.empty())
402 FATAL_ERROR("Setting::set_genname()");
403 genname = p_prefix;
404 // a single underscore character is needed as separator if neither p_prefix
405 // ends nor p_suffix begins with a single underscore character
406 size_t p_prefix_len = p_prefix.size();
407 if ((p_prefix[p_prefix_len - 1] != '_' ||
408 (p_prefix_len >= 2 && p_prefix[p_prefix_len - 2] == '_')) &&
409 (p_suffix[0] != '_' ||
410 (p_suffix.size() >= 2 && p_suffix[1] == '_'))) genname += '_';
411 genname += p_suffix;
412 }
413
414 const string& Setting::get_genname_own() const
415 {
416 if (genname.empty())
417 FATAL_ERROR("Setting::get_genname_own(): genname is not set in %s", \
418 get_fullname().c_str());
419 return genname;
420 }
421
422 string Setting::get_genname_own(Scope *p_scope) const
423 {
424 if (!p_scope || !my_scope) FATAL_ERROR("Setting::get_genname_own");
425 string ret_val;
426 Module *my_mod = my_scope->get_scope_mod_gen();
427 if (my_mod != p_scope->get_scope_mod_gen() &&
428 !Asn::Assignments::is_spec_asss(my_mod)) {
429 // when the definition is referred from another module
430 // the reference shall be qualified with the namespace of my module
431 ret_val = my_mod->get_modid().get_name();
432 ret_val += "::";
433 }
434 ret_val += get_genname_own();
435 return ret_val;
436 }
437
438 string Setting::create_stringRepr()
439 {
440 return string("<string representation not implemented for " +
441 get_fullname() + ">");
442 }
443
444 // =================================
445 // ===== Setting_Error
446 // =================================
447
448 Setting_Error* Setting_Error::clone() const
449 {
450 FATAL_ERROR("Setting_Error::clone");
451 }
452
453 // =================================
454 // ===== Governor
455 // =================================
456
457 // =================================
458 // ===== Governed
459 // =================================
460
461 // =================================
462 // ===== GovernedSimple
463 // =================================
464
465 string GovernedSimple::get_lhs_name() const
466 {
467 string ret_val;
468 if (genname_prefix) ret_val += genname_prefix;
469 ret_val += get_genname_own();
470 return ret_val;
471 }
472
473 bool GovernedSimple::needs_init_precede(const GovernedSimple *refd) const
474 {
475 if (refd->code_generated) return false;
476 if (code_section == CS_UNKNOWN || refd->code_section == CS_UNKNOWN)
477 FATAL_ERROR("GovernedSimple::needs_init_precede()");
478 if (code_section != refd->code_section) return false;
479 if (get_my_scope()->get_scope_mod_gen() !=
480 refd->get_my_scope()->get_scope_mod_gen()) return false;
481 else return true;
482 }
483
484 bool GovernedSimple::is_toplevel() const
485 {
486 const string& name = get_genname_own();
487 const char *name_str = name.c_str();
488 size_t name_len = name.size();
489 for (size_t i = 0; i < name_len; i++) {
490 char c = name_str[i];
491 if ((c < 'A' || c > 'Z') && (c < 'a' ||c > 'z') &&
492 (c < '0' || c > '9') && c != '_') return false;
493 }
494 return true;
495 }
496
497 // =================================
498 // ===== GovdSet
499 // =================================
500
501 // =================================
502 // ===== Scope
503 // =================================
504
505 string Scope::get_scope_name() const
506 {
507 string s;
508 if (parent_scope) s = parent_scope->get_scope_name();
509 if (!scope_name.empty()) {
510 if (s.empty()) s = scope_name;
511 else {
512 s += '.';
513 s += scope_name;
514 }
515 }
516 return s;
517 }
518
519 string Scope::get_scopeMacro_name() const
520 {
521 if (!scopeMacro_name.empty()) return scopeMacro_name;
522 if (parent_scope) return parent_scope->get_scopeMacro_name();
523 return scopeMacro_name;
524 }
525
526 Ttcn::StatementBlock *Scope::get_statementblock_scope()
527 {
528 if (parent_scope) return parent_scope->get_statementblock_scope();
529 else return 0;
530 }
531
532 Ttcn::RunsOnScope *Scope::get_scope_runs_on()
533 {
534 if (parent_scope) return parent_scope->get_scope_runs_on();
535 else return 0;
536 }
537
538 Assignments *Scope::get_scope_asss()
539 {
540 if (parent_scope) return parent_scope->get_scope_asss();
541 else
542 FATAL_ERROR("The assignments scope is not visible from this scope: " \
543 "`%s'", get_scope_name().c_str());
544 return 0;
545 }
546
547 Module* Scope::get_scope_mod()
548 {
549 if(parent_scope) return parent_scope->get_scope_mod();
550 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
551 get_scope_name().c_str());
552 return 0;
553 }
554
555 Module* Scope::get_scope_mod_gen()
556 {
557 if(parent_scope_gen) return parent_scope_gen->get_scope_mod_gen();
558 else if(parent_scope) return parent_scope->get_scope_mod_gen();
559 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
560 get_scope_name().c_str());
561 return 0;
562 }
563
564 bool Scope::has_ass_withId(const Identifier& p_id)
565 {
566 if (parent_scope) return parent_scope->has_ass_withId(p_id);
567 else return false;
568 }
569
570 bool Scope::is_valid_moduleid(const Identifier& p_id)
571 {
572 if (parent_scope) return parent_scope->is_valid_moduleid(p_id);
573 else return false;
574 }
575
af710487 576 Type *Scope::get_mtc_system_comptype(bool is_system)
970ed795 577 {
af710487 578 if (parent_scope) return parent_scope->get_mtc_system_comptype(is_system);
970ed795
EL
579 else return 0;
580 }
581
582 void Scope::chk_runs_on_clause(Assignment *p_ass, const Location& p_loc,
583 const char *p_what)
584 {
585 // component type of the referred definition
586 Type *refd_comptype = p_ass->get_RunsOnType();
587 // definitions without 'runs on' can be called from anywhere
588 if (!refd_comptype) return;
589 Ttcn::RunsOnScope *t_ros = get_scope_runs_on();
590 if (t_ros) {
591 Type *local_comptype = t_ros->get_component_type();
592 if (!refd_comptype->is_compatible(local_comptype, NULL)) {
593 // the 'runs on' clause of the referred definition is not compatible
594 // with that of the current scope (i.e. the referring definition)
595 p_loc.error("Runs on clause mismatch: A definition that runs on "
596 "component type `%s' cannot %s %s, which runs on `%s'",
597 local_comptype->get_typename().c_str(), p_what,
598 p_ass->get_description().c_str(),
599 refd_comptype->get_typename().c_str());
600 }
601 } else {
602 // the current scope unit (i.e. the referring definition) does not have
603 // 'runs on' clause
604 p_loc.error("A definition without `runs on' clause cannot %s %s, which "
605 "runs on component type `%s'", p_what, p_ass->get_description().c_str(),
606 refd_comptype->get_typename().c_str());
607 }
608 }
609
610 void Scope::chk_runs_on_clause(Type *p_fat, const Location& p_loc,
611 const char *p_what)
612 {
613 if (!p_fat) FATAL_ERROR("Scope::chk_runs_on_clause()");
614 Type *refd_comptype = p_fat->get_fat_runs_on_type();
615 // values of function/altstep types without 'runs on' clause
616 // or using 'runs on self' clause can be called from anywhere
617 if (!refd_comptype) return;
618 const char *typetype_name;
619 switch (p_fat->get_typetype()) {
620 case Type::T_FUNCTION:
621 typetype_name = "function";
622 break;
623 case Type::T_ALTSTEP:
624 typetype_name = "altstep";
625 break;
626 default:
627 FATAL_ERROR("Scope::chk_runs_on_clause()");
628 typetype_name = 0;
629 }
630 Ttcn::RunsOnScope *t_ros = get_scope_runs_on();
631 if (t_ros) {
632 Type *local_comptype = t_ros->get_component_type();
633 if (!refd_comptype->is_compatible(local_comptype, NULL)) {
634 // the 'runs on' clause of the function/altstep type is not compatible
635 // with that of the current scope (i.e. the referring definition)
636 p_loc.error("Runs on clause mismatch: A definition that runs on "
637 "component type `%s' cannot %s a value of %s type `%s', which runs "
638 "on `%s'", local_comptype->get_typename().c_str(), p_what,
639 typetype_name, p_fat->get_typename().c_str(),
640 refd_comptype->get_typename().c_str());
641 }
642 } else {
643 // the current scope unit (i.e. the referring definition) does not have
644 // 'runs on' clause
645 p_loc.error("A definition without `runs on' clause cannot %s a value of "
646 "%s type `%s', which runs on component type `%s'", p_what,
647 typetype_name, p_fat->get_typename().c_str(),
648 refd_comptype->get_typename().c_str());
649 }
650 }
651
652 // =================================
653 // ===== Reference
654 // =================================
655
656 size_t Reference::_Reference_counter=0;
657 Setting_Error *Reference::setting_error = 0;
658
659 Reference::~Reference()
660 {
661 if (_Reference_counter <= 0) FATAL_ERROR("Reference::~Reference()");
662 else if (--_Reference_counter == 0) {
663 delete setting_error;
664 setting_error = 0;
665 }
666 }
667
668 void Reference::set_my_scope(Scope *p_scope)
669 {
670 my_scope = p_scope;
671 }
672
673 bool Reference::get_is_erroneous()
674 {
675 return is_erroneous;
676 }
677
678 Setting* Reference::get_refd_setting_error()
679 {
680 is_erroneous=true;
681 if(!setting_error)
682 setting_error=new Setting_Error();
683 return setting_error;
684 }
685
686 bool Reference::refers_to_st(Setting::settingtype_t p_st,
687 ReferenceChain*)
688 {
689 Setting *t_setting=get_refd_setting();
690 if(t_setting) return t_setting->get_st()==p_st;
691 else return p_st==Setting::S_ERROR;
692 }
693
694 void Reference::set_code_section(GovernedSimple::code_section_t)
695 {
696 }
697
698 Ttcn::FieldOrArrayRefs *Reference::get_subrefs()
699 {
700 return 0;
701 }
702
703 Ttcn::ActualParList *Reference::get_parlist()
704 {
705 return 0;
706 }
707
708 void Reference::dump(unsigned level) const
709 {
710 DEBUG(level, "Reference: %s", const_cast<Reference*>(this)->get_dispname().c_str());
711 }
712
713 // =================================
714 // ===== Ref_simple
715 // =================================
716
717 string Ref_simple::get_dispname()
718 {
719 string ret_val;
720 const Identifier *t_modid = get_modid();
721 if (t_modid) {
722 ret_val += t_modid->get_dispname();
723 ret_val += '.';
724 }
725 ret_val += get_id()->get_dispname();
726 return ret_val;
727 }
728
729 Setting* Ref_simple::get_refd_setting()
730 {
731 if(get_is_erroneous()) return get_refd_setting_error();
732 Assignment *ass = get_refd_assignment();
733 if (ass) return ass->get_Setting();
734 else return get_refd_setting_error();
735 }
736
737 Assignment* Ref_simple::get_refd_assignment(bool)
738 {
739 if (!refd_ass) {
740 if (!my_scope) FATAL_ERROR("Common::Ref_simple::get_refd_assignment()");
741 refd_ass = my_scope->get_ass_bySRef(this);
742 }
743 return refd_ass;
744 }
745
746 bool Ref_simple::has_single_expr()
747 {
748 return true;
749 }
750
751 // =================================
752 // ===== ReferenceChain
753 // =================================
754
755 ReferenceChain::ReferenceChain(const Location *p_loc, const char *p_str)
756 : my_loc(p_loc), err_str(p_str), report_error(true)
757 {
758 if(!p_loc)
759 FATAL_ERROR("ReferenceChain::ReferenceChain()");
760 }
761
762 ReferenceChain::~ReferenceChain()
763 {
764 reset();
765 }
766
767 ReferenceChain *ReferenceChain::clone() const
768 {
769 FATAL_ERROR("ReferenceChain::clone()");
770 return 0;
771 }
772
773 bool ReferenceChain::exists(const string& s) const
774 {
775 for (size_t i = 0; i < refs.size(); i++)
776 if (*refs[i]==s) return true;
777 return false;
778 }
779
780 bool ReferenceChain::add(const string& s)
781 {
782 if (!exists(s)) {
783 refs.add(new string(s));
784 return true;
785 }
786
787 if (report_error) {
788 if (err_str) {
789 my_loc->error("%s: Circular reference: %s", err_str,
790 get_dispstr(s).c_str());
791 } else {
792 my_loc->error("Circular reference: %s", get_dispstr(s).c_str());
793 }
794 } else {
795 errors.add(get_dispstr(s));
796 }
797 return false;
798 }
799
800 void ReferenceChain::set_error_reporting(bool enable) {
801 report_error = enable;
802 }
803
804 size_t ReferenceChain::nof_errors() const {
805 return errors.size() - (err_stack.empty() ? 0 : *err_stack.top());
806 }
807
808 void ReferenceChain::report_errors()
809 {
810 if (!err_stack.empty() && *err_stack.top() > errors.size())
811 FATAL_ERROR("Common::ReferenceChain::report_errors()");
812
813 string err_msg;
814 if (err_str) {
815 err_msg += err_str;
816 err_msg += ": ";
817 }
818
819 for (size_t i = (err_stack.empty() ? 0 : *err_stack.top());
820 i < errors.size(); ++i) {
821 my_loc->error("%sCircular reference: %s",
822 err_msg.c_str(), errors[i].c_str());
823 }
824 }
825
826 void ReferenceChain::mark_error_state()
827 {
828 err_stack.push(new size_t(errors.size()));
829 }
830
831 void ReferenceChain::prev_error_state()
832 {
833 if (err_stack.empty())
834 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
835 if (errors.size() < *err_stack.top())
836 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
837
838 int state = static_cast<int>(*err_stack.top());
839 for (int i = static_cast<int>(errors.size()) - 1; i >= state; --i) {
840 errors.remove(i);
841 }
842 delete err_stack.pop();
843 }
844
845 void ReferenceChain::mark_state()
846 {
847 refstack.push(new size_t(refs.size()));
848 }
849
850 void ReferenceChain::prev_state()
851 {
852 if(refstack.empty())
853 FATAL_ERROR("Common::ReferenceChain::prev_state()");
854 size_t state=*refstack.top();
855 if(refs.size()<state)
856 FATAL_ERROR("Common::ReferenceChain::prev_state()");
857 for(size_t i=state; i<refs.size(); i++) delete refs[i];
858 refs.replace(state, refs.size()-state);
859 delete refstack.pop();
860 }
861
862 void ReferenceChain::reset()
863 {
864 for(size_t i=0; i<refs.size(); i++) delete refs[i];
865 refs.clear();
866 while(!refstack.empty()) delete refstack.pop();
867
868 errors.clear();
869 while(!err_stack.empty()) delete err_stack.pop();
870 }
871
872 string ReferenceChain::get_dispstr(const string& s) const
873 {
874 size_t i = 0;
875 // skip the elements before the first occurrence of s
876 for ( ; i < refs.size(); i++) if (*refs[i] == s) break;
877 string str;
878 for( ; i < refs.size(); i++) {
879 str += '`';
880 str += *refs[i];
881 str += "' -> ";
882 }
883 // putting s at the end
884 str += '`';
885 str += s;
886 str += '\'';
887 return str;
888 }
889
890} // namespace Common
This page took 0.056834 seconds and 5 git commands to generate.