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
21 * Szabo, Janos Zoltan – initial implementation
24 ******************************************************************************/
25 #include "../common/dbgnew.hh"
30 #include "Identifier.hh"
31 #include "CompilerError.hh"
33 #include "asn1/AST_asn1.hh"
34 #include "ttcn3/AST_ttcn3.hh"
38 #include "ttcn3/profiler.h"
42 // =================================
44 // =================================
46 map
<string
,void> *Location::source_file_names
= NULL
;
47 bool Location::transparency
= false;
49 const char* Location::add_source_file_name(const string
& file_name
)
51 if (source_file_names
==NULL
)
52 source_file_names
= new map
<string
,void>();
53 if (!source_file_names
->has_key(file_name
))
54 source_file_names
->add(file_name
, NULL
);
55 return source_file_names
->get_key(file_name
).c_str();
58 void Location::delete_source_file_names()
60 if (source_file_names
!=NULL
)
62 source_file_names
->clear();
63 delete source_file_names
;
64 source_file_names
= NULL
;
73 yyloc
.first_column
= 0;
74 yyloc
.last_column
= 0;
77 void Location::set_location(const char *p_filename
, int p_lineno
)
79 filename
= p_filename
;
80 yyloc
.first_line
= p_lineno
;
81 yyloc
.first_column
= 0;
82 yyloc
.last_line
= p_lineno
;
83 yyloc
.last_column
= 0;
86 void Location::set_location(const char *p_filename
, const YYLTYPE
& p_yyloc
)
88 filename
= p_filename
;
92 void Location::set_location(const char *p_filename
, const YYLTYPE
& p_firstloc
,
93 const YYLTYPE
& p_lastloc
)
95 filename
= p_filename
;
96 yyloc
.first_line
= p_firstloc
.first_line
;
97 yyloc
.first_column
= p_firstloc
.first_column
;
98 yyloc
.last_line
= p_lastloc
.last_line
;
99 yyloc
.last_column
= p_lastloc
.last_column
;
102 void Location::set_location(const char *p_filename
, int p_first_line
,
103 int p_first_column
, int p_last_line
, int p_last_column
)
105 filename
= p_filename
;
106 yyloc
.first_line
= p_first_line
;
107 yyloc
.first_column
= p_first_column
;
108 yyloc
.last_line
= p_last_line
;
109 yyloc
.last_column
= p_last_column
;
112 void Location::join_location(const Location
& p
)
114 // do nothing if this and p refer to different files
116 if (!p
.filename
) return;
117 else if (strcmp(filename
, p
.filename
)) return;
118 } else if (p
.filename
) return;
119 if (yyloc
.last_line
< p
.yyloc
.first_line
||
120 (yyloc
.last_line
== p
.yyloc
.first_line
&&
121 yyloc
.last_column
<= p
.yyloc
.first_column
)) {
123 yyloc
.last_line
= p
.yyloc
.last_line
;
124 yyloc
.last_column
= p
.yyloc
.last_column
;
125 } else if (yyloc
.first_line
> p
.yyloc
.last_line
||
126 (yyloc
.first_line
== p
.yyloc
.last_line
&&
127 yyloc
.first_column
>= p
.yyloc
.last_column
)) {
129 yyloc
.first_line
= p
.yyloc
.first_line
;
130 yyloc
.first_column
= p
.yyloc
.first_column
;
134 void Location::print_line_info(FILE *fp
) const
136 if (yyloc
.first_line
> 0) {
137 // at least partial line/column information is available
138 if (output_only_linenum
|| (yyloc
.first_line
== yyloc
.last_line
&&
139 yyloc
.first_column
<= 0 && yyloc
.last_column
<= 0)) {
140 // print only the first line
141 fprintf(fp
, "%d", yyloc
.first_line
);
142 } else if (yyloc
.last_line
> yyloc
.first_line
) {
144 if (yyloc
.first_column
>= 0 && yyloc
.last_column
>= 0) {
145 // all line/column fields are valid
147 fprintf(fp
, "%d:%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
150 fprintf(fp
, "%d.%d-%d.%d", yyloc
.first_line
,
151 yyloc
.first_column
+ 1, yyloc
.last_line
, yyloc
.last_column
);
154 // only the line numbers are valid
156 fprintf(fp
, "%d", yyloc
.first_line
);
159 fprintf(fp
, "%d-%d", yyloc
.first_line
, yyloc
.last_line
);
162 } else if (yyloc
.first_line
== yyloc
.last_line
) {
164 if (yyloc
.first_column
>= 0 && yyloc
.last_column
> yyloc
.first_column
) {
166 fprintf(fp
, "%d:%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
169 if (yyloc
.last_column
> yyloc
.first_column
+ 1) {
170 // more characters are covered
171 fprintf(fp
, "%d.%d-%d", yyloc
.first_line
, yyloc
.first_column
+ 1,
174 // only a single character is covered
175 fprintf(fp
, "%d.%d", yyloc
.first_line
, yyloc
.first_column
+ 1);
179 // the column information is invalid, print the line number only
180 fprintf(fp
, "%d", yyloc
.first_line
);
183 // the last line is smaller than the first line
184 // print only the first line
185 fprintf(fp
, "%d", yyloc
.first_line
);
188 // line information is not available
189 fputs("<unknown>", fp
);
193 void Location::print_location(FILE *fp
) const
197 if (yyloc
.first_line
> 0) {
198 // print the line information only if it is available
204 // do not print anything if the file name is unknown
207 void Location::error(const char *fmt
, ...) const
211 Error_Context::report_error(this, fmt
, args
);
215 void Location::warning(const char *fmt
, ...) const
219 Error_Context::report_warning(this, fmt
, args
);
223 void Location::note(const char *fmt
, ...) const
227 Error_Context::report_note(this, fmt
, args
);
231 char *Location::create_location_object(char *str
, const char *entitytype
,
232 const char *entityname
) const
234 if (!filename
|| yyloc
.first_line
<= 0)
235 FATAL_ERROR("Location::create_location_object()");
236 if (include_location_info
&& !transparency
) {
237 bool tcov_enabled
= tcov_file_name
&& in_tcov_files(get_filename());
239 !tcov_enabled
? "TTCN_Location current_location(\""
240 : "TTCN_Location_Statistics current_location(\"");
241 str
= Code::translate_string(str
, filename
);
242 str
= mputprintf(str
,
243 !tcov_enabled
? "\", %d, TTCN_Location::LOCATION_%s, \"%s\");\n"
244 : "\", %d, TTCN_Location_Statistics::LOCATION_%s, \"%s\");\n", yyloc
.first_line
, entitytype
, entityname
);
246 effective_module_lines
=
247 mputprintf(effective_module_lines
, "%s%d",
248 (effective_module_lines
? ", " : ""), yyloc
.first_line
);
249 effective_module_functions
=
250 mputprintf(effective_module_functions
, "%s\"%s\"",
251 (effective_module_functions
? ", " : ""), entityname
);
253 if (is_file_profiled(filename
)) {
255 size_t file_name_len
= strlen(filename
);
256 if ('p' == filename
[file_name_len
- 1] && 'p' == filename
[file_name_len
- 2]) {
259 char* file_name2
= mcopystrn(filename
, file_name_len
);
260 str
= mputprintf(str
,
261 "TTCN3_Stack_Depth stack_depth;\n"
262 "ttcn3_prof.enter_function(\"%s\", %d);\n", file_name2
, yyloc
.first_line
);
263 insert_profiler_code_line(file_name2
,
264 (0 == strcmp(entitytype
, "CONTROLPART") ? "control" : entityname
),
272 char *Location::update_location_object(char *str
) const
274 if (filename
&& yyloc
.first_line
> 0) {
275 if (include_location_info
&& !transparency
) {
276 str
= mputprintf(str
, "current_location.update_lineno(%d);\n",
278 const char* file_name
= get_filename();
279 if (is_file_profiled(file_name
)) {
281 size_t file_name_len
= strlen(file_name
);
282 if ('p' == file_name
[file_name_len
- 1] && 'p' == file_name
[file_name_len
- 2]) {
285 char* file_name2
= mcopystrn(file_name
, file_name_len
);
286 str
= mputprintf(str
, "ttcn3_prof.execute_line(\"%s\", %d);\n",
287 file_name2
, yyloc
.first_line
);
288 insert_profiler_code_line(file_name2
, NULL
, yyloc
.first_line
);
291 if (tcov_file_name
&& in_tcov_files(file_name
)) {
292 effective_module_lines
=
293 mputprintf(effective_module_lines
, "%s%d",
294 (effective_module_lines
? ", " : ""), yyloc
.first_line
);
296 if (debugger_active
) {
297 str
= mputprintf(str
, "ttcn3_debugger.breakpoint_entry(%d);\n", yyloc
.first_line
);
301 if (include_line_info
)
302 str
= mputprintf(str
, "#line %d \"%s\"\n", yyloc
.first_line
, filename
);
303 else str
= mputprintf(str
, "/* %s, line %d */\n", filename
,
309 // =================================
311 // =================================
315 static Node
*list_head
= 0, *list_tail
= 0;
321 prev_node
= list_tail
;
323 if (list_tail
) list_tail
->next_node
= this;
324 else list_head
= this;
330 Node::Node(const Node
&)
334 prev_node
= list_tail
;
336 if (list_tail
) list_tail
->next_node
= this;
337 else list_head
= this;
347 if (prev_node
) prev_node
->next_node
= next_node
;
348 else list_head
= next_node
;
349 if (next_node
) next_node
->prev_node
= prev_node
;
350 else list_tail
= prev_node
;
355 void Node::chk_counter()
357 DEBUG(1, "Node::counter is %d", counter
);
359 WARNING("%d nodes were not deleted."
360 " Please send a bug report including"
361 " the current input file(s).", counter
);
363 for (Node
*iter
= list_head
; iter
; iter
= iter
->next_node
) {
364 fprintf(stderr
, "Undeleted node: `%s' (address %p).\n",
365 iter
->get_fullname().c_str(), static_cast<void*>(iter
));
372 void Node::set_fullname(const string
& p_fullname
)
374 fullname
= p_fullname
;
377 void Node::set_my_scope(Scope
*)
381 void Node::dump(unsigned level
) const
383 DEBUG(level
, "Node: %s", fullname
.c_str());
386 // =================================
388 // =================================
390 Setting::Setting(settingtype_t p_st
)
391 : Node(), Location(),
392 st(p_st
), my_scope(0), checked(false), recurs_checked(false)
396 void Setting::set_my_scope(Scope
*p_scope
)
401 bool Setting::is_asn1() const
403 if (!my_scope
) FATAL_ERROR("Setting::is_asn1()");
404 return my_scope
->get_scope_mod()->get_moduletype() == Module::MOD_ASN
;
407 string
Setting::get_temporary_id() const
409 if (!my_scope
) FATAL_ERROR("Setting::get_temporary_id()");
410 return my_scope
->get_scope_mod_gen()->get_temporary_id();
413 void Setting::set_genname(const string
& p_genname
)
415 if (p_genname
.empty()) FATAL_ERROR("Setting::set_genname()");
419 void Setting::set_genname(const string
& p_prefix
, const string
& p_suffix
)
421 if (p_prefix
.empty() || p_suffix
.empty())
422 FATAL_ERROR("Setting::set_genname()");
424 // a single underscore character is needed as separator if neither p_prefix
425 // ends nor p_suffix begins with a single underscore character
426 size_t p_prefix_len
= p_prefix
.size();
427 if ((p_prefix
[p_prefix_len
- 1] != '_' ||
428 (p_prefix_len
>= 2 && p_prefix
[p_prefix_len
- 2] == '_')) &&
429 (p_suffix
[0] != '_' ||
430 (p_suffix
.size() >= 2 && p_suffix
[1] == '_'))) genname
+= '_';
434 const string
& Setting::get_genname_own() const
437 FATAL_ERROR("Setting::get_genname_own(): genname is not set in %s", \
438 get_fullname().c_str());
442 string
Setting::get_genname_own(Scope
*p_scope
) const
444 if (!p_scope
|| !my_scope
) FATAL_ERROR("Setting::get_genname_own");
446 Module
*my_mod
= my_scope
->get_scope_mod_gen();
447 if (my_mod
!= p_scope
->get_scope_mod_gen() &&
448 !Asn::Assignments::is_spec_asss(my_mod
)) {
449 // when the definition is referred from another module
450 // the reference shall be qualified with the namespace of my module
451 ret_val
= my_mod
->get_modid().get_name();
454 ret_val
+= get_genname_own();
458 string
Setting::create_stringRepr()
460 return string("<string representation not implemented for " +
461 get_fullname() + ">");
464 // =================================
465 // ===== Setting_Error
466 // =================================
468 Setting_Error
* Setting_Error::clone() const
470 FATAL_ERROR("Setting_Error::clone");
473 // =================================
475 // =================================
477 // =================================
479 // =================================
481 // =================================
482 // ===== GovernedSimple
483 // =================================
485 string
GovernedSimple::get_lhs_name() const
488 if (genname_prefix
) ret_val
+= genname_prefix
;
489 ret_val
+= get_genname_own();
493 bool GovernedSimple::needs_init_precede(const GovernedSimple
*refd
) const
495 if (refd
->code_generated
) return false;
496 if (code_section
== CS_UNKNOWN
|| refd
->code_section
== CS_UNKNOWN
)
497 FATAL_ERROR("GovernedSimple::needs_init_precede()");
498 if (code_section
!= refd
->code_section
) return false;
499 if (get_my_scope()->get_scope_mod_gen() !=
500 refd
->get_my_scope()->get_scope_mod_gen()) return false;
504 bool GovernedSimple::is_toplevel() const
506 const string
& name
= get_genname_own();
507 const char *name_str
= name
.c_str();
508 size_t name_len
= name
.size();
509 for (size_t i
= 0; i
< name_len
; i
++) {
510 char c
= name_str
[i
];
511 if ((c
< 'A' || c
> 'Z') && (c
< 'a' ||c
> 'z') &&
512 (c
< '0' || c
> '9') && c
!= '_') return false;
517 // =================================
519 // =================================
521 // =================================
523 // =================================
525 string
Scope::get_scope_name() const
528 if (parent_scope
) s
= parent_scope
->get_scope_name();
529 if (!scope_name
.empty()) {
530 if (s
.empty()) s
= scope_name
;
539 string
Scope::get_scopeMacro_name() const
541 if (!scopeMacro_name
.empty()) return scopeMacro_name
;
542 if (parent_scope
) return parent_scope
->get_scopeMacro_name();
543 return scopeMacro_name
;
546 Ttcn::StatementBlock
*Scope::get_statementblock_scope()
548 if (parent_scope
) return parent_scope
->get_statementblock_scope();
552 Ttcn::RunsOnScope
*Scope::get_scope_runs_on()
554 if (parent_scope
) return parent_scope
->get_scope_runs_on();
558 Assignments
*Scope::get_scope_asss()
560 if (parent_scope
) return parent_scope
->get_scope_asss();
562 FATAL_ERROR("The assignments scope is not visible from this scope: " \
563 "`%s'", get_scope_name().c_str());
567 Module
* Scope::get_scope_mod()
569 if(parent_scope
) return parent_scope
->get_scope_mod();
570 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
571 get_scope_name().c_str());
575 Module
* Scope::get_scope_mod_gen()
577 if(parent_scope_gen
) return parent_scope_gen
->get_scope_mod_gen();
578 else if(parent_scope
) return parent_scope
->get_scope_mod_gen();
579 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
580 get_scope_name().c_str());
584 bool Scope::has_ass_withId(const Identifier
& p_id
)
586 if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
590 bool Scope::is_valid_moduleid(const Identifier
& p_id
)
592 if (parent_scope
) return parent_scope
->is_valid_moduleid(p_id
);
596 Type
*Scope::get_mtc_system_comptype(bool is_system
)
598 if (parent_scope
) return parent_scope
->get_mtc_system_comptype(is_system
);
602 void Scope::chk_runs_on_clause(Assignment
*p_ass
, const Location
& p_loc
,
605 // component type of the referred definition
606 Type
*refd_comptype
= p_ass
->get_RunsOnType();
607 // definitions without 'runs on' can be called from anywhere
608 if (!refd_comptype
) return;
609 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
611 Type
*local_comptype
= t_ros
->get_component_type();
612 if (!refd_comptype
->is_compatible(local_comptype
, NULL
)) {
613 // the 'runs on' clause of the referred definition is not compatible
614 // with that of the current scope (i.e. the referring definition)
615 p_loc
.error("Runs on clause mismatch: A definition that runs on "
616 "component type `%s' cannot %s %s, which runs on `%s'",
617 local_comptype
->get_typename().c_str(), p_what
,
618 p_ass
->get_description().c_str(),
619 refd_comptype
->get_typename().c_str());
622 // the current scope unit (i.e. the referring definition) does not have
624 p_loc
.error("A definition without `runs on' clause cannot %s %s, which "
625 "runs on component type `%s'", p_what
, p_ass
->get_description().c_str(),
626 refd_comptype
->get_typename().c_str());
630 void Scope::chk_runs_on_clause(Type
*p_fat
, const Location
& p_loc
,
633 if (!p_fat
) FATAL_ERROR("Scope::chk_runs_on_clause()");
634 Type
*refd_comptype
= p_fat
->get_fat_runs_on_type();
635 // values of function/altstep types without 'runs on' clause
636 // or using 'runs on self' clause can be called from anywhere
637 if (!refd_comptype
) return;
638 const char *typetype_name
;
639 switch (p_fat
->get_typetype()) {
640 case Type::T_FUNCTION
:
641 typetype_name
= "function";
643 case Type::T_ALTSTEP
:
644 typetype_name
= "altstep";
647 FATAL_ERROR("Scope::chk_runs_on_clause()");
650 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
652 Type
*local_comptype
= t_ros
->get_component_type();
653 if (!refd_comptype
->is_compatible(local_comptype
, NULL
)) {
654 // the 'runs on' clause of the function/altstep type is not compatible
655 // with that of the current scope (i.e. the referring definition)
656 p_loc
.error("Runs on clause mismatch: A definition that runs on "
657 "component type `%s' cannot %s a value of %s type `%s', which runs "
658 "on `%s'", local_comptype
->get_typename().c_str(), p_what
,
659 typetype_name
, p_fat
->get_typename().c_str(),
660 refd_comptype
->get_typename().c_str());
663 // the current scope unit (i.e. the referring definition) does not have
665 p_loc
.error("A definition without `runs on' clause cannot %s a value of "
666 "%s type `%s', which runs on component type `%s'", p_what
,
667 typetype_name
, p_fat
->get_typename().c_str(),
668 refd_comptype
->get_typename().c_str());
672 // =================================
674 // =================================
676 size_t Reference::_Reference_counter
=0;
677 Setting_Error
*Reference::setting_error
= 0;
679 Reference::~Reference()
681 if (_Reference_counter
<= 0) FATAL_ERROR("Reference::~Reference()");
682 else if (--_Reference_counter
== 0) {
683 delete setting_error
;
688 void Reference::set_my_scope(Scope
*p_scope
)
693 bool Reference::get_is_erroneous()
698 Setting
* Reference::get_refd_setting_error()
702 setting_error
=new Setting_Error();
703 return setting_error
;
706 bool Reference::refers_to_st(Setting::settingtype_t p_st
,
709 Setting
*t_setting
=get_refd_setting();
710 if(t_setting
) return t_setting
->get_st()==p_st
;
711 else return p_st
==Setting::S_ERROR
;
714 void Reference::set_code_section(GovernedSimple::code_section_t
)
718 Ttcn::FieldOrArrayRefs
*Reference::get_subrefs()
723 Ttcn::ActualParList
*Reference::get_parlist()
728 void Reference::dump(unsigned level
) const
730 DEBUG(level
, "Reference: %s", const_cast<Reference
*>(this)->get_dispname().c_str());
733 // =================================
735 // =================================
737 string
Ref_simple::get_dispname()
740 const Identifier
*t_modid
= get_modid();
742 ret_val
+= t_modid
->get_dispname();
745 ret_val
+= get_id()->get_dispname();
749 Setting
* Ref_simple::get_refd_setting()
751 if(get_is_erroneous()) return get_refd_setting_error();
752 Assignment
*ass
= get_refd_assignment();
753 if (ass
) return ass
->get_Setting();
754 else return get_refd_setting_error();
757 Assignment
* Ref_simple::get_refd_assignment(bool)
760 if (!my_scope
) FATAL_ERROR("Common::Ref_simple::get_refd_assignment()");
761 refd_ass
= my_scope
->get_ass_bySRef(this);
766 bool Ref_simple::has_single_expr()
771 // =================================
772 // ===== ReferenceChain
773 // =================================
775 ReferenceChain::ReferenceChain(const Location
*p_loc
, const char *p_str
)
776 : my_loc(p_loc
), err_str(p_str
), report_error(true)
779 FATAL_ERROR("ReferenceChain::ReferenceChain()");
782 ReferenceChain::~ReferenceChain()
787 ReferenceChain
*ReferenceChain::clone() const
789 FATAL_ERROR("ReferenceChain::clone()");
793 bool ReferenceChain::exists(const string
& s
) const
795 for (size_t i
= 0; i
< refs
.size(); i
++)
796 if (*refs
[i
]==s
) return true;
800 bool ReferenceChain::add(const string
& s
)
803 refs
.add(new string(s
));
809 my_loc
->error("%s: Circular reference: %s", err_str
,
810 get_dispstr(s
).c_str());
812 my_loc
->error("Circular reference: %s", get_dispstr(s
).c_str());
815 errors
.add(get_dispstr(s
));
820 void ReferenceChain::set_error_reporting(bool enable
) {
821 report_error
= enable
;
824 size_t ReferenceChain::nof_errors() const {
825 return errors
.size() - (err_stack
.empty() ? 0 : *err_stack
.top());
828 void ReferenceChain::report_errors()
830 if (!err_stack
.empty() && *err_stack
.top() > errors
.size())
831 FATAL_ERROR("Common::ReferenceChain::report_errors()");
839 for (size_t i
= (err_stack
.empty() ? 0 : *err_stack
.top());
840 i
< errors
.size(); ++i
) {
841 my_loc
->error("%sCircular reference: %s",
842 err_msg
.c_str(), errors
[i
].c_str());
846 void ReferenceChain::mark_error_state()
848 err_stack
.push(new size_t(errors
.size()));
851 void ReferenceChain::prev_error_state()
853 if (err_stack
.empty())
854 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
855 if (errors
.size() < *err_stack
.top())
856 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
858 int state
= static_cast<int>(*err_stack
.top());
859 for (int i
= static_cast<int>(errors
.size()) - 1; i
>= state
; --i
) {
862 delete err_stack
.pop();
865 void ReferenceChain::mark_state()
867 refstack
.push(new size_t(refs
.size()));
870 void ReferenceChain::prev_state()
873 FATAL_ERROR("Common::ReferenceChain::prev_state()");
874 size_t state
=*refstack
.top();
875 if(refs
.size()<state
)
876 FATAL_ERROR("Common::ReferenceChain::prev_state()");
877 for(size_t i
=state
; i
<refs
.size(); i
++) delete refs
[i
];
878 refs
.replace(state
, refs
.size()-state
);
879 delete refstack
.pop();
882 void ReferenceChain::reset()
884 for(size_t i
=0; i
<refs
.size(); i
++) delete refs
[i
];
886 while(!refstack
.empty()) delete refstack
.pop();
889 while(!err_stack
.empty()) delete err_stack
.pop();
892 string
ReferenceChain::get_dispstr(const string
& s
) const
895 // skip the elements before the first occurrence of s
896 for ( ; i
< refs
.size(); i
++) if (*refs
[i
] == s
) break;
898 for( ; i
< refs
.size(); i
++) {
903 // putting s at the end
910 } // namespace Common