1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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"
21 #include "ttcn3/profiler.h"
25 // =================================
27 // =================================
29 map
<string
,void> *Location::source_file_names
= NULL
;
30 bool Location::transparency
= false;
32 const char* Location::add_source_file_name(const string
& file_name
)
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();
41 void Location::delete_source_file_names()
43 if (source_file_names
!=NULL
)
45 source_file_names
->clear();
46 delete source_file_names
;
47 source_file_names
= NULL
;
56 yyloc
.first_column
= 0;
57 yyloc
.last_column
= 0;
60 void Location::set_location(const char *p_filename
, int p_lineno
)
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;
69 void Location::set_location(const char *p_filename
, const YYLTYPE
& p_yyloc
)
71 filename
= p_filename
;
75 void Location::set_location(const char *p_filename
, const YYLTYPE
& p_firstloc
,
76 const YYLTYPE
& p_lastloc
)
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
;
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
)
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
;
95 void Location::join_location(const Location
& p
)
97 // do nothing if this and p refer to different files
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
)) {
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
)) {
112 yyloc
.first_line
= p
.yyloc
.first_line
;
113 yyloc
.first_column
= p
.yyloc
.first_column
;
117 void Location::print_line_info(FILE *fp
) const
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
) {
127 if (yyloc
.first_column
>= 0 && yyloc
.last_column
>= 0) {
128 // all line/column fields are valid
130 fprintf(fp
, "%d:%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
133 fprintf(fp
, "%d.%d-%d.%d", yyloc
.first_line
,
134 yyloc
.first_column
+ 1, yyloc
.last_line
, yyloc
.last_column
);
137 // only the line numbers are valid
139 fprintf(fp
, "%d", yyloc
.first_line
);
142 fprintf(fp
, "%d-%d", yyloc
.first_line
, yyloc
.last_line
);
145 } else if (yyloc
.first_line
== yyloc
.last_line
) {
147 if (yyloc
.first_column
>= 0 && yyloc
.last_column
> yyloc
.first_column
) {
149 fprintf(fp
, "%d:%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
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,
157 // only a single character is covered
158 fprintf(fp
, "%d.%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
162 // the column information is invalid, print the line number only
163 fprintf(fp
, "%d", yyloc
.first_line
);
166 // the last line is smaller than the first line
167 // print only the first line
168 fprintf(fp
, "%d", yyloc
.first_line
);
171 // line information is not available
172 fputs("<unknown>", fp
);
176 void Location::print_location(FILE *fp
) const
180 if (yyloc
.first_line
> 0) {
181 // print the line information only if it is available
187 // do not print anything if the file name is unknown
190 void Location::error(const char *fmt
, ...) const
194 Error_Context::report_error(this, fmt
, args
);
198 void Location::warning(const char *fmt
, ...) const
202 Error_Context::report_warning(this, fmt
, args
);
206 void Location::note(const char *fmt
, ...) const
210 Error_Context::report_note(this, fmt
, args
);
214 char *Location::create_location_object(char *str
, const char *entitytype
,
215 const char *entityname
) const
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());
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
);
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
);
236 if (is_file_profiled(filename
)) {
238 size_t file_name_len
= strlen(filename
);
239 if ('p' == filename
[file_name_len
- 1] && 'p' == filename
[file_name_len
- 2]) {
242 char* file_name2
= mcopystrn(filename
, file_name_len
);
243 str
= mputprintf(str
,
244 "TTCN3_Stack_Depth stack_depth;\n"
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
),
255 char *Location::update_location_object(char *str
) const
257 if (filename
&& yyloc
.first_line
> 0) {
258 if (include_location_info
&& !transparency
) {
259 str
= mputprintf(str
, "current_location.update_lineno(%d);\n",
261 const char* file_name
= get_filename();
262 if (is_file_profiled(file_name
)) {
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]) {
268 char* file_name2
= mcopystrn(file_name
, file_name_len
);
269 str
= mputprintf(str
, "ttcn3_prof.execute_line(\"%s\", %d);\n",
270 file_name2
, yyloc
.first_line
);
271 insert_profiler_code_line(file_name2
, NULL
, yyloc
.first_line
);
274 if (tcov_file_name
&& in_tcov_files(file_name
)) {
275 effective_module_lines
=
276 mputprintf(effective_module_lines
, "%s%d",
277 (effective_module_lines
? ", " : ""), yyloc
.first_line
);
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
,
289 // =================================
291 // =================================
295 static Node
*list_head
= 0, *list_tail
= 0;
301 prev_node
= list_tail
;
303 if (list_tail
) list_tail
->next_node
= this;
304 else list_head
= this;
310 Node::Node(const Node
&)
314 prev_node
= list_tail
;
316 if (list_tail
) list_tail
->next_node
= this;
317 else list_head
= this;
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
;
335 void Node::chk_counter()
337 DEBUG(1, "Node::counter is %d", counter
);
339 WARNING("%d nodes were not deleted."
340 " Please send a bug report including"
341 " the current input file(s).", counter
);
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
));
352 void Node::set_fullname(const string
& p_fullname
)
354 fullname
= p_fullname
;
357 void Node::set_my_scope(Scope
*)
361 void Node::dump(unsigned level
) const
363 DEBUG(level
, "Node: %s", fullname
.c_str());
366 // =================================
368 // =================================
370 Setting::Setting(settingtype_t p_st
)
371 : Node(), Location(),
372 st(p_st
), my_scope(0), checked(false), recurs_checked(false)
376 void Setting::set_my_scope(Scope
*p_scope
)
381 bool Setting::is_asn1() const
383 if (!my_scope
) FATAL_ERROR("Setting::is_asn1()");
384 return my_scope
->get_scope_mod()->get_moduletype() == Module::MOD_ASN
;
387 string
Setting::get_temporary_id() const
389 if (!my_scope
) FATAL_ERROR("Setting::get_temporary_id()");
390 return my_scope
->get_scope_mod_gen()->get_temporary_id();
393 void Setting::set_genname(const string
& p_genname
)
395 if (p_genname
.empty()) FATAL_ERROR("Setting::set_genname()");
399 void Setting::set_genname(const string
& p_prefix
, const string
& p_suffix
)
401 if (p_prefix
.empty() || p_suffix
.empty())
402 FATAL_ERROR("Setting::set_genname()");
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
+= '_';
414 const string
& Setting::get_genname_own() const
417 FATAL_ERROR("Setting::get_genname_own(): genname is not set in %s", \
418 get_fullname().c_str());
422 string
Setting::get_genname_own(Scope
*p_scope
) const
424 if (!p_scope
|| !my_scope
) FATAL_ERROR("Setting::get_genname_own");
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();
434 ret_val
+= get_genname_own();
438 string
Setting::create_stringRepr()
440 return string("<string representation not implemented for " +
441 get_fullname() + ">");
444 // =================================
445 // ===== Setting_Error
446 // =================================
448 Setting_Error
* Setting_Error::clone() const
450 FATAL_ERROR("Setting_Error::clone");
453 // =================================
455 // =================================
457 // =================================
459 // =================================
461 // =================================
462 // ===== GovernedSimple
463 // =================================
465 string
GovernedSimple::get_lhs_name() const
468 if (genname_prefix
) ret_val
+= genname_prefix
;
469 ret_val
+= get_genname_own();
473 bool GovernedSimple::needs_init_precede(const GovernedSimple
*refd
) const
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;
484 bool GovernedSimple::is_toplevel() const
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;
497 // =================================
499 // =================================
501 // =================================
503 // =================================
505 string
Scope::get_scope_name() const
508 if (parent_scope
) s
= parent_scope
->get_scope_name();
509 if (!scope_name
.empty()) {
510 if (s
.empty()) s
= scope_name
;
519 string
Scope::get_scopeMacro_name() const
521 if (!scopeMacro_name
.empty()) return scopeMacro_name
;
522 if (parent_scope
) return parent_scope
->get_scopeMacro_name();
523 return scopeMacro_name
;
526 Ttcn::StatementBlock
*Scope::get_statementblock_scope()
528 if (parent_scope
) return parent_scope
->get_statementblock_scope();
532 Ttcn::RunsOnScope
*Scope::get_scope_runs_on()
534 if (parent_scope
) return parent_scope
->get_scope_runs_on();
538 Assignments
*Scope::get_scope_asss()
540 if (parent_scope
) return parent_scope
->get_scope_asss();
542 FATAL_ERROR("The assignments scope is not visible from this scope: " \
543 "`%s'", get_scope_name().c_str());
547 Module
* Scope::get_scope_mod()
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());
555 Module
* Scope::get_scope_mod_gen()
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());
564 bool Scope::has_ass_withId(const Identifier
& p_id
)
566 if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
570 bool Scope::is_valid_moduleid(const Identifier
& p_id
)
572 if (parent_scope
) return parent_scope
->is_valid_moduleid(p_id
);
576 Type
*Scope::get_mtc_system_comptype(bool is_system
)
578 if (parent_scope
) return parent_scope
->get_mtc_system_comptype(is_system
);
582 void Scope::chk_runs_on_clause(Assignment
*p_ass
, const Location
& p_loc
,
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();
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());
602 // the current scope unit (i.e. the referring definition) does not have
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());
610 void Scope::chk_runs_on_clause(Type
*p_fat
, const Location
& p_loc
,
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";
623 case Type::T_ALTSTEP
:
624 typetype_name
= "altstep";
627 FATAL_ERROR("Scope::chk_runs_on_clause()");
630 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
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());
643 // the current scope unit (i.e. the referring definition) does not have
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());
652 // =================================
654 // =================================
656 size_t Reference::_Reference_counter
=0;
657 Setting_Error
*Reference::setting_error
= 0;
659 Reference::~Reference()
661 if (_Reference_counter
<= 0) FATAL_ERROR("Reference::~Reference()");
662 else if (--_Reference_counter
== 0) {
663 delete setting_error
;
668 void Reference::set_my_scope(Scope
*p_scope
)
673 bool Reference::get_is_erroneous()
678 Setting
* Reference::get_refd_setting_error()
682 setting_error
=new Setting_Error();
683 return setting_error
;
686 bool Reference::refers_to_st(Setting::settingtype_t p_st
,
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
;
694 void Reference::set_code_section(GovernedSimple::code_section_t
)
698 Ttcn::FieldOrArrayRefs
*Reference::get_subrefs()
703 Ttcn::ActualParList
*Reference::get_parlist()
708 void Reference::dump(unsigned level
) const
710 DEBUG(level
, "Reference: %s", const_cast<Reference
*>(this)->get_dispname().c_str());
713 // =================================
715 // =================================
717 string
Ref_simple::get_dispname()
720 const Identifier
*t_modid
= get_modid();
722 ret_val
+= t_modid
->get_dispname();
725 ret_val
+= get_id()->get_dispname();
729 Setting
* Ref_simple::get_refd_setting()
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();
737 Assignment
* Ref_simple::get_refd_assignment(bool)
740 if (!my_scope
) FATAL_ERROR("Common::Ref_simple::get_refd_assignment()");
741 refd_ass
= my_scope
->get_ass_bySRef(this);
746 bool Ref_simple::has_single_expr()
751 // =================================
752 // ===== ReferenceChain
753 // =================================
755 ReferenceChain::ReferenceChain(const Location
*p_loc
, const char *p_str
)
756 : my_loc(p_loc
), err_str(p_str
), report_error(true)
759 FATAL_ERROR("ReferenceChain::ReferenceChain()");
762 ReferenceChain::~ReferenceChain()
767 ReferenceChain
*ReferenceChain::clone() const
769 FATAL_ERROR("ReferenceChain::clone()");
773 bool ReferenceChain::exists(const string
& s
) const
775 for (size_t i
= 0; i
< refs
.size(); i
++)
776 if (*refs
[i
]==s
) return true;
780 bool ReferenceChain::add(const string
& s
)
783 refs
.add(new string(s
));
789 my_loc
->error("%s: Circular reference: %s", err_str
,
790 get_dispstr(s
).c_str());
792 my_loc
->error("Circular reference: %s", get_dispstr(s
).c_str());
795 errors
.add(get_dispstr(s
));
800 void ReferenceChain::set_error_reporting(bool enable
) {
801 report_error
= enable
;
804 size_t ReferenceChain::nof_errors() const {
805 return errors
.size() - (err_stack
.empty() ? 0 : *err_stack
.top());
808 void ReferenceChain::report_errors()
810 if (!err_stack
.empty() && *err_stack
.top() > errors
.size())
811 FATAL_ERROR("Common::ReferenceChain::report_errors()");
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());
826 void ReferenceChain::mark_error_state()
828 err_stack
.push(new size_t(errors
.size()));
831 void ReferenceChain::prev_error_state()
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()");
838 int state
= static_cast<int>(*err_stack
.top());
839 for (int i
= static_cast<int>(errors
.size()) - 1; i
>= state
; --i
) {
842 delete err_stack
.pop();
845 void ReferenceChain::mark_state()
847 refstack
.push(new size_t(refs
.size()));
850 void ReferenceChain::prev_state()
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();
862 void ReferenceChain::reset()
864 for(size_t i
=0; i
<refs
.size(); i
++) delete refs
[i
];
866 while(!refstack
.empty()) delete refstack
.pop();
869 while(!err_stack
.empty()) delete err_stack
.pop();
872 string
ReferenceChain::get_dispstr(const string
& s
) const
875 // skip the elements before the first occurrence of s
876 for ( ; i
< refs
.size(); i
++) if (*refs
[i
] == s
) break;
878 for( ; i
< refs
.size(); i
++) {
883 // putting s at the end
890 } // namespace Common