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
18 * Zalanyi, Balazs Andor
21 ******************************************************************************/
22 #include "../../common/dbgnew.hh"
23 #include "AST_ttcn3.hh"
24 #include "../Identifier.hh"
25 #include "../CompilerError.hh"
26 #include "../Setting.hh"
28 #include "../CompField.hh"
29 #include "../CompType.hh"
30 #include "../TypeCompat.hh"
31 #include "../Valuestuff.hh"
32 #include "../Value.hh"
33 #include "Ttcnstuff.hh"
34 #include "TtcnTemplate.hh"
35 #include "Templatestuff.hh"
36 #include "ArrayDimensions.hh"
39 #include "Statement.hh"
41 #include "Attributes.hh"
42 #include "PatternString.hh"
43 #include "../../common/version_internal.h"
44 #include "../CodeGenHelper.hh"
45 #include "../../common/JSON_Tokenizer.hh"
46 #include "../DebuggerStuff.hh"
49 // implemented in coding_attrib_p.y
50 extern Ttcn::ExtensionAttributes
* parse_extattributes(
51 Ttcn::WithAttribPath
*w_attrib_path
);
53 // implemented in compiler.y
54 extern Ttcn::ErroneousAttributeSpec
* ttcn3_parse_erroneous_attr_spec_string(
55 const char* p_str
, const Common::Location
& str_loc
);
58 extern void init_coding_attrib_lex(const Ttcn::AttributeSpec
& attrib
);
59 extern int coding_attrib_parse();
60 extern void cleanup_coding_attrib_lex();
61 extern Ttcn::ExtensionAttributes
*extatrs
;
63 /** Create a field name in the anytype
65 * The output of this function will be used to create an identifier
66 * to be used as the field name in the anytype.
67 * The type_name may be a built-in type (e.g. "integer") or a user-defined
70 * If the name has multiple components (a fullname?), it keeps just the last
71 * component without any dots. *
72 * Also, the space in "universal charstring" needs to be replaced
73 * with an underscore to make it an identifier.
75 * Note: Prefixing with "AT_" is not done here, but in defUnionClass().
77 * @param type_name string
78 * @return string to be used as the identifier.
80 string
anytype_field(const string
& type_name
)
82 string
retval(type_name
);
84 // keep just the last part of the name
85 // TODO check if there's a way to get just the last component (note that fetching the string is done outside of this function)
86 size_t dot
= retval
.rfind('.');
87 if (dot
>= retval
.size()) dot
= 0;
89 retval
.replace(0, dot
, "");
94 extern Common::Modules
*modules
; // in main.cc
97 static const string
_T_("_T_");
102 using namespace Common
;
104 // =================================
105 // ===== FieldOrArrayRef
106 // =================================
108 FieldOrArrayRef::FieldOrArrayRef(const FieldOrArrayRef
& p
)
109 : Node(p
), Location(p
), ref_type(p
.ref_type
)
111 switch (p
.ref_type
) {
113 u
.id
= p
.u
.id
->clone();
116 u
.arp
= p
.u
.arp
->clone();
119 FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
123 FieldOrArrayRef::FieldOrArrayRef(Identifier
*p_id
)
124 : Node(), Location(), ref_type(FIELD_REF
)
126 if (!p_id
) FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
130 FieldOrArrayRef::FieldOrArrayRef(Value
*p_arp
)
131 : Node(), Location(), ref_type(ARRAY_REF
)
133 if (!p_arp
) FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
137 FieldOrArrayRef::~FieldOrArrayRef()
147 FATAL_ERROR("FieldOrArrayRef::~FieldOrArrayRef()");
151 FieldOrArrayRef
*FieldOrArrayRef::clone() const
153 return new FieldOrArrayRef(*this);
156 void FieldOrArrayRef::set_fullname(const string
& p_fullname
)
158 Node::set_fullname(p_fullname
);
159 if (ref_type
== ARRAY_REF
)
160 u
.arp
->set_fullname(p_fullname
+ ".<array_index>");
163 void FieldOrArrayRef::set_my_scope(Scope
*p_scope
)
165 if (ref_type
== ARRAY_REF
) u
.arp
->set_my_scope(p_scope
);
168 const Identifier
* FieldOrArrayRef::get_id() const
170 if (ref_type
!= FIELD_REF
) FATAL_ERROR("FieldOrArrayRef::get_id()");
174 Value
*FieldOrArrayRef::get_val() const
176 if (ref_type
!= ARRAY_REF
) FATAL_ERROR("FieldOrArrayRef::get_val()");
180 void FieldOrArrayRef::append_stringRepr(string
& str
) const
185 str
+= u
.id
->get_dispname();
189 str
+= u
.arp
->get_stringRepr();
193 str
+= "<unknown sub-reference>";
197 void FieldOrArrayRef::set_field_name_to_lowercase()
199 if (ref_type
!= FIELD_REF
) FATAL_ERROR("FieldOrArrayRef::set_field_name_to_lowercase()");
200 string new_name
= u
.id
->get_name();
201 if (isupper(new_name
[0])) {
202 new_name
[0] = tolower(new_name
[0]);
203 if (new_name
[new_name
.size() - 1] == '_') {
204 // an underscore is inserted at the end of the field name if it's
205 // a basic type's name (since it would conflict with the class generated
207 // remove the underscore, it won't conflict with anything if its name
208 // starts with a lowercase letter
209 new_name
.replace(new_name
.size() - 1, 1, "");
212 u
.id
= new Identifier(Identifier::ID_NAME
, new_name
);
216 // =================================
217 // ===== FieldOrArrayRefs
218 // =================================
220 FieldOrArrayRefs::FieldOrArrayRefs(const FieldOrArrayRefs
& p
)
221 : Node(p
), refs_str_element(false)
223 for (size_t i
= 0; i
< p
.refs
.size(); i
++) refs
.add(p
.refs
[i
]->clone());
226 FieldOrArrayRefs::~FieldOrArrayRefs()
228 for (size_t i
= 0; i
< refs
.size(); i
++) delete refs
[i
];
232 FieldOrArrayRefs
*FieldOrArrayRefs::clone() const
234 return new FieldOrArrayRefs(*this);
237 void FieldOrArrayRefs::set_fullname(const string
& p_fullname
)
239 Node::set_fullname(p_fullname
);
240 for (size_t i
= 0; i
< refs
.size(); i
++)
241 refs
[i
]->set_fullname(p_fullname
+
242 ".<sub_reference" + Int2string(i
+ 1) + ">");
245 void FieldOrArrayRefs::set_my_scope(Scope
*p_scope
)
247 for (size_t i
= 0; i
< refs
.size(); i
++) refs
[i
]->set_my_scope(p_scope
);
250 bool FieldOrArrayRefs::has_unfoldable_index() const
252 for (size_t i
= 0; i
< refs
.size(); i
++) {
253 FieldOrArrayRef
*ref
= refs
[i
];
254 if (ref
->get_type() == FieldOrArrayRef::ARRAY_REF
) {
255 Value
*v
= ref
->get_val();
256 v
->set_lowerid_to_ref();
257 if (v
->is_unfoldable()) return true;
263 void FieldOrArrayRefs::remove_refs(size_t n
)
265 for (size_t i
= 0; i
< n
; i
++) delete refs
[i
];
266 refs
.replace(0, n
, NULL
);
267 set_fullname(get_fullname());
270 /* remove_last_field is used when unfolding references for
271 ischosen and ispresent function operands.
272 In this case it is NOT sure the last field exists.
273 Calling remove_last_field previously
274 will avoid getting the "variable...Has no member called..." error message.
275 The last field component will be checked as a separate step.
276 Warning: the removed Identifier has to be deleted later */
278 Identifier
* FieldOrArrayRefs::remove_last_field()
280 if (refs
.size() == 0) return 0;
281 size_t last_elem_ind
= refs
.size() - 1;
282 FieldOrArrayRef
* last_elem
= refs
[last_elem_ind
];
283 if (last_elem
->get_type() == FieldOrArrayRef::FIELD_REF
) {
284 Identifier
*ret_val
= last_elem
->get_id()->clone();
286 refs
.replace(last_elem_ind
, 1, NULL
);
291 void FieldOrArrayRefs::generate_code(expression_struct
*expr
,
292 Common::Assignment
*ass
, size_t nof_subrefs
/* = UINT_MAX*/)
295 bool is_template
= false;
296 switch (ass
->get_asstype()) {
297 case Common::Assignment::A_CONST
: // a Def_Const
298 case Common::Assignment::A_EXT_CONST
: // a Def_ExtConst
299 case Common::Assignment::A_MODULEPAR
: // a Def_Modulepar
300 case Common::Assignment::A_VAR
: // a Def_Var
301 case Common::Assignment::A_FUNCTION_RVAL
: // a Def_Function
302 case Common::Assignment::A_EXT_FUNCTION_RVAL
: // a Def_ExtFunction
303 case Common::Assignment::A_PAR_VAL_IN
: // a FormalPar
304 case Common::Assignment::A_PAR_VAL_OUT
: // a FormalPar
305 case Common::Assignment::A_PAR_VAL_INOUT
: // a FormalPar
306 // The type is important since the referred entities are value objects.
307 type
= ass
->get_Type();
309 case Common::Assignment::A_MODULEPAR_TEMP
: // a Def_Modulepar_Template
310 case Common::Assignment::A_TEMPLATE
: // a Def_Template
311 case Common::Assignment::A_VAR_TEMPLATE
: // a Def_Var_Template
312 case Common::Assignment::A_PAR_TEMPL_IN
: // a FormalPar
313 case Common::Assignment::A_PAR_TEMPL_OUT
: // a FormalPar
314 case Common::Assignment::A_PAR_TEMPL_INOUT
: // a FormalPar
315 // The type is semi-important because fields of anytype templates
317 type
= ass
->get_Type();
320 case Common::Assignment::A_TIMER
: // a Def_Timer
321 case Common::Assignment::A_PORT
: // a Def_Port
322 case Common::Assignment::A_FUNCTION_RTEMP
: // a Def_Function
323 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: // a Def_ExtFunction
324 case Common::Assignment::A_PAR_TIMER
: // a FormalPar
325 case Common::Assignment::A_PAR_PORT
: // a FormalPar
326 // The type is not relevant (i.e. the optional fields do not require
327 // special handling).
331 // Reference to other definitions cannot occur during code generation.
332 FATAL_ERROR("FieldOrArrayRefs::generate_code()");
335 size_t n_refs
= (nof_subrefs
!= UINT_MAX
) ? nof_subrefs
: refs
.size();
336 for (size_t i
= 0; i
< n_refs
; i
++) {
337 if (type
) type
= type
->get_type_refd_last();
338 // type changes inside the loop; need to recompute "last" every time.
339 FieldOrArrayRef
*ref
= refs
[i
];
340 if (ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
341 // Write a call to the field accessor method.
342 // Fields of the anytype get a special prefix; see also:
343 // Template::generate_code_init_se, TypeConv::gen_conv_func_choice_anytype,
344 // defUnionClass and defUnionTemplate.
345 const Identifier
& id
= *ref
->get_id();
346 expr
->expr
= mputprintf(expr
->expr
, ".%s%s()",
347 ((type
!=0 && type
->get_typetype()==Type::T_ANYTYPE
) ? "AT_" : ""),
348 id
.get_name().c_str());
350 CompField
*cf
= type
->get_comp_byName(id
);
351 // If the field is optional, the return type of the accessor is an
352 // OPTIONAL<T>. Write a call to OPTIONAL<T>::operator(),
353 // which "reaches into" the OPTIONAL to get the contained type T.
354 // Don't do this at the end of the reference chain.
355 // Accessor methods for a foo_template return a bar_template
356 // and OPTIONAL<> is not involved, hence no "()".
357 if (!is_template
&& i
< n_refs
- 1 && cf
->get_is_optional())
358 expr
->expr
= mputstr(expr
->expr
, "()");
359 // Follow the field type.
360 type
= cf
->get_type();
363 // Generate code for array reference.
364 expr
->expr
= mputc(expr
->expr
, '[');
365 ref
->get_val()->generate_code_expr(expr
);
366 expr
->expr
= mputc(expr
->expr
, ']');
368 // Follow the embedded type.
369 switch (type
->get_typetype()) {
373 type
= type
->get_ofType();
376 // The index points to a string element.
377 // There are no further sub-references.
381 } // if (ref->get_type)
385 void FieldOrArrayRefs::append_stringRepr(string
& str
) const
387 for (size_t i
= 0; i
< refs
.size(); i
++) refs
[i
]->append_stringRepr(str
);
390 // =================================
392 // =================================
394 Ref_base::Ref_base(const Ref_base
& p
)
395 : Ref_simple(p
), subrefs(p
.subrefs
)
397 modid
= p
.modid
? p
.modid
->clone() : 0;
398 id
= p
.id
? p
.id
->clone() : 0;
399 params_checked
= p
.is_erroneous
;
402 Ref_base::Ref_base(Identifier
*p_modid
, Identifier
*p_id
)
403 : Ref_simple(), modid(p_modid
), id(p_id
), params_checked(false)
404 , usedInIsbound(false)
407 FATAL_ERROR("NULL parameter: Ttcn::Ref_base::Ref_base()");
410 Ref_base::~Ref_base()
416 void Ref_base::set_fullname(const string
& p_fullname
)
418 Ref_simple::set_fullname(p_fullname
);
419 subrefs
.set_fullname(p_fullname
);
422 void Ref_base::set_my_scope(Scope
*p_scope
)
424 Ref_simple::set_my_scope(p_scope
);
425 subrefs
.set_my_scope(p_scope
);
428 /* returns the referenced variable's base type or value */
429 Setting
* Ref_base::get_refd_setting()
431 Common::Assignment
*ass
= get_refd_assignment();
432 if (ass
) return ass
->get_Setting();
436 FieldOrArrayRefs
*Ref_base::get_subrefs()
438 if (!id
) get_modid();
439 if (subrefs
.get_nof_refs() == 0) return 0;
440 else return &subrefs
;
443 bool Ref_base::has_single_expr()
445 Common::Assignment
*ass
= get_refd_assignment();
446 if (!ass
) FATAL_ERROR("Ref_base::has_single_expr()");
447 for (size_t i
= 0; i
< subrefs
.get_nof_refs(); i
++) {
448 FieldOrArrayRef
*ref
= subrefs
.get_ref(i
);
449 if (ref
->get_type() == FieldOrArrayRef::ARRAY_REF
&&
450 !ref
->get_val()->has_single_expr()) return false;
455 void Ref_base::set_code_section(
456 GovernedSimple::code_section_t p_code_section
)
458 for (size_t i
= 0; i
< subrefs
.get_nof_refs(); i
++) {
459 FieldOrArrayRef
*ref
= subrefs
.get_ref(i
);
460 if (ref
->get_type() == FieldOrArrayRef::ARRAY_REF
)
461 ref
->get_val()->set_code_section(p_code_section
);
465 void Ref_base::generate_code_const_ref(expression_struct_t */
*expr*/
)
467 FATAL_ERROR("Ref_base::generate_code_const_ref()");
470 // =================================
472 // =================================
474 Reference::Reference(Identifier
*p_id
)
475 : Ref_base(), parlist(0)
477 subrefs
.add(new FieldOrArrayRef(p_id
));
480 Reference::~Reference()
488 * Common::PortTypeBody::PortTypeBody
490 * Common::TypeMappingTarget::TypeMappingTarget
491 * Common::PatternString::ps_elem_t::chk_ref */
492 Reference
*Reference::clone() const
494 return new Reference(*this);
497 string
Reference::get_dispname()
502 ret_val
+= modid
->get_dispname();
505 ret_val
+= id
->get_dispname();
506 subrefs
.append_stringRepr(ret_val
);
508 subrefs
.append_stringRepr(ret_val
);
509 // cut the leading dot
510 if (!ret_val
.empty() && ret_val
[0] == '.')
511 ret_val
.replace(0, 1, "");
516 Common::Assignment
* Reference::get_refd_assignment(bool check_parlist
)
518 Common::Assignment
*ass
= Ref_base::get_refd_assignment(check_parlist
);
519 // In fact calls Ref_simple::get_refd_assignment
520 if (ass
&& check_parlist
&& !params_checked
) {
521 params_checked
= true;
522 FormalParList
*fplist
= ass
->get_FormalParList();
524 if (fplist
->has_only_default_values()
525 && Common::Assignment::A_TEMPLATE
== ass
->get_asstype()) {
526 Ttcn::ParsedActualParameters params
;
527 Error_Context
cntxt(¶ms
, "In actual parameter list of %s",
528 ass
->get_description().c_str());
529 parlist
= new ActualParList();
530 is_erroneous
= fplist
->fold_named_and_chk(¶ms
, parlist
);
531 parlist
->set_fullname(get_fullname());
532 parlist
->set_my_scope(my_scope
);
534 error("Reference to parameterized definition `%s' without "
535 "actual parameter list", ass
->get_id().get_dispname().c_str());
542 const Identifier
* Reference::get_modid()
544 if (!id
) detect_modid();
548 const Identifier
* Reference::get_id()
550 if (!id
) detect_modid();
554 Type
*Reference::chk_variable_ref()
556 Common::Assignment
*t_ass
= get_refd_assignment();
557 if (!t_ass
) return 0;
558 switch (t_ass
->get_asstype()) {
559 case Common::Assignment::A_PAR_VAL_IN
:
560 t_ass
->use_as_lvalue(*this);
562 case Common::Assignment::A_VAR
:
563 case Common::Assignment::A_PAR_VAL_OUT
:
564 case Common::Assignment::A_PAR_VAL_INOUT
:
567 error("Reference to a variable or value parameter was "
568 "expected instead of %s", t_ass
->get_description().c_str());
571 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
572 Type
*ret_val
= t_ass
->get_Type()->get_field_type(t_subrefs
,
573 Type::EXPECTED_DYNAMIC_VALUE
);
574 if (ret_val
&& t_subrefs
&& t_subrefs
->refers_to_string_element()) {
575 error("Reference to a string element of type `%s' cannot be used in "
576 "this context", ret_val
->get_typename().c_str());
581 Type
*Reference::chk_comptype_ref()
583 Common::Assignment
*ass
= get_refd_assignment();
585 if (ass
->get_asstype() == Common::Assignment::A_TYPE
) {
586 Type
*t
= ass
->get_Type()->get_type_refd_last();
587 switch (t
->get_typetype()) {
591 case Type::T_COMPONENT
:
594 error("Reference `%s' does not refer to a component type",
595 get_dispname().c_str());
598 error("Reference `%s' does not refer to a type",
599 get_dispname().c_str());
605 bool Reference::has_single_expr()
607 if (!Ref_base::has_single_expr()) {
610 if (parlist
!= NULL
) {
611 for (size_t i
= 0; i
< parlist
->get_nof_pars(); i
++) {
612 if (!parlist
->get_par(i
)->has_single_expr()) {
620 void Reference::refd_param_usage_found()
622 Common::Assignment
*ass
= get_refd_assignment();
623 if (!ass
) FATAL_ERROR("Reference::refd_param_usage_found()");
624 switch (ass
->get_asstype()) {
625 case Common::Assignment::A_PAR_VAL_OUT
:
626 case Common::Assignment::A_PAR_TEMPL_OUT
:
627 case Common::Assignment::A_PAR_VAL
:
628 case Common::Assignment::A_PAR_VAL_IN
:
629 case Common::Assignment::A_PAR_VAL_INOUT
:
630 case Common::Assignment::A_PAR_TEMPL_IN
:
631 case Common::Assignment::A_PAR_TEMPL_INOUT
:
632 case Common::Assignment::A_PAR_PORT
:
633 case Common::Assignment::A_PAR_TIMER
: {
634 FormalPar
*fpar
= dynamic_cast<FormalPar
*>(ass
);
635 if (!fpar
) FATAL_ERROR("Reference::refd_param_usage_found()");
636 fpar
->set_usage_found();
643 void Reference::generate_code(expression_struct_t
*expr
)
645 refd_param_usage_found();
646 Common::Assignment
*ass
= get_refd_assignment();
647 if (!ass
) FATAL_ERROR("Reference::generate_code()");
649 // reference without parameters to a template that has only default formal parameters.
650 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
651 expr
->expr
= mputprintf(expr
->expr
, "%s(",
652 ass
->get_genname_from_scope(my_scope
).c_str());
653 parlist
->generate_code_alias(expr
, ass
->get_FormalParList(),
654 ass
->get_RunsOnType(), false);
655 expr
->expr
= mputc(expr
->expr
, ')');
657 expr
->expr
= mputstr(expr
->expr
,
658 LazyParamData::in_lazy() ?
659 LazyParamData::add_ref_genname(ass
, my_scope
).c_str() :
660 ass
->get_genname_from_scope(my_scope
).c_str());
662 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
665 void Reference::generate_code_const_ref(expression_struct_t
*expr
)
667 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
668 if (!t_subrefs
|| t_subrefs
->get_nof_refs() == 0) {
673 refd_param_usage_found();
674 Common::Assignment
*ass
= get_refd_assignment();
675 if (!ass
) FATAL_ERROR("Reference::generate_code_const_ref()");
678 switch (ass
->get_asstype()) {
679 case Common::Assignment::A_MODULEPAR
:
680 case Common::Assignment::A_VAR
:
681 case Common::Assignment::A_FUNCTION_RVAL
:
682 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
683 case Common::Assignment::A_PAR_VAL_IN
:
684 case Common::Assignment::A_PAR_VAL_OUT
:
685 case Common::Assignment::A_PAR_VAL_INOUT
: {
688 case Common::Assignment::A_MODULEPAR_TEMP
:
689 case Common::Assignment::A_TEMPLATE
:
690 case Common::Assignment::A_VAR_TEMPLATE
:
691 case Common::Assignment::A_PAR_TEMPL_IN
:
692 case Common::Assignment::A_PAR_TEMPL_OUT
:
693 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
696 case Common::Assignment::A_CONST
:
697 case Common::Assignment::A_EXT_CONST
:
703 Type
*refd_gov
= ass
->get_Type();
705 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
706 refd_gov
->get_genname_template(get_my_scope()).c_str() );
708 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
709 refd_gov
->get_genname_value(get_my_scope()).c_str());
712 // reference without parameters to a template that has only default formal parameters.
713 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
714 expr
->expr
= mputprintf(expr
->expr
, "%s(",
715 ass
->get_genname_from_scope(my_scope
).c_str());
716 parlist
->generate_code_alias(expr
, ass
->get_FormalParList(),
717 ass
->get_RunsOnType(), false);
718 expr
->expr
= mputc(expr
->expr
, ')');
720 expr
->expr
= mputstr(expr
->expr
,
721 LazyParamData::in_lazy() ?
722 LazyParamData::add_ref_genname(ass
, my_scope
).c_str() :
723 ass
->get_genname_from_scope(my_scope
).c_str());
725 expr
->expr
= mputstr(expr
->expr
, ")");
727 if (t_subrefs
&& t_subrefs
->get_nof_refs() > 0)
728 t_subrefs
->generate_code(expr
, ass
);
731 void Reference::generate_code_portref(expression_struct_t
*expr
,
734 refd_param_usage_found();
735 Common::Assignment
*ass
= get_refd_assignment();
736 if (!ass
) FATAL_ERROR("Reference::generate_code_portref()");
737 expr
->expr
= mputstr(expr
->expr
,
738 ass
->get_genname_from_scope(p_scope
).c_str());
739 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
743 void Reference::generate_code_ispresentbound(expression_struct_t
*expr
,
744 bool is_template
, const bool isbound
)
746 refd_param_usage_found();
747 Common::Assignment
*ass
= get_refd_assignment();
748 const string
& ass_id
= ass
->get_genname_from_scope(my_scope
);
749 const char *ass_id_str
= ass_id
.c_str();
751 if (subrefs
.get_nof_refs() > 0) {
752 const string
& tmp_generalid
= my_scope
->get_scope_mod_gen()
753 ->get_temporary_id();
754 const char *tmp_generalid_str
= tmp_generalid
.c_str();
756 expression_struct isbound_expr
;
757 Code::init_expr(&isbound_expr
);
758 isbound_expr
.preamble
= mputprintf(isbound_expr
.preamble
,
759 "boolean %s = %s.is_bound();\n", tmp_generalid_str
,
761 ass
->get_Type()->generate_code_ispresentbound(&isbound_expr
, &subrefs
, my_scope
->get_scope_mod_gen(),
762 tmp_generalid
, ass_id
, is_template
, isbound
);
764 expr
->preamble
= mputstr(expr
->preamble
, isbound_expr
.preamble
);
765 expr
->preamble
= mputstr(expr
->preamble
, isbound_expr
.expr
);
766 Code::free_expr(&isbound_expr
);
768 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_generalid_str
);
770 expr
->expr
= mputprintf(expr
->expr
, "%s.%s(%s)", ass_id_str
,
771 isbound
? "is_bound":"is_present",
772 (!isbound
&& is_template
&& omit_in_value_list
) ? "TRUE" : "");
776 void Reference::detect_modid()
778 // do nothing if detection is already performed
780 // the first element of subrefs must be an <id>
781 const Identifier
*first_id
= subrefs
.get_ref(0)->get_id(), *second_id
= 0;
782 if (subrefs
.get_nof_refs() > 1) {
783 FieldOrArrayRef
*second_ref
= subrefs
.get_ref(1);
784 if (second_ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
785 // the reference begins with <id>.<id> (most complicated case)
786 // there are 3 possible situations:
787 // 1. first_id points to a local definition (this has the priority)
788 // modid: 0, id: first_id
789 // 2. first_id points to an imported module (trivial case)
790 // modid: first_id, id: second_id
791 // 3. none of the above (first_id might be an imported symbol)
792 // modid: 0, id: first_id
793 // Note: Rule 1 has the priority because it can be overridden using
794 // the notation <id>.objid { ... }.<id> (modid and id are set in the
795 // constructor), but there is no work-around in the reverse way.
796 if (!my_scope
->has_ass_withId(*first_id
)
797 && my_scope
->is_valid_moduleid(*first_id
)) {
798 // rule 1 is not fulfilled, but rule 2 is fulfilled
799 second_id
= second_ref
->get_id();
801 } // else: the reference begins with <id>[<arrayref>] -> there is no modid
802 } // else: the reference consists of a single <id> -> there is no modid
804 modid
= first_id
->clone();
805 id
= second_id
->clone();
806 subrefs
.remove_refs(2);
809 id
= first_id
->clone();
810 subrefs
.remove_refs(1);
814 // =================================
816 // =================================
818 Ref_pard::Ref_pard(const Ref_pard
& p
)
819 : Ref_base(p
), parlist(p
.parlist
), expr_cache(0)
821 params
= p
.params
? p
.params
->clone() : 0;
824 Ref_pard::Ref_pard(Identifier
*p_modid
, Identifier
*p_id
,
825 ParsedActualParameters
*p_params
)
826 : Ref_base(p_modid
, p_id
), parlist(), params(p_params
), expr_cache(0)
829 FATAL_ERROR("Ttcn::Ref_pard::Ref_pard(): NULL parameter");
832 Ref_pard::~Ref_pard()
838 Ref_pard
*Ref_pard::clone() const
840 return new Ref_pard(*this);
843 void Ref_pard::set_fullname(const string
& p_fullname
)
845 Ref_base::set_fullname(p_fullname
);
846 parlist
.set_fullname(p_fullname
);
847 if (params
) params
->set_fullname(p_fullname
);
850 void Ref_pard::set_my_scope(Scope
*p_scope
)
852 Ref_base::set_my_scope(p_scope
);
853 parlist
.set_my_scope(p_scope
);
854 if (params
) params
->set_my_scope(p_scope
);
857 string
Ref_pard::get_dispname()
859 if (is_erroneous
) return string("erroneous");
862 ret_val
+= modid
->get_dispname();
865 ret_val
+= id
->get_dispname();
867 if (params_checked
) {
868 // used after semantic analysis
869 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++) {
870 if (i
> 0) ret_val
+= ", ";
871 parlist
.get_par(i
)->append_stringRepr(ret_val
);
874 // used before semantic analysis
875 for (size_t i
= 0; i
< params
->get_nof_tis(); i
++) {
876 if (i
> 0) ret_val
+= ", ";
877 params
->get_ti_byIndex(i
)->append_stringRepr(ret_val
);
881 subrefs
.append_stringRepr(ret_val
);
885 Common::Assignment
* Ref_pard::get_refd_assignment(bool check_parlist
)
887 Common::Assignment
*ass
= Ref_base::get_refd_assignment(check_parlist
);
888 if (ass
&& check_parlist
&& !params_checked
) {
889 params_checked
= true;
890 FormalParList
*fplist
= ass
->get_FormalParList();
892 Error_Context
cntxt(params
, "In actual parameter list of %s",
893 ass
->get_description().c_str());
894 is_erroneous
= fplist
->fold_named_and_chk(params
, &parlist
);
895 parlist
.set_fullname(get_fullname());
896 parlist
.set_my_scope(my_scope
);
897 // the parsed parameter list is no longer needed
901 params
->error("The referenced %s cannot have actual parameters",
902 ass
->get_description().c_str());
908 const Identifier
* Ref_pard::get_modid()
913 const Identifier
* Ref_pard::get_id()
918 ActualParList
*Ref_pard::get_parlist()
920 if (!params_checked
) FATAL_ERROR("Ref_pard::get_parlist()");
924 bool Ref_pard::chk_activate_argument()
926 Common::Assignment
*t_ass
= get_refd_assignment();
927 if (!t_ass
) return false;
928 if (t_ass
->get_asstype() != Common::Assignment::A_ALTSTEP
) {
929 error("Reference to an altstep was expected in the argument instead of "
930 "%s", t_ass
->get_description().c_str());
933 my_scope
->chk_runs_on_clause(t_ass
, *this, "activate");
934 // the altstep reference cannot have sub-references
935 if (get_subrefs()) FATAL_ERROR("Ref_pard::chk_activate_argument()");
936 FormalParList
*fp_list
= t_ass
->get_FormalParList();
937 // the altstep must have formal parameter list
938 if (!fp_list
) FATAL_ERROR("Ref_pard::chk_activate_argument()");
939 return fp_list
->chk_activate_argument(&parlist
,
940 t_ass
->get_description().c_str());
943 bool Ref_pard::has_single_expr()
945 if (!Ref_base::has_single_expr()) return false;
946 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++)
947 if (!parlist
.get_par(i
)->has_single_expr()) return false;
948 // if any formal parameter has lazy evaluation
949 Common::Assignment
*ass
= get_refd_assignment();
951 const FormalParList
*fplist
= ass
->get_FormalParList();
953 size_t num_formal
= fplist
->get_nof_fps();
954 for (size_t i
=0; i
<num_formal
; ++i
) {
955 const FormalPar
*fp
= fplist
->get_fp_byIndex(i
);
956 if (fp
->get_lazy_eval()) return false;
963 void Ref_pard::set_code_section(
964 GovernedSimple::code_section_t p_code_section
)
966 Ref_base::set_code_section(p_code_section
);
967 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++)
968 parlist
.get_par(i
)->set_code_section(p_code_section
);
971 void Ref_pard::generate_code(expression_struct_t
*expr
)
973 Common::Assignment
*ass
= get_refd_assignment();
974 // C++ function reference with actual parameter list
975 expr
->expr
= mputprintf(expr
->expr
, "%s(",
976 ass
->get_genname_from_scope(my_scope
).c_str());
977 parlist
.generate_code_alias(expr
, ass
->get_FormalParList(),
978 ass
->get_RunsOnType(),false);
979 expr
->expr
= mputc(expr
->expr
, ')');
981 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
984 void Ref_pard::generate_code_cached(expression_struct_t
*expr
)
987 expr
->expr
= mputstr(expr
->expr
, expr_cache
);
991 expr_cache
= mputstr(expr_cache
, expr
->expr
);
995 void Ref_pard::generate_code_const_ref(expression_struct_t
*expr
)
997 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
998 if (!t_subrefs
|| t_subrefs
->get_nof_refs() == 0) {
1003 Common::Assignment
*ass
= get_refd_assignment();
1004 if (!ass
) FATAL_ERROR("Ref_pard::generate_code_const_ref()");
1007 switch (ass
->get_asstype()) {
1008 case Common::Assignment::A_TEMPLATE
:
1009 if (NULL
== ass
->get_FormalParList()) {
1010 // not a parameterized template
1014 // else fall through
1015 case Common::Assignment::A_CONST
:
1016 case Common::Assignment::A_EXT_CONST
:
1017 case Common::Assignment::A_ALTSTEP
:
1018 case Common::Assignment::A_TESTCASE
:
1019 case Common::Assignment::A_FUNCTION
:
1020 case Common::Assignment::A_EXT_FUNCTION
:
1021 case Common::Assignment::A_FUNCTION_RVAL
:
1022 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
1023 case Common::Assignment::A_FUNCTION_RTEMP
:
1024 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
1025 generate_code(expr
);
1027 case Common::Assignment::A_MODULEPAR
:
1028 case Common::Assignment::A_VAR
:
1029 case Common::Assignment::A_PAR_VAL_IN
:
1030 case Common::Assignment::A_PAR_VAL_OUT
:
1031 case Common::Assignment::A_PAR_VAL_INOUT
: {
1032 is_template
= false;
1034 case Common::Assignment::A_MODULEPAR_TEMP
:
1035 case Common::Assignment::A_VAR_TEMPLATE
:
1036 case Common::Assignment::A_PAR_TEMPL_IN
:
1037 case Common::Assignment::A_PAR_TEMPL_OUT
:
1038 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
1042 is_template
= false;
1046 Type
*refd_gov
= ass
->get_Type();
1048 generate_code(expr
);
1053 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
1054 refd_gov
->get_genname_template(get_my_scope()).c_str() );
1056 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s%s&>(",
1057 refd_gov
->get_genname_value(get_my_scope()).c_str(),
1058 is_template
? "_template":"");
1061 expr
->expr
= mputprintf(expr
->expr
, "%s(",
1062 ass
->get_genname_from_scope(my_scope
).c_str());
1063 parlist
.generate_code_alias(expr
, ass
->get_FormalParList(),
1064 ass
->get_RunsOnType(), false);
1065 expr
->expr
= mputstr(expr
->expr
, "))");
1067 t_subrefs
->generate_code(expr
, ass
);
1070 // =================================
1071 // ===== NameBridgingScope
1072 // =================================
1073 string
NameBridgingScope::get_scopeMacro_name() const
1075 if (scopeMacro_name
.empty()) FATAL_ERROR("NameBridgingScope::get_scopeMacro_name()");
1076 return scopeMacro_name
;
1079 NameBridgingScope
*NameBridgingScope::clone() const
1081 FATAL_ERROR("NameBridgingScope::clone");
1084 Common::Assignment
* NameBridgingScope::get_ass_bySRef(Ref_simple
*p_ref
)
1086 return get_parent_scope()->get_ass_bySRef(p_ref
);
1089 // =================================
1090 // ===== RunsOnScope
1091 // =================================
1093 RunsOnScope::RunsOnScope(Type
*p_comptype
)
1094 : Scope(), component_type(p_comptype
)
1096 if (!p_comptype
|| p_comptype
->get_typetype() != Type::T_COMPONENT
)
1097 FATAL_ERROR("RunsOnScope::RunsOnScope()");
1098 component_type
->set_ownertype(Type::OT_RUNSON_SCOPE
, this);
1099 component_defs
= p_comptype
->get_CompBody();
1100 set_scope_name("runs on `" + p_comptype
->get_fullname() + "'");
1103 RunsOnScope
*RunsOnScope::clone() const
1105 FATAL_ERROR("RunsOnScope::clone()");
1108 void RunsOnScope::chk_uniq()
1110 // do not perform this check if the component type is defined in the same
1111 // module as the 'runs on' clause
1112 if (parent_scope
->get_scope_mod() == component_defs
->get_scope_mod())
1114 size_t nof_defs
= component_defs
->get_nof_asss();
1115 for (size_t i
= 0; i
< nof_defs
; i
++) {
1116 Common::Assignment
*comp_def
= component_defs
->get_ass_byIndex(i
);
1117 const Identifier
& id
= comp_def
->get_id();
1118 if (parent_scope
->has_ass_withId(id
)) {
1119 comp_def
->warning("Imported component element definition `%s' hides a "
1120 "definition at module scope", comp_def
->get_fullname().c_str());
1121 Reference
ref(0, id
.clone());
1122 Common::Assignment
*hidden_ass
= parent_scope
->get_ass_bySRef(&ref
);
1123 hidden_ass
->warning("Hidden definition `%s' is here",
1124 hidden_ass
->get_fullname().c_str());
1130 RunsOnScope
*RunsOnScope::get_scope_runs_on()
1135 Common::Assignment
*RunsOnScope::get_ass_bySRef(Ref_simple
*p_ref
)
1137 if (!p_ref
) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1138 if (p_ref
->get_modid()) return parent_scope
->get_ass_bySRef(p_ref
);
1140 const Identifier
& id
= *p_ref
->get_id();
1141 if (component_defs
->has_local_ass_withId(id
)) {
1142 Common::Assignment
* ass
= component_defs
->get_local_ass_byId(id
);
1143 if (!ass
) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1145 if (component_defs
->is_own_assignment(ass
)) return ass
;
1146 else if (ass
->get_visibility() == PUBLIC
) {
1150 p_ref
->error("The member definition `%s' in component type `%s'"
1151 " is not visible in this scope", id
.get_dispname().c_str(),
1152 component_defs
->get_id()->get_dispname().c_str());
1154 } else return parent_scope
->get_ass_bySRef(p_ref
);
1158 bool RunsOnScope::has_ass_withId(const Identifier
& p_id
)
1160 return component_defs
->has_ass_withId(p_id
)
1161 || parent_scope
->has_ass_withId(p_id
);
1164 // =================================
1166 // =================================
1168 FriendMod::FriendMod(Identifier
*p_modid
)
1169 : Node(), modid(p_modid
), w_attrib_path(0), parentgroup(0), checked(false)
1171 if (!p_modid
) FATAL_ERROR("NULL parameter: Ttcn::FriendMod::FriendMod()");
1172 set_fullname("<friends>."+modid
->get_dispname());
1175 FriendMod::~FriendMod()
1179 delete w_attrib_path
;
1182 FriendMod
*FriendMod::clone() const
1184 FATAL_ERROR("Ttcn::FriendMod::clone()");
1187 void FriendMod::set_fullname(const string
& p_fullname
)
1189 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
1192 void FriendMod::chk()
1194 if (checked
) return;
1196 Error_Context
cntxt(this, "In friend module declaration");
1198 if (w_attrib_path
) {
1199 w_attrib_path
->chk_global_attrib();
1200 w_attrib_path
->chk_no_qualif();
1206 void FriendMod::set_with_attr(MultiWithAttrib
* p_attrib
)
1208 if (w_attrib_path
) FATAL_ERROR("FriendMod::set_with_attr()");
1209 w_attrib_path
= new WithAttribPath();
1210 if (p_attrib
&& p_attrib
->get_nof_elements() > 0) {
1211 w_attrib_path
->set_with_attr(p_attrib
);
1215 WithAttribPath
* FriendMod::get_attrib_path()
1217 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1218 return w_attrib_path
;
1221 void FriendMod::set_parent_path(WithAttribPath
* p_path
)
1223 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1224 w_attrib_path
->set_parent(p_path
);
1227 void FriendMod::set_parent_group(Group
* p_group
)
1229 if(parentgroup
) FATAL_ERROR("FriendMod::set_parent_group");
1230 parentgroup
= p_group
;
1233 // =================================
1235 // =================================
1237 ImpMod::ImpMod(Identifier
*p_modid
)
1238 : Node(), mod(0), my_mod(0), imptype(I_UNDEF
), modid(p_modid
),
1239 language_spec(0), is_recursive(false),
1240 w_attrib_path(0), parentgroup(0), visibility(PRIVATE
)
1242 if (!p_modid
) FATAL_ERROR("NULL parameter: Ttcn::ImpMod::ImpMod()");
1243 set_fullname("<imports>." + modid
->get_dispname());
1249 delete language_spec
;
1251 delete w_attrib_path
;
1254 ImpMod
*ImpMod::clone() const
1256 FATAL_ERROR("No clone for you!");
1259 void ImpMod::set_fullname(const string
& p_fullname
)
1261 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
1266 if (w_attrib_path
) {
1267 w_attrib_path
->chk_global_attrib();
1268 w_attrib_path
->chk_no_qualif();
1272 void ImpMod::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
1274 Error_Context
cntxt(this, "In import definition");
1276 if (!modules
->has_mod_withId(*modid
)) {
1277 error("There is no module with identifier `%s'",
1278 modid
->get_dispname().c_str());
1282 Common::Module
*m
= modules
->get_mod_byId(*modid
);
1288 error("A module cannot import from itself");
1296 if (refch
.exists(my_mod
->get_fullname())) {
1297 if(my_mod
->get_moduletype()!=Common::Module::MOD_ASN
){ // Do not warning for circular import in ASN.1 module. It is legal
1298 my_mod
->warning("Circular import chain is not recommended: %s",
1299 refch
.get_dispstr(my_mod
->get_fullname()).c_str());
1304 refch
.add(my_mod
->get_fullname());
1306 if (ImpMod::I_IMPORTIMPORT
== imptype
){
1307 Ttcn::Module
* ttcnmodule
=static_cast<Ttcn::Module
*>(m
);
1308 const Imports
& imp
= ttcnmodule
->get_imports();
1310 for (size_t t
= 0; t
< imp
.impmods_v
.size(); t
++) {
1311 const ImpMod
*im
= imp
.impmods_v
[t
];
1312 const Identifier
& im_id
= im
->get_modid();
1313 Common::Module
*cm
= modules
->get_mod_byId(im_id
); // never NULL
1316 if (PRIVATE
!= im
->get_visibility()) {
1317 if (refch
.exists(m
->get_fullname())) {
1318 if(m
->get_moduletype()!=Common::Module::MOD_ASN
){ // Do not warning for circular import in ASN.1 module. It is legal
1319 m
->warning("Circular import chain is not recommended: %s",
1320 refch
.get_dispstr(m
->get_fullname()).c_str());
1325 refch
.add(m
->get_fullname());
1326 cm
->chk_imp(refch
, moduleStack
);
1332 //refch.mark_state();
1333 m
->chk_imp(refch
, moduleStack
);
1334 //refch.prev_state();
1339 size_t state
=moduleStack
.size();
1340 moduleStack
.replace(state
, moduleStack
.size() - state
);
1343 bool ImpMod::has_imported_def(const Identifier
& p_source_modid
,
1344 const Identifier
& p_id
, const Location
*loc
) const
1346 if (!mod
) return false;
1352 Common::Assignment
* return_assignment
= mod
->importAssignment(p_source_modid
, p_id
);
1353 if (return_assignment
!= NULL
) {
1360 case I_IMPORTIMPORT
:
1362 Ttcn::Module
*tm
= static_cast<Ttcn::Module
*>(mod
); // B
1364 const Imports
& imps
= tm
->get_imports();
1366 vector
<ImpMod
> tempusedImpMods
;
1367 for (size_t i
= 0, num
= imps
.impmods_v
.size(); i
< num
; ++i
) {
1368 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
1369 Common::Assignment
* return_assignment
= imps
.impmods_v
[i
]->
1370 get_imported_def(p_source_modid
, p_id
, loc
, referencechain
, tempusedImpMods
); // C
1371 referencechain
->reset();
1372 delete referencechain
;
1374 if (return_assignment
!= NULL
) {
1380 //satisfy destructor
1381 tempusedImpMods
.clear();
1386 FATAL_ERROR("ImpMod::get_imported_def");
1392 Common::Assignment
*ImpMod::get_imported_def(
1393 const Identifier
& p_source_modid
, const Identifier
& p_id
,
1394 const Location
*loc
, ReferenceChain
* refch
,
1395 vector
<ImpMod
>& usedImpMods
) const
1400 Common::Assignment
* result
= NULL
;
1405 result
= mod
->importAssignment(p_source_modid
, p_id
);
1406 if (result
!= NULL
) {
1407 usedImpMods
.add(const_cast<Ttcn::ImpMod
*>(this));
1411 case I_IMPORTIMPORT
:
1413 Ttcn::Module
*tm
= static_cast<Ttcn::Module
*>(mod
);
1415 const Imports
& imps
= tm
->get_imports();
1416 Common::Assignment
* t_ass
= NULL
;
1418 for (size_t i
= 0, num
= imps
.impmods_v
.size(); i
< num
; ++i
) {
1419 vector
<ImpMod
> tempusedImpMods
;
1421 refch
->mark_state();
1422 if (imps
.impmods_v
[i
]->get_visibility() == PUBLIC
) {
1423 t_ass
= imps
.impmods_v
[i
]->get_imported_def(p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1425 else if (imps
.impmods_v
[i
]->get_visibility() == FRIEND
) {
1426 t_ass
= imps
.impmods_v
[i
]->get_imported_def(p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1428 tempusedImpMods
.add(imps
.impmods_v
[i
]);
1431 refch
->prev_state();
1433 if (t_ass
!= NULL
) {
1434 bool visible
= true;
1435 for (size_t j
= 0; j
< tempusedImpMods
.size(); j
++) {
1436 ImpMod
* impmod_l
= tempusedImpMods
[j
];
1437 //check whether the module is TTCN
1438 if (impmod_l
->get_mod()->get_moduletype() == Common::Module::MOD_TTCN
) {
1439 // cast to ttcn module
1440 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(impmod_l
->get_mod());
1441 if (!ttcn_m
->is_visible(mod
->get_modid(), impmod_l
->get_visibility())) {
1447 for (size_t t
= 0; i
< tempusedImpMods
.size(); i
++) {
1448 usedImpMods
.add(tempusedImpMods
[t
]);
1453 } else if(result
!= t_ass
) {
1458 "It is not possible to resolve the reference unambiguously"
1459 ", as it can be resolved to `%s' and to `%s'",
1460 result
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
1466 tempusedImpMods
.clear();
1469 if (result
!= NULL
) {
1470 usedImpMods
.add(const_cast<Ttcn::ImpMod
*>(this));
1476 FATAL_ERROR("ImpMod::get_imported_def");
1481 void ImpMod::set_language_spec(const char *p_language_spec
)
1483 if (language_spec
) FATAL_ERROR("ImpMod::set_language_spec()");
1484 if (p_language_spec
) language_spec
= new string(p_language_spec
);
1487 void ImpMod::generate_code(output_struct
*target
)
1489 const char *module_name
= modid
->get_name().c_str();
1491 target
->header
.includes
= mputprintf(target
->header
.includes
,
1492 "#include \"%s.hh\"\n",
1493 duplicate_underscores
? module_name
: modid
->get_ttcnname().c_str());
1495 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
1496 "%s%s.pre_init_module();\n", module_name
,
1499 if (mod
->get_moduletype() == Common::Module::MOD_TTCN
) {
1500 target
->functions
.post_init
= mputprintf(target
->functions
.post_init
,
1501 "%s%s.post_init_module();\n", module_name
,
1507 void ImpMod::dump(unsigned level
) const
1509 DEBUG(level
, "Import from module %s", modid
->get_dispname().c_str());
1510 if (w_attrib_path
) {
1511 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
1513 DEBUG(level
+ 1, "Attributes:");
1514 attrib
->dump(level
+ 2);
1519 void ImpMod::set_with_attr(MultiWithAttrib
* p_attrib
)
1521 if (w_attrib_path
) FATAL_ERROR("ImpMod::set_with_attr()");
1522 w_attrib_path
= new WithAttribPath();
1523 if (p_attrib
&& p_attrib
->get_nof_elements() > 0) {
1524 w_attrib_path
->set_with_attr(p_attrib
);
1528 WithAttribPath
* ImpMod::get_attrib_path()
1530 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1531 return w_attrib_path
;
1534 void ImpMod::set_parent_path(WithAttribPath
* p_path
)
1536 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1537 w_attrib_path
->set_parent(p_path
);
1540 void ImpMod::set_parent_group(Group
* p_group
)
1542 if(parentgroup
) FATAL_ERROR("ImpMod::set_parent_group");
1543 parentgroup
= p_group
;
1546 // =================================
1548 // =================================
1552 for (size_t i
= 0; i
< impmods_v
.size(); i
++)
1553 delete impmods_v
[i
];
1557 Imports
*Imports::clone() const
1559 FATAL_ERROR("Ttcn::Imports::clone()");
1562 void Imports::add_impmod(ImpMod
*p_impmod
)
1564 if (!p_impmod
) FATAL_ERROR("Ttcn::Imports::add_impmod()");
1565 impmods_v
.add(p_impmod
);
1566 p_impmod
->set_my_mod(my_mod
);
1569 void Imports::set_my_mod(Module
*p_mod
)
1572 for(size_t i
= 0; i
< impmods_v
.size(); i
++)
1573 impmods_v
[i
]->set_my_mod(my_mod
);
1576 bool Imports::has_impmod_withId(const Identifier
& p_id
) const
1578 for (size_t i
= 0, size
= impmods_v
.size(); i
< size
; ++i
) {
1579 const ImpMod
* im
= impmods_v
[i
];
1580 const Identifier
& im_id
= im
->get_modid();
1581 const string
& im_name
= im_id
.get_name();
1582 if (p_id
.get_name() == im_name
) {
1583 // The identifier represents a module imported in the current module
1590 void Imports::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
1592 if (impmods_v
.size() <= 0) return;
1594 if (!my_mod
) FATAL_ERROR("Ttcn::Imports::chk_imp()");
1599 for(size_t n
= 0; n
< impmods_v
.size(); n
++)
1601 impmods_v
[n
]->chk();
1604 //TODO this whole thing should be moved into impmod::chk
1605 Identifier
address_id(Identifier::ID_TTCN
, string("address"));
1606 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1607 ImpMod
*im
= impmods_v
[n
];
1608 im
->chk_imp(refch
, moduleStack
);
1610 const Identifier
& im_id
= im
->get_modid();
1611 Common::Module
*m
= modules
->get_mod_byId(im_id
);
1614 if (m
->get_gen_code()) my_mod
->set_gen_code();
1615 } // next assignment
1618 bool Imports::has_imported_def(const Identifier
& p_id
, const Location
*loc
) const
1620 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1621 ImpMod
*im
= impmods_v
[n
];
1622 bool return_bool
= im
->has_imported_def(my_mod
->get_modid(), p_id
, loc
);
1623 if (return_bool
) return true;
1628 Common::Assignment
*Imports::get_imported_def(
1629 const Identifier
& p_source_modid
, const Identifier
& p_id
,
1630 const Location
*loc
, ReferenceChain
* refch
)
1632 vector
<ImpMod
> tempusedImpMods
;
1633 Common::Assignment
* result
= NULL
;
1634 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1635 ImpMod
*im
= impmods_v
[n
];
1636 refch
->mark_state();
1637 Common::Assignment
* ass
= im
->get_imported_def(
1638 p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1639 tempusedImpMods
.clear();
1640 refch
->prev_state();
1645 } else if(result
!= ass
&& loc
) {
1650 "It is not possible to resolve the reference unambiguously"
1651 ", as it can be resolved to `%s' and to `%s'",
1652 result
->get_fullname().c_str(), ass
->get_fullname().c_str());
1660 void Imports::get_imported_mods(Module::module_set_t
& p_imported_mods
) const
1662 for (size_t i
= 0; i
< impmods_v
.size(); i
++) {
1663 ImpMod
*im
= impmods_v
[i
];
1664 Common::Module
*m
= im
->get_mod();
1666 if (!p_imported_mods
.has_key(m
)) {
1667 p_imported_mods
.add(m
, 0);
1668 m
->get_visible_mods(p_imported_mods
);
1673 void Imports::generate_code(output_struct
*target
)
1675 target
->header
.includes
= mputstr(target
->header
.includes
,
1676 "#include <TTCN3.hh>\n");
1677 /*if (debugger_active) {
1678 target->header.includes = mputstr(target->header.includes,
1679 "#include \"init_debug.inc\"\n");
1681 for (size_t i
= 0; i
< impmods_v
.size(); i
++) {
1682 ImpMod
*im
= impmods_v
[i
];
1683 Common::Module
*m
= im
->get_mod();
1684 // inclusion of m's header file can be eliminated if we find another
1685 // imported module that imports m
1686 bool covered
= false;
1687 for (size_t j
= 0; j
< impmods_v
.size(); j
++) {
1688 // skip over the same import definition
1689 if (j
== i
) continue;
1690 ImpMod
*im2
= impmods_v
[j
];
1691 Common::Module
*m2
= im2
->get_mod();
1692 // a module that is equivalent to the current module due to
1693 // circular imports cannot be used to cover anything
1694 if (m2
->is_visible(my_mod
)) continue;
1695 if (m2
->is_visible(m
) && !m
->is_visible(m2
)) {
1696 // m2 covers m (i.e. m is visible from m2)
1697 // and they are not in the same import loop
1702 // do not generate the #include if a covering module is found
1703 if (!covered
) im
->generate_code(target
);
1707 void Imports::generate_code(CodeGenHelper
& cgh
) {
1708 generate_code(cgh
.get_current_outputstruct());
1711 void Imports::dump(unsigned level
) const
1713 DEBUG(level
, "Imports (%lu pcs.)", (unsigned long) impmods_v
.size());
1714 for (size_t i
= 0; i
< impmods_v
.size(); i
++)
1715 impmods_v
[i
]->dump(level
+ 1);
1718 // =================================
1719 // ===== Definitions
1720 // =================================
1722 Definitions::~Definitions()
1724 for(size_t i
= 0; i
< ass_v
.size(); i
++) delete ass_v
[i
];
1729 Definitions
*Definitions::clone() const
1731 FATAL_ERROR("Definitions::clone");
1734 void Definitions::add_ass(Definition
*p_ass
)
1736 // it is too late to add a new one after it has been checked.
1737 if (checked
|| !p_ass
) FATAL_ERROR("Ttcn::OtherDefinitions::add_ass()");
1739 p_ass
->set_my_scope(this);
1742 void Definitions::set_fullname(const string
& p_fullname
)
1744 Common::Assignments::set_fullname(p_fullname
);
1745 for(size_t i
= 0; i
< ass_v
.size(); i
++) {
1746 Definition
*ass
= ass_v
[i
];
1747 ass
->set_fullname(p_fullname
+ "." + ass
->get_id().get_dispname());
1751 bool Definitions::has_local_ass_withId(const Identifier
& p_id
)
1753 if (!checked
) chk_uniq();
1754 return ass_m
.has_key(p_id
.get_name());
1757 Common::Assignment
* Definitions::get_local_ass_byId(const Identifier
& p_id
)
1759 if (!checked
) chk_uniq();
1760 return ass_m
[p_id
.get_name()];
1763 size_t Definitions::get_nof_asss()
1765 if (!checked
) chk_uniq();
1766 return ass_m
.size();
1769 size_t Definitions::get_nof_raw_asss()
1771 return ass_v
.size();
1774 Common::Assignment
* Definitions::get_ass_byIndex(size_t p_i
)
1776 if (!checked
) chk_uniq();
1777 return ass_m
.get_nth_elem(p_i
);
1780 Ttcn::Definition
* Definitions::get_raw_ass_byIndex(size_t p_i
) {
1784 void Definitions::chk_uniq()
1786 if (checked
) return;
1788 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1789 Definition
*ass
= ass_v
[i
];
1790 const Identifier
& id
= ass
->get_id();
1791 const string
& name
= id
.get_name();
1792 if (ass_m
.has_key(name
)) {
1793 const char *dispname_str
= id
.get_dispname().c_str();
1794 ass
->error("Duplicate definition with name `%s'", dispname_str
);
1795 ass_m
[name
]->note("Previous definition of `%s' is here", dispname_str
);
1797 ass_m
.add(name
, ass
);
1798 if (parent_scope
->is_valid_moduleid(id
)) {
1799 ass
->warning("Definition with name `%s' hides a module identifier",
1800 id
.get_dispname().c_str());
1807 void Definitions::chk()
1809 for (size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->chk();
1812 void Definitions::chk_for()
1814 if (checked
) return;
1817 // all checks are done in one iteration because
1818 // forward referencing is not allowed between the definitions
1819 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1820 Definition
*def
= ass_v
[i
];
1821 const Identifier
& id
= def
->get_id();
1822 const string
& name
= id
.get_name();
1823 if (ass_m
.has_key(name
)) {
1824 const char *dispname_str
= id
.get_dispname().c_str();
1825 def
->error("Duplicate definition with name `%s'", dispname_str
);
1826 ass_m
[name
]->note("Previous definition of `%s' is here", dispname_str
);
1828 ass_m
.add(name
, def
);
1830 if (parent_scope
->has_ass_withId(id
)) {
1831 const char *dispname_str
= id
.get_dispname().c_str();
1832 def
->error("Definition with identifier `%s' is not unique in the "
1833 "scope hierarchy", dispname_str
);
1834 Reference
ref(0, id
.clone());
1835 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
1836 if (!ass
) FATAL_ERROR("OtherDefinitions::chk_for()");
1837 ass
->note("Previous definition with identifier `%s' in higher "
1838 "scope unit is here", dispname_str
);
1839 } else if (parent_scope
->is_valid_moduleid(id
)) {
1840 def
->warning("Definition with name `%s' hides a module identifier",
1841 id
.get_dispname().c_str());
1849 void Definitions::set_genname(const string
& prefix
)
1851 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1852 Definition
*def
= ass_v
[i
];
1853 def
->set_genname(prefix
+ def
->get_id().get_name());
1857 void Definitions::generate_code(output_struct
* target
)
1859 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->generate_code(target
);
1862 void Definitions::generate_code(CodeGenHelper
& cgh
) {
1864 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->generate_code(cgh
);
1867 char* Definitions::generate_code_str(char *str
)
1869 for(size_t i
=0; i
<ass_v
.size(); i
++) {
1870 str
= ass_v
[i
]->update_location_object(str
);
1871 str
=ass_v
[i
]->generate_code_str(str
);
1876 void Definitions::ilt_generate_code(ILT
*ilt
)
1878 for(size_t i
=0; i
<ass_v
.size(); i
++)
1879 ass_v
[i
]->ilt_generate_code(ilt
);
1883 void Definitions::dump(unsigned level
) const
1885 DEBUG(level
, "Definitions: (%lu pcs.)", (unsigned long) ass_v
.size());
1886 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->dump(level
+ 1);
1889 // =================================
1891 // =================================
1893 Group::Group(Identifier
*p_id
)
1894 : Node(), Location(), parent_group(0), w_attrib_path(0), id(p_id
),
1897 if (!p_id
) FATAL_ERROR("Group::Group()");
1902 delete w_attrib_path
;
1905 for (size_t i
= 0; i
< group_v
.size(); i
++) delete group_v
[i
];
1909 friendmods_v
.clear();
1913 Group
* Group::clone() const
1915 FATAL_ERROR("Ttcn::Group::clone()");
1918 void Group::set_fullname(const string
& p_fullname
)
1920 Node::set_fullname(p_fullname
);
1921 for(size_t i
= 0; i
< group_v
.size() ; i
++)
1923 group_v
[i
]->set_fullname(p_fullname
+ ".<group " + Int2string(i
) + ">");
1925 if (w_attrib_path
) w_attrib_path
->set_fullname( p_fullname
1929 void Group::add_ass(Definition
* p_ass
)
1932 p_ass
->set_parent_group(this);
1935 void Group::add_group(Group
* p_group
)
1937 group_v
.add(p_group
);
1940 void Group::set_parent_group(Group
* p_parent_group
)
1942 if (parent_group
) FATAL_ERROR("Group::set_parent_group()");
1943 parent_group
= p_parent_group
;
1946 void Group::set_with_attr(MultiWithAttrib
* p_attrib
)
1948 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1949 w_attrib_path
->set_with_attr(p_attrib
);
1952 WithAttribPath
* Group::get_attrib_path()
1954 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1955 return w_attrib_path
;
1958 void Group::set_parent_path(WithAttribPath
* p_path
)
1960 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1961 w_attrib_path
->set_parent(p_path
);
1964 void Group::chk_uniq()
1966 if (checked
) return;
1970 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1971 Definition
*ass
= ass_v
[i
];
1972 const string
& ass_name
= ass
->get_id().get_name();
1973 if (!ass_m
.has_key(ass_name
)) ass_m
.add(ass_name
, ass
);
1976 for(size_t i
= 0; i
< group_v
.size(); i
++) {
1977 Group
*group
= group_v
[i
];
1978 const Identifier
& group_id
= group
->get_id();
1979 const string
& group_name
= group_id
.get_name();
1980 if (ass_m
.has_key(group_name
)) {
1981 group
->error("Group name `%s' clashes with a definition",
1982 group_id
.get_dispname().c_str());
1983 ass_m
[group_name
]->note("Definition of `%s' is here",
1984 group_id
.get_dispname().c_str());
1986 if (group_m
.has_key(group_name
)) {
1987 group
->error("Duplicate group with name `%s'",
1988 group_id
.get_dispname().c_str());
1989 group_m
[group_name
]->note("Group `%s' is already defined here",
1990 group_id
.get_dispname().c_str());
1991 } else group_m
.add(group_name
, group
);
1998 Error_Context
cntxt(this, "In group `%s'", id
->get_dispname().c_str());
2002 if (w_attrib_path
) {
2003 w_attrib_path
->chk_global_attrib();
2004 w_attrib_path
->chk_no_qualif();
2007 for(size_t i
= 0; i
< group_v
.size(); i
++) group_v
[i
]->chk();
2010 void Group::add_impmod(ImpMod
*p_impmod
)
2012 impmods_v
.add(p_impmod
);
2013 p_impmod
->set_parent_group(this);
2016 void Group::add_friendmod(FriendMod
*p_friendmod
)
2018 friendmods_v
.add(p_friendmod
);
2019 p_friendmod
->set_parent_group(this);
2022 void Group::dump(unsigned level
) const
2024 DEBUG(level
, "Group: %s", id
->get_dispname().c_str());
2025 DEBUG(level
+ 1, "Nested groups: (%lu pcs.)",
2026 (unsigned long) group_v
.size());
2027 for(size_t i
= 0; i
< group_v
.size(); i
++) group_v
[i
]->dump(level
+ 2);
2028 DEBUG(level
+ 1, "Nested definitions: (%lu pcs.)",
2029 (unsigned long) ass_v
.size());
2030 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->dump(level
+ 2);
2031 DEBUG(level
+ 1, "Nested imports: (%lu pcs.)",
2032 (unsigned long) impmods_v
.size());
2033 for(size_t i
= 0; i
< impmods_v
.size(); i
++) impmods_v
[i
]->dump(level
+ 2);
2034 if (w_attrib_path
) {
2035 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2037 DEBUG(level
+ 1, "Group Attributes:");
2038 attrib
->dump(level
+ 2);
2043 // =================================
2044 // ===== ControlPart
2045 // =================================
2047 ControlPart::ControlPart(StatementBlock
* p_block
)
2048 : Node(), Location(), block(p_block
), w_attrib_path(0)
2050 if (!p_block
) FATAL_ERROR("ControlPart::ControlPart()");
2053 ControlPart::~ControlPart()
2056 delete w_attrib_path
;
2059 ControlPart
* ControlPart::clone() const
2061 FATAL_ERROR("ControlPart::clone");
2064 void ControlPart::set_fullname(const string
& p_fullname
)
2066 block
->set_fullname(p_fullname
);
2067 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
2070 void ControlPart::set_my_scope(Scope
*p_scope
)
2072 bridgeScope
.set_parent_scope(p_scope
);
2073 string
temp("control");
2074 bridgeScope
.set_scopeMacro_name(temp
);
2076 block
->set_my_scope(&bridgeScope
);
2079 void ControlPart::chk()
2081 Error_Context
cntxt(this, "In control part");
2083 if (!semantic_check_only
)
2084 block
->set_code_section(GovernedSimple::CS_INLINE
);
2085 if (w_attrib_path
) {
2086 w_attrib_path
->chk_global_attrib();
2087 w_attrib_path
->chk_no_qualif();
2091 void ControlPart::generate_code(output_struct
*target
, Module
*my_module
)
2093 const char *module_dispname
= my_module
->get_modid().get_dispname().c_str();
2094 target
->functions
.control
=
2095 create_location_object(target
->functions
.control
, "CONTROLPART",
2097 target
->functions
.control
= mputprintf(target
->functions
.control
,
2098 "TTCN_Runtime::begin_controlpart(\"%s\");\n", module_dispname
);
2099 if (debugger_active
) {
2100 target
->functions
.control
= mputprintf(target
->functions
.control
,
2101 "charstring_list no_params = NULL_VALUE;\n"
2102 "TTCN3_Debug_Function debug_scope(NULL, \"control\", \"%s\", no_params, no_params, NULL);\n"
2103 "debug_scope.initial_snapshot();\n", module_dispname
);
2105 target
->functions
.control
=
2106 block
->generate_code(target
->functions
.control
);
2107 target
->functions
.control
= mputstr(target
->functions
.control
,
2108 "TTCN_Runtime::end_controlpart();\n");
2111 void ControlPart::set_with_attr(MultiWithAttrib
* p_attrib
)
2113 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2114 w_attrib_path
->set_with_attr(p_attrib
);
2117 WithAttribPath
* ControlPart::get_attrib_path()
2119 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2120 return w_attrib_path
;
2123 void ControlPart::set_parent_path(WithAttribPath
* p_path
)
2125 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2126 w_attrib_path
->set_parent(p_path
);
2127 block
->set_parent_path(w_attrib_path
);
2130 void ControlPart::dump(unsigned level
) const
2132 DEBUG(level
, "Control part");
2133 block
->dump(level
+ 1);
2134 if (w_attrib_path
) {
2135 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2137 DEBUG(level
+ 1, "Attributes:");
2138 attrib
->dump(level
+ 2);
2143 // =================================
2145 // =================================
2147 Module::Module(Identifier
*p_modid
)
2148 : Common::Module(MOD_TTCN
, p_modid
), language_spec(0), w_attrib_path(0),
2151 asss
= new Definitions();
2152 asss
->set_parent_scope(this);
2153 imp
= new Imports();
2154 imp
->set_my_mod(this);
2155 //modified_encodings = true; // Assume always true for TTCN modules
2160 delete language_spec
;
2162 for (size_t i
= 0; i
< group_v
.size(); i
++) delete group_v
[i
];
2166 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) delete friendmods_v
[i
];
2167 friendmods_v
.clear();
2169 for (size_t i
= 0; i
< runs_on_scopes
.size(); i
++)
2170 delete runs_on_scopes
[i
];
2171 runs_on_scopes
.clear();
2172 delete w_attrib_path
;
2175 void Module::add_group(Group
* p_group
)
2177 group_v
.add(p_group
);
2180 void Module::add_friendmod(FriendMod
*p_friendmod
)
2182 friendmods_v
.add(p_friendmod
);
2183 p_friendmod
->set_my_mod(this);
2186 Module
*Module::clone() const
2188 FATAL_ERROR("Ttcn::Module::clone()");
2191 Common::Assignment
*Module::importAssignment(const Identifier
& p_modid
,
2192 const Identifier
& p_id
) const
2194 if (asss
->has_local_ass_withId(p_id
)) {
2195 Common::Assignment
* ass
= asss
->get_local_ass_byId(p_id
);
2196 if (!ass
) FATAL_ERROR("Ttcn::Module::importAssignment()");
2198 switch(ass
->get_visibility()) {
2200 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) {
2201 if (friendmods_v
[i
]->get_modid() == p_modid
) return ass
;
2209 FATAL_ERROR("Ttcn::Module::importAssignment()");
2215 void Module::set_fullname(const string
& p_fullname
)
2217 Node::set_fullname(p_fullname
);
2218 asss
->set_fullname(p_fullname
);
2219 if (controlpart
) controlpart
->set_fullname(p_fullname
+ ".control");
2220 for(size_t i
= 0; i
< group_v
.size(); i
++)
2222 group_v
[i
]->set_fullname(p_fullname
+ ".<group " + Int2string(i
) + ">");
2224 if (w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
2228 Common::Assignments
*Module::get_scope_asss()
2233 bool Module::has_imported_ass_withId(const Identifier
& p_id
)
2235 const Location
*loc
= NULL
;
2236 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2237 const ImpMod
* im
= imp
->get_impmod(i
);
2238 //TODO use a reference instead of an identifier
2239 if(im
->has_imported_def(*modid
, p_id
, loc
)) return true;
2244 Common::Assignment
* Module::get_ass_bySRef(Ref_simple
*p_ref
)
2246 const Identifier
*r_modid
= p_ref
->get_modid();
2247 const Identifier
*r_id
= p_ref
->get_id();
2249 // the reference contains a module name
2250 if (r_modid
->get_name() != modid
->get_name()) {
2251 // the reference points to another module
2252 bool has_impmod_with_name
= false;
2253 Common::Assignment
* result_ass
= NULL
;
2254 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2255 const ImpMod
* im
= imp
->get_impmod(i
);
2256 const Identifier
& im_id
= im
->get_modid();
2257 const string
& im_name
= im_id
.get_name();
2258 if (r_modid
->get_name() == im_name
) {
2259 has_impmod_with_name
= true;
2260 vector
<ImpMod
> tempusedImpMods
;
2261 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2262 Common::Assignment
*t_ass
= im
->get_imported_def(*modid
, *r_id
, p_ref
, referencechain
, tempusedImpMods
);
2263 referencechain
->reset();
2264 delete referencechain
;
2266 if (t_ass
!= NULL
) {
2267 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(im
->get_mod());
2268 if (!ttcn_m
->is_visible(*modid
, t_ass
->get_visibility())) {
2272 if (t_ass
!= NULL
) {
2273 if (result_ass
== NULL
) {
2275 } else if(result_ass
!= t_ass
) {
2277 "It is not possible to resolve the reference unambiguously"
2278 ", as it can be resolved to `%s' and to `%s'",
2279 result_ass
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
2283 tempusedImpMods
.clear();
2286 if (result_ass
) return result_ass
;
2288 if (has_impmod_with_name
) {
2289 p_ref
->error("There is no definition with name `%s' visible from "
2290 "module `%s'", r_id
->get_dispname().c_str(),
2291 r_modid
->get_dispname().c_str());
2293 if (modules
->has_mod_withId(*r_modid
)) {
2294 Common::Module
*m
= modules
->get_mod_byId(*r_modid
);
2295 if (m
->get_asss()->has_ass_withId(*r_id
)) {
2296 p_ref
->error("Definition with name `%s' is not imported from "
2297 "module `%s'", r_id
->get_dispname().c_str(),
2298 r_modid
->get_dispname().c_str());
2300 p_ref
->error("There is no definition with name `%s' in "
2301 "module `%s'", r_id
->get_dispname().c_str(),
2302 r_modid
->get_dispname().c_str());
2305 p_ref
->error("There is no module with name `%s'",
2306 r_modid
->get_dispname().c_str());
2311 // the reference points to the own module
2312 if (asss
->has_local_ass_withId(*r_id
)) {
2313 return asss
->get_local_ass_byId(*r_id
);
2315 p_ref
->error("There is no definition with name `%s' in "
2316 "module `%s'", r_id
->get_dispname().c_str(),
2317 r_modid
->get_dispname().c_str());
2321 // no module name is given in the reference
2322 if (asss
->has_local_ass_withId(*r_id
)) {
2323 return asss
->get_local_ass_byId(*r_id
);
2325 // the reference was not found locally -> look at the import list
2326 Common::Assignment
*t_result
= NULL
, *t_ass
= NULL
;
2327 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2328 const ImpMod
* im
= imp
->get_impmod(i
);
2330 vector
<ImpMod
> tempusedImpMods
;
2331 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2332 t_ass
= im
->get_imported_def(*modid
, *r_id
, p_ref
, referencechain
, tempusedImpMods
);
2333 referencechain
->reset();
2335 delete referencechain
;
2336 if (t_ass
!= NULL
) {
2337 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(im
->get_mod());
2338 if (!ttcn_m
->is_visible(*modid
, t_ass
->get_visibility())) {
2342 if (t_ass
!= NULL
) {
2343 if (t_result
== NULL
) {
2345 } else if(t_result
!= t_ass
) {
2347 "It is not possible to resolve the reference unambiguously"
2348 ", as it can be resolved to `%s' and to `%s'",
2349 t_result
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
2353 tempusedImpMods
.clear();
2356 if (t_result
) return t_result
;
2358 p_ref
->error("There is no local or imported definition with name `%s'"
2359 ,r_id
->get_dispname().c_str());
2365 bool Module::is_valid_moduleid(const Identifier
& p_id
)
2367 // The identifier represents the current module
2368 if (p_id
.get_name() == modid
->get_name()) return true;
2369 // The identifier represents a module imported in the current module
2370 if(imp
->has_impmod_withId(p_id
)) return true;
2374 Common::Assignments
*Module::get_asss()
2379 bool Module::exports_sym(const Identifier
&)
2381 FATAL_ERROR("Ttcn::Module::exports_sym()");
2385 Type
*Module::get_address_type()
2387 Identifier
address_id(Identifier::ID_TTCN
, string("address"));
2388 // return NULL if address type is not defined
2389 if (!asss
->has_local_ass_withId(address_id
)) return 0;
2390 Common::Assignment
*t_ass
= asss
->get_local_ass_byId(address_id
);
2391 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
)
2392 FATAL_ERROR("Module::get_address_type(): address is not a type");
2393 return t_ass
->get_Type();
2396 void Module::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
2398 if (imp_checked
) return;
2399 const string
& module_name
= modid
->get_dispname();
2401 Error_Context backup
;
2402 Error_Context
cntxt(this, "In TTCN-3 module `%s'", module_name
.c_str());
2403 imp
->chk_imp(refch
, moduleStack
);
2406 collect_visible_mods();
2411 DEBUG(1, "Checking TTCN-3 module `%s'", modid
->get_dispname().c_str());
2412 Error_Context
cntxt(this, "In TTCN-3 module `%s'",
2413 modid
->get_dispname().c_str());
2414 if (w_attrib_path
) {
2415 w_attrib_path
->chk_global_attrib();
2416 w_attrib_path
->chk_no_qualif();
2418 // Check "extension" attributes in the module's "with" statement
2419 MultiWithAttrib
*multi
= w_attrib_path
->get_with_attr();
2420 if (multi
) for (size_t i
= 0; i
< multi
->get_nof_elements(); ++i
) {
2421 const SingleWithAttrib
*single
= multi
->get_element(i
);
2422 if (single
->get_attribKeyword() != SingleWithAttrib::AT_EXTENSION
) continue;
2423 // Parse the extension attribute
2424 // We circumvent parse_extattributes() in coding_attrib_p.y because
2425 // it processes all attributes in the "with" statement and
2426 // doesn't allow the removal on a case-by-case basis.
2428 init_coding_attrib_lex(single
->get_attribSpec());
2429 int result
= coding_attrib_parse();// 0=OK, 1=error, 2=out of memory
2430 cleanup_coding_attrib_lex();
2437 const size_t num_parsed
= extatrs
->size();
2438 for (size_t a
= 0; a
< num_parsed
; ++a
) {
2439 Ttcn::ExtensionAttribute
& ex
= extatrs
->get(0);
2441 switch (ex
.get_type()) {
2442 case Ttcn::ExtensionAttribute::VERSION_TEMPLATE
:
2443 case Ttcn::ExtensionAttribute::VERSION
: {
2444 char* act_product_number
;
2445 unsigned int act_suffix
, act_rel
, act_patch
, act_build
;
2447 (void)ex
.get_id(act_product_number
, act_suffix
, act_rel
, act_patch
, act_build
, extra_junk
);
2449 if (release
!= UINT_MAX
) {
2450 ex
.error("Duplicate 'version' attribute");
2453 product_number
= mcopystr(act_product_number
);
2454 suffix
= act_suffix
;
2458 extra
= mcopystr(extra_junk
);
2460 // Avoid propagating the attribute needlessly
2461 multi
->delete_element(i
--);
2465 case Ttcn::ExtensionAttribute::REQUIRES
: {
2466 // Imports have already been checked
2467 char* exp_product_number
;
2468 unsigned int exp_suffix
, exp_rel
, exp_patch
, exp_build
;
2470 Common::Identifier
*req_id
= ex
.get_id(exp_product_number
,
2471 exp_suffix
, exp_rel
, exp_patch
, exp_build
, exp_extra
);
2473 if (imp
->has_impmod_withId(*req_id
)) {
2474 Common::Module
* m
= modules
->get_mod_byId(*req_id
);
2475 if (m
->product_number
== NULL
&& exp_product_number
!= NULL
) {
2476 ex
.error("Module '%s' requires module '%s' of product %s"
2477 ", but it is not specified",
2478 this->modid
->get_dispname().c_str(), req_id
->get_dispname().c_str(),
2479 exp_product_number
);
2480 multi
->delete_element(i
--);
2483 } else if (exp_product_number
== NULL
&&
2484 m
->product_number
!= NULL
&& strcmp(m
->product_number
, "") > 0){
2485 ex
.warning("Module '%s' requires module '%s' of any product"
2486 ", while it specifies '%s'",
2487 this->modid
->get_dispname().c_str(),
2488 req_id
->get_dispname().c_str(), m
->product_number
);
2489 } else if (m
->product_number
!= NULL
&& exp_product_number
!= NULL
2490 && 0 != strcmp(m
->product_number
, exp_product_number
)) {
2491 char *req_product_identifier
=
2492 get_product_identifier(exp_product_number
,
2493 exp_suffix
, exp_rel
, exp_patch
, exp_build
);
2494 char *mod_product_identifier
=
2495 get_product_identifier(m
->product_number
,
2496 m
->suffix
, m
->release
, m
->patch
, m
->build
);
2498 ex
.error("Module '%s' requires version %s of module"
2499 " '%s', but only %s is available",
2500 this->modid
->get_dispname().c_str(), req_product_identifier
,
2501 req_id
->get_dispname().c_str(), mod_product_identifier
);
2502 Free(req_product_identifier
);
2503 Free(mod_product_identifier
);
2504 multi
->delete_element(i
--);
2508 // different suffixes are always incompatible
2509 // unless the special version number is used
2510 if (m
->suffix
!= exp_suffix
&& (m
->suffix
!= UINT_MAX
)) {
2511 char *req_product_identifier
=
2512 get_product_identifier(exp_product_number
,exp_suffix
, exp_rel
, exp_patch
, exp_build
);
2513 char *mod_product_identifier
=
2514 get_product_identifier(m
->product_number
,
2515 m
->suffix
, m
->release
, m
->patch
, m
->build
);
2517 ex
.error("Module '%s' requires version %s of module"
2518 " '%s', but only %s is available",
2519 this->modid
->get_dispname().c_str(), req_product_identifier
,
2520 req_id
->get_dispname().c_str(), mod_product_identifier
);
2521 Free(req_product_identifier
);
2522 Free(mod_product_identifier
);
2523 multi
->delete_element(i
--);
2527 if ( m
->release
< exp_rel
2528 ||(m
->release
== exp_rel
&& m
->patch
< exp_patch
)
2529 ||(m
->patch
== exp_patch
&& m
->build
< exp_build
)) {
2530 char *mod_bld_str
= buildstr(m
->build
);
2531 char *exp_bld_str
= buildstr(exp_build
);
2532 if (mod_bld_str
==0 || exp_bld_str
==0) FATAL_ERROR(
2533 "Ttcn::Module::chk() invalid build number");
2534 ex
.error("Module '%s' requires version R%u%c%s of module"
2535 " '%s', but only R%u%c%s is available",
2536 this->modid
->get_dispname().c_str(),
2537 exp_rel
, eri(exp_patch
), exp_bld_str
,
2538 req_id
->get_dispname().c_str(),
2539 m
->release
, eri(m
->patch
), mod_bld_str
);
2544 single
->error("No imported module named '%s'",
2545 req_id
->get_dispname().c_str());
2547 multi
->delete_element(i
--);
2551 case Ttcn::ExtensionAttribute::REQ_TITAN
: {
2552 char* exp_product_number
;
2553 unsigned int exp_suffix
, exp_minor
, exp_patch
, exp_build
;
2555 (void)ex
.get_id(exp_product_number
, exp_suffix
, exp_minor
, exp_patch
, exp_build
, exp_extra
);
2556 if (exp_product_number
!= NULL
&& strcmp(exp_product_number
,"CRL 113 200") != 0) {
2557 ex
.error("This module needs to be compiled with TITAN, but "
2558 " product number %s is not TITAN"
2559 , exp_product_number
);
2561 if (0 == exp_suffix
) {
2562 exp_suffix
= 1; // previous version number format did not list the suffix part
2564 // TTCN3_MAJOR is always 1
2565 int expected_version
= exp_suffix
* 1000000
2566 + exp_minor
* 10000 + exp_patch
* 100 + exp_build
;
2567 if (expected_version
> TTCN3_VERSION_MONOTONE
) {
2568 char *exp_product_identifier
=
2569 get_product_identifier(exp_product_number
, exp_suffix
, exp_minor
, exp_patch
, exp_build
);
2570 ex
.error("This module needs to be compiled with TITAN version"
2571 " %s or higher; version %s detected"
2572 , exp_product_identifier
, PRODUCT_NUMBER
);
2573 Free(exp_product_identifier
);
2575 multi
->delete_element(i
--);
2578 case Ttcn::ExtensionAttribute::PRINTING
: {
2579 ex
.error("Attribute 'printing' not allowed at module level");
2580 multi
->delete_element(i
--);
2586 // Let everything else propagate into the module.
2587 // Extension attributes in the module's "with" statement
2588 // may be impractical, but not outright erroneous.
2599 if (controlpart
) controlpart
->chk();
2600 if (control_ns
&& !*control_ns
) { // set but empty
2601 error("Invalid URI value for control namespace");
2603 if (control_ns_prefix
&& !*control_ns_prefix
) { // set but empty
2604 error("Empty NCName for the control namespace prefix is not allowed");
2606 // TODO proper URI and NCName validation
2609 void Module::chk_friends()
2611 map
<string
, FriendMod
> friends_m
;
2613 for(size_t i
= 0; i
< friendmods_v
.size(); i
++)
2615 FriendMod
* temp_friend
= friendmods_v
[i
];
2616 const Identifier
& friend_id
= temp_friend
->get_modid();
2617 const string
& friend_name
= friend_id
.get_name();
2618 if(friends_m
.has_key(friend_name
))
2620 temp_friend
->error("Duplicate friend module with name `%s'",
2621 friend_id
.get_dispname().c_str());
2622 friends_m
[friend_name
]->note("Friend module `%s' is already defined here",
2623 friend_id
.get_dispname().c_str());
2625 friends_m
.add(friend_name
, temp_friend
);
2628 friendmods_v
[i
]->chk();
2635 void Module::chk_groups()
2637 map
<string
,Common::Assignment
> ass_m
;
2639 for(size_t i
= 0; i
< asss
->get_nof_asss(); i
++)
2641 Common::Assignment
*temp_ass
= asss
->get_ass_byIndex(i
);
2642 if(!temp_ass
->get_parent_group())
2644 const string
& ass_name
= temp_ass
->get_id().get_name();
2645 if (!ass_m
.has_key(ass_name
)) ass_m
.add(ass_name
, temp_ass
);
2649 for(size_t i
= 0; i
< group_v
.size(); i
++)
2651 const Group
* group
= group_v
[i
];
2652 const Identifier
& group_id
= group
->get_id();
2653 const string
& group_name
= group_id
.get_name();
2654 if(ass_m
.has_key(group_name
))
2656 group
->error("Group name `%s' clashes with a definition",
2657 group_id
.get_dispname().c_str());
2658 ass_m
[group_name
]->note("Definition of `%s' is here",
2659 group_id
.get_dispname().c_str());
2661 if(group_m
.has_key(group_name
))
2663 group
->error("Duplicate group with name `%s'",
2664 group_id
.get_dispname().c_str());
2665 group_m
[group_name
]->note("Group `%s' is already defined here",
2666 group_id
.get_dispname().c_str());
2668 group_m
.add(group_name
,group_v
[i
]);
2674 for(size_t i
= 0; i
< group_v
.size(); i
++)
2680 void Module::get_imported_mods(module_set_t
& p_imported_mods
)
2682 imp
->get_imported_mods(p_imported_mods
);
2685 void Module::generate_code_internal(CodeGenHelper
& cgh
) {
2686 imp
->generate_code(cgh
);
2687 asss
->generate_code(cgh
);
2689 controlpart
->generate_code(cgh
.get_outputstruct(modid
->get_ttcnname()), this);
2692 RunsOnScope
*Module::get_runs_on_scope(Type
*comptype
)
2694 RunsOnScope
*ret_val
= new RunsOnScope(comptype
);
2695 runs_on_scopes
.add(ret_val
);
2696 ret_val
->set_parent_scope(asss
);
2697 ret_val
->chk_uniq();
2702 void Module::dump(unsigned level
) const
2704 DEBUG(level
, "TTCN-3 module: %s", modid
->get_dispname().c_str());
2706 if(imp
) imp
->dump(level
);
2707 if(asss
) asss
->dump(level
);
2709 for(size_t i
= 0; i
< group_v
.size(); i
++)
2711 group_v
[i
]->dump(level
);
2714 if(controlpart
) controlpart
->dump(level
);
2716 if (w_attrib_path
) {
2717 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2719 DEBUG(level
, "Module Attributes:");
2720 attrib
->dump(level
+ 1);
2725 void Module::set_language_spec(const char *p_language_spec
)
2727 if (language_spec
) FATAL_ERROR("Module::set_language_spec()");
2728 if (p_language_spec
) language_spec
= new string(p_language_spec
);
2731 void Module::add_ass(Definition
* p_ass
)
2733 asss
->add_ass(p_ass
);
2736 void Module::add_impmod(ImpMod
*p_impmod
)
2738 imp
->add_impmod(p_impmod
);
2741 void Module::add_controlpart(ControlPart
* p_controlpart
)
2743 if (!p_controlpart
|| controlpart
) FATAL_ERROR("Module::add_controlpart()");
2744 controlpart
= p_controlpart
;
2745 controlpart
->set_my_scope(asss
);
2748 void Module::set_with_attr(MultiWithAttrib
* p_attrib
)
2750 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2751 w_attrib_path
->set_with_attr(p_attrib
);
2754 WithAttribPath
* Module::get_attrib_path()
2756 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2757 return w_attrib_path
;
2760 void Module::set_parent_path(WithAttribPath
* p_path
)
2762 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2763 w_attrib_path
->set_parent(p_path
);
2766 bool Module::is_visible(const Identifier
& id
, visibility_t visibility
){
2768 if (visibility
== PUBLIC
) {
2771 if (visibility
== FRIEND
) {
2772 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) {
2773 if (friendmods_v
[i
]->get_modid() == id
) {
2781 void Module::generate_json_schema(JSON_Tokenizer
& json
, map
<Type
*, JSON_Tokenizer
>& json_refs
)
2783 // add a new property for this module
2784 json
.put_next_token(JSON_TOKEN_NAME
, modid
->get_ttcnname().c_str());
2786 // add type definitions into an object
2787 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2789 // cycle through each type, generate schema segment and reference when needed
2790 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2791 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2793 Type
* t
= def
->get_Type();
2794 if (t
->has_encoding(Type::CT_JSON
)) {
2795 // insert type's schema segment
2796 t
->generate_json_schema(json
, false, false);
2798 if (json_refs_for_all_types
&& !json_refs
.has_key(t
)) {
2799 // create JSON schema reference for the type
2800 JSON_Tokenizer
* json_ref
= new JSON_Tokenizer
;
2801 json_refs
.add(t
, json_ref
);
2802 t
->generate_json_schema_ref(*json_ref
);
2808 // end of type definitions
2809 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2811 // insert function data
2812 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2813 Def_ExtFunction
* def
= dynamic_cast<Def_ExtFunction
*>(asss
->get_ass_byIndex(i
));
2815 def
->generate_json_schema_ref(json_refs
);
2820 void Module::generate_debugger_init(output_struct
* output
)
2822 // create the initializer function
2823 output
->source
.global_vars
= mputstr(output
->source
.global_vars
,
2824 "\n/* Initializing TTCN-3 debugger */\n"
2825 "void init_ttcn3_debugger()\n"
2827 /*" debugger_manual_init();\n"*/);
2829 // initialize global scope and variables (including imported variables)
2830 char* str_glob
= generate_debugger_global_vars(NULL
, this);
2831 for (int i
= 0; i
< imp
->get_imports_size(); ++i
) {
2832 str_glob
= imp
->get_impmod(i
)->get_mod()->generate_debugger_global_vars(str_glob
, this);
2834 if (str_glob
!= NULL
) {
2835 // only add the global scope if it actually has variables
2836 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2837 " /* global variables */\n"
2838 " TTCN3_Debug_Scope* global_scope = ttcn3_debugger.add_global_scope(\"%s\");\n"
2840 get_modid().get_dispname().c_str(), str_glob
);
2844 // initialize components' scopes and their variables
2845 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2846 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2848 Type
* comp_type
= def
->get_Type();
2849 if (comp_type
->get_typetype() == Type::T_COMPONENT
) {
2850 char* str_comp
= NULL
;
2851 ComponentTypeBody
* comp_body
= comp_type
->get_CompBody();
2852 for (size_t j
= 0; j
< comp_body
->get_nof_asss(); ++j
) {
2853 str_comp
= generate_code_debugger_add_var(str_comp
, comp_body
->get_ass_byIndex(j
),
2854 this, comp_type
->get_dispname().c_str());
2856 if (str_comp
!= NULL
) {
2857 // only add the component if it actually has variables
2858 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2859 " /* variables of component %s */\n"
2860 " TTCN3_Debug_Scope* %s_scope = ttcn3_debugger.add_component_scope(\"%s\");\n"
2862 , comp_type
->get_dispname().c_str(), comp_type
->get_dispname().c_str()
2863 , comp_type
->get_dispname().c_str(), str_comp
);
2870 // close the initializer function
2871 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, "}\n");
2874 char* Module::generate_debugger_global_vars(char* str
, Common::Module
* current_mod
)
2876 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2877 Common::Assignment
* ass
= asss
->get_ass_byIndex(i
);
2878 switch (ass
->get_asstype()) {
2879 case Common::Assignment::A_TEMPLATE
:
2880 if (ass
->get_FormalParList() != NULL
) {
2881 // don't add parameterized templates, since they are functions in C++
2884 // else fall through
2885 case Common::Assignment::A_CONST
:
2886 //case Common::Assignment::A_EXT_CONST: TODO: handle unused ext_const
2887 case Common::Assignment::A_MODULEPAR
:
2888 case Common::Assignment::A_MODULEPAR_TEMP
:
2889 str
= generate_code_debugger_add_var(str
, ass
, current_mod
, "global");
2898 void Module::generate_debugger_functions(output_struct
*output
)
2901 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2902 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2904 Type
* t
= def
->get_Type();
2905 if (!t
->is_ref() && t
->get_typetype() != Type::T_COMPONENT
) {
2906 // don't generate code for subtypes
2907 if (t
->get_typetype() != Type::T_SIGNATURE
) {
2908 str
= mputprintf(str
,
2909 " %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
2910 " ((const %s*)p_var.value)->log();\n"
2912 , (str
!= NULL
) ? "else " : ""
2913 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2915 if (t
->get_typetype() != Type::T_PORT
) {
2916 str
= mputprintf(str
,
2917 " %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
2918 " ((const %s_template*)p_var.value)->log();\n"
2920 , (str
!= NULL
) ? "else " : ""
2921 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2927 // don't generate an empty printing function
2928 output
->header
.class_defs
= mputprintf(output
->header
.class_defs
,
2929 "/* Debugger printing function for types declared in this module */\n\n"
2930 "extern CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var);\n",
2931 get_modid().get_ttcnname().c_str());
2932 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2933 "\n/* Debugger printing function for types declared in this module */\n"
2934 "CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var)\n"
2936 " TTCN_Logger::begin_event_log2str();\n"
2939 " TTCN_Logger::log_event_str(\"<unrecognized value or template>\");\n"
2941 " return TTCN_Logger::end_event_log2str();\n"
2942 "}\n", get_modid().get_ttcnname().c_str(), str
);
2946 // =================================
2948 // =================================
2950 string
Definition::get_genname() const
2952 if (!genname
.empty()) return genname
;
2953 else return id
->get_name();
2956 namedbool
Definition::has_implicit_omit_attr() const {
2957 if (w_attrib_path
) {
2958 const vector
<SingleWithAttrib
>& real_attribs
=
2959 w_attrib_path
->get_real_attrib();
2960 for (size_t in
= real_attribs
.size(); in
> 0; in
--) {
2961 if (SingleWithAttrib::AT_OPTIONAL
==
2962 real_attribs
[in
-1]->get_attribKeyword()) {
2963 if ("implicit omit" ==
2964 real_attribs
[in
-1]->get_attribSpec().get_spec()) {
2965 return IMPLICIT_OMIT
;
2966 } else if ("explicit omit" ==
2967 real_attribs
[in
-1]->get_attribSpec().get_spec()) {
2968 return NOT_IMPLICIT_OMIT
;
2969 } // error reporting for other values is in chk_global_attrib
2973 return NOT_IMPLICIT_OMIT
;
2976 Definition::~Definition()
2978 delete w_attrib_path
;
2979 delete erroneous_attrs
;
2982 void Definition::set_fullname(const string
& p_fullname
)
2984 Common::Assignment::set_fullname(p_fullname
);
2985 if (w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
2986 if (erroneous_attrs
) erroneous_attrs
->set_fullname(p_fullname
+".<erroneous_attributes>");
2989 bool Definition::is_local() const
2991 if (!my_scope
) FATAL_ERROR("Definition::is_local()");
2992 for (Scope
*scope
= my_scope
; scope
; scope
= scope
->get_parent_scope()) {
2993 if (dynamic_cast<StatementBlock
*>(scope
)) return true;
2998 bool Definition::chk_identical(Definition
*)
3000 FATAL_ERROR("Definition::chk_identical()");
3004 void Definition::chk_erroneous_attr()
3006 if (!w_attrib_path
) return;
3007 const Ttcn::MultiWithAttrib
* attribs
= w_attrib_path
->get_local_attrib();
3008 if (!attribs
) return;
3009 for (size_t i
= 0; i
< attribs
->get_nof_elements(); i
++) {
3010 const Ttcn::SingleWithAttrib
* act_attr
= attribs
->get_element(i
);
3011 if (act_attr
->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_ERRONEOUS
) {
3012 if (!use_runtime_2
) {
3013 error("`erroneous' attributes can be used only with the Function Test Runtime");
3014 note("If you need negative testing use the -R flag when generating the makefile");
3017 size_t nof_qualifiers
= act_attr
->get_attribQualifiers() ? act_attr
->get_attribQualifiers()->get_nof_qualifiers() : 0;
3018 dynamic_array
<Type
*> refd_type_array(nof_qualifiers
); // only the qualifiers pointing to existing fields will be added to erroneous_attrs objects
3019 if (nof_qualifiers
==0) {
3020 act_attr
->error("At least one qualifier must be specified for the `erroneous' attribute");
3022 // check if qualifiers point to existing fields
3023 for (size_t qi
=0; qi
<nof_qualifiers
; qi
++) {
3024 Qualifier
* act_qual
= const_cast<Qualifier
*>(act_attr
->get_attribQualifiers()->get_qualifier(qi
));
3025 act_qual
->set_my_scope(get_my_scope());
3026 Type
* field_type
= get_Type()->get_field_type(act_qual
, Type::EXPECTED_CONSTANT
);
3028 dynamic_array
<size_t> subrefs_array
;
3029 dynamic_array
<Type
*> type_array
;
3030 bool valid_indexes
= get_Type()->get_subrefs_as_array(act_qual
, subrefs_array
, type_array
);
3031 if (!valid_indexes
) field_type
= NULL
;
3032 if (act_qual
->refers_to_string_element()) {
3033 act_qual
->error("Reference to a string element cannot be used in this context");
3037 refd_type_array
.add(field_type
);
3040 // parse the attr. spec.
3041 ErroneousAttributeSpec
* err_attr_spec
= ttcn3_parse_erroneous_attr_spec_string(
3042 act_attr
->get_attribSpec().get_spec().c_str(), act_attr
->get_attribSpec());
3043 if (err_attr_spec
) {
3044 if (!erroneous_attrs
) erroneous_attrs
= new ErroneousAttributes(get_Type());
3045 // attr.spec will be owned by erroneous_attrs object
3046 erroneous_attrs
->add_spec(err_attr_spec
);
3047 err_attr_spec
->set_fullname(get_fullname());
3048 err_attr_spec
->set_my_scope(get_my_scope());
3049 err_attr_spec
->chk();
3050 // create qualifier - err.attr.spec. pairs
3051 for (size_t qi
=0; qi
<nof_qualifiers
; qi
++) {
3052 if (refd_type_array
[qi
] && (err_attr_spec
->get_indicator()!=ErroneousAttributeSpec::I_INVALID
)) {
3053 erroneous_attrs
->add_pair(act_attr
->get_attribQualifiers()->get_qualifier(qi
), err_attr_spec
);
3059 if (erroneous_attrs
) erroneous_attrs
->chk();
3062 char* Definition::generate_code_str(char *str
)
3064 FATAL_ERROR("Definition::generate_code_str()");
3068 void Definition::ilt_generate_code(ILT
*)
3070 FATAL_ERROR("Definition::ilt_generate_code()");
3073 char *Definition::generate_code_init_comp(char *str
, Definition
*)
3075 FATAL_ERROR("Definition::generate_code_init_comp()");
3079 void Definition::set_with_attr(MultiWithAttrib
* p_attrib
)
3081 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3082 w_attrib_path
->set_with_attr(p_attrib
);
3085 WithAttribPath
* Definition::get_attrib_path()
3087 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3088 return w_attrib_path
;
3091 void Definition::set_parent_path(WithAttribPath
* p_path
)
3093 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3094 w_attrib_path
->set_parent(p_path
);
3097 void Definition::set_parent_group(Group
* p_group
)
3099 if(parentgroup
) // there would be a leak!
3100 FATAL_ERROR("Definition::set_parent_group()");
3101 parentgroup
= p_group
;
3104 Group
* Definition::get_parent_group()
3109 void Definition::dump_internal(unsigned level
) const
3111 DEBUG(level
, "Move along, nothing to see here");
3114 void Definition::dump(unsigned level
) const
3116 dump_internal(level
);
3117 if (w_attrib_path
) {
3118 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
3120 DEBUG(level
+ 1, "Definition Attributes:");
3121 attrib
->dump(level
+ 2);
3124 if (erroneous_attrs
) erroneous_attrs
->dump(level
+1);
3127 // =================================
3129 // =================================
3131 Def_Type::Def_Type(Identifier
*p_id
, Type
*p_type
)
3132 : Definition(A_TYPE
, p_id
), type(p_type
)
3134 if(!p_type
) FATAL_ERROR("Ttcn::Def_Type::Def_Type()");
3135 type
->set_ownertype(Type::OT_TYPE_DEF
, this);
3138 Def_Type::~Def_Type()
3143 Def_Type
*Def_Type::clone() const
3145 FATAL_ERROR("Def_Type::clone");
3148 void Def_Type::set_fullname(const string
& p_fullname
)
3150 Definition::set_fullname(p_fullname
);
3151 type
->set_fullname(p_fullname
);
3154 void Def_Type::set_my_scope(Scope
*p_scope
)
3156 bridgeScope
.set_parent_scope(p_scope
);
3157 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
3159 Definition::set_my_scope(&bridgeScope
);
3160 type
->set_my_scope(&bridgeScope
);
3164 Setting
*Def_Type::get_Setting()
3169 Type
*Def_Type::get_Type()
3175 void Def_Type::chk()
3177 if (checked
) return;
3179 Error_Context
cntxt(this, "In %s definition `%s'",
3180 type
->get_typetype() == Type::T_SIGNATURE
? "signature" : "type",
3181 id
->get_dispname().c_str());
3182 type
->set_genname(get_genname());
3183 if (!semantic_check_only
&& type
->get_typetype() == Type::T_COMPONENT
) {
3184 // the prefix of embedded definitions must be set before the checking
3185 type
->get_CompBody()->set_genname(get_genname() + "_component_");
3188 while (w_attrib_path
) { // not a loop, but we can _break_ out of it
3189 w_attrib_path
->chk_global_attrib();
3190 w_attrib_path
->chk_no_qualif();
3191 if (type
->get_typetype() != Type::T_ANYTYPE
) break;
3192 // This is the anytype; it must be empty (we're about to add the fields)
3193 if (type
->get_nof_comps() > 0) FATAL_ERROR("Def_Type::chk");
3195 Ttcn::ExtensionAttributes
*extattrs
= parse_extattributes(w_attrib_path
);
3196 if (extattrs
== 0) break; // NULL means parsing error
3198 size_t num_atrs
= extattrs
->size();
3199 for (size_t k
= 0; k
< num_atrs
; ++k
) {
3200 ExtensionAttribute
&ea
= extattrs
->get(k
);
3201 switch (ea
.get_type()) {
3202 case ExtensionAttribute::ANYTYPELIST
: {
3203 Types
*anytypes
= ea
.get_types();
3204 // List of types to be converted into fields for the anytype.
3205 // Make sure scope is set on all types in the list.
3206 anytypes
->set_my_scope(get_my_scope());
3208 // Convert the list of types into field names for the anytype
3209 for (size_t i
=0; i
< anytypes
->get_nof_types(); ++i
) {
3210 Type
*t
= anytypes
->extract_type_byIndex(i
);
3211 // we are now the owner of the Type.
3212 if (t
->get_typetype()==Type::T_ERROR
) { // should we give up?
3218 const char* btn
= Type::get_typename_builtin(t
->get_typetype());
3222 else if (t
->get_typetype() == Type::T_REFD
) {
3223 // Extract the identifier
3224 Common::Reference
*ref
= t
->get_Reference();
3225 Ttcn::Reference
*tref
= dynamic_cast<Ttcn::Reference
*>(ref
);
3226 if (!tref
) FATAL_ERROR("Def_Type::chk, wrong kind of reference");
3227 const Common::Identifier
*modid
= tref
->get_modid();
3229 ea
.error("Qualified name '%s' cannot be added to the anytype",
3230 tref
->get_dispname().c_str());
3234 field_name
= tref
->get_id()->get_ttcnname();
3237 // Can't happen here
3238 FATAL_ERROR("Unexpected type %d", t
->get_typetype());
3241 const string
& at_field
= anytype_field(field_name
);
3242 Identifier
*field_id
= new Identifier(Identifier::ID_TTCN
, at_field
);
3243 CompField
*cf
= new CompField(field_id
, t
, false, 0);
3244 cf
->set_location(ea
);
3245 cf
->set_fullname(get_fullname());
3251 w_attrib_path
->get_with_attr()->error("Type def can only have anytype");
3257 break; // do not loop
3260 // Now we can check the type
3262 type
->chk_constructor_name(*id
);
3263 if (id
->get_ttcnname() == "address") type
->chk_address();
3264 ReferenceChain
refch(type
, "While checking embedded recursions");
3265 type
->chk_recursions(refch
);
3267 if (type
->get_typetype()==Type::T_FUNCTION
3268 ||type
->get_typetype()==Type::T_ALTSTEP
3269 ||type
->get_typetype()==Type::T_TESTCASE
) {
3270 // TR 922. This is a function/altstep/testcase reference.
3271 // Set this definition as the definition for the formal parameters.
3272 type
->get_fat_parameters()->set_my_def(this);
3276 void Def_Type::generate_code(output_struct
*target
, bool)
3278 type
->generate_code(target
);
3279 if (type
->get_typetype() == Type::T_COMPONENT
) {
3280 // the C++ equivalents of embedded component element definitions must be
3281 // generated from outside Type::generate_code() because the function can
3282 // call itself recursively and create invalid (overlapped) initializer
3284 type
->get_CompBody()->generate_code(target
);
3288 void Def_Type::generate_code(CodeGenHelper
& cgh
) {
3289 type
->generate_code(cgh
.get_outputstruct(get_Type()));
3290 if (type
->get_typetype() == Type::T_COMPONENT
) {
3291 // the C++ equivalents of embedded component element definitions must be
3292 // generated from outside Type::generate_code() because the function can
3293 // call itself recursively and create invalid (overlapped) initializer
3295 type
->get_CompBody()->generate_code(cgh
.get_current_outputstruct());
3297 cgh
.finalize_generation(get_Type());
3301 void Def_Type::dump_internal(unsigned level
) const
3303 DEBUG(level
, "Type def: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3304 type
->dump(level
+ 1);
3307 void Def_Type::set_with_attr(MultiWithAttrib
* p_attrib
)
3309 if (!w_attrib_path
) {
3310 w_attrib_path
= new WithAttribPath();
3311 type
->set_parent_path(w_attrib_path
);
3313 type
->set_with_attr(p_attrib
);
3316 WithAttribPath
* Def_Type::get_attrib_path()
3318 if (!w_attrib_path
) {
3319 w_attrib_path
= new WithAttribPath();
3320 type
->set_parent_path(w_attrib_path
);
3322 return w_attrib_path
;
3325 void Def_Type::set_parent_path(WithAttribPath
* p_path
)
3327 if (!w_attrib_path
) {
3328 w_attrib_path
= new WithAttribPath();
3329 type
->set_parent_path(w_attrib_path
);
3331 w_attrib_path
->set_parent(p_path
);
3334 // =================================
3336 // =================================
3338 Def_Const::Def_Const(Identifier
*p_id
, Type
*p_type
, Value
*p_value
)
3339 : Definition(A_CONST
, p_id
)
3341 if (!p_type
|| !p_value
) FATAL_ERROR("Ttcn::Def_Const::Def_Const()");
3343 type
->set_ownertype(Type::OT_CONST_DEF
, this);
3345 value_under_check
=false;
3348 Def_Const::~Def_Const()
3354 Def_Const
*Def_Const::clone() const
3356 FATAL_ERROR("Def_Const::clone");
3359 void Def_Const::set_fullname(const string
& p_fullname
)
3361 Definition::set_fullname(p_fullname
);
3362 type
->set_fullname(p_fullname
+ ".<type>");
3363 value
->set_fullname(p_fullname
);
3366 void Def_Const::set_my_scope(Scope
*p_scope
)
3368 Definition::set_my_scope(p_scope
);
3369 type
->set_my_scope(p_scope
);
3370 value
->set_my_scope(p_scope
);
3373 Setting
*Def_Const::get_Setting()
3378 Type
*Def_Const::get_Type()
3385 Value
*Def_Const::get_Value()
3391 void Def_Const::chk()
3394 if (value_under_check
) {
3395 error("Circular reference in constant definition `%s'",
3396 id
->get_dispname().c_str());
3397 value_under_check
= false; // only report the error once for this definition
3401 Error_Context
cntxt(this, "In constant definition `%s'",
3402 id
->get_dispname().c_str());
3403 type
->set_genname(_T_
, get_genname());
3405 value
->set_my_governor(type
);
3406 type
->chk_this_value_ref(value
);
3408 if (w_attrib_path
) {
3409 w_attrib_path
->chk_global_attrib(true);
3410 switch (type
->get_type_refd_last()->get_typetype_ttcn3()) {
3413 case Type::T_CHOICE_T
:
3414 // These types may have qualified attributes
3416 case Type::T_SEQOF
: case Type::T_SETOF
:
3419 w_attrib_path
->chk_no_qualif();
3423 Type
*t
= type
->get_type_refd_last();
3424 switch (t
->get_typetype()) {
3426 error("Constant cannot be defined for port type `%s'",
3427 t
->get_fullname().c_str());
3429 case Type::T_SIGNATURE
:
3430 error("Constant cannot be defined for signature `%s'",
3431 t
->get_fullname().c_str());
3434 value_under_check
= true;
3435 type
->chk_this_value(value
, 0, Type::EXPECTED_CONSTANT
, INCOMPLETE_ALLOWED
,
3436 OMIT_NOT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr());
3437 value_under_check
= false;
3438 chk_erroneous_attr();
3439 if (erroneous_attrs
) value
->set_err_descr(erroneous_attrs
->get_err_descr());
3441 ReferenceChain
refch(type
, "While checking embedded recursions");
3442 value
->chk_recursions(refch
);
3446 if (!semantic_check_only
) {
3447 value
->set_genname_prefix("const_");
3448 value
->set_genname_recursive(get_genname());
3449 value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3453 bool Def_Const::chk_identical(Definition
*p_def
)
3457 if (p_def
->get_asstype() != A_CONST
) {
3458 const char *dispname_str
= id
->get_dispname().c_str();
3459 error("Local definition `%s' is a constant, but the definition "
3460 "inherited from component type `%s' is a %s", dispname_str
,
3461 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
3462 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
3465 Def_Const
*p_def_const
= dynamic_cast<Def_Const
*>(p_def
);
3466 if (!p_def_const
) FATAL_ERROR("Def_Const::chk_identical()");
3467 if (!type
->is_identical(p_def_const
->type
)) {
3468 const char *dispname_str
= id
->get_dispname().c_str();
3469 type
->error("Local constant `%s' has type `%s', but the constant "
3470 "inherited from component type `%s' has type `%s'", dispname_str
,
3471 type
->get_typename().c_str(),
3472 p_def_const
->get_my_scope()->get_fullname().c_str(),
3473 p_def_const
->type
->get_typename().c_str());
3474 p_def_const
->note("The inherited constant `%s' is here", dispname_str
);
3476 } else if (!(*value
== *p_def_const
->value
)) {
3477 const char *dispname_str
= id
->get_dispname().c_str();
3478 value
->error("Local constant `%s' and the constant inherited from "
3479 "component type `%s' have different values", dispname_str
,
3480 p_def_const
->get_my_scope()->get_fullname().c_str());
3481 p_def_const
->note("The inherited constant `%s' is here", dispname_str
);
3486 void Def_Const::generate_code(output_struct
*target
, bool)
3488 type
->generate_code(target
);
3490 Code::init_cdef(&cdef
);
3491 type
->generate_code_object(&cdef
, value
);
3492 cdef
.init
= update_location_object(cdef
.init
);
3493 cdef
.init
= value
->generate_code_init(cdef
.init
,
3494 value
->get_lhs_name().c_str());
3495 Code::merge_cdef(target
, &cdef
);
3496 Code::free_cdef(&cdef
);
3499 void Def_Const::generate_code(Common::CodeGenHelper
& cgh
) {
3500 // constant definitions always go to its containing module
3501 generate_code(cgh
.get_current_outputstruct());
3504 char *Def_Const::generate_code_str(char *str
)
3506 const string
& t_genname
= get_genname();
3507 const char *genname_str
= t_genname
.c_str();
3508 if (value
->has_single_expr()) {
3509 // the value can be represented by a single C++ expression
3510 // the object is initialized by the constructor
3511 str
= mputprintf(str
, "%s %s(%s);\n",
3512 type
->get_genname_value(my_scope
).c_str(), genname_str
,
3513 value
->get_single_expr().c_str());
3515 // use the default constructor
3516 str
= mputprintf(str
, "%s %s;\n",
3517 type
->get_genname_value(my_scope
).c_str(), genname_str
);
3518 // the value is assigned using subsequent statements
3519 str
= value
->generate_code_init(str
, genname_str
);
3521 if (debugger_active
) {
3522 str
= generate_code_debugger_add_var(str
, this);
3527 void Def_Const::ilt_generate_code(ILT
*ilt
)
3529 const string
& t_genname
= get_genname();
3530 const char *genname_str
= t_genname
.c_str();
3531 char*& def
=ilt
->get_out_def();
3532 char*& init
=ilt
->get_out_branches();
3533 def
= mputprintf(def
, "%s %s;\n", type
->get_genname_value(my_scope
).c_str(),
3535 init
= value
->generate_code_init(init
, genname_str
);
3538 char *Def_Const::generate_code_init_comp(char *str
, Definition
*)
3540 /* This function actually does nothing as \a this and \a base_defn are
3541 * exactly the same. */
3545 void Def_Const::dump_internal(unsigned level
) const
3547 DEBUG(level
, "Constant: %s @%p", id
->get_dispname().c_str(), (const void*)this);
3548 type
->dump(level
+ 1);
3549 value
->dump(level
+ 1);
3552 // =================================
3553 // ===== Def_ExtConst
3554 // =================================
3556 Def_ExtConst::Def_ExtConst(Identifier
*p_id
, Type
*p_type
)
3557 : Definition(A_EXT_CONST
, p_id
)
3559 if (!p_type
) FATAL_ERROR("Ttcn::Def_ExtConst::Def_ExtConst()");
3561 type
->set_ownertype(Type::OT_CONST_DEF
, this);
3564 Def_ExtConst::~Def_ExtConst()
3569 Def_ExtConst
*Def_ExtConst::clone() const
3571 FATAL_ERROR("Def_ExtConst::clone");
3574 void Def_ExtConst::set_fullname(const string
& p_fullname
)
3576 Definition::set_fullname(p_fullname
);
3577 type
->set_fullname(p_fullname
+ ".<type>");
3580 void Def_ExtConst::set_my_scope(Scope
*p_scope
)
3582 Definition::set_my_scope(p_scope
);
3583 type
->set_my_scope(p_scope
);
3586 Type
*Def_ExtConst::get_Type()
3592 void Def_ExtConst::chk()
3595 Error_Context
cntxt(this, "In external constant definition `%s'",
3596 id
->get_dispname().c_str());
3597 type
->set_genname(_T_
, get_genname());
3600 Type
*t
= type
->get_type_refd_last();
3601 switch (t
->get_typetype()) {
3603 error("External constant cannot be defined for port type `%s'",
3604 t
->get_fullname().c_str());
3606 case Type::T_SIGNATURE
:
3607 error("External constant cannot be defined for signature `%s'",
3608 t
->get_fullname().c_str());
3613 if (w_attrib_path
) {
3614 w_attrib_path
->chk_global_attrib();
3615 switch (type
->get_type_refd_last()->get_typetype()) {
3618 case Type::T_CHOICE_T
:
3619 // These types may have qualified attributes
3621 case Type::T_SEQOF
: case Type::T_SETOF
:
3624 w_attrib_path
->chk_no_qualif();
3630 void Def_ExtConst::generate_code(output_struct
*target
, bool)
3632 type
->generate_code(target
);
3633 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
3634 "extern const %s& %s;\n", type
->get_genname_value(my_scope
).c_str(),
3635 get_genname().c_str());
3638 void Def_ExtConst::generate_code(Common::CodeGenHelper
& cgh
) {
3639 // constant definitions always go to its containing module
3640 generate_code(cgh
.get_current_outputstruct());
3643 void Def_ExtConst::dump_internal(unsigned level
) const
3645 DEBUG(level
, "External constant: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3646 type
->dump(level
+ 1);
3649 // =================================
3650 // ===== Def_Modulepar
3651 // =================================
3653 Def_Modulepar::Def_Modulepar(Identifier
*p_id
, Type
*p_type
, Value
*p_defval
)
3654 : Definition(A_MODULEPAR
, p_id
)
3656 if (!p_type
) FATAL_ERROR("Ttcn::Def_Modulepar::Def_Modulepar()");
3658 type
->set_ownertype(Type::OT_MODPAR_DEF
, this);
3659 def_value
= p_defval
;
3662 Def_Modulepar::~Def_Modulepar()
3668 Def_Modulepar
* Def_Modulepar::clone() const
3670 FATAL_ERROR("Def_Modulepar::clone");
3673 void Def_Modulepar::set_fullname(const string
& p_fullname
)
3675 Definition::set_fullname(p_fullname
);
3676 type
->set_fullname(p_fullname
+ ".<type>");
3677 if (def_value
) def_value
->set_fullname(p_fullname
+ ".<default_value>");
3680 void Def_Modulepar::set_my_scope(Scope
*p_scope
)
3682 Definition::set_my_scope(p_scope
);
3683 type
->set_my_scope(p_scope
);
3684 if (def_value
) def_value
->set_my_scope(p_scope
);
3687 Type
*Def_Modulepar::get_Type()
3693 void Def_Modulepar::chk()
3696 Error_Context
cntxt(this, "In module parameter definition `%s'",
3697 id
->get_dispname().c_str());
3698 type
->set_genname(_T_
, get_genname());
3700 if (w_attrib_path
) {
3701 w_attrib_path
->chk_global_attrib();
3702 switch (type
->get_type_refd_last()->get_typetype()) {
3705 case Type::T_CHOICE_T
:
3706 // These types may have qualified attributes
3708 case Type::T_SEQOF
: case Type::T_SETOF
:
3711 w_attrib_path
->chk_no_qualif();
3715 map
<Type
*,void> type_chain
;
3716 map
<Type::typetype_t
, void> not_allowed
;
3717 not_allowed
.add(Type::T_PORT
, 0);
3718 Type
*t
= type
->get_type_refd_last();
3719 // if the type is valid the original will be returned
3720 Type::typetype_t tt
= t
->search_for_not_allowed_type(type_chain
, not_allowed
);
3722 not_allowed
.clear();
3725 error("Type of module parameter cannot be or embed port type `%s'",
3726 t
->get_fullname().c_str());
3728 case Type::T_SIGNATURE
:
3729 error("Type of module parameter cannot be signature `%s'",
3730 t
->get_fullname().c_str());
3732 case Type::T_FUNCTION
:
3733 case Type::T_ALTSTEP
:
3734 case Type::T_TESTCASE
:
3735 if (t
->get_fat_runs_on_self()) {
3736 error("Type of module parameter cannot be of function reference type"
3737 " `%s' which has runs on self clause", t
->get_fullname().c_str());
3745 Error_Context
cntxt2(def_value
, "In default value");
3746 def_value
->set_my_governor(type
);
3747 type
->chk_this_value_ref(def_value
);
3749 type
->chk_this_value(def_value
, 0, Type::EXPECTED_CONSTANT
, INCOMPLETE_ALLOWED
,
3750 OMIT_NOT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr());
3751 if (!semantic_check_only
) {
3752 def_value
->set_genname_prefix("modulepar_");
3753 def_value
->set_genname_recursive(get_genname());
3754 def_value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3756 } else checked
= true;
3762 void Def_Modulepar::generate_code(output_struct
*target
, bool)
3764 type
->generate_code(target
);
3766 Code::init_cdef(&cdef
);
3767 const string
& t_genname
= get_genname();
3768 const char *name
= t_genname
.c_str();
3769 type
->generate_code_object(&cdef
, my_scope
, t_genname
, "modulepar_", false);
3771 cdef
.init
= update_location_object(cdef
.init
);
3772 cdef
.init
= def_value
->generate_code_init(cdef
.init
, def_value
->get_lhs_name().c_str());
3774 Code::merge_cdef(target
, &cdef
);
3775 Code::free_cdef(&cdef
);
3777 if (has_implicit_omit_attr()) {
3778 target
->functions
.post_init
= mputprintf(target
->functions
.post_init
,
3779 "modulepar_%s.set_implicit_omit();\n", name
);
3782 const char *dispname
= id
->get_dispname().c_str();
3783 target
->functions
.set_param
= mputprintf(target
->functions
.set_param
,
3784 "if (!strcmp(par_name, \"%s\")) {\n"
3785 "modulepar_%s.set_param(param);\n"
3787 "} else ", dispname
, name
);
3788 target
->functions
.get_param
= mputprintf(target
->functions
.get_param
,
3789 "if (!strcmp(par_name, \"%s\")) {\n"
3790 "return modulepar_%s.get_param(param_name);\n"
3791 "} else ", dispname
, name
);
3793 if (target
->functions
.log_param
) {
3794 // this is not the first modulepar
3795 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3796 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname
);
3798 // this is the first modulepar
3799 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3800 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname
);
3802 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3803 "%s.log();\n", name
);
3806 void Def_Modulepar::generate_code(Common::CodeGenHelper
& cgh
) {
3807 // module parameter definitions always go to its containing module
3808 generate_code(cgh
.get_current_outputstruct());
3811 void Def_Modulepar::dump_internal(unsigned level
) const
3813 DEBUG(level
, "Module parameter: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3814 type
->dump(level
+ 1);
3815 if (def_value
) def_value
->dump(level
+ 1);
3816 else DEBUG(level
+ 1, "No default value");
3819 // =================================
3820 // ===== Def_Modulepar_Template
3821 // =================================
3823 Def_Modulepar_Template::Def_Modulepar_Template(Identifier
*p_id
, Type
*p_type
, Template
*p_deftmpl
)
3824 : Definition(A_MODULEPAR_TEMP
, p_id
)
3826 if (!p_type
) FATAL_ERROR("Ttcn::Def_Modulepar_Template::Def_Modulepar_Template()");
3828 type
->set_ownertype(Type::OT_MODPAR_DEF
, this);
3829 def_template
= p_deftmpl
;
3832 Def_Modulepar_Template::~Def_Modulepar_Template()
3835 delete def_template
;
3838 Def_Modulepar_Template
* Def_Modulepar_Template::clone() const
3840 FATAL_ERROR("Def_Modulepar_Template::clone");
3843 void Def_Modulepar_Template::set_fullname(const string
& p_fullname
)
3845 Definition::set_fullname(p_fullname
);
3846 type
->set_fullname(p_fullname
+ ".<type>");
3847 if (def_template
) def_template
->set_fullname(p_fullname
+ ".<default_template>");
3850 void Def_Modulepar_Template::set_my_scope(Scope
*p_scope
)
3852 Definition::set_my_scope(p_scope
);
3853 type
->set_my_scope(p_scope
);
3854 if (def_template
) def_template
->set_my_scope(p_scope
);
3857 Type
*Def_Modulepar_Template::get_Type()
3863 void Def_Modulepar_Template::chk()
3866 Error_Context
cntxt(this, "In template module parameter definition `%s'",
3867 id
->get_dispname().c_str());
3868 if (w_attrib_path
) {
3869 w_attrib_path
->chk_global_attrib();
3870 switch (type
->get_type_refd_last()->get_typetype()) {
3873 case Type::T_CHOICE_T
:
3874 // These types may have qualified attributes
3876 case Type::T_SEQOF
: case Type::T_SETOF
:
3879 w_attrib_path
->chk_no_qualif();
3883 type
->set_genname(_T_
, get_genname());
3885 Type
*t
= type
->get_type_refd_last();
3886 switch (t
->get_typetype()) {
3888 error("Type of template module parameter cannot be port type `%s'",
3889 t
->get_fullname().c_str());
3891 case Type::T_SIGNATURE
:
3892 error("Type of template module parameter cannot be signature `%s'",
3893 t
->get_fullname().c_str());
3895 case Type::T_FUNCTION
:
3896 case Type::T_ALTSTEP
:
3897 case Type::T_TESTCASE
:
3898 if (t
->get_fat_runs_on_self()) {
3899 error("Type of template module parameter cannot be of function reference type"
3900 " `%s' which has runs on self clause", t
->get_fullname().c_str());
3904 if (has_implicit_omit_attr()) {
3905 error("Implicit omit not supported for template module parameters");
3911 Error_Context
cntxt2(def_template
, "In default template");
3912 def_template
->set_my_governor(type
);
3913 def_template
->flatten(false);
3914 if (def_template
->get_templatetype() == Template::CSTR_PATTERN
&&
3915 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
3916 def_template
->set_templatetype(Template::USTR_PATTERN
);
3917 def_template
->get_ustr_pattern()->set_pattern_type(
3918 PatternString::USTR_PATTERN
);
3920 type
->chk_this_template_ref(def_template
);
3922 type
->chk_this_template_generic(def_template
, INCOMPLETE_ALLOWED
,
3923 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr() ? IMPLICIT_OMIT
: NOT_IMPLICIT_OMIT
, 0);
3924 if (!semantic_check_only
) {
3925 def_template
->set_genname_prefix("modulepar_");
3926 def_template
->set_genname_recursive(get_genname());
3927 def_template
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3929 } else checked
= true;
3935 void Def_Modulepar_Template::generate_code(output_struct
*target
, bool)
3937 type
->generate_code(target
);
3939 Code::init_cdef(&cdef
);
3940 const string
& t_genname
= get_genname();
3941 const char *name
= t_genname
.c_str();
3942 type
->generate_code_object(&cdef
, my_scope
, t_genname
, "modulepar_", true);
3944 cdef
.init
= update_location_object(cdef
.init
);
3945 cdef
.init
= def_template
->generate_code_init(cdef
.init
, def_template
->get_lhs_name().c_str());
3947 Code::merge_cdef(target
, &cdef
);
3948 Code::free_cdef(&cdef
);
3950 if (has_implicit_omit_attr()) {
3951 FATAL_ERROR("Def_Modulepar_Template::generate_code()");
3954 const char *dispname
= id
->get_dispname().c_str();
3955 target
->functions
.set_param
= mputprintf(target
->functions
.set_param
,
3956 "if (!strcmp(par_name, \"%s\")) {\n"
3957 "modulepar_%s.set_param(param);\n"
3959 "} else ", dispname
, name
);
3960 target
->functions
.get_param
= mputprintf(target
->functions
.get_param
,
3961 "if (!strcmp(par_name, \"%s\")) {\n"
3962 "return modulepar_%s.get_param(param_name);\n"
3963 "} else ", dispname
, name
);
3965 if (target
->functions
.log_param
) {
3966 // this is not the first modulepar
3967 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3968 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname
);
3970 // this is the first modulepar
3971 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3972 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname
);
3974 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3975 "%s.log();\n", name
);
3978 void Def_Modulepar_Template::generate_code(Common::CodeGenHelper
& cgh
) {
3979 // module parameter definitions always go to its containing module
3980 generate_code(cgh
.get_current_outputstruct());
3983 void Def_Modulepar_Template::dump_internal(unsigned level
) const
3985 DEBUG(level
, "Module parameter: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3986 type
->dump(level
+ 1);
3987 if (def_template
) def_template
->dump(level
+ 1);
3988 else DEBUG(level
+ 1, "No default template");
3991 // =================================
3992 // ===== Def_Template
3993 // =================================
3995 Def_Template::Def_Template(template_restriction_t p_template_restriction
,
3996 Identifier
*p_id
, Type
*p_type
, FormalParList
*p_fpl
,
3997 Reference
*p_derived_ref
, Template
*p_body
)
3998 : Definition(A_TEMPLATE
, p_id
), type(p_type
), fp_list(p_fpl
),
3999 derived_ref(p_derived_ref
), base_template(0), recurs_deriv_checked(false),
4000 body(p_body
), template_restriction(p_template_restriction
),
4001 gen_restriction_check(false)
4003 if (!p_type
|| !p_body
) FATAL_ERROR("Ttcn::Def_Template::Def_Template()");
4004 type
->set_ownertype(Type::OT_TEMPLATE_DEF
, this);
4005 if (fp_list
) fp_list
->set_my_def(this);
4008 Def_Template::~Def_Template()
4016 Def_Template
*Def_Template::clone() const
4018 FATAL_ERROR("Def_Template::clone");
4021 void Def_Template::set_fullname(const string
& p_fullname
)
4023 Definition::set_fullname(p_fullname
);
4024 type
->set_fullname(p_fullname
+ ".<type>");
4025 if (fp_list
) fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
4027 derived_ref
->set_fullname(p_fullname
+ ".<derived_reference>");
4028 body
->set_fullname(p_fullname
);
4031 void Def_Template::set_my_scope(Scope
*p_scope
)
4033 bridgeScope
.set_parent_scope(p_scope
);
4034 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
4036 Definition::set_my_scope(&bridgeScope
);
4037 type
->set_my_scope(&bridgeScope
);
4038 if (derived_ref
) derived_ref
->set_my_scope(&bridgeScope
);
4040 fp_list
->set_my_scope(&bridgeScope
);
4041 body
->set_my_scope(fp_list
);
4042 } else body
->set_my_scope(&bridgeScope
);
4045 Setting
*Def_Template::get_Setting()
4047 return get_Template();
4050 Type
*Def_Template::get_Type()
4052 if (!checked
) chk();
4056 Template
*Def_Template::get_Template()
4058 if (!checked
) chk();
4062 FormalParList
*Def_Template::get_FormalParList()
4064 if (!checked
) chk();
4068 void Def_Template::chk()
4070 if (checked
) return;
4071 Error_Context
cntxt(this, "In template definition `%s'",
4072 id
->get_dispname().c_str());
4073 const string
& t_genname
= get_genname();
4074 type
->set_genname(_T_
, t_genname
);
4076 if (w_attrib_path
) {
4077 w_attrib_path
->chk_global_attrib(true);
4078 switch (type
->get_type_refd_last()->get_typetype_ttcn3()) {
4081 case Type::T_CHOICE_T
:
4082 // These types may have qualified attributes
4084 case Type::T_SEQOF
: case Type::T_SETOF
:
4087 w_attrib_path
->chk_no_qualif();
4093 fp_list
->chk(asstype
);
4094 if (local_scope
) error("Parameterized local template `%s' not supported",
4095 id
->get_dispname().c_str());
4098 // Merge the elements of "all from" into the list
4099 body
->flatten(false);
4101 body
->set_my_governor(type
);
4103 if (body
->get_templatetype() == Template::CSTR_PATTERN
&&
4104 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
4105 body
->set_templatetype(Template::USTR_PATTERN
);
4106 body
->get_ustr_pattern()->set_pattern_type(PatternString::USTR_PATTERN
);
4109 type
->chk_this_template_ref(body
);
4111 Type
*t
= type
->get_type_refd_last();
4112 if (t
->get_typetype() == Type::T_PORT
) {
4113 error("Template cannot be defined for port type `%s'",
4114 t
->get_fullname().c_str());
4117 chk_recursive_derivation();
4118 type
->chk_this_template_generic(body
, INCOMPLETE_ALLOWED
, OMIT_ALLOWED
,
4119 ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
4120 has_implicit_omit_attr() ? IMPLICIT_OMIT
: NOT_IMPLICIT_OMIT
, 0);
4122 chk_erroneous_attr();
4123 if (erroneous_attrs
) body
->set_err_descr(erroneous_attrs
->get_err_descr());
4126 ReferenceChain
refch(type
, "While checking embedded recursions");
4127 body
->chk_recursions(refch
);
4129 if (template_restriction
!=TR_NONE
) {
4130 Error_Context
ec(this, "While checking template restriction `%s'",
4131 Template::get_restriction_name(template_restriction
));
4132 gen_restriction_check
=
4133 body
->chk_restriction("template definition", template_restriction
, body
);
4134 if (fp_list
&& template_restriction
!=TR_PRESENT
) {
4135 size_t nof_fps
= fp_list
->get_nof_fps();
4136 for (size_t i
=0; i
<nof_fps
; i
++) {
4137 FormalPar
* fp
= fp_list
->get_fp_byIndex(i
);
4138 // if formal par is not template then skip restriction checking,
4139 // templates can have only `in' parameters
4140 if (fp
->get_asstype()!=A_PAR_TEMPL_IN
) continue;
4141 template_restriction_t fp_tr
= fp
->get_template_restriction();
4142 switch (template_restriction
) {
4151 fp
->error("Formal parameter with template restriction `%s' "
4152 "not allowed here", Template::get_restriction_name(fp_tr
));
4155 fp
->error("Formal parameter without template restriction "
4156 "not allowed here");
4159 FATAL_ERROR("Ttcn::Def_Template::chk()");
4163 FATAL_ERROR("Ttcn::Def_Template::chk()");
4168 if (!semantic_check_only
) {
4169 if (fp_list
) fp_list
->set_genname(t_genname
);
4170 body
->set_genname_prefix("template_");
4171 body
->set_genname_recursive(t_genname
);
4172 body
->set_code_section(fp_list
? GovernedSimple::CS_INLINE
:
4173 GovernedSimple::CS_POST_INIT
);
4178 void Def_Template::chk_default() const
4180 if (!fp_list
) FATAL_ERROR("Def_Template::chk_default()");
4182 if (fp_list
->has_notused_defval())
4183 fp_list
->error("Only modified templates are allowed to use the not "
4184 "used symbol (`-') as the default parameter");
4187 Common::Assignment
*ass
= derived_ref
->get_refd_assignment(false);
4188 if (!ass
|| ass
->get_asstype() != A_TEMPLATE
) return; // Work locally.
4189 Def_Template
*base
= dynamic_cast<Def_Template
*>(ass
);
4190 if (!base
) FATAL_ERROR("Def_Template::chk_default()");
4191 FormalParList
*base_fpl
= base
->get_FormalParList();
4192 size_t nof_base_fps
= base_fpl
? base_fpl
->get_nof_fps() : 0;
4193 size_t nof_local_fps
= fp_list
? fp_list
->get_nof_fps() : 0;
4194 size_t min_fps
= nof_base_fps
;
4195 if (nof_local_fps
< nof_base_fps
) min_fps
= nof_local_fps
;
4196 for (size_t i
= 0; i
< min_fps
; i
++) {
4197 FormalPar
*base_fp
= base_fpl
->get_fp_byIndex(i
);
4198 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4199 if (local_fp
->has_notused_defval()) {
4200 if (base_fp
->has_defval()) {
4201 local_fp
->set_defval(base_fp
->get_defval());
4203 local_fp
->error("Not used symbol (`-') doesn't have the "
4204 "corresponding default parameter in the "
4209 // Additional parameters in the derived template with using the not used
4210 // symbol. TODO: Merge the loops.
4211 for (size_t i
= nof_base_fps
; i
< nof_local_fps
; i
++) {
4212 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4213 if (local_fp
->has_notused_defval())
4214 local_fp
->error("Not used symbol (`-') doesn't have the "
4215 "corresponding default parameter in the "
4220 void Def_Template::chk_modified()
4222 if (!derived_ref
) return;
4223 // Do not check the (non-existent) actual parameter list of the derived
4224 // reference against the formal parameter list of the base template.
4225 // According to TTCN-3 syntax the derived reference cannot have parameters
4226 // even if the base template is parameterized.
4227 Common::Assignment
*ass
= derived_ref
->get_refd_assignment(false);
4228 // Checking the existence and type compatibility of the base template.
4230 if (ass
->get_asstype() != A_TEMPLATE
) {
4231 derived_ref
->error("Reference to a template was expected in the "
4232 "`modifies' definition instead of %s",
4233 ass
->get_description().c_str());
4236 base_template
= dynamic_cast<Def_Template
*>(ass
);
4237 if (!base_template
) FATAL_ERROR("Def_Template::chk_modified()");
4238 Type
*base_type
= base_template
->get_Type();
4239 TypeCompatInfo
info_base(my_scope
->get_scope_mod(), type
, base_type
, true,
4241 TypeChain l_chain_base
;
4242 TypeChain r_chain_base
;
4243 if (!type
->is_compatible(base_type
, &info_base
, &l_chain_base
,
4245 if (info_base
.is_subtype_error()) {
4246 type
->error("%s", info_base
.get_subtype_error().c_str());
4248 if (!info_base
.is_erroneous()) {
4249 type
->error("The modified template has different type than base "
4250 "template `%s': `%s' was expected instead of `%s'",
4251 ass
->get_fullname().c_str(),
4252 base_type
->get_typename().c_str(),
4253 type
->get_typename().c_str());
4255 // Always use the format string.
4256 type
->error("%s", info_base
.get_error_str_str().c_str());
4259 if (info_base
.needs_conversion())
4260 body
->set_needs_conversion();
4262 // Check for restriction.
4263 if (Template::is_less_restrictive(base_template
->get_template_restriction(),
4264 template_restriction
)) {
4265 error("The template restriction is not the same or more "
4266 "restrictive as of base template `%s'", ass
->get_fullname().c_str());
4268 // Checking formal parameter lists.
4269 FormalParList
*base_fpl
= base_template
->get_FormalParList();
4270 size_t nof_base_fps
= base_fpl
? base_fpl
->get_nof_fps() : 0;
4271 size_t nof_local_fps
= fp_list
? fp_list
->get_nof_fps() : 0;
4273 if (nof_local_fps
< nof_base_fps
) {
4274 error("The modified template has fewer formal parameters than base "
4275 "template `%s': at least %lu parameter%s expected instead of %lu",
4276 ass
->get_fullname().c_str(), (unsigned long)nof_base_fps
,
4277 nof_base_fps
> 1 ? "s were" : " was", (unsigned long)nof_local_fps
);
4278 min_fps
= nof_local_fps
;
4279 } else min_fps
= nof_base_fps
;
4281 for (size_t i
= 0; i
< min_fps
; i
++) {
4282 FormalPar
*base_fp
= base_fpl
->get_fp_byIndex(i
);
4283 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4284 Error_Context
cntxt(local_fp
, "In formal parameter #%lu",
4285 (unsigned long)(i
+ 1));
4286 // Check for parameter kind equivalence (value or template).
4287 if (base_fp
->get_asstype() != local_fp
->get_asstype())
4288 local_fp
->error("The kind of parameter is not the same as in base "
4289 "template `%s': %s was expected instead of %s",
4290 ass
->get_fullname().c_str(), base_fp
->get_assname(),
4291 local_fp
->get_assname());
4292 // Check for type compatibility.
4293 Type
*base_fp_type
= base_fp
->get_Type();
4294 Type
*local_fp_type
= local_fp
->get_Type();
4295 TypeCompatInfo
info_par(my_scope
->get_scope_mod(), base_fp_type
,
4296 local_fp_type
, true, false);
4297 TypeChain l_chain_par
;
4298 TypeChain r_chain_par
;
4299 if (!base_fp_type
->is_compatible(local_fp_type
, &info_par
, &l_chain_par
,
4301 if (info_par
.is_subtype_error()) {
4302 local_fp_type
->error("%s", info_par
.get_subtype_error().c_str());
4304 if (!info_par
.is_erroneous()) {
4305 local_fp_type
->error("The type of parameter is not the same as in "
4306 "base template `%s': `%s' was expected instead "
4308 ass
->get_fullname().c_str(),
4309 base_fp_type
->get_typename().c_str(),
4310 local_fp_type
->get_typename().c_str());
4312 local_fp_type
->error("%s", info_par
.get_error_str_str().c_str());
4315 if (info_par
.needs_conversion())
4316 body
->set_needs_conversion();
4318 // Check for name equivalence.
4319 const Identifier
& base_fp_id
= base_fp
->get_id();
4320 const Identifier
& local_fp_id
= local_fp
->get_id();
4321 if (!(base_fp_id
== local_fp_id
))
4322 local_fp
->error("The name of parameter is not the same as in base "
4323 "template `%s': `%s' was expected instead of `%s'",
4324 ass
->get_fullname().c_str(),
4325 base_fp_id
.get_dispname().c_str(),
4326 local_fp_id
.get_dispname().c_str());
4327 // Check for restrictions: the derived must be same or more restrictive.
4328 if (base_fp
->get_asstype()==local_fp
->get_asstype() &&
4329 Template::is_less_restrictive(base_fp
->get_template_restriction(),
4330 local_fp
->get_template_restriction())) {
4331 local_fp
->error("The restriction of parameter is not the same or more "
4332 "restrictive as in base template `%s'", ass
->get_fullname().c_str());
4335 // Set the pointer to the body of base template.
4336 body
->set_base_template(base_template
->get_Template());
4339 void Def_Template::chk_recursive_derivation()
4341 if (recurs_deriv_checked
) return;
4342 if (base_template
) {
4343 ReferenceChain
refch(this, "While checking the chain of base templates");
4344 refch
.add(get_fullname());
4345 for (Def_Template
*iter
= base_template
; iter
; iter
= iter
->base_template
)
4347 if (iter
->recurs_deriv_checked
) break;
4348 else if (refch
.add(iter
->get_fullname()))
4349 iter
->recurs_deriv_checked
= true;
4353 recurs_deriv_checked
= true;
4356 void Def_Template::generate_code(output_struct
*target
, bool)
4358 type
->generate_code(target
);
4360 // Parameterized template. Generate code for a function which returns
4361 // a $(genname)_template and has the appropriate parameters.
4362 const string
& t_genname
= get_genname();
4363 const char *template_name
= t_genname
.c_str();
4364 const char *template_dispname
= id
->get_dispname().c_str();
4365 const string
& type_genname
= type
->get_genname_template(my_scope
);
4366 const char *type_genname_str
= type_genname
.c_str();
4368 // assemble the function body first (this also determines which parameters
4370 size_t nof_base_pars
= 0;
4371 char* function_body
= create_location_object(memptystr(), "TEMPLATE",
4373 if (debugger_active
) {
4374 function_body
= generate_code_debugger_function_init(function_body
, this);
4376 if (base_template
) {
4377 // modified template
4378 function_body
= mputprintf(function_body
, "%s ret_val(%s",
4380 base_template
->get_genname_from_scope(my_scope
).c_str());
4381 if (base_template
->fp_list
) {
4382 // the base template is also parameterized
4383 function_body
= mputc(function_body
, '(');
4384 nof_base_pars
= base_template
->fp_list
->get_nof_fps();
4385 for (size_t i
= 0; i
< nof_base_pars
; i
++) {
4386 if (i
> 0) function_body
= mputstr(function_body
, ", ");
4387 function_body
= mputstr(function_body
,
4388 fp_list
->get_fp_byIndex(i
)->get_id().get_name().c_str());
4390 function_body
= mputc(function_body
, ')');
4392 function_body
= mputstr(function_body
, ");\n");
4395 function_body
= mputprintf(function_body
, "%s ret_val;\n",
4398 if (erroneous_attrs
&& erroneous_attrs
->get_err_descr()) {
4399 function_body
= erroneous_attrs
->get_err_descr()->
4400 generate_code_str(function_body
, string("ret_val"));
4402 function_body
= body
->generate_code_init(function_body
, "ret_val");
4403 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4404 function_body
= Template::generate_restriction_check_code(function_body
,
4405 "ret_val", template_restriction
);
4406 if (debugger_active
) {
4407 function_body
= mputstr(function_body
,
4408 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
4409 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
4411 function_body
= mputstr(function_body
, "return ret_val;\n");
4412 // if the template modifies a parameterized template, then the inherited
4413 // formal parameters must always be displayed, otherwise generate a smart
4414 // formal parameter list (where the names of unused parameters are omitted)
4415 char *formal_par_list
= fp_list
->generate_code(memptystr(), nof_base_pars
);
4416 fp_list
->generate_code_defval(target
);
4418 target
->header
.function_prototypes
=
4419 mputprintf(target
->header
.function_prototypes
,
4420 "extern %s %s(%s);\n",
4421 type_genname_str
, template_name
, formal_par_list
);
4422 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
4426 "}\n\n", type_genname_str
, template_name
, formal_par_list
, function_body
);
4427 Free(formal_par_list
);
4428 Free(function_body
);
4430 // non-parameterized template
4432 Code::init_cdef(&cdef
);
4433 type
->generate_code_object(&cdef
, body
);
4434 cdef
.init
= update_location_object(cdef
.init
);
4435 if (base_template
) {
4436 // modified template
4437 if (base_template
->my_scope
->get_scope_mod_gen() ==
4438 my_scope
->get_scope_mod_gen()) {
4439 // if the base template is in the same module its body has to be
4440 // initialized first
4441 cdef
.init
= base_template
->body
->generate_code_init(cdef
.init
,
4442 base_template
->body
->get_lhs_name().c_str());
4444 if (use_runtime_2
&& body
->get_needs_conversion()) {
4445 Type
*body_type
= body
->get_my_governor()->get_type_refd_last();
4446 Type
*base_type
= base_template
->body
->get_my_governor()
4447 ->get_type_refd_last();
4448 if (!body_type
|| !base_type
)
4449 FATAL_ERROR("Def_Template::generate_code()");
4450 const string
& tmp_id
= body
->get_temporary_id();
4451 const char *tmp_id_str
= tmp_id
.c_str();
4452 // base template initialization
4453 cdef
.init
= mputprintf(cdef
.init
,
4455 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4456 "and `%s' are not compatible at run-time\");\n"
4458 body_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
4459 TypeConv::get_conv_func(base_type
, body_type
, my_scope
4460 ->get_scope_mod()).c_str(), tmp_id_str
, base_template
4461 ->get_genname_from_scope(my_scope
).c_str(), base_type
4462 ->get_typename().c_str(), body_type
->get_typename().c_str(),
4463 body
->get_lhs_name().c_str(), tmp_id_str
);
4465 cdef
.init
= mputprintf(cdef
.init
, "%s = %s;\n",
4466 body
->get_lhs_name().c_str(),
4467 base_template
->get_genname_from_scope(my_scope
).c_str());
4470 if (use_runtime_2
&& TypeConv::needs_conv_refd(body
))
4471 cdef
.init
= TypeConv::gen_conv_code_refd(cdef
.init
,
4472 body
->get_lhs_name().c_str(), body
);
4474 cdef
.init
= body
->generate_code_init(cdef
.init
,
4475 body
->get_lhs_name().c_str());
4476 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
4477 cdef
.init
= Template::generate_restriction_check_code(cdef
.init
,
4478 body
->get_lhs_name().c_str(), template_restriction
);
4479 target
->header
.global_vars
= mputstr(target
->header
.global_vars
,
4481 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
4483 target
->functions
.post_init
= mputstr(target
->functions
.post_init
,
4485 Code::free_cdef(&cdef
);
4489 void Def_Template::generate_code(Common::CodeGenHelper
& cgh
) {
4490 generate_code(cgh
.get_outputstruct(this));
4493 char *Def_Template::generate_code_str(char *str
)
4495 const string
& t_genname
= get_genname();
4496 const char *genname_str
= t_genname
.c_str();
4497 const string
& type_genname
= type
->get_genname_template(my_scope
);
4498 const char *type_genname_str
= type_genname
.c_str();
4500 const char *dispname_str
= id
->get_dispname().c_str();
4501 NOTSUPP("Code generation for parameterized local template `%s'",
4503 str
= mputprintf(str
, "/* NOT SUPPORTED: template %s */\n",
4506 if (base_template
) {
4507 // non-parameterized modified template
4508 if (use_runtime_2
&& body
->get_needs_conversion()) {
4509 Type
*body_type
= body
->get_my_governor()->get_type_refd_last();
4510 Type
*base_type
= base_template
->body
->get_my_governor()
4511 ->get_type_refd_last();
4512 if (!body_type
|| !base_type
)
4513 FATAL_ERROR("Def_Template::generate_code_str()");
4514 const string
& tmp_id
= body
->get_temporary_id();
4515 const char *tmp_id_str
= tmp_id
.c_str();
4516 str
= mputprintf(str
,
4518 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4519 "and `%s' are not compatible at run-time\");\n"
4521 body_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
4522 TypeConv::get_conv_func(base_type
, body_type
, my_scope
4523 ->get_scope_mod()).c_str(), tmp_id_str
, base_template
4524 ->get_genname_from_scope(my_scope
).c_str(), base_type
4525 ->get_typename().c_str(), body_type
->get_typename().c_str(),
4526 type_genname_str
, genname_str
, tmp_id_str
);
4528 // the object is initialized from the base template by the
4530 str
= mputprintf(str
, "%s %s(%s);\n", type_genname_str
, genname_str
,
4531 base_template
->get_genname_from_scope(my_scope
).c_str());
4533 // the modified body is assigned in the subsequent statements
4534 str
= body
->generate_code_init(str
, genname_str
);
4536 // non-parameterized non-modified template
4537 if (body
->has_single_expr()) {
4538 // the object is initialized by the constructor
4539 str
= mputprintf(str
, "%s %s(%s);\n", type_genname_str
,
4540 genname_str
, body
->get_single_expr(false).c_str());
4541 // make sure the template's code is not generated twice (TR: HU56425)
4542 body
->set_code_generated();
4544 // the default constructor is used
4545 str
= mputprintf(str
, "%s %s;\n", type_genname_str
, genname_str
);
4546 // the body is assigned in the subsequent statements
4547 str
= body
->generate_code_init(str
, genname_str
);
4550 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
4551 str
= Template::generate_restriction_check_code(str
, genname_str
,
4552 template_restriction
);
4554 if (debugger_active
) {
4555 str
= generate_code_debugger_add_var(str
, this);
4560 void Def_Template::ilt_generate_code(ILT
*ilt
)
4562 const string
& t_genname
= get_genname();
4563 const char *genname_str
= t_genname
.c_str();
4564 char*& def
=ilt
->get_out_def();
4565 char*& init
=ilt
->get_out_branches();
4567 const char *dispname_str
= id
->get_dispname().c_str();
4568 NOTSUPP("Code generation for parameterized local template `%s'",
4570 def
= mputprintf(def
, "/* NOT SUPPORTED: template %s */\n", dispname_str
);
4571 init
= mputprintf(init
, "/* NOT SUPPORTED: template %s */\n",
4574 // non-parameterized template
4575 // use the default constructor for initialization
4576 def
= mputprintf(def
, "%s %s;\n",
4577 type
->get_genname_template(my_scope
).c_str(), genname_str
);
4578 if (base_template
) {
4579 // copy the base template with an assignment
4580 init
= mputprintf(init
, "%s = %s;\n", genname_str
,
4581 base_template
->get_genname_from_scope(my_scope
).c_str());
4583 // finally assign the body
4584 init
= body
->generate_code_init(init
, genname_str
);
4585 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4586 init
= Template::generate_restriction_check_code(init
, genname_str
,
4587 template_restriction
);
4591 void Def_Template::dump_internal(unsigned level
) const
4593 DEBUG(level
, "Template: %s", id
->get_dispname().c_str());
4594 if (fp_list
) fp_list
->dump(level
+ 1);
4596 DEBUG(level
+ 1, "modifies: %s", derived_ref
->get_dispname().c_str());
4597 if (template_restriction
!=TR_NONE
)
4598 DEBUG(level
+ 1, "restriction: %s",
4599 Template::get_restriction_name(template_restriction
));
4600 type
->dump(level
+ 1);
4601 body
->dump(level
+ 1);
4604 // =================================
4606 // =================================
4608 Def_Var::Def_Var(Identifier
*p_id
, Type
*p_type
, Value
*p_initial_value
)
4609 : Definition(A_VAR
, p_id
), type(p_type
), initial_value(p_initial_value
)
4611 if (!p_type
) FATAL_ERROR("Ttcn::Def_Var::Def_Var()");
4612 type
->set_ownertype(Type::OT_VAR_DEF
, this);
4618 delete initial_value
;
4621 Def_Var
*Def_Var::clone() const
4623 FATAL_ERROR("Def_Var::clone");
4626 void Def_Var::set_fullname(const string
& p_fullname
)
4628 Definition::set_fullname(p_fullname
);
4629 type
->set_fullname(p_fullname
+ ".<type>");
4631 initial_value
->set_fullname(p_fullname
+ ".<initial_value>");
4634 void Def_Var::set_my_scope(Scope
*p_scope
)
4636 Definition::set_my_scope(p_scope
);
4637 type
->set_my_scope(p_scope
);
4638 if (initial_value
) initial_value
->set_my_scope(p_scope
);
4641 Type
*Def_Var::get_Type()
4650 Error_Context
cntxt(this, "In variable definition `%s'",
4651 id
->get_dispname().c_str());
4652 type
->set_genname(_T_
, get_genname());
4655 Type
*t
= type
->get_type_refd_last();
4656 switch (t
->get_typetype()) {
4658 error("Variable cannot be defined for port type `%s'",
4659 t
->get_fullname().c_str());
4661 case Type::T_SIGNATURE
:
4662 error("Variable cannot be defined for signature `%s'",
4663 t
->get_fullname().c_str());
4666 if (initial_value
) {
4667 initial_value
->set_my_governor(type
);
4668 type
->chk_this_value_ref(initial_value
);
4669 type
->chk_this_value(initial_value
, this, is_local() ?
4670 Type::EXPECTED_DYNAMIC_VALUE
: Type::EXPECTED_STATIC_VALUE
,
4671 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
4672 if (!semantic_check_only
) {
4673 initial_value
->set_genname_recursive(get_genname());
4674 initial_value
->set_code_section(GovernedSimple::CS_INLINE
);
4680 if (w_attrib_path
) {
4681 w_attrib_path
->chk_global_attrib();
4682 w_attrib_path
->chk_no_qualif();
4686 bool Def_Var::chk_identical(Definition
*p_def
)
4690 if (p_def
->get_asstype() != A_VAR
) {
4691 const char *dispname_str
= id
->get_dispname().c_str();
4692 error("Local definition `%s' is a variable, but the definition "
4693 "inherited from component type `%s' is a %s", dispname_str
,
4694 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
4695 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
4698 Def_Var
*p_def_var
= dynamic_cast<Def_Var
*>(p_def
);
4699 if (!p_def_var
) FATAL_ERROR("Def_Var::chk_identical()");
4700 if (!type
->is_identical(p_def_var
->type
)) {
4701 const char *dispname_str
= id
->get_dispname().c_str();
4702 type
->error("Local variable `%s' has type `%s', but the variable "
4703 "inherited from component type `%s' has type `%s'", dispname_str
,
4704 type
->get_typename().c_str(),
4705 p_def_var
->get_my_scope()->get_fullname().c_str(),
4706 p_def_var
->type
->get_typename().c_str());
4707 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4710 if (initial_value
) {
4711 if (p_def_var
->initial_value
) {
4712 if (!initial_value
->is_unfoldable() &&
4713 !p_def_var
->initial_value
->is_unfoldable() &&
4714 !(*initial_value
== *p_def_var
->initial_value
)) {
4715 const char *dispname_str
= id
->get_dispname().c_str();
4716 initial_value
->warning("Local variable `%s' and the variable "
4717 "inherited from component type `%s' have different initial values",
4718 dispname_str
, p_def_var
->get_my_scope()->get_fullname().c_str());
4719 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4722 const char *dispname_str
= id
->get_dispname().c_str();
4723 initial_value
->warning("Local variable `%s' has initial value, but "
4724 "the variable inherited from component type `%s' does not",
4725 dispname_str
, p_def_var
->get_my_scope()->get_fullname().c_str());
4726 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4728 } else if (p_def_var
->initial_value
) {
4729 const char *dispname_str
= id
->get_dispname().c_str();
4730 warning("Local variable `%s' does not have initial value, but the "
4731 "variable inherited from component type `%s' has", dispname_str
,
4732 p_def_var
->get_my_scope()->get_fullname().c_str());
4733 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4738 void Def_Var::generate_code(output_struct
*target
, bool clean_up
)
4740 type
->generate_code(target
);
4742 Code::init_cdef(&cdef
);
4743 type
->generate_code_object(&cdef
, my_scope
, get_genname(), 0, false);
4744 Code::merge_cdef(target
, &cdef
);
4745 Code::free_cdef(&cdef
);
4746 if (initial_value
) {
4747 target
->functions
.init_comp
=
4748 initial_value
->generate_code_init(target
->functions
.init_comp
,
4749 initial_value
->get_lhs_name().c_str());
4750 } else if (clean_up
) { // No initial value.
4751 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
4752 "%s.clean_up();\n", get_genname().c_str());
4756 void Def_Var::generate_code(CodeGenHelper
& cgh
)
4758 generate_code(cgh
.get_outputstruct(this));
4761 char *Def_Var::generate_code_str(char *str
)
4763 const string
& t_genname
= get_genname();
4764 const char *genname_str
= t_genname
.c_str();
4765 if (initial_value
&& initial_value
->has_single_expr()) {
4766 // the initial value can be represented by a single C++ expression
4767 // the object is initialized by the constructor
4768 str
= mputprintf(str
, "%s %s(%s);\n",
4769 type
->get_genname_value(my_scope
).c_str(), genname_str
,
4770 initial_value
->get_single_expr().c_str());
4772 // use the default constructor
4773 str
= mputprintf(str
, "%s %s;\n",
4774 type
->get_genname_value(my_scope
).c_str(), genname_str
);
4775 if (initial_value
) {
4776 // the initial value is assigned using subsequent statements
4777 str
= initial_value
->generate_code_init(str
, genname_str
);
4780 if (debugger_active
) {
4781 str
= generate_code_debugger_add_var(str
, this);
4786 void Def_Var::ilt_generate_code(ILT
*ilt
)
4788 const string
& t_genname
= get_genname();
4789 const char *genname_str
= t_genname
.c_str();
4790 char*& def
=ilt
->get_out_def();
4791 char*& init
=ilt
->get_out_branches();
4792 def
= mputprintf(def
, "%s %s;\n", type
->get_genname_value(my_scope
).c_str(),
4795 init
= initial_value
->generate_code_init(init
, genname_str
);
4798 char *Def_Var::generate_code_init_comp(char *str
, Definition
*base_defn
)
4800 if (initial_value
) {
4801 str
= initial_value
->generate_code_init(str
,
4802 base_defn
->get_genname_from_scope(my_scope
).c_str());
4807 void Def_Var::dump_internal(unsigned level
) const
4809 DEBUG(level
, "Variable %s", id
->get_dispname().c_str());
4810 type
->dump(level
+ 1);
4811 if (initial_value
) initial_value
->dump(level
+ 1);
4814 // =================================
4815 // ===== Def_Var_Template
4816 // =================================
4818 Def_Var_Template::Def_Var_Template(Identifier
*p_id
, Type
*p_type
,
4819 Template
*p_initial_value
, template_restriction_t p_template_restriction
)
4820 : Definition(A_VAR_TEMPLATE
, p_id
), type(p_type
),
4821 initial_value(p_initial_value
), template_restriction(p_template_restriction
)
4823 if (!p_type
) FATAL_ERROR("Ttcn::Def_Var_Template::Def_Var_Template()");
4824 type
->set_ownertype(Type::OT_VARTMPL_DEF
, this);
4827 Def_Var_Template::~Def_Var_Template()
4830 delete initial_value
;
4833 Def_Var_Template
*Def_Var_Template::clone() const
4835 FATAL_ERROR("Def_Var_Template::clone");
4838 void Def_Var_Template::set_fullname(const string
& p_fullname
)
4840 Definition::set_fullname(p_fullname
);
4841 type
->set_fullname(p_fullname
+ ".<type>");
4843 initial_value
->set_fullname(p_fullname
+ ".<initial_value>");
4846 void Def_Var_Template::set_my_scope(Scope
*p_scope
)
4848 Definition::set_my_scope(p_scope
);
4849 type
->set_my_scope(p_scope
);
4850 if (initial_value
) initial_value
->set_my_scope(p_scope
);
4853 Type
*Def_Var_Template::get_Type()
4859 void Def_Var_Template::chk()
4862 Error_Context
cntxt(this, "In template variable definition `%s'",
4863 id
->get_dispname().c_str());
4864 type
->set_genname(_T_
, get_genname());
4867 Type
*t
= type
->get_type_refd_last();
4868 if (t
->get_typetype() == Type::T_PORT
) {
4869 error("Template variable cannot be defined for port type `%s'",
4870 t
->get_fullname().c_str());
4873 if (initial_value
) {
4874 initial_value
->set_my_governor(type
);
4875 initial_value
->flatten(false);
4877 if (initial_value
->get_templatetype() == Template::CSTR_PATTERN
&&
4878 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
4879 initial_value
->set_templatetype(Template::USTR_PATTERN
);
4880 initial_value
->get_ustr_pattern()->set_pattern_type(
4881 PatternString::USTR_PATTERN
);
4884 type
->chk_this_template_ref(initial_value
);
4885 // temporary hack: to allow incomplete body as initial value
4886 // checking as a modified template, but without a base template
4887 type
->chk_this_template_generic(initial_value
, INCOMPLETE_ALLOWED
,
4888 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, IMPLICIT_OMIT
, 0);
4889 gen_restriction_check
=
4890 initial_value
->chk_restriction("template variable definition",
4891 template_restriction
, initial_value
);
4892 if (!semantic_check_only
) {
4893 initial_value
->set_genname_recursive(get_genname());
4894 initial_value
->set_code_section(GovernedSimple::CS_INLINE
);
4897 if (w_attrib_path
) {
4898 w_attrib_path
->chk_global_attrib();
4899 w_attrib_path
->chk_no_qualif();
4903 bool Def_Var_Template::chk_identical(Definition
*p_def
)
4907 if (p_def
->get_asstype() != A_VAR_TEMPLATE
) {
4908 const char *dispname_str
= id
->get_dispname().c_str();
4909 error("Local definition `%s' is a template variable, but the definition "
4910 "inherited from component type `%s' is a %s", dispname_str
,
4911 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
4912 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
4915 Def_Var_Template
*p_def_var_template
=
4916 dynamic_cast<Def_Var_Template
*>(p_def
);
4917 if (!p_def_var_template
) FATAL_ERROR("Def_Var_Template::chk_identical()");
4918 if (!type
->is_identical(p_def_var_template
->type
)) {
4919 const char *dispname_str
= id
->get_dispname().c_str();
4920 type
->error("Local template variable `%s' has type `%s', but the "
4921 "template variable inherited from component type `%s' has type `%s'",
4922 dispname_str
, type
->get_typename().c_str(),
4923 p_def_var_template
->get_my_scope()->get_fullname().c_str(),
4924 p_def_var_template
->type
->get_typename().c_str());
4925 p_def_var_template
->note("The inherited template variable `%s' is here",
4929 if (initial_value
) {
4930 if (!p_def_var_template
->initial_value
) {
4931 const char *dispname_str
= id
->get_dispname().c_str();
4932 initial_value
->warning("Local template variable `%s' has initial "
4933 "value, but the template variable inherited from component type "
4934 "`%s' does not", dispname_str
,
4935 p_def_var_template
->get_my_scope()->get_fullname().c_str());
4936 p_def_var_template
->note("The inherited template variable `%s' is here",
4939 } else if (p_def_var_template
->initial_value
) {
4940 const char *dispname_str
= id
->get_dispname().c_str();
4941 warning("Local template variable `%s' does not have initial value, but "
4942 "the template variable inherited from component type `%s' has",
4944 p_def_var_template
->get_my_scope()->get_fullname().c_str());
4945 p_def_var_template
->note("The inherited template variable `%s' is here",
4951 void Def_Var_Template::generate_code(output_struct
*target
, bool clean_up
)
4953 type
->generate_code(target
);
4955 Code::init_cdef(&cdef
);
4956 type
->generate_code_object(&cdef
, my_scope
, get_genname(), 0, true);
4957 Code::merge_cdef(target
, &cdef
);
4958 Code::free_cdef(&cdef
);
4959 if (initial_value
) {
4960 if (Common::Type::T_SEQOF
== initial_value
->get_my_governor()->get_typetype() ||
4961 Common::Type::T_ARRAY
== initial_value
->get_my_governor()->get_typetype()) {
4962 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
4963 "%s.remove_all_permutations();\n", initial_value
->get_lhs_name().c_str());
4965 target
->functions
.init_comp
=
4966 initial_value
->generate_code_init(target
->functions
.init_comp
,
4967 initial_value
->get_lhs_name().c_str());
4968 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4969 target
->functions
.init_comp
= Template::generate_restriction_check_code(
4970 target
->functions
.init_comp
, initial_value
->get_lhs_name().c_str(),
4971 template_restriction
);
4972 } else if (clean_up
) { // No initial value.
4973 // Always reset component variables/variable templates on component
4974 // reinitialization. Fix for HM79493.
4975 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
4976 "%s.clean_up();\n", get_genname().c_str());
4980 void Def_Var_Template::generate_code(CodeGenHelper
& cgh
)
4982 generate_code(cgh
.get_outputstruct(this));
4985 char *Def_Var_Template::generate_code_str(char *str
)
4987 const string
& t_genname
= get_genname();
4988 const char *genname_str
= t_genname
.c_str();
4989 if (initial_value
&& initial_value
->has_single_expr()) {
4990 // The initial value can be represented by a single C++ expression
4991 // the object is initialized by the constructor.
4992 str
= mputprintf(str
, "%s %s(%s);\n",
4993 type
->get_genname_template(my_scope
).c_str(), genname_str
,
4994 initial_value
->get_single_expr(false).c_str());
4996 // Use the default constructor.
4997 str
= mputprintf(str
, "%s %s;\n",
4998 type
->get_genname_template(my_scope
).c_str(), genname_str
);
4999 if (initial_value
) {
5000 // The initial value is assigned using subsequent statements.
5001 if (use_runtime_2
&& TypeConv::needs_conv_refd(initial_value
))
5002 str
= TypeConv::gen_conv_code_refd(str
, genname_str
, initial_value
);
5003 else str
= initial_value
->generate_code_init(str
, genname_str
);
5006 if (initial_value
&& template_restriction
!= TR_NONE
5007 && gen_restriction_check
)
5008 str
= Template::generate_restriction_check_code(str
, genname_str
,
5009 template_restriction
);
5010 if (debugger_active
) {
5011 str
= generate_code_debugger_add_var(str
, this);
5016 void Def_Var_Template::ilt_generate_code(ILT
*ilt
)
5018 const string
& t_genname
= get_genname();
5019 const char *genname_str
= t_genname
.c_str();
5020 char*& def
=ilt
->get_out_def();
5021 char*& init
=ilt
->get_out_branches();
5022 def
= mputprintf(def
, "%s %s;\n",
5023 type
->get_genname_template(my_scope
).c_str(), genname_str
);
5024 if (initial_value
) {
5025 init
= initial_value
->generate_code_init(init
, genname_str
);
5026 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
5027 init
= Template::generate_restriction_check_code(init
, genname_str
,
5028 template_restriction
);
5032 char *Def_Var_Template::generate_code_init_comp(char *str
,
5033 Definition
*base_defn
)
5035 if (initial_value
) {
5036 str
= initial_value
->generate_code_init(str
,
5037 base_defn
->get_genname_from_scope(my_scope
).c_str());
5038 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
5039 str
= Template::generate_restriction_check_code(str
,
5040 base_defn
->get_genname_from_scope(my_scope
).c_str(),
5041 template_restriction
);
5046 void Def_Var_Template::dump_internal(unsigned level
) const
5048 DEBUG(level
, "Template variable %s", id
->get_dispname().c_str());
5049 if (template_restriction
!=TR_NONE
)
5050 DEBUG(level
+ 1, "restriction: %s",
5051 Template::get_restriction_name(template_restriction
));
5052 type
->dump(level
+ 1);
5053 if (initial_value
) initial_value
->dump(level
+ 1);
5056 // =================================
5058 // =================================
5060 Def_Timer::~Def_Timer()
5063 delete default_duration
;
5066 Def_Timer
*Def_Timer::clone() const
5068 FATAL_ERROR("Def_Timer::clone");
5071 void Def_Timer::set_fullname(const string
& p_fullname
)
5073 Definition::set_fullname(p_fullname
);
5074 if (dimensions
) dimensions
->set_fullname(p_fullname
+ ".<dimensions>");
5075 if (default_duration
)
5076 default_duration
->set_fullname(p_fullname
+ ".<default_duration>");
5079 void Def_Timer::set_my_scope(Scope
*p_scope
)
5081 Definition::set_my_scope(p_scope
);
5082 if (dimensions
) dimensions
->set_my_scope(p_scope
);
5083 if (default_duration
) default_duration
->set_my_scope(p_scope
);
5086 ArrayDimensions
*Def_Timer::get_Dimensions()
5088 if (!checked
) chk();
5092 void Def_Timer::chk()
5095 Error_Context
cntxt(this, "In timer definition `%s'",
5096 id
->get_dispname().c_str());
5097 if (dimensions
) dimensions
->chk();
5098 if (default_duration
) {
5099 Error_Context
cntxt2(default_duration
, "In default duration");
5100 if (dimensions
) chk_array_duration(default_duration
);
5101 else chk_single_duration(default_duration
);
5102 if (!semantic_check_only
) {
5103 default_duration
->set_code_section(GovernedSimple::CS_POST_INIT
);
5107 if (w_attrib_path
) {
5108 w_attrib_path
->chk_global_attrib();
5109 w_attrib_path
->chk_no_qualif();
5113 bool Def_Timer::chk_identical(Definition
*p_def
)
5117 if (p_def
->get_asstype() != A_TIMER
) {
5118 const char *dispname_str
= id
->get_dispname().c_str();
5119 error("Local definition `%s' is a timer, but the definition inherited "
5120 "from component type `%s' is a %s", dispname_str
,
5121 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
5122 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
5125 Def_Timer
*p_def_timer
= dynamic_cast<Def_Timer
*>(p_def
);
5126 if (!p_def_timer
) FATAL_ERROR("Def_Timer::chk_identical()");
5128 if (p_def_timer
->dimensions
) {
5129 if (!dimensions
->is_identical(p_def_timer
->dimensions
)) {
5130 const char *dispname_str
= id
->get_dispname().c_str();
5131 error("Local timer `%s' and the timer inherited from component type "
5132 "`%s' have different array dimensions", dispname_str
,
5133 p_def_timer
->get_my_scope()->get_fullname().c_str());
5134 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5138 const char *dispname_str
= id
->get_dispname().c_str();
5139 error("Local definition `%s' is a timer array, but the definition "
5140 "inherited from component type `%s' is a single timer", dispname_str
,
5141 p_def_timer
->get_my_scope()->get_fullname().c_str());
5142 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5145 } else if (p_def_timer
->dimensions
) {
5146 const char *dispname_str
= id
->get_dispname().c_str();
5147 error("Local definition `%s' is a single timer, but the definition "
5148 "inherited from component type `%s' is a timer array", dispname_str
,
5149 p_def_timer
->get_my_scope()->get_fullname().c_str());
5150 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5153 if (default_duration
) {
5154 if (p_def_timer
->default_duration
) {
5155 if (!default_duration
->is_unfoldable() &&
5156 !p_def_timer
->default_duration
->is_unfoldable() &&
5157 !(*default_duration
== *p_def_timer
->default_duration
)) {
5158 const char *dispname_str
= id
->get_dispname().c_str();
5159 default_duration
->warning("Local timer `%s' and the timer inherited "
5160 "from component type `%s' have different default durations",
5161 dispname_str
, p_def_timer
->get_my_scope()->get_fullname().c_str());
5162 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5165 const char *dispname_str
= id
->get_dispname().c_str();
5166 default_duration
->error("Local timer `%s' has default duration, but "
5167 "the timer inherited from component type `%s' does not", dispname_str
,
5168 p_def_timer
->get_my_scope()->get_fullname().c_str());
5169 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5172 } else if (p_def_timer
->default_duration
) {
5173 const char *dispname_str
= id
->get_dispname().c_str();
5174 error("Local timer `%s' does not have default duration, but the timer "
5175 "inherited from component type `%s' has", dispname_str
,
5176 p_def_timer
->get_my_scope()->get_fullname().c_str());
5177 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5183 bool Def_Timer::has_default_duration(FieldOrArrayRefs
*p_subrefs
)
5185 // return true in case of any uncertainity
5186 if (!default_duration
) return false;
5187 else if (!dimensions
|| !p_subrefs
) return true;
5188 Value
*v
= default_duration
;
5189 size_t nof_dims
= dimensions
->get_nof_dims();
5190 size_t nof_refs
= p_subrefs
->get_nof_refs();
5191 size_t upper_limit
= nof_dims
< nof_refs
? nof_dims
: nof_refs
;
5192 for (size_t i
= 0; i
< upper_limit
; i
++) {
5193 v
= v
->get_value_refd_last();
5194 if (v
->get_valuetype() != Value::V_SEQOF
) break;
5195 FieldOrArrayRef
*ref
= p_subrefs
->get_ref(i
);
5196 if (ref
->get_type() != FieldOrArrayRef::ARRAY_REF
) return true;
5197 Value
*v_index
= ref
->get_val()->get_value_refd_last();
5198 if (v_index
->get_valuetype() != Value::V_INT
) return true;
5199 Int index
= v_index
->get_val_Int()->get_val()
5200 - dimensions
->get_dim_byIndex(i
)->get_offset();
5201 if (index
>= 0 && index
< static_cast<Int
>(v
->get_nof_comps()))
5202 v
= v
->get_comp_byIndex(index
);
5205 return v
->get_valuetype() != Value::V_NOTUSED
;
5208 void Def_Timer::chk_single_duration(Value
*dur
)
5210 dur
->chk_expr_float(is_local() ?
5211 Type::EXPECTED_DYNAMIC_VALUE
: Type::EXPECTED_STATIC_VALUE
);
5212 Value
*v
= dur
->get_value_refd_last();
5213 if (v
->get_valuetype() == Value::V_REAL
) {
5214 ttcn3float v_real
= v
->get_val_Real();
5215 if ( (v_real
<0.0) || isSpecialFloatValue(v_real
) ) {
5216 dur
->error("A non-negative float value was expected "
5217 "as timer duration instead of `%s'", Real2string(v_real
).c_str());
5222 void Def_Timer::chk_array_duration(Value
*dur
, size_t start_dim
)
5224 ArrayDimension
*dim
= dimensions
->get_dim_byIndex(start_dim
);
5225 bool array_size_known
= !dim
->get_has_error();
5226 size_t array_size
= 0;
5227 if (array_size_known
) array_size
= dim
->get_size();
5228 Value
*v
= dur
->get_value_refd_last();
5229 switch (v
->get_valuetype()) {
5230 case Value::V_ERROR
:
5232 case Value::V_SEQOF
: {
5233 size_t nof_vs
= v
->get_nof_comps();
5234 // Value-list notation.
5235 if (!v
->is_indexed()) {
5236 if (array_size_known
) {
5237 if (array_size
> nof_vs
) {
5238 dur
->error("Too few elements in the default duration of timer "
5239 "array: %lu was expected instead of %lu",
5240 (unsigned long)array_size
, (unsigned long)nof_vs
);
5241 } else if (array_size
< nof_vs
) {
5242 dur
->error("Too many elements in the default duration of timer "
5243 "array: %lu was expected instead of %lu",
5244 (unsigned long)array_size
, (unsigned long)nof_vs
);
5247 bool last_dimension
= start_dim
+ 1 >= dimensions
->get_nof_dims();
5248 for (size_t i
= 0; i
< nof_vs
; i
++) {
5249 Value
*array_v
= v
->get_comp_byIndex(i
);
5250 if (array_v
->get_valuetype() == Value::V_NOTUSED
) continue;
5251 if (last_dimension
) chk_single_duration(array_v
);
5252 else chk_array_duration(array_v
, start_dim
+ 1);
5255 // Indexed-notation.
5256 bool last_dimension
= start_dim
+ 1 >= dimensions
->get_nof_dims();
5257 map
<Int
, Int
> index_map
;
5258 for (size_t i
= 0; i
< nof_vs
; i
++) {
5259 Value
*array_v
= v
->get_comp_byIndex(i
);
5260 if (array_v
->get_valuetype() == Value::V_NOTUSED
) continue;
5261 if (last_dimension
) chk_single_duration(array_v
);
5262 else chk_array_duration(array_v
, start_dim
+ 1);
5263 Error_Context
cntxt(this, "In timer array element %lu",
5264 (unsigned long)(i
+ 1));
5265 Value
*index
= v
->get_index_byIndex(i
);
5266 dim
->chk_index(index
, Type::EXPECTED_DYNAMIC_VALUE
);
5267 if (index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
5268 const int_val_t
*index_int
= index
->get_value_refd_last()
5270 if (*index_int
> INT_MAX
) {
5271 index
->error("An integer value less than `%d' was expected for "
5272 "indexing timer array instead of `%s'", INT_MAX
,
5273 (index_int
->t_str()).c_str());
5274 index
->set_valuetype(Value::V_ERROR
);
5276 Int index_val
= index_int
->get_val();
5277 if (index_map
.has_key(index_val
)) {
5278 index
->error("Duplicate index value `%s' for timer array "
5279 "elements `%s' and `%s'",
5280 Int2string(index_val
).c_str(),
5281 Int2string((Int
)i
+ 1).c_str(),
5282 Int2string(*index_map
[index_val
]).c_str());
5283 index
->set_valuetype(Value::V_ERROR
);
5285 index_map
.add(index_val
, new Int((Int
)i
+ 1));
5290 // It's not possible to have "index_map.size() > array_size", since we
5291 // add only correct constant-index values into the map. It's possible
5292 // to create partially initialized timer arrays.
5293 for (size_t i
= 0; i
< index_map
.size(); i
++)
5294 delete index_map
.get_nth_elem(i
);
5299 if (array_size_known
) {
5300 dur
->error("An array value (with %lu elements) was expected as "
5301 "default duration of timer array",
5302 (unsigned long)array_size
);
5304 dur
->error("An array value was expected as default duration of timer "
5307 dur
->set_valuetype(Value::V_ERROR
);
5312 void Def_Timer::generate_code(output_struct
*target
, bool)
5314 const string
& t_genname
= get_genname();
5315 const char *genname_str
= t_genname
.c_str();
5316 const string
& dispname
= id
->get_dispname();
5319 const string
& array_type
= dimensions
->get_timer_type();
5320 const char *array_type_str
= array_type
.c_str();
5321 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5322 "extern %s %s;\n", array_type_str
, genname_str
);
5323 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5324 "%s %s;\n", array_type_str
, genname_str
);
5325 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
, "{\n"
5326 "static const char * const timer_name = \"");
5327 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
5329 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
5331 "%s.set_name(timer_name);\n"
5332 "}\n", genname_str
);
5333 if (default_duration
) target
->functions
.post_init
=
5334 generate_code_array_duration(target
->functions
.post_init
, genname_str
,
5338 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5339 "extern TIMER %s;\n", genname_str
);
5340 if (default_duration
) {
5341 // has default duration
5342 Value
*v
= default_duration
->get_value_refd_last();
5343 if (v
->get_valuetype() == Value::V_REAL
) {
5344 // duration is known at compilation time -> set in the constructor
5345 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5346 "TIMER %s(\"%s\", %s);\n", genname_str
, dispname
.c_str(),
5347 v
->get_single_expr().c_str());
5349 // duration is known only at runtime -> set in post_init
5350 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5351 "TIMER %s(\"%s\");\n", genname_str
, dispname
.c_str());
5352 expression_struct expr
;
5353 Code::init_expr(&expr
);
5354 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5356 default_duration
->generate_code_expr(&expr
);
5357 expr
.expr
= mputc(expr
.expr
, ')');
5358 target
->functions
.post_init
=
5359 Code::merge_free_expr(target
->functions
.post_init
, &expr
);
5362 // does not have default duration
5363 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5364 "TIMER %s(\"%s\");\n", genname_str
, dispname
.c_str());
5369 void Def_Timer::generate_code(CodeGenHelper
& cgh
) {
5370 generate_code(cgh
.get_current_outputstruct());
5373 char *Def_Timer::generate_code_array_duration(char *str
,
5374 const char *object_name
, Value
*dur
, size_t start_dim
)
5376 ArrayDimension
*dim
= dimensions
->get_dim_byIndex(start_dim
);
5377 size_t dim_size
= dim
->get_size();
5378 Value
*v
= dur
->get_value_refd_last();
5379 if (v
->get_valuetype() != Value::V_SEQOF
5380 || (v
->get_nof_comps() != dim_size
&& !v
->is_indexed()))
5381 FATAL_ERROR("Def_Timer::generate_code_array_duration()");
5382 // Value-list notation.
5383 if (!v
->is_indexed()) {
5384 if (start_dim
+ 1 < dimensions
->get_nof_dims()) {
5385 // There are more dimensions, the elements of "v" are arrays a
5386 // temporary reference shall be introduced if the next dimension has
5387 // more than 1 elements.
5388 bool temp_ref_needed
=
5389 dimensions
->get_dim_byIndex(start_dim
+ 1)->get_size() > 1;
5390 for (size_t i
= 0; i
< dim_size
; i
++) {
5391 Value
*v_elem
= v
->get_comp_byIndex(i
);
5392 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5393 if (temp_ref_needed
) {
5394 const string
& tmp_id
= my_scope
->get_scope_mod_gen()
5395 ->get_temporary_id();
5396 const char *tmp_str
= tmp_id
.c_str();
5397 str
= mputprintf(str
, "{\n"
5398 "%s& %s = %s.array_element(%lu);\n",
5399 dimensions
->get_timer_type(start_dim
+ 1).c_str(),
5400 tmp_str
, object_name
, (unsigned long)i
);
5401 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5403 str
= mputstr(str
, "}\n");
5405 char *tmp_str
= mprintf("%s.array_element(%lu)", object_name
,
5407 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5413 // We are in the last dimension, the elements of "v" are floats.
5414 for (size_t i
= 0; i
< dim_size
; i
++) {
5415 Value
*v_elem
= v
->get_comp_byIndex(i
);
5416 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5417 expression_struct expr
;
5418 Code::init_expr(&expr
);
5419 expr
.expr
= mputprintf(expr
.expr
,
5420 "%s.array_element(%lu).set_default_duration(",
5421 object_name
, (unsigned long)i
);
5422 v_elem
->generate_code_expr(&expr
);
5423 expr
.expr
= mputc(expr
.expr
, ')');
5424 str
= Code::merge_free_expr(str
, &expr
);
5427 // Indexed-list notation.
5429 if (start_dim
+ 1 < dimensions
->get_nof_dims()) {
5430 bool temp_ref_needed
=
5431 dimensions
->get_dim_byIndex(start_dim
+ 1)->get_size() > 1;
5432 for (size_t i
= 0; i
< v
->get_nof_comps(); i
++) {
5433 Value
*v_elem
= v
->get_comp_byIndex(i
);
5434 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5435 if (temp_ref_needed
) {
5436 const string
& tmp_id
= my_scope
->get_scope_mod_gen()
5437 ->get_temporary_id();
5438 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5439 ->get_temporary_id();
5440 const char *tmp_str
= tmp_id
.c_str();
5441 str
= mputstr(str
, "{\n");
5442 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5443 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5445 str
= mputprintf(str
, "%s& %s = %s.array_element(%s);\n",
5446 dimensions
->get_timer_type(start_dim
+ 1).c_str(),
5447 tmp_str
, object_name
, idx_id
.c_str());
5448 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5450 str
= mputstr(str
, "}\n");
5452 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5453 ->get_temporary_id();
5454 str
= mputstr(str
, "{\n");
5455 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5456 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5458 char *tmp_str
= mprintf("%s.array_element(%s)", object_name
,
5460 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5462 str
= mputstr(str
, "}\n");
5467 for (size_t i
= 0; i
< v
->get_nof_comps(); i
++) {
5468 Value
*v_elem
= v
->get_comp_byIndex(i
);
5469 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5470 expression_struct expr
;
5471 Code::init_expr(&expr
);
5472 str
= mputstr(str
, "{\n");
5473 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5474 ->get_temporary_id();
5475 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5476 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5478 str
= mputprintf(str
,
5479 "%s.array_element(%s).set_default_duration(",
5480 object_name
, idx_id
.c_str());
5481 v_elem
->generate_code_expr(&expr
);
5482 expr
.expr
= mputc(expr
.expr
, ')');
5483 str
= Code::merge_free_expr(str
, &expr
);
5484 str
= mputstr(str
, "}\n");
5491 char *Def_Timer::generate_code_str(char *str
)
5493 const string
& t_genname
= get_genname();
5494 const char *genname_str
= t_genname
.c_str();
5495 const string
& dispname
= id
->get_dispname();
5498 const string
& array_type
= dimensions
->get_timer_type();
5499 const char *array_type_str
= array_type
.c_str();
5500 str
= mputprintf(str
, "%s %s;\n", array_type_str
, genname_str
);
5501 str
= mputstr(str
, "{\n"
5502 "static const char * const timer_name = \"");
5503 str
= mputstr(str
, dispname
.c_str());
5504 str
= mputprintf(str
, "\";\n"
5505 "%s.set_name(timer_name);\n"
5506 "}\n", genname_str
);
5507 if (default_duration
) str
= generate_code_array_duration(str
,
5508 genname_str
, default_duration
);
5511 if (default_duration
&& default_duration
->has_single_expr()) {
5512 // the default duration can be passed to the constructor
5513 str
= mputprintf(str
, "TIMER %s(\"%s\", %s);\n", genname_str
,
5514 dispname
.c_str(), default_duration
->get_single_expr().c_str());
5516 // only the name is passed to the constructor
5517 str
= mputprintf(str
, "TIMER %s(\"%s\");\n", genname_str
,
5519 if (default_duration
) {
5520 // the default duration is set explicitly
5521 expression_struct expr
;
5522 Code::init_expr(&expr
);
5523 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5525 default_duration
->generate_code_expr(&expr
);
5526 expr
.expr
= mputc(expr
.expr
, ')');
5527 str
= Code::merge_free_expr(str
, &expr
);
5531 if (debugger_active
) {
5532 str
= generate_code_debugger_add_var(str
, this);
5537 void Def_Timer::ilt_generate_code(ILT
*ilt
)
5539 const string
& t_genname
= get_genname();
5540 const char *genname_str
= t_genname
.c_str();
5541 const string
& dispname
= id
->get_dispname();
5543 char*& def
= ilt
->get_out_def();
5544 char*& init
= ilt
->get_out_branches();
5548 const string
& array_type
= dimensions
->get_timer_type();
5549 const char *array_type_str
= array_type
.c_str();
5550 def
= mputprintf(def
, "%s %s;\n", array_type_str
, genname_str
);
5551 def
= mputstr(def
, "{\n"
5552 "static const char * const timer_names[] = { ");
5553 def
= dimensions
->generate_element_names(def
, dispname
);
5554 def
= mputprintf(def
, " };\n"
5555 "%s.set_name(%lu, timer_names);\n"
5556 "}\n", genname_str
, (unsigned long) dimensions
->get_array_size());
5557 if (default_duration
) init
= generate_code_array_duration(init
,
5558 genname_str
, default_duration
);
5561 if (default_duration
) {
5562 // has default duration
5563 Value
*v
= default_duration
->get_value_refd_last();
5564 if (v
->get_valuetype() == Value::V_REAL
) {
5565 // duration is known at compilation time -> set in the constructor
5566 def
= mputprintf(def
, "TIMER %s(\"%s\", %s);\n", genname_str
,
5567 dispname
.c_str(), v
->get_single_expr().c_str());
5569 // duration is known only at runtime -> set when control reaches the
5571 def
= mputprintf(def
, "TIMER %s(\"%s\");\n", genname_str
,
5573 expression_struct expr
;
5574 Code::init_expr(&expr
);
5575 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5577 default_duration
->generate_code_expr(&expr
);
5578 expr
.expr
= mputc(expr
.expr
, ')');
5579 init
= Code::merge_free_expr(init
, &expr
);
5582 // does not have default duration
5583 def
= mputprintf(def
, "TIMER %s(\"%s\");\n", genname_str
,
5589 char *Def_Timer::generate_code_init_comp(char *str
, Definition
*base_defn
)
5591 if (default_duration
) {
5592 Def_Timer
*base_timer_defn
= dynamic_cast<Def_Timer
*>(base_defn
);
5593 if (!base_timer_defn
|| !base_timer_defn
->default_duration
)
5594 FATAL_ERROR("Def_Timer::generate_code_init_comp()");
5595 // initializer is not needed if the default durations are the same
5596 // constants in both timers
5597 if (default_duration
->is_unfoldable() ||
5598 base_timer_defn
->default_duration
->is_unfoldable() ||
5599 !(*default_duration
== *base_timer_defn
->default_duration
)) {
5601 str
= generate_code_array_duration(str
,
5602 base_timer_defn
->get_genname_from_scope(my_scope
).c_str(),
5605 expression_struct expr
;
5606 Code::init_expr(&expr
);
5607 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5608 base_timer_defn
->get_genname_from_scope(my_scope
).c_str());
5609 default_duration
->generate_code_expr(&expr
);
5610 expr
.expr
= mputc(expr
.expr
, ')');
5611 str
= Code::merge_free_expr(str
, &expr
);
5618 void Def_Timer::dump_internal(unsigned level
) const
5620 DEBUG(level
, "Timer: %s", id
->get_dispname().c_str());
5621 if (dimensions
) dimensions
->dump(level
+ 1);
5622 if (default_duration
) {
5623 DEBUG(level
+ 1, "Default duration:");
5624 default_duration
->dump(level
+ 1);
5628 // =================================
5630 // =================================
5632 Def_Port::Def_Port(Identifier
*p_id
, Reference
*p_tref
,
5633 ArrayDimensions
*p_dims
)
5634 : Definition(A_PORT
, p_id
), type_ref(p_tref
), port_type(0),
5637 if (!p_tref
) FATAL_ERROR("Def_Port::Def_Port()");
5640 Def_Port::~Def_Port()
5646 Def_Port
*Def_Port::clone() const
5648 FATAL_ERROR("Def_Port::clone");
5651 void Def_Port::set_fullname(const string
& p_fullname
)
5653 Definition::set_fullname(p_fullname
);
5654 type_ref
->set_fullname(p_fullname
+ ".<type_ref>");
5655 if (dimensions
) dimensions
->set_fullname(p_fullname
);
5658 void Def_Port::set_my_scope(Scope
*p_scope
)
5660 Definition::set_my_scope(p_scope
);
5661 type_ref
->set_my_scope(p_scope
);
5662 if (dimensions
) dimensions
->set_my_scope(p_scope
);
5665 Type
*Def_Port::get_Type()
5671 ArrayDimensions
*Def_Port::get_Dimensions()
5673 if (!checked
) chk();
5677 void Def_Port::chk()
5679 if (checked
) return;
5681 Error_Context
cntxt(this, "In port definition `%s'",
5682 id
->get_dispname().c_str());
5683 Common::Assignment
*ass
= type_ref
->get_refd_assignment();
5685 if (ass
->get_asstype() == A_TYPE
) {
5686 Type
*t
= ass
->get_Type()->get_type_refd_last();
5687 if (t
->get_typetype() == Type::T_PORT
) port_type
= t
;
5688 else type_ref
->error("Type reference `%s' does not refer to a "
5689 "port type", type_ref
->get_dispname().c_str());
5690 } else type_ref
->error("Reference `%s' does not refer to a "
5691 "type", type_ref
->get_dispname().c_str());
5693 if (dimensions
) dimensions
->chk();
5694 if (w_attrib_path
) {
5695 w_attrib_path
->chk_global_attrib();
5696 w_attrib_path
->chk_no_qualif();
5700 bool Def_Port::chk_identical(Definition
*p_def
)
5704 if (p_def
->get_asstype() != A_PORT
) {
5705 const char *dispname_str
= id
->get_dispname().c_str();
5706 error("Local definition `%s' is a port, but the definition inherited "
5707 "from component type `%s' is a %s", dispname_str
,
5708 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
5709 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
5712 Def_Port
*p_def_port
= dynamic_cast<Def_Port
*>(p_def
);
5713 if (!p_def_port
) FATAL_ERROR("Def_Port::chk_identical()");
5714 if (port_type
&& p_def_port
->port_type
&&
5715 port_type
!= p_def_port
->port_type
) {
5716 const char *dispname_str
= id
->get_dispname().c_str();
5717 type_ref
->error("Local port `%s' has type `%s', but the port inherited "
5718 "from component type `%s' has type `%s'", dispname_str
,
5719 port_type
->get_typename().c_str(),
5720 p_def_port
->get_my_scope()->get_fullname().c_str(),
5721 p_def_port
->port_type
->get_typename().c_str());
5722 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5726 if (p_def_port
->dimensions
) {
5727 if (!dimensions
->is_identical(p_def_port
->dimensions
)) {
5728 const char *dispname_str
= id
->get_dispname().c_str();
5729 error("Local port `%s' and the port inherited from component type "
5730 "`%s' have different array dimensions", dispname_str
,
5731 p_def_port
->get_my_scope()->get_fullname().c_str());
5732 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5736 const char *dispname_str
= id
->get_dispname().c_str();
5737 error("Local definition `%s' is a port array, but the definition "
5738 "inherited from component type `%s' is a single port", dispname_str
,
5739 p_def_port
->get_my_scope()->get_fullname().c_str());
5740 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5743 } else if (p_def_port
->dimensions
) {
5744 const char *dispname_str
= id
->get_dispname().c_str();
5745 error("Local definition `%s' is a single port, but the definition "
5746 "inherited from component type `%s' is a port array", dispname_str
,
5747 p_def_port
->get_my_scope()->get_fullname().c_str());
5748 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5754 void Def_Port::generate_code(output_struct
*target
, bool)
5756 const string
& t_genname
= get_genname();
5757 const char *genname_str
= t_genname
.c_str();
5758 const string
& type_genname
= port_type
->get_genname_value(my_scope
);
5759 const string
& dispname
= id
->get_dispname();
5762 const string
& array_type
= dimensions
->get_port_type(type_genname
);
5763 const char *array_type_str
= array_type
.c_str();
5764 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5765 "extern %s %s;\n", array_type_str
, genname_str
);
5766 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5767 "%s %s;\n", array_type_str
, genname_str
);
5768 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
, "{\n"
5769 "static const char * const port_name = \"");
5770 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
5772 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
5774 "%s.set_name(port_name);\n"
5775 "}\n", genname_str
);
5778 const char *type_genname_str
= type_genname
.c_str();
5779 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5780 "extern %s %s;\n", type_genname_str
, genname_str
);
5781 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5782 "%s %s(\"%s\");\n", type_genname_str
, genname_str
, dispname
.c_str());
5784 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5785 "%s.activate_port();\n", genname_str
);
5788 void Def_Port::generate_code(CodeGenHelper
& cgh
) {
5789 generate_code(cgh
.get_current_outputstruct());
5792 char *Def_Port::generate_code_init_comp(char *str
, Definition
*base_defn
)
5794 return mputprintf(str
, "%s.activate_port();\n",
5795 base_defn
->get_genname_from_scope(my_scope
).c_str());
5798 void Def_Port::dump_internal(unsigned level
) const
5800 DEBUG(level
, "Port: %s", id
->get_dispname().c_str());
5801 DEBUG(level
+ 1, "Port type:");
5802 type_ref
->dump(level
+ 2);
5803 if (dimensions
) dimensions
->dump(level
+ 1);
5806 // =================================
5807 // ===== Def_Function_Base
5808 // =================================
5810 Def_Function_Base::asstype_t
Def_Function_Base::determine_asstype(
5811 bool is_external
, bool has_return_type
, bool returns_template
)
5814 if (has_return_type
) {
5815 if (returns_template
) return A_EXT_FUNCTION_RTEMP
;
5816 else return A_EXT_FUNCTION_RVAL
;
5818 if (returns_template
)
5819 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5820 return A_EXT_FUNCTION
;
5822 } else { // not an external function
5823 if (has_return_type
) {
5824 if (returns_template
) return A_FUNCTION_RTEMP
;
5825 else return A_FUNCTION_RVAL
;
5827 if (returns_template
)
5828 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5834 Def_Function_Base::Def_Function_Base(const Def_Function_Base
& p
)
5835 : Definition(p
), prototype(PROTOTYPE_NONE
), input_type(0), output_type(0)
5837 fp_list
= p
.fp_list
->clone();
5838 fp_list
->set_my_def(this);
5839 return_type
= p
.return_type
? p
.return_type
->clone() : 0;
5840 template_restriction
= p
.template_restriction
;
5843 Def_Function_Base::Def_Function_Base(bool is_external
, Identifier
*p_id
,
5844 FormalParList
*p_fpl
, Type
*p_return_type
, bool returns_template
,
5845 template_restriction_t p_template_restriction
)
5846 : Definition(determine_asstype(is_external
, p_return_type
!= 0,
5847 returns_template
), p_id
), fp_list(p_fpl
), return_type(p_return_type
),
5848 prototype(PROTOTYPE_NONE
), input_type(0), output_type(0),
5849 template_restriction(p_template_restriction
)
5851 if (!p_fpl
) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
5852 fp_list
->set_my_def(this);
5853 if (return_type
) return_type
->set_ownertype(Type::OT_FUNCTION_DEF
, this);
5856 Def_Function_Base::~Def_Function_Base()
5862 void Def_Function_Base::set_fullname(const string
& p_fullname
)
5864 Definition::set_fullname(p_fullname
);
5865 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
5866 if (return_type
) return_type
->set_fullname(p_fullname
+ ".<return_type>");
5869 void Def_Function_Base::set_my_scope(Scope
*p_scope
)
5871 Definition::set_my_scope(p_scope
);
5872 fp_list
->set_my_scope(p_scope
);
5873 if (return_type
) return_type
->set_my_scope(p_scope
);
5876 Type
*Def_Function_Base::get_Type()
5878 if (!checked
) chk();
5882 FormalParList
*Def_Function_Base::get_FormalParList()
5884 if (!checked
) chk();
5888 const char *Def_Function_Base::get_prototype_name() const
5890 switch (prototype
) {
5891 case PROTOTYPE_NONE
:
5892 return "<no prototype>";
5893 case PROTOTYPE_CONVERT
:
5895 case PROTOTYPE_FAST
:
5897 case PROTOTYPE_BACKTRACK
:
5899 case PROTOTYPE_SLIDING
:
5902 return "<unknown prototype>";
5906 void Def_Function_Base::chk_prototype()
5908 switch (prototype
) {
5909 case PROTOTYPE_NONE
:
5910 // return immediately
5912 case PROTOTYPE_CONVERT
:
5913 case PROTOTYPE_FAST
:
5914 case PROTOTYPE_BACKTRACK
:
5915 case PROTOTYPE_SLIDING
:
5916 // perform the checks below
5919 FATAL_ERROR("Def_Function_Base::chk_prototype()");
5921 // checking the formal parameter list
5922 if (prototype
== PROTOTYPE_CONVERT
) {
5923 if (fp_list
->get_nof_fps() == 1) {
5924 FormalPar
*par
= fp_list
->get_fp_byIndex(0);
5925 if (par
->get_asstype() == A_PAR_VAL_IN
) {
5926 input_type
= par
->get_Type();
5928 par
->error("The parameter must be an `in' value parameter for "
5929 "attribute `prototype(%s)' instead of %s", get_prototype_name(),
5930 par
->get_assname());
5933 fp_list
->error("The function must have one parameter instead of %lu "
5934 "for attribute `prototype(%s)'", (unsigned long) fp_list
->get_nof_fps(),
5935 get_prototype_name());
5937 } else { // not PROTOTYPE_CONVERT
5938 if (fp_list
->get_nof_fps() == 2) {
5939 FormalPar
*first_par
= fp_list
->get_fp_byIndex(0);
5940 if (prototype
== PROTOTYPE_SLIDING
) {
5941 if (first_par
->get_asstype() == A_PAR_VAL_INOUT
) {
5942 Type
*first_par_type
= first_par
->get_Type();
5943 switch (first_par_type
->get_type_refd_last()
5944 ->get_typetype_ttcn3()) {
5949 input_type
= first_par_type
;
5952 first_par_type
->error("The type of the first parameter must be "
5953 "`octetstring' or `charstring' or `bitstring' for attribute "
5954 "`prototype(%s)' instead of `%s'", get_prototype_name(),
5955 first_par_type
->get_typename().c_str());
5958 first_par
->error("The first parameter must be an `inout' value "
5959 "parameter for attribute `prototype(%s)' instead of %s",
5960 get_prototype_name(), first_par
->get_assname());
5963 if (first_par
->get_asstype() == A_PAR_VAL_IN
) {
5964 input_type
= first_par
->get_Type();
5966 first_par
->error("The first parameter must be an `in' value "
5967 "parameter for attribute `prototype(%s)' instead of %s",
5968 get_prototype_name(), first_par
->get_assname());
5971 FormalPar
*second_par
= fp_list
->get_fp_byIndex(1);
5972 if (second_par
->get_asstype() == A_PAR_VAL_OUT
) {
5973 output_type
= second_par
->get_Type();
5975 second_par
->error("The second parameter must be an `out' value "
5976 "parameter for attribute `prototype(%s)' instead of %s",
5977 get_prototype_name(), second_par
->get_assname());
5980 fp_list
->error("The function must have two parameters for attribute "
5981 "`prototype(%s)' instead of %lu", get_prototype_name(),
5982 (unsigned long) fp_list
->get_nof_fps());
5985 // checking the return type
5986 if (prototype
== PROTOTYPE_FAST
) {
5988 return_type
->error("The function cannot have return type for "
5989 "attribute `prototype(%s)'", get_prototype_name());
5993 if (asstype
== A_FUNCTION_RTEMP
|| asstype
== A_EXT_FUNCTION_RTEMP
)
5994 return_type
->error("The function must return a value instead of a "
5995 "template for attribute `prototype(%s)'", get_prototype_name());
5996 if (prototype
== PROTOTYPE_CONVERT
) {
5997 output_type
= return_type
;
5999 switch (return_type
->get_type_refd_last()->get_typetype_ttcn3()) {
6004 return_type
->error("The return type of the function must be "
6005 "`integer' instead of `%s' for attribute `prototype(%s)'",
6006 return_type
->get_typename().c_str(), get_prototype_name());
6010 error("The function must have return type for attribute "
6011 "`prototype(%s)'", get_prototype_name());
6014 // checking the 'runs on' clause
6015 if (get_RunsOnType()) {
6016 error("The function cannot have `runs on' clause for attribute "
6017 "`prototype(%s)'", get_prototype_name());
6021 Type
*Def_Function_Base::get_input_type()
6023 if (!checked
) chk();
6027 Type
*Def_Function_Base::get_output_type()
6029 if (!checked
) chk();
6034 // =================================
6035 // ===== Def_Function
6036 // =================================
6038 Def_Function::Def_Function(Identifier
*p_id
, FormalParList
*p_fpl
,
6039 Reference
*p_runs_on_ref
, Type
*p_return_type
,
6040 bool returns_template
,
6041 template_restriction_t p_template_restriction
,
6042 StatementBlock
*p_block
)
6043 : Def_Function_Base(false, p_id
, p_fpl
, p_return_type
, returns_template
,
6044 p_template_restriction
),
6045 runs_on_ref(p_runs_on_ref
), runs_on_type(0), block(p_block
),
6046 is_startable(false), transparent(false)
6048 if (!p_block
) FATAL_ERROR("Def_Function::Def_Function()");
6049 block
->set_my_def(this);
6052 Def_Function::~Def_Function()
6058 Def_Function
*Def_Function::clone() const
6060 FATAL_ERROR("Def_Function::clone");
6063 void Def_Function::set_fullname(const string
& p_fullname
)
6065 Def_Function_Base::set_fullname(p_fullname
);
6066 if (runs_on_ref
) runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
6067 block
->set_fullname(p_fullname
+ ".<statement_block>");
6070 void Def_Function::set_my_scope(Scope
*p_scope
)
6072 bridgeScope
.set_parent_scope(p_scope
);
6073 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
6075 Def_Function_Base::set_my_scope(&bridgeScope
);
6076 if (runs_on_ref
) runs_on_ref
->set_my_scope(&bridgeScope
);
6077 block
->set_my_scope(fp_list
);
6080 Type
*Def_Function::get_RunsOnType()
6082 if (!checked
) chk();
6083 return runs_on_type
;
6086 RunsOnScope
*Def_Function::get_runs_on_scope(Type
*comptype
)
6088 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
6089 if (!my_module
) FATAL_ERROR("Def_Function::get_runs_on_scope()");
6090 return my_module
->get_runs_on_scope(comptype
);
6093 void Def_Function::chk()
6095 if (checked
) return;
6097 Error_Context
cntxt(this, "In function definition `%s'",
6098 id
->get_dispname().c_str());
6099 // checking the `runs on' clause
6101 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
6102 runs_on_type
= runs_on_ref
->chk_comptype_ref();
6103 // override the scope of the formal parameter list
6105 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
6106 runs_on_scope
->set_parent_scope(my_scope
);
6107 fp_list
->set_my_scope(runs_on_scope
);
6110 // checking the formal parameter list
6111 fp_list
->chk(asstype
);
6112 // checking of return type
6114 Error_Context
cntxt2(return_type
, "In return type");
6116 return_type
->chk_as_return_type(asstype
== A_FUNCTION_RVAL
,"function");
6118 // decision of startability
6119 is_startable
= runs_on_ref
!= 0;
6120 if (is_startable
&& !fp_list
->get_startability()) is_startable
= false;
6121 if (is_startable
&& return_type
&& return_type
->is_component_internal())
6122 is_startable
= false;
6123 // checking of statement block
6126 // checking the presence of return statements
6127 switch (block
->has_return()) {
6128 case StatementBlock::RS_NO
:
6129 error("The function has return type, but it does not have any return "
6132 case StatementBlock::RS_MAYBE
:
6133 error("The function has return type, but control might leave it "
6134 "without reaching a return statement");
6139 if (!semantic_check_only
) {
6140 fp_list
->set_genname(get_genname());
6141 block
->set_code_section(GovernedSimple::CS_INLINE
);
6143 if (w_attrib_path
) {
6144 w_attrib_path
->chk_global_attrib();
6145 w_attrib_path
->chk_no_qualif();
6146 Ttcn::ExtensionAttributes
* extattrs
= parse_extattributes(w_attrib_path
);
6147 if (extattrs
!= 0) { // NULL means parsing error
6148 size_t num_atrs
= extattrs
->size();
6149 for (size_t i
=0; i
< num_atrs
; ++i
) {
6150 ExtensionAttribute
&ea
= extattrs
->get(i
);
6151 switch (ea
.get_type()) {
6152 case ExtensionAttribute::PROTOTYPE
: {
6153 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE
) {
6154 ea
.error("Duplicate attribute `prototype'");
6156 Def_Function_Base::prototype_t proto
= ea
.get_proto();
6157 set_prototype(proto
);
6160 case ExtensionAttribute::ANYTYPELIST
: // ignore it
6161 case ExtensionAttribute::NONE
: // erroneous, do not issue an error
6164 case ExtensionAttribute::TRANSPARENT
:
6168 case ExtensionAttribute::ENCODE
:
6169 case ExtensionAttribute::DECODE
:
6170 case ExtensionAttribute::ERRORBEHAVIOR
:
6171 case ExtensionAttribute::PRINTING
:
6172 ea
.error("Extension attribute 'encode', 'decode', 'errorbehavior'"
6173 " or 'printing' can only be applied to external functions");
6176 default: // complain
6177 ea
.error("Function definition can only have the 'prototype'"
6178 " extension attribute");
6188 bool Def_Function::chk_startable()
6190 if (!checked
) chk();
6191 if (is_startable
) return true;
6192 if (!runs_on_ref
) error("Function `%s' cannot be started on a parallel "
6193 "test component because it does not have `runs on' clause",
6194 get_fullname().c_str());
6195 fp_list
->chk_startability("Function", get_fullname().c_str());
6196 if (return_type
&& return_type
->is_component_internal()) {
6197 map
<Type
*,void> type_chain
;
6198 char* err_str
= mprintf("the return type or embedded in the return type "
6199 "of function `%s' if it is started on a parallel test component",
6200 get_fullname().c_str());
6201 return_type
->chk_component_internal(type_chain
, err_str
);
6207 void Def_Function::generate_code(output_struct
*target
, bool)
6209 transparency_holder
glass(*this);
6210 const string
& t_genname
= get_genname();
6211 const char *genname_str
= t_genname
.c_str();
6212 const char *dispname_str
= id
->get_dispname().c_str();
6213 string return_type_name
;
6216 return_type_name
= "void";
6218 case A_FUNCTION_RVAL
:
6219 return_type_name
= return_type
->get_genname_value(my_scope
);
6221 case A_FUNCTION_RTEMP
:
6222 return_type_name
= return_type
->get_genname_template(my_scope
);
6225 FATAL_ERROR("Def_Function::generate_code()");
6227 const char *return_type_str
= return_type_name
.c_str();
6229 // assemble the function body first (this also determines which parameters
6231 char* body
= create_location_object(memptystr(), "FUNCTION", dispname_str
);
6232 if (!enable_set_bound_out_param
)
6233 body
= fp_list
->generate_code_set_unbound(body
); // conform the standard out parameter is unbound
6234 body
= fp_list
->generate_shadow_objects(body
);
6235 if (debugger_active
) {
6236 body
= generate_code_debugger_function_init(body
, this);
6238 body
= block
->generate_code(body
);
6239 // smart formal parameter list (names of unused parameters are omitted)
6240 char *formal_par_list
= fp_list
->generate_code(memptystr());
6241 fp_list
->generate_code_defval(target
);
6242 // function prototype
6243 target
->header
.function_prototypes
=
6244 mputprintf(target
->header
.function_prototypes
, "extern %s %s(%s);\n",
6245 return_type_str
, genname_str
, formal_par_list
);
6248 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
6252 "}\n\n", return_type_str
, genname_str
, formal_par_list
, body
);
6253 Free(formal_par_list
);
6257 size_t nof_fps
= fp_list
->get_nof_fps();
6258 // use the full list of formal parameters here (since they are all logged)
6259 char *full_formal_par_list
= fp_list
->generate_code(memptystr(), nof_fps
);
6260 // starter function (stub)
6261 // function prototype
6262 target
->header
.function_prototypes
=
6263 mputprintf(target
->header
.function_prototypes
,
6264 "extern void start_%s(const COMPONENT& component_reference%s%s);\n",
6265 genname_str
, nof_fps
>0?", ":"", full_formal_par_list
);
6267 body
= mprintf("void start_%s(const COMPONENT& component_reference%s"
6270 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6271 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6272 genname_str
, nof_fps
>0?", ":"", full_formal_par_list
, dispname_str
);
6273 for (size_t i
= 0; i
< nof_fps
; i
++) {
6274 if (i
> 0) body
= mputstr(body
,
6275 "TTCN_Logger::log_event_str(\", \");\n");
6276 body
= mputprintf(body
, "%s.log();\n",
6277 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6279 body
= mputprintf(body
,
6280 "TTCN_Logger::log_event_str(\") on component \");\n"
6281 "component_reference.log();\n"
6282 "TTCN_Logger::log_char('.');\n"
6283 "TTCN_Logger::end_event();\n"
6284 "Text_Buf text_buf;\n"
6285 "TTCN_Runtime::prepare_start_component(component_reference, "
6286 "\"%s\", \"%s\", text_buf);\n",
6287 my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
6289 for (size_t i
= 0; i
< nof_fps
; i
++) {
6290 body
= mputprintf(body
, "%s.encode_text(text_buf);\n",
6291 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6293 body
= mputstr(body
, "TTCN_Runtime::send_start_component(text_buf);\n"
6295 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
6299 // an entry in start_ptc_function
6300 body
= mprintf("if (!strcmp(function_name, \"%s\")) {\n",
6303 body
= fp_list
->generate_code_object(body
, "", ' ');
6304 for (size_t i
= 0; i
< nof_fps
; i
++) {
6305 body
= mputprintf(body
, "%s.decode_text(function_arguments);\n",
6306 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6308 body
= mputprintf(body
,
6309 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6310 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6312 for (size_t i
= 0; i
< nof_fps
; i
++) {
6313 if (i
> 0) body
= mputstr(body
,
6314 "TTCN_Logger::log_event_str(\", \");\n");
6315 body
= mputprintf(body
, "%s.log();\n",
6316 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6318 body
= mputstr(body
, "TTCN_Logger::log_event_str(\").\");\n"
6319 "TTCN_Logger::end_event();\n");
6321 body
= mputprintf(body
,
6322 "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
6323 "%s().\");\n", dispname_str
);
6325 body
= mputstr(body
,
6326 "TTCN_Runtime::function_started(function_arguments);\n");
6327 char *actual_par_list
=
6328 fp_list
->generate_code_actual_parlist(memptystr(), "");
6329 bool return_value_kept
= false;
6330 if (asstype
== A_FUNCTION_RVAL
) {
6331 // the return value is kept only if the function returns a value
6332 // (rather than a template) and the return type has the "done"
6333 // extension attribute
6334 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
6335 if (t
->has_done_attribute()) {
6336 return_value_kept
= true;
6338 } else if (!t
->is_ref()) break;
6341 if (return_value_kept
) {
6342 const string
& return_type_dispname
= return_type
->get_typename();
6343 const char *return_type_dispname_str
= return_type_dispname
.c_str();
6344 body
= mputprintf(body
, "%s ret_val(%s(%s));\n"
6345 "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
6346 "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
6348 "Text_Buf text_buf;\n"
6349 "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
6350 "ret_val.encode_text(text_buf);\n"
6351 "TTCN_Runtime::send_function_finished(text_buf);\n",
6352 return_type_str
, genname_str
, actual_par_list
, dispname_str
,
6353 return_type_dispname_str
, return_type_dispname_str
);
6355 body
= mputprintf(body
, "%s(%s);\n"
6356 "TTCN_Runtime::function_finished(\"%s\");\n",
6357 genname_str
, actual_par_list
, dispname_str
);
6359 Free(actual_par_list
);
6360 body
= mputstr(body
, "return TRUE;\n"
6362 target
->functions
.start
= mputstr(target
->functions
.start
, body
);
6364 Free(full_formal_par_list
);
6367 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
6368 "%s.add_function(\"%s\", (genericfunc_t)&%s, ", get_module_object_name(),
6369 dispname_str
, genname_str
);
6371 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
6372 "(genericfunc_t)&start_%s);\n", genname_str
);
6374 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
6378 void Def_Function::generate_code(CodeGenHelper
& cgh
) {
6379 generate_code(cgh
.get_current_outputstruct());
6382 void Def_Function::dump_internal(unsigned level
) const
6384 DEBUG(level
, "Function: %s", id
->get_dispname().c_str());
6385 DEBUG(level
+ 1, "Parameters:");
6386 fp_list
->dump(level
+ 1);
6388 DEBUG(level
+ 1, "Runs on clause:");
6389 runs_on_ref
->dump(level
+ 2);
6392 DEBUG(level
+ 1, "Return type:");
6393 return_type
->dump(level
+ 2);
6394 if (asstype
== A_FUNCTION_RTEMP
) DEBUG(level
+ 1, "Returns template");
6396 if (prototype
!= PROTOTYPE_NONE
)
6397 DEBUG(level
+ 1, "Prototype: %s", get_prototype_name());
6398 //DEBUG(level + 1, "Statement block:");
6399 block
->dump(level
+ 1);
6402 void Def_Function::set_parent_path(WithAttribPath
* p_path
) {
6403 Def_Function_Base::set_parent_path(p_path
);
6404 block
->set_parent_path(w_attrib_path
);
6407 // =================================
6408 // ===== Def_ExtFunction
6409 // =================================
6411 Def_ExtFunction::~Def_ExtFunction()
6413 delete encoding_options
;
6415 if (NULL
!= json_printing
) {
6416 delete json_printing
;
6420 Def_ExtFunction
*Def_ExtFunction::clone() const
6422 FATAL_ERROR("Def_ExtFunction::clone");
6425 void Def_ExtFunction::set_fullname(const string
& p_fullname
)
6427 Def_Function_Base::set_fullname(p_fullname
);
6428 if (eb_list
) eb_list
->set_fullname(p_fullname
+ ".<errorbehavior_list>");
6431 void Def_ExtFunction::set_encode_parameters(Type::MessageEncodingType_t
6432 p_encoding_type
, string
*p_encoding_options
)
6434 function_type
= EXTFUNC_ENCODE
;
6435 encoding_type
= p_encoding_type
;
6436 delete encoding_options
;
6437 encoding_options
= p_encoding_options
;
6440 void Def_ExtFunction::set_decode_parameters(Type::MessageEncodingType_t
6441 p_encoding_type
, string
*p_encoding_options
)
6443 function_type
= EXTFUNC_DECODE
;
6444 encoding_type
= p_encoding_type
;
6445 delete encoding_options
;
6446 encoding_options
= p_encoding_options
;
6449 void Def_ExtFunction::add_eb_list(Ttcn::ErrorBehaviorList
*p_eb_list
)
6451 if (!p_eb_list
) FATAL_ERROR("Def_ExtFunction::add_eb_list()");
6453 eb_list
->steal_ebs(p_eb_list
);
6456 eb_list
= p_eb_list
;
6457 eb_list
->set_fullname(get_fullname() + ".<errorbehavior_list>");
6461 void Def_ExtFunction::chk_function_type()
6463 switch (function_type
) {
6464 case EXTFUNC_MANUAL
:
6466 eb_list
->error("Attribute `errorbehavior' can only be used together "
6467 "with `encode' or `decode'");
6471 case EXTFUNC_ENCODE
:
6472 switch (prototype
) {
6473 case PROTOTYPE_NONE
:
6474 error("Attribute `encode' cannot be used without `prototype'");
6476 case PROTOTYPE_BACKTRACK
:
6477 case PROTOTYPE_SLIDING
:
6478 error("Attribute `encode' cannot be used with `prototype(%s)'",
6479 get_prototype_name());
6480 default: /* CONVERT and FAST allowed */
6485 if (!input_type
->has_encoding(encoding_type
, encoding_options
)) {
6486 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6487 input_type
->error("Input type `%s' does not support custom encoding '%s'",
6488 input_type
->get_typename().c_str(), encoding_options
->c_str());
6491 input_type
->error("Input type `%s' does not support %s encoding",
6492 input_type
->get_typename().c_str(),
6493 Type::get_encoding_name(encoding_type
));
6497 if (Common::Type::CT_XER
== encoding_type
6498 && input_type
->get_type_refd_last()->is_untagged()) {
6499 // "untagged" on the (toplevel) input type will have no effect.
6500 warning("UNTAGGED encoding attribute is ignored on top-level type");
6502 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6503 if (PROTOTYPE_CONVERT
!= prototype
) {
6504 error("Only `prototype(convert)' is allowed for custom encoding functions");
6507 // let the input type know that this is its encoding function
6508 input_type
->get_type_refd()->set_coding_function(true,
6509 get_genname_from_scope(input_type
->get_type_refd()->get_my_scope()));
6510 // treat this as a manual external function during code generation
6511 function_type
= EXTFUNC_MANUAL
;
6517 if(encoding_type
== Common::Type::CT_TEXT
) { // TEXT encoding supports both octetstring and charstring stream types
6518 Type
*stream_type
= Type::get_stream_type(encoding_type
,0);
6519 Type
*stream_type2
= Type::get_stream_type(encoding_type
,1);
6520 if ( (!stream_type
->is_identical(output_type
)) && (!stream_type2
->is_identical(output_type
)) ) {
6521 output_type
->error("The output type of %s encoding should be `%s' or `%s' "
6522 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6523 stream_type
->get_typename().c_str(),
6524 stream_type2
->get_typename().c_str(),
6525 output_type
->get_typename().c_str());
6528 Type
*stream_type
= Type::get_stream_type(encoding_type
);
6529 if (!stream_type
->is_identical(output_type
)) {
6530 output_type
->error("The output type of %s encoding should be `%s' "
6531 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6532 stream_type
->get_typename().c_str(),
6533 output_type
->get_typename().c_str());
6537 if (eb_list
) eb_list
->chk();
6538 chk_allowed_encode();
6540 case EXTFUNC_DECODE
:
6541 if (prototype
== PROTOTYPE_NONE
) {
6542 error("Attribute `decode' cannot be used without `prototype'");
6545 if(encoding_type
== Common::Type::CT_TEXT
) { // TEXT encoding supports both octetstring and charstring stream types
6546 Type
*stream_type
= Type::get_stream_type(encoding_type
,0);
6547 Type
*stream_type2
= Type::get_stream_type(encoding_type
,1);
6548 if ( (!stream_type
->is_identical(input_type
)) && (!stream_type2
->is_identical(input_type
)) ) {
6549 input_type
->error("The input type of %s decoding should be `%s' or `%s' "
6550 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6551 stream_type
->get_typename().c_str(),
6552 stream_type2
->get_typename().c_str(),
6553 input_type
->get_typename().c_str());
6556 Type
*stream_type
= Type::get_stream_type(encoding_type
);
6557 if (!stream_type
->is_identical(input_type
)) {
6558 input_type
->error("The input type of %s decoding should be `%s' "
6559 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6560 stream_type
->get_typename().c_str(),
6561 input_type
->get_typename().c_str());
6566 if (output_type
&& !output_type
->has_encoding(encoding_type
, encoding_options
)) {
6567 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6568 output_type
->error("Output type `%s' does not support custom encoding '%s'",
6569 output_type
->get_typename().c_str(), encoding_options
->c_str());
6572 output_type
->error("Output type `%s' does not support %s encoding",
6573 output_type
->get_typename().c_str(),
6574 Type::get_encoding_name(encoding_type
));
6578 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6579 if (PROTOTYPE_SLIDING
!= prototype
) {
6580 error("Only `prototype(sliding)' is allowed for custom decoding functions");
6582 else if (output_type
) {
6583 // let the output type know that this is its decoding function
6584 output_type
->get_type_refd()->set_coding_function(false,
6585 get_genname_from_scope(output_type
->get_type_refd()->get_my_scope()));
6586 // treat this as a manual external function during code generation
6587 function_type
= EXTFUNC_MANUAL
;
6591 if (eb_list
) eb_list
->chk();
6592 chk_allowed_encode();
6595 FATAL_ERROR("Def_ExtFunction::chk()");
6599 void Def_ExtFunction::chk_allowed_encode()
6601 switch (encoding_type
) {
6603 if (enable_ber()) return; // ok
6606 if (enable_raw()) return; // ok
6609 if (enable_text()) return; // ok
6612 if (enable_xer()) return; // ok
6615 if (enable_per()) return; // ok?
6618 if (enable_json()) return;
6620 case Type::CT_CUSTOM
:
6621 return; // cannot be disabled
6623 FATAL_ERROR("Def_ExtFunction::chk_allowed_encode");
6627 error("%s encoding is disallowed by license or commandline options",
6628 Type::get_encoding_name(encoding_type
));
6631 void Def_ExtFunction::chk()
6633 if (checked
) return;
6635 Error_Context
cntxt(this, "In external function definition `%s'",
6636 id
->get_dispname().c_str());
6637 fp_list
->chk(asstype
);
6639 Error_Context
cntxt2(return_type
, "In return type");
6641 return_type
->chk_as_return_type(asstype
== A_EXT_FUNCTION_RVAL
,
6642 "external function");
6644 if (!semantic_check_only
) fp_list
->set_genname(get_genname());
6645 if (w_attrib_path
) {
6646 w_attrib_path
->chk_global_attrib();
6647 w_attrib_path
->chk_no_qualif();
6648 const Ttcn::ExtensionAttributes
* extattrs
= parse_extattributes(w_attrib_path
);
6649 if (extattrs
!= 0) {
6650 size_t num_atrs
= extattrs
->size();
6651 for (size_t i
=0; i
< num_atrs
; ++i
) {
6652 ExtensionAttribute
&ea
= extattrs
->get(i
);
6653 switch (ea
.get_type()) {
6654 case ExtensionAttribute::PROTOTYPE
: {
6655 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE
) {
6656 ea
.error("Duplicate attribute `prototype'");
6658 Def_Function_Base::prototype_t proto
= ea
.get_proto();
6659 set_prototype(proto
);
6662 case ExtensionAttribute::ENCODE
: {
6663 switch (get_function_type()) {
6664 case Def_ExtFunction::EXTFUNC_MANUAL
:
6666 case Def_ExtFunction::EXTFUNC_ENCODE
: {
6667 ea
.error("Duplicate attribute `encode'");
6669 case Def_ExtFunction::EXTFUNC_DECODE
: {
6670 ea
.error("Attributes `decode' and `encode' "
6671 "cannot be used at the same time");
6674 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6676 Type::MessageEncodingType_t et
;
6678 ea
.get_encdec_parameters(et
, opt
);
6679 set_encode_parameters(et
, opt
);
6682 case ExtensionAttribute::ERRORBEHAVIOR
: {
6683 add_eb_list(ea
.get_eb_list());
6686 case ExtensionAttribute::DECODE
: {
6687 switch (get_function_type()) {
6688 case Def_ExtFunction::EXTFUNC_MANUAL
:
6690 case Def_ExtFunction::EXTFUNC_ENCODE
: {
6691 ea
.error("Attributes `encode' and `decode' "
6692 "cannot be used at the same time");
6694 case Def_ExtFunction::EXTFUNC_DECODE
: {
6695 ea
.error("Duplicate attribute `decode'");
6698 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6700 Type::MessageEncodingType_t et
;
6702 ea
.get_encdec_parameters(et
, opt
);
6703 set_decode_parameters(et
, opt
);
6706 case ExtensionAttribute::PRINTING
: {
6707 json_printing
= ea
.get_printing();
6710 case ExtensionAttribute::ANYTYPELIST
:
6711 // ignore, because we can't distinguish between a local
6712 // "extension anytype" (which is bogus) and an inherited one
6713 // (which was meant for a type definition)
6716 case ExtensionAttribute::NONE
:
6717 // Ignore, do not issue "wrong type" error
6722 "Only the following extension attributes may be applied to "
6723 "external functions: 'prototype', 'encode', 'decode', 'errorbehavior'");
6731 chk_function_type();
6733 if (NULL
!= json_printing
&& (EXTFUNC_ENCODE
!= function_type
||
6734 Type::CT_JSON
!= encoding_type
)) {
6735 error("Attribute 'printing' is only allowed for JSON encoding functions.");
6739 char *Def_ExtFunction::generate_code_encode(char *str
)
6741 const char *function_name
= id
->get_dispname().c_str();
6742 const char *first_par_name
=
6743 fp_list
->get_fp_byIndex(0)->get_id().get_name().c_str();
6744 // producing debug printout of the input PDU
6745 str
= mputprintf(str
,
6747 "// written by %s in " __FILE__
" at %d\n"
6749 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6750 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6751 "TTCN_Logger::log_event_str(\"%s(): Encoding %s: \");\n"
6753 "TTCN_Logger::end_event();\n"
6756 , __FUNCTION__
, __LINE__
6758 , function_name
, input_type
->get_typename().c_str(), first_par_name
);
6759 // setting error behavior
6760 if (eb_list
) str
= eb_list
->generate_code(str
);
6761 else str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6762 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6763 // encoding PDU into the buffer
6764 str
= mputstr(str
, "TTCN_Buffer ttcn_buffer;\n");
6765 str
= mputprintf(str
, "%s.encode(%s_descr_, ttcn_buffer, TTCN_EncDec::CT_%s",
6767 input_type
->get_genname_typedescriptor(my_scope
).c_str(),
6768 Type::get_encoding_name(encoding_type
));
6769 if (encoding_type
== Type::CT_JSON
) {
6770 if (json_printing
!= NULL
) {
6771 str
= json_printing
->generate_code(str
);
6773 str
= mputstr(str
, ", 0");
6776 if (encoding_options
) str
= mputprintf(str
, ", %s",
6777 encoding_options
->c_str());
6778 str
= mputstr(str
, ");\n");
6779 const char *result_name
;
6780 switch (prototype
) {
6781 case PROTOTYPE_CONVERT
:
6782 result_name
= "ret_val";
6783 // creating a local variable for the result stream
6784 str
= mputprintf(str
, "%s ret_val;\n",
6785 output_type
->get_genname_value(my_scope
).c_str());
6787 case PROTOTYPE_FAST
:
6788 result_name
= fp_list
->get_fp_byIndex(1)->get_id().get_name().c_str();
6791 FATAL_ERROR("Def_ExtFunction::generate_code_encode()");
6794 // taking the result from the buffer and producing debug printout
6795 str
= mputprintf(str
, "ttcn_buffer.get_string(%s);\n"
6796 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6797 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6798 "TTCN_Logger::log_event_str(\"%s(): Stream after encoding: \");\n"
6800 "TTCN_Logger::end_event();\n"
6801 "}\n", result_name
, function_name
, result_name
);
6802 // returning the result stream if necessary
6803 if (prototype
== PROTOTYPE_CONVERT
) {
6804 if (debugger_active
) {
6806 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
6807 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
6809 str
= mputstr(str
, "return ret_val;\n");
6814 char *Def_ExtFunction::generate_code_decode(char *str
)
6816 const char *function_name
= id
->get_dispname().c_str();
6817 const char *first_par_name
=
6818 fp_list
->get_fp_byIndex(0)->get_id().get_name().c_str();
6819 // producing debug printout of the input stream
6820 str
= mputprintf(str
,
6822 "// written by %s in " __FILE__
" at %d\n"
6824 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6825 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6826 "TTCN_Logger::log_event_str(\"%s(): Stream before decoding: \");\n"
6828 "TTCN_Logger::end_event();\n"
6831 , __FUNCTION__
, __LINE__
6833 , function_name
, first_par_name
);
6834 // setting error behavior
6835 if (eb_list
) str
= eb_list
->generate_code(str
);
6836 else if (prototype
== PROTOTYPE_BACKTRACK
|| prototype
== PROTOTYPE_SLIDING
) {
6837 str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6838 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n");
6839 } else str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6840 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6841 // creating a buffer from the input stream
6842 str
= mputprintf(str
, "TTCN_EncDec::clear_error();\n"
6843 "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name
);
6844 const char *result_name
;
6845 if (prototype
== PROTOTYPE_CONVERT
) {
6846 // creating a local variable for the result
6847 str
= mputprintf(str
, "%s ret_val;\n",
6848 output_type
->get_genname_value(my_scope
).c_str());
6849 result_name
= "ret_val";
6851 result_name
= fp_list
->get_fp_byIndex(1)->get_id().get_name().c_str();
6853 if(encoding_type
==Type::CT_TEXT
){
6854 str
= mputprintf(str
,
6855 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6856 " TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_LOG_MATCHING, TTCN_EncDec::EB_WARNING);\n"
6859 str
= mputprintf(str
, "%s.decode(%s_descr_, ttcn_buffer, "
6860 "TTCN_EncDec::CT_%s", result_name
,
6861 output_type
->get_genname_typedescriptor(my_scope
).c_str(),
6862 Type::get_encoding_name(encoding_type
));
6863 if (encoding_options
) str
= mputprintf(str
, ", %s",
6864 encoding_options
->c_str());
6865 str
= mputstr(str
, ");\n");
6866 // producing debug printout of the result PDU
6867 str
= mputprintf(str
,
6868 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6869 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6870 "TTCN_Logger::log_event_str(\"%s(): Decoded %s: \");\n"
6872 "TTCN_Logger::end_event();\n"
6873 "}\n", function_name
, output_type
->get_typename().c_str(), result_name
);
6874 if (prototype
!= PROTOTYPE_SLIDING
) {
6875 // checking for remaining data in the buffer if decoding was successful
6876 str
= mputprintf(str
, "if (TTCN_EncDec::get_last_error_type() == "
6877 "TTCN_EncDec::ET_NONE) {\n"
6878 "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
6879 "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
6880 "ttcn_buffer.cut();\n"
6881 "%s remaining_stream;\n"
6882 "ttcn_buffer.get_string(remaining_stream);\n"
6883 "TTCN_Logger::begin_event(TTCN_WARNING);\n"
6884 "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
6885 "of the stream after successful decoding: \");\n"
6886 "remaining_stream.log();\n"
6887 "TTCN_Logger::end_event();\n"
6888 "}\n", input_type
->get_genname_value(my_scope
).c_str(), function_name
);
6889 // closing the block and returning the appropriate result or status code
6890 if (prototype
== PROTOTYPE_BACKTRACK
) {
6891 if (debugger_active
) {
6892 str
= mputstr(str
, "ttcn3_debugger.set_return_value(\"0\");\n");
6897 if (debugger_active
) {
6898 str
= mputstr(str
, "ttcn3_debugger.set_return_value(\"1\");\n");
6904 str
= mputstr(str
, "}\n");
6905 if (prototype
== PROTOTYPE_CONVERT
) {
6906 if (debugger_active
) {
6908 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
6909 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
6911 str
= mputstr(str
, "return ret_val;\n");
6915 // result handling and debug printout for sliding decoders
6916 str
= mputprintf(str
, "switch (TTCN_EncDec::get_last_error_type()) {\n"
6917 "case TTCN_EncDec::ET_NONE:\n"
6918 // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
6919 "ttcn_buffer.cut();\n"
6920 "ttcn_buffer.get_string(%s);\n"
6921 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6922 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6923 "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
6925 "TTCN_Logger::end_event();\n"
6928 "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
6929 "case TTCN_EncDec::ET_LEN_ERR:\n"
6933 "}\n", first_par_name
, function_name
, first_par_name
,
6934 debugger_active
? "ttcn3_debugger.set_return_value(\"0\");\n" : "",
6935 debugger_active
? "ttcn3_debugger.set_return_value(\"2\");\n" : "",
6936 debugger_active
? "ttcn3_debugger.set_return_value(\"1\");\n" : "");
6941 void Def_ExtFunction::generate_code(output_struct
*target
, bool)
6943 const string
& t_genname
= get_genname();
6944 const char *genname_str
= t_genname
.c_str();
6945 string return_type_name
;
6947 case A_EXT_FUNCTION
:
6948 return_type_name
= "void";
6950 case A_EXT_FUNCTION_RVAL
:
6951 return_type_name
= return_type
->get_genname_value(my_scope
);
6953 case A_EXT_FUNCTION_RTEMP
:
6954 return_type_name
= return_type
->get_genname_template(my_scope
);
6957 FATAL_ERROR("Def_ExtFunction::generate_code()");
6959 const char *return_type_str
= return_type_name
.c_str();
6960 char *formal_par_list
= fp_list
->generate_code(memptystr(), fp_list
->get_nof_fps());
6961 fp_list
->generate_code_defval(target
);
6962 // function prototype
6963 target
->header
.function_prototypes
=
6964 mputprintf(target
->header
.function_prototypes
, "extern %s %s(%s);\n",
6965 return_type_str
, genname_str
, formal_par_list
);
6967 if (function_type
!= EXTFUNC_MANUAL
) {
6968 // function body written by the compiler
6971 body
= mprintf("// written by %s in " __FILE__
" at %d\n"
6972 , __FUNCTION__
, __LINE__
);
6974 body
= mputprintf(body
,
6977 , return_type_str
, genname_str
, formal_par_list
);
6978 if (debugger_active
) {
6979 body
= generate_code_debugger_function_init(body
, this);
6981 switch (function_type
) {
6982 case EXTFUNC_ENCODE
:
6983 body
= generate_code_encode(body
);
6985 case EXTFUNC_DECODE
:
6986 body
= generate_code_decode(body
);
6989 FATAL_ERROR("Def_ExtFunction::generate_code()");
6991 body
= mputstr(body
, "}\n\n");
6992 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
6997 Free(formal_par_list
);
6999 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7000 "%s.add_function(\"%s\", (genericfunc_t)&%s, NULL);\n",
7001 get_module_object_name(), id
->get_dispname().c_str(), genname_str
);
7004 void Def_ExtFunction::generate_code(CodeGenHelper
& cgh
) {
7005 generate_code(cgh
.get_current_outputstruct());
7008 void Def_ExtFunction::dump_internal(unsigned level
) const
7010 DEBUG(level
, "External function: %s", id
->get_dispname().c_str());
7011 DEBUG(level
+ 1, "Parameters:");
7012 fp_list
->dump(level
+ 2);
7014 DEBUG(level
+ 1, "Return type:");
7015 return_type
->dump(level
+ 2);
7016 if(asstype
== A_EXT_FUNCTION_RTEMP
) DEBUG(level
+ 1, "Returns template");
7018 if (prototype
!= PROTOTYPE_NONE
)
7019 DEBUG(level
+ 1, "Prototype: %s", get_prototype_name());
7020 if (function_type
!= EXTFUNC_MANUAL
) {
7021 DEBUG(level
+ 1, "Automatically generated: %s",
7022 function_type
== EXTFUNC_ENCODE
? "encoder" : "decoder");
7023 DEBUG(level
+ 2, "Encoding type: %s",
7024 Type::get_encoding_name(encoding_type
));
7025 if (encoding_options
)
7026 DEBUG(level
+ 2, "Encoding options: %s", encoding_options
->c_str());
7028 if (eb_list
) eb_list
->dump(level
+ 1);
7031 void Def_ExtFunction::generate_json_schema_ref(map
<Type
*, JSON_Tokenizer
>& json_refs
)
7033 // only do anything if this is a JSON encoding or decoding function
7034 if (encoding_type
== Type::CT_JSON
&&
7035 (function_type
== EXTFUNC_ENCODE
|| function_type
== EXTFUNC_DECODE
)) {
7036 // retrieve the encoded type
7038 if (function_type
== EXTFUNC_ENCODE
) {
7039 // for encoding functions it's always the first parameter
7040 type
= fp_list
->get_fp_byIndex(0)->get_Type();
7042 // for decoding functions it depends on the prototype
7043 switch (prototype
) {
7044 case PROTOTYPE_CONVERT
:
7047 case PROTOTYPE_FAST
:
7048 case PROTOTYPE_BACKTRACK
:
7049 case PROTOTYPE_SLIDING
:
7050 type
= fp_list
->get_fp_byIndex(1)->get_Type();
7053 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
7057 // step over the type reference created for this function
7058 type
= type
->get_type_refd();
7060 JSON_Tokenizer
* json
= NULL
;
7061 if (json_refs
.has_key(type
)) {
7062 // the schema segment containing the type's reference already exists
7063 json
= json_refs
[type
];
7065 // the schema segment doesn't exist yet, create it and insert the reference
7066 json
= new JSON_Tokenizer
;
7067 json_refs
.add(type
, json
);
7068 type
->generate_json_schema_ref(*json
);
7071 // insert a property to specify which function this is (encoding or decoding)
7072 json
->put_next_token(JSON_TOKEN_NAME
, (function_type
== EXTFUNC_ENCODE
) ?
7073 "encoding" : "decoding");
7075 // place the function's info in an object
7076 json
->put_next_token(JSON_TOKEN_OBJECT_START
);
7078 // insert information related to the function's prototype in an array
7079 json
->put_next_token(JSON_TOKEN_NAME
, "prototype");
7080 json
->put_next_token(JSON_TOKEN_ARRAY_START
);
7082 // 1st element: external function prototype name (as string)
7084 case PROTOTYPE_CONVERT
:
7085 json
->put_next_token(JSON_TOKEN_STRING
, "\"convert\"");
7087 case PROTOTYPE_FAST
:
7088 json
->put_next_token(JSON_TOKEN_STRING
, "\"fast\"");
7090 case PROTOTYPE_BACKTRACK
:
7091 json
->put_next_token(JSON_TOKEN_STRING
, "\"backtrack\"");
7093 case PROTOTYPE_SLIDING
:
7094 json
->put_next_token(JSON_TOKEN_STRING
, "\"sliding\"");
7097 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
7100 // 2nd element: external function name
7101 char* func_name_str
= mprintf("\"%s\"", id
->get_dispname().c_str());
7102 json
->put_next_token(JSON_TOKEN_STRING
, func_name_str
);
7103 Free(func_name_str
);
7105 // the rest of the elements contain the names of the function's parameters (1 or 2)
7106 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7107 char* param_str
= mprintf("\"%s\"",
7108 fp_list
->get_fp_byIndex(i
)->get_id().get_dispname().c_str());
7109 json
->put_next_token(JSON_TOKEN_STRING
, param_str
);
7113 // end of the prototype's array
7114 json
->put_next_token(JSON_TOKEN_ARRAY_END
);
7116 // insert error behavior data
7117 if (eb_list
!= NULL
) {
7118 json
->put_next_token(JSON_TOKEN_NAME
, "errorBehavior");
7119 json
->put_next_token(JSON_TOKEN_OBJECT_START
);
7121 // add each error behavior modification as a property
7122 for (size_t i
= 0; i
< eb_list
->get_nof_ebs(); ++i
) {
7123 ErrorBehaviorSetting
* eb
= eb_list
->get_ebs_byIndex(i
);
7124 json
->put_next_token(JSON_TOKEN_NAME
, eb
->get_error_type().c_str());
7125 char* handling_str
= mprintf("\"%s\"", eb
->get_error_handling().c_str());
7126 json
->put_next_token(JSON_TOKEN_STRING
, handling_str
);
7130 json
->put_next_token(JSON_TOKEN_OBJECT_END
);
7133 // insert printing type
7134 if (json_printing
!= NULL
) {
7135 json
->put_next_token(JSON_TOKEN_NAME
, "printing");
7136 json
->put_next_token(JSON_TOKEN_STRING
,
7137 (json_printing
->get_printing() == PrintingType::PT_PRETTY
) ?
7138 "\"pretty\"" : "\"compact\"");
7141 // end of this function's object
7142 json
->put_next_token(JSON_TOKEN_OBJECT_END
);
7146 // =================================
7147 // ===== Def_Altstep
7148 // =================================
7150 Def_Altstep::Def_Altstep(Identifier
*p_id
, FormalParList
*p_fpl
,
7151 Reference
*p_runs_on_ref
, StatementBlock
*p_sb
,
7153 : Definition(A_ALTSTEP
, p_id
), fp_list(p_fpl
), runs_on_ref(p_runs_on_ref
),
7154 runs_on_type(0), sb(p_sb
), ags(p_ags
)
7156 if (!p_fpl
|| !p_sb
|| !p_ags
)
7157 FATAL_ERROR("Def_Altstep::Def_Altstep()");
7158 fp_list
->set_my_def(this);
7159 sb
->set_my_def(this);
7160 ags
->set_my_def(this);
7161 ags
->set_my_sb(sb
, 0);
7164 Def_Altstep::~Def_Altstep()
7172 Def_Altstep
*Def_Altstep::clone() const
7174 FATAL_ERROR("Def_Altstep::clone");
7177 void Def_Altstep::set_fullname(const string
& p_fullname
)
7179 Definition::set_fullname(p_fullname
);
7180 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
7181 if (runs_on_ref
) runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
7182 sb
->set_fullname(p_fullname
+".<block>");
7183 ags
->set_fullname(p_fullname
+ ".<guards>");
7186 void Def_Altstep::set_my_scope(Scope
*p_scope
)
7188 bridgeScope
.set_parent_scope(p_scope
);
7189 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
7191 Definition::set_my_scope(&bridgeScope
);
7192 // the scope of the parameter list is set during checking
7193 if (runs_on_ref
) runs_on_ref
->set_my_scope(&bridgeScope
);
7194 sb
->set_my_scope(fp_list
);
7195 ags
->set_my_scope(sb
);
7198 Type
*Def_Altstep::get_RunsOnType()
7200 if (!checked
) chk();
7201 return runs_on_type
;
7204 FormalParList
*Def_Altstep::get_FormalParList()
7206 if (!checked
) chk();
7210 RunsOnScope
*Def_Altstep::get_runs_on_scope(Type
*comptype
)
7212 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
7213 if (!my_module
) FATAL_ERROR("Def_Altstep::get_runs_on_scope()");
7214 return my_module
->get_runs_on_scope(comptype
);
7217 void Def_Altstep::chk()
7219 if (checked
) return;
7221 Error_Context
cntxt(this, "In altstep definition `%s'",
7222 id
->get_dispname().c_str());
7223 Scope
*parlist_scope
= my_scope
;
7225 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
7226 runs_on_type
= runs_on_ref
->chk_comptype_ref();
7228 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
7229 runs_on_scope
->set_parent_scope(my_scope
);
7230 parlist_scope
= runs_on_scope
;
7233 fp_list
->set_my_scope(parlist_scope
);
7234 fp_list
->chk(asstype
);
7236 ags
->set_is_altstep();
7237 ags
->set_my_ags(ags
);
7238 ags
->set_my_laic_stmt(ags
, 0);
7240 if (!semantic_check_only
) {
7241 fp_list
->set_genname(get_genname());
7242 sb
->set_code_section(GovernedSimple::CS_INLINE
);
7243 ags
->set_code_section(GovernedSimple::CS_INLINE
);
7245 if (w_attrib_path
) {
7246 w_attrib_path
->chk_global_attrib();
7247 w_attrib_path
->chk_no_qualif();
7251 void Def_Altstep::generate_code(output_struct
*target
, bool)
7253 const string
& t_genname
= get_genname();
7254 const char *genname_str
= t_genname
.c_str();
7255 const char *dispname_str
= id
->get_dispname().c_str();
7257 // function for altstep instance:
7258 // assemble the function body first (this also determines which parameters
7260 char* body
= create_location_object(memptystr(), "ALTSTEP", dispname_str
);
7261 body
= fp_list
->generate_shadow_objects(body
);
7262 if (debugger_active
) {
7263 body
= generate_code_debugger_function_init(body
, this);
7265 body
= sb
->generate_code(body
);
7266 body
= ags
->generate_code_altstep(body
);
7267 // generate a smart formal parameter list (omits unused parameter names)
7268 char *formal_par_list
= fp_list
->generate_code(memptystr());
7269 fp_list
->generate_code_defval(target
);
7271 // function for altstep instance: prototype
7272 target
->header
.function_prototypes
=
7273 mputprintf(target
->header
.function_prototypes
,
7274 "extern alt_status %s_instance(%s);\n", genname_str
, formal_par_list
);
7276 // function for altstep instance: body
7277 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7278 "alt_status %s_instance(%s)\n"
7281 "}\n\n", genname_str
, formal_par_list
, body
);
7282 Free(formal_par_list
);
7285 char *actual_par_list
=
7286 fp_list
->generate_code_actual_parlist(memptystr(), "");
7288 // use a full formal parameter list for the rest of the functions
7289 char *full_formal_par_list
= fp_list
->generate_code(memptystr(),
7290 fp_list
->get_nof_fps());
7292 // wrapper function for stand-alone instantiation: prototype
7293 target
->header
.function_prototypes
=
7294 mputprintf(target
->header
.function_prototypes
,
7295 "extern void %s(%s);\n", genname_str
, full_formal_par_list
);
7297 // wrapper function for stand-alone instantiation: body
7298 target
->source
.function_bodies
=
7299 mputprintf(target
->source
.function_bodies
, "void %s(%s)\n"
7302 "boolean block_flag = FALSE;\n"
7303 "alt_status altstep_flag = ALT_UNCHECKED, "
7304 "default_flag = ALT_UNCHECKED;\n"
7306 "TTCN_Snapshot::take_new(block_flag);\n"
7307 "if (altstep_flag != ALT_NO) {\n"
7308 "altstep_flag = %s_instance(%s);\n"
7309 "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
7310 "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
7312 "if (default_flag != ALT_NO) {\n"
7313 "default_flag = TTCN_Default::try_altsteps();\n"
7314 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
7315 "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
7317 "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
7318 "TTCN_error(\"None of the branches can be chosen in altstep %s.\");\n"
7319 "else block_flag = TRUE;\n"
7321 "}\n\n", genname_str
, full_formal_par_list
, genname_str
, actual_par_list
,
7324 // class for keeping the altstep in the default context
7325 // the class is for internal use, we do not need to publish it in the
7327 char* str
= mprintf("class %s_Default : public Default_Base {\n", genname_str
);
7328 str
= fp_list
->generate_code_object(str
, "par_");
7329 str
= mputprintf(str
, "public:\n"
7331 "alt_status call_altstep();\n"
7332 "};\n\n", genname_str
, full_formal_par_list
);
7333 target
->source
.class_defs
= mputstr(target
->source
.class_defs
, str
);
7335 // member functions of the class
7336 str
= mprintf("%s_Default::%s_Default(%s)\n"
7337 " : Default_Base(\"%s\")", genname_str
, genname_str
, full_formal_par_list
,
7339 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); i
++) {
7340 const char *fp_name_str
=
7341 fp_list
->get_fp_byIndex(i
)->get_id().get_name().c_str();
7342 str
= mputprintf(str
, ", par_%s(%s)", fp_name_str
, fp_name_str
);
7344 str
= mputstr(str
, "\n{\n}\n\n");
7345 char *actual_par_list_prefixed
=
7346 fp_list
->generate_code_actual_parlist(memptystr(), "par_");
7347 str
= mputprintf(str
, "alt_status %s_Default::call_altstep()\n"
7349 "return %s_instance(%s);\n"
7350 "}\n\n", genname_str
, genname_str
, actual_par_list_prefixed
);
7351 Free(actual_par_list_prefixed
);
7352 target
->source
.methods
= mputstr(target
->source
.methods
, str
);
7355 // function for default activation: prototype
7356 target
->header
.function_prototypes
=
7357 mputprintf(target
->header
.function_prototypes
,
7358 "extern Default_Base *activate_%s(%s);\n", genname_str
,
7359 full_formal_par_list
);
7361 // function for default activation: body
7362 str
= mprintf("Default_Base *activate_%s(%s)\n"
7363 "{\n", genname_str
, full_formal_par_list
);
7364 str
= mputprintf(str
, "return new %s_Default(%s);\n"
7365 "}\n\n", genname_str
, actual_par_list
);
7366 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7370 Free(full_formal_par_list
);
7371 Free(actual_par_list
);
7373 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7374 "%s.add_altstep(\"%s\", (genericfunc_t)&%s_instance, (genericfunc_t )&activate_%s, "
7375 "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str
, genname_str
,
7376 genname_str
, genname_str
);
7379 void Def_Altstep::generate_code(CodeGenHelper
& cgh
) {
7380 generate_code(cgh
.get_current_outputstruct());
7383 void Def_Altstep::dump_internal(unsigned level
) const
7385 DEBUG(level
, "Altstep: %s", id
->get_dispname().c_str());
7386 DEBUG(level
+ 1, "Parameters:");
7387 fp_list
->dump(level
+ 1);
7389 DEBUG(level
+ 1, "Runs on clause:");
7390 runs_on_ref
->dump(level
+ 2);
7393 DEBUG(level + 1, "Local definitions:");
7394 sb->dump(level + 2);
7396 DEBUG(level
+ 1, "Guards:");
7397 ags
->dump(level
+ 2);
7400 void Def_Altstep::set_parent_path(WithAttribPath
* p_path
) {
7401 Definition::set_parent_path(p_path
);
7402 sb
->set_parent_path(w_attrib_path
);
7405 // =================================
7406 // ===== Def_Testcase
7407 // =================================
7409 Def_Testcase::Def_Testcase(Identifier
*p_id
, FormalParList
*p_fpl
,
7410 Reference
*p_runs_on_ref
, Reference
*p_system_ref
,
7411 StatementBlock
*p_block
)
7412 : Definition(A_TESTCASE
, p_id
), fp_list(p_fpl
), runs_on_ref(p_runs_on_ref
),
7413 runs_on_type(0), system_ref(p_system_ref
), system_type(0), block(p_block
)
7415 if (!p_fpl
|| !p_runs_on_ref
|| !p_block
)
7416 FATAL_ERROR("Def_Testcase::Def_Testcase()");
7417 fp_list
->set_my_def(this);
7418 block
->set_my_def(this);
7421 Def_Testcase::~Def_Testcase()
7429 Def_Testcase
*Def_Testcase::clone() const
7431 FATAL_ERROR("Def_Testcase::clone");
7434 void Def_Testcase::set_fullname(const string
& p_fullname
)
7436 Definition::set_fullname(p_fullname
);
7437 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
7438 runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
7439 if (system_ref
) system_ref
->set_fullname(p_fullname
+ ".<system_type>");
7440 block
->set_fullname(p_fullname
+ ".<statement_block>");
7443 void Def_Testcase::set_my_scope(Scope
*p_scope
)
7445 bridgeScope
.set_parent_scope(p_scope
);
7446 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
7448 Definition::set_my_scope(&bridgeScope
);
7449 // the scope of the parameter list is set during checking
7450 runs_on_ref
->set_my_scope(&bridgeScope
);
7451 if (system_ref
) system_ref
->set_my_scope(&bridgeScope
);
7452 block
->set_my_scope(fp_list
);
7455 Type
*Def_Testcase::get_RunsOnType()
7457 if (!checked
) chk();
7458 return runs_on_type
;
7461 Type
*Def_Testcase::get_SystemType()
7463 if (!checked
) chk();
7467 FormalParList
*Def_Testcase::get_FormalParList()
7469 if (!checked
) chk();
7473 RunsOnScope
*Def_Testcase::get_runs_on_scope(Type
*comptype
)
7475 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
7476 if (!my_module
) FATAL_ERROR("Def_Testcase::get_runs_on_scope()");
7477 return my_module
->get_runs_on_scope(comptype
);
7480 void Def_Testcase::chk()
7482 if (checked
) return;
7484 Error_Context
cntxt(this, "In testcase definition `%s'",
7485 id
->get_dispname().c_str());
7486 Scope
*parlist_scope
= my_scope
;
7488 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
7489 runs_on_type
= runs_on_ref
->chk_comptype_ref();
7491 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
7492 runs_on_scope
->set_parent_scope(my_scope
);
7493 parlist_scope
= runs_on_scope
;
7497 Error_Context
cntxt2(system_ref
, "In `system' clause");
7498 system_type
= system_ref
->chk_comptype_ref();;
7500 fp_list
->set_my_scope(parlist_scope
);
7501 fp_list
->chk(asstype
);
7503 if (!semantic_check_only
) {
7504 fp_list
->set_genname(get_genname());
7505 block
->set_code_section(GovernedSimple::CS_INLINE
);
7507 if (w_attrib_path
) {
7508 w_attrib_path
->chk_global_attrib();
7509 w_attrib_path
->chk_no_qualif();
7513 void Def_Testcase::generate_code(output_struct
*target
, bool)
7515 const string
& t_genname
= get_genname();
7516 const char *genname_str
= t_genname
.c_str();
7517 const char *dispname_str
= id
->get_dispname().c_str();
7519 // assemble the function body first (this also determines which parameters
7522 // Checking whether the testcase was invoked from another one.
7523 // At this point the location information should refer to the execute()
7524 // statement rather than this testcase.
7525 char* body
= mputstr(memptystr(), "TTCN_Runtime::check_begin_testcase(has_timer, "
7527 body
= create_location_object(body
, "TESTCASE", dispname_str
);
7528 body
= fp_list
->generate_shadow_objects(body
);
7529 body
= mputprintf(body
, "try {\n"
7530 "TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
7531 my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
7533 ComponentTypeBody
*runs_on_body
= runs_on_type
->get_CompBody();
7534 body
= runs_on_body
->generate_code_comptype_name(body
);
7535 body
= mputstr(body
, ", ");
7537 body
= system_type
->get_CompBody()->generate_code_comptype_name(body
);
7538 else body
= runs_on_body
->generate_code_comptype_name(body
);
7539 body
= mputstr(body
, ", has_timer, timer_value);\n");
7540 if (debugger_active
) {
7541 body
= generate_code_debugger_function_init(body
, this);
7543 body
= block
->generate_code(body
);
7544 body
= mputprintf(body
,
7545 "} catch (const TC_Error& tc_error) {\n"
7546 "} catch (const TC_End& tc_end) {\n"
7547 "TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
7548 "}\n", dispname_str
);
7549 body
= mputstr(body
, "return TTCN_Runtime::end_testcase();\n");
7551 // smart formal parameter list (names of unused parameters are omitted)
7552 char *formal_par_list
= fp_list
->generate_code(memptystr());
7553 fp_list
->generate_code_defval(target
);
7554 if (fp_list
->get_nof_fps() > 0)
7555 formal_par_list
= mputstr(formal_par_list
, ", ");
7556 formal_par_list
= mputstr(formal_par_list
,
7557 "boolean has_timer, double timer_value");
7559 // function prototype
7560 target
->header
.function_prototypes
=
7561 mputprintf(target
->header
.function_prototypes
,
7562 "extern verdicttype testcase_%s(%s);\n", genname_str
, formal_par_list
);
7565 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7566 "verdicttype testcase_%s(%s)\n"
7569 "}\n\n", genname_str
, formal_par_list
, body
);
7570 Free(formal_par_list
);
7573 if (fp_list
->get_nof_fps() == 0) {
7574 // adding to the list of startable testcases
7575 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7576 "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
7577 get_module_object_name(), dispname_str
, genname_str
);
7579 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7580 "%s.add_testcase_pard(\"%s\", (genericfunc_t)&testcase_%s);\n",
7581 get_module_object_name(), dispname_str
, genname_str
);
7583 // If every formal parameter has a default value, the testcase
7584 // might be callable after all.
7585 bool callable
= true;
7586 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7587 FormalPar
*fp
= fp_list
->get_fp_byIndex(i
);
7588 if (!fp
->has_defval()) {
7595 // Write a wrapper, which acts as a no-param testcase
7596 // by calling the parameterized testcase with the default values.
7597 target
->header
.function_prototypes
=
7598 mputprintf(target
->header
.function_prototypes
,
7599 "extern verdicttype testcase_%s_defparams(boolean has_timer, double timer_value);\n",
7601 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7602 "verdicttype testcase_%s_defparams(boolean has_timer, double timer_value) {\n"
7603 " return testcase_%s(",
7604 genname_str
, genname_str
);
7606 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7607 FormalPar
*fp
= fp_list
->get_fp_byIndex(i
);
7608 ActualPar
*ap
= fp
->get_defval();
7609 switch (ap
->get_selection()) {
7610 case ActualPar::AP_VALUE
:
7611 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7612 ap
->get_Value()->get_genname_own(my_scope
).c_str());
7614 case ActualPar::AP_TEMPLATE
:
7615 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7616 ap
->get_TemplateInstance()->get_Template()->get_genname_own(my_scope
).c_str());
7618 case ActualPar::AP_REF
:
7619 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7620 ap
->get_Ref()->get_refd_assignment()->get_genname_from_scope(my_scope
).c_str());
7622 case ActualPar::AP_DEFAULT
:
7623 // Can't happen. This ActualPar was created by
7624 // Ttcn::FormalPar::chk_actual_par as the default value for
7625 // a FormalPar, and it only ever creates vale, template or ref.
7628 FATAL_ERROR("Def_Testcase::generate_code()");
7631 // always append a comma, because has_timer and timer_value follows
7632 target
->source
.function_bodies
= mputstrn(target
->source
.function_bodies
,
7636 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7637 "has_timer, timer_value);\n"
7639 // Add the non-parameterized wrapper *after* the parameterized one,
7640 // with the same name. Linear search will always find the first
7641 // (user-visible, parameterized) testcase.
7642 // TTCN_Module::execute_testcase knows that if after a parameterized
7643 // testcase another testcase with the same name follows,
7644 // it's the callable, non-parameterized wrapper.
7646 // TTCN_Module::list_testcases skips parameterized testcases;
7647 // it will now list the non-parameterized wrapper.
7648 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7649 "%s.add_testcase_nonpard(\"%s\", testcase_%s_defparams);\n",
7650 get_module_object_name(), dispname_str
, genname_str
);
7652 } // has formal parameters
7655 void Def_Testcase::generate_code(CodeGenHelper
& cgh
) {
7656 generate_code(cgh
.get_current_outputstruct());
7659 void Def_Testcase::dump_internal(unsigned level
) const
7661 DEBUG(level
, "Testcase: %s", id
->get_dispname().c_str());
7662 DEBUG(level
+ 1, "Parameters:");
7663 fp_list
->dump(level
+ 1);
7664 DEBUG(level
+ 1, "Runs on clause:");
7665 runs_on_ref
->dump(level
+ 2);
7667 DEBUG(level
+ 1, "System clause:");
7668 system_ref
->dump(level
+ 2);
7670 DEBUG(level
+ 1, "Statement block:");
7671 block
->dump(level
+ 2);
7674 void Def_Testcase::set_parent_path(WithAttribPath
* p_path
) {
7675 Definition::set_parent_path(p_path
);
7677 block
->set_parent_path(w_attrib_path
);
7680 // =================================
7682 // =================================
7684 FormalPar::FormalPar(asstype_t p_asstype
, Type
*p_type
, Identifier
* p_name
,
7685 TemplateInstance
*p_defval
, bool p_lazy_eval
)
7686 : Definition(p_asstype
, p_name
), type(p_type
), my_parlist(0),
7687 used_as_lvalue(false), template_restriction(TR_NONE
),
7688 lazy_eval(p_lazy_eval
), defval_generated(false), usage_found(false)
7690 switch (p_asstype
) {
7694 case A_PAR_VAL_INOUT
:
7695 case A_PAR_TEMPL_IN
:
7696 case A_PAR_TEMPL_OUT
:
7697 case A_PAR_TEMPL_INOUT
:
7701 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7704 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7705 type
->set_ownertype(Type::OT_FORMAL_PAR
, this);
7706 defval
.ti
= p_defval
;
7709 FormalPar::FormalPar(asstype_t p_asstype
,
7710 template_restriction_t p_template_restriction
, Type
*p_type
,
7711 Identifier
* p_name
, TemplateInstance
*p_defval
, bool p_lazy_eval
)
7712 : Definition(p_asstype
, p_name
), type(p_type
), my_parlist(0),
7713 used_as_lvalue(false), template_restriction(p_template_restriction
),
7714 lazy_eval(p_lazy_eval
), defval_generated(false), usage_found(false)
7716 switch (p_asstype
) {
7717 case A_PAR_TEMPL_IN
:
7718 case A_PAR_TEMPL_OUT
:
7719 case A_PAR_TEMPL_INOUT
:
7722 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): parameter not template");
7725 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7726 type
->set_ownertype(Type::OT_FORMAL_PAR
, this);
7727 defval
.ti
= p_defval
;
7730 FormalPar::FormalPar(asstype_t p_asstype
, Identifier
* p_name
,
7731 TemplateInstance
*p_defval
)
7732 : Definition(p_asstype
, p_name
), type(0), my_parlist(0),
7733 used_as_lvalue(false), template_restriction(TR_NONE
), lazy_eval(false),
7734 defval_generated(false), usage_found(false)
7736 if (p_asstype
!= A_PAR_TIMER
)
7737 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7738 defval
.ti
= p_defval
;
7741 FormalPar::~FormalPar()
7744 if (checked
) delete defval
.ap
;
7745 else delete defval
.ti
;
7748 FormalPar
* FormalPar::clone() const
7750 FATAL_ERROR("FormalPar::clone");
7753 void FormalPar::set_fullname(const string
& p_fullname
)
7755 Definition::set_fullname(p_fullname
);
7756 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
7758 if (defval
.ap
) defval
.ap
->set_fullname(p_fullname
+ ".<default_value>");
7760 if (defval
.ti
) defval
.ti
->set_fullname(p_fullname
+ ".<default_value>");
7764 void FormalPar::set_my_scope(Scope
*p_scope
)
7766 Definition::set_my_scope(p_scope
);
7767 if (type
) type
->set_my_scope(p_scope
);
7769 if (defval
.ap
) defval
.ap
->set_my_scope(p_scope
);
7771 if (defval
.ti
) defval
.ti
->set_my_scope(p_scope
);
7775 bool FormalPar::is_local() const
7780 Type
*FormalPar::get_Type()
7782 if (!checked
) chk();
7783 if (!type
) FATAL_ERROR("FormalPar::get_Type()");
7787 void FormalPar::chk()
7789 if (checked
) return;
7791 TemplateInstance
*default_value
= defval
.ti
;
7795 Type
*t
= type
->get_type_refd_last();
7796 // checks for forbidden type <-> parameter combinations
7797 switch (t
->get_typetype()) {
7801 case A_PAR_VAL_INOUT
:
7802 asstype
= A_PAR_PORT
;
7805 error("Port type `%s' cannot be used as %s",
7806 t
->get_fullname().c_str(), get_assname());
7809 case Type::T_SIGNATURE
:
7811 case A_PAR_TEMPL_IN
:
7812 case A_PAR_TEMPL_OUT
:
7813 case A_PAR_TEMPL_INOUT
:
7816 error("Signature `%s' cannot be used as %s",
7817 t
->get_fullname().c_str(), get_assname());
7824 FATAL_ERROR("FormalPar::chk()");
7826 asstype
= A_PAR_VAL_IN
;
7831 } else if (asstype
!= A_PAR_TIMER
) FATAL_ERROR("FormalPar::chk()");
7833 if (default_value
) {
7834 Error_Context
cntxt(default_value
, "In default value");
7835 defval
.ap
= chk_actual_par(default_value
, Type::EXPECTED_STATIC_VALUE
);
7836 delete default_value
;
7837 if (!semantic_check_only
)
7838 defval
.ap
->set_code_section(GovernedSimple::CS_POST_INIT
);
7842 bool FormalPar::has_defval() const
7844 if (checked
) return defval
.ap
!= 0;
7845 else return defval
.ti
!= 0;
7848 bool FormalPar::has_notused_defval() const
7850 if (checked
) FATAL_ERROR("FormalPar::has_notused_defval");
7851 if (!defval
.ti
|| !defval
.ti
->get_Template())
7853 return defval
.ti
->get_Template()->get_templatetype()
7854 == Template::TEMPLATE_NOTUSED
;
7857 ActualPar
*FormalPar::get_defval() const
7859 if (!checked
) FATAL_ERROR("FormalPar::get_defval()");
7863 // Extract the TemplateInstance from an ActualPar.
7864 void FormalPar::set_defval(ActualPar
*defpar
)
7866 // ActualPar::clone() is not implemented, since we need such a function
7867 // only here only for AP_{VALUE,TEMPLATE} parameters. AP_ERROR can also
7868 // happen for Def_Template nodes, but they will be errors later.
7869 // FIXME: This function is Def_Template specific.
7870 if (!defval
.ti
->get_Template() || defval
.ti
->get_Template()
7871 ->get_templatetype() != Template::TEMPLATE_NOTUSED
)
7872 FATAL_ERROR("FormalPar::set_defval()");
7873 TemplateInstance
*reversed_ti
= 0;
7874 switch (defpar
->get_selection()) {
7875 case ActualPar::AP_VALUE
:
7876 reversed_ti
= new TemplateInstance(type
->clone(), 0, new Template
7877 (defpar
->get_Value()->clone())); // Trust the clone().
7879 case ActualPar::AP_TEMPLATE
:
7880 reversed_ti
= defpar
->get_TemplateInstance()->clone();
7882 case ActualPar::AP_ERROR
:
7883 break; // Can happen, but let it go.
7884 case ActualPar::AP_REF
:
7885 case ActualPar::AP_DEFAULT
:
7887 FATAL_ERROR("FormalPar::set_defval()");
7891 reversed_ti
->set_my_scope(get_my_scope());
7892 defval
.ti
= reversed_ti
;
7896 ActualPar
*FormalPar::chk_actual_par(TemplateInstance
*actual_par
,
7897 Type::expected_value_t exp_val
)
7899 if (!checked
) chk();
7903 return chk_actual_par_value(actual_par
, exp_val
);
7905 case A_PAR_VAL_INOUT
:
7906 return chk_actual_par_by_ref(actual_par
, false, exp_val
);
7907 case A_PAR_TEMPL_IN
:
7908 return chk_actual_par_template(actual_par
, exp_val
);
7909 case A_PAR_TEMPL_OUT
:
7910 case A_PAR_TEMPL_INOUT
:
7911 return chk_actual_par_by_ref(actual_par
, true, exp_val
);
7913 return chk_actual_par_timer(actual_par
, exp_val
);
7915 return chk_actual_par_port(actual_par
, exp_val
);
7917 FATAL_ERROR("FormalPar::chk_actual_par()");
7919 return 0; // to avoid warnings
7922 ActualPar
*FormalPar::chk_actual_par_value(TemplateInstance
*actual_par
,
7923 Type::expected_value_t exp_val
)
7925 actual_par
->chk_Type(type
);
7926 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
7928 derived_ref
->error("An in-line modified template cannot be used as %s",
7930 actual_par
->chk_DerivedRef(type
);
7932 Template
*ap_template
= actual_par
->get_Template();
7933 if (ap_template
->is_Value()) {
7934 Value
*v
= ap_template
->get_Value();
7935 v
->set_my_governor(type
);
7936 type
->chk_this_value_ref(v
);
7937 type
->chk_this_value(v
, 0, exp_val
, INCOMPLETE_NOT_ALLOWED
,
7938 OMIT_NOT_ALLOWED
, SUB_CHK
);
7939 return new ActualPar(v
);
7941 actual_par
->error("A specific value without matching symbols "
7942 "was expected for a %s", get_assname());
7943 return new ActualPar();
7947 static void chk_defpar_value(const Value
* v
)
7949 Common::Reference
*vref
= v
->get_reference();
7950 Common::Assignment
*ass2
= vref
->get_refd_assignment();
7952 Scope
*scope
= ass2
->get_my_scope();
7953 ComponentTypeBody
*ctb
= dynamic_cast<ComponentTypeBody
*>(scope
);
7954 if (ctb
) { // this is a component variable
7955 v
->error("default value cannot refer to"
7956 " a template field of the component in the `runs on' clause");
7960 static void chk_defpar_template(const Template
*body
,
7961 Type::expected_value_t exp_val
)
7963 switch (body
->get_templatetype()) {
7964 case Template::TEMPLATE_ERROR
:
7965 break; // could be erroneous in the source; skip it
7966 case Template::TEMPLATE_NOTUSED
:
7967 case Template::OMIT_VALUE
:
7968 case Template::ANY_VALUE
:
7969 case Template::ANY_OR_OMIT
:
7970 break; // acceptable (?)
7971 case Template::TEMPLATE_INVOKE
: // calling a function is not acceptable
7972 body
->error("default value can not be a function invocation");
7974 case Template::VALUE_RANGE
: {
7975 ValueRange
*range
= body
->get_value_range();
7976 Value
*low
= range
->get_min_v();
7977 Type::typetype_t tt_low
= low
->get_expr_returntype(exp_val
);
7978 Value
*high
= range
->get_max_v();
7979 Type::typetype_t tt_high
= high
->get_expr_returntype(exp_val
);
7980 if (tt_low
== tt_high
) break;
7983 case Template::BSTR_PATTERN
:
7984 case Template::HSTR_PATTERN
:
7985 case Template::OSTR_PATTERN
:
7986 case Template::CSTR_PATTERN
:
7987 case Template::USTR_PATTERN
:
7988 break; // should be acceptable in all cases (if only fixed strings possible)
7990 case Template::SPECIFIC_VALUE
: {
7991 Common::Value
*v
= body
->get_specific_value();
7992 if (v
->get_valuetype() == Value::V_REFD
) chk_defpar_value(v
);
7995 case Template::ALL_FROM
:
7996 case Template::VALUE_LIST_ALL_FROM
:
7997 FATAL_ERROR("should have been flattened");
7999 case Template::SUPERSET_MATCH
:
8000 case Template::SUBSET_MATCH
:
8001 case Template::PERMUTATION_MATCH
:
8002 case Template::TEMPLATE_LIST
:
8003 case Template::COMPLEMENTED_LIST
:
8004 case Template::VALUE_LIST
: {
8005 // in template charstring par := charstring : ("foo", "bar", "baz")
8006 size_t num
= body
->get_nof_comps();
8007 for (size_t i
= 0; i
< num
; ++i
) {
8008 const Template
*tpl
= body
->get_temp_byIndex(i
);
8009 chk_defpar_template(tpl
, exp_val
);
8013 case Template::NAMED_TEMPLATE_LIST
: {
8014 size_t num
= body
->get_nof_comps();
8015 for (size_t i
= 0; i
< num
; ++i
) {
8016 const NamedTemplate
*nt
= body
->get_namedtemp_byIndex(i
);
8017 const Template
*tpl
= nt
->get_template();
8018 chk_defpar_template(tpl
, exp_val
);
8022 case Template::INDEXED_TEMPLATE_LIST
: {
8023 size_t num
= body
->get_nof_comps();
8024 for (size_t i
= 0; i
< num
; ++i
) {
8025 const IndexedTemplate
*it
= body
->get_indexedtemp_byIndex(i
);
8026 const Template
*tpl
= it
->get_template();
8027 chk_defpar_template(tpl
, exp_val
);
8031 case Template::TEMPLATE_REFD
: {
8032 Ref_base
*ref
= body
->get_reference();
8034 Ttcn::ActualParList
*aplist
= ref
->get_parlist();
8036 size_t num
= aplist
->get_nof_pars();
8037 for (size_t i
= 0; i
< num
; ++i
) {
8038 const Ttcn::ActualPar
*ap
= aplist
->get_par(i
);
8040 switch (ap
->get_selection()) {
8041 case ActualPar::AP_ERROR
: {
8043 case ActualPar::AP_VALUE
: {
8044 Value
*v
= ap
->get_Value(); // "v_variable" as the parameter of the template
8046 switch (v
->get_valuetype()) {
8047 case Value::V_REFD
: {
8048 chk_defpar_value(v
);
8054 case ActualPar::AP_TEMPLATE
: {
8055 // A component cannot contain a template definition, parameterized or not.
8056 // Therefore the template this actual par references, cannot be
8057 // a field of a component => no error possible, nothing to do.
8059 case ActualPar::AP_REF
: {
8060 // A template cannot have an out/inout parameter
8061 FATAL_ERROR("Template with out parameter?");
8063 case ActualPar::AP_DEFAULT
: {
8064 ap
= ap
->get_ActualPar();
8068 } // switch actual par selection
8072 } // switch templatetype
8076 // This function is called in two situations:
8077 // 1. FormalParList::chk calls FormalPar::chk to compute the default value
8078 // (make an ActualPar from a TemplateInstance).
8079 // In this case, defval.ti==0, and actual_par contains its old value.
8080 // This case is called only if the formal par has a default value.
8081 // 2. FormalParList::chk_actual_parlist calls FormalPar::chk_actual_par
8082 // to check the parameters supplied by the execute statement to the tc.
8083 // In this case, defval.ap has the value computed in case 1.
8084 ActualPar
*FormalPar::chk_actual_par_template(TemplateInstance
*actual_par
,
8085 Type::expected_value_t exp_val
)
8087 actual_par
->chk(type
);
8088 // actual_par->template_body may change: SPECIFIC_VALUE to TEMPLATE_REFD
8089 Definition
*fplist_def
= my_parlist
->get_my_def();
8090 // The parameter list belongs to this definition. If it's a function
8091 // or testcase, it may have a "runs on" clause.
8092 Def_Function
*parent_fn
= dynamic_cast<Def_Function
*>(fplist_def
);
8093 Type
*runs_on_type
= 0;
8094 if (parent_fn
) runs_on_type
= parent_fn
->get_RunsOnType();
8095 else { // not a function; maybe a testcase
8096 Def_Testcase
*parent_tc
= dynamic_cast<Def_Testcase
*>(fplist_def
);
8097 if (parent_tc
) runs_on_type
= parent_tc
->get_RunsOnType();
8100 // If it _has_ a runs on clause, the type must be a component.
8101 if (runs_on_type
->get_typetype() != Type::T_COMPONENT
) FATAL_ERROR("not component?");
8102 // The default value "shall not refer to elements of the component type
8103 // in the runs on clause"
8104 ComponentTypeBody
*runs_on_component
= runs_on_type
->get_CompBody();
8105 size_t compass
= runs_on_component
->get_nof_asss();
8106 for (size_t c
= 0; c
< compass
; c
++) {
8107 Assignment
*ass
= runs_on_component
->get_ass_byIndex(c
);
8112 Ttcn::Template
* body
= actual_par
->get_Template();
8113 if (exp_val
== Type::EXPECTED_STATIC_VALUE
8114 ||exp_val
== Type::EXPECTED_CONSTANT
) {
8115 chk_defpar_template(body
, exp_val
);
8117 // Rip out the type, derived ref and template from actual_par
8118 // (which may come from a function invocation or the definition
8119 // of the default value) and give it to the new ActualPar.
8120 ActualPar
*ret_val
= new ActualPar(
8121 new TemplateInstance(actual_par
->get_Type(),
8122 actual_par
->get_DerivedRef(), actual_par
->get_Template()));
8123 // Zero out these members because the caller will soon call delete
8124 // on actual_par, but they now belong to ret_val.
8125 // FIXME: should this really be in here, or outside in the caller before the delete ?
8126 actual_par
->release();
8128 if (template_restriction
!=TR_NONE
) {
8129 bool needs_runtime_check
=
8130 ret_val
->get_TemplateInstance()->chk_restriction(
8131 "template formal parameter", template_restriction
,
8132 ret_val
->get_TemplateInstance());
8133 if (needs_runtime_check
)
8134 ret_val
->set_gen_restriction_check(template_restriction
);
8139 ActualPar
*FormalPar::chk_actual_par_by_ref(TemplateInstance
*actual_par
,
8140 bool is_template
, Type::expected_value_t exp_val
)
8142 Type
*ap_type
= actual_par
->get_Type();
8144 ap_type
->warning("Explicit type specification is useless for an %s",
8146 actual_par
->chk_Type(type
);
8148 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8150 derived_ref
->error("An in-line modified template cannot be used as %s",
8152 actual_par
->chk_DerivedRef(type
);
8154 // needed for the error messages
8155 const char *expected_string
= is_template
?
8156 "template variable or template parameter" :
8157 "variable or value parameter";
8158 Template
*ap_template
= actual_par
->get_Template();
8159 if (ap_template
->is_Ref()) {
8160 Ref_base
*ref
= ap_template
->get_Ref();
8161 Common::Assignment
*ass
= ref
->get_refd_assignment();
8164 return new ActualPar();
8166 bool asstype_correct
= false;
8167 switch (ass
->get_asstype()) {
8169 ass
->use_as_lvalue(*ref
);
8170 if (get_asstype() == A_PAR_VAL_OUT
|| get_asstype() == A_PAR_TEMPL_OUT
) {
8171 ass
->warning("Passing an `in' parameter as another function's `out' parameter");
8176 case A_PAR_VAL_INOUT
:
8177 if (!is_template
) asstype_correct
= true;
8179 case A_PAR_TEMPL_IN
:
8180 ass
->use_as_lvalue(*ref
);
8181 if (get_asstype() == A_PAR_VAL_OUT
|| get_asstype() == A_PAR_TEMPL_OUT
) {
8182 ass
->warning("Passing an `in' parameter as another function's `out' parameter");
8185 case A_VAR_TEMPLATE
:
8186 case A_PAR_TEMPL_OUT
:
8187 case A_PAR_TEMPL_INOUT
:
8188 if (is_template
) asstype_correct
= true;
8193 if (asstype_correct
) {
8194 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
8195 Type
*ref_type
= ass
->get_Type()->get_field_type(t_subrefs
, exp_val
);
8197 if (!type
->is_identical(ref_type
)) {
8198 ref
->error("Type mismatch: Reference to a %s of type "
8199 "`%s' was expected instead of `%s'", expected_string
,
8200 type
->get_typename().c_str(), ref_type
->get_typename().c_str());
8201 } else if (type
->get_sub_type() && ref_type
->get_sub_type() &&
8202 (type
->get_sub_type()->get_subtypetype()==ref_type
->get_sub_type()->get_subtypetype()) &&
8203 (!type
->get_sub_type()->is_compatible(ref_type
->get_sub_type()))) {
8204 ref
->error("Subtype mismatch: subtype %s has no common value with subtype %s",
8205 type
->get_sub_type()->to_string().c_str(),
8206 ref_type
->get_sub_type()->to_string().c_str());
8208 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
8209 ref
->error("Reference to a string element of type `%s' cannot be "
8210 "used in this context", ref_type
->get_typename().c_str());
8214 ref
->error("Reference to a %s was expected for an %s instead of %s",
8215 expected_string
, get_assname(), ass
->get_description().c_str());
8217 ActualPar
* ret_val_ap
= new ActualPar(ref
);
8218 // restriction checking if this is a reference to a template variable
8219 // this is an 'out' or 'inout' template parameter
8220 if (is_template
&& asstype_correct
) {
8221 template_restriction_t refd_tr
;
8222 switch (ass
->get_asstype()) {
8223 case A_VAR_TEMPLATE
: {
8224 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(ass
);
8225 if (!dvt
) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8226 refd_tr
= dvt
->get_template_restriction();
8228 case A_PAR_TEMPL_IN
:
8229 case A_PAR_TEMPL_OUT
:
8230 case A_PAR_TEMPL_INOUT
: {
8231 FormalPar
* fp
= dynamic_cast<FormalPar
*>(ass
);
8232 if (!fp
) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8233 refd_tr
= fp
->get_template_restriction();
8236 FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8239 refd_tr
= Template::get_sub_restriction(refd_tr
, ref
);
8240 if (template_restriction
!=refd_tr
) {
8241 bool pre_call_check
=
8242 Template::is_less_restrictive(template_restriction
, refd_tr
);
8243 bool post_call_check
=
8244 Template::is_less_restrictive(refd_tr
, template_restriction
);
8245 if (pre_call_check
|| post_call_check
) {
8246 ref
->warning("Inadequate restriction on the referenced %s `%s', "
8247 "this may cause a dynamic test case error at runtime",
8248 ass
->get_assname(), ref
->get_dispname().c_str());
8249 ass
->note("Referenced %s is here", ass
->get_assname());
8252 ret_val_ap
->set_gen_restriction_check(template_restriction
);
8253 if (post_call_check
)
8254 ret_val_ap
->set_gen_post_restriction_check(refd_tr
);
8256 // for out and inout template parameters of external functions
8257 // always check because we do not trust user written C++ code
8258 if (refd_tr
!=TR_NONE
) {
8259 switch (my_parlist
->get_my_def()->get_asstype()) {
8260 case A_EXT_FUNCTION
:
8261 case A_EXT_FUNCTION_RVAL
:
8262 case A_EXT_FUNCTION_RTEMP
:
8263 ret_val_ap
->set_gen_post_restriction_check(refd_tr
);
8272 actual_par
->error("Reference to a %s was expected for an %s",
8273 expected_string
, get_assname());
8274 return new ActualPar();
8278 ActualPar
*FormalPar::chk_actual_par_timer(TemplateInstance
*actual_par
,
8279 Type::expected_value_t exp_val
)
8281 Type
*ap_type
= actual_par
->get_Type();
8283 ap_type
->error("Explicit type specification cannot be used for a "
8285 actual_par
->chk_Type(0);
8287 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8289 derived_ref
->error("An in-line modified template cannot be used as "
8291 actual_par
->chk_DerivedRef(0);
8293 Template
*ap_template
= actual_par
->get_Template();
8294 if (ap_template
->is_Ref()) {
8295 Ref_base
*ref
= ap_template
->get_Ref();
8296 Common::Assignment
*ass
= ref
->get_refd_assignment();
8299 return new ActualPar();
8301 switch (ass
->get_asstype()) {
8303 ArrayDimensions
*dims
= ass
->get_Dimensions();
8304 if (dims
) dims
->chk_indices(ref
, "timer", false, exp_val
);
8305 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8306 "cannot have field or array sub-references",
8307 ass
->get_description().c_str());
8310 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8311 "field or array sub-references", ass
->get_description().c_str());
8314 ref
->error("Reference to a timer or timer parameter was expected for "
8315 "a timer parameter instead of %s", ass
->get_description().c_str());
8317 return new ActualPar(ref
);
8319 actual_par
->error("Reference to a timer or timer parameter was "
8320 "expected for a timer parameter");
8321 return new ActualPar();
8325 ActualPar
*FormalPar::chk_actual_par_port(TemplateInstance
*actual_par
,
8326 Type::expected_value_t exp_val
)
8328 Type
*ap_type
= actual_par
->get_Type();
8330 ap_type
->warning("Explicit type specification is useless for a port "
8332 actual_par
->chk_Type(type
);
8334 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8336 derived_ref
->error("An in-line modified template cannot be used as "
8338 actual_par
->chk_DerivedRef(type
);
8340 Template
*ap_template
= actual_par
->get_Template();
8341 if (ap_template
->is_Ref()) {
8342 Ref_base
*ref
= ap_template
->get_Ref();
8343 Common::Assignment
*ass
= ref
->get_refd_assignment();
8346 return new ActualPar();
8348 bool asstype_correct
= false;
8349 switch (ass
->get_asstype()) {
8351 ArrayDimensions
*dims
= ass
->get_Dimensions();
8352 if (dims
) dims
->chk_indices(ref
, "port", false, exp_val
);
8353 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8354 "cannot have field or array sub-references",
8355 ass
->get_description().c_str());
8356 asstype_correct
= true;
8359 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8360 "field or array sub-references", ass
->get_description().c_str());
8361 asstype_correct
= true;
8364 ref
->error("Reference to a port or port parameter was expected for a "
8365 "port parameter instead of %s", ass
->get_description().c_str());
8367 if (asstype_correct
) {
8368 Type
*ref_type
= ass
->get_Type();
8369 if (ref_type
&& !type
->is_identical(ref_type
))
8370 ref
->error("Type mismatch: Reference to a port or port parameter "
8371 "of type `%s' was expected instead of `%s'",
8372 type
->get_typename().c_str(), ref_type
->get_typename().c_str());
8374 return new ActualPar(ref
);
8376 actual_par
->error("Reference to a port or port parameter was expected "
8377 "for a port parameter");
8378 return new ActualPar();
8382 void FormalPar::use_as_lvalue(const Location
& p_loc
)
8386 case A_PAR_TEMPL_IN
:
8389 FATAL_ERROR("FormalPar::use_as_lvalue()");
8391 if (!used_as_lvalue
) {
8392 Definition
*my_def
= my_parlist
->get_my_def();
8393 if (!my_def
) FATAL_ERROR("FormalPar::use_as_lvalue()");
8394 if (my_def
->get_asstype() == A_TEMPLATE
)
8395 p_loc
.error("Parameter `%s' of the template cannot be passed further "
8396 "as `out' or `inout' parameter", id
->get_dispname().c_str());
8398 // update the genname so that all references in the generated code
8399 // will point to the shadow object
8401 set_genname(id
->get_name() + "_shadow");
8403 used_as_lvalue
= true;
8408 char* FormalPar::generate_code_defval(char* str
)
8410 if (!defval
.ap
|| defval_generated
) return str
;
8411 defval_generated
= true;
8412 switch (defval
.ap
->get_selection()) {
8413 case ActualPar::AP_VALUE
: {
8414 Value
*val
= defval
.ap
->get_Value();
8415 if (use_runtime_2
&& TypeConv::needs_conv_refd(val
)) {
8416 str
= TypeConv::gen_conv_code_refd(str
, val
->get_lhs_name().c_str(), val
);
8418 str
= val
->generate_code_init(str
, val
->get_lhs_name().c_str());
8421 case ActualPar::AP_TEMPLATE
: {
8422 TemplateInstance
*ti
= defval
.ap
->get_TemplateInstance();
8423 Template
*temp
= ti
->get_Template();
8424 Ref_base
*dref
= ti
->get_DerivedRef();
8426 expression_struct expr
;
8427 Code::init_expr(&expr
);
8428 expr
.expr
= mputprintf(expr
.expr
, "%s = ",
8429 temp
->get_lhs_name().c_str());
8430 dref
->generate_code(&expr
);
8431 str
= Code::merge_free_expr(str
, &expr
, false);
8433 if (use_runtime_2
&& TypeConv::needs_conv_refd(temp
)) {
8434 str
= TypeConv::gen_conv_code_refd(str
, temp
->get_lhs_name().c_str(), temp
);
8436 str
= temp
->generate_code_init(str
, temp
->get_lhs_name().c_str());
8438 if (defval
.ap
->get_gen_restriction_check() != TR_NONE
) {
8439 str
= Template::generate_restriction_check_code(str
,
8440 temp
->get_lhs_name().c_str(), defval
.ap
->get_gen_restriction_check());
8443 case ActualPar::AP_REF
:
8446 FATAL_ERROR("FormalPar::generate_code()");
8451 void FormalPar::generate_code_defval(output_struct
*target
, bool)
8453 if (!defval
.ap
) return;
8454 switch (defval
.ap
->get_selection()) {
8455 case ActualPar::AP_VALUE
: {
8456 Value
*val
= defval
.ap
->get_Value();
8458 Code::init_cdef(&cdef
);
8459 type
->generate_code_object(&cdef
, val
);
8460 Code::merge_cdef(target
, &cdef
);
8461 Code::free_cdef(&cdef
);
8463 case ActualPar::AP_TEMPLATE
: {
8464 TemplateInstance
*ti
= defval
.ap
->get_TemplateInstance();
8465 Template
*temp
= ti
->get_Template();
8467 Code::init_cdef(&cdef
);
8468 type
->generate_code_object(&cdef
, temp
);
8469 Code::merge_cdef(target
, &cdef
);
8470 Code::free_cdef(&cdef
);
8472 case ActualPar::AP_REF
:
8475 FATAL_ERROR("FormalPar::generate_code()");
8477 target
->functions
.post_init
= generate_code_defval(target
->functions
.post_init
);
8480 char *FormalPar::generate_code_fpar(char *str
, bool display_unused
/* = false */)
8482 // the name of the parameter should not be displayed if the parameter is not
8483 // used (to avoid a compiler warning)
8484 bool display_name
= (usage_found
|| display_unused
|| debugger_active
||
8485 (!enable_set_bound_out_param
&& (asstype
== A_PAR_VAL_OUT
|| asstype
== A_PAR_TEMPL_OUT
)));
8486 const char *name_str
= display_name
? id
->get_name().c_str() : "";
8490 str
= mputprintf(str
, "Lazy_Param<%s>& %s", type
->get_genname_value(my_scope
).c_str(), name_str
);
8492 str
= mputprintf(str
, "const %s& %s", type
->get_genname_value(my_scope
).c_str(), name_str
);
8496 case A_PAR_VAL_INOUT
:
8498 str
= mputprintf(str
, "%s& %s", type
->get_genname_value(my_scope
).c_str(),
8501 case A_PAR_TEMPL_IN
:
8503 str
= mputprintf(str
, "Lazy_Param<%s>& %s", type
->get_genname_template(my_scope
).c_str(), name_str
);
8505 str
= mputprintf(str
, "const %s& %s", type
->get_genname_template(my_scope
).c_str(), name_str
);
8508 case A_PAR_TEMPL_OUT
:
8509 case A_PAR_TEMPL_INOUT
:
8510 str
= mputprintf(str
, "%s& %s",
8511 type
->get_genname_template(my_scope
).c_str(), name_str
);
8514 str
= mputprintf(str
, "TIMER& %s", name_str
);
8517 FATAL_ERROR("FormalPar::generate_code()");
8522 string
FormalPar::get_reference_name(Scope
* scope
) const
8528 case A_PAR_TEMPL_IN
:
8529 ret_val
+= type
->get_genname_template(scope
);
8532 ret_val
+= type
->get_genname_value(scope
);
8537 ret_val
+= get_id().get_name();
8544 char *FormalPar::generate_code_object(char *str
, const char *p_prefix
, char refch
)
8546 const char *name_str
= id
->get_name().c_str();
8550 str
= mputprintf(str
, "Lazy_Param<%s> %s%s;\n", type
->get_genname_value(my_scope
).c_str(), p_prefix
, name_str
);
8552 str
= mputprintf(str
, "%s %s%s;\n", type
->get_genname_value(my_scope
).c_str(), p_prefix
, name_str
);
8556 case A_PAR_VAL_INOUT
:
8558 str
= mputprintf(str
, "%s%c %s%s;\n",
8559 type
->get_genname_value(my_scope
).c_str(), refch
, p_prefix
, name_str
);
8561 case A_PAR_TEMPL_IN
:
8563 str
= mputprintf(str
, "Lazy_Param<%s> %s%s;\n", type
->get_genname_template(my_scope
).c_str(), p_prefix
, name_str
);
8565 str
= mputprintf(str
, "%s %s%s;\n", type
->get_genname_template(my_scope
).c_str(), p_prefix
, name_str
);
8568 case A_PAR_TEMPL_OUT
:
8569 case A_PAR_TEMPL_INOUT
:
8570 str
= mputprintf(str
, "%s%c %s%s;\n",
8571 type
->get_genname_template(my_scope
).c_str(), refch
, p_prefix
, name_str
);
8574 str
= mputprintf(str
, "TIMER& %s%s;\n", p_prefix
, name_str
);
8577 FATAL_ERROR("FormalPar::generate_code_object()");
8582 char *FormalPar::generate_shadow_object(char *str
) const
8584 if (used_as_lvalue
&& !lazy_eval
) {
8585 const string
& t_genname
= get_genname();
8586 const char *genname_str
= t_genname
.c_str();
8587 const char *name_str
= id
->get_name().c_str();
8590 str
= mputprintf(str
, "%s %s(%s);\n",
8591 type
->get_genname_value(my_scope
).c_str(), genname_str
, name_str
);
8593 case A_PAR_TEMPL_IN
:
8594 str
= mputprintf(str
, "%s %s(%s);\n",
8595 type
->get_genname_template(my_scope
).c_str(), genname_str
, name_str
);
8598 FATAL_ERROR("FormalPar::generate_shadow_object()");
8604 char *FormalPar::generate_code_set_unbound(char *str
) const
8607 case A_PAR_TEMPL_OUT
:
8609 str
= mputprintf(str
, "%s.clean_up();\n", id
->get_name().c_str());
8617 void FormalPar::dump_internal(unsigned level
) const
8619 DEBUG(level
, "%s: %s", get_assname(), id
->get_dispname().c_str());
8620 if (type
) type
->dump(level
+ 1);
8623 DEBUG(level
+ 1, "default value:");
8624 defval
.ap
->dump(level
+ 2);
8628 DEBUG(level
+ 1, "default value:");
8629 defval
.ti
->dump(level
+ 2);
8634 // =================================
8635 // ===== FormalParList
8636 // =================================
8638 FormalParList::~FormalParList()
8640 size_t nof_pars
= pars_v
.size();
8641 for (size_t i
= 0; i
< nof_pars
; i
++) delete pars_v
[i
];
8646 FormalParList
*FormalParList::clone() const
8648 FATAL_ERROR("FormalParList::clone");
8651 void FormalParList::set_fullname(const string
& p_fullname
)
8653 Node::set_fullname(p_fullname
);
8654 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8655 FormalPar
*par
= pars_v
[i
];
8656 par
->set_fullname(p_fullname
+ "." + par
->get_id().get_dispname());
8660 void FormalParList::set_my_scope(Scope
*p_scope
)
8662 set_parent_scope(p_scope
);
8663 Node::set_my_scope(p_scope
);
8664 // the scope of parameters is set to the parent scope instead of this
8665 // because they cannot refer to each other
8666 for (size_t i
= 0; i
< pars_v
.size(); i
++) pars_v
[i
]->set_my_scope(p_scope
);
8669 void FormalParList::add_fp(FormalPar
*p_fp
)
8671 if (!p_fp
) FATAL_ERROR("NULL parameter: Ttcn::FormalParList::add_fp()");
8673 p_fp
->set_my_parlist(this);
8677 bool FormalParList::has_notused_defval() const
8679 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8680 if (pars_v
[i
]->has_notused_defval())
8686 bool FormalParList::has_only_default_values() const
8688 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8689 if (!pars_v
[i
]->has_defval()) {
8697 bool FormalParList::has_fp_withName(const Identifier
& p_name
)
8699 if (!checked
) chk(Definition::A_UNDEF
);
8700 return pars_m
.has_key(p_name
.get_name());
8703 FormalPar
*FormalParList::get_fp_byName(const Identifier
& p_name
)
8705 if (!checked
) chk(Definition::A_UNDEF
);
8706 return pars_m
[p_name
.get_name()];
8709 bool FormalParList::get_startability()
8711 if(!checked
) FATAL_ERROR("FormalParList::get_startability()");
8712 return is_startable
;
8715 Common::Assignment
*FormalParList::get_ass_bySRef(Common::Ref_simple
*p_ref
)
8717 if (!p_ref
|| !checked
) FATAL_ERROR("FormalParList::get_ass_bySRef()");
8718 if (p_ref
->get_modid()) return parent_scope
->get_ass_bySRef(p_ref
);
8720 const string
& name
= p_ref
->get_id()->get_name();
8721 if (pars_m
.has_key(name
)) return pars_m
[name
];
8722 else return parent_scope
->get_ass_bySRef(p_ref
);
8726 bool FormalParList::has_ass_withId(const Identifier
& p_id
)
8728 if (!checked
) FATAL_ERROR("Ttcn::FormalParList::has_ass_withId()");
8729 return pars_m
.has_key(p_id
.get_name())
8730 || parent_scope
->has_ass_withId(p_id
);
8733 void FormalParList::set_genname(const string
& p_prefix
)
8735 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8736 FormalPar
*par
= pars_v
[i
];
8737 const string
& par_name
= par
->get_id().get_name();
8738 if (par
->get_asstype() != Definition::A_PAR_TIMER
)
8739 par
->get_Type()->set_genname(p_prefix
, par_name
);
8740 if (par
->has_defval()) {
8741 string
embedded_genname(p_prefix
);
8742 embedded_genname
+= '_';
8743 embedded_genname
+= par_name
;
8744 embedded_genname
+= "_defval";
8745 ActualPar
*defval
= par
->get_defval();
8746 switch (defval
->get_selection()) {
8747 case ActualPar::AP_ERROR
:
8748 case ActualPar::AP_REF
:
8750 case ActualPar::AP_VALUE
: {
8751 Value
*v
= defval
->get_Value();
8752 v
->set_genname_prefix("const_");
8753 v
->set_genname_recursive(embedded_genname
);
8755 case ActualPar::AP_TEMPLATE
: {
8756 Template
*t
= defval
->get_TemplateInstance()->get_Template();
8757 t
->set_genname_prefix("template_");
8758 t
->set_genname_recursive(embedded_genname
);
8761 FATAL_ERROR("FormalParList::set_genname()");
8767 void FormalParList::chk(Definition::asstype_t deftype
)
8769 if (checked
) return;
8772 is_startable
= true;
8773 Error_Context
cntxt(this, "In formal parameter list");
8774 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8775 FormalPar
*par
= pars_v
[i
];
8776 const Identifier
& id
= par
->get_id();
8777 const string
& name
= id
.get_name();
8778 const char *dispname
= id
.get_dispname().c_str();
8779 if (pars_m
.has_key(name
)) {
8780 par
->error("Duplicate parameter with name `%s'", dispname
);
8781 pars_m
[name
]->note("Previous definition of `%s' is here", dispname
);
8783 pars_m
.add(name
, par
);
8784 if (parent_scope
&& parent_scope
->has_ass_withId(id
)) {
8785 par
->error("Parameter name `%s' is not unique in the scope "
8786 "hierarchy", dispname
);
8787 Reference
ref(0, id
.clone());
8788 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
8789 if (!ass
) FATAL_ERROR("FormalParList::chk()");
8790 ass
->note("Symbol `%s' is already defined here in a higher scope "
8794 Error_Context
cntxt2(par
, "In parameter `%s'", dispname
);
8796 // check whether the parameter type is allowed
8798 case Definition::A_TEMPLATE
:
8799 switch (par
->get_asstype()) {
8800 case Definition::A_PAR_VAL_IN
:
8801 case Definition::A_PAR_TEMPL_IN
:
8802 // these are allowed
8805 par
->error("A template cannot have %s", par
->get_assname());
8808 case Definition::A_TESTCASE
:
8809 switch (par
->get_asstype()) {
8810 case Definition::A_PAR_TIMER
:
8811 case Definition::A_PAR_PORT
:
8812 // these are forbidden
8813 par
->error("A testcase cannot have %s", par
->get_assname());
8818 // everything is allowed for functions and altsteps
8822 switch(par
->get_asstype()) {
8823 case Common::Assignment::A_PAR_VAL_IN
:
8824 case Common::Assignment::A_PAR_TEMPL_IN
:
8825 case Common::Assignment::A_PAR_VAL_INOUT
:
8826 case Common::Assignment::A_PAR_TEMPL_INOUT
:
8827 if (is_startable
&& par
->get_Type()->is_component_internal())
8828 is_startable
= false;
8831 is_startable
= false;
8834 if (!par
->has_defval()) min_nof_pars
= i
+ 1;
8835 // the last parameter without a default value determines the minimum
8839 // check that @lazy paramterization not used in cases currently unsupported
8840 void FormalParList::chk_noLazyParams() {
8841 Error_Context
cntxt(this, "In formal parameter list");
8842 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8843 FormalPar
*par
= pars_v
[i
];
8844 if (par
->get_lazy_eval()) {
8845 par
->error("Formal parameter `%s' cannot be @lazy, not supported in this case.",
8846 par
->get_id().get_dispname().c_str());
8851 void FormalParList::chk_startability(const char *p_what
, const char *p_name
)
8853 if(!checked
) FATAL_ERROR("FormalParList::chk_startability()");
8854 if (is_startable
) return;
8855 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8856 FormalPar
*par
= pars_v
[i
];
8857 switch (par
->get_asstype()) {
8858 case Common::Assignment::A_PAR_VAL_IN
:
8859 case Common::Assignment::A_PAR_TEMPL_IN
:
8860 case Common::Assignment::A_PAR_VAL_INOUT
:
8861 case Common::Assignment::A_PAR_TEMPL_INOUT
:
8862 if (par
->get_Type()->is_component_internal()) {
8863 map
<Type
*,void> type_chain
;
8864 char* err_str
= mprintf("a parameter or embedded in a parameter of "
8865 "a function used in a start operation. "
8866 "%s `%s' cannot be started on a parallel test component "
8867 "because of `%s'", p_what
, p_name
, par
->get_description().c_str());
8868 par
->get_Type()->chk_component_internal(type_chain
, err_str
);
8873 par
->error("%s `%s' cannot be started on a parallel test component "
8874 "because it has %s", p_what
, p_name
, par
->get_description().c_str());
8879 void FormalParList::chk_compatibility(FormalParList
* p_fp_list
,
8882 size_t nof_type_pars
= pars_v
.size();
8883 size_t nof_function_pars
= p_fp_list
->pars_v
.size();
8884 // check for the number of parameters
8885 if (nof_type_pars
!= nof_function_pars
) {
8886 p_fp_list
->error("Too %s parameters: %lu was expected instead of %lu",
8887 nof_type_pars
< nof_function_pars
? "many" : "few",
8888 (unsigned long) nof_type_pars
, (unsigned long) nof_function_pars
);
8890 size_t upper_limit
=
8891 nof_type_pars
< nof_function_pars
? nof_type_pars
: nof_function_pars
;
8892 for (size_t i
= 0; i
< upper_limit
; i
++) {
8893 FormalPar
*type_par
= pars_v
[i
];
8894 FormalPar
*function_par
= p_fp_list
->pars_v
[i
];
8895 Error_Context
cntxt(function_par
, "In parameter #%lu",
8896 (unsigned long) (i
+ 1));
8897 FormalPar::asstype_t type_par_asstype
= type_par
->get_asstype();
8898 FormalPar::asstype_t function_par_asstype
= function_par
->get_asstype();
8899 // check for parameter kind equivalence
8900 // (in, out or inout / value or template)
8901 if (type_par_asstype
!= function_par_asstype
) {
8902 function_par
->error("The kind of the parameter is not the same as in "
8903 "type `%s': %s was expected instead of %s", where
,
8904 type_par
->get_assname(), function_par
->get_assname());
8906 // check for type equivalence
8907 if (type_par_asstype
!= FormalPar::A_PAR_TIMER
&&
8908 function_par_asstype
!= FormalPar::A_PAR_TIMER
) {
8909 Type
*type_par_type
= type_par
->get_Type();
8910 Type
*function_par_type
= function_par
->get_Type();
8911 if (!type_par_type
->is_identical(function_par_type
)) {
8912 function_par_type
->error("The type of the parameter is not the same "
8913 "as in type `%s': `%s' was expected instead of `%s'", where
,
8914 type_par_type
->get_typename().c_str(),
8915 function_par_type
->get_typename().c_str());
8916 } else if (type_par_type
->get_sub_type() && function_par_type
->get_sub_type() &&
8917 (type_par_type
->get_sub_type()->get_subtypetype()==function_par_type
->get_sub_type()->get_subtypetype()) &&
8918 (!type_par_type
->get_sub_type()->is_compatible(function_par_type
->get_sub_type()))) {
8919 // TODO: maybe equivalence should be checked, or maybe that is too strict
8920 function_par_type
->error(
8921 "Subtype mismatch: subtype %s has no common value with subtype %s",
8922 type_par_type
->get_sub_type()->to_string().c_str(),
8923 function_par_type
->get_sub_type()->to_string().c_str());
8926 // check for template restriction equivalence
8927 if (type_par
->get_template_restriction()!=
8928 function_par
->get_template_restriction()) {
8929 function_par
->error("The template restriction of the parameter is "
8930 "not the same as in type `%s': %s restriction was expected instead "
8931 "of %s restriction", where
,
8932 type_par
->get_template_restriction()==TR_NONE
? "no" :
8933 Template::get_restriction_name(type_par
->get_template_restriction()),
8934 function_par
->get_template_restriction()==TR_NONE
? "no" :
8935 Template::get_restriction_name(function_par
->
8936 get_template_restriction()));
8938 // check for @lazy equivalence
8939 if (type_par
->get_lazy_eval()!=function_par
->get_lazy_eval()) {
8940 function_par
->error("Parameter @lazy-ness mismatch");
8942 // check for name equivalence
8943 const Identifier
& type_par_id
= type_par
->get_id();
8944 const Identifier
& function_par_id
= function_par
->get_id();
8945 if (type_par_id
!= function_par_id
) {
8946 function_par
->warning("The name of the parameter is not the same "
8947 "as in type `%s': `%s' was expected instead of `%s'", where
,
8948 type_par_id
.get_dispname().c_str(),
8949 function_par_id
.get_dispname().c_str());
8954 bool FormalParList::fold_named_and_chk(ParsedActualParameters
*p_paps
,
8955 ActualParList
*p_aplist
)
8957 const size_t num_named
= p_paps
->get_nof_nps();
8958 const size_t num_unnamed
= p_paps
->get_nof_tis();
8959 size_t num_actual
= num_unnamed
;
8961 // Construct a map to tell us what index a FormalPar has
8962 typedef map
<FormalPar
*, size_t> formalpar_map_t
;
8963 formalpar_map_t formalpar_map
;
8965 size_t num_fp
= get_nof_fps();
8966 for (size_t fpx
= 0; fpx
< num_fp
; ++fpx
) {
8967 FormalPar
*fp
= get_fp_byIndex(fpx
);
8968 formalpar_map
.add(fp
, new size_t(fpx
));
8971 // Go through the named parameters
8972 for (size_t i
= 0; i
< num_named
; ++i
) {
8973 NamedParam
*np
= p_paps
->extract_np_byIndex(i
);
8974 // We are now responsible for np.
8976 if (has_fp_withName(*np
->get_name())) {
8977 // there is a formal parameter with that name
8978 FormalPar
*fp
= get_fp_byName(*np
->get_name());
8979 const size_t is_at
= *formalpar_map
[fp
]; // the index of the formal par
8980 if (is_at
>= num_actual
) {
8981 // There is no actual par in the unnamed part.
8982 // Create one from the named param.
8984 // First, pad the gap with '-'
8985 for (; num_actual
< is_at
; ++num_actual
) {
8987 if (pars_v
[num_actual
]->has_defval()) {
8988 not_used
= new Template(Template::TEMPLATE_NOTUSED
);
8990 else { // cannot use '-' if no default value
8991 not_used
= new Template(Template::TEMPLATE_ERROR
);
8993 TemplateInstance
*new_ti
= new TemplateInstance(0, 0, not_used
);
8994 // Conjure a location info at the beginning of the unnamed part
8995 // (that is, the beginning of the actual parameter list)
8996 new_ti
->set_location(p_paps
->get_tis()->get_filename(),
8997 p_paps
->get_tis()->get_first_line(),
8998 p_paps
->get_tis()->get_first_column(), 0, 0);
8999 p_paps
->get_tis()->add_ti(new_ti
);
9001 TemplateInstance
* namedti
= np
->extract_ti();
9002 p_paps
->get_tis()->add_ti(namedti
);
9005 // There is already an actual par at that position, fetch it
9006 TemplateInstance
* ti
= p_paps
->get_tis()->get_ti_byIndex(is_at
);
9007 Template::templatetype_t tt
= ti
->get_Template()->get_templatetype();
9009 if (is_at
>= num_unnamed
&& !ti
->get_Type() && !ti
->get_DerivedRef()
9010 && (tt
== Template::TEMPLATE_NOTUSED
|| tt
== Template::TEMPLATE_ERROR
)) {
9011 // NotUsed in the named part => padding
9012 np
->error("Named parameter `%s' out of order",
9013 np
->get_name()->get_dispname().c_str());
9015 // attempt to override an original unnamed param with a named one
9016 np
->error("Formal parameter `%s' assigned more than once",
9017 np
->get_name()->get_dispname().c_str());
9021 else { // no formal parameter with that name
9023 switch (my_def
->get_asstype()) {
9024 case Common::Assignment::A_TYPE
: {
9025 Type
*t
= my_def
->get_Type();
9027 switch (t
? t
->get_typetype() : 0) {
9028 case Type::T_FUNCTION
:
9029 nam
= mcopystr("Function reference");
9031 case Type::T_ALTSTEP
:
9032 nam
= mcopystr("Altstep reference");
9034 case Type::T_TESTCASE
:
9035 nam
= mcopystr("Testcase reference");
9038 FATAL_ERROR("FormalParList::chk_actual_parlist() "
9039 "Unexpected type %s", t
->get_typename().c_str());
9040 } // switch(typetype)
9043 nam
= mcopystr(my_def
->get_assname());
9045 } // switch(asstype)
9047 *nam
&= ~('a'-'A'); // Make the first letter uppercase
9048 p_paps
->get_tis()->error("%s `%s' has no formal parameter `%s'",
9050 my_def
->get_fullname().c_str(),
9051 np
->get_name()->get_dispname().c_str());
9058 for (size_t fpx
= 0; fpx
< num_fp
; ++fpx
) {
9059 delete formalpar_map
.get_nth_elem(fpx
);
9061 formalpar_map
.clear();
9063 return chk_actual_parlist(p_paps
->get_tis(), p_aplist
);
9066 bool FormalParList::chk_actual_parlist(TemplateInstances
*p_tis
,
9067 ActualParList
*p_aplist
)
9069 size_t formal_pars
= pars_v
.size();
9070 size_t actual_pars
= p_tis
->get_nof_tis();
9071 // p_aplist->get_nof_pars() is usually 0 on entry
9072 bool error_flag
= false;
9074 if (min_nof_pars
== formal_pars
) {
9075 // none of the parameters have default value
9076 if (actual_pars
!= formal_pars
) {
9077 p_tis
->error("Too %s parameters: %lu was expected "
9078 "instead of %lu", actual_pars
< formal_pars
? "few" : "many",
9079 (unsigned long) formal_pars
, (unsigned long) actual_pars
);
9083 // some parameters have default value
9084 if (actual_pars
< min_nof_pars
) {
9085 p_tis
->error("Too few parameters: at least %lu "
9086 "was expected instead of %lu",
9087 (unsigned long) min_nof_pars
, (unsigned long) actual_pars
);
9089 } else if (actual_pars
> formal_pars
) {
9090 p_tis
->error("Too many parameters: at most %lu "
9091 "was expected instead of %lu",
9092 (unsigned long) formal_pars
, (unsigned long) actual_pars
);
9097 // Do not check actual parameters in excess of the formal ones
9098 size_t upper_limit
= actual_pars
< formal_pars
? actual_pars
: formal_pars
;
9099 for (size_t i
= 0; i
< upper_limit
; i
++) {
9100 TemplateInstance
*ti
= p_tis
->get_ti_byIndex(i
);
9102 // the formal parameter for the current actual parameter
9103 FormalPar
*fp
= pars_v
[i
];
9104 Error_Context
cntxt(ti
, "In parameter #%lu for `%s'",
9105 (unsigned long) (i
+ 1), fp
->get_id().get_dispname().c_str());
9106 if (!ti
->get_Type() && !ti
->get_DerivedRef() && ti
->get_Template()
9107 ->get_templatetype() == Template::TEMPLATE_NOTUSED
) {
9108 if (fp
->has_defval()) {
9109 ActualPar
*defval
= fp
->get_defval();
9110 p_aplist
->add(new ActualPar(defval
));
9111 if (defval
->is_erroneous()) error_flag
= true;
9113 ti
->error("Not used symbol (`-') cannot be used for parameter "
9114 "that does not have default value");
9115 p_aplist
->add(new ActualPar());
9118 } else if (!ti
->get_Type() && !ti
->get_DerivedRef() && ti
->get_Template()
9119 ->get_templatetype() == Template::TEMPLATE_ERROR
) {
9120 ti
->error("Parameter not specified");
9122 ActualPar
*ap
= fp
->chk_actual_par(ti
, Type::EXPECTED_DYNAMIC_VALUE
);
9124 if (ap
->is_erroneous()) error_flag
= true;
9128 // The rest of formal parameters have no corresponding actual parameters.
9129 // Create actual parameters for them based on their default values
9130 // (which must exist).
9131 for (size_t i
= upper_limit
; i
< formal_pars
; i
++) {
9132 FormalPar
*fp
= pars_v
[i
];
9133 if (fp
->has_defval()) {
9134 ActualPar
*defval
= fp
->get_defval();
9135 p_aplist
->add(new ActualPar(defval
));
9136 if (defval
->is_erroneous()) error_flag
= true;
9138 p_aplist
->add(new ActualPar()); // erroneous
9145 bool FormalParList::chk_activate_argument(ActualParList
*p_aplist
,
9146 const char* p_description
)
9148 bool ret_val
= true;
9149 for(size_t i
= 0; i
< p_aplist
->get_nof_pars(); i
++) {
9150 ActualPar
*t_ap
= p_aplist
->get_par(i
);
9151 if(t_ap
->get_selection() != ActualPar::AP_REF
) continue;
9152 FormalPar
*t_fp
= pars_v
[i
];
9153 switch(t_fp
->get_asstype()) {
9154 case Common::Assignment::A_PAR_VAL_OUT
:
9155 case Common::Assignment::A_PAR_VAL_INOUT
:
9156 case Common::Assignment::A_PAR_TEMPL_OUT
:
9157 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9158 case Common::Assignment::A_PAR_TIMER
:
9159 //the checking shall be performed for these parameter types
9161 case Common::Assignment::A_PAR_PORT
:
9162 // port parameters are always correct because ports can be defined
9163 // only in component types
9166 FATAL_ERROR("FormalParList::chk_activate_argument()");
9168 Ref_base
*t_ref
= t_ap
->get_Ref();
9169 Common::Assignment
*t_par_ass
= t_ref
->get_refd_assignment();
9170 if(!t_par_ass
) FATAL_ERROR("FormalParList::chk_activate_argument()");
9171 switch (t_par_ass
->get_asstype()) {
9172 case Common::Assignment::A_VAR
:
9173 case Common::Assignment::A_VAR_TEMPLATE
:
9174 case Common::Assignment::A_TIMER
:
9175 // it is not allowed to pass references of local variables or timers
9176 if (t_par_ass
->is_local()) {
9177 t_ref
->error("Parameter #%lu of %s refers to %s, which is a local "
9178 "definition within a statement block and may have shorter "
9179 "lifespan than the activated default. Only references to "
9180 "variables and timers defined in the component type can be passed "
9181 "to activated defaults", (unsigned long) (i
+ 1), p_description
,
9182 t_par_ass
->get_description().c_str());
9186 case Common::Assignment::A_PAR_VAL_IN
:
9187 case Common::Assignment::A_PAR_VAL_OUT
:
9188 case Common::Assignment::A_PAR_VAL_INOUT
:
9189 case Common::Assignment::A_PAR_TEMPL_IN
:
9190 case Common::Assignment::A_PAR_TEMPL_OUT
:
9191 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9192 case Common::Assignment::A_PAR_TIMER
: {
9193 // it is not allowed to pass references pointing to formal parameters
9194 // except for activate() statements within testcases
9195 // note: all defaults are deactivated at the end of the testcase
9196 FormalPar
*t_refd_fp
= dynamic_cast<FormalPar
*>(t_par_ass
);
9197 if (!t_refd_fp
) FATAL_ERROR("FormalParList::chk_activate_argument()");
9198 FormalParList
*t_fpl
= t_refd_fp
->get_my_parlist();
9199 if (!t_fpl
|| !t_fpl
->my_def
)
9200 FATAL_ERROR("FormalParList::chk_activate_argument()");
9201 if (t_fpl
->my_def
->get_asstype() != Common::Assignment::A_TESTCASE
) {
9202 t_ref
->error("Parameter #%lu of %s refers to %s, which may have "
9203 "shorter lifespan than the activated default. Only references to "
9204 "variables and timers defined in the component type can be passed "
9205 "to activated defaults", (unsigned long) (i
+ 1), p_description
,
9206 t_par_ass
->get_description().c_str());
9216 char *FormalParList::generate_code(char *str
, size_t display_unused
/* = 0 */)
9218 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9219 if (i
> 0) str
= mputstr(str
, ", ");
9220 str
= pars_v
[i
]->generate_code_fpar(str
, i
< display_unused
);
9225 char* FormalParList::generate_code_defval(char* str
)
9227 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9228 str
= pars_v
[i
]->generate_code_defval(str
);
9233 void FormalParList::generate_code_defval(output_struct
*target
)
9235 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9236 pars_v
[i
]->generate_code_defval(target
);
9240 char *FormalParList::generate_code_actual_parlist(char *str
,
9241 const char *p_prefix
)
9243 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9244 if (i
> 0) str
= mputstr(str
, ", ");
9245 str
= mputstr(str
, p_prefix
);
9246 str
= mputstr(str
, pars_v
[i
]->get_id().get_name().c_str());
9251 char *FormalParList::generate_code_object(char *str
, const char *p_prefix
, char refch
)
9253 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9254 str
= pars_v
[i
]->generate_code_object(str
, p_prefix
, refch
);
9258 char *FormalParList::generate_shadow_objects(char *str
) const
9260 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9261 str
= pars_v
[i
]->generate_shadow_object(str
);
9265 char *FormalParList::generate_code_set_unbound(char *str
) const
9267 if (enable_set_bound_out_param
) return str
;
9268 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9269 str
= pars_v
[i
]->generate_code_set_unbound(str
);
9274 void FormalParList::dump(unsigned level
) const
9276 size_t nof_pars
= pars_v
.size();
9277 DEBUG(level
, "formal parameters: %lu pcs.", (unsigned long) nof_pars
);
9278 for(size_t i
= 0; i
< nof_pars
; i
++) pars_v
[i
]->dump(level
+ 1);
9281 // =================================
9283 // =================================
9285 ActualPar::ActualPar(Value
*v
)
9286 : Node(), selection(AP_VALUE
), my_scope(0), gen_restriction_check(TR_NONE
),
9287 gen_post_restriction_check(TR_NONE
)
9289 if (!v
) FATAL_ERROR("ActualPar::ActualPar()");
9293 ActualPar::ActualPar(TemplateInstance
*t
)
9294 : Node(), selection(AP_TEMPLATE
), my_scope(0),
9295 gen_restriction_check(TR_NONE
), gen_post_restriction_check(TR_NONE
)
9297 if (!t
) FATAL_ERROR("ActualPar::ActualPar()");
9301 ActualPar::ActualPar(Ref_base
*r
)
9302 : Node(), selection(AP_REF
), my_scope(0), gen_restriction_check(TR_NONE
),
9303 gen_post_restriction_check(TR_NONE
)
9305 if (!r
) FATAL_ERROR("ActualPar::ActualPar()");
9309 ActualPar::ActualPar(ActualPar
*a
)
9310 : Node(), selection(AP_DEFAULT
), my_scope(0),
9311 gen_restriction_check(TR_NONE
), gen_post_restriction_check(TR_NONE
)
9313 if (!a
) FATAL_ERROR("ActualPar::ActualPar()");
9317 ActualPar::~ActualPar()
9332 break; // nothing to do with act
9334 FATAL_ERROR("ActualPar::~ActualPar()");
9338 ActualPar
*ActualPar::clone() const
9340 FATAL_ERROR("ActualPar::clone");
9343 void ActualPar::set_fullname(const string
& p_fullname
)
9345 Node::set_fullname(p_fullname
);
9350 val
->set_fullname(p_fullname
);
9353 temp
->set_fullname(p_fullname
);
9356 ref
->set_fullname(p_fullname
);
9361 FATAL_ERROR("ActualPar::set_fullname()");
9365 void ActualPar::set_my_scope(Scope
*p_scope
)
9372 val
->set_my_scope(p_scope
);
9375 temp
->set_my_scope(p_scope
);
9378 ref
->set_my_scope(p_scope
);
9381 switch (act
->selection
) {
9383 ref
->set_my_scope(p_scope
);
9390 FATAL_ERROR("ActualPar::set_my_scope()");
9394 FATAL_ERROR("ActualPar::set_my_scope()");
9398 Value
*ActualPar::get_Value() const
9400 if (selection
!= AP_VALUE
) FATAL_ERROR("ActualPar::get_Value()");
9404 TemplateInstance
*ActualPar::get_TemplateInstance() const
9406 if (selection
!= AP_TEMPLATE
)
9407 FATAL_ERROR("ActualPar::get_TemplateInstance()");
9411 Ref_base
*ActualPar::get_Ref() const
9413 if (selection
!= AP_REF
) FATAL_ERROR("ActualPar::get_Ref()");
9417 ActualPar
*ActualPar::get_ActualPar() const
9419 if (selection
!= AP_DEFAULT
) FATAL_ERROR("ActualPar::get_ActualPar()");
9423 void ActualPar::chk_recursions(ReferenceChain
& refch
)
9425 switch (selection
) {
9428 val
->chk_recursions(refch
);
9432 Ref_base
*derived_ref
= temp
->get_DerivedRef();
9434 ActualParList
*parlist
= derived_ref
->get_parlist();
9437 parlist
->chk_recursions(refch
);
9442 Ttcn::Def_Template
* defTemp
= temp
->get_Referenced_Base_Template();
9445 refch
.add(defTemp
->get_fullname());
9449 temp
->get_Template()->chk_recursions(refch
);
9457 bool ActualPar::has_single_expr()
9459 switch (selection
) {
9461 return val
->has_single_expr();
9463 if (gen_restriction_check
!=TR_NONE
||
9464 gen_post_restriction_check
!=TR_NONE
) return false;
9465 return temp
->has_single_expr();
9467 if (gen_restriction_check
!=TR_NONE
||
9468 gen_post_restriction_check
!=TR_NONE
) return false;
9469 if (use_runtime_2
&& ref
->get_subrefs() != NULL
) {
9470 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
9471 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
9472 if (FieldOrArrayRef::ARRAY_REF
== subrefs
->get_ref(i
)->get_type()) {
9477 return ref
->has_single_expr();
9481 FATAL_ERROR("ActualPar::has_single_expr()");
9486 void ActualPar::set_code_section(
9487 GovernedSimple::code_section_t p_code_section
)
9489 switch (selection
) {
9491 val
->set_code_section(p_code_section
);
9494 temp
->set_code_section(p_code_section
);
9497 ref
->set_code_section(p_code_section
);
9503 void ActualPar::generate_code(expression_struct
*expr
, bool copy_needed
, bool lazy_param
, bool used_as_lvalue
) const
9505 switch (selection
) {
9507 if (lazy_param
) { // copy_needed doesn't matter in this case
9508 LazyParamData::init(used_as_lvalue
);
9509 LazyParamData::generate_code(expr
, val
, my_scope
);
9510 LazyParamData::clean();
9511 if (val
->get_valuetype() == Value::V_REFD
) {
9512 // check if the reference is a parameter, mark it as used if it is
9513 Reference
* ref
= dynamic_cast<Reference
*>(val
->get_reference());
9515 ref
->refd_param_usage_found();
9519 if (copy_needed
) expr
->expr
= mputprintf(expr
->expr
, "%s(",
9520 val
->get_my_governor()->get_genname_value(my_scope
).c_str());
9521 if (use_runtime_2
&& TypeConv::needs_conv_refd(val
)) {
9522 // Generate everything to preamble to be able to tackle the wrapper
9523 // constructor call. TODO: Reduce the number of temporaries created.
9524 const string
& tmp_id
= val
->get_temporary_id();
9525 const char *tmp_id_str
= tmp_id
.c_str();
9526 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
9527 val
->get_my_governor()->get_genname_value(my_scope
).c_str(),
9529 expr
->preamble
= TypeConv::gen_conv_code_refd(expr
->preamble
,
9531 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
9532 } else val
->generate_code_expr(expr
);
9533 if (copy_needed
) expr
->expr
= mputc(expr
->expr
, ')');
9537 if (lazy_param
) { // copy_needed doesn't matter in this case
9538 LazyParamData::init(used_as_lvalue
);
9539 LazyParamData::generate_code(expr
, temp
, gen_restriction_check
, my_scope
);
9540 LazyParamData::clean();
9541 if (temp
->get_DerivedRef() != NULL
||
9542 temp
->get_Template()->get_templatetype() == Template::TEMPLATE_REFD
) {
9543 // check if the reference is a parameter, mark it as used if it is
9544 Reference
* ref
= dynamic_cast<Reference
*>(temp
->get_DerivedRef() != NULL
?
9545 temp
->get_DerivedRef() : temp
->get_Template()->get_reference());
9547 ref
->refd_param_usage_found();
9552 expr
->expr
= mputprintf(expr
->expr
, "%s(", temp
->get_Template()
9553 ->get_my_governor()->get_genname_template(my_scope
).c_str());
9554 if (use_runtime_2
&& TypeConv::needs_conv_refd(temp
->get_Template())) {
9555 const string
& tmp_id
= temp
->get_Template()->get_temporary_id();
9556 const char *tmp_id_str
= tmp_id
.c_str();
9557 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
9558 temp
->get_Template()->get_my_governor()
9559 ->get_genname_template(my_scope
).c_str(), tmp_id_str
);
9560 expr
->preamble
= TypeConv::gen_conv_code_refd(expr
->preamble
,
9561 tmp_id_str
, temp
->get_Template());
9562 // Not incorporated into gen_conv_code() yet.
9563 if (gen_restriction_check
!= TR_NONE
)
9564 expr
->preamble
= Template::generate_restriction_check_code(
9565 expr
->preamble
, tmp_id_str
, gen_restriction_check
);
9566 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
9567 } else temp
->generate_code(expr
, gen_restriction_check
);
9568 if (copy_needed
) expr
->expr
= mputc(expr
->expr
, ')');
9572 if (lazy_param
) FATAL_ERROR("ActualPar::generate_code()"); // syntax error should have already happened
9573 if (copy_needed
) FATAL_ERROR("ActualPar::generate_code()");
9574 if (gen_restriction_check
!= TR_NONE
||
9575 gen_post_restriction_check
!= TR_NONE
) {
9576 // generate runtime check for restricted templates
9577 // code for reference + restriction check
9578 Common::Assignment
*ass
= ref
->get_refd_assignment();
9579 const string
& tmp_id
= my_scope
->get_scope_mod_gen()->get_temporary_id();
9580 const char *tmp_id_str
= tmp_id
.c_str();
9581 expression_struct ref_expr
;
9582 Code::init_expr(&ref_expr
);
9583 ref
->generate_code_const_ref(&ref_expr
);
9584 ref_expr
.preamble
= mputprintf(ref_expr
.preamble
, "%s& %s = %s;\n",
9585 ass
->get_Type()->get_genname_template(ref
->get_my_scope()).c_str(),
9586 tmp_id_str
, ref_expr
.expr
);
9587 if (gen_restriction_check
!= TR_NONE
) {
9588 ref_expr
.preamble
= Template::generate_restriction_check_code(
9589 ref_expr
.preamble
, tmp_id_str
, gen_restriction_check
);
9591 if (gen_post_restriction_check
!= TR_NONE
) {
9592 ref_expr
.postamble
= Template::generate_restriction_check_code(
9593 ref_expr
.postamble
, tmp_id_str
, gen_post_restriction_check
);
9595 // copy content of ref_expr to expr
9596 expr
->preamble
= mputstr(expr
->preamble
, ref_expr
.preamble
);
9597 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_id_str
);
9598 expr
->postamble
= mputstr(expr
->postamble
, ref_expr
.postamble
);
9599 Code::free_expr(&ref_expr
);
9601 ref
->generate_code(expr
);
9605 if (copy_needed
) FATAL_ERROR("ActualPar::generate_code()");
9606 switch (act
->selection
) {
9609 LazyParamData::generate_code_ap_default_ref(expr
, act
->ref
, my_scope
);
9611 act
->ref
->generate_code(expr
);
9616 LazyParamData::generate_code_ap_default_value(expr
, act
->val
, my_scope
);
9618 expr
->expr
= mputstr(expr
->expr
, act
->val
->get_genname_own(my_scope
).c_str());
9623 LazyParamData::generate_code_ap_default_ti(expr
, act
->temp
, my_scope
);
9625 expr
->expr
= mputstr(expr
->expr
, act
->temp
->get_Template()->get_genname_own(my_scope
).c_str());
9629 FATAL_ERROR("ActualPar::generate_code()");
9633 FATAL_ERROR("ActualPar::generate_code()");
9637 char *ActualPar::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
9639 switch (selection
) {
9641 str
= val
->rearrange_init_code(str
);
9644 str
= temp
->rearrange_init_code(str
, usage_mod
);
9648 str
= act
->rearrange_init_code_defval(str
, usage_mod
);
9651 FATAL_ERROR("ActualPar::rearrange_init_code()");
9656 char *ActualPar::rearrange_init_code_defval(char *str
, Common::Module
* usage_mod
)
9658 switch (selection
) {
9660 if (val
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
9661 str
= val
->generate_code_init(str
, val
->get_lhs_name().c_str());
9665 str
= temp
->rearrange_init_code(str
, usage_mod
);
9666 Template
*t
= temp
->get_Template();
9667 if (t
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
9668 Ref_base
*dref
= temp
->get_DerivedRef();
9670 expression_struct expr
;
9671 Code::init_expr(&expr
);
9672 expr
.expr
= mputprintf(expr
.expr
, "%s = ", t
->get_lhs_name().c_str());
9673 dref
->generate_code(&expr
);
9674 str
= Code::merge_free_expr(str
, &expr
, false);
9676 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
9680 FATAL_ERROR("ActualPar::rearrange_init_code_defval()");
9685 void ActualPar::append_stringRepr(string
& str
) const
9687 switch (selection
) {
9689 str
+= val
->get_stringRepr();
9692 temp
->append_stringRepr(str
);
9695 str
+= ref
->get_dispname();
9701 str
+= "<erroneous actual parameter>";
9705 void ActualPar::dump(unsigned level
) const
9707 switch (selection
) {
9709 DEBUG(level
, "actual parameter: value");
9710 val
->dump(level
+ 1);
9713 DEBUG(level
, "actual parameter: template");
9714 temp
->dump(level
+ 1);
9717 DEBUG(level
, "actual parameter: referecne");
9718 ref
->dump(level
+ 1);
9721 DEBUG(level
, "actual parameter: default");
9724 DEBUG(level
, "actual parameter: erroneous");
9728 // =================================
9729 // ===== ActualParList
9730 // =================================
9732 ActualParList::ActualParList(const ActualParList
& p
)
9735 size_t nof_pars
= p
.params
.size();
9736 for (size_t i
= 0; i
< nof_pars
; i
++) params
.add(p
.params
[i
]->clone());
9739 ActualParList::~ActualParList()
9741 size_t nof_pars
= params
.size();
9742 for (size_t i
= 0; i
< nof_pars
; i
++) delete params
[i
];
9746 ActualParList
*ActualParList::clone() const
9748 return new ActualParList(*this);
9751 void ActualParList::set_fullname(const string
& p_fullname
)
9753 Node::set_fullname(p_fullname
);
9754 size_t nof_pars
= params
.size();
9755 for(size_t i
= 0; i
< nof_pars
; i
++)
9756 params
[i
]->set_fullname(p_fullname
+
9757 ".<parameter" + Int2string(i
+ 1) + ">");
9760 void ActualParList::set_my_scope(Scope
*p_scope
)
9762 size_t nof_pars
= params
.size();
9763 for (size_t i
= 0; i
< nof_pars
; i
++) params
[i
]->set_my_scope(p_scope
);
9766 void ActualParList::chk_recursions(ReferenceChain
& refch
)
9768 size_t nof_pars
= params
.size();
9769 for (size_t i
= 0; i
< nof_pars
; i
++)
9770 params
[i
]->chk_recursions(refch
);
9773 void ActualParList::generate_code_noalias(expression_struct
*expr
, FormalParList
*p_fpl
)
9775 size_t nof_pars
= params
.size();
9776 for (size_t i
= 0; i
< nof_pars
; i
++) {
9777 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
9778 params
[i
]->generate_code(expr
, false, p_fpl
&& p_fpl
->get_fp_byIndex(i
)->get_lazy_eval(), p_fpl
&& p_fpl
->get_fp_byIndex(i
)->get_used_as_lvalue());
9782 void ActualParList::generate_code_alias(expression_struct
*expr
,
9783 FormalParList
*p_fpl
, Type
*p_comptype
, bool p_compself
)
9785 size_t nof_pars
= params
.size();
9786 // collect all value and template definitions that are passed by reference
9787 map
<Common::Assignment
*, void> value_refs
, template_refs
;
9788 for (size_t i
= 0; i
< nof_pars
; i
++) {
9789 ActualPar
*par
= params
[i
];
9790 if (par
->get_selection() == ActualPar::AP_DEFAULT
)
9791 par
= par
->get_ActualPar();
9792 if (par
->get_selection() == ActualPar::AP_REF
) {
9793 Common::Assignment
*ass
= par
->get_Ref()->get_refd_assignment();
9794 switch (ass
->get_asstype()) {
9795 case Common::Assignment::A_VAR
:
9796 case Common::Assignment::A_PAR_VAL_IN
:
9797 case Common::Assignment::A_PAR_VAL_OUT
:
9798 case Common::Assignment::A_PAR_VAL_INOUT
:
9799 if (!value_refs
.has_key(ass
)) value_refs
.add(ass
, 0);
9801 case Common::Assignment::A_VAR_TEMPLATE
:
9802 case Common::Assignment::A_PAR_TEMPL_IN
:
9803 case Common::Assignment::A_PAR_TEMPL_OUT
:
9804 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9805 if (!template_refs
.has_key(ass
)) template_refs
.add(ass
, 0);
9811 // walk through the parameter list and generate the code
9812 // add an extra copy constructor call to the referenced value and template
9813 // parameters if the referred definition is also passed by reference to
9814 // another parameter
9815 for (size_t i
= 0; i
< nof_pars
; i
++) {
9816 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
9817 ActualPar
*par
= params
[i
];
9818 bool copy_needed
= false;
9819 // the copy constructor call is not needed if the parameter is copied
9820 // into a shadow object in the body of the called function
9821 if (!p_fpl
|| !p_fpl
->get_fp_byIndex(i
)->get_used_as_lvalue()) {
9822 switch (par
->get_selection()) {
9823 case ActualPar::AP_VALUE
: {
9824 Value
*v
= par
->get_Value();
9825 if (v
->get_valuetype() == Value::V_REFD
) {
9826 Common::Assignment
*t_ass
=
9827 v
->get_reference()->get_refd_assignment();
9828 if (value_refs
.has_key(t_ass
)) {
9829 // a reference to the same variable is also passed to the called
9832 } else if (p_comptype
|| p_compself
) {
9833 // the called definition has a 'runs on' clause so it can access
9834 // component variables
9835 switch (t_ass
->get_asstype()) {
9836 case Common::Assignment::A_PAR_VAL_OUT
:
9837 case Common::Assignment::A_PAR_VAL_INOUT
:
9838 // the parameter may be an alias of a component variable
9841 case Common::Assignment::A_VAR
:
9842 // copy is needed if t_ass is a component variable that is
9843 // visible by the called definition
9844 if (!t_ass
->is_local()) copy_needed
= true;
9845 /** \todo component type compatibility: check whether t_ass is
9846 * visible from p_comptype (otherwise copy is not needed) */
9853 case ActualPar::AP_TEMPLATE
: {
9854 TemplateInstance
*ti
= par
->get_TemplateInstance();
9855 if (!ti
->get_DerivedRef()) {
9856 Template
*t
= ti
->get_Template();
9857 if (t
->get_templatetype() == Template::TEMPLATE_REFD
) {
9858 Common::Assignment
*t_ass
=
9859 t
->get_reference()->get_refd_assignment();
9860 if (template_refs
.has_key(t_ass
)) {
9861 // a reference to the same variable is also passed to the called
9864 } else if (p_comptype
|| p_compself
) {
9865 // the called definition has a 'runs on' clause so it can access
9866 // component variables
9867 switch (t_ass
->get_asstype()) {
9868 case Common::Assignment::A_PAR_TEMPL_OUT
:
9869 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9870 // the parameter may be an alias of a component variable
9873 case Common::Assignment::A_VAR_TEMPLATE
:
9874 // copy is needed if t_ass is a component variable that is
9875 // visible by the called definition
9876 if (!t_ass
->is_local()) copy_needed
= true;
9877 /** \todo component type compatibility: check whether t_ass is
9878 * visible from p_comptype (otherwise copy is not needed) */
9890 if (use_runtime_2
&& ActualPar::AP_REF
== par
->get_selection()) {
9891 // if the parameter references an element of a record of/set of, then
9892 // the record of object needs to know, so it doesn't delete the referenced
9894 Ref_base
* ref
= par
->get_Ref();
9895 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
9896 if (subrefs
!= NULL
) {
9897 Common::Assignment
* ass
= ref
->get_refd_assignment();
9899 for (ref_i
= 0; ref_i
< subrefs
->get_nof_refs(); ++ref_i
) {
9900 FieldOrArrayRef
* subref
= subrefs
->get_ref(ref_i
);
9901 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
9902 // set the referenced index in each array in the subrefs
9903 expression_struct array_expr
;
9904 Code::init_expr(&array_expr
);
9905 // the array object's name contains the reference, followed by
9906 // the subrefs before the current array ref
9907 array_expr
.expr
= mcopystr(LazyParamData::in_lazy() ?
9908 LazyParamData::add_ref_genname(ass
, ref
->get_my_scope()).c_str() :
9909 ass
->get_genname_from_scope(ref
->get_my_scope()).c_str());
9911 subrefs
->generate_code(&array_expr
, ass
, ref_i
);
9913 expression_struct index_expr
;
9914 Code::init_expr(&index_expr
);
9915 subrefs
->get_ref(ref_i
)->get_val()->generate_code_expr(&index_expr
);
9916 // insert any preambles the array object or the index might have
9917 if (array_expr
.preamble
!= NULL
) {
9918 expr
->preamble
= mputstr(expr
->preamble
, array_expr
.preamble
);
9919 expr
->postamble
= mputstr(expr
->postamble
, array_expr
.preamble
);
9921 if (index_expr
.preamble
!= NULL
) {
9922 expr
->preamble
= mputstr(expr
->preamble
, index_expr
.preamble
);
9923 expr
->postamble
= mputstr(expr
->postamble
, index_expr
.preamble
);
9925 // let the array object know that the index is referenced before
9926 // calling the function, and let it know that it's now longer
9927 // referenced after the function call (this is done with the help
9928 // of the RefdIndexHandler's constructor and destructor)
9929 string tmp_id
= ref
->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
9930 expr
->preamble
= mputprintf(expr
->preamble
,
9931 "RefdIndexHandler %s(&%s, %s);\n",
9932 tmp_id
.c_str(), array_expr
.expr
, index_expr
.expr
);
9933 // insert any postambles the array object or the index might have
9934 if (array_expr
.postamble
!= NULL
) {
9935 expr
->preamble
= mputstr(expr
->preamble
, array_expr
.postamble
);
9936 expr
->postamble
= mputstr(expr
->postamble
, array_expr
.postamble
);
9938 if (index_expr
.postamble
!= NULL
) {
9939 expr
->preamble
= mputstr(expr
->preamble
, index_expr
.postamble
);
9940 expr
->postamble
= mputstr(expr
->postamble
, index_expr
.postamble
);
9942 Code::free_expr(&array_expr
);
9943 Code::free_expr(&index_expr
);
9944 } // if (FieldOrArrayRef::ARRAY_REF == subref->get_type())
9946 } // if (subrefs != NULL)
9947 } // if (ActualPar::AP_REF == par->get_selection())
9949 par
->generate_code(expr
, copy_needed
, p_fpl
&& p_fpl
->get_fp_byIndex(i
)->get_lazy_eval(), p_fpl
&& p_fpl
->get_fp_byIndex(i
)->get_used_as_lvalue());
9952 template_refs
.clear();
9955 char *ActualParList::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
9957 for (size_t i
= 0; i
< params
.size(); i
++)
9958 str
= params
[i
]->rearrange_init_code(str
, usage_mod
);
9962 void ActualParList::dump(unsigned level
) const
9964 DEBUG(level
, "actual parameter list: %lu parameters",
9965 (unsigned long) params
.size());
9966 for (size_t i
= 0; i
< params
.size(); i
++)
9967 params
[i
]->dump(level
+ 1);