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"
13 #include "Identifier.hh"
14 #include "CompilerError.hh"
16 #include "asn1/AST_asn1.hh"
17 #include "ttcn3/AST_ttcn3.hh"
24 // =================================
26 // =================================
28 map
<string
,void> *Location::source_file_names
= NULL
;
29 bool Location::transparency
= false;
31 const char* Location::add_source_file_name(const string
& file_name
)
33 if (source_file_names
==NULL
)
34 source_file_names
= new map
<string
,void>();
35 if (!source_file_names
->has_key(file_name
))
36 source_file_names
->add(file_name
, NULL
);
37 return source_file_names
->get_key(file_name
).c_str();
40 void Location::delete_source_file_names()
42 if (source_file_names
!=NULL
)
44 source_file_names
->clear();
45 delete source_file_names
;
46 source_file_names
= NULL
;
55 yyloc
.first_column
= 0;
56 yyloc
.last_column
= 0;
59 void Location::set_location(const char *p_filename
, int p_lineno
)
61 filename
= p_filename
;
62 yyloc
.first_line
= p_lineno
;
63 yyloc
.first_column
= 0;
64 yyloc
.last_line
= p_lineno
;
65 yyloc
.last_column
= 0;
68 void Location::set_location(const char *p_filename
, const YYLTYPE
& p_yyloc
)
70 filename
= p_filename
;
74 void Location::set_location(const char *p_filename
, const YYLTYPE
& p_firstloc
,
75 const YYLTYPE
& p_lastloc
)
77 filename
= p_filename
;
78 yyloc
.first_line
= p_firstloc
.first_line
;
79 yyloc
.first_column
= p_firstloc
.first_column
;
80 yyloc
.last_line
= p_lastloc
.last_line
;
81 yyloc
.last_column
= p_lastloc
.last_column
;
84 void Location::set_location(const char *p_filename
, int p_first_line
,
85 int p_first_column
, int p_last_line
, int p_last_column
)
87 filename
= p_filename
;
88 yyloc
.first_line
= p_first_line
;
89 yyloc
.first_column
= p_first_column
;
90 yyloc
.last_line
= p_last_line
;
91 yyloc
.last_column
= p_last_column
;
94 void Location::join_location(const Location
& p
)
96 // do nothing if this and p refer to different files
98 if (!p
.filename
) return;
99 else if (strcmp(filename
, p
.filename
)) return;
100 } else if (p
.filename
) return;
101 if (yyloc
.last_line
< p
.yyloc
.first_line
||
102 (yyloc
.last_line
== p
.yyloc
.first_line
&&
103 yyloc
.last_column
<= p
.yyloc
.first_column
)) {
105 yyloc
.last_line
= p
.yyloc
.last_line
;
106 yyloc
.last_column
= p
.yyloc
.last_column
;
107 } else if (yyloc
.first_line
> p
.yyloc
.last_line
||
108 (yyloc
.first_line
== p
.yyloc
.last_line
&&
109 yyloc
.first_column
>= p
.yyloc
.last_column
)) {
111 yyloc
.first_line
= p
.yyloc
.first_line
;
112 yyloc
.first_column
= p
.yyloc
.first_column
;
116 void Location::print_line_info(FILE *fp
) const
118 if (yyloc
.first_line
> 0) {
119 // at least partial line/column information is available
120 if (output_only_linenum
|| (yyloc
.first_line
== yyloc
.last_line
&&
121 yyloc
.first_column
<= 0 && yyloc
.last_column
<= 0)) {
122 // print only the first line
123 fprintf(fp
, "%d", yyloc
.first_line
);
124 } else if (yyloc
.last_line
> yyloc
.first_line
) {
126 if (yyloc
.first_column
>= 0 && yyloc
.last_column
>= 0) {
127 // all line/column fields are valid
129 fprintf(fp
, "%d:%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
132 fprintf(fp
, "%d.%d-%d.%d", yyloc
.first_line
,
133 yyloc
.first_column
+ 1, yyloc
.last_line
, yyloc
.last_column
);
136 // only the line numbers are valid
138 fprintf(fp
, "%d", yyloc
.first_line
);
141 fprintf(fp
, "%d-%d", yyloc
.first_line
, yyloc
.last_line
);
144 } else if (yyloc
.first_line
== yyloc
.last_line
) {
146 if (yyloc
.first_column
>= 0 && yyloc
.last_column
> yyloc
.first_column
) {
148 fprintf(fp
, "%d:%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
151 if (yyloc
.last_column
> yyloc
.first_column
+ 1) {
152 // more characters are covered
153 fprintf(fp
, "%d.%d-%d", yyloc
.first_line
, yyloc
.first_column
+ 1,
156 // only a single character is covered
157 fprintf(fp
, "%d.%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
161 // the column information is invalid, print the line number only
162 fprintf(fp
, "%d", yyloc
.first_line
);
165 // the last line is smaller than the first line
166 // print only the first line
167 fprintf(fp
, "%d", yyloc
.first_line
);
170 // line information is not available
171 fputs("<unknown>", fp
);
175 void Location::print_location(FILE *fp
) const
179 if (yyloc
.first_line
> 0) {
180 // print the line information only if it is available
186 // do not print anything if the file name is unknown
189 void Location::error(const char *fmt
, ...) const
193 Error_Context::report_error(this, fmt
, args
);
197 void Location::warning(const char *fmt
, ...) const
201 Error_Context::report_warning(this, fmt
, args
);
205 void Location::note(const char *fmt
, ...) const
209 Error_Context::report_note(this, fmt
, args
);
213 char *Location::create_location_object(char *str
, const char *entitytype
,
214 const char *entityname
) const
216 if (!filename
|| yyloc
.first_line
<= 0)
217 FATAL_ERROR("Location::create_location_object()");
218 if (include_location_info
&& !transparency
) {
219 bool tcov_enabled
= tcov_file_name
&& in_tcov_files(get_filename());
221 !tcov_enabled
? "TTCN_Location current_location(\""
222 : "TTCN_Location_Statistics current_location(\"");
223 str
= Code::translate_string(str
, filename
);
224 str
= mputprintf(str
,
225 !tcov_enabled
? "\", %d, TTCN_Location::LOCATION_%s, \"%s\");\n"
226 : "\", %d, TTCN_Location_Statistics::LOCATION_%s, \"%s\");\n", yyloc
.first_line
, entitytype
, entityname
);
228 effective_module_lines
=
229 mputprintf(effective_module_lines
, "%s%d",
230 (effective_module_lines
? ", " : ""), yyloc
.first_line
);
231 effective_module_functions
=
232 mputprintf(effective_module_functions
, "%s\"%s\"",
233 (effective_module_functions
? ", " : ""), entityname
);
239 char *Location::update_location_object(char *str
) const
241 if (filename
&& yyloc
.first_line
> 0) {
242 if (include_location_info
&& !transparency
) {
243 str
= mputprintf(str
, "current_location.update_lineno(%d);\n",
245 if (tcov_file_name
&& in_tcov_files(get_filename())) {
246 effective_module_lines
=
247 mputprintf(effective_module_lines
, "%s%d",
248 (effective_module_lines
? ", " : ""), yyloc
.first_line
);
252 if (include_line_info
)
253 str
= mputprintf(str
, "#line %d \"%s\"\n", yyloc
.first_line
, filename
);
254 else str
= mputprintf(str
, "/* %s, line %d */\n", filename
,
260 // =================================
262 // =================================
266 static Node
*list_head
= 0, *list_tail
= 0;
272 prev_node
= list_tail
;
274 if (list_tail
) list_tail
->next_node
= this;
275 else list_head
= this;
281 Node::Node(const Node
&)
285 prev_node
= list_tail
;
287 if (list_tail
) list_tail
->next_node
= this;
288 else list_head
= this;
298 if (prev_node
) prev_node
->next_node
= next_node
;
299 else list_head
= next_node
;
300 if (next_node
) next_node
->prev_node
= prev_node
;
301 else list_tail
= prev_node
;
306 void Node::chk_counter()
308 DEBUG(1, "Node::counter is %d", counter
);
310 WARNING("%d nodes were not deleted."
311 " Please send a bug report including"
312 " the current input file(s).", counter
);
314 for (Node
*iter
= list_head
; iter
; iter
= iter
->next_node
) {
315 fprintf(stderr
, "Undeleted node: `%s' (address %p).\n",
316 iter
->get_fullname().c_str(), static_cast<void*>(iter
));
323 void Node::set_fullname(const string
& p_fullname
)
325 fullname
= p_fullname
;
328 void Node::set_my_scope(Scope
*)
332 void Node::dump(unsigned level
) const
334 DEBUG(level
, "Node: %s", fullname
.c_str());
337 // =================================
339 // =================================
341 Setting::Setting(settingtype_t p_st
)
342 : Node(), Location(),
343 st(p_st
), my_scope(0), checked(false), recurs_checked(false)
347 void Setting::set_my_scope(Scope
*p_scope
)
352 bool Setting::is_asn1() const
354 if (!my_scope
) FATAL_ERROR("Setting::is_asn1()");
355 return my_scope
->get_scope_mod()->get_moduletype() == Module::MOD_ASN
;
358 string
Setting::get_temporary_id() const
360 if (!my_scope
) FATAL_ERROR("Setting::get_temporary_id()");
361 return my_scope
->get_scope_mod_gen()->get_temporary_id();
364 void Setting::set_genname(const string
& p_genname
)
366 if (p_genname
.empty()) FATAL_ERROR("Setting::set_genname()");
370 void Setting::set_genname(const string
& p_prefix
, const string
& p_suffix
)
372 if (p_prefix
.empty() || p_suffix
.empty())
373 FATAL_ERROR("Setting::set_genname()");
375 // a single underscore character is needed as separator if neither p_prefix
376 // ends nor p_suffix begins with a single underscore character
377 size_t p_prefix_len
= p_prefix
.size();
378 if ((p_prefix
[p_prefix_len
- 1] != '_' ||
379 (p_prefix_len
>= 2 && p_prefix
[p_prefix_len
- 2] == '_')) &&
380 (p_suffix
[0] != '_' ||
381 (p_suffix
.size() >= 2 && p_suffix
[1] == '_'))) genname
+= '_';
385 const string
& Setting::get_genname_own() const
388 FATAL_ERROR("Setting::get_genname_own(): genname is not set in %s", \
389 get_fullname().c_str());
393 string
Setting::get_genname_own(Scope
*p_scope
) const
395 if (!p_scope
|| !my_scope
) FATAL_ERROR("Setting::get_genname_own");
397 Module
*my_mod
= my_scope
->get_scope_mod_gen();
398 if (my_mod
!= p_scope
->get_scope_mod_gen() &&
399 !Asn::Assignments::is_spec_asss(my_mod
)) {
400 // when the definition is referred from another module
401 // the reference shall be qualified with the namespace of my module
402 ret_val
= my_mod
->get_modid().get_name();
405 ret_val
+= get_genname_own();
409 string
Setting::create_stringRepr()
411 return string("<string representation not implemented for " +
412 get_fullname() + ">");
415 // =================================
416 // ===== Setting_Error
417 // =================================
419 Setting_Error
* Setting_Error::clone() const
421 FATAL_ERROR("Setting_Error::clone");
424 // =================================
426 // =================================
428 // =================================
430 // =================================
432 // =================================
433 // ===== GovernedSimple
434 // =================================
436 string
GovernedSimple::get_lhs_name() const
439 if (genname_prefix
) ret_val
+= genname_prefix
;
440 ret_val
+= get_genname_own();
444 bool GovernedSimple::needs_init_precede(const GovernedSimple
*refd
) const
446 if (refd
->code_generated
) return false;
447 if (code_section
== CS_UNKNOWN
|| refd
->code_section
== CS_UNKNOWN
)
448 FATAL_ERROR("GovernedSimple::needs_init_precede()");
449 if (code_section
!= refd
->code_section
) return false;
450 if (get_my_scope()->get_scope_mod_gen() !=
451 refd
->get_my_scope()->get_scope_mod_gen()) return false;
455 bool GovernedSimple::is_toplevel() const
457 const string
& name
= get_genname_own();
458 const char *name_str
= name
.c_str();
459 size_t name_len
= name
.size();
460 for (size_t i
= 0; i
< name_len
; i
++) {
461 char c
= name_str
[i
];
462 if ((c
< 'A' || c
> 'Z') && (c
< 'a' ||c
> 'z') &&
463 (c
< '0' || c
> '9') && c
!= '_') return false;
468 // =================================
470 // =================================
472 // =================================
474 // =================================
476 string
Scope::get_scope_name() const
479 if (parent_scope
) s
= parent_scope
->get_scope_name();
480 if (!scope_name
.empty()) {
481 if (s
.empty()) s
= scope_name
;
490 string
Scope::get_scopeMacro_name() const
492 if (!scopeMacro_name
.empty()) return scopeMacro_name
;
493 if (parent_scope
) return parent_scope
->get_scopeMacro_name();
494 return scopeMacro_name
;
497 Ttcn::StatementBlock
*Scope::get_statementblock_scope()
499 if (parent_scope
) return parent_scope
->get_statementblock_scope();
503 Ttcn::RunsOnScope
*Scope::get_scope_runs_on()
505 if (parent_scope
) return parent_scope
->get_scope_runs_on();
509 Assignments
*Scope::get_scope_asss()
511 if (parent_scope
) return parent_scope
->get_scope_asss();
513 FATAL_ERROR("The assignments scope is not visible from this scope: " \
514 "`%s'", get_scope_name().c_str());
518 Module
* Scope::get_scope_mod()
520 if(parent_scope
) return parent_scope
->get_scope_mod();
521 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
522 get_scope_name().c_str());
526 Module
* Scope::get_scope_mod_gen()
528 if(parent_scope_gen
) return parent_scope_gen
->get_scope_mod_gen();
529 else if(parent_scope
) return parent_scope
->get_scope_mod_gen();
530 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
531 get_scope_name().c_str());
535 bool Scope::has_ass_withId(const Identifier
& p_id
)
537 if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
541 bool Scope::is_valid_moduleid(const Identifier
& p_id
)
543 if (parent_scope
) return parent_scope
->is_valid_moduleid(p_id
);
547 Type
*Scope::get_mtc_system_comptype(bool is_system
, bool is_connecting
)
549 if (parent_scope
) return parent_scope
->get_mtc_system_comptype(is_system
, is_connecting
);
553 void Scope::chk_runs_on_clause(Assignment
*p_ass
, const Location
& p_loc
,
556 // component type of the referred definition
557 Type
*refd_comptype
= p_ass
->get_RunsOnType();
558 // definitions without 'runs on' can be called from anywhere
559 if (!refd_comptype
) return;
560 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
562 Type
*local_comptype
= t_ros
->get_component_type();
563 if (!refd_comptype
->is_compatible(local_comptype
, NULL
)) {
564 // the 'runs on' clause of the referred definition is not compatible
565 // with that of the current scope (i.e. the referring definition)
566 p_loc
.error("Runs on clause mismatch: A definition that runs on "
567 "component type `%s' cannot %s %s, which runs on `%s'",
568 local_comptype
->get_typename().c_str(), p_what
,
569 p_ass
->get_description().c_str(),
570 refd_comptype
->get_typename().c_str());
573 // the current scope unit (i.e. the referring definition) does not have
575 p_loc
.error("A definition without `runs on' clause cannot %s %s, which "
576 "runs on component type `%s'", p_what
, p_ass
->get_description().c_str(),
577 refd_comptype
->get_typename().c_str());
581 void Scope::chk_runs_on_clause(Type
*p_fat
, const Location
& p_loc
,
584 if (!p_fat
) FATAL_ERROR("Scope::chk_runs_on_clause()");
585 Type
*refd_comptype
= p_fat
->get_fat_runs_on_type();
586 // values of function/altstep types without 'runs on' clause
587 // or using 'runs on self' clause can be called from anywhere
588 if (!refd_comptype
) return;
589 const char *typetype_name
;
590 switch (p_fat
->get_typetype()) {
591 case Type::T_FUNCTION
:
592 typetype_name
= "function";
594 case Type::T_ALTSTEP
:
595 typetype_name
= "altstep";
598 FATAL_ERROR("Scope::chk_runs_on_clause()");
601 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
603 Type
*local_comptype
= t_ros
->get_component_type();
604 if (!refd_comptype
->is_compatible(local_comptype
, NULL
)) {
605 // the 'runs on' clause of the function/altstep type is not compatible
606 // with that of the current scope (i.e. the referring definition)
607 p_loc
.error("Runs on clause mismatch: A definition that runs on "
608 "component type `%s' cannot %s a value of %s type `%s', which runs "
609 "on `%s'", local_comptype
->get_typename().c_str(), p_what
,
610 typetype_name
, p_fat
->get_typename().c_str(),
611 refd_comptype
->get_typename().c_str());
614 // the current scope unit (i.e. the referring definition) does not have
616 p_loc
.error("A definition without `runs on' clause cannot %s a value of "
617 "%s type `%s', which runs on component type `%s'", p_what
,
618 typetype_name
, p_fat
->get_typename().c_str(),
619 refd_comptype
->get_typename().c_str());
623 // =================================
625 // =================================
627 size_t Reference::_Reference_counter
=0;
628 Setting_Error
*Reference::setting_error
= 0;
630 Reference::~Reference()
632 if (_Reference_counter
<= 0) FATAL_ERROR("Reference::~Reference()");
633 else if (--_Reference_counter
== 0) {
634 delete setting_error
;
639 void Reference::set_my_scope(Scope
*p_scope
)
644 bool Reference::get_is_erroneous()
649 Setting
* Reference::get_refd_setting_error()
653 setting_error
=new Setting_Error();
654 return setting_error
;
657 bool Reference::refers_to_st(Setting::settingtype_t p_st
,
660 Setting
*t_setting
=get_refd_setting();
661 if(t_setting
) return t_setting
->get_st()==p_st
;
662 else return p_st
==Setting::S_ERROR
;
665 void Reference::set_code_section(GovernedSimple::code_section_t
)
669 Ttcn::FieldOrArrayRefs
*Reference::get_subrefs()
674 Ttcn::ActualParList
*Reference::get_parlist()
679 void Reference::dump(unsigned level
) const
681 DEBUG(level
, "Reference: %s", const_cast<Reference
*>(this)->get_dispname().c_str());
684 // =================================
686 // =================================
688 string
Ref_simple::get_dispname()
691 const Identifier
*t_modid
= get_modid();
693 ret_val
+= t_modid
->get_dispname();
696 ret_val
+= get_id()->get_dispname();
700 Setting
* Ref_simple::get_refd_setting()
702 if(get_is_erroneous()) return get_refd_setting_error();
703 Assignment
*ass
= get_refd_assignment();
704 if (ass
) return ass
->get_Setting();
705 else return get_refd_setting_error();
708 Assignment
* Ref_simple::get_refd_assignment(bool)
711 if (!my_scope
) FATAL_ERROR("Common::Ref_simple::get_refd_assignment()");
712 refd_ass
= my_scope
->get_ass_bySRef(this);
717 bool Ref_simple::has_single_expr()
722 // =================================
723 // ===== ReferenceChain
724 // =================================
726 ReferenceChain::ReferenceChain(const Location
*p_loc
, const char *p_str
)
727 : my_loc(p_loc
), err_str(p_str
), report_error(true)
730 FATAL_ERROR("ReferenceChain::ReferenceChain()");
733 ReferenceChain::~ReferenceChain()
738 ReferenceChain
*ReferenceChain::clone() const
740 FATAL_ERROR("ReferenceChain::clone()");
744 bool ReferenceChain::exists(const string
& s
) const
746 for (size_t i
= 0; i
< refs
.size(); i
++)
747 if (*refs
[i
]==s
) return true;
751 bool ReferenceChain::add(const string
& s
)
754 refs
.add(new string(s
));
760 my_loc
->error("%s: Circular reference: %s", err_str
,
761 get_dispstr(s
).c_str());
763 my_loc
->error("Circular reference: %s", get_dispstr(s
).c_str());
766 errors
.add(get_dispstr(s
));
771 void ReferenceChain::set_error_reporting(bool enable
) {
772 report_error
= enable
;
775 size_t ReferenceChain::nof_errors() const {
776 return errors
.size() - (err_stack
.empty() ? 0 : *err_stack
.top());
779 void ReferenceChain::report_errors()
781 if (!err_stack
.empty() && *err_stack
.top() > errors
.size())
782 FATAL_ERROR("Common::ReferenceChain::report_errors()");
790 for (size_t i
= (err_stack
.empty() ? 0 : *err_stack
.top());
791 i
< errors
.size(); ++i
) {
792 my_loc
->error("%sCircular reference: %s",
793 err_msg
.c_str(), errors
[i
].c_str());
797 void ReferenceChain::mark_error_state()
799 err_stack
.push(new size_t(errors
.size()));
802 void ReferenceChain::prev_error_state()
804 if (err_stack
.empty())
805 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
806 if (errors
.size() < *err_stack
.top())
807 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
809 int state
= static_cast<int>(*err_stack
.top());
810 for (int i
= static_cast<int>(errors
.size()) - 1; i
>= state
; --i
) {
813 delete err_stack
.pop();
816 void ReferenceChain::mark_state()
818 refstack
.push(new size_t(refs
.size()));
821 void ReferenceChain::prev_state()
824 FATAL_ERROR("Common::ReferenceChain::prev_state()");
825 size_t state
=*refstack
.top();
826 if(refs
.size()<state
)
827 FATAL_ERROR("Common::ReferenceChain::prev_state()");
828 for(size_t i
=state
; i
<refs
.size(); i
++) delete refs
[i
];
829 refs
.replace(state
, refs
.size()-state
);
830 delete refstack
.pop();
833 void ReferenceChain::reset()
835 for(size_t i
=0; i
<refs
.size(); i
++) delete refs
[i
];
837 while(!refstack
.empty()) delete refstack
.pop();
840 while(!err_stack
.empty()) delete err_stack
.pop();
843 string
ReferenceChain::get_dispstr(const string
& s
) const
846 // skip the elements before the first occurrence of s
847 for ( ; i
< refs
.size(); i
++) if (*refs
[i
] == s
) break;
849 for( ; i
< refs
.size(); i
++) {
854 // putting s at the end
861 } // namespace Common