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
);
235 if (profiler_enabled
) {
236 str
= mputprintf(str
,
237 "TTCN3_Stack_Depth stack_depth;\n"
238 "ttcn3_prof.enter_function(\"%s\", %d, \"%s\");\n",
239 filename
, yyloc
.first_line
, entityname
);
245 char *Location::update_location_object(char *str
) const
247 if (filename
&& yyloc
.first_line
> 0) {
248 if (include_location_info
&& !transparency
) {
249 str
= mputprintf(str
, "current_location.update_lineno(%d);\n",
251 if (profiler_enabled
) {
252 str
= mputprintf(str
, "ttcn3_prof.execute_line(\"%s\", %d);\n",
253 get_filename(), yyloc
.first_line
);
255 if (tcov_file_name
&& in_tcov_files(get_filename())) {
256 effective_module_lines
=
257 mputprintf(effective_module_lines
, "%s%d",
258 (effective_module_lines
? ", " : ""), yyloc
.first_line
);
262 if (include_line_info
)
263 str
= mputprintf(str
, "#line %d \"%s\"\n", yyloc
.first_line
, filename
);
264 else str
= mputprintf(str
, "/* %s, line %d */\n", filename
,
270 // =================================
272 // =================================
276 static Node
*list_head
= 0, *list_tail
= 0;
282 prev_node
= list_tail
;
284 if (list_tail
) list_tail
->next_node
= this;
285 else list_head
= this;
291 Node::Node(const Node
&)
295 prev_node
= list_tail
;
297 if (list_tail
) list_tail
->next_node
= this;
298 else list_head
= this;
308 if (prev_node
) prev_node
->next_node
= next_node
;
309 else list_head
= next_node
;
310 if (next_node
) next_node
->prev_node
= prev_node
;
311 else list_tail
= prev_node
;
316 void Node::chk_counter()
318 DEBUG(1, "Node::counter is %d", counter
);
320 WARNING("%d nodes were not deleted."
321 " Please send a bug report including"
322 " the current input file(s).", counter
);
324 for (Node
*iter
= list_head
; iter
; iter
= iter
->next_node
) {
325 fprintf(stderr
, "Undeleted node: `%s' (address %p).\n",
326 iter
->get_fullname().c_str(), static_cast<void*>(iter
));
333 void Node::set_fullname(const string
& p_fullname
)
335 fullname
= p_fullname
;
338 void Node::set_my_scope(Scope
*)
342 void Node::dump(unsigned level
) const
344 DEBUG(level
, "Node: %s", fullname
.c_str());
347 // =================================
349 // =================================
351 Setting::Setting(settingtype_t p_st
)
352 : Node(), Location(),
353 st(p_st
), my_scope(0), checked(false), recurs_checked(false)
357 void Setting::set_my_scope(Scope
*p_scope
)
362 bool Setting::is_asn1() const
364 if (!my_scope
) FATAL_ERROR("Setting::is_asn1()");
365 return my_scope
->get_scope_mod()->get_moduletype() == Module::MOD_ASN
;
368 string
Setting::get_temporary_id() const
370 if (!my_scope
) FATAL_ERROR("Setting::get_temporary_id()");
371 return my_scope
->get_scope_mod_gen()->get_temporary_id();
374 void Setting::set_genname(const string
& p_genname
)
376 if (p_genname
.empty()) FATAL_ERROR("Setting::set_genname()");
380 void Setting::set_genname(const string
& p_prefix
, const string
& p_suffix
)
382 if (p_prefix
.empty() || p_suffix
.empty())
383 FATAL_ERROR("Setting::set_genname()");
385 // a single underscore character is needed as separator if neither p_prefix
386 // ends nor p_suffix begins with a single underscore character
387 size_t p_prefix_len
= p_prefix
.size();
388 if ((p_prefix
[p_prefix_len
- 1] != '_' ||
389 (p_prefix_len
>= 2 && p_prefix
[p_prefix_len
- 2] == '_')) &&
390 (p_suffix
[0] != '_' ||
391 (p_suffix
.size() >= 2 && p_suffix
[1] == '_'))) genname
+= '_';
395 const string
& Setting::get_genname_own() const
398 FATAL_ERROR("Setting::get_genname_own(): genname is not set in %s", \
399 get_fullname().c_str());
403 string
Setting::get_genname_own(Scope
*p_scope
) const
405 if (!p_scope
|| !my_scope
) FATAL_ERROR("Setting::get_genname_own");
407 Module
*my_mod
= my_scope
->get_scope_mod_gen();
408 if (my_mod
!= p_scope
->get_scope_mod_gen() &&
409 !Asn::Assignments::is_spec_asss(my_mod
)) {
410 // when the definition is referred from another module
411 // the reference shall be qualified with the namespace of my module
412 ret_val
= my_mod
->get_modid().get_name();
415 ret_val
+= get_genname_own();
419 string
Setting::create_stringRepr()
421 return string("<string representation not implemented for " +
422 get_fullname() + ">");
425 // =================================
426 // ===== Setting_Error
427 // =================================
429 Setting_Error
* Setting_Error::clone() const
431 FATAL_ERROR("Setting_Error::clone");
434 // =================================
436 // =================================
438 // =================================
440 // =================================
442 // =================================
443 // ===== GovernedSimple
444 // =================================
446 string
GovernedSimple::get_lhs_name() const
449 if (genname_prefix
) ret_val
+= genname_prefix
;
450 ret_val
+= get_genname_own();
454 bool GovernedSimple::needs_init_precede(const GovernedSimple
*refd
) const
456 if (refd
->code_generated
) return false;
457 if (code_section
== CS_UNKNOWN
|| refd
->code_section
== CS_UNKNOWN
)
458 FATAL_ERROR("GovernedSimple::needs_init_precede()");
459 if (code_section
!= refd
->code_section
) return false;
460 if (get_my_scope()->get_scope_mod_gen() !=
461 refd
->get_my_scope()->get_scope_mod_gen()) return false;
465 bool GovernedSimple::is_toplevel() const
467 const string
& name
= get_genname_own();
468 const char *name_str
= name
.c_str();
469 size_t name_len
= name
.size();
470 for (size_t i
= 0; i
< name_len
; i
++) {
471 char c
= name_str
[i
];
472 if ((c
< 'A' || c
> 'Z') && (c
< 'a' ||c
> 'z') &&
473 (c
< '0' || c
> '9') && c
!= '_') return false;
478 // =================================
480 // =================================
482 // =================================
484 // =================================
486 string
Scope::get_scope_name() const
489 if (parent_scope
) s
= parent_scope
->get_scope_name();
490 if (!scope_name
.empty()) {
491 if (s
.empty()) s
= scope_name
;
500 string
Scope::get_scopeMacro_name() const
502 if (!scopeMacro_name
.empty()) return scopeMacro_name
;
503 if (parent_scope
) return parent_scope
->get_scopeMacro_name();
504 return scopeMacro_name
;
507 Ttcn::StatementBlock
*Scope::get_statementblock_scope()
509 if (parent_scope
) return parent_scope
->get_statementblock_scope();
513 Ttcn::RunsOnScope
*Scope::get_scope_runs_on()
515 if (parent_scope
) return parent_scope
->get_scope_runs_on();
519 Assignments
*Scope::get_scope_asss()
521 if (parent_scope
) return parent_scope
->get_scope_asss();
523 FATAL_ERROR("The assignments scope is not visible from this scope: " \
524 "`%s'", get_scope_name().c_str());
528 Module
* Scope::get_scope_mod()
530 if(parent_scope
) return parent_scope
->get_scope_mod();
531 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
532 get_scope_name().c_str());
536 Module
* Scope::get_scope_mod_gen()
538 if(parent_scope_gen
) return parent_scope_gen
->get_scope_mod_gen();
539 else if(parent_scope
) return parent_scope
->get_scope_mod_gen();
540 else FATAL_ERROR("The module scope is not visible from this scope: `%s'", \
541 get_scope_name().c_str());
545 bool Scope::has_ass_withId(const Identifier
& p_id
)
547 if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
551 bool Scope::is_valid_moduleid(const Identifier
& p_id
)
553 if (parent_scope
) return parent_scope
->is_valid_moduleid(p_id
);
557 Type
*Scope::get_mtc_system_comptype(bool is_system
)
559 if (parent_scope
) return parent_scope
->get_mtc_system_comptype(is_system
);
563 void Scope::chk_runs_on_clause(Assignment
*p_ass
, const Location
& p_loc
,
566 // component type of the referred definition
567 Type
*refd_comptype
= p_ass
->get_RunsOnType();
568 // definitions without 'runs on' can be called from anywhere
569 if (!refd_comptype
) return;
570 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
572 Type
*local_comptype
= t_ros
->get_component_type();
573 if (!refd_comptype
->is_compatible(local_comptype
, NULL
)) {
574 // the 'runs on' clause of the referred definition is not compatible
575 // with that of the current scope (i.e. the referring definition)
576 p_loc
.error("Runs on clause mismatch: A definition that runs on "
577 "component type `%s' cannot %s %s, which runs on `%s'",
578 local_comptype
->get_typename().c_str(), p_what
,
579 p_ass
->get_description().c_str(),
580 refd_comptype
->get_typename().c_str());
583 // the current scope unit (i.e. the referring definition) does not have
585 p_loc
.error("A definition without `runs on' clause cannot %s %s, which "
586 "runs on component type `%s'", p_what
, p_ass
->get_description().c_str(),
587 refd_comptype
->get_typename().c_str());
591 void Scope::chk_runs_on_clause(Type
*p_fat
, const Location
& p_loc
,
594 if (!p_fat
) FATAL_ERROR("Scope::chk_runs_on_clause()");
595 Type
*refd_comptype
= p_fat
->get_fat_runs_on_type();
596 // values of function/altstep types without 'runs on' clause
597 // or using 'runs on self' clause can be called from anywhere
598 if (!refd_comptype
) return;
599 const char *typetype_name
;
600 switch (p_fat
->get_typetype()) {
601 case Type::T_FUNCTION
:
602 typetype_name
= "function";
604 case Type::T_ALTSTEP
:
605 typetype_name
= "altstep";
608 FATAL_ERROR("Scope::chk_runs_on_clause()");
611 Ttcn::RunsOnScope
*t_ros
= get_scope_runs_on();
613 Type
*local_comptype
= t_ros
->get_component_type();
614 if (!refd_comptype
->is_compatible(local_comptype
, NULL
)) {
615 // the 'runs on' clause of the function/altstep type is not compatible
616 // with that of the current scope (i.e. the referring definition)
617 p_loc
.error("Runs on clause mismatch: A definition that runs on "
618 "component type `%s' cannot %s a value of %s type `%s', which runs "
619 "on `%s'", local_comptype
->get_typename().c_str(), p_what
,
620 typetype_name
, p_fat
->get_typename().c_str(),
621 refd_comptype
->get_typename().c_str());
624 // the current scope unit (i.e. the referring definition) does not have
626 p_loc
.error("A definition without `runs on' clause cannot %s a value of "
627 "%s type `%s', which runs on component type `%s'", p_what
,
628 typetype_name
, p_fat
->get_typename().c_str(),
629 refd_comptype
->get_typename().c_str());
633 // =================================
635 // =================================
637 size_t Reference::_Reference_counter
=0;
638 Setting_Error
*Reference::setting_error
= 0;
640 Reference::~Reference()
642 if (_Reference_counter
<= 0) FATAL_ERROR("Reference::~Reference()");
643 else if (--_Reference_counter
== 0) {
644 delete setting_error
;
649 void Reference::set_my_scope(Scope
*p_scope
)
654 bool Reference::get_is_erroneous()
659 Setting
* Reference::get_refd_setting_error()
663 setting_error
=new Setting_Error();
664 return setting_error
;
667 bool Reference::refers_to_st(Setting::settingtype_t p_st
,
670 Setting
*t_setting
=get_refd_setting();
671 if(t_setting
) return t_setting
->get_st()==p_st
;
672 else return p_st
==Setting::S_ERROR
;
675 void Reference::set_code_section(GovernedSimple::code_section_t
)
679 Ttcn::FieldOrArrayRefs
*Reference::get_subrefs()
684 Ttcn::ActualParList
*Reference::get_parlist()
689 void Reference::dump(unsigned level
) const
691 DEBUG(level
, "Reference: %s", const_cast<Reference
*>(this)->get_dispname().c_str());
694 // =================================
696 // =================================
698 string
Ref_simple::get_dispname()
701 const Identifier
*t_modid
= get_modid();
703 ret_val
+= t_modid
->get_dispname();
706 ret_val
+= get_id()->get_dispname();
710 Setting
* Ref_simple::get_refd_setting()
712 if(get_is_erroneous()) return get_refd_setting_error();
713 Assignment
*ass
= get_refd_assignment();
714 if (ass
) return ass
->get_Setting();
715 else return get_refd_setting_error();
718 Assignment
* Ref_simple::get_refd_assignment(bool)
721 if (!my_scope
) FATAL_ERROR("Common::Ref_simple::get_refd_assignment()");
722 refd_ass
= my_scope
->get_ass_bySRef(this);
727 bool Ref_simple::has_single_expr()
732 // =================================
733 // ===== ReferenceChain
734 // =================================
736 ReferenceChain::ReferenceChain(const Location
*p_loc
, const char *p_str
)
737 : my_loc(p_loc
), err_str(p_str
), report_error(true)
740 FATAL_ERROR("ReferenceChain::ReferenceChain()");
743 ReferenceChain::~ReferenceChain()
748 ReferenceChain
*ReferenceChain::clone() const
750 FATAL_ERROR("ReferenceChain::clone()");
754 bool ReferenceChain::exists(const string
& s
) const
756 for (size_t i
= 0; i
< refs
.size(); i
++)
757 if (*refs
[i
]==s
) return true;
761 bool ReferenceChain::add(const string
& s
)
764 refs
.add(new string(s
));
770 my_loc
->error("%s: Circular reference: %s", err_str
,
771 get_dispstr(s
).c_str());
773 my_loc
->error("Circular reference: %s", get_dispstr(s
).c_str());
776 errors
.add(get_dispstr(s
));
781 void ReferenceChain::set_error_reporting(bool enable
) {
782 report_error
= enable
;
785 size_t ReferenceChain::nof_errors() const {
786 return errors
.size() - (err_stack
.empty() ? 0 : *err_stack
.top());
789 void ReferenceChain::report_errors()
791 if (!err_stack
.empty() && *err_stack
.top() > errors
.size())
792 FATAL_ERROR("Common::ReferenceChain::report_errors()");
800 for (size_t i
= (err_stack
.empty() ? 0 : *err_stack
.top());
801 i
< errors
.size(); ++i
) {
802 my_loc
->error("%sCircular reference: %s",
803 err_msg
.c_str(), errors
[i
].c_str());
807 void ReferenceChain::mark_error_state()
809 err_stack
.push(new size_t(errors
.size()));
812 void ReferenceChain::prev_error_state()
814 if (err_stack
.empty())
815 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
816 if (errors
.size() < *err_stack
.top())
817 FATAL_ERROR("Common::ReferenceChain::prev_error_state()");
819 int state
= static_cast<int>(*err_stack
.top());
820 for (int i
= static_cast<int>(errors
.size()) - 1; i
>= state
; --i
) {
823 delete err_stack
.pop();
826 void ReferenceChain::mark_state()
828 refstack
.push(new size_t(refs
.size()));
831 void ReferenceChain::prev_state()
834 FATAL_ERROR("Common::ReferenceChain::prev_state()");
835 size_t state
=*refstack
.top();
836 if(refs
.size()<state
)
837 FATAL_ERROR("Common::ReferenceChain::prev_state()");
838 for(size_t i
=state
; i
<refs
.size(); i
++) delete refs
[i
];
839 refs
.replace(state
, refs
.size()-state
);
840 delete refstack
.pop();
843 void ReferenceChain::reset()
845 for(size_t i
=0; i
<refs
.size(); i
++) delete refs
[i
];
847 while(!refstack
.empty()) delete refstack
.pop();
850 while(!err_stack
.empty()) delete err_stack
.pop();
853 string
ReferenceChain::get_dispstr(const string
& s
) const
856 // skip the elements before the first occurrence of s
857 for ( ; i
< refs
.size(); i
++) if (*refs
[i
] == s
) break;
859 for( ; i
< refs
.size(); i
++) {
864 // putting s at the end
871 } // namespace Common