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::ref_usage_found()
622 Common::Assignment
*ass
= get_refd_assignment();
623 if (!ass
) FATAL_ERROR("Reference::ref_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
);
636 FATAL_ERROR("Reference::ref_usage_found()");
638 fpar
->set_usage_found();
640 case Common::Assignment::A_EXT_CONST
: {
641 Def_ExtConst
* def
= dynamic_cast<Def_ExtConst
*>(ass
);
643 FATAL_ERROR("Reference::ref_usage_found()");
645 def
->set_usage_found();
652 void Reference::generate_code(expression_struct_t
*expr
)
655 Common::Assignment
*ass
= get_refd_assignment();
656 if (!ass
) FATAL_ERROR("Reference::generate_code()");
658 // reference without parameters to a template that has only default formal parameters.
659 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
660 expr
->expr
= mputprintf(expr
->expr
, "%s(",
661 ass
->get_genname_from_scope(my_scope
).c_str());
662 parlist
->generate_code_alias(expr
, ass
->get_FormalParList(),
663 ass
->get_RunsOnType(), false);
664 expr
->expr
= mputc(expr
->expr
, ')');
666 expr
->expr
= mputstr(expr
->expr
,
667 LazyParamData::in_lazy() ?
668 LazyParamData::add_ref_genname(ass
, my_scope
).c_str() :
669 ass
->get_genname_from_scope(my_scope
).c_str());
671 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
674 void Reference::generate_code_const_ref(expression_struct_t
*expr
)
676 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
677 if (!t_subrefs
|| t_subrefs
->get_nof_refs() == 0) {
683 Common::Assignment
*ass
= get_refd_assignment();
684 if (!ass
) FATAL_ERROR("Reference::generate_code_const_ref()");
687 switch (ass
->get_asstype()) {
688 case Common::Assignment::A_MODULEPAR
:
689 case Common::Assignment::A_VAR
:
690 case Common::Assignment::A_FUNCTION_RVAL
:
691 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
692 case Common::Assignment::A_PAR_VAL_IN
:
693 case Common::Assignment::A_PAR_VAL_OUT
:
694 case Common::Assignment::A_PAR_VAL_INOUT
: {
697 case Common::Assignment::A_MODULEPAR_TEMP
:
698 case Common::Assignment::A_TEMPLATE
:
699 case Common::Assignment::A_VAR_TEMPLATE
:
700 case Common::Assignment::A_PAR_TEMPL_IN
:
701 case Common::Assignment::A_PAR_TEMPL_OUT
:
702 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
705 case Common::Assignment::A_CONST
:
706 case Common::Assignment::A_EXT_CONST
:
712 Type
*refd_gov
= ass
->get_Type();
714 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
715 refd_gov
->get_genname_template(get_my_scope()).c_str() );
717 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
718 refd_gov
->get_genname_value(get_my_scope()).c_str());
721 // reference without parameters to a template that has only default formal parameters.
722 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
723 expr
->expr
= mputprintf(expr
->expr
, "%s(",
724 ass
->get_genname_from_scope(my_scope
).c_str());
725 parlist
->generate_code_alias(expr
, ass
->get_FormalParList(),
726 ass
->get_RunsOnType(), false);
727 expr
->expr
= mputc(expr
->expr
, ')');
729 expr
->expr
= mputstr(expr
->expr
,
730 LazyParamData::in_lazy() ?
731 LazyParamData::add_ref_genname(ass
, my_scope
).c_str() :
732 ass
->get_genname_from_scope(my_scope
).c_str());
734 expr
->expr
= mputstr(expr
->expr
, ")");
736 if (t_subrefs
&& t_subrefs
->get_nof_refs() > 0)
737 t_subrefs
->generate_code(expr
, ass
);
740 void Reference::generate_code_portref(expression_struct_t
*expr
,
744 Common::Assignment
*ass
= get_refd_assignment();
745 if (!ass
) FATAL_ERROR("Reference::generate_code_portref()");
746 expr
->expr
= mputstr(expr
->expr
,
747 ass
->get_genname_from_scope(p_scope
).c_str());
748 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
752 void Reference::generate_code_ispresentbound(expression_struct_t
*expr
,
753 bool is_template
, const bool isbound
)
756 Common::Assignment
*ass
= get_refd_assignment();
757 const string
& ass_id
= ass
->get_genname_from_scope(my_scope
);
758 const char *ass_id_str
= ass_id
.c_str();
760 if (subrefs
.get_nof_refs() > 0) {
761 const string
& tmp_generalid
= my_scope
->get_scope_mod_gen()
762 ->get_temporary_id();
763 const char *tmp_generalid_str
= tmp_generalid
.c_str();
765 expression_struct isbound_expr
;
766 Code::init_expr(&isbound_expr
);
767 isbound_expr
.preamble
= mputprintf(isbound_expr
.preamble
,
768 "boolean %s = %s.is_bound();\n", tmp_generalid_str
,
770 ass
->get_Type()->generate_code_ispresentbound(&isbound_expr
, &subrefs
, my_scope
->get_scope_mod_gen(),
771 tmp_generalid
, ass_id
, is_template
, isbound
);
773 expr
->preamble
= mputstr(expr
->preamble
, isbound_expr
.preamble
);
774 expr
->preamble
= mputstr(expr
->preamble
, isbound_expr
.expr
);
775 Code::free_expr(&isbound_expr
);
777 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_generalid_str
);
779 expr
->expr
= mputprintf(expr
->expr
, "%s.%s(%s)", ass_id_str
,
780 isbound
? "is_bound":"is_present",
781 (!isbound
&& is_template
&& omit_in_value_list
) ? "TRUE" : "");
785 void Reference::detect_modid()
787 // do nothing if detection is already performed
789 // the first element of subrefs must be an <id>
790 const Identifier
*first_id
= subrefs
.get_ref(0)->get_id(), *second_id
= 0;
791 if (subrefs
.get_nof_refs() > 1) {
792 FieldOrArrayRef
*second_ref
= subrefs
.get_ref(1);
793 if (second_ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
794 // the reference begins with <id>.<id> (most complicated case)
795 // there are 3 possible situations:
796 // 1. first_id points to a local definition (this has the priority)
797 // modid: 0, id: first_id
798 // 2. first_id points to an imported module (trivial case)
799 // modid: first_id, id: second_id
800 // 3. none of the above (first_id might be an imported symbol)
801 // modid: 0, id: first_id
802 // Note: Rule 1 has the priority because it can be overridden using
803 // the notation <id>.objid { ... }.<id> (modid and id are set in the
804 // constructor), but there is no work-around in the reverse way.
805 if (!my_scope
->has_ass_withId(*first_id
)
806 && my_scope
->is_valid_moduleid(*first_id
)) {
807 // rule 1 is not fulfilled, but rule 2 is fulfilled
808 second_id
= second_ref
->get_id();
810 } // else: the reference begins with <id>[<arrayref>] -> there is no modid
811 } // else: the reference consists of a single <id> -> there is no modid
813 modid
= first_id
->clone();
814 id
= second_id
->clone();
815 subrefs
.remove_refs(2);
818 id
= first_id
->clone();
819 subrefs
.remove_refs(1);
823 // =================================
825 // =================================
827 Ref_pard::Ref_pard(const Ref_pard
& p
)
828 : Ref_base(p
), parlist(p
.parlist
), expr_cache(0)
830 params
= p
.params
? p
.params
->clone() : 0;
833 Ref_pard::Ref_pard(Identifier
*p_modid
, Identifier
*p_id
,
834 ParsedActualParameters
*p_params
)
835 : Ref_base(p_modid
, p_id
), parlist(), params(p_params
), expr_cache(0)
838 FATAL_ERROR("Ttcn::Ref_pard::Ref_pard(): NULL parameter");
841 Ref_pard::~Ref_pard()
847 Ref_pard
*Ref_pard::clone() const
849 return new Ref_pard(*this);
852 void Ref_pard::set_fullname(const string
& p_fullname
)
854 Ref_base::set_fullname(p_fullname
);
855 parlist
.set_fullname(p_fullname
);
856 if (params
) params
->set_fullname(p_fullname
);
859 void Ref_pard::set_my_scope(Scope
*p_scope
)
861 Ref_base::set_my_scope(p_scope
);
862 parlist
.set_my_scope(p_scope
);
863 if (params
) params
->set_my_scope(p_scope
);
866 string
Ref_pard::get_dispname()
868 if (is_erroneous
) return string("erroneous");
871 ret_val
+= modid
->get_dispname();
874 ret_val
+= id
->get_dispname();
876 if (params_checked
) {
877 // used after semantic analysis
878 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++) {
879 if (i
> 0) ret_val
+= ", ";
880 parlist
.get_par(i
)->append_stringRepr(ret_val
);
883 // used before semantic analysis
884 for (size_t i
= 0; i
< params
->get_nof_tis(); i
++) {
885 if (i
> 0) ret_val
+= ", ";
886 params
->get_ti_byIndex(i
)->append_stringRepr(ret_val
);
890 subrefs
.append_stringRepr(ret_val
);
894 Common::Assignment
* Ref_pard::get_refd_assignment(bool check_parlist
)
896 Common::Assignment
*ass
= Ref_base::get_refd_assignment(check_parlist
);
897 if (ass
&& check_parlist
&& !params_checked
) {
898 params_checked
= true;
899 FormalParList
*fplist
= ass
->get_FormalParList();
901 Error_Context
cntxt(params
, "In actual parameter list of %s",
902 ass
->get_description().c_str());
903 is_erroneous
= fplist
->fold_named_and_chk(params
, &parlist
);
904 parlist
.set_fullname(get_fullname());
905 parlist
.set_my_scope(my_scope
);
906 // the parsed parameter list is no longer needed
910 params
->error("The referenced %s cannot have actual parameters",
911 ass
->get_description().c_str());
917 const Identifier
* Ref_pard::get_modid()
922 const Identifier
* Ref_pard::get_id()
927 ActualParList
*Ref_pard::get_parlist()
929 if (!params_checked
) FATAL_ERROR("Ref_pard::get_parlist()");
933 bool Ref_pard::chk_activate_argument()
935 Common::Assignment
*t_ass
= get_refd_assignment();
936 if (!t_ass
) return false;
937 if (t_ass
->get_asstype() != Common::Assignment::A_ALTSTEP
) {
938 error("Reference to an altstep was expected in the argument instead of "
939 "%s", t_ass
->get_description().c_str());
942 my_scope
->chk_runs_on_clause(t_ass
, *this, "activate");
943 // the altstep reference cannot have sub-references
944 if (get_subrefs()) FATAL_ERROR("Ref_pard::chk_activate_argument()");
945 FormalParList
*fp_list
= t_ass
->get_FormalParList();
946 // the altstep must have formal parameter list
947 if (!fp_list
) FATAL_ERROR("Ref_pard::chk_activate_argument()");
948 return fp_list
->chk_activate_argument(&parlist
,
949 t_ass
->get_description().c_str());
952 bool Ref_pard::has_single_expr()
954 if (!Ref_base::has_single_expr()) return false;
955 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++)
956 if (!parlist
.get_par(i
)->has_single_expr()) return false;
957 // if any formal parameter has lazy evaluation
958 Common::Assignment
*ass
= get_refd_assignment();
960 const FormalParList
*fplist
= ass
->get_FormalParList();
962 size_t num_formal
= fplist
->get_nof_fps();
963 for (size_t i
=0; i
<num_formal
; ++i
) {
964 const FormalPar
*fp
= fplist
->get_fp_byIndex(i
);
965 if (fp
->get_lazy_eval()) return false;
972 void Ref_pard::set_code_section(
973 GovernedSimple::code_section_t p_code_section
)
975 Ref_base::set_code_section(p_code_section
);
976 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++)
977 parlist
.get_par(i
)->set_code_section(p_code_section
);
980 void Ref_pard::generate_code(expression_struct_t
*expr
)
982 Common::Assignment
*ass
= get_refd_assignment();
983 // C++ function reference with actual parameter list
984 expr
->expr
= mputprintf(expr
->expr
, "%s(",
985 ass
->get_genname_from_scope(my_scope
).c_str());
986 parlist
.generate_code_alias(expr
, ass
->get_FormalParList(),
987 ass
->get_RunsOnType(),false);
988 expr
->expr
= mputc(expr
->expr
, ')');
990 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
993 void Ref_pard::generate_code_cached(expression_struct_t
*expr
)
996 expr
->expr
= mputstr(expr
->expr
, expr_cache
);
1000 expr_cache
= mputstr(expr_cache
, expr
->expr
);
1004 void Ref_pard::generate_code_const_ref(expression_struct_t
*expr
)
1006 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
1007 if (!t_subrefs
|| t_subrefs
->get_nof_refs() == 0) {
1008 generate_code(expr
);
1012 Common::Assignment
*ass
= get_refd_assignment();
1013 if (!ass
) FATAL_ERROR("Ref_pard::generate_code_const_ref()");
1016 switch (ass
->get_asstype()) {
1017 case Common::Assignment::A_TEMPLATE
:
1018 if (NULL
== ass
->get_FormalParList()) {
1019 // not a parameterized template
1023 // else fall through
1024 case Common::Assignment::A_CONST
:
1025 case Common::Assignment::A_EXT_CONST
:
1026 case Common::Assignment::A_ALTSTEP
:
1027 case Common::Assignment::A_TESTCASE
:
1028 case Common::Assignment::A_FUNCTION
:
1029 case Common::Assignment::A_EXT_FUNCTION
:
1030 case Common::Assignment::A_FUNCTION_RVAL
:
1031 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
1032 case Common::Assignment::A_FUNCTION_RTEMP
:
1033 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
1034 generate_code(expr
);
1036 case Common::Assignment::A_MODULEPAR
:
1037 case Common::Assignment::A_VAR
:
1038 case Common::Assignment::A_PAR_VAL_IN
:
1039 case Common::Assignment::A_PAR_VAL_OUT
:
1040 case Common::Assignment::A_PAR_VAL_INOUT
: {
1041 is_template
= false;
1043 case Common::Assignment::A_MODULEPAR_TEMP
:
1044 case Common::Assignment::A_VAR_TEMPLATE
:
1045 case Common::Assignment::A_PAR_TEMPL_IN
:
1046 case Common::Assignment::A_PAR_TEMPL_OUT
:
1047 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
1051 is_template
= false;
1055 Type
*refd_gov
= ass
->get_Type();
1057 generate_code(expr
);
1062 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
1063 refd_gov
->get_genname_template(get_my_scope()).c_str() );
1065 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s%s&>(",
1066 refd_gov
->get_genname_value(get_my_scope()).c_str(),
1067 is_template
? "_template":"");
1070 expr
->expr
= mputprintf(expr
->expr
, "%s(",
1071 ass
->get_genname_from_scope(my_scope
).c_str());
1072 parlist
.generate_code_alias(expr
, ass
->get_FormalParList(),
1073 ass
->get_RunsOnType(), false);
1074 expr
->expr
= mputstr(expr
->expr
, "))");
1076 t_subrefs
->generate_code(expr
, ass
);
1079 // =================================
1080 // ===== NameBridgingScope
1081 // =================================
1082 string
NameBridgingScope::get_scopeMacro_name() const
1084 if (scopeMacro_name
.empty()) FATAL_ERROR("NameBridgingScope::get_scopeMacro_name()");
1085 return scopeMacro_name
;
1088 NameBridgingScope
*NameBridgingScope::clone() const
1090 FATAL_ERROR("NameBridgingScope::clone");
1093 Common::Assignment
* NameBridgingScope::get_ass_bySRef(Ref_simple
*p_ref
)
1095 return get_parent_scope()->get_ass_bySRef(p_ref
);
1098 // =================================
1099 // ===== RunsOnScope
1100 // =================================
1102 RunsOnScope::RunsOnScope(Type
*p_comptype
)
1103 : Scope(), component_type(p_comptype
)
1105 if (!p_comptype
|| p_comptype
->get_typetype() != Type::T_COMPONENT
)
1106 FATAL_ERROR("RunsOnScope::RunsOnScope()");
1107 component_type
->set_ownertype(Type::OT_RUNSON_SCOPE
, this);
1108 component_defs
= p_comptype
->get_CompBody();
1109 set_scope_name("runs on `" + p_comptype
->get_fullname() + "'");
1112 RunsOnScope
*RunsOnScope::clone() const
1114 FATAL_ERROR("RunsOnScope::clone()");
1117 void RunsOnScope::chk_uniq()
1119 // do not perform this check if the component type is defined in the same
1120 // module as the 'runs on' clause
1121 if (parent_scope
->get_scope_mod() == component_defs
->get_scope_mod())
1123 size_t nof_defs
= component_defs
->get_nof_asss();
1124 for (size_t i
= 0; i
< nof_defs
; i
++) {
1125 Common::Assignment
*comp_def
= component_defs
->get_ass_byIndex(i
);
1126 const Identifier
& id
= comp_def
->get_id();
1127 if (parent_scope
->has_ass_withId(id
)) {
1128 comp_def
->warning("Imported component element definition `%s' hides a "
1129 "definition at module scope", comp_def
->get_fullname().c_str());
1130 Reference
ref(0, id
.clone());
1131 Common::Assignment
*hidden_ass
= parent_scope
->get_ass_bySRef(&ref
);
1132 hidden_ass
->warning("Hidden definition `%s' is here",
1133 hidden_ass
->get_fullname().c_str());
1139 RunsOnScope
*RunsOnScope::get_scope_runs_on()
1144 Common::Assignment
*RunsOnScope::get_ass_bySRef(Ref_simple
*p_ref
)
1146 if (!p_ref
) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1147 if (p_ref
->get_modid()) return parent_scope
->get_ass_bySRef(p_ref
);
1149 const Identifier
& id
= *p_ref
->get_id();
1150 if (component_defs
->has_local_ass_withId(id
)) {
1151 Common::Assignment
* ass
= component_defs
->get_local_ass_byId(id
);
1152 if (!ass
) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1154 if (component_defs
->is_own_assignment(ass
)) return ass
;
1155 else if (ass
->get_visibility() == PUBLIC
) {
1159 p_ref
->error("The member definition `%s' in component type `%s'"
1160 " is not visible in this scope", id
.get_dispname().c_str(),
1161 component_defs
->get_id()->get_dispname().c_str());
1163 } else return parent_scope
->get_ass_bySRef(p_ref
);
1167 bool RunsOnScope::has_ass_withId(const Identifier
& p_id
)
1169 return component_defs
->has_ass_withId(p_id
)
1170 || parent_scope
->has_ass_withId(p_id
);
1173 // =================================
1175 // =================================
1177 FriendMod::FriendMod(Identifier
*p_modid
)
1178 : Node(), modid(p_modid
), w_attrib_path(0), parentgroup(0), checked(false)
1180 if (!p_modid
) FATAL_ERROR("NULL parameter: Ttcn::FriendMod::FriendMod()");
1181 set_fullname("<friends>."+modid
->get_dispname());
1184 FriendMod::~FriendMod()
1188 delete w_attrib_path
;
1191 FriendMod
*FriendMod::clone() const
1193 FATAL_ERROR("Ttcn::FriendMod::clone()");
1196 void FriendMod::set_fullname(const string
& p_fullname
)
1198 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
1201 void FriendMod::chk()
1203 if (checked
) return;
1205 Error_Context
cntxt(this, "In friend module declaration");
1207 if (w_attrib_path
) {
1208 w_attrib_path
->chk_global_attrib();
1209 w_attrib_path
->chk_no_qualif();
1215 void FriendMod::set_with_attr(MultiWithAttrib
* p_attrib
)
1217 if (w_attrib_path
) FATAL_ERROR("FriendMod::set_with_attr()");
1218 w_attrib_path
= new WithAttribPath();
1219 if (p_attrib
&& p_attrib
->get_nof_elements() > 0) {
1220 w_attrib_path
->set_with_attr(p_attrib
);
1224 WithAttribPath
* FriendMod::get_attrib_path()
1226 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1227 return w_attrib_path
;
1230 void FriendMod::set_parent_path(WithAttribPath
* p_path
)
1232 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1233 w_attrib_path
->set_parent(p_path
);
1236 void FriendMod::set_parent_group(Group
* p_group
)
1238 if(parentgroup
) FATAL_ERROR("FriendMod::set_parent_group");
1239 parentgroup
= p_group
;
1242 // =================================
1244 // =================================
1246 ImpMod::ImpMod(Identifier
*p_modid
)
1247 : Node(), mod(0), my_mod(0), imptype(I_UNDEF
), modid(p_modid
),
1248 language_spec(0), is_recursive(false),
1249 w_attrib_path(0), parentgroup(0), visibility(PRIVATE
)
1251 if (!p_modid
) FATAL_ERROR("NULL parameter: Ttcn::ImpMod::ImpMod()");
1252 set_fullname("<imports>." + modid
->get_dispname());
1258 delete language_spec
;
1260 delete w_attrib_path
;
1263 ImpMod
*ImpMod::clone() const
1265 FATAL_ERROR("No clone for you!");
1268 void ImpMod::set_fullname(const string
& p_fullname
)
1270 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
1275 if (w_attrib_path
) {
1276 w_attrib_path
->chk_global_attrib();
1277 w_attrib_path
->chk_no_qualif();
1281 void ImpMod::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
1283 Error_Context
cntxt(this, "In import definition");
1285 if (!modules
->has_mod_withId(*modid
)) {
1286 error("There is no module with identifier `%s'",
1287 modid
->get_dispname().c_str());
1291 Common::Module
*m
= modules
->get_mod_byId(*modid
);
1297 error("A module cannot import from itself");
1305 if (refch
.exists(my_mod
->get_fullname())) {
1306 if(my_mod
->get_moduletype()!=Common::Module::MOD_ASN
){ // Do not warning for circular import in ASN.1 module. It is legal
1307 my_mod
->warning("Circular import chain is not recommended: %s",
1308 refch
.get_dispstr(my_mod
->get_fullname()).c_str());
1313 refch
.add(my_mod
->get_fullname());
1315 if (ImpMod::I_IMPORTIMPORT
== imptype
){
1316 Ttcn::Module
* ttcnmodule
=static_cast<Ttcn::Module
*>(m
);
1317 const Imports
& imp
= ttcnmodule
->get_imports();
1319 for (size_t t
= 0; t
< imp
.impmods_v
.size(); t
++) {
1320 const ImpMod
*im
= imp
.impmods_v
[t
];
1321 const Identifier
& im_id
= im
->get_modid();
1322 Common::Module
*cm
= modules
->get_mod_byId(im_id
); // never NULL
1325 if (PRIVATE
!= im
->get_visibility()) {
1326 if (refch
.exists(m
->get_fullname())) {
1327 if(m
->get_moduletype()!=Common::Module::MOD_ASN
){ // Do not warning for circular import in ASN.1 module. It is legal
1328 m
->warning("Circular import chain is not recommended: %s",
1329 refch
.get_dispstr(m
->get_fullname()).c_str());
1334 refch
.add(m
->get_fullname());
1335 cm
->chk_imp(refch
, moduleStack
);
1341 //refch.mark_state();
1342 m
->chk_imp(refch
, moduleStack
);
1343 //refch.prev_state();
1348 size_t state
=moduleStack
.size();
1349 moduleStack
.replace(state
, moduleStack
.size() - state
);
1352 bool ImpMod::has_imported_def(const Identifier
& p_source_modid
,
1353 const Identifier
& p_id
, const Location
*loc
) const
1355 if (!mod
) return false;
1361 Common::Assignment
* return_assignment
= mod
->importAssignment(p_source_modid
, p_id
);
1362 if (return_assignment
!= NULL
) {
1369 case I_IMPORTIMPORT
:
1371 Ttcn::Module
*tm
= static_cast<Ttcn::Module
*>(mod
); // B
1373 const Imports
& imps
= tm
->get_imports();
1375 vector
<ImpMod
> tempusedImpMods
;
1376 for (size_t i
= 0, num
= imps
.impmods_v
.size(); i
< num
; ++i
) {
1377 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
1378 Common::Assignment
* return_assignment
= imps
.impmods_v
[i
]->
1379 get_imported_def(p_source_modid
, p_id
, loc
, referencechain
, tempusedImpMods
); // C
1380 referencechain
->reset();
1381 delete referencechain
;
1383 if (return_assignment
!= NULL
) {
1389 //satisfy destructor
1390 tempusedImpMods
.clear();
1395 FATAL_ERROR("ImpMod::get_imported_def");
1401 Common::Assignment
*ImpMod::get_imported_def(
1402 const Identifier
& p_source_modid
, const Identifier
& p_id
,
1403 const Location
*loc
, ReferenceChain
* refch
,
1404 vector
<ImpMod
>& usedImpMods
) const
1409 Common::Assignment
* result
= NULL
;
1414 result
= mod
->importAssignment(p_source_modid
, p_id
);
1415 if (result
!= NULL
) {
1416 usedImpMods
.add(const_cast<Ttcn::ImpMod
*>(this));
1420 case I_IMPORTIMPORT
:
1422 Ttcn::Module
*tm
= static_cast<Ttcn::Module
*>(mod
);
1424 const Imports
& imps
= tm
->get_imports();
1425 Common::Assignment
* t_ass
= NULL
;
1427 for (size_t i
= 0, num
= imps
.impmods_v
.size(); i
< num
; ++i
) {
1428 vector
<ImpMod
> tempusedImpMods
;
1430 refch
->mark_state();
1431 if (imps
.impmods_v
[i
]->get_visibility() == PUBLIC
) {
1432 t_ass
= imps
.impmods_v
[i
]->get_imported_def(p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1434 else if (imps
.impmods_v
[i
]->get_visibility() == FRIEND
) {
1435 t_ass
= imps
.impmods_v
[i
]->get_imported_def(p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1437 tempusedImpMods
.add(imps
.impmods_v
[i
]);
1440 refch
->prev_state();
1442 if (t_ass
!= NULL
) {
1443 bool visible
= true;
1444 for (size_t j
= 0; j
< tempusedImpMods
.size(); j
++) {
1445 ImpMod
* impmod_l
= tempusedImpMods
[j
];
1446 //check whether the module is TTCN
1447 if (impmod_l
->get_mod()->get_moduletype() == Common::Module::MOD_TTCN
) {
1448 // cast to ttcn module
1449 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(impmod_l
->get_mod());
1450 if (!ttcn_m
->is_visible(mod
->get_modid(), impmod_l
->get_visibility())) {
1456 for (size_t t
= 0; i
< tempusedImpMods
.size(); i
++) {
1457 usedImpMods
.add(tempusedImpMods
[t
]);
1462 } else if(result
!= t_ass
) {
1467 "It is not possible to resolve the reference unambiguously"
1468 ", as it can be resolved to `%s' and to `%s'",
1469 result
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
1475 tempusedImpMods
.clear();
1478 if (result
!= NULL
) {
1479 usedImpMods
.add(const_cast<Ttcn::ImpMod
*>(this));
1485 FATAL_ERROR("ImpMod::get_imported_def");
1490 void ImpMod::set_language_spec(const char *p_language_spec
)
1492 if (language_spec
) FATAL_ERROR("ImpMod::set_language_spec()");
1493 if (p_language_spec
) language_spec
= new string(p_language_spec
);
1496 void ImpMod::generate_code(output_struct
*target
)
1498 const char *module_name
= modid
->get_name().c_str();
1500 target
->header
.includes
= mputprintf(target
->header
.includes
,
1501 "#include \"%s.hh\"\n",
1502 duplicate_underscores
? module_name
: modid
->get_ttcnname().c_str());
1504 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
1505 "%s%s.pre_init_module();\n", module_name
,
1508 if (mod
->get_moduletype() == Common::Module::MOD_TTCN
) {
1509 target
->functions
.post_init
= mputprintf(target
->functions
.post_init
,
1510 "%s%s.post_init_module();\n", module_name
,
1516 void ImpMod::dump(unsigned level
) const
1518 DEBUG(level
, "Import from module %s", modid
->get_dispname().c_str());
1519 if (w_attrib_path
) {
1520 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
1522 DEBUG(level
+ 1, "Attributes:");
1523 attrib
->dump(level
+ 2);
1528 void ImpMod::set_with_attr(MultiWithAttrib
* p_attrib
)
1530 if (w_attrib_path
) FATAL_ERROR("ImpMod::set_with_attr()");
1531 w_attrib_path
= new WithAttribPath();
1532 if (p_attrib
&& p_attrib
->get_nof_elements() > 0) {
1533 w_attrib_path
->set_with_attr(p_attrib
);
1537 WithAttribPath
* ImpMod::get_attrib_path()
1539 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1540 return w_attrib_path
;
1543 void ImpMod::set_parent_path(WithAttribPath
* p_path
)
1545 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1546 w_attrib_path
->set_parent(p_path
);
1549 void ImpMod::set_parent_group(Group
* p_group
)
1551 if(parentgroup
) FATAL_ERROR("ImpMod::set_parent_group");
1552 parentgroup
= p_group
;
1555 // =================================
1557 // =================================
1561 for (size_t i
= 0; i
< impmods_v
.size(); i
++)
1562 delete impmods_v
[i
];
1566 Imports
*Imports::clone() const
1568 FATAL_ERROR("Ttcn::Imports::clone()");
1571 void Imports::add_impmod(ImpMod
*p_impmod
)
1573 if (!p_impmod
) FATAL_ERROR("Ttcn::Imports::add_impmod()");
1574 impmods_v
.add(p_impmod
);
1575 p_impmod
->set_my_mod(my_mod
);
1578 void Imports::set_my_mod(Module
*p_mod
)
1581 for(size_t i
= 0; i
< impmods_v
.size(); i
++)
1582 impmods_v
[i
]->set_my_mod(my_mod
);
1585 bool Imports::has_impmod_withId(const Identifier
& p_id
) const
1587 for (size_t i
= 0, size
= impmods_v
.size(); i
< size
; ++i
) {
1588 const ImpMod
* im
= impmods_v
[i
];
1589 const Identifier
& im_id
= im
->get_modid();
1590 const string
& im_name
= im_id
.get_name();
1591 if (p_id
.get_name() == im_name
) {
1592 // The identifier represents a module imported in the current module
1599 void Imports::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
1601 if (impmods_v
.size() <= 0) return;
1603 if (!my_mod
) FATAL_ERROR("Ttcn::Imports::chk_imp()");
1608 for(size_t n
= 0; n
< impmods_v
.size(); n
++)
1610 impmods_v
[n
]->chk();
1613 //TODO this whole thing should be moved into impmod::chk
1614 Identifier
address_id(Identifier::ID_TTCN
, string("address"));
1615 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1616 ImpMod
*im
= impmods_v
[n
];
1617 im
->chk_imp(refch
, moduleStack
);
1619 const Identifier
& im_id
= im
->get_modid();
1620 Common::Module
*m
= modules
->get_mod_byId(im_id
);
1623 if (m
->get_gen_code()) my_mod
->set_gen_code();
1624 } // next assignment
1627 bool Imports::has_imported_def(const Identifier
& p_id
, const Location
*loc
) const
1629 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1630 ImpMod
*im
= impmods_v
[n
];
1631 bool return_bool
= im
->has_imported_def(my_mod
->get_modid(), p_id
, loc
);
1632 if (return_bool
) return true;
1637 Common::Assignment
*Imports::get_imported_def(
1638 const Identifier
& p_source_modid
, const Identifier
& p_id
,
1639 const Location
*loc
, ReferenceChain
* refch
)
1641 vector
<ImpMod
> tempusedImpMods
;
1642 Common::Assignment
* result
= NULL
;
1643 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1644 ImpMod
*im
= impmods_v
[n
];
1645 refch
->mark_state();
1646 Common::Assignment
* ass
= im
->get_imported_def(
1647 p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1648 tempusedImpMods
.clear();
1649 refch
->prev_state();
1654 } else if(result
!= ass
&& loc
) {
1659 "It is not possible to resolve the reference unambiguously"
1660 ", as it can be resolved to `%s' and to `%s'",
1661 result
->get_fullname().c_str(), ass
->get_fullname().c_str());
1669 void Imports::get_imported_mods(Module::module_set_t
& p_imported_mods
) const
1671 for (size_t i
= 0; i
< impmods_v
.size(); i
++) {
1672 ImpMod
*im
= impmods_v
[i
];
1673 Common::Module
*m
= im
->get_mod();
1675 if (!p_imported_mods
.has_key(m
)) {
1676 p_imported_mods
.add(m
, 0);
1677 m
->get_visible_mods(p_imported_mods
);
1682 void Imports::generate_code(output_struct
*target
)
1684 target
->header
.includes
= mputstr(target
->header
.includes
,
1685 "#include <TTCN3.hh>\n");
1686 for (size_t i
= 0; i
< impmods_v
.size(); i
++) {
1687 ImpMod
*im
= impmods_v
[i
];
1688 Common::Module
*m
= im
->get_mod();
1689 // inclusion of m's header file can be eliminated if we find another
1690 // imported module that imports m
1691 bool covered
= false;
1692 for (size_t j
= 0; j
< impmods_v
.size(); j
++) {
1693 // skip over the same import definition
1694 if (j
== i
) continue;
1695 ImpMod
*im2
= impmods_v
[j
];
1696 Common::Module
*m2
= im2
->get_mod();
1697 // a module that is equivalent to the current module due to
1698 // circular imports cannot be used to cover anything
1699 if (m2
->is_visible(my_mod
)) continue;
1700 if (m2
->is_visible(m
) && !m
->is_visible(m2
)) {
1701 // m2 covers m (i.e. m is visible from m2)
1702 // and they are not in the same import loop
1707 // do not generate the #include if a covering module is found
1708 if (!covered
) im
->generate_code(target
);
1712 void Imports::generate_code(CodeGenHelper
& cgh
) {
1713 generate_code(cgh
.get_current_outputstruct());
1716 void Imports::dump(unsigned level
) const
1718 DEBUG(level
, "Imports (%lu pcs.)", (unsigned long) impmods_v
.size());
1719 for (size_t i
= 0; i
< impmods_v
.size(); i
++)
1720 impmods_v
[i
]->dump(level
+ 1);
1723 // =================================
1724 // ===== Definitions
1725 // =================================
1727 Definitions::~Definitions()
1729 for(size_t i
= 0; i
< ass_v
.size(); i
++) delete ass_v
[i
];
1734 Definitions
*Definitions::clone() const
1736 FATAL_ERROR("Definitions::clone");
1739 void Definitions::add_ass(Definition
*p_ass
)
1741 // it is too late to add a new one after it has been checked.
1742 if (checked
|| !p_ass
) FATAL_ERROR("Ttcn::OtherDefinitions::add_ass()");
1744 p_ass
->set_my_scope(this);
1747 void Definitions::set_fullname(const string
& p_fullname
)
1749 Common::Assignments::set_fullname(p_fullname
);
1750 for(size_t i
= 0; i
< ass_v
.size(); i
++) {
1751 Definition
*ass
= ass_v
[i
];
1752 ass
->set_fullname(p_fullname
+ "." + ass
->get_id().get_dispname());
1756 bool Definitions::has_local_ass_withId(const Identifier
& p_id
)
1758 if (!checked
) chk_uniq();
1759 return ass_m
.has_key(p_id
.get_name());
1762 Common::Assignment
* Definitions::get_local_ass_byId(const Identifier
& p_id
)
1764 if (!checked
) chk_uniq();
1765 return ass_m
[p_id
.get_name()];
1768 size_t Definitions::get_nof_asss()
1770 if (!checked
) chk_uniq();
1771 return ass_m
.size();
1774 size_t Definitions::get_nof_raw_asss()
1776 return ass_v
.size();
1779 Common::Assignment
* Definitions::get_ass_byIndex(size_t p_i
)
1781 if (!checked
) chk_uniq();
1782 return ass_m
.get_nth_elem(p_i
);
1785 Ttcn::Definition
* Definitions::get_raw_ass_byIndex(size_t p_i
) {
1789 void Definitions::chk_uniq()
1791 if (checked
) return;
1793 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1794 Definition
*ass
= ass_v
[i
];
1795 const Identifier
& id
= ass
->get_id();
1796 const string
& name
= id
.get_name();
1797 if (ass_m
.has_key(name
)) {
1798 const char *dispname_str
= id
.get_dispname().c_str();
1799 ass
->error("Duplicate definition with name `%s'", dispname_str
);
1800 ass_m
[name
]->note("Previous definition of `%s' is here", dispname_str
);
1802 ass_m
.add(name
, ass
);
1803 if (parent_scope
->is_valid_moduleid(id
)) {
1804 ass
->warning("Definition with name `%s' hides a module identifier",
1805 id
.get_dispname().c_str());
1812 void Definitions::chk()
1814 for (size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->chk();
1817 void Definitions::chk_for()
1819 if (checked
) return;
1822 // all checks are done in one iteration because
1823 // forward referencing is not allowed between the definitions
1824 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1825 Definition
*def
= ass_v
[i
];
1826 const Identifier
& id
= def
->get_id();
1827 const string
& name
= id
.get_name();
1828 if (ass_m
.has_key(name
)) {
1829 const char *dispname_str
= id
.get_dispname().c_str();
1830 def
->error("Duplicate definition with name `%s'", dispname_str
);
1831 ass_m
[name
]->note("Previous definition of `%s' is here", dispname_str
);
1833 ass_m
.add(name
, def
);
1835 if (parent_scope
->has_ass_withId(id
)) {
1836 const char *dispname_str
= id
.get_dispname().c_str();
1837 def
->error("Definition with identifier `%s' is not unique in the "
1838 "scope hierarchy", dispname_str
);
1839 Reference
ref(0, id
.clone());
1840 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
1841 if (!ass
) FATAL_ERROR("OtherDefinitions::chk_for()");
1842 ass
->note("Previous definition with identifier `%s' in higher "
1843 "scope unit is here", dispname_str
);
1844 } else if (parent_scope
->is_valid_moduleid(id
)) {
1845 def
->warning("Definition with name `%s' hides a module identifier",
1846 id
.get_dispname().c_str());
1854 void Definitions::set_genname(const string
& prefix
)
1856 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1857 Definition
*def
= ass_v
[i
];
1858 def
->set_genname(prefix
+ def
->get_id().get_name());
1862 void Definitions::generate_code(output_struct
* target
)
1864 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->generate_code(target
);
1867 void Definitions::generate_code(CodeGenHelper
& cgh
) {
1869 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->generate_code(cgh
);
1872 char* Definitions::generate_code_str(char *str
)
1874 for(size_t i
=0; i
<ass_v
.size(); i
++) {
1875 str
= ass_v
[i
]->update_location_object(str
);
1876 str
=ass_v
[i
]->generate_code_str(str
);
1881 void Definitions::ilt_generate_code(ILT
*ilt
)
1883 for(size_t i
=0; i
<ass_v
.size(); i
++)
1884 ass_v
[i
]->ilt_generate_code(ilt
);
1888 void Definitions::dump(unsigned level
) const
1890 DEBUG(level
, "Definitions: (%lu pcs.)", (unsigned long) ass_v
.size());
1891 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->dump(level
+ 1);
1894 // =================================
1896 // =================================
1898 Group::Group(Identifier
*p_id
)
1899 : Node(), Location(), parent_group(0), w_attrib_path(0), id(p_id
),
1902 if (!p_id
) FATAL_ERROR("Group::Group()");
1907 delete w_attrib_path
;
1910 for (size_t i
= 0; i
< group_v
.size(); i
++) delete group_v
[i
];
1914 friendmods_v
.clear();
1918 Group
* Group::clone() const
1920 FATAL_ERROR("Ttcn::Group::clone()");
1923 void Group::set_fullname(const string
& p_fullname
)
1925 Node::set_fullname(p_fullname
);
1926 for(size_t i
= 0; i
< group_v
.size() ; i
++)
1928 group_v
[i
]->set_fullname(p_fullname
+ ".<group " + Int2string(i
) + ">");
1930 if (w_attrib_path
) w_attrib_path
->set_fullname( p_fullname
1934 void Group::add_ass(Definition
* p_ass
)
1937 p_ass
->set_parent_group(this);
1940 void Group::add_group(Group
* p_group
)
1942 group_v
.add(p_group
);
1945 void Group::set_parent_group(Group
* p_parent_group
)
1947 if (parent_group
) FATAL_ERROR("Group::set_parent_group()");
1948 parent_group
= p_parent_group
;
1951 void Group::set_with_attr(MultiWithAttrib
* p_attrib
)
1953 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1954 w_attrib_path
->set_with_attr(p_attrib
);
1957 WithAttribPath
* Group::get_attrib_path()
1959 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1960 return w_attrib_path
;
1963 void Group::set_parent_path(WithAttribPath
* p_path
)
1965 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1966 w_attrib_path
->set_parent(p_path
);
1969 void Group::chk_uniq()
1971 if (checked
) return;
1975 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1976 Definition
*ass
= ass_v
[i
];
1977 const string
& ass_name
= ass
->get_id().get_name();
1978 if (!ass_m
.has_key(ass_name
)) ass_m
.add(ass_name
, ass
);
1981 for(size_t i
= 0; i
< group_v
.size(); i
++) {
1982 Group
*group
= group_v
[i
];
1983 const Identifier
& group_id
= group
->get_id();
1984 const string
& group_name
= group_id
.get_name();
1985 if (ass_m
.has_key(group_name
)) {
1986 group
->error("Group name `%s' clashes with a definition",
1987 group_id
.get_dispname().c_str());
1988 ass_m
[group_name
]->note("Definition of `%s' is here",
1989 group_id
.get_dispname().c_str());
1991 if (group_m
.has_key(group_name
)) {
1992 group
->error("Duplicate group with name `%s'",
1993 group_id
.get_dispname().c_str());
1994 group_m
[group_name
]->note("Group `%s' is already defined here",
1995 group_id
.get_dispname().c_str());
1996 } else group_m
.add(group_name
, group
);
2003 Error_Context
cntxt(this, "In group `%s'", id
->get_dispname().c_str());
2007 if (w_attrib_path
) {
2008 w_attrib_path
->chk_global_attrib();
2009 w_attrib_path
->chk_no_qualif();
2012 for(size_t i
= 0; i
< group_v
.size(); i
++) group_v
[i
]->chk();
2015 void Group::add_impmod(ImpMod
*p_impmod
)
2017 impmods_v
.add(p_impmod
);
2018 p_impmod
->set_parent_group(this);
2021 void Group::add_friendmod(FriendMod
*p_friendmod
)
2023 friendmods_v
.add(p_friendmod
);
2024 p_friendmod
->set_parent_group(this);
2027 void Group::dump(unsigned level
) const
2029 DEBUG(level
, "Group: %s", id
->get_dispname().c_str());
2030 DEBUG(level
+ 1, "Nested groups: (%lu pcs.)",
2031 (unsigned long) group_v
.size());
2032 for(size_t i
= 0; i
< group_v
.size(); i
++) group_v
[i
]->dump(level
+ 2);
2033 DEBUG(level
+ 1, "Nested definitions: (%lu pcs.)",
2034 (unsigned long) ass_v
.size());
2035 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->dump(level
+ 2);
2036 DEBUG(level
+ 1, "Nested imports: (%lu pcs.)",
2037 (unsigned long) impmods_v
.size());
2038 for(size_t i
= 0; i
< impmods_v
.size(); i
++) impmods_v
[i
]->dump(level
+ 2);
2039 if (w_attrib_path
) {
2040 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2042 DEBUG(level
+ 1, "Group Attributes:");
2043 attrib
->dump(level
+ 2);
2048 // =================================
2049 // ===== ControlPart
2050 // =================================
2052 ControlPart::ControlPart(StatementBlock
* p_block
)
2053 : Node(), Location(), block(p_block
), w_attrib_path(0)
2055 if (!p_block
) FATAL_ERROR("ControlPart::ControlPart()");
2058 ControlPart::~ControlPart()
2061 delete w_attrib_path
;
2064 ControlPart
* ControlPart::clone() const
2066 FATAL_ERROR("ControlPart::clone");
2069 void ControlPart::set_fullname(const string
& p_fullname
)
2071 block
->set_fullname(p_fullname
);
2072 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
2075 void ControlPart::set_my_scope(Scope
*p_scope
)
2077 bridgeScope
.set_parent_scope(p_scope
);
2078 string
temp("control");
2079 bridgeScope
.set_scopeMacro_name(temp
);
2081 block
->set_my_scope(&bridgeScope
);
2084 void ControlPart::chk()
2086 Error_Context
cntxt(this, "In control part");
2088 if (!semantic_check_only
)
2089 block
->set_code_section(GovernedSimple::CS_INLINE
);
2090 if (w_attrib_path
) {
2091 w_attrib_path
->chk_global_attrib();
2092 w_attrib_path
->chk_no_qualif();
2096 void ControlPart::generate_code(output_struct
*target
, Module
*my_module
)
2098 const char *module_dispname
= my_module
->get_modid().get_dispname().c_str();
2099 target
->functions
.control
=
2100 create_location_object(target
->functions
.control
, "CONTROLPART",
2102 target
->functions
.control
= mputprintf(target
->functions
.control
,
2103 "TTCN_Runtime::begin_controlpart(\"%s\");\n", module_dispname
);
2104 if (debugger_active
) {
2105 target
->functions
.control
= mputprintf(target
->functions
.control
,
2106 "charstring_list no_params = NULL_VALUE;\n"
2107 "TTCN3_Debug_Function debug_scope(NULL, \"control\", \"%s\", no_params, no_params, NULL);\n"
2108 "debug_scope.initial_snapshot();\n", module_dispname
);
2110 target
->functions
.control
=
2111 block
->generate_code(target
->functions
.control
);
2112 target
->functions
.control
= mputstr(target
->functions
.control
,
2113 "TTCN_Runtime::end_controlpart();\n");
2116 void ControlPart::set_with_attr(MultiWithAttrib
* p_attrib
)
2118 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2119 w_attrib_path
->set_with_attr(p_attrib
);
2122 WithAttribPath
* ControlPart::get_attrib_path()
2124 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2125 return w_attrib_path
;
2128 void ControlPart::set_parent_path(WithAttribPath
* p_path
)
2130 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2131 w_attrib_path
->set_parent(p_path
);
2132 block
->set_parent_path(w_attrib_path
);
2135 void ControlPart::dump(unsigned level
) const
2137 DEBUG(level
, "Control part");
2138 block
->dump(level
+ 1);
2139 if (w_attrib_path
) {
2140 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2142 DEBUG(level
+ 1, "Attributes:");
2143 attrib
->dump(level
+ 2);
2148 // =================================
2150 // =================================
2152 Module::Module(Identifier
*p_modid
)
2153 : Common::Module(MOD_TTCN
, p_modid
), language_spec(0), w_attrib_path(0),
2156 asss
= new Definitions();
2157 asss
->set_parent_scope(this);
2158 imp
= new Imports();
2159 imp
->set_my_mod(this);
2160 //modified_encodings = true; // Assume always true for TTCN modules
2165 delete language_spec
;
2167 for (size_t i
= 0; i
< group_v
.size(); i
++) delete group_v
[i
];
2171 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) delete friendmods_v
[i
];
2172 friendmods_v
.clear();
2174 for (size_t i
= 0; i
< runs_on_scopes
.size(); i
++)
2175 delete runs_on_scopes
[i
];
2176 runs_on_scopes
.clear();
2177 delete w_attrib_path
;
2180 void Module::add_group(Group
* p_group
)
2182 group_v
.add(p_group
);
2185 void Module::add_friendmod(FriendMod
*p_friendmod
)
2187 friendmods_v
.add(p_friendmod
);
2188 p_friendmod
->set_my_mod(this);
2191 Module
*Module::clone() const
2193 FATAL_ERROR("Ttcn::Module::clone()");
2196 Common::Assignment
*Module::importAssignment(const Identifier
& p_modid
,
2197 const Identifier
& p_id
) const
2199 if (asss
->has_local_ass_withId(p_id
)) {
2200 Common::Assignment
* ass
= asss
->get_local_ass_byId(p_id
);
2201 if (!ass
) FATAL_ERROR("Ttcn::Module::importAssignment()");
2203 switch(ass
->get_visibility()) {
2205 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) {
2206 if (friendmods_v
[i
]->get_modid() == p_modid
) return ass
;
2214 FATAL_ERROR("Ttcn::Module::importAssignment()");
2220 void Module::set_fullname(const string
& p_fullname
)
2222 Node::set_fullname(p_fullname
);
2223 asss
->set_fullname(p_fullname
);
2224 if (controlpart
) controlpart
->set_fullname(p_fullname
+ ".control");
2225 for(size_t i
= 0; i
< group_v
.size(); i
++)
2227 group_v
[i
]->set_fullname(p_fullname
+ ".<group " + Int2string(i
) + ">");
2229 if (w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
2233 Common::Assignments
*Module::get_scope_asss()
2238 bool Module::has_imported_ass_withId(const Identifier
& p_id
)
2240 const Location
*loc
= NULL
;
2241 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2242 const ImpMod
* im
= imp
->get_impmod(i
);
2243 //TODO use a reference instead of an identifier
2244 if(im
->has_imported_def(*modid
, p_id
, loc
)) return true;
2249 Common::Assignment
* Module::get_ass_bySRef(Ref_simple
*p_ref
)
2251 const Identifier
*r_modid
= p_ref
->get_modid();
2252 const Identifier
*r_id
= p_ref
->get_id();
2254 // the reference contains a module name
2255 if (r_modid
->get_name() != modid
->get_name()) {
2256 // the reference points to another module
2257 bool has_impmod_with_name
= false;
2258 Common::Assignment
* result_ass
= NULL
;
2259 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2260 const ImpMod
* im
= imp
->get_impmod(i
);
2261 const Identifier
& im_id
= im
->get_modid();
2262 const string
& im_name
= im_id
.get_name();
2263 if (r_modid
->get_name() == im_name
) {
2264 has_impmod_with_name
= true;
2265 vector
<ImpMod
> tempusedImpMods
;
2266 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2267 Common::Assignment
*t_ass
= im
->get_imported_def(*modid
, *r_id
, p_ref
, referencechain
, tempusedImpMods
);
2268 referencechain
->reset();
2269 delete referencechain
;
2271 if (t_ass
!= NULL
) {
2272 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(im
->get_mod());
2273 if (!ttcn_m
->is_visible(*modid
, t_ass
->get_visibility())) {
2277 if (t_ass
!= NULL
) {
2278 if (result_ass
== NULL
) {
2280 } else if(result_ass
!= t_ass
) {
2282 "It is not possible to resolve the reference unambiguously"
2283 ", as it can be resolved to `%s' and to `%s'",
2284 result_ass
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
2288 tempusedImpMods
.clear();
2291 if (result_ass
) return result_ass
;
2293 if (has_impmod_with_name
) {
2294 p_ref
->error("There is no definition with name `%s' visible from "
2295 "module `%s'", r_id
->get_dispname().c_str(),
2296 r_modid
->get_dispname().c_str());
2298 if (modules
->has_mod_withId(*r_modid
)) {
2299 Common::Module
*m
= modules
->get_mod_byId(*r_modid
);
2300 if (m
->get_asss()->has_ass_withId(*r_id
)) {
2301 p_ref
->error("Definition with name `%s' is not imported from "
2302 "module `%s'", r_id
->get_dispname().c_str(),
2303 r_modid
->get_dispname().c_str());
2305 p_ref
->error("There is no definition with name `%s' in "
2306 "module `%s'", r_id
->get_dispname().c_str(),
2307 r_modid
->get_dispname().c_str());
2310 p_ref
->error("There is no module with name `%s'",
2311 r_modid
->get_dispname().c_str());
2316 // the reference points to the own module
2317 if (asss
->has_local_ass_withId(*r_id
)) {
2318 return asss
->get_local_ass_byId(*r_id
);
2320 p_ref
->error("There is no definition with name `%s' in "
2321 "module `%s'", r_id
->get_dispname().c_str(),
2322 r_modid
->get_dispname().c_str());
2326 // no module name is given in the reference
2327 if (asss
->has_local_ass_withId(*r_id
)) {
2328 return asss
->get_local_ass_byId(*r_id
);
2330 // the reference was not found locally -> look at the import list
2331 Common::Assignment
*t_result
= NULL
, *t_ass
= NULL
;
2332 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2333 const ImpMod
* im
= imp
->get_impmod(i
);
2335 vector
<ImpMod
> tempusedImpMods
;
2336 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2337 t_ass
= im
->get_imported_def(*modid
, *r_id
, p_ref
, referencechain
, tempusedImpMods
);
2338 referencechain
->reset();
2340 delete referencechain
;
2341 if (t_ass
!= NULL
) {
2342 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(im
->get_mod());
2343 if (!ttcn_m
->is_visible(*modid
, t_ass
->get_visibility())) {
2347 if (t_ass
!= NULL
) {
2348 if (t_result
== NULL
) {
2350 } else if(t_result
!= t_ass
) {
2352 "It is not possible to resolve the reference unambiguously"
2353 ", as it can be resolved to `%s' and to `%s'",
2354 t_result
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
2358 tempusedImpMods
.clear();
2361 if (t_result
) return t_result
;
2363 p_ref
->error("There is no local or imported definition with name `%s'"
2364 ,r_id
->get_dispname().c_str());
2370 bool Module::is_valid_moduleid(const Identifier
& p_id
)
2372 // The identifier represents the current module
2373 if (p_id
.get_name() == modid
->get_name()) return true;
2374 // The identifier represents a module imported in the current module
2375 if(imp
->has_impmod_withId(p_id
)) return true;
2379 Common::Assignments
*Module::get_asss()
2384 bool Module::exports_sym(const Identifier
&)
2386 FATAL_ERROR("Ttcn::Module::exports_sym()");
2390 Type
*Module::get_address_type()
2392 Identifier
address_id(Identifier::ID_TTCN
, string("address"));
2393 // return NULL if address type is not defined
2394 if (!asss
->has_local_ass_withId(address_id
)) return 0;
2395 Common::Assignment
*t_ass
= asss
->get_local_ass_byId(address_id
);
2396 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
)
2397 FATAL_ERROR("Module::get_address_type(): address is not a type");
2398 return t_ass
->get_Type();
2401 void Module::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
2403 if (imp_checked
) return;
2404 const string
& module_name
= modid
->get_dispname();
2406 Error_Context backup
;
2407 Error_Context
cntxt(this, "In TTCN-3 module `%s'", module_name
.c_str());
2408 imp
->chk_imp(refch
, moduleStack
);
2411 collect_visible_mods();
2416 DEBUG(1, "Checking TTCN-3 module `%s'", modid
->get_dispname().c_str());
2417 Error_Context
cntxt(this, "In TTCN-3 module `%s'",
2418 modid
->get_dispname().c_str());
2419 if (w_attrib_path
) {
2420 w_attrib_path
->chk_global_attrib();
2421 w_attrib_path
->chk_no_qualif();
2423 // Check "extension" attributes in the module's "with" statement
2424 MultiWithAttrib
*multi
= w_attrib_path
->get_with_attr();
2425 if (multi
) for (size_t i
= 0; i
< multi
->get_nof_elements(); ++i
) {
2426 const SingleWithAttrib
*single
= multi
->get_element(i
);
2427 if (single
->get_attribKeyword() != SingleWithAttrib::AT_EXTENSION
) continue;
2428 // Parse the extension attribute
2429 // We circumvent parse_extattributes() in coding_attrib_p.y because
2430 // it processes all attributes in the "with" statement and
2431 // doesn't allow the removal on a case-by-case basis.
2433 init_coding_attrib_lex(single
->get_attribSpec());
2434 int result
= coding_attrib_parse();// 0=OK, 1=error, 2=out of memory
2435 cleanup_coding_attrib_lex();
2442 const size_t num_parsed
= extatrs
->size();
2443 for (size_t a
= 0; a
< num_parsed
; ++a
) {
2444 Ttcn::ExtensionAttribute
& ex
= extatrs
->get(0);
2446 switch (ex
.get_type()) {
2447 case Ttcn::ExtensionAttribute::VERSION_TEMPLATE
:
2448 case Ttcn::ExtensionAttribute::VERSION
: {
2449 char* act_product_number
;
2450 unsigned int act_suffix
, act_rel
, act_patch
, act_build
;
2452 (void)ex
.get_id(act_product_number
, act_suffix
, act_rel
, act_patch
, act_build
, extra_junk
);
2454 if (release
!= UINT_MAX
) {
2455 ex
.error("Duplicate 'version' attribute");
2458 product_number
= mcopystr(act_product_number
);
2459 suffix
= act_suffix
;
2463 extra
= mcopystr(extra_junk
);
2465 // Avoid propagating the attribute needlessly
2466 multi
->delete_element(i
--);
2470 case Ttcn::ExtensionAttribute::REQUIRES
: {
2471 // Imports have already been checked
2472 char* exp_product_number
;
2473 unsigned int exp_suffix
, exp_rel
, exp_patch
, exp_build
;
2475 Common::Identifier
*req_id
= ex
.get_id(exp_product_number
,
2476 exp_suffix
, exp_rel
, exp_patch
, exp_build
, exp_extra
);
2478 if (imp
->has_impmod_withId(*req_id
)) {
2479 Common::Module
* m
= modules
->get_mod_byId(*req_id
);
2480 if (m
->product_number
== NULL
&& exp_product_number
!= NULL
) {
2481 ex
.error("Module '%s' requires module '%s' of product %s"
2482 ", but it is not specified",
2483 this->modid
->get_dispname().c_str(), req_id
->get_dispname().c_str(),
2484 exp_product_number
);
2485 multi
->delete_element(i
--);
2488 } else if (exp_product_number
== NULL
&&
2489 m
->product_number
!= NULL
&& strcmp(m
->product_number
, "") > 0){
2490 ex
.warning("Module '%s' requires module '%s' of any product"
2491 ", while it specifies '%s'",
2492 this->modid
->get_dispname().c_str(),
2493 req_id
->get_dispname().c_str(), m
->product_number
);
2494 } else if (m
->product_number
!= NULL
&& exp_product_number
!= NULL
2495 && 0 != strcmp(m
->product_number
, exp_product_number
)) {
2496 char *req_product_identifier
=
2497 get_product_identifier(exp_product_number
,
2498 exp_suffix
, exp_rel
, exp_patch
, exp_build
);
2499 char *mod_product_identifier
=
2500 get_product_identifier(m
->product_number
,
2501 m
->suffix
, m
->release
, m
->patch
, m
->build
);
2503 ex
.error("Module '%s' requires version %s of module"
2504 " '%s', but only %s is available",
2505 this->modid
->get_dispname().c_str(), req_product_identifier
,
2506 req_id
->get_dispname().c_str(), mod_product_identifier
);
2507 Free(req_product_identifier
);
2508 Free(mod_product_identifier
);
2509 multi
->delete_element(i
--);
2513 // different suffixes are always incompatible
2514 // unless the special version number is used
2515 if (m
->suffix
!= exp_suffix
&& (m
->suffix
!= UINT_MAX
)) {
2516 char *req_product_identifier
=
2517 get_product_identifier(exp_product_number
,exp_suffix
, exp_rel
, exp_patch
, exp_build
);
2518 char *mod_product_identifier
=
2519 get_product_identifier(m
->product_number
,
2520 m
->suffix
, m
->release
, m
->patch
, m
->build
);
2522 ex
.error("Module '%s' requires version %s of module"
2523 " '%s', but only %s is available",
2524 this->modid
->get_dispname().c_str(), req_product_identifier
,
2525 req_id
->get_dispname().c_str(), mod_product_identifier
);
2526 Free(req_product_identifier
);
2527 Free(mod_product_identifier
);
2528 multi
->delete_element(i
--);
2532 if ( m
->release
< exp_rel
2533 ||(m
->release
== exp_rel
&& m
->patch
< exp_patch
)
2534 ||(m
->patch
== exp_patch
&& m
->build
< exp_build
)) {
2535 char *mod_bld_str
= buildstr(m
->build
);
2536 char *exp_bld_str
= buildstr(exp_build
);
2537 if (mod_bld_str
==0 || exp_bld_str
==0) FATAL_ERROR(
2538 "Ttcn::Module::chk() invalid build number");
2539 ex
.error("Module '%s' requires version R%u%c%s of module"
2540 " '%s', but only R%u%c%s is available",
2541 this->modid
->get_dispname().c_str(),
2542 exp_rel
, eri(exp_patch
), exp_bld_str
,
2543 req_id
->get_dispname().c_str(),
2544 m
->release
, eri(m
->patch
), mod_bld_str
);
2549 single
->error("No imported module named '%s'",
2550 req_id
->get_dispname().c_str());
2552 multi
->delete_element(i
--);
2556 case Ttcn::ExtensionAttribute::REQ_TITAN
: {
2557 char* exp_product_number
;
2558 unsigned int exp_suffix
, exp_minor
, exp_patch
, exp_build
;
2560 (void)ex
.get_id(exp_product_number
, exp_suffix
, exp_minor
, exp_patch
, exp_build
, exp_extra
);
2561 if (exp_product_number
!= NULL
&& strcmp(exp_product_number
,"CRL 113 200") != 0) {
2562 ex
.error("This module needs to be compiled with TITAN, but "
2563 " product number %s is not TITAN"
2564 , exp_product_number
);
2566 if (0 == exp_suffix
) {
2567 exp_suffix
= 1; // previous version number format did not list the suffix part
2569 // TTCN3_MAJOR is always 1
2570 int expected_version
= exp_suffix
* 1000000
2571 + exp_minor
* 10000 + exp_patch
* 100 + exp_build
;
2572 if (expected_version
> TTCN3_VERSION_MONOTONE
) {
2573 char *exp_product_identifier
=
2574 get_product_identifier(exp_product_number
, exp_suffix
, exp_minor
, exp_patch
, exp_build
);
2575 ex
.error("This module needs to be compiled with TITAN version"
2576 " %s or higher; version %s detected"
2577 , exp_product_identifier
, PRODUCT_NUMBER
);
2578 Free(exp_product_identifier
);
2580 multi
->delete_element(i
--);
2583 case Ttcn::ExtensionAttribute::PRINTING
: {
2584 ex
.error("Attribute 'printing' not allowed at module level");
2585 multi
->delete_element(i
--);
2591 // Let everything else propagate into the module.
2592 // Extension attributes in the module's "with" statement
2593 // may be impractical, but not outright erroneous.
2604 if (controlpart
) controlpart
->chk();
2605 if (control_ns
&& !*control_ns
) { // set but empty
2606 error("Invalid URI value for control namespace");
2608 if (control_ns_prefix
&& !*control_ns_prefix
) { // set but empty
2609 error("Empty NCName for the control namespace prefix is not allowed");
2611 // TODO proper URI and NCName validation
2614 void Module::chk_friends()
2616 map
<string
, FriendMod
> friends_m
;
2618 for(size_t i
= 0; i
< friendmods_v
.size(); i
++)
2620 FriendMod
* temp_friend
= friendmods_v
[i
];
2621 const Identifier
& friend_id
= temp_friend
->get_modid();
2622 const string
& friend_name
= friend_id
.get_name();
2623 if(friends_m
.has_key(friend_name
))
2625 temp_friend
->error("Duplicate friend module with name `%s'",
2626 friend_id
.get_dispname().c_str());
2627 friends_m
[friend_name
]->note("Friend module `%s' is already defined here",
2628 friend_id
.get_dispname().c_str());
2630 friends_m
.add(friend_name
, temp_friend
);
2633 friendmods_v
[i
]->chk();
2640 void Module::chk_groups()
2642 map
<string
,Common::Assignment
> ass_m
;
2644 for(size_t i
= 0; i
< asss
->get_nof_asss(); i
++)
2646 Common::Assignment
*temp_ass
= asss
->get_ass_byIndex(i
);
2647 if(!temp_ass
->get_parent_group())
2649 const string
& ass_name
= temp_ass
->get_id().get_name();
2650 if (!ass_m
.has_key(ass_name
)) ass_m
.add(ass_name
, temp_ass
);
2654 for(size_t i
= 0; i
< group_v
.size(); i
++)
2656 const Group
* group
= group_v
[i
];
2657 const Identifier
& group_id
= group
->get_id();
2658 const string
& group_name
= group_id
.get_name();
2659 if(ass_m
.has_key(group_name
))
2661 group
->error("Group name `%s' clashes with a definition",
2662 group_id
.get_dispname().c_str());
2663 ass_m
[group_name
]->note("Definition of `%s' is here",
2664 group_id
.get_dispname().c_str());
2666 if(group_m
.has_key(group_name
))
2668 group
->error("Duplicate group with name `%s'",
2669 group_id
.get_dispname().c_str());
2670 group_m
[group_name
]->note("Group `%s' is already defined here",
2671 group_id
.get_dispname().c_str());
2673 group_m
.add(group_name
,group_v
[i
]);
2679 for(size_t i
= 0; i
< group_v
.size(); i
++)
2685 void Module::get_imported_mods(module_set_t
& p_imported_mods
)
2687 imp
->get_imported_mods(p_imported_mods
);
2690 void Module::generate_code_internal(CodeGenHelper
& cgh
) {
2691 imp
->generate_code(cgh
);
2692 asss
->generate_code(cgh
);
2694 controlpart
->generate_code(cgh
.get_outputstruct(modid
->get_ttcnname()), this);
2697 RunsOnScope
*Module::get_runs_on_scope(Type
*comptype
)
2699 RunsOnScope
*ret_val
= new RunsOnScope(comptype
);
2700 runs_on_scopes
.add(ret_val
);
2701 ret_val
->set_parent_scope(asss
);
2702 ret_val
->chk_uniq();
2707 void Module::dump(unsigned level
) const
2709 DEBUG(level
, "TTCN-3 module: %s", modid
->get_dispname().c_str());
2711 if(imp
) imp
->dump(level
);
2712 if(asss
) asss
->dump(level
);
2714 for(size_t i
= 0; i
< group_v
.size(); i
++)
2716 group_v
[i
]->dump(level
);
2719 if(controlpart
) controlpart
->dump(level
);
2721 if (w_attrib_path
) {
2722 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2724 DEBUG(level
, "Module Attributes:");
2725 attrib
->dump(level
+ 1);
2730 void Module::set_language_spec(const char *p_language_spec
)
2732 if (language_spec
) FATAL_ERROR("Module::set_language_spec()");
2733 if (p_language_spec
) language_spec
= new string(p_language_spec
);
2736 void Module::add_ass(Definition
* p_ass
)
2738 asss
->add_ass(p_ass
);
2741 void Module::add_impmod(ImpMod
*p_impmod
)
2743 imp
->add_impmod(p_impmod
);
2746 void Module::add_controlpart(ControlPart
* p_controlpart
)
2748 if (!p_controlpart
|| controlpart
) FATAL_ERROR("Module::add_controlpart()");
2749 controlpart
= p_controlpart
;
2750 controlpart
->set_my_scope(asss
);
2753 void Module::set_with_attr(MultiWithAttrib
* p_attrib
)
2755 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2756 w_attrib_path
->set_with_attr(p_attrib
);
2759 WithAttribPath
* Module::get_attrib_path()
2761 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2762 return w_attrib_path
;
2765 void Module::set_parent_path(WithAttribPath
* p_path
)
2767 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2768 w_attrib_path
->set_parent(p_path
);
2771 bool Module::is_visible(const Identifier
& id
, visibility_t visibility
){
2773 if (visibility
== PUBLIC
) {
2776 if (visibility
== FRIEND
) {
2777 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) {
2778 if (friendmods_v
[i
]->get_modid() == id
) {
2786 void Module::generate_json_schema(JSON_Tokenizer
& json
, map
<Type
*, JSON_Tokenizer
>& json_refs
)
2788 // add a new property for this module
2789 json
.put_next_token(JSON_TOKEN_NAME
, modid
->get_ttcnname().c_str());
2791 // add type definitions into an object
2792 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2794 // cycle through each type, generate schema segment and reference when needed
2795 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2796 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2798 Type
* t
= def
->get_Type();
2799 if (t
->has_encoding(Type::CT_JSON
)) {
2800 // insert type's schema segment
2801 t
->generate_json_schema(json
, false, false);
2803 if (json_refs_for_all_types
&& !json_refs
.has_key(t
)) {
2804 // create JSON schema reference for the type
2805 JSON_Tokenizer
* json_ref
= new JSON_Tokenizer
;
2806 json_refs
.add(t
, json_ref
);
2807 t
->generate_json_schema_ref(*json_ref
);
2813 // end of type definitions
2814 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2816 // insert function data
2817 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2818 Def_ExtFunction
* def
= dynamic_cast<Def_ExtFunction
*>(asss
->get_ass_byIndex(i
));
2820 def
->generate_json_schema_ref(json_refs
);
2825 void Module::generate_debugger_init(output_struct
* output
)
2827 static boolean first
= TRUE
;
2828 // create the initializer function
2829 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2830 "\n/* Initializing the TTCN-3 debugger */\n"
2831 "void init_ttcn3_debugger()\n"
2833 "%s", first
? " ttcn3_debugger.activate();\n" : "");
2836 // initialize global scope and variables (including imported variables)
2837 char* str_glob
= generate_debugger_global_vars(NULL
, this);
2838 for (int i
= 0; i
< imp
->get_imports_size(); ++i
) {
2839 str_glob
= imp
->get_impmod(i
)->get_mod()->generate_debugger_global_vars(str_glob
, this);
2841 if (str_glob
!= NULL
) {
2842 // only add the global scope if it actually has variables
2843 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2844 " /* global variables */\n"
2845 " TTCN3_Debug_Scope* global_scope = ttcn3_debugger.add_global_scope(\"%s\");\n"
2847 get_modid().get_dispname().c_str(), str_glob
);
2851 // initialize components' scopes and their variables
2852 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2853 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2855 Type
* comp_type
= def
->get_Type();
2856 if (comp_type
->get_typetype() == Type::T_COMPONENT
) {
2857 char* str_comp
= NULL
;
2858 ComponentTypeBody
* comp_body
= comp_type
->get_CompBody();
2859 for (size_t j
= 0; j
< comp_body
->get_nof_asss(); ++j
) {
2860 str_comp
= generate_code_debugger_add_var(str_comp
, comp_body
->get_ass_byIndex(j
),
2861 this, comp_type
->get_dispname().c_str());
2863 if (str_comp
!= NULL
) {
2864 // only add the component if it actually has variables
2865 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2866 " /* variables of component %s */\n"
2867 " TTCN3_Debug_Scope* %s_scope = ttcn3_debugger.add_component_scope(\"%s\");\n"
2869 , comp_type
->get_dispname().c_str(), comp_type
->get_dispname().c_str()
2870 , comp_type
->get_dispname().c_str(), str_comp
);
2877 // close the initializer function
2878 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, "}\n");
2881 char* Module::generate_debugger_global_vars(char* str
, Common::Module
* current_mod
)
2883 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2884 Common::Assignment
* ass
= asss
->get_ass_byIndex(i
);
2885 switch (ass
->get_asstype()) {
2886 case Common::Assignment::A_TEMPLATE
:
2887 if (ass
->get_FormalParList() != NULL
) {
2888 // don't add parameterized templates, since they are functions in C++
2891 // else fall through
2892 case Common::Assignment::A_CONST
:
2893 case Common::Assignment::A_MODULEPAR
:
2894 case Common::Assignment::A_MODULEPAR_TEMP
:
2895 str
= generate_code_debugger_add_var(str
, ass
, current_mod
, "global");
2897 case Common::Assignment::A_EXT_CONST
: {
2898 Def_ExtConst
* def
= dynamic_cast<Def_ExtConst
*>(ass
);
2900 FATAL_ERROR("Module::generate_debugger_global_vars");
2902 if (def
->is_used()) {
2903 str
= generate_code_debugger_add_var(str
, ass
, current_mod
, "global");
2913 void Module::generate_debugger_functions(output_struct
*output
)
2915 char* print_str
= NULL
;
2916 char* overwrite_str
= NULL
;
2917 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2918 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2920 Type
* t
= def
->get_Type();
2921 if (!t
->is_ref() && t
->get_typetype() != Type::T_COMPONENT
&&
2922 t
->get_typetype() != Type::T_PORT
) {
2923 // don't generate code for subtypes
2924 if (t
->get_typetype() != Type::T_SIGNATURE
) {
2925 print_str
= mputprintf(print_str
,
2926 " %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
2927 " ((const %s*)ptr)->log();\n"
2929 , (print_str
!= NULL
) ? "else " : ""
2930 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2931 overwrite_str
= mputprintf(overwrite_str
,
2932 " %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
2933 " ((%s*)p_var.value)->set_param(p_new_value);\n"
2935 , (overwrite_str
!= NULL
) ? "else " : ""
2936 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2938 print_str
= mputprintf(print_str
,
2939 " %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
2940 " ((const %s_template*)ptr)->log();\n"
2942 , (print_str
!= NULL
) ? "else " : ""
2943 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2944 if (t
->get_typetype() != Type::T_SIGNATURE
) {
2945 overwrite_str
= mputprintf(overwrite_str
,
2946 " %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
2947 " ((%s_template*)p_var.value)->set_param(p_new_value);\n"
2949 , (overwrite_str
!= NULL
) ? "else " : ""
2950 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2955 if (print_str
!= NULL
) {
2956 // don't generate an empty printing function
2957 output
->header
.class_defs
= mputprintf(output
->header
.class_defs
,
2958 "/* Debugger printing and overwriting functions for types declared in this module */\n\n"
2959 "extern CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var);\n",
2960 get_modid().get_ttcnname().c_str());
2961 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2962 "\n/* Debugger printing function for types declared in this module */\n"
2963 "CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var)\n"
2965 " const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;\n"
2966 " TTCN_Logger::begin_event_log2str();\n"
2969 " TTCN_Logger::log_event_str(\"<unrecognized value or template>\");\n"
2971 " return TTCN_Logger::end_event_log2str();\n"
2972 "}\n", get_modid().get_ttcnname().c_str(), print_str
);
2975 if (overwrite_str
!= NULL
) {
2976 // don't generate an empty overwriting function
2977 output
->header
.class_defs
= mputprintf(output
->header
.class_defs
,
2978 "extern boolean set_var_%s(TTCN3_Debugger::variable_t& p_var, Module_Param& p_new_value);\n",
2979 get_modid().get_ttcnname().c_str());
2980 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2981 "\n/* Debugger overwriting function for types declared in this module */\n"
2982 "boolean set_var_%s(TTCN3_Debugger::variable_t& p_var, Module_Param& p_new_value)\n"
2989 "}\n", get_modid().get_ttcnname().c_str(), overwrite_str
);
2990 Free(overwrite_str
);
2994 // =================================
2996 // =================================
2998 string
Definition::get_genname() const
3000 if (!genname
.empty()) return genname
;
3001 else return id
->get_name();
3004 namedbool
Definition::has_implicit_omit_attr() const {
3005 if (w_attrib_path
) {
3006 const vector
<SingleWithAttrib
>& real_attribs
=
3007 w_attrib_path
->get_real_attrib();
3008 for (size_t in
= real_attribs
.size(); in
> 0; in
--) {
3009 if (SingleWithAttrib::AT_OPTIONAL
==
3010 real_attribs
[in
-1]->get_attribKeyword()) {
3011 if ("implicit omit" ==
3012 real_attribs
[in
-1]->get_attribSpec().get_spec()) {
3013 return IMPLICIT_OMIT
;
3014 } else if ("explicit omit" ==
3015 real_attribs
[in
-1]->get_attribSpec().get_spec()) {
3016 return NOT_IMPLICIT_OMIT
;
3017 } // error reporting for other values is in chk_global_attrib
3021 return NOT_IMPLICIT_OMIT
;
3024 Definition::~Definition()
3026 delete w_attrib_path
;
3027 delete erroneous_attrs
;
3030 void Definition::set_fullname(const string
& p_fullname
)
3032 Common::Assignment::set_fullname(p_fullname
);
3033 if (w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
3034 if (erroneous_attrs
) erroneous_attrs
->set_fullname(p_fullname
+".<erroneous_attributes>");
3037 bool Definition::is_local() const
3039 if (!my_scope
) FATAL_ERROR("Definition::is_local()");
3040 for (Scope
*scope
= my_scope
; scope
; scope
= scope
->get_parent_scope()) {
3041 if (dynamic_cast<StatementBlock
*>(scope
)) return true;
3046 bool Definition::chk_identical(Definition
*)
3048 FATAL_ERROR("Definition::chk_identical()");
3052 void Definition::chk_erroneous_attr()
3054 if (!w_attrib_path
) return;
3055 const Ttcn::MultiWithAttrib
* attribs
= w_attrib_path
->get_local_attrib();
3056 if (!attribs
) return;
3057 for (size_t i
= 0; i
< attribs
->get_nof_elements(); i
++) {
3058 const Ttcn::SingleWithAttrib
* act_attr
= attribs
->get_element(i
);
3059 if (act_attr
->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_ERRONEOUS
) {
3060 if (!use_runtime_2
) {
3061 error("`erroneous' attributes can be used only with the Function Test Runtime");
3062 note("If you need negative testing use the -R flag when generating the makefile");
3065 size_t nof_qualifiers
= act_attr
->get_attribQualifiers() ? act_attr
->get_attribQualifiers()->get_nof_qualifiers() : 0;
3066 dynamic_array
<Type
*> refd_type_array(nof_qualifiers
); // only the qualifiers pointing to existing fields will be added to erroneous_attrs objects
3067 if (nof_qualifiers
==0) {
3068 act_attr
->error("At least one qualifier must be specified for the `erroneous' attribute");
3070 // check if qualifiers point to existing fields
3071 for (size_t qi
=0; qi
<nof_qualifiers
; qi
++) {
3072 Qualifier
* act_qual
= const_cast<Qualifier
*>(act_attr
->get_attribQualifiers()->get_qualifier(qi
));
3073 act_qual
->set_my_scope(get_my_scope());
3074 Type
* field_type
= get_Type()->get_field_type(act_qual
, Type::EXPECTED_CONSTANT
);
3076 dynamic_array
<size_t> subrefs_array
;
3077 dynamic_array
<Type
*> type_array
;
3078 bool valid_indexes
= get_Type()->get_subrefs_as_array(act_qual
, subrefs_array
, type_array
);
3079 if (!valid_indexes
) field_type
= NULL
;
3080 if (act_qual
->refers_to_string_element()) {
3081 act_qual
->error("Reference to a string element cannot be used in this context");
3085 refd_type_array
.add(field_type
);
3088 // parse the attr. spec.
3089 ErroneousAttributeSpec
* err_attr_spec
= ttcn3_parse_erroneous_attr_spec_string(
3090 act_attr
->get_attribSpec().get_spec().c_str(), act_attr
->get_attribSpec());
3091 if (err_attr_spec
) {
3092 if (!erroneous_attrs
) erroneous_attrs
= new ErroneousAttributes(get_Type());
3093 // attr.spec will be owned by erroneous_attrs object
3094 erroneous_attrs
->add_spec(err_attr_spec
);
3095 err_attr_spec
->set_fullname(get_fullname());
3096 err_attr_spec
->set_my_scope(get_my_scope());
3097 err_attr_spec
->chk();
3098 // create qualifier - err.attr.spec. pairs
3099 for (size_t qi
=0; qi
<nof_qualifiers
; qi
++) {
3100 if (refd_type_array
[qi
] && (err_attr_spec
->get_indicator()!=ErroneousAttributeSpec::I_INVALID
)) {
3101 erroneous_attrs
->add_pair(act_attr
->get_attribQualifiers()->get_qualifier(qi
), err_attr_spec
);
3107 if (erroneous_attrs
) erroneous_attrs
->chk();
3110 char* Definition::generate_code_str(char *str
)
3112 FATAL_ERROR("Definition::generate_code_str()");
3116 void Definition::ilt_generate_code(ILT
*)
3118 FATAL_ERROR("Definition::ilt_generate_code()");
3121 char *Definition::generate_code_init_comp(char *str
, Definition
*)
3123 FATAL_ERROR("Definition::generate_code_init_comp()");
3127 void Definition::set_with_attr(MultiWithAttrib
* p_attrib
)
3129 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3130 w_attrib_path
->set_with_attr(p_attrib
);
3133 WithAttribPath
* Definition::get_attrib_path()
3135 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3136 return w_attrib_path
;
3139 void Definition::set_parent_path(WithAttribPath
* p_path
)
3141 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3142 w_attrib_path
->set_parent(p_path
);
3145 void Definition::set_parent_group(Group
* p_group
)
3147 if(parentgroup
) // there would be a leak!
3148 FATAL_ERROR("Definition::set_parent_group()");
3149 parentgroup
= p_group
;
3152 Group
* Definition::get_parent_group()
3157 void Definition::dump_internal(unsigned level
) const
3159 DEBUG(level
, "Move along, nothing to see here");
3162 void Definition::dump(unsigned level
) const
3164 dump_internal(level
);
3165 if (w_attrib_path
) {
3166 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
3168 DEBUG(level
+ 1, "Definition Attributes:");
3169 attrib
->dump(level
+ 2);
3172 if (erroneous_attrs
) erroneous_attrs
->dump(level
+1);
3175 // =================================
3177 // =================================
3179 Def_Type::Def_Type(Identifier
*p_id
, Type
*p_type
)
3180 : Definition(A_TYPE
, p_id
), type(p_type
)
3182 if(!p_type
) FATAL_ERROR("Ttcn::Def_Type::Def_Type()");
3183 type
->set_ownertype(Type::OT_TYPE_DEF
, this);
3186 Def_Type::~Def_Type()
3191 Def_Type
*Def_Type::clone() const
3193 FATAL_ERROR("Def_Type::clone");
3196 void Def_Type::set_fullname(const string
& p_fullname
)
3198 Definition::set_fullname(p_fullname
);
3199 type
->set_fullname(p_fullname
);
3202 void Def_Type::set_my_scope(Scope
*p_scope
)
3204 bridgeScope
.set_parent_scope(p_scope
);
3205 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
3207 Definition::set_my_scope(&bridgeScope
);
3208 type
->set_my_scope(&bridgeScope
);
3212 Setting
*Def_Type::get_Setting()
3217 Type
*Def_Type::get_Type()
3223 void Def_Type::chk()
3225 if (checked
) return;
3227 Error_Context
cntxt(this, "In %s definition `%s'",
3228 type
->get_typetype() == Type::T_SIGNATURE
? "signature" : "type",
3229 id
->get_dispname().c_str());
3230 type
->set_genname(get_genname());
3231 if (!semantic_check_only
&& type
->get_typetype() == Type::T_COMPONENT
) {
3232 // the prefix of embedded definitions must be set before the checking
3233 type
->get_CompBody()->set_genname(get_genname() + "_component_");
3236 while (w_attrib_path
) { // not a loop, but we can _break_ out of it
3237 w_attrib_path
->chk_global_attrib();
3238 w_attrib_path
->chk_no_qualif();
3239 if (type
->get_typetype() != Type::T_ANYTYPE
) break;
3240 // This is the anytype; it must be empty (we're about to add the fields)
3241 if (type
->get_nof_comps() > 0) FATAL_ERROR("Def_Type::chk");
3243 Ttcn::ExtensionAttributes
*extattrs
= parse_extattributes(w_attrib_path
);
3244 if (extattrs
== 0) break; // NULL means parsing error
3246 size_t num_atrs
= extattrs
->size();
3247 for (size_t k
= 0; k
< num_atrs
; ++k
) {
3248 ExtensionAttribute
&ea
= extattrs
->get(k
);
3249 switch (ea
.get_type()) {
3250 case ExtensionAttribute::ANYTYPELIST
: {
3251 Types
*anytypes
= ea
.get_types();
3252 // List of types to be converted into fields for the anytype.
3253 // Make sure scope is set on all types in the list.
3254 anytypes
->set_my_scope(get_my_scope());
3256 // Convert the list of types into field names for the anytype
3257 for (size_t i
=0; i
< anytypes
->get_nof_types(); ++i
) {
3258 Type
*t
= anytypes
->extract_type_byIndex(i
);
3259 // we are now the owner of the Type.
3260 if (t
->get_typetype()==Type::T_ERROR
) { // should we give up?
3266 const char* btn
= Type::get_typename_builtin(t
->get_typetype());
3270 else if (t
->get_typetype() == Type::T_REFD
) {
3271 // Extract the identifier
3272 Common::Reference
*ref
= t
->get_Reference();
3273 Ttcn::Reference
*tref
= dynamic_cast<Ttcn::Reference
*>(ref
);
3274 if (!tref
) FATAL_ERROR("Def_Type::chk, wrong kind of reference");
3275 const Common::Identifier
*modid
= tref
->get_modid();
3277 ea
.error("Qualified name '%s' cannot be added to the anytype",
3278 tref
->get_dispname().c_str());
3282 field_name
= tref
->get_id()->get_ttcnname();
3285 // Can't happen here
3286 FATAL_ERROR("Unexpected type %d", t
->get_typetype());
3289 const string
& at_field
= anytype_field(field_name
);
3290 Identifier
*field_id
= new Identifier(Identifier::ID_TTCN
, at_field
);
3291 CompField
*cf
= new CompField(field_id
, t
, false, 0);
3292 cf
->set_location(ea
);
3293 cf
->set_fullname(get_fullname());
3299 w_attrib_path
->get_with_attr()->error("Type def can only have anytype");
3305 break; // do not loop
3308 // Now we can check the type
3310 type
->chk_constructor_name(*id
);
3311 if (id
->get_ttcnname() == "address") type
->chk_address();
3312 ReferenceChain
refch(type
, "While checking embedded recursions");
3313 type
->chk_recursions(refch
);
3315 if (type
->get_typetype()==Type::T_FUNCTION
3316 ||type
->get_typetype()==Type::T_ALTSTEP
3317 ||type
->get_typetype()==Type::T_TESTCASE
) {
3318 // TR 922. This is a function/altstep/testcase reference.
3319 // Set this definition as the definition for the formal parameters.
3320 type
->get_fat_parameters()->set_my_def(this);
3324 void Def_Type::generate_code(output_struct
*target
, bool)
3326 type
->generate_code(target
);
3327 if (type
->get_typetype() == Type::T_COMPONENT
) {
3328 // the C++ equivalents of embedded component element definitions must be
3329 // generated from outside Type::generate_code() because the function can
3330 // call itself recursively and create invalid (overlapped) initializer
3332 type
->get_CompBody()->generate_code(target
);
3336 void Def_Type::generate_code(CodeGenHelper
& cgh
) {
3337 type
->generate_code(cgh
.get_outputstruct(get_Type()));
3338 if (type
->get_typetype() == Type::T_COMPONENT
) {
3339 // the C++ equivalents of embedded component element definitions must be
3340 // generated from outside Type::generate_code() because the function can
3341 // call itself recursively and create invalid (overlapped) initializer
3343 type
->get_CompBody()->generate_code(cgh
.get_current_outputstruct());
3345 cgh
.finalize_generation(get_Type());
3349 void Def_Type::dump_internal(unsigned level
) const
3351 DEBUG(level
, "Type def: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3352 type
->dump(level
+ 1);
3355 void Def_Type::set_with_attr(MultiWithAttrib
* p_attrib
)
3357 if (!w_attrib_path
) {
3358 w_attrib_path
= new WithAttribPath();
3359 type
->set_parent_path(w_attrib_path
);
3361 type
->set_with_attr(p_attrib
);
3364 WithAttribPath
* Def_Type::get_attrib_path()
3366 if (!w_attrib_path
) {
3367 w_attrib_path
= new WithAttribPath();
3368 type
->set_parent_path(w_attrib_path
);
3370 return w_attrib_path
;
3373 void Def_Type::set_parent_path(WithAttribPath
* p_path
)
3375 if (!w_attrib_path
) {
3376 w_attrib_path
= new WithAttribPath();
3377 type
->set_parent_path(w_attrib_path
);
3379 w_attrib_path
->set_parent(p_path
);
3382 // =================================
3384 // =================================
3386 Def_Const::Def_Const(Identifier
*p_id
, Type
*p_type
, Value
*p_value
)
3387 : Definition(A_CONST
, p_id
)
3389 if (!p_type
|| !p_value
) FATAL_ERROR("Ttcn::Def_Const::Def_Const()");
3391 type
->set_ownertype(Type::OT_CONST_DEF
, this);
3393 value_under_check
=false;
3396 Def_Const::~Def_Const()
3402 Def_Const
*Def_Const::clone() const
3404 FATAL_ERROR("Def_Const::clone");
3407 void Def_Const::set_fullname(const string
& p_fullname
)
3409 Definition::set_fullname(p_fullname
);
3410 type
->set_fullname(p_fullname
+ ".<type>");
3411 value
->set_fullname(p_fullname
);
3414 void Def_Const::set_my_scope(Scope
*p_scope
)
3416 Definition::set_my_scope(p_scope
);
3417 type
->set_my_scope(p_scope
);
3418 value
->set_my_scope(p_scope
);
3421 Setting
*Def_Const::get_Setting()
3426 Type
*Def_Const::get_Type()
3433 Value
*Def_Const::get_Value()
3439 void Def_Const::chk()
3442 if (value_under_check
) {
3443 error("Circular reference in constant definition `%s'",
3444 id
->get_dispname().c_str());
3445 value_under_check
= false; // only report the error once for this definition
3449 Error_Context
cntxt(this, "In constant definition `%s'",
3450 id
->get_dispname().c_str());
3451 type
->set_genname(_T_
, get_genname());
3453 value
->set_my_governor(type
);
3454 type
->chk_this_value_ref(value
);
3456 if (w_attrib_path
) {
3457 w_attrib_path
->chk_global_attrib(true);
3458 switch (type
->get_type_refd_last()->get_typetype_ttcn3()) {
3461 case Type::T_CHOICE_T
:
3462 // These types may have qualified attributes
3464 case Type::T_SEQOF
: case Type::T_SETOF
:
3467 w_attrib_path
->chk_no_qualif();
3471 Type
*t
= type
->get_type_refd_last();
3472 switch (t
->get_typetype()) {
3474 error("Constant cannot be defined for port type `%s'",
3475 t
->get_fullname().c_str());
3477 case Type::T_SIGNATURE
:
3478 error("Constant cannot be defined for signature `%s'",
3479 t
->get_fullname().c_str());
3482 value_under_check
= true;
3483 type
->chk_this_value(value
, 0, Type::EXPECTED_CONSTANT
, INCOMPLETE_ALLOWED
,
3484 OMIT_NOT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr());
3485 value_under_check
= false;
3486 chk_erroneous_attr();
3487 if (erroneous_attrs
) value
->set_err_descr(erroneous_attrs
->get_err_descr());
3489 ReferenceChain
refch(type
, "While checking embedded recursions");
3490 value
->chk_recursions(refch
);
3494 if (!semantic_check_only
) {
3495 value
->set_genname_prefix("const_");
3496 value
->set_genname_recursive(get_genname());
3497 value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3501 bool Def_Const::chk_identical(Definition
*p_def
)
3505 if (p_def
->get_asstype() != A_CONST
) {
3506 const char *dispname_str
= id
->get_dispname().c_str();
3507 error("Local definition `%s' is a constant, but the definition "
3508 "inherited from component type `%s' is a %s", dispname_str
,
3509 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
3510 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
3513 Def_Const
*p_def_const
= dynamic_cast<Def_Const
*>(p_def
);
3514 if (!p_def_const
) FATAL_ERROR("Def_Const::chk_identical()");
3515 if (!type
->is_identical(p_def_const
->type
)) {
3516 const char *dispname_str
= id
->get_dispname().c_str();
3517 type
->error("Local constant `%s' has type `%s', but the constant "
3518 "inherited from component type `%s' has type `%s'", dispname_str
,
3519 type
->get_typename().c_str(),
3520 p_def_const
->get_my_scope()->get_fullname().c_str(),
3521 p_def_const
->type
->get_typename().c_str());
3522 p_def_const
->note("The inherited constant `%s' is here", dispname_str
);
3524 } else if (!(*value
== *p_def_const
->value
)) {
3525 const char *dispname_str
= id
->get_dispname().c_str();
3526 value
->error("Local constant `%s' and the constant inherited from "
3527 "component type `%s' have different values", dispname_str
,
3528 p_def_const
->get_my_scope()->get_fullname().c_str());
3529 p_def_const
->note("The inherited constant `%s' is here", dispname_str
);
3534 void Def_Const::generate_code(output_struct
*target
, bool)
3536 type
->generate_code(target
);
3538 Code::init_cdef(&cdef
);
3539 type
->generate_code_object(&cdef
, value
);
3540 cdef
.init
= update_location_object(cdef
.init
);
3541 cdef
.init
= value
->generate_code_init(cdef
.init
,
3542 value
->get_lhs_name().c_str());
3543 Code::merge_cdef(target
, &cdef
);
3544 Code::free_cdef(&cdef
);
3547 void Def_Const::generate_code(Common::CodeGenHelper
& cgh
) {
3548 // constant definitions always go to its containing module
3549 generate_code(cgh
.get_current_outputstruct());
3552 char *Def_Const::generate_code_str(char *str
)
3554 const string
& t_genname
= get_genname();
3555 const char *genname_str
= t_genname
.c_str();
3556 if (value
->has_single_expr()) {
3557 // the value can be represented by a single C++ expression
3558 // the object is initialized by the constructor
3559 str
= mputprintf(str
, "%s %s(%s);\n",
3560 type
->get_genname_value(my_scope
).c_str(), genname_str
,
3561 value
->get_single_expr().c_str());
3563 // use the default constructor
3564 str
= mputprintf(str
, "%s %s;\n",
3565 type
->get_genname_value(my_scope
).c_str(), genname_str
);
3566 // the value is assigned using subsequent statements
3567 str
= value
->generate_code_init(str
, genname_str
);
3569 if (debugger_active
) {
3570 str
= generate_code_debugger_add_var(str
, this);
3575 void Def_Const::ilt_generate_code(ILT
*ilt
)
3577 const string
& t_genname
= get_genname();
3578 const char *genname_str
= t_genname
.c_str();
3579 char*& def
=ilt
->get_out_def();
3580 char*& init
=ilt
->get_out_branches();
3581 def
= mputprintf(def
, "%s %s;\n", type
->get_genname_value(my_scope
).c_str(),
3583 init
= value
->generate_code_init(init
, genname_str
);
3586 char *Def_Const::generate_code_init_comp(char *str
, Definition
*)
3588 /* This function actually does nothing as \a this and \a base_defn are
3589 * exactly the same. */
3593 void Def_Const::dump_internal(unsigned level
) const
3595 DEBUG(level
, "Constant: %s @%p", id
->get_dispname().c_str(), (const void*)this);
3596 type
->dump(level
+ 1);
3597 value
->dump(level
+ 1);
3600 // =================================
3601 // ===== Def_ExtConst
3602 // =================================
3604 Def_ExtConst::Def_ExtConst(Identifier
*p_id
, Type
*p_type
)
3605 : Definition(A_EXT_CONST
, p_id
)
3607 if (!p_type
) FATAL_ERROR("Ttcn::Def_ExtConst::Def_ExtConst()");
3609 type
->set_ownertype(Type::OT_CONST_DEF
, this);
3610 usage_found
= false;
3613 Def_ExtConst::~Def_ExtConst()
3618 Def_ExtConst
*Def_ExtConst::clone() const
3620 FATAL_ERROR("Def_ExtConst::clone");
3623 void Def_ExtConst::set_fullname(const string
& p_fullname
)
3625 Definition::set_fullname(p_fullname
);
3626 type
->set_fullname(p_fullname
+ ".<type>");
3629 void Def_ExtConst::set_my_scope(Scope
*p_scope
)
3631 Definition::set_my_scope(p_scope
);
3632 type
->set_my_scope(p_scope
);
3635 Type
*Def_ExtConst::get_Type()
3641 void Def_ExtConst::chk()
3644 Error_Context
cntxt(this, "In external constant definition `%s'",
3645 id
->get_dispname().c_str());
3646 type
->set_genname(_T_
, get_genname());
3649 Type
*t
= type
->get_type_refd_last();
3650 switch (t
->get_typetype()) {
3652 error("External constant cannot be defined for port type `%s'",
3653 t
->get_fullname().c_str());
3655 case Type::T_SIGNATURE
:
3656 error("External constant cannot be defined for signature `%s'",
3657 t
->get_fullname().c_str());
3662 if (w_attrib_path
) {
3663 w_attrib_path
->chk_global_attrib();
3664 switch (type
->get_type_refd_last()->get_typetype()) {
3667 case Type::T_CHOICE_T
:
3668 // These types may have qualified attributes
3670 case Type::T_SEQOF
: case Type::T_SETOF
:
3673 w_attrib_path
->chk_no_qualif();
3679 void Def_ExtConst::generate_code(output_struct
*target
, bool)
3681 type
->generate_code(target
);
3682 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
3683 "extern const %s& %s;\n", type
->get_genname_value(my_scope
).c_str(),
3684 get_genname().c_str());
3687 void Def_ExtConst::generate_code(Common::CodeGenHelper
& cgh
) {
3688 // constant definitions always go to its containing module
3689 generate_code(cgh
.get_current_outputstruct());
3692 void Def_ExtConst::dump_internal(unsigned level
) const
3694 DEBUG(level
, "External constant: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3695 type
->dump(level
+ 1);
3698 // =================================
3699 // ===== Def_Modulepar
3700 // =================================
3702 Def_Modulepar::Def_Modulepar(Identifier
*p_id
, Type
*p_type
, Value
*p_defval
)
3703 : Definition(A_MODULEPAR
, p_id
)
3705 if (!p_type
) FATAL_ERROR("Ttcn::Def_Modulepar::Def_Modulepar()");
3707 type
->set_ownertype(Type::OT_MODPAR_DEF
, this);
3708 def_value
= p_defval
;
3711 Def_Modulepar::~Def_Modulepar()
3717 Def_Modulepar
* Def_Modulepar::clone() const
3719 FATAL_ERROR("Def_Modulepar::clone");
3722 void Def_Modulepar::set_fullname(const string
& p_fullname
)
3724 Definition::set_fullname(p_fullname
);
3725 type
->set_fullname(p_fullname
+ ".<type>");
3726 if (def_value
) def_value
->set_fullname(p_fullname
+ ".<default_value>");
3729 void Def_Modulepar::set_my_scope(Scope
*p_scope
)
3731 Definition::set_my_scope(p_scope
);
3732 type
->set_my_scope(p_scope
);
3733 if (def_value
) def_value
->set_my_scope(p_scope
);
3736 Type
*Def_Modulepar::get_Type()
3742 void Def_Modulepar::chk()
3745 Error_Context
cntxt(this, "In module parameter definition `%s'",
3746 id
->get_dispname().c_str());
3747 type
->set_genname(_T_
, get_genname());
3749 if (w_attrib_path
) {
3750 w_attrib_path
->chk_global_attrib();
3751 switch (type
->get_type_refd_last()->get_typetype()) {
3754 case Type::T_CHOICE_T
:
3755 // These types may have qualified attributes
3757 case Type::T_SEQOF
: case Type::T_SETOF
:
3760 w_attrib_path
->chk_no_qualif();
3764 map
<Type
*,void> type_chain
;
3765 map
<Type::typetype_t
, void> not_allowed
;
3766 not_allowed
.add(Type::T_PORT
, 0);
3767 Type
*t
= type
->get_type_refd_last();
3768 // if the type is valid the original will be returned
3769 Type::typetype_t tt
= t
->search_for_not_allowed_type(type_chain
, not_allowed
);
3771 not_allowed
.clear();
3774 error("Type of module parameter cannot be or embed port type `%s'",
3775 t
->get_fullname().c_str());
3777 case Type::T_SIGNATURE
:
3778 error("Type of module parameter cannot be signature `%s'",
3779 t
->get_fullname().c_str());
3781 case Type::T_FUNCTION
:
3782 case Type::T_ALTSTEP
:
3783 case Type::T_TESTCASE
:
3784 if (t
->get_fat_runs_on_self()) {
3785 error("Type of module parameter cannot be of function reference type"
3786 " `%s' which has runs on self clause", t
->get_fullname().c_str());
3794 Error_Context
cntxt2(def_value
, "In default value");
3795 def_value
->set_my_governor(type
);
3796 type
->chk_this_value_ref(def_value
);
3798 type
->chk_this_value(def_value
, 0, Type::EXPECTED_CONSTANT
, INCOMPLETE_ALLOWED
,
3799 OMIT_NOT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr());
3800 if (!semantic_check_only
) {
3801 def_value
->set_genname_prefix("modulepar_");
3802 def_value
->set_genname_recursive(get_genname());
3803 def_value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3805 } else checked
= true;
3811 void Def_Modulepar::generate_code(output_struct
*target
, bool)
3813 type
->generate_code(target
);
3815 Code::init_cdef(&cdef
);
3816 const string
& t_genname
= get_genname();
3817 const char *name
= t_genname
.c_str();
3818 type
->generate_code_object(&cdef
, my_scope
, t_genname
, "modulepar_", false);
3820 cdef
.init
= update_location_object(cdef
.init
);
3821 cdef
.init
= def_value
->generate_code_init(cdef
.init
, def_value
->get_lhs_name().c_str());
3823 Code::merge_cdef(target
, &cdef
);
3824 Code::free_cdef(&cdef
);
3826 if (has_implicit_omit_attr()) {
3827 target
->functions
.post_init
= mputprintf(target
->functions
.post_init
,
3828 "modulepar_%s.set_implicit_omit();\n", name
);
3831 const char *dispname
= id
->get_dispname().c_str();
3832 target
->functions
.set_param
= mputprintf(target
->functions
.set_param
,
3833 "if (!strcmp(par_name, \"%s\")) {\n"
3834 "modulepar_%s.set_param(param);\n"
3836 "} else ", dispname
, name
);
3837 target
->functions
.get_param
= mputprintf(target
->functions
.get_param
,
3838 "if (!strcmp(par_name, \"%s\")) {\n"
3839 "return modulepar_%s.get_param(param_name);\n"
3840 "} else ", dispname
, name
);
3842 if (target
->functions
.log_param
) {
3843 // this is not the first modulepar
3844 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3845 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname
);
3847 // this is the first modulepar
3848 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3849 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname
);
3851 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3852 "%s.log();\n", name
);
3855 void Def_Modulepar::generate_code(Common::CodeGenHelper
& cgh
) {
3856 // module parameter definitions always go to its containing module
3857 generate_code(cgh
.get_current_outputstruct());
3860 void Def_Modulepar::dump_internal(unsigned level
) const
3862 DEBUG(level
, "Module parameter: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3863 type
->dump(level
+ 1);
3864 if (def_value
) def_value
->dump(level
+ 1);
3865 else DEBUG(level
+ 1, "No default value");
3868 // =================================
3869 // ===== Def_Modulepar_Template
3870 // =================================
3872 Def_Modulepar_Template::Def_Modulepar_Template(Identifier
*p_id
, Type
*p_type
, Template
*p_deftmpl
)
3873 : Definition(A_MODULEPAR_TEMP
, p_id
)
3875 if (!p_type
) FATAL_ERROR("Ttcn::Def_Modulepar_Template::Def_Modulepar_Template()");
3877 type
->set_ownertype(Type::OT_MODPAR_DEF
, this);
3878 def_template
= p_deftmpl
;
3881 Def_Modulepar_Template::~Def_Modulepar_Template()
3884 delete def_template
;
3887 Def_Modulepar_Template
* Def_Modulepar_Template::clone() const
3889 FATAL_ERROR("Def_Modulepar_Template::clone");
3892 void Def_Modulepar_Template::set_fullname(const string
& p_fullname
)
3894 Definition::set_fullname(p_fullname
);
3895 type
->set_fullname(p_fullname
+ ".<type>");
3896 if (def_template
) def_template
->set_fullname(p_fullname
+ ".<default_template>");
3899 void Def_Modulepar_Template::set_my_scope(Scope
*p_scope
)
3901 Definition::set_my_scope(p_scope
);
3902 type
->set_my_scope(p_scope
);
3903 if (def_template
) def_template
->set_my_scope(p_scope
);
3906 Type
*Def_Modulepar_Template::get_Type()
3912 void Def_Modulepar_Template::chk()
3915 Error_Context
cntxt(this, "In template module parameter definition `%s'",
3916 id
->get_dispname().c_str());
3917 if (w_attrib_path
) {
3918 w_attrib_path
->chk_global_attrib();
3919 switch (type
->get_type_refd_last()->get_typetype()) {
3922 case Type::T_CHOICE_T
:
3923 // These types may have qualified attributes
3925 case Type::T_SEQOF
: case Type::T_SETOF
:
3928 w_attrib_path
->chk_no_qualif();
3932 type
->set_genname(_T_
, get_genname());
3934 Type
*t
= type
->get_type_refd_last();
3935 switch (t
->get_typetype()) {
3937 error("Type of template module parameter cannot be port type `%s'",
3938 t
->get_fullname().c_str());
3940 case Type::T_SIGNATURE
:
3941 error("Type of template module parameter cannot be signature `%s'",
3942 t
->get_fullname().c_str());
3944 case Type::T_FUNCTION
:
3945 case Type::T_ALTSTEP
:
3946 case Type::T_TESTCASE
:
3947 if (t
->get_fat_runs_on_self()) {
3948 error("Type of template module parameter cannot be of function reference type"
3949 " `%s' which has runs on self clause", t
->get_fullname().c_str());
3953 if (has_implicit_omit_attr()) {
3954 error("Implicit omit not supported for template module parameters");
3960 Error_Context
cntxt2(def_template
, "In default template");
3961 def_template
->set_my_governor(type
);
3962 def_template
->flatten(false);
3963 if (def_template
->get_templatetype() == Template::CSTR_PATTERN
&&
3964 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
3965 def_template
->set_templatetype(Template::USTR_PATTERN
);
3966 def_template
->get_ustr_pattern()->set_pattern_type(
3967 PatternString::USTR_PATTERN
);
3969 type
->chk_this_template_ref(def_template
);
3971 type
->chk_this_template_generic(def_template
, INCOMPLETE_ALLOWED
,
3972 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr() ? IMPLICIT_OMIT
: NOT_IMPLICIT_OMIT
, 0);
3973 if (!semantic_check_only
) {
3974 def_template
->set_genname_prefix("modulepar_");
3975 def_template
->set_genname_recursive(get_genname());
3976 def_template
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3978 } else checked
= true;
3984 void Def_Modulepar_Template::generate_code(output_struct
*target
, bool)
3986 type
->generate_code(target
);
3988 Code::init_cdef(&cdef
);
3989 const string
& t_genname
= get_genname();
3990 const char *name
= t_genname
.c_str();
3991 type
->generate_code_object(&cdef
, my_scope
, t_genname
, "modulepar_", true);
3993 cdef
.init
= update_location_object(cdef
.init
);
3994 cdef
.init
= def_template
->generate_code_init(cdef
.init
, def_template
->get_lhs_name().c_str());
3996 Code::merge_cdef(target
, &cdef
);
3997 Code::free_cdef(&cdef
);
3999 if (has_implicit_omit_attr()) {
4000 FATAL_ERROR("Def_Modulepar_Template::generate_code()");
4003 const char *dispname
= id
->get_dispname().c_str();
4004 target
->functions
.set_param
= mputprintf(target
->functions
.set_param
,
4005 "if (!strcmp(par_name, \"%s\")) {\n"
4006 "modulepar_%s.set_param(param);\n"
4008 "} else ", dispname
, name
);
4009 target
->functions
.get_param
= mputprintf(target
->functions
.get_param
,
4010 "if (!strcmp(par_name, \"%s\")) {\n"
4011 "return modulepar_%s.get_param(param_name);\n"
4012 "} else ", dispname
, name
);
4014 if (target
->functions
.log_param
) {
4015 // this is not the first modulepar
4016 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
4017 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname
);
4019 // this is the first modulepar
4020 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
4021 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname
);
4023 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
4024 "%s.log();\n", name
);
4027 void Def_Modulepar_Template::generate_code(Common::CodeGenHelper
& cgh
) {
4028 // module parameter definitions always go to its containing module
4029 generate_code(cgh
.get_current_outputstruct());
4032 void Def_Modulepar_Template::dump_internal(unsigned level
) const
4034 DEBUG(level
, "Module parameter: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
4035 type
->dump(level
+ 1);
4036 if (def_template
) def_template
->dump(level
+ 1);
4037 else DEBUG(level
+ 1, "No default template");
4040 // =================================
4041 // ===== Def_Template
4042 // =================================
4044 Def_Template::Def_Template(template_restriction_t p_template_restriction
,
4045 Identifier
*p_id
, Type
*p_type
, FormalParList
*p_fpl
,
4046 Reference
*p_derived_ref
, Template
*p_body
)
4047 : Definition(A_TEMPLATE
, p_id
), type(p_type
), fp_list(p_fpl
),
4048 derived_ref(p_derived_ref
), base_template(0), recurs_deriv_checked(false),
4049 body(p_body
), template_restriction(p_template_restriction
),
4050 gen_restriction_check(false)
4052 if (!p_type
|| !p_body
) FATAL_ERROR("Ttcn::Def_Template::Def_Template()");
4053 type
->set_ownertype(Type::OT_TEMPLATE_DEF
, this);
4054 if (fp_list
) fp_list
->set_my_def(this);
4057 Def_Template::~Def_Template()
4065 Def_Template
*Def_Template::clone() const
4067 FATAL_ERROR("Def_Template::clone");
4070 void Def_Template::set_fullname(const string
& p_fullname
)
4072 Definition::set_fullname(p_fullname
);
4073 type
->set_fullname(p_fullname
+ ".<type>");
4074 if (fp_list
) fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
4076 derived_ref
->set_fullname(p_fullname
+ ".<derived_reference>");
4077 body
->set_fullname(p_fullname
);
4080 void Def_Template::set_my_scope(Scope
*p_scope
)
4082 bridgeScope
.set_parent_scope(p_scope
);
4083 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
4085 Definition::set_my_scope(&bridgeScope
);
4086 type
->set_my_scope(&bridgeScope
);
4087 if (derived_ref
) derived_ref
->set_my_scope(&bridgeScope
);
4089 fp_list
->set_my_scope(&bridgeScope
);
4090 body
->set_my_scope(fp_list
);
4091 } else body
->set_my_scope(&bridgeScope
);
4094 Setting
*Def_Template::get_Setting()
4096 return get_Template();
4099 Type
*Def_Template::get_Type()
4101 if (!checked
) chk();
4105 Template
*Def_Template::get_Template()
4107 if (!checked
) chk();
4111 FormalParList
*Def_Template::get_FormalParList()
4113 if (!checked
) chk();
4117 void Def_Template::chk()
4119 if (checked
) return;
4120 Error_Context
cntxt(this, "In template definition `%s'",
4121 id
->get_dispname().c_str());
4122 const string
& t_genname
= get_genname();
4123 type
->set_genname(_T_
, t_genname
);
4125 if (w_attrib_path
) {
4126 w_attrib_path
->chk_global_attrib(true);
4127 switch (type
->get_type_refd_last()->get_typetype_ttcn3()) {
4130 case Type::T_CHOICE_T
:
4131 // These types may have qualified attributes
4133 case Type::T_SEQOF
: case Type::T_SETOF
:
4136 w_attrib_path
->chk_no_qualif();
4142 fp_list
->chk(asstype
);
4143 if (local_scope
) error("Parameterized local template `%s' not supported",
4144 id
->get_dispname().c_str());
4147 // Merge the elements of "all from" into the list
4148 body
->flatten(false);
4150 body
->set_my_governor(type
);
4152 if (body
->get_templatetype() == Template::CSTR_PATTERN
&&
4153 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
4154 body
->set_templatetype(Template::USTR_PATTERN
);
4155 body
->get_ustr_pattern()->set_pattern_type(PatternString::USTR_PATTERN
);
4158 type
->chk_this_template_ref(body
);
4160 Type
*t
= type
->get_type_refd_last();
4161 if (t
->get_typetype() == Type::T_PORT
) {
4162 error("Template cannot be defined for port type `%s'",
4163 t
->get_fullname().c_str());
4166 chk_recursive_derivation();
4167 type
->chk_this_template_generic(body
, INCOMPLETE_ALLOWED
, OMIT_ALLOWED
,
4168 ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
4169 has_implicit_omit_attr() ? IMPLICIT_OMIT
: NOT_IMPLICIT_OMIT
, 0);
4171 chk_erroneous_attr();
4172 if (erroneous_attrs
) body
->set_err_descr(erroneous_attrs
->get_err_descr());
4175 ReferenceChain
refch(type
, "While checking embedded recursions");
4176 body
->chk_recursions(refch
);
4178 if (template_restriction
!=TR_NONE
) {
4179 Error_Context
ec(this, "While checking template restriction `%s'",
4180 Template::get_restriction_name(template_restriction
));
4181 gen_restriction_check
=
4182 body
->chk_restriction("template definition", template_restriction
, body
);
4183 if (fp_list
&& template_restriction
!=TR_PRESENT
) {
4184 size_t nof_fps
= fp_list
->get_nof_fps();
4185 for (size_t i
=0; i
<nof_fps
; i
++) {
4186 FormalPar
* fp
= fp_list
->get_fp_byIndex(i
);
4187 // if formal par is not template then skip restriction checking,
4188 // templates can have only `in' parameters
4189 if (fp
->get_asstype()!=A_PAR_TEMPL_IN
) continue;
4190 template_restriction_t fp_tr
= fp
->get_template_restriction();
4191 switch (template_restriction
) {
4200 fp
->error("Formal parameter with template restriction `%s' "
4201 "not allowed here", Template::get_restriction_name(fp_tr
));
4204 fp
->error("Formal parameter without template restriction "
4205 "not allowed here");
4208 FATAL_ERROR("Ttcn::Def_Template::chk()");
4212 FATAL_ERROR("Ttcn::Def_Template::chk()");
4217 if (!semantic_check_only
) {
4218 if (fp_list
) fp_list
->set_genname(t_genname
);
4219 body
->set_genname_prefix("template_");
4220 body
->set_genname_recursive(t_genname
);
4221 body
->set_code_section(fp_list
? GovernedSimple::CS_INLINE
:
4222 GovernedSimple::CS_POST_INIT
);
4227 void Def_Template::chk_default() const
4229 if (!fp_list
) FATAL_ERROR("Def_Template::chk_default()");
4231 if (fp_list
->has_notused_defval())
4232 fp_list
->error("Only modified templates are allowed to use the not "
4233 "used symbol (`-') as the default parameter");
4236 Common::Assignment
*ass
= derived_ref
->get_refd_assignment(false);
4237 if (!ass
|| ass
->get_asstype() != A_TEMPLATE
) return; // Work locally.
4238 Def_Template
*base
= dynamic_cast<Def_Template
*>(ass
);
4239 if (!base
) FATAL_ERROR("Def_Template::chk_default()");
4240 FormalParList
*base_fpl
= base
->get_FormalParList();
4241 size_t nof_base_fps
= base_fpl
? base_fpl
->get_nof_fps() : 0;
4242 size_t nof_local_fps
= fp_list
? fp_list
->get_nof_fps() : 0;
4243 size_t min_fps
= nof_base_fps
;
4244 if (nof_local_fps
< nof_base_fps
) min_fps
= nof_local_fps
;
4245 for (size_t i
= 0; i
< min_fps
; i
++) {
4246 FormalPar
*base_fp
= base_fpl
->get_fp_byIndex(i
);
4247 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4248 if (local_fp
->has_notused_defval()) {
4249 if (base_fp
->has_defval()) {
4250 local_fp
->set_defval(base_fp
->get_defval());
4252 local_fp
->error("Not used symbol (`-') doesn't have the "
4253 "corresponding default parameter in the "
4258 // Additional parameters in the derived template with using the not used
4259 // symbol. TODO: Merge the loops.
4260 for (size_t i
= nof_base_fps
; i
< nof_local_fps
; i
++) {
4261 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4262 if (local_fp
->has_notused_defval())
4263 local_fp
->error("Not used symbol (`-') doesn't have the "
4264 "corresponding default parameter in the "
4269 void Def_Template::chk_modified()
4271 if (!derived_ref
) return;
4272 // Do not check the (non-existent) actual parameter list of the derived
4273 // reference against the formal parameter list of the base template.
4274 // According to TTCN-3 syntax the derived reference cannot have parameters
4275 // even if the base template is parameterized.
4276 Common::Assignment
*ass
= derived_ref
->get_refd_assignment(false);
4277 // Checking the existence and type compatibility of the base template.
4279 if (ass
->get_asstype() != A_TEMPLATE
) {
4280 derived_ref
->error("Reference to a template was expected in the "
4281 "`modifies' definition instead of %s",
4282 ass
->get_description().c_str());
4285 base_template
= dynamic_cast<Def_Template
*>(ass
);
4286 if (!base_template
) FATAL_ERROR("Def_Template::chk_modified()");
4287 Type
*base_type
= base_template
->get_Type();
4288 TypeCompatInfo
info_base(my_scope
->get_scope_mod(), type
, base_type
, true,
4290 TypeChain l_chain_base
;
4291 TypeChain r_chain_base
;
4292 if (!type
->is_compatible(base_type
, &info_base
, &l_chain_base
,
4294 if (info_base
.is_subtype_error()) {
4295 type
->error("%s", info_base
.get_subtype_error().c_str());
4297 if (!info_base
.is_erroneous()) {
4298 type
->error("The modified template has different type than base "
4299 "template `%s': `%s' was expected instead of `%s'",
4300 ass
->get_fullname().c_str(),
4301 base_type
->get_typename().c_str(),
4302 type
->get_typename().c_str());
4304 // Always use the format string.
4305 type
->error("%s", info_base
.get_error_str_str().c_str());
4308 if (info_base
.needs_conversion())
4309 body
->set_needs_conversion();
4311 // Check for restriction.
4312 if (Template::is_less_restrictive(base_template
->get_template_restriction(),
4313 template_restriction
)) {
4314 error("The template restriction is not the same or more "
4315 "restrictive as of base template `%s'", ass
->get_fullname().c_str());
4317 // Checking formal parameter lists.
4318 FormalParList
*base_fpl
= base_template
->get_FormalParList();
4319 size_t nof_base_fps
= base_fpl
? base_fpl
->get_nof_fps() : 0;
4320 size_t nof_local_fps
= fp_list
? fp_list
->get_nof_fps() : 0;
4322 if (nof_local_fps
< nof_base_fps
) {
4323 error("The modified template has fewer formal parameters than base "
4324 "template `%s': at least %lu parameter%s expected instead of %lu",
4325 ass
->get_fullname().c_str(), (unsigned long)nof_base_fps
,
4326 nof_base_fps
> 1 ? "s were" : " was", (unsigned long)nof_local_fps
);
4327 min_fps
= nof_local_fps
;
4328 } else min_fps
= nof_base_fps
;
4330 for (size_t i
= 0; i
< min_fps
; i
++) {
4331 FormalPar
*base_fp
= base_fpl
->get_fp_byIndex(i
);
4332 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4333 Error_Context
cntxt(local_fp
, "In formal parameter #%lu",
4334 (unsigned long)(i
+ 1));
4335 // Check for parameter kind equivalence (value or template).
4336 if (base_fp
->get_asstype() != local_fp
->get_asstype())
4337 local_fp
->error("The kind of parameter is not the same as in base "
4338 "template `%s': %s was expected instead of %s",
4339 ass
->get_fullname().c_str(), base_fp
->get_assname(),
4340 local_fp
->get_assname());
4341 // Check for type compatibility.
4342 Type
*base_fp_type
= base_fp
->get_Type();
4343 Type
*local_fp_type
= local_fp
->get_Type();
4344 TypeCompatInfo
info_par(my_scope
->get_scope_mod(), base_fp_type
,
4345 local_fp_type
, true, false);
4346 TypeChain l_chain_par
;
4347 TypeChain r_chain_par
;
4348 if (!base_fp_type
->is_compatible(local_fp_type
, &info_par
, &l_chain_par
,
4350 if (info_par
.is_subtype_error()) {
4351 local_fp_type
->error("%s", info_par
.get_subtype_error().c_str());
4353 if (!info_par
.is_erroneous()) {
4354 local_fp_type
->error("The type of parameter is not the same as in "
4355 "base template `%s': `%s' was expected instead "
4357 ass
->get_fullname().c_str(),
4358 base_fp_type
->get_typename().c_str(),
4359 local_fp_type
->get_typename().c_str());
4361 local_fp_type
->error("%s", info_par
.get_error_str_str().c_str());
4364 if (info_par
.needs_conversion())
4365 body
->set_needs_conversion();
4367 // Check for name equivalence.
4368 const Identifier
& base_fp_id
= base_fp
->get_id();
4369 const Identifier
& local_fp_id
= local_fp
->get_id();
4370 if (!(base_fp_id
== local_fp_id
))
4371 local_fp
->error("The name of parameter is not the same as in base "
4372 "template `%s': `%s' was expected instead of `%s'",
4373 ass
->get_fullname().c_str(),
4374 base_fp_id
.get_dispname().c_str(),
4375 local_fp_id
.get_dispname().c_str());
4376 // Check for restrictions: the derived must be same or more restrictive.
4377 if (base_fp
->get_asstype()==local_fp
->get_asstype() &&
4378 Template::is_less_restrictive(base_fp
->get_template_restriction(),
4379 local_fp
->get_template_restriction())) {
4380 local_fp
->error("The restriction of parameter is not the same or more "
4381 "restrictive as in base template `%s'", ass
->get_fullname().c_str());
4384 // Set the pointer to the body of base template.
4385 body
->set_base_template(base_template
->get_Template());
4388 void Def_Template::chk_recursive_derivation()
4390 if (recurs_deriv_checked
) return;
4391 if (base_template
) {
4392 ReferenceChain
refch(this, "While checking the chain of base templates");
4393 refch
.add(get_fullname());
4394 for (Def_Template
*iter
= base_template
; iter
; iter
= iter
->base_template
)
4396 if (iter
->recurs_deriv_checked
) break;
4397 else if (refch
.add(iter
->get_fullname()))
4398 iter
->recurs_deriv_checked
= true;
4402 recurs_deriv_checked
= true;
4405 void Def_Template::generate_code(output_struct
*target
, bool)
4407 type
->generate_code(target
);
4409 // Parameterized template. Generate code for a function which returns
4410 // a $(genname)_template and has the appropriate parameters.
4411 const string
& t_genname
= get_genname();
4412 const char *template_name
= t_genname
.c_str();
4413 const char *template_dispname
= id
->get_dispname().c_str();
4414 const string
& type_genname
= type
->get_genname_template(my_scope
);
4415 const char *type_genname_str
= type_genname
.c_str();
4417 // assemble the function body first (this also determines which parameters
4419 size_t nof_base_pars
= 0;
4420 char* function_body
= create_location_object(memptystr(), "TEMPLATE",
4422 if (debugger_active
) {
4423 function_body
= generate_code_debugger_function_init(function_body
, this);
4425 if (base_template
) {
4426 // modified template
4427 function_body
= mputprintf(function_body
, "%s ret_val(%s",
4429 base_template
->get_genname_from_scope(my_scope
).c_str());
4430 if (base_template
->fp_list
) {
4431 // the base template is also parameterized
4432 function_body
= mputc(function_body
, '(');
4433 nof_base_pars
= base_template
->fp_list
->get_nof_fps();
4434 for (size_t i
= 0; i
< nof_base_pars
; i
++) {
4435 if (i
> 0) function_body
= mputstr(function_body
, ", ");
4436 function_body
= mputstr(function_body
,
4437 fp_list
->get_fp_byIndex(i
)->get_id().get_name().c_str());
4439 function_body
= mputc(function_body
, ')');
4441 function_body
= mputstr(function_body
, ");\n");
4444 function_body
= mputprintf(function_body
, "%s ret_val;\n",
4447 if (erroneous_attrs
&& erroneous_attrs
->get_err_descr()) {
4448 function_body
= erroneous_attrs
->get_err_descr()->
4449 generate_code_str(function_body
, string("ret_val"));
4451 function_body
= body
->generate_code_init(function_body
, "ret_val");
4452 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4453 function_body
= Template::generate_restriction_check_code(function_body
,
4454 "ret_val", template_restriction
);
4455 if (debugger_active
) {
4456 function_body
= mputstr(function_body
,
4457 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
4458 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
4460 function_body
= mputstr(function_body
, "return ret_val;\n");
4461 // if the template modifies a parameterized template, then the inherited
4462 // formal parameters must always be displayed, otherwise generate a smart
4463 // formal parameter list (where the names of unused parameters are omitted)
4464 char *formal_par_list
= fp_list
->generate_code(memptystr(), nof_base_pars
);
4465 fp_list
->generate_code_defval(target
);
4467 target
->header
.function_prototypes
=
4468 mputprintf(target
->header
.function_prototypes
,
4469 "extern %s %s(%s);\n",
4470 type_genname_str
, template_name
, formal_par_list
);
4471 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
4475 "}\n\n", type_genname_str
, template_name
, formal_par_list
, function_body
);
4476 Free(formal_par_list
);
4477 Free(function_body
);
4479 // non-parameterized template
4481 Code::init_cdef(&cdef
);
4482 type
->generate_code_object(&cdef
, body
);
4483 cdef
.init
= update_location_object(cdef
.init
);
4484 if (base_template
) {
4485 // modified template
4486 if (base_template
->my_scope
->get_scope_mod_gen() ==
4487 my_scope
->get_scope_mod_gen()) {
4488 // if the base template is in the same module its body has to be
4489 // initialized first
4490 cdef
.init
= base_template
->body
->generate_code_init(cdef
.init
,
4491 base_template
->body
->get_lhs_name().c_str());
4493 if (use_runtime_2
&& body
->get_needs_conversion()) {
4494 Type
*body_type
= body
->get_my_governor()->get_type_refd_last();
4495 Type
*base_type
= base_template
->body
->get_my_governor()
4496 ->get_type_refd_last();
4497 if (!body_type
|| !base_type
)
4498 FATAL_ERROR("Def_Template::generate_code()");
4499 const string
& tmp_id
= body
->get_temporary_id();
4500 const char *tmp_id_str
= tmp_id
.c_str();
4501 // base template initialization
4502 cdef
.init
= mputprintf(cdef
.init
,
4504 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4505 "and `%s' are not compatible at run-time\");\n"
4507 body_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
4508 TypeConv::get_conv_func(base_type
, body_type
, my_scope
4509 ->get_scope_mod()).c_str(), tmp_id_str
, base_template
4510 ->get_genname_from_scope(my_scope
).c_str(), base_type
4511 ->get_typename().c_str(), body_type
->get_typename().c_str(),
4512 body
->get_lhs_name().c_str(), tmp_id_str
);
4514 cdef
.init
= mputprintf(cdef
.init
, "%s = %s;\n",
4515 body
->get_lhs_name().c_str(),
4516 base_template
->get_genname_from_scope(my_scope
).c_str());
4519 if (use_runtime_2
&& TypeConv::needs_conv_refd(body
))
4520 cdef
.init
= TypeConv::gen_conv_code_refd(cdef
.init
,
4521 body
->get_lhs_name().c_str(), body
);
4523 cdef
.init
= body
->generate_code_init(cdef
.init
,
4524 body
->get_lhs_name().c_str());
4525 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
4526 cdef
.init
= Template::generate_restriction_check_code(cdef
.init
,
4527 body
->get_lhs_name().c_str(), template_restriction
);
4528 target
->header
.global_vars
= mputstr(target
->header
.global_vars
,
4530 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
4532 target
->functions
.post_init
= mputstr(target
->functions
.post_init
,
4534 Code::free_cdef(&cdef
);
4538 void Def_Template::generate_code(Common::CodeGenHelper
& cgh
) {
4539 generate_code(cgh
.get_outputstruct(this));
4542 char *Def_Template::generate_code_str(char *str
)
4544 const string
& t_genname
= get_genname();
4545 const char *genname_str
= t_genname
.c_str();
4546 const string
& type_genname
= type
->get_genname_template(my_scope
);
4547 const char *type_genname_str
= type_genname
.c_str();
4549 const char *dispname_str
= id
->get_dispname().c_str();
4550 NOTSUPP("Code generation for parameterized local template `%s'",
4552 str
= mputprintf(str
, "/* NOT SUPPORTED: template %s */\n",
4555 if (base_template
) {
4556 // non-parameterized modified template
4557 if (use_runtime_2
&& body
->get_needs_conversion()) {
4558 Type
*body_type
= body
->get_my_governor()->get_type_refd_last();
4559 Type
*base_type
= base_template
->body
->get_my_governor()
4560 ->get_type_refd_last();
4561 if (!body_type
|| !base_type
)
4562 FATAL_ERROR("Def_Template::generate_code_str()");
4563 const string
& tmp_id
= body
->get_temporary_id();
4564 const char *tmp_id_str
= tmp_id
.c_str();
4565 str
= mputprintf(str
,
4567 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4568 "and `%s' are not compatible at run-time\");\n"
4570 body_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
4571 TypeConv::get_conv_func(base_type
, body_type
, my_scope
4572 ->get_scope_mod()).c_str(), tmp_id_str
, base_template
4573 ->get_genname_from_scope(my_scope
).c_str(), base_type
4574 ->get_typename().c_str(), body_type
->get_typename().c_str(),
4575 type_genname_str
, genname_str
, tmp_id_str
);
4577 // the object is initialized from the base template by the
4579 str
= mputprintf(str
, "%s %s(%s);\n", type_genname_str
, genname_str
,
4580 base_template
->get_genname_from_scope(my_scope
).c_str());
4582 // the modified body is assigned in the subsequent statements
4583 str
= body
->generate_code_init(str
, genname_str
);
4585 // non-parameterized non-modified template
4586 if (body
->has_single_expr()) {
4587 // the object is initialized by the constructor
4588 str
= mputprintf(str
, "%s %s(%s);\n", type_genname_str
,
4589 genname_str
, body
->get_single_expr(false).c_str());
4590 // make sure the template's code is not generated twice (TR: HU56425)
4591 body
->set_code_generated();
4593 // the default constructor is used
4594 str
= mputprintf(str
, "%s %s;\n", type_genname_str
, genname_str
);
4595 // the body is assigned in the subsequent statements
4596 str
= body
->generate_code_init(str
, genname_str
);
4599 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
4600 str
= Template::generate_restriction_check_code(str
, genname_str
,
4601 template_restriction
);
4603 if (debugger_active
) {
4604 str
= generate_code_debugger_add_var(str
, this);
4609 void Def_Template::ilt_generate_code(ILT
*ilt
)
4611 const string
& t_genname
= get_genname();
4612 const char *genname_str
= t_genname
.c_str();
4613 char*& def
=ilt
->get_out_def();
4614 char*& init
=ilt
->get_out_branches();
4616 const char *dispname_str
= id
->get_dispname().c_str();
4617 NOTSUPP("Code generation for parameterized local template `%s'",
4619 def
= mputprintf(def
, "/* NOT SUPPORTED: template %s */\n", dispname_str
);
4620 init
= mputprintf(init
, "/* NOT SUPPORTED: template %s */\n",
4623 // non-parameterized template
4624 // use the default constructor for initialization
4625 def
= mputprintf(def
, "%s %s;\n",
4626 type
->get_genname_template(my_scope
).c_str(), genname_str
);
4627 if (base_template
) {
4628 // copy the base template with an assignment
4629 init
= mputprintf(init
, "%s = %s;\n", genname_str
,
4630 base_template
->get_genname_from_scope(my_scope
).c_str());
4632 // finally assign the body
4633 init
= body
->generate_code_init(init
, genname_str
);
4634 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4635 init
= Template::generate_restriction_check_code(init
, genname_str
,
4636 template_restriction
);
4640 void Def_Template::dump_internal(unsigned level
) const
4642 DEBUG(level
, "Template: %s", id
->get_dispname().c_str());
4643 if (fp_list
) fp_list
->dump(level
+ 1);
4645 DEBUG(level
+ 1, "modifies: %s", derived_ref
->get_dispname().c_str());
4646 if (template_restriction
!=TR_NONE
)
4647 DEBUG(level
+ 1, "restriction: %s",
4648 Template::get_restriction_name(template_restriction
));
4649 type
->dump(level
+ 1);
4650 body
->dump(level
+ 1);
4653 // =================================
4655 // =================================
4657 Def_Var::Def_Var(Identifier
*p_id
, Type
*p_type
, Value
*p_initial_value
)
4658 : Definition(A_VAR
, p_id
), type(p_type
), initial_value(p_initial_value
)
4660 if (!p_type
) FATAL_ERROR("Ttcn::Def_Var::Def_Var()");
4661 type
->set_ownertype(Type::OT_VAR_DEF
, this);
4667 delete initial_value
;
4670 Def_Var
*Def_Var::clone() const
4672 FATAL_ERROR("Def_Var::clone");
4675 void Def_Var::set_fullname(const string
& p_fullname
)
4677 Definition::set_fullname(p_fullname
);
4678 type
->set_fullname(p_fullname
+ ".<type>");
4680 initial_value
->set_fullname(p_fullname
+ ".<initial_value>");
4683 void Def_Var::set_my_scope(Scope
*p_scope
)
4685 Definition::set_my_scope(p_scope
);
4686 type
->set_my_scope(p_scope
);
4687 if (initial_value
) initial_value
->set_my_scope(p_scope
);
4690 Type
*Def_Var::get_Type()
4699 Error_Context
cntxt(this, "In variable definition `%s'",
4700 id
->get_dispname().c_str());
4701 type
->set_genname(_T_
, get_genname());
4704 Type
*t
= type
->get_type_refd_last();
4705 switch (t
->get_typetype()) {
4707 error("Variable cannot be defined for port type `%s'",
4708 t
->get_fullname().c_str());
4710 case Type::T_SIGNATURE
:
4711 error("Variable cannot be defined for signature `%s'",
4712 t
->get_fullname().c_str());
4715 if (initial_value
) {
4716 initial_value
->set_my_governor(type
);
4717 type
->chk_this_value_ref(initial_value
);
4718 type
->chk_this_value(initial_value
, this, is_local() ?
4719 Type::EXPECTED_DYNAMIC_VALUE
: Type::EXPECTED_STATIC_VALUE
,
4720 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
4721 if (!semantic_check_only
) {
4722 initial_value
->set_genname_recursive(get_genname());
4723 initial_value
->set_code_section(GovernedSimple::CS_INLINE
);
4729 if (w_attrib_path
) {
4730 w_attrib_path
->chk_global_attrib();
4731 w_attrib_path
->chk_no_qualif();
4735 bool Def_Var::chk_identical(Definition
*p_def
)
4739 if (p_def
->get_asstype() != A_VAR
) {
4740 const char *dispname_str
= id
->get_dispname().c_str();
4741 error("Local definition `%s' is a variable, but the definition "
4742 "inherited from component type `%s' is a %s", dispname_str
,
4743 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
4744 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
4747 Def_Var
*p_def_var
= dynamic_cast<Def_Var
*>(p_def
);
4748 if (!p_def_var
) FATAL_ERROR("Def_Var::chk_identical()");
4749 if (!type
->is_identical(p_def_var
->type
)) {
4750 const char *dispname_str
= id
->get_dispname().c_str();
4751 type
->error("Local variable `%s' has type `%s', but the variable "
4752 "inherited from component type `%s' has type `%s'", dispname_str
,
4753 type
->get_typename().c_str(),
4754 p_def_var
->get_my_scope()->get_fullname().c_str(),
4755 p_def_var
->type
->get_typename().c_str());
4756 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4759 if (initial_value
) {
4760 if (p_def_var
->initial_value
) {
4761 if (!initial_value
->is_unfoldable() &&
4762 !p_def_var
->initial_value
->is_unfoldable() &&
4763 !(*initial_value
== *p_def_var
->initial_value
)) {
4764 const char *dispname_str
= id
->get_dispname().c_str();
4765 initial_value
->warning("Local variable `%s' and the variable "
4766 "inherited from component type `%s' have different initial values",
4767 dispname_str
, p_def_var
->get_my_scope()->get_fullname().c_str());
4768 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4771 const char *dispname_str
= id
->get_dispname().c_str();
4772 initial_value
->warning("Local variable `%s' has initial value, but "
4773 "the variable inherited from component type `%s' does not",
4774 dispname_str
, p_def_var
->get_my_scope()->get_fullname().c_str());
4775 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4777 } else if (p_def_var
->initial_value
) {
4778 const char *dispname_str
= id
->get_dispname().c_str();
4779 warning("Local variable `%s' does not have initial value, but the "
4780 "variable inherited from component type `%s' has", dispname_str
,
4781 p_def_var
->get_my_scope()->get_fullname().c_str());
4782 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4787 void Def_Var::generate_code(output_struct
*target
, bool clean_up
)
4789 type
->generate_code(target
);
4791 Code::init_cdef(&cdef
);
4792 type
->generate_code_object(&cdef
, my_scope
, get_genname(), 0, false);
4793 Code::merge_cdef(target
, &cdef
);
4794 Code::free_cdef(&cdef
);
4795 if (initial_value
) {
4796 target
->functions
.init_comp
=
4797 initial_value
->generate_code_init(target
->functions
.init_comp
,
4798 initial_value
->get_lhs_name().c_str());
4799 } else if (clean_up
) { // No initial value.
4800 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
4801 "%s.clean_up();\n", get_genname().c_str());
4805 void Def_Var::generate_code(CodeGenHelper
& cgh
)
4807 generate_code(cgh
.get_outputstruct(this));
4810 char *Def_Var::generate_code_str(char *str
)
4812 const string
& t_genname
= get_genname();
4813 const char *genname_str
= t_genname
.c_str();
4814 if (initial_value
&& initial_value
->has_single_expr()) {
4815 // the initial value can be represented by a single C++ expression
4816 // the object is initialized by the constructor
4817 str
= mputprintf(str
, "%s %s(%s);\n",
4818 type
->get_genname_value(my_scope
).c_str(), genname_str
,
4819 initial_value
->get_single_expr().c_str());
4821 // use the default constructor
4822 str
= mputprintf(str
, "%s %s;\n",
4823 type
->get_genname_value(my_scope
).c_str(), genname_str
);
4824 if (initial_value
) {
4825 // the initial value is assigned using subsequent statements
4826 str
= initial_value
->generate_code_init(str
, genname_str
);
4829 if (debugger_active
) {
4830 str
= generate_code_debugger_add_var(str
, this);
4835 void Def_Var::ilt_generate_code(ILT
*ilt
)
4837 const string
& t_genname
= get_genname();
4838 const char *genname_str
= t_genname
.c_str();
4839 char*& def
=ilt
->get_out_def();
4840 char*& init
=ilt
->get_out_branches();
4841 def
= mputprintf(def
, "%s %s;\n", type
->get_genname_value(my_scope
).c_str(),
4844 init
= initial_value
->generate_code_init(init
, genname_str
);
4847 char *Def_Var::generate_code_init_comp(char *str
, Definition
*base_defn
)
4849 if (initial_value
) {
4850 str
= initial_value
->generate_code_init(str
,
4851 base_defn
->get_genname_from_scope(my_scope
).c_str());
4856 void Def_Var::dump_internal(unsigned level
) const
4858 DEBUG(level
, "Variable %s", id
->get_dispname().c_str());
4859 type
->dump(level
+ 1);
4860 if (initial_value
) initial_value
->dump(level
+ 1);
4863 // =================================
4864 // ===== Def_Var_Template
4865 // =================================
4867 Def_Var_Template::Def_Var_Template(Identifier
*p_id
, Type
*p_type
,
4868 Template
*p_initial_value
, template_restriction_t p_template_restriction
)
4869 : Definition(A_VAR_TEMPLATE
, p_id
), type(p_type
),
4870 initial_value(p_initial_value
), template_restriction(p_template_restriction
)
4872 if (!p_type
) FATAL_ERROR("Ttcn::Def_Var_Template::Def_Var_Template()");
4873 type
->set_ownertype(Type::OT_VARTMPL_DEF
, this);
4876 Def_Var_Template::~Def_Var_Template()
4879 delete initial_value
;
4882 Def_Var_Template
*Def_Var_Template::clone() const
4884 FATAL_ERROR("Def_Var_Template::clone");
4887 void Def_Var_Template::set_fullname(const string
& p_fullname
)
4889 Definition::set_fullname(p_fullname
);
4890 type
->set_fullname(p_fullname
+ ".<type>");
4892 initial_value
->set_fullname(p_fullname
+ ".<initial_value>");
4895 void Def_Var_Template::set_my_scope(Scope
*p_scope
)
4897 Definition::set_my_scope(p_scope
);
4898 type
->set_my_scope(p_scope
);
4899 if (initial_value
) initial_value
->set_my_scope(p_scope
);
4902 Type
*Def_Var_Template::get_Type()
4908 void Def_Var_Template::chk()
4911 Error_Context
cntxt(this, "In template variable definition `%s'",
4912 id
->get_dispname().c_str());
4913 type
->set_genname(_T_
, get_genname());
4916 Type
*t
= type
->get_type_refd_last();
4917 if (t
->get_typetype() == Type::T_PORT
) {
4918 error("Template variable cannot be defined for port type `%s'",
4919 t
->get_fullname().c_str());
4922 if (initial_value
) {
4923 initial_value
->set_my_governor(type
);
4924 initial_value
->flatten(false);
4926 if (initial_value
->get_templatetype() == Template::CSTR_PATTERN
&&
4927 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
4928 initial_value
->set_templatetype(Template::USTR_PATTERN
);
4929 initial_value
->get_ustr_pattern()->set_pattern_type(
4930 PatternString::USTR_PATTERN
);
4933 type
->chk_this_template_ref(initial_value
);
4934 // temporary hack: to allow incomplete body as initial value
4935 // checking as a modified template, but without a base template
4936 type
->chk_this_template_generic(initial_value
, INCOMPLETE_ALLOWED
,
4937 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, IMPLICIT_OMIT
, 0);
4938 gen_restriction_check
=
4939 initial_value
->chk_restriction("template variable definition",
4940 template_restriction
, initial_value
);
4941 if (!semantic_check_only
) {
4942 initial_value
->set_genname_recursive(get_genname());
4943 initial_value
->set_code_section(GovernedSimple::CS_INLINE
);
4946 if (w_attrib_path
) {
4947 w_attrib_path
->chk_global_attrib();
4948 w_attrib_path
->chk_no_qualif();
4952 bool Def_Var_Template::chk_identical(Definition
*p_def
)
4956 if (p_def
->get_asstype() != A_VAR_TEMPLATE
) {
4957 const char *dispname_str
= id
->get_dispname().c_str();
4958 error("Local definition `%s' is a template variable, but the definition "
4959 "inherited from component type `%s' is a %s", dispname_str
,
4960 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
4961 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
4964 Def_Var_Template
*p_def_var_template
=
4965 dynamic_cast<Def_Var_Template
*>(p_def
);
4966 if (!p_def_var_template
) FATAL_ERROR("Def_Var_Template::chk_identical()");
4967 if (!type
->is_identical(p_def_var_template
->type
)) {
4968 const char *dispname_str
= id
->get_dispname().c_str();
4969 type
->error("Local template variable `%s' has type `%s', but the "
4970 "template variable inherited from component type `%s' has type `%s'",
4971 dispname_str
, type
->get_typename().c_str(),
4972 p_def_var_template
->get_my_scope()->get_fullname().c_str(),
4973 p_def_var_template
->type
->get_typename().c_str());
4974 p_def_var_template
->note("The inherited template variable `%s' is here",
4978 if (initial_value
) {
4979 if (!p_def_var_template
->initial_value
) {
4980 const char *dispname_str
= id
->get_dispname().c_str();
4981 initial_value
->warning("Local template variable `%s' has initial "
4982 "value, but the template variable inherited from component type "
4983 "`%s' does not", dispname_str
,
4984 p_def_var_template
->get_my_scope()->get_fullname().c_str());
4985 p_def_var_template
->note("The inherited template variable `%s' is here",
4988 } else if (p_def_var_template
->initial_value
) {
4989 const char *dispname_str
= id
->get_dispname().c_str();
4990 warning("Local template variable `%s' does not have initial value, but "
4991 "the template variable inherited from component type `%s' has",
4993 p_def_var_template
->get_my_scope()->get_fullname().c_str());
4994 p_def_var_template
->note("The inherited template variable `%s' is here",
5000 void Def_Var_Template::generate_code(output_struct
*target
, bool clean_up
)
5002 type
->generate_code(target
);
5004 Code::init_cdef(&cdef
);
5005 type
->generate_code_object(&cdef
, my_scope
, get_genname(), 0, true);
5006 Code::merge_cdef(target
, &cdef
);
5007 Code::free_cdef(&cdef
);
5008 if (initial_value
) {
5009 if (Common::Type::T_SEQOF
== initial_value
->get_my_governor()->get_typetype() ||
5010 Common::Type::T_ARRAY
== initial_value
->get_my_governor()->get_typetype()) {
5011 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5012 "%s.remove_all_permutations();\n", initial_value
->get_lhs_name().c_str());
5014 target
->functions
.init_comp
=
5015 initial_value
->generate_code_init(target
->functions
.init_comp
,
5016 initial_value
->get_lhs_name().c_str());
5017 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
5018 target
->functions
.init_comp
= Template::generate_restriction_check_code(
5019 target
->functions
.init_comp
, initial_value
->get_lhs_name().c_str(),
5020 template_restriction
);
5021 } else if (clean_up
) { // No initial value.
5022 // Always reset component variables/variable templates on component
5023 // reinitialization. Fix for HM79493.
5024 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5025 "%s.clean_up();\n", get_genname().c_str());
5029 void Def_Var_Template::generate_code(CodeGenHelper
& cgh
)
5031 generate_code(cgh
.get_outputstruct(this));
5034 char *Def_Var_Template::generate_code_str(char *str
)
5036 const string
& t_genname
= get_genname();
5037 const char *genname_str
= t_genname
.c_str();
5038 if (initial_value
&& initial_value
->has_single_expr()) {
5039 // The initial value can be represented by a single C++ expression
5040 // the object is initialized by the constructor.
5041 str
= mputprintf(str
, "%s %s(%s);\n",
5042 type
->get_genname_template(my_scope
).c_str(), genname_str
,
5043 initial_value
->get_single_expr(false).c_str());
5045 // Use the default constructor.
5046 str
= mputprintf(str
, "%s %s;\n",
5047 type
->get_genname_template(my_scope
).c_str(), genname_str
);
5048 if (initial_value
) {
5049 // The initial value is assigned using subsequent statements.
5050 if (use_runtime_2
&& TypeConv::needs_conv_refd(initial_value
))
5051 str
= TypeConv::gen_conv_code_refd(str
, genname_str
, initial_value
);
5052 else str
= initial_value
->generate_code_init(str
, genname_str
);
5055 if (initial_value
&& template_restriction
!= TR_NONE
5056 && gen_restriction_check
)
5057 str
= Template::generate_restriction_check_code(str
, genname_str
,
5058 template_restriction
);
5059 if (debugger_active
) {
5060 str
= generate_code_debugger_add_var(str
, this);
5065 void Def_Var_Template::ilt_generate_code(ILT
*ilt
)
5067 const string
& t_genname
= get_genname();
5068 const char *genname_str
= t_genname
.c_str();
5069 char*& def
=ilt
->get_out_def();
5070 char*& init
=ilt
->get_out_branches();
5071 def
= mputprintf(def
, "%s %s;\n",
5072 type
->get_genname_template(my_scope
).c_str(), genname_str
);
5073 if (initial_value
) {
5074 init
= initial_value
->generate_code_init(init
, genname_str
);
5075 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
5076 init
= Template::generate_restriction_check_code(init
, genname_str
,
5077 template_restriction
);
5081 char *Def_Var_Template::generate_code_init_comp(char *str
,
5082 Definition
*base_defn
)
5084 if (initial_value
) {
5085 str
= initial_value
->generate_code_init(str
,
5086 base_defn
->get_genname_from_scope(my_scope
).c_str());
5087 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
5088 str
= Template::generate_restriction_check_code(str
,
5089 base_defn
->get_genname_from_scope(my_scope
).c_str(),
5090 template_restriction
);
5095 void Def_Var_Template::dump_internal(unsigned level
) const
5097 DEBUG(level
, "Template variable %s", id
->get_dispname().c_str());
5098 if (template_restriction
!=TR_NONE
)
5099 DEBUG(level
+ 1, "restriction: %s",
5100 Template::get_restriction_name(template_restriction
));
5101 type
->dump(level
+ 1);
5102 if (initial_value
) initial_value
->dump(level
+ 1);
5105 // =================================
5107 // =================================
5109 Def_Timer::~Def_Timer()
5112 delete default_duration
;
5115 Def_Timer
*Def_Timer::clone() const
5117 FATAL_ERROR("Def_Timer::clone");
5120 void Def_Timer::set_fullname(const string
& p_fullname
)
5122 Definition::set_fullname(p_fullname
);
5123 if (dimensions
) dimensions
->set_fullname(p_fullname
+ ".<dimensions>");
5124 if (default_duration
)
5125 default_duration
->set_fullname(p_fullname
+ ".<default_duration>");
5128 void Def_Timer::set_my_scope(Scope
*p_scope
)
5130 Definition::set_my_scope(p_scope
);
5131 if (dimensions
) dimensions
->set_my_scope(p_scope
);
5132 if (default_duration
) default_duration
->set_my_scope(p_scope
);
5135 ArrayDimensions
*Def_Timer::get_Dimensions()
5137 if (!checked
) chk();
5141 void Def_Timer::chk()
5144 Error_Context
cntxt(this, "In timer definition `%s'",
5145 id
->get_dispname().c_str());
5146 if (dimensions
) dimensions
->chk();
5147 if (default_duration
) {
5148 Error_Context
cntxt2(default_duration
, "In default duration");
5149 if (dimensions
) chk_array_duration(default_duration
);
5150 else chk_single_duration(default_duration
);
5151 if (!semantic_check_only
) {
5152 default_duration
->set_code_section(GovernedSimple::CS_POST_INIT
);
5156 if (w_attrib_path
) {
5157 w_attrib_path
->chk_global_attrib();
5158 w_attrib_path
->chk_no_qualif();
5162 bool Def_Timer::chk_identical(Definition
*p_def
)
5166 if (p_def
->get_asstype() != A_TIMER
) {
5167 const char *dispname_str
= id
->get_dispname().c_str();
5168 error("Local definition `%s' is a timer, but the definition inherited "
5169 "from component type `%s' is a %s", dispname_str
,
5170 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
5171 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
5174 Def_Timer
*p_def_timer
= dynamic_cast<Def_Timer
*>(p_def
);
5175 if (!p_def_timer
) FATAL_ERROR("Def_Timer::chk_identical()");
5177 if (p_def_timer
->dimensions
) {
5178 if (!dimensions
->is_identical(p_def_timer
->dimensions
)) {
5179 const char *dispname_str
= id
->get_dispname().c_str();
5180 error("Local timer `%s' and the timer inherited from component type "
5181 "`%s' have different array dimensions", dispname_str
,
5182 p_def_timer
->get_my_scope()->get_fullname().c_str());
5183 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5187 const char *dispname_str
= id
->get_dispname().c_str();
5188 error("Local definition `%s' is a timer array, but the definition "
5189 "inherited from component type `%s' is a single timer", dispname_str
,
5190 p_def_timer
->get_my_scope()->get_fullname().c_str());
5191 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5194 } else if (p_def_timer
->dimensions
) {
5195 const char *dispname_str
= id
->get_dispname().c_str();
5196 error("Local definition `%s' is a single timer, but the definition "
5197 "inherited from component type `%s' is a timer array", dispname_str
,
5198 p_def_timer
->get_my_scope()->get_fullname().c_str());
5199 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5202 if (default_duration
) {
5203 if (p_def_timer
->default_duration
) {
5204 if (!default_duration
->is_unfoldable() &&
5205 !p_def_timer
->default_duration
->is_unfoldable() &&
5206 !(*default_duration
== *p_def_timer
->default_duration
)) {
5207 const char *dispname_str
= id
->get_dispname().c_str();
5208 default_duration
->warning("Local timer `%s' and the timer inherited "
5209 "from component type `%s' have different default durations",
5210 dispname_str
, p_def_timer
->get_my_scope()->get_fullname().c_str());
5211 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5214 const char *dispname_str
= id
->get_dispname().c_str();
5215 default_duration
->error("Local timer `%s' has default duration, but "
5216 "the timer inherited from component type `%s' does not", dispname_str
,
5217 p_def_timer
->get_my_scope()->get_fullname().c_str());
5218 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5221 } else if (p_def_timer
->default_duration
) {
5222 const char *dispname_str
= id
->get_dispname().c_str();
5223 error("Local timer `%s' does not have default duration, but the timer "
5224 "inherited from component type `%s' has", dispname_str
,
5225 p_def_timer
->get_my_scope()->get_fullname().c_str());
5226 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5232 bool Def_Timer::has_default_duration(FieldOrArrayRefs
*p_subrefs
)
5234 // return true in case of any uncertainity
5235 if (!default_duration
) return false;
5236 else if (!dimensions
|| !p_subrefs
) return true;
5237 Value
*v
= default_duration
;
5238 size_t nof_dims
= dimensions
->get_nof_dims();
5239 size_t nof_refs
= p_subrefs
->get_nof_refs();
5240 size_t upper_limit
= nof_dims
< nof_refs
? nof_dims
: nof_refs
;
5241 for (size_t i
= 0; i
< upper_limit
; i
++) {
5242 v
= v
->get_value_refd_last();
5243 if (v
->get_valuetype() != Value::V_SEQOF
) break;
5244 FieldOrArrayRef
*ref
= p_subrefs
->get_ref(i
);
5245 if (ref
->get_type() != FieldOrArrayRef::ARRAY_REF
) return true;
5246 Value
*v_index
= ref
->get_val()->get_value_refd_last();
5247 if (v_index
->get_valuetype() != Value::V_INT
) return true;
5248 Int index
= v_index
->get_val_Int()->get_val()
5249 - dimensions
->get_dim_byIndex(i
)->get_offset();
5250 if (index
>= 0 && index
< static_cast<Int
>(v
->get_nof_comps()))
5251 v
= v
->get_comp_byIndex(index
);
5254 return v
->get_valuetype() != Value::V_NOTUSED
;
5257 void Def_Timer::chk_single_duration(Value
*dur
)
5259 dur
->chk_expr_float(is_local() ?
5260 Type::EXPECTED_DYNAMIC_VALUE
: Type::EXPECTED_STATIC_VALUE
);
5261 Value
*v
= dur
->get_value_refd_last();
5262 if (v
->get_valuetype() == Value::V_REAL
) {
5263 ttcn3float v_real
= v
->get_val_Real();
5264 if ( (v_real
<0.0) || isSpecialFloatValue(v_real
) ) {
5265 dur
->error("A non-negative float value was expected "
5266 "as timer duration instead of `%s'", Real2string(v_real
).c_str());
5271 void Def_Timer::chk_array_duration(Value
*dur
, size_t start_dim
)
5273 ArrayDimension
*dim
= dimensions
->get_dim_byIndex(start_dim
);
5274 bool array_size_known
= !dim
->get_has_error();
5275 size_t array_size
= 0;
5276 if (array_size_known
) array_size
= dim
->get_size();
5277 Value
*v
= dur
->get_value_refd_last();
5278 switch (v
->get_valuetype()) {
5279 case Value::V_ERROR
:
5281 case Value::V_SEQOF
: {
5282 size_t nof_vs
= v
->get_nof_comps();
5283 // Value-list notation.
5284 if (!v
->is_indexed()) {
5285 if (array_size_known
) {
5286 if (array_size
> nof_vs
) {
5287 dur
->error("Too few elements in the default duration of timer "
5288 "array: %lu was expected instead of %lu",
5289 (unsigned long)array_size
, (unsigned long)nof_vs
);
5290 } else if (array_size
< nof_vs
) {
5291 dur
->error("Too many elements in the default duration of timer "
5292 "array: %lu was expected instead of %lu",
5293 (unsigned long)array_size
, (unsigned long)nof_vs
);
5296 bool last_dimension
= start_dim
+ 1 >= dimensions
->get_nof_dims();
5297 for (size_t i
= 0; i
< nof_vs
; i
++) {
5298 Value
*array_v
= v
->get_comp_byIndex(i
);
5299 if (array_v
->get_valuetype() == Value::V_NOTUSED
) continue;
5300 if (last_dimension
) chk_single_duration(array_v
);
5301 else chk_array_duration(array_v
, start_dim
+ 1);
5304 // Indexed-notation.
5305 bool last_dimension
= start_dim
+ 1 >= dimensions
->get_nof_dims();
5306 map
<Int
, Int
> index_map
;
5307 for (size_t i
= 0; i
< nof_vs
; i
++) {
5308 Value
*array_v
= v
->get_comp_byIndex(i
);
5309 if (array_v
->get_valuetype() == Value::V_NOTUSED
) continue;
5310 if (last_dimension
) chk_single_duration(array_v
);
5311 else chk_array_duration(array_v
, start_dim
+ 1);
5312 Error_Context
cntxt(this, "In timer array element %lu",
5313 (unsigned long)(i
+ 1));
5314 Value
*index
= v
->get_index_byIndex(i
);
5315 dim
->chk_index(index
, Type::EXPECTED_DYNAMIC_VALUE
);
5316 if (index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
5317 const int_val_t
*index_int
= index
->get_value_refd_last()
5319 if (*index_int
> INT_MAX
) {
5320 index
->error("An integer value less than `%d' was expected for "
5321 "indexing timer array instead of `%s'", INT_MAX
,
5322 (index_int
->t_str()).c_str());
5323 index
->set_valuetype(Value::V_ERROR
);
5325 Int index_val
= index_int
->get_val();
5326 if (index_map
.has_key(index_val
)) {
5327 index
->error("Duplicate index value `%s' for timer array "
5328 "elements `%s' and `%s'",
5329 Int2string(index_val
).c_str(),
5330 Int2string((Int
)i
+ 1).c_str(),
5331 Int2string(*index_map
[index_val
]).c_str());
5332 index
->set_valuetype(Value::V_ERROR
);
5334 index_map
.add(index_val
, new Int((Int
)i
+ 1));
5339 // It's not possible to have "index_map.size() > array_size", since we
5340 // add only correct constant-index values into the map. It's possible
5341 // to create partially initialized timer arrays.
5342 for (size_t i
= 0; i
< index_map
.size(); i
++)
5343 delete index_map
.get_nth_elem(i
);
5348 if (array_size_known
) {
5349 dur
->error("An array value (with %lu elements) was expected as "
5350 "default duration of timer array",
5351 (unsigned long)array_size
);
5353 dur
->error("An array value was expected as default duration of timer "
5356 dur
->set_valuetype(Value::V_ERROR
);
5361 void Def_Timer::generate_code(output_struct
*target
, bool)
5363 const string
& t_genname
= get_genname();
5364 const char *genname_str
= t_genname
.c_str();
5365 const string
& dispname
= id
->get_dispname();
5368 const string
& array_type
= dimensions
->get_timer_type();
5369 const char *array_type_str
= array_type
.c_str();
5370 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5371 "extern %s %s;\n", array_type_str
, genname_str
);
5372 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5373 "%s %s;\n", array_type_str
, genname_str
);
5374 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
, "{\n"
5375 "static const char * const timer_name = \"");
5376 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
5378 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
5380 "%s.set_name(timer_name);\n"
5381 "}\n", genname_str
);
5382 if (default_duration
) target
->functions
.post_init
=
5383 generate_code_array_duration(target
->functions
.post_init
, genname_str
,
5387 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5388 "extern TIMER %s;\n", genname_str
);
5389 if (default_duration
) {
5390 // has default duration
5391 Value
*v
= default_duration
->get_value_refd_last();
5392 if (v
->get_valuetype() == Value::V_REAL
) {
5393 // duration is known at compilation time -> set in the constructor
5394 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5395 "TIMER %s(\"%s\", %s);\n", genname_str
, dispname
.c_str(),
5396 v
->get_single_expr().c_str());
5398 // duration is known only at runtime -> set in post_init
5399 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5400 "TIMER %s(\"%s\");\n", genname_str
, dispname
.c_str());
5401 expression_struct expr
;
5402 Code::init_expr(&expr
);
5403 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5405 default_duration
->generate_code_expr(&expr
);
5406 expr
.expr
= mputc(expr
.expr
, ')');
5407 target
->functions
.post_init
=
5408 Code::merge_free_expr(target
->functions
.post_init
, &expr
);
5411 // does not have default duration
5412 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5413 "TIMER %s(\"%s\");\n", genname_str
, dispname
.c_str());
5418 void Def_Timer::generate_code(CodeGenHelper
& cgh
) {
5419 generate_code(cgh
.get_current_outputstruct());
5422 char *Def_Timer::generate_code_array_duration(char *str
,
5423 const char *object_name
, Value
*dur
, size_t start_dim
)
5425 ArrayDimension
*dim
= dimensions
->get_dim_byIndex(start_dim
);
5426 size_t dim_size
= dim
->get_size();
5427 Value
*v
= dur
->get_value_refd_last();
5428 if (v
->get_valuetype() != Value::V_SEQOF
5429 || (v
->get_nof_comps() != dim_size
&& !v
->is_indexed()))
5430 FATAL_ERROR("Def_Timer::generate_code_array_duration()");
5431 // Value-list notation.
5432 if (!v
->is_indexed()) {
5433 if (start_dim
+ 1 < dimensions
->get_nof_dims()) {
5434 // There are more dimensions, the elements of "v" are arrays a
5435 // temporary reference shall be introduced if the next dimension has
5436 // more than 1 elements.
5437 bool temp_ref_needed
=
5438 dimensions
->get_dim_byIndex(start_dim
+ 1)->get_size() > 1;
5439 for (size_t i
= 0; i
< dim_size
; i
++) {
5440 Value
*v_elem
= v
->get_comp_byIndex(i
);
5441 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5442 if (temp_ref_needed
) {
5443 const string
& tmp_id
= my_scope
->get_scope_mod_gen()
5444 ->get_temporary_id();
5445 const char *tmp_str
= tmp_id
.c_str();
5446 str
= mputprintf(str
, "{\n"
5447 "%s& %s = %s.array_element(%lu);\n",
5448 dimensions
->get_timer_type(start_dim
+ 1).c_str(),
5449 tmp_str
, object_name
, (unsigned long)i
);
5450 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5452 str
= mputstr(str
, "}\n");
5454 char *tmp_str
= mprintf("%s.array_element(%lu)", object_name
,
5456 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5462 // We are in the last dimension, the elements of "v" are floats.
5463 for (size_t i
= 0; i
< dim_size
; i
++) {
5464 Value
*v_elem
= v
->get_comp_byIndex(i
);
5465 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5466 expression_struct expr
;
5467 Code::init_expr(&expr
);
5468 expr
.expr
= mputprintf(expr
.expr
,
5469 "%s.array_element(%lu).set_default_duration(",
5470 object_name
, (unsigned long)i
);
5471 v_elem
->generate_code_expr(&expr
);
5472 expr
.expr
= mputc(expr
.expr
, ')');
5473 str
= Code::merge_free_expr(str
, &expr
);
5476 // Indexed-list notation.
5478 if (start_dim
+ 1 < dimensions
->get_nof_dims()) {
5479 bool temp_ref_needed
=
5480 dimensions
->get_dim_byIndex(start_dim
+ 1)->get_size() > 1;
5481 for (size_t i
= 0; i
< v
->get_nof_comps(); i
++) {
5482 Value
*v_elem
= v
->get_comp_byIndex(i
);
5483 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5484 if (temp_ref_needed
) {
5485 const string
& tmp_id
= my_scope
->get_scope_mod_gen()
5486 ->get_temporary_id();
5487 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5488 ->get_temporary_id();
5489 const char *tmp_str
= tmp_id
.c_str();
5490 str
= mputstr(str
, "{\n");
5491 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5492 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5494 str
= mputprintf(str
, "%s& %s = %s.array_element(%s);\n",
5495 dimensions
->get_timer_type(start_dim
+ 1).c_str(),
5496 tmp_str
, object_name
, idx_id
.c_str());
5497 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5499 str
= mputstr(str
, "}\n");
5501 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5502 ->get_temporary_id();
5503 str
= mputstr(str
, "{\n");
5504 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5505 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5507 char *tmp_str
= mprintf("%s.array_element(%s)", object_name
,
5509 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5511 str
= mputstr(str
, "}\n");
5516 for (size_t i
= 0; i
< v
->get_nof_comps(); i
++) {
5517 Value
*v_elem
= v
->get_comp_byIndex(i
);
5518 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5519 expression_struct expr
;
5520 Code::init_expr(&expr
);
5521 str
= mputstr(str
, "{\n");
5522 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5523 ->get_temporary_id();
5524 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5525 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5527 str
= mputprintf(str
,
5528 "%s.array_element(%s).set_default_duration(",
5529 object_name
, idx_id
.c_str());
5530 v_elem
->generate_code_expr(&expr
);
5531 expr
.expr
= mputc(expr
.expr
, ')');
5532 str
= Code::merge_free_expr(str
, &expr
);
5533 str
= mputstr(str
, "}\n");
5540 char *Def_Timer::generate_code_str(char *str
)
5542 const string
& t_genname
= get_genname();
5543 const char *genname_str
= t_genname
.c_str();
5544 const string
& dispname
= id
->get_dispname();
5547 const string
& array_type
= dimensions
->get_timer_type();
5548 const char *array_type_str
= array_type
.c_str();
5549 str
= mputprintf(str
, "%s %s;\n", array_type_str
, genname_str
);
5550 str
= mputstr(str
, "{\n"
5551 "static const char * const timer_name = \"");
5552 str
= mputstr(str
, dispname
.c_str());
5553 str
= mputprintf(str
, "\";\n"
5554 "%s.set_name(timer_name);\n"
5555 "}\n", genname_str
);
5556 if (default_duration
) str
= generate_code_array_duration(str
,
5557 genname_str
, default_duration
);
5560 if (default_duration
&& default_duration
->has_single_expr()) {
5561 // the default duration can be passed to the constructor
5562 str
= mputprintf(str
, "TIMER %s(\"%s\", %s);\n", genname_str
,
5563 dispname
.c_str(), default_duration
->get_single_expr().c_str());
5565 // only the name is passed to the constructor
5566 str
= mputprintf(str
, "TIMER %s(\"%s\");\n", genname_str
,
5568 if (default_duration
) {
5569 // the default duration is set explicitly
5570 expression_struct expr
;
5571 Code::init_expr(&expr
);
5572 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5574 default_duration
->generate_code_expr(&expr
);
5575 expr
.expr
= mputc(expr
.expr
, ')');
5576 str
= Code::merge_free_expr(str
, &expr
);
5580 if (debugger_active
) {
5581 str
= generate_code_debugger_add_var(str
, this);
5586 void Def_Timer::ilt_generate_code(ILT
*ilt
)
5588 const string
& t_genname
= get_genname();
5589 const char *genname_str
= t_genname
.c_str();
5590 const string
& dispname
= id
->get_dispname();
5592 char*& def
= ilt
->get_out_def();
5593 char*& init
= ilt
->get_out_branches();
5597 const string
& array_type
= dimensions
->get_timer_type();
5598 const char *array_type_str
= array_type
.c_str();
5599 def
= mputprintf(def
, "%s %s;\n", array_type_str
, genname_str
);
5600 def
= mputstr(def
, "{\n"
5601 "static const char * const timer_names[] = { ");
5602 def
= dimensions
->generate_element_names(def
, dispname
);
5603 def
= mputprintf(def
, " };\n"
5604 "%s.set_name(%lu, timer_names);\n"
5605 "}\n", genname_str
, (unsigned long) dimensions
->get_array_size());
5606 if (default_duration
) init
= generate_code_array_duration(init
,
5607 genname_str
, default_duration
);
5610 if (default_duration
) {
5611 // has default duration
5612 Value
*v
= default_duration
->get_value_refd_last();
5613 if (v
->get_valuetype() == Value::V_REAL
) {
5614 // duration is known at compilation time -> set in the constructor
5615 def
= mputprintf(def
, "TIMER %s(\"%s\", %s);\n", genname_str
,
5616 dispname
.c_str(), v
->get_single_expr().c_str());
5618 // duration is known only at runtime -> set when control reaches the
5620 def
= mputprintf(def
, "TIMER %s(\"%s\");\n", genname_str
,
5622 expression_struct expr
;
5623 Code::init_expr(&expr
);
5624 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5626 default_duration
->generate_code_expr(&expr
);
5627 expr
.expr
= mputc(expr
.expr
, ')');
5628 init
= Code::merge_free_expr(init
, &expr
);
5631 // does not have default duration
5632 def
= mputprintf(def
, "TIMER %s(\"%s\");\n", genname_str
,
5638 char *Def_Timer::generate_code_init_comp(char *str
, Definition
*base_defn
)
5640 if (default_duration
) {
5641 Def_Timer
*base_timer_defn
= dynamic_cast<Def_Timer
*>(base_defn
);
5642 if (!base_timer_defn
|| !base_timer_defn
->default_duration
)
5643 FATAL_ERROR("Def_Timer::generate_code_init_comp()");
5644 // initializer is not needed if the default durations are the same
5645 // constants in both timers
5646 if (default_duration
->is_unfoldable() ||
5647 base_timer_defn
->default_duration
->is_unfoldable() ||
5648 !(*default_duration
== *base_timer_defn
->default_duration
)) {
5650 str
= generate_code_array_duration(str
,
5651 base_timer_defn
->get_genname_from_scope(my_scope
).c_str(),
5654 expression_struct expr
;
5655 Code::init_expr(&expr
);
5656 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5657 base_timer_defn
->get_genname_from_scope(my_scope
).c_str());
5658 default_duration
->generate_code_expr(&expr
);
5659 expr
.expr
= mputc(expr
.expr
, ')');
5660 str
= Code::merge_free_expr(str
, &expr
);
5667 void Def_Timer::dump_internal(unsigned level
) const
5669 DEBUG(level
, "Timer: %s", id
->get_dispname().c_str());
5670 if (dimensions
) dimensions
->dump(level
+ 1);
5671 if (default_duration
) {
5672 DEBUG(level
+ 1, "Default duration:");
5673 default_duration
->dump(level
+ 1);
5677 // =================================
5679 // =================================
5681 Def_Port::Def_Port(Identifier
*p_id
, Reference
*p_tref
,
5682 ArrayDimensions
*p_dims
)
5683 : Definition(A_PORT
, p_id
), type_ref(p_tref
), port_type(0),
5686 if (!p_tref
) FATAL_ERROR("Def_Port::Def_Port()");
5689 Def_Port::~Def_Port()
5695 Def_Port
*Def_Port::clone() const
5697 FATAL_ERROR("Def_Port::clone");
5700 void Def_Port::set_fullname(const string
& p_fullname
)
5702 Definition::set_fullname(p_fullname
);
5703 type_ref
->set_fullname(p_fullname
+ ".<type_ref>");
5704 if (dimensions
) dimensions
->set_fullname(p_fullname
);
5707 void Def_Port::set_my_scope(Scope
*p_scope
)
5709 Definition::set_my_scope(p_scope
);
5710 type_ref
->set_my_scope(p_scope
);
5711 if (dimensions
) dimensions
->set_my_scope(p_scope
);
5714 Type
*Def_Port::get_Type()
5720 ArrayDimensions
*Def_Port::get_Dimensions()
5722 if (!checked
) chk();
5726 void Def_Port::chk()
5728 if (checked
) return;
5730 Error_Context
cntxt(this, "In port definition `%s'",
5731 id
->get_dispname().c_str());
5732 Common::Assignment
*ass
= type_ref
->get_refd_assignment();
5734 if (ass
->get_asstype() == A_TYPE
) {
5735 Type
*t
= ass
->get_Type()->get_type_refd_last();
5736 if (t
->get_typetype() == Type::T_PORT
) port_type
= t
;
5737 else type_ref
->error("Type reference `%s' does not refer to a "
5738 "port type", type_ref
->get_dispname().c_str());
5739 } else type_ref
->error("Reference `%s' does not refer to a "
5740 "type", type_ref
->get_dispname().c_str());
5742 if (dimensions
) dimensions
->chk();
5743 if (w_attrib_path
) {
5744 w_attrib_path
->chk_global_attrib();
5745 w_attrib_path
->chk_no_qualif();
5749 bool Def_Port::chk_identical(Definition
*p_def
)
5753 if (p_def
->get_asstype() != A_PORT
) {
5754 const char *dispname_str
= id
->get_dispname().c_str();
5755 error("Local definition `%s' is a port, but the definition inherited "
5756 "from component type `%s' is a %s", dispname_str
,
5757 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
5758 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
5761 Def_Port
*p_def_port
= dynamic_cast<Def_Port
*>(p_def
);
5762 if (!p_def_port
) FATAL_ERROR("Def_Port::chk_identical()");
5763 if (port_type
&& p_def_port
->port_type
&&
5764 port_type
!= p_def_port
->port_type
) {
5765 const char *dispname_str
= id
->get_dispname().c_str();
5766 type_ref
->error("Local port `%s' has type `%s', but the port inherited "
5767 "from component type `%s' has type `%s'", dispname_str
,
5768 port_type
->get_typename().c_str(),
5769 p_def_port
->get_my_scope()->get_fullname().c_str(),
5770 p_def_port
->port_type
->get_typename().c_str());
5771 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5775 if (p_def_port
->dimensions
) {
5776 if (!dimensions
->is_identical(p_def_port
->dimensions
)) {
5777 const char *dispname_str
= id
->get_dispname().c_str();
5778 error("Local port `%s' and the port inherited from component type "
5779 "`%s' have different array dimensions", dispname_str
,
5780 p_def_port
->get_my_scope()->get_fullname().c_str());
5781 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5785 const char *dispname_str
= id
->get_dispname().c_str();
5786 error("Local definition `%s' is a port array, but the definition "
5787 "inherited from component type `%s' is a single port", dispname_str
,
5788 p_def_port
->get_my_scope()->get_fullname().c_str());
5789 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5792 } else if (p_def_port
->dimensions
) {
5793 const char *dispname_str
= id
->get_dispname().c_str();
5794 error("Local definition `%s' is a single port, but the definition "
5795 "inherited from component type `%s' is a port array", dispname_str
,
5796 p_def_port
->get_my_scope()->get_fullname().c_str());
5797 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5803 void Def_Port::generate_code(output_struct
*target
, bool)
5805 const string
& t_genname
= get_genname();
5806 const char *genname_str
= t_genname
.c_str();
5807 const string
& type_genname
= port_type
->get_genname_value(my_scope
);
5808 const string
& dispname
= id
->get_dispname();
5811 const string
& array_type
= dimensions
->get_port_type(type_genname
);
5812 const char *array_type_str
= array_type
.c_str();
5813 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5814 "extern %s %s;\n", array_type_str
, genname_str
);
5815 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5816 "%s %s;\n", array_type_str
, genname_str
);
5817 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
, "{\n"
5818 "static const char * const port_name = \"");
5819 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
5821 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
5823 "%s.set_name(port_name);\n"
5824 "}\n", genname_str
);
5827 const char *type_genname_str
= type_genname
.c_str();
5828 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5829 "extern %s %s;\n", type_genname_str
, genname_str
);
5830 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5831 "%s %s(\"%s\");\n", type_genname_str
, genname_str
, dispname
.c_str());
5833 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5834 "%s.activate_port();\n", genname_str
);
5837 void Def_Port::generate_code(CodeGenHelper
& cgh
) {
5838 generate_code(cgh
.get_current_outputstruct());
5841 char *Def_Port::generate_code_init_comp(char *str
, Definition
*base_defn
)
5843 return mputprintf(str
, "%s.activate_port();\n",
5844 base_defn
->get_genname_from_scope(my_scope
).c_str());
5847 void Def_Port::dump_internal(unsigned level
) const
5849 DEBUG(level
, "Port: %s", id
->get_dispname().c_str());
5850 DEBUG(level
+ 1, "Port type:");
5851 type_ref
->dump(level
+ 2);
5852 if (dimensions
) dimensions
->dump(level
+ 1);
5855 // =================================
5856 // ===== Def_Function_Base
5857 // =================================
5859 Def_Function_Base::asstype_t
Def_Function_Base::determine_asstype(
5860 bool is_external
, bool has_return_type
, bool returns_template
)
5863 if (has_return_type
) {
5864 if (returns_template
) return A_EXT_FUNCTION_RTEMP
;
5865 else return A_EXT_FUNCTION_RVAL
;
5867 if (returns_template
)
5868 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5869 return A_EXT_FUNCTION
;
5871 } else { // not an external function
5872 if (has_return_type
) {
5873 if (returns_template
) return A_FUNCTION_RTEMP
;
5874 else return A_FUNCTION_RVAL
;
5876 if (returns_template
)
5877 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5883 Def_Function_Base::Def_Function_Base(const Def_Function_Base
& p
)
5884 : Definition(p
), prototype(PROTOTYPE_NONE
), input_type(0), output_type(0)
5886 fp_list
= p
.fp_list
->clone();
5887 fp_list
->set_my_def(this);
5888 return_type
= p
.return_type
? p
.return_type
->clone() : 0;
5889 template_restriction
= p
.template_restriction
;
5892 Def_Function_Base::Def_Function_Base(bool is_external
, Identifier
*p_id
,
5893 FormalParList
*p_fpl
, Type
*p_return_type
, bool returns_template
,
5894 template_restriction_t p_template_restriction
)
5895 : Definition(determine_asstype(is_external
, p_return_type
!= 0,
5896 returns_template
), p_id
), fp_list(p_fpl
), return_type(p_return_type
),
5897 prototype(PROTOTYPE_NONE
), input_type(0), output_type(0),
5898 template_restriction(p_template_restriction
)
5900 if (!p_fpl
) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
5901 fp_list
->set_my_def(this);
5902 if (return_type
) return_type
->set_ownertype(Type::OT_FUNCTION_DEF
, this);
5905 Def_Function_Base::~Def_Function_Base()
5911 void Def_Function_Base::set_fullname(const string
& p_fullname
)
5913 Definition::set_fullname(p_fullname
);
5914 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
5915 if (return_type
) return_type
->set_fullname(p_fullname
+ ".<return_type>");
5918 void Def_Function_Base::set_my_scope(Scope
*p_scope
)
5920 Definition::set_my_scope(p_scope
);
5921 fp_list
->set_my_scope(p_scope
);
5922 if (return_type
) return_type
->set_my_scope(p_scope
);
5925 Type
*Def_Function_Base::get_Type()
5927 if (!checked
) chk();
5931 FormalParList
*Def_Function_Base::get_FormalParList()
5933 if (!checked
) chk();
5937 const char *Def_Function_Base::get_prototype_name() const
5939 switch (prototype
) {
5940 case PROTOTYPE_NONE
:
5941 return "<no prototype>";
5942 case PROTOTYPE_CONVERT
:
5944 case PROTOTYPE_FAST
:
5946 case PROTOTYPE_BACKTRACK
:
5948 case PROTOTYPE_SLIDING
:
5951 return "<unknown prototype>";
5955 void Def_Function_Base::chk_prototype()
5957 switch (prototype
) {
5958 case PROTOTYPE_NONE
:
5959 // return immediately
5961 case PROTOTYPE_CONVERT
:
5962 case PROTOTYPE_FAST
:
5963 case PROTOTYPE_BACKTRACK
:
5964 case PROTOTYPE_SLIDING
:
5965 // perform the checks below
5968 FATAL_ERROR("Def_Function_Base::chk_prototype()");
5970 // checking the formal parameter list
5971 if (prototype
== PROTOTYPE_CONVERT
) {
5972 if (fp_list
->get_nof_fps() == 1) {
5973 FormalPar
*par
= fp_list
->get_fp_byIndex(0);
5974 if (par
->get_asstype() == A_PAR_VAL_IN
) {
5975 input_type
= par
->get_Type();
5977 par
->error("The parameter must be an `in' value parameter for "
5978 "attribute `prototype(%s)' instead of %s", get_prototype_name(),
5979 par
->get_assname());
5982 fp_list
->error("The function must have one parameter instead of %lu "
5983 "for attribute `prototype(%s)'", (unsigned long) fp_list
->get_nof_fps(),
5984 get_prototype_name());
5986 } else { // not PROTOTYPE_CONVERT
5987 if (fp_list
->get_nof_fps() == 2) {
5988 FormalPar
*first_par
= fp_list
->get_fp_byIndex(0);
5989 if (prototype
== PROTOTYPE_SLIDING
) {
5990 if (first_par
->get_asstype() == A_PAR_VAL_INOUT
) {
5991 Type
*first_par_type
= first_par
->get_Type();
5992 switch (first_par_type
->get_type_refd_last()
5993 ->get_typetype_ttcn3()) {
5998 input_type
= first_par_type
;
6001 first_par_type
->error("The type of the first parameter must be "
6002 "`octetstring' or `charstring' or `bitstring' for attribute "
6003 "`prototype(%s)' instead of `%s'", get_prototype_name(),
6004 first_par_type
->get_typename().c_str());
6007 first_par
->error("The first parameter must be an `inout' value "
6008 "parameter for attribute `prototype(%s)' instead of %s",
6009 get_prototype_name(), first_par
->get_assname());
6012 if (first_par
->get_asstype() == A_PAR_VAL_IN
) {
6013 input_type
= first_par
->get_Type();
6015 first_par
->error("The first parameter must be an `in' value "
6016 "parameter for attribute `prototype(%s)' instead of %s",
6017 get_prototype_name(), first_par
->get_assname());
6020 FormalPar
*second_par
= fp_list
->get_fp_byIndex(1);
6021 if (second_par
->get_asstype() == A_PAR_VAL_OUT
) {
6022 output_type
= second_par
->get_Type();
6024 second_par
->error("The second parameter must be an `out' value "
6025 "parameter for attribute `prototype(%s)' instead of %s",
6026 get_prototype_name(), second_par
->get_assname());
6029 fp_list
->error("The function must have two parameters for attribute "
6030 "`prototype(%s)' instead of %lu", get_prototype_name(),
6031 (unsigned long) fp_list
->get_nof_fps());
6034 // checking the return type
6035 if (prototype
== PROTOTYPE_FAST
) {
6037 return_type
->error("The function cannot have return type for "
6038 "attribute `prototype(%s)'", get_prototype_name());
6042 if (asstype
== A_FUNCTION_RTEMP
|| asstype
== A_EXT_FUNCTION_RTEMP
)
6043 return_type
->error("The function must return a value instead of a "
6044 "template for attribute `prototype(%s)'", get_prototype_name());
6045 if (prototype
== PROTOTYPE_CONVERT
) {
6046 output_type
= return_type
;
6048 switch (return_type
->get_type_refd_last()->get_typetype_ttcn3()) {
6053 return_type
->error("The return type of the function must be "
6054 "`integer' instead of `%s' for attribute `prototype(%s)'",
6055 return_type
->get_typename().c_str(), get_prototype_name());
6059 error("The function must have return type for attribute "
6060 "`prototype(%s)'", get_prototype_name());
6063 // checking the 'runs on' clause
6064 if (get_RunsOnType()) {
6065 error("The function cannot have `runs on' clause for attribute "
6066 "`prototype(%s)'", get_prototype_name());
6070 Type
*Def_Function_Base::get_input_type()
6072 if (!checked
) chk();
6076 Type
*Def_Function_Base::get_output_type()
6078 if (!checked
) chk();
6083 // =================================
6084 // ===== Def_Function
6085 // =================================
6087 Def_Function::Def_Function(Identifier
*p_id
, FormalParList
*p_fpl
,
6088 Reference
*p_runs_on_ref
, Type
*p_return_type
,
6089 bool returns_template
,
6090 template_restriction_t p_template_restriction
,
6091 StatementBlock
*p_block
)
6092 : Def_Function_Base(false, p_id
, p_fpl
, p_return_type
, returns_template
,
6093 p_template_restriction
),
6094 runs_on_ref(p_runs_on_ref
), runs_on_type(0), block(p_block
),
6095 is_startable(false), transparent(false)
6097 if (!p_block
) FATAL_ERROR("Def_Function::Def_Function()");
6098 block
->set_my_def(this);
6101 Def_Function::~Def_Function()
6107 Def_Function
*Def_Function::clone() const
6109 FATAL_ERROR("Def_Function::clone");
6112 void Def_Function::set_fullname(const string
& p_fullname
)
6114 Def_Function_Base::set_fullname(p_fullname
);
6115 if (runs_on_ref
) runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
6116 block
->set_fullname(p_fullname
+ ".<statement_block>");
6119 void Def_Function::set_my_scope(Scope
*p_scope
)
6121 bridgeScope
.set_parent_scope(p_scope
);
6122 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
6124 Def_Function_Base::set_my_scope(&bridgeScope
);
6125 if (runs_on_ref
) runs_on_ref
->set_my_scope(&bridgeScope
);
6126 block
->set_my_scope(fp_list
);
6129 Type
*Def_Function::get_RunsOnType()
6131 if (!checked
) chk();
6132 return runs_on_type
;
6135 RunsOnScope
*Def_Function::get_runs_on_scope(Type
*comptype
)
6137 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
6138 if (!my_module
) FATAL_ERROR("Def_Function::get_runs_on_scope()");
6139 return my_module
->get_runs_on_scope(comptype
);
6142 void Def_Function::chk()
6144 if (checked
) return;
6146 Error_Context
cntxt(this, "In function definition `%s'",
6147 id
->get_dispname().c_str());
6148 // checking the `runs on' clause
6150 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
6151 runs_on_type
= runs_on_ref
->chk_comptype_ref();
6152 // override the scope of the formal parameter list
6154 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
6155 runs_on_scope
->set_parent_scope(my_scope
);
6156 fp_list
->set_my_scope(runs_on_scope
);
6159 // checking the formal parameter list
6160 fp_list
->chk(asstype
);
6161 // checking of return type
6163 Error_Context
cntxt2(return_type
, "In return type");
6165 return_type
->chk_as_return_type(asstype
== A_FUNCTION_RVAL
,"function");
6167 // decision of startability
6168 is_startable
= runs_on_ref
!= 0;
6169 if (is_startable
&& !fp_list
->get_startability()) is_startable
= false;
6170 if (is_startable
&& return_type
&& return_type
->is_component_internal())
6171 is_startable
= false;
6172 // checking of statement block
6175 // checking the presence of return statements
6176 switch (block
->has_return()) {
6177 case StatementBlock::RS_NO
:
6178 error("The function has return type, but it does not have any return "
6181 case StatementBlock::RS_MAYBE
:
6182 error("The function has return type, but control might leave it "
6183 "without reaching a return statement");
6188 if (!semantic_check_only
) {
6189 fp_list
->set_genname(get_genname());
6190 block
->set_code_section(GovernedSimple::CS_INLINE
);
6192 if (w_attrib_path
) {
6193 w_attrib_path
->chk_global_attrib();
6194 w_attrib_path
->chk_no_qualif();
6195 Ttcn::ExtensionAttributes
* extattrs
= parse_extattributes(w_attrib_path
);
6196 if (extattrs
!= 0) { // NULL means parsing error
6197 size_t num_atrs
= extattrs
->size();
6198 for (size_t i
=0; i
< num_atrs
; ++i
) {
6199 ExtensionAttribute
&ea
= extattrs
->get(i
);
6200 switch (ea
.get_type()) {
6201 case ExtensionAttribute::PROTOTYPE
: {
6202 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE
) {
6203 ea
.error("Duplicate attribute `prototype'");
6205 Def_Function_Base::prototype_t proto
= ea
.get_proto();
6206 set_prototype(proto
);
6209 case ExtensionAttribute::ANYTYPELIST
: // ignore it
6210 case ExtensionAttribute::NONE
: // erroneous, do not issue an error
6213 case ExtensionAttribute::TRANSPARENT
:
6217 case ExtensionAttribute::ENCODE
:
6218 case ExtensionAttribute::DECODE
:
6219 case ExtensionAttribute::ERRORBEHAVIOR
:
6220 case ExtensionAttribute::PRINTING
:
6221 ea
.error("Extension attribute 'encode', 'decode', 'errorbehavior'"
6222 " or 'printing' can only be applied to external functions");
6225 default: // complain
6226 ea
.error("Function definition can only have the 'prototype'"
6227 " extension attribute");
6237 bool Def_Function::chk_startable()
6239 if (!checked
) chk();
6240 if (is_startable
) return true;
6241 if (!runs_on_ref
) error("Function `%s' cannot be started on a parallel "
6242 "test component because it does not have `runs on' clause",
6243 get_fullname().c_str());
6244 fp_list
->chk_startability("Function", get_fullname().c_str());
6245 if (return_type
&& return_type
->is_component_internal()) {
6246 map
<Type
*,void> type_chain
;
6247 char* err_str
= mprintf("the return type or embedded in the return type "
6248 "of function `%s' if it is started on a parallel test component",
6249 get_fullname().c_str());
6250 return_type
->chk_component_internal(type_chain
, err_str
);
6256 void Def_Function::generate_code(output_struct
*target
, bool)
6258 transparency_holder
glass(*this);
6259 const string
& t_genname
= get_genname();
6260 const char *genname_str
= t_genname
.c_str();
6261 const char *dispname_str
= id
->get_dispname().c_str();
6262 string return_type_name
;
6265 return_type_name
= "void";
6267 case A_FUNCTION_RVAL
:
6268 return_type_name
= return_type
->get_genname_value(my_scope
);
6270 case A_FUNCTION_RTEMP
:
6271 return_type_name
= return_type
->get_genname_template(my_scope
);
6274 FATAL_ERROR("Def_Function::generate_code()");
6276 const char *return_type_str
= return_type_name
.c_str();
6278 // assemble the function body first (this also determines which parameters
6280 char* body
= create_location_object(memptystr(), "FUNCTION", dispname_str
);
6281 if (!enable_set_bound_out_param
)
6282 body
= fp_list
->generate_code_set_unbound(body
); // conform the standard out parameter is unbound
6283 body
= fp_list
->generate_shadow_objects(body
);
6284 if (debugger_active
) {
6285 body
= generate_code_debugger_function_init(body
, this);
6287 body
= block
->generate_code(body
);
6288 // smart formal parameter list (names of unused parameters are omitted)
6289 char *formal_par_list
= fp_list
->generate_code(memptystr());
6290 fp_list
->generate_code_defval(target
);
6291 // function prototype
6292 target
->header
.function_prototypes
=
6293 mputprintf(target
->header
.function_prototypes
, "extern %s %s(%s);\n",
6294 return_type_str
, genname_str
, formal_par_list
);
6297 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
6301 "}\n\n", return_type_str
, genname_str
, formal_par_list
, body
);
6302 Free(formal_par_list
);
6306 size_t nof_fps
= fp_list
->get_nof_fps();
6307 // use the full list of formal parameters here (since they are all logged)
6308 char *full_formal_par_list
= fp_list
->generate_code(memptystr(), nof_fps
);
6309 // starter function (stub)
6310 // function prototype
6311 target
->header
.function_prototypes
=
6312 mputprintf(target
->header
.function_prototypes
,
6313 "extern void start_%s(const COMPONENT& component_reference%s%s);\n",
6314 genname_str
, nof_fps
>0?", ":"", full_formal_par_list
);
6316 body
= mprintf("void start_%s(const COMPONENT& component_reference%s"
6319 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6320 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6321 genname_str
, nof_fps
>0?", ":"", full_formal_par_list
, dispname_str
);
6322 for (size_t i
= 0; i
< nof_fps
; i
++) {
6323 if (i
> 0) body
= mputstr(body
,
6324 "TTCN_Logger::log_event_str(\", \");\n");
6325 body
= mputprintf(body
, "%s.log();\n",
6326 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6328 body
= mputprintf(body
,
6329 "TTCN_Logger::log_event_str(\") on component \");\n"
6330 "component_reference.log();\n"
6331 "TTCN_Logger::log_char('.');\n"
6332 "TTCN_Logger::end_event();\n"
6333 "Text_Buf text_buf;\n"
6334 "TTCN_Runtime::prepare_start_component(component_reference, "
6335 "\"%s\", \"%s\", text_buf);\n",
6336 my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
6338 for (size_t i
= 0; i
< nof_fps
; i
++) {
6339 body
= mputprintf(body
, "%s.encode_text(text_buf);\n",
6340 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6342 body
= mputstr(body
, "TTCN_Runtime::send_start_component(text_buf);\n"
6344 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
6348 // an entry in start_ptc_function
6349 body
= mprintf("if (!strcmp(function_name, \"%s\")) {\n",
6352 body
= fp_list
->generate_code_object(body
, "", ' ');
6353 for (size_t i
= 0; i
< nof_fps
; i
++) {
6354 body
= mputprintf(body
, "%s.decode_text(function_arguments);\n",
6355 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6357 body
= mputprintf(body
,
6358 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6359 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6361 for (size_t i
= 0; i
< nof_fps
; i
++) {
6362 if (i
> 0) body
= mputstr(body
,
6363 "TTCN_Logger::log_event_str(\", \");\n");
6364 body
= mputprintf(body
, "%s.log();\n",
6365 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6367 body
= mputstr(body
, "TTCN_Logger::log_event_str(\").\");\n"
6368 "TTCN_Logger::end_event();\n");
6370 body
= mputprintf(body
,
6371 "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
6372 "%s().\");\n", dispname_str
);
6374 body
= mputstr(body
,
6375 "TTCN_Runtime::function_started(function_arguments);\n");
6376 char *actual_par_list
=
6377 fp_list
->generate_code_actual_parlist(memptystr(), "");
6378 bool return_value_kept
= false;
6379 if (asstype
== A_FUNCTION_RVAL
) {
6380 // the return value is kept only if the function returns a value
6381 // (rather than a template) and the return type has the "done"
6382 // extension attribute
6383 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
6384 if (t
->has_done_attribute()) {
6385 return_value_kept
= true;
6387 } else if (!t
->is_ref()) break;
6390 if (return_value_kept
) {
6391 const string
& return_type_dispname
= return_type
->get_typename();
6392 const char *return_type_dispname_str
= return_type_dispname
.c_str();
6393 body
= mputprintf(body
, "%s ret_val(%s(%s));\n"
6394 "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
6395 "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
6397 "Text_Buf text_buf;\n"
6398 "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
6399 "ret_val.encode_text(text_buf);\n"
6400 "TTCN_Runtime::send_function_finished(text_buf);\n",
6401 return_type_str
, genname_str
, actual_par_list
, dispname_str
,
6402 return_type_dispname_str
, return_type_dispname_str
);
6404 body
= mputprintf(body
, "%s(%s);\n"
6405 "TTCN_Runtime::function_finished(\"%s\");\n",
6406 genname_str
, actual_par_list
, dispname_str
);
6408 Free(actual_par_list
);
6409 body
= mputstr(body
, "return TRUE;\n"
6411 target
->functions
.start
= mputstr(target
->functions
.start
, body
);
6413 Free(full_formal_par_list
);
6416 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
6417 "%s.add_function(\"%s\", (genericfunc_t)&%s, ", get_module_object_name(),
6418 dispname_str
, genname_str
);
6420 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
6421 "(genericfunc_t)&start_%s);\n", genname_str
);
6423 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
6427 void Def_Function::generate_code(CodeGenHelper
& cgh
) {
6428 generate_code(cgh
.get_current_outputstruct());
6431 void Def_Function::dump_internal(unsigned level
) const
6433 DEBUG(level
, "Function: %s", id
->get_dispname().c_str());
6434 DEBUG(level
+ 1, "Parameters:");
6435 fp_list
->dump(level
+ 1);
6437 DEBUG(level
+ 1, "Runs on clause:");
6438 runs_on_ref
->dump(level
+ 2);
6441 DEBUG(level
+ 1, "Return type:");
6442 return_type
->dump(level
+ 2);
6443 if (asstype
== A_FUNCTION_RTEMP
) DEBUG(level
+ 1, "Returns template");
6445 if (prototype
!= PROTOTYPE_NONE
)
6446 DEBUG(level
+ 1, "Prototype: %s", get_prototype_name());
6447 //DEBUG(level + 1, "Statement block:");
6448 block
->dump(level
+ 1);
6451 void Def_Function::set_parent_path(WithAttribPath
* p_path
) {
6452 Def_Function_Base::set_parent_path(p_path
);
6453 block
->set_parent_path(w_attrib_path
);
6456 // =================================
6457 // ===== Def_ExtFunction
6458 // =================================
6460 Def_ExtFunction::~Def_ExtFunction()
6462 delete encoding_options
;
6464 if (NULL
!= json_printing
) {
6465 delete json_printing
;
6469 Def_ExtFunction
*Def_ExtFunction::clone() const
6471 FATAL_ERROR("Def_ExtFunction::clone");
6474 void Def_ExtFunction::set_fullname(const string
& p_fullname
)
6476 Def_Function_Base::set_fullname(p_fullname
);
6477 if (eb_list
) eb_list
->set_fullname(p_fullname
+ ".<errorbehavior_list>");
6480 void Def_ExtFunction::set_encode_parameters(Type::MessageEncodingType_t
6481 p_encoding_type
, string
*p_encoding_options
)
6483 function_type
= EXTFUNC_ENCODE
;
6484 encoding_type
= p_encoding_type
;
6485 delete encoding_options
;
6486 encoding_options
= p_encoding_options
;
6489 void Def_ExtFunction::set_decode_parameters(Type::MessageEncodingType_t
6490 p_encoding_type
, string
*p_encoding_options
)
6492 function_type
= EXTFUNC_DECODE
;
6493 encoding_type
= p_encoding_type
;
6494 delete encoding_options
;
6495 encoding_options
= p_encoding_options
;
6498 void Def_ExtFunction::add_eb_list(Ttcn::ErrorBehaviorList
*p_eb_list
)
6500 if (!p_eb_list
) FATAL_ERROR("Def_ExtFunction::add_eb_list()");
6502 eb_list
->steal_ebs(p_eb_list
);
6505 eb_list
= p_eb_list
;
6506 eb_list
->set_fullname(get_fullname() + ".<errorbehavior_list>");
6510 void Def_ExtFunction::chk_function_type()
6512 switch (function_type
) {
6513 case EXTFUNC_MANUAL
:
6515 eb_list
->error("Attribute `errorbehavior' can only be used together "
6516 "with `encode' or `decode'");
6520 case EXTFUNC_ENCODE
:
6521 switch (prototype
) {
6522 case PROTOTYPE_NONE
:
6523 error("Attribute `encode' cannot be used without `prototype'");
6525 case PROTOTYPE_BACKTRACK
:
6526 case PROTOTYPE_SLIDING
:
6527 error("Attribute `encode' cannot be used with `prototype(%s)'",
6528 get_prototype_name());
6529 default: /* CONVERT and FAST allowed */
6534 if (!input_type
->has_encoding(encoding_type
, encoding_options
)) {
6535 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6536 input_type
->error("Input type `%s' does not support custom encoding '%s'",
6537 input_type
->get_typename().c_str(), encoding_options
->c_str());
6540 input_type
->error("Input type `%s' does not support %s encoding",
6541 input_type
->get_typename().c_str(),
6542 Type::get_encoding_name(encoding_type
));
6546 if (Common::Type::CT_XER
== encoding_type
6547 && input_type
->get_type_refd_last()->is_untagged()) {
6548 // "untagged" on the (toplevel) input type will have no effect.
6549 warning("UNTAGGED encoding attribute is ignored on top-level type");
6551 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6552 if (PROTOTYPE_CONVERT
!= prototype
) {
6553 error("Only `prototype(convert)' is allowed for custom encoding functions");
6556 // let the input type know that this is its encoding function
6557 input_type
->get_type_refd()->set_coding_function(true,
6558 get_genname_from_scope(input_type
->get_type_refd()->get_my_scope()));
6559 // treat this as a manual external function during code generation
6560 function_type
= EXTFUNC_MANUAL
;
6566 if(encoding_type
== Common::Type::CT_TEXT
) { // TEXT encoding supports both octetstring and charstring stream types
6567 Type
*stream_type
= Type::get_stream_type(encoding_type
,0);
6568 Type
*stream_type2
= Type::get_stream_type(encoding_type
,1);
6569 if ( (!stream_type
->is_identical(output_type
)) && (!stream_type2
->is_identical(output_type
)) ) {
6570 output_type
->error("The output type of %s encoding should be `%s' or `%s' "
6571 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6572 stream_type
->get_typename().c_str(),
6573 stream_type2
->get_typename().c_str(),
6574 output_type
->get_typename().c_str());
6577 Type
*stream_type
= Type::get_stream_type(encoding_type
);
6578 if (!stream_type
->is_identical(output_type
)) {
6579 output_type
->error("The output type of %s encoding should be `%s' "
6580 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6581 stream_type
->get_typename().c_str(),
6582 output_type
->get_typename().c_str());
6586 if (eb_list
) eb_list
->chk();
6587 chk_allowed_encode();
6589 case EXTFUNC_DECODE
:
6590 if (prototype
== PROTOTYPE_NONE
) {
6591 error("Attribute `decode' cannot be used without `prototype'");
6594 if(encoding_type
== Common::Type::CT_TEXT
) { // TEXT encoding supports both octetstring and charstring stream types
6595 Type
*stream_type
= Type::get_stream_type(encoding_type
,0);
6596 Type
*stream_type2
= Type::get_stream_type(encoding_type
,1);
6597 if ( (!stream_type
->is_identical(input_type
)) && (!stream_type2
->is_identical(input_type
)) ) {
6598 input_type
->error("The input type of %s decoding should be `%s' or `%s' "
6599 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6600 stream_type
->get_typename().c_str(),
6601 stream_type2
->get_typename().c_str(),
6602 input_type
->get_typename().c_str());
6605 Type
*stream_type
= Type::get_stream_type(encoding_type
);
6606 if (!stream_type
->is_identical(input_type
)) {
6607 input_type
->error("The input type of %s decoding should be `%s' "
6608 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6609 stream_type
->get_typename().c_str(),
6610 input_type
->get_typename().c_str());
6615 if (output_type
&& !output_type
->has_encoding(encoding_type
, encoding_options
)) {
6616 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6617 output_type
->error("Output type `%s' does not support custom encoding '%s'",
6618 output_type
->get_typename().c_str(), encoding_options
->c_str());
6621 output_type
->error("Output type `%s' does not support %s encoding",
6622 output_type
->get_typename().c_str(),
6623 Type::get_encoding_name(encoding_type
));
6627 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6628 if (PROTOTYPE_SLIDING
!= prototype
) {
6629 error("Only `prototype(sliding)' is allowed for custom decoding functions");
6631 else if (output_type
) {
6632 // let the output type know that this is its decoding function
6633 output_type
->get_type_refd()->set_coding_function(false,
6634 get_genname_from_scope(output_type
->get_type_refd()->get_my_scope()));
6635 // treat this as a manual external function during code generation
6636 function_type
= EXTFUNC_MANUAL
;
6640 if (eb_list
) eb_list
->chk();
6641 chk_allowed_encode();
6644 FATAL_ERROR("Def_ExtFunction::chk()");
6648 void Def_ExtFunction::chk_allowed_encode()
6650 switch (encoding_type
) {
6652 if (enable_ber()) return; // ok
6655 if (enable_raw()) return; // ok
6658 if (enable_text()) return; // ok
6661 if (enable_xer()) return; // ok
6664 if (enable_per()) return; // ok?
6667 if (enable_json()) return;
6669 case Type::CT_CUSTOM
:
6670 return; // cannot be disabled
6672 FATAL_ERROR("Def_ExtFunction::chk_allowed_encode");
6676 error("%s encoding is disallowed by license or commandline options",
6677 Type::get_encoding_name(encoding_type
));
6680 void Def_ExtFunction::chk()
6682 if (checked
) return;
6684 Error_Context
cntxt(this, "In external function definition `%s'",
6685 id
->get_dispname().c_str());
6686 fp_list
->chk(asstype
);
6688 Error_Context
cntxt2(return_type
, "In return type");
6690 return_type
->chk_as_return_type(asstype
== A_EXT_FUNCTION_RVAL
,
6691 "external function");
6693 if (!semantic_check_only
) fp_list
->set_genname(get_genname());
6694 if (w_attrib_path
) {
6695 w_attrib_path
->chk_global_attrib();
6696 w_attrib_path
->chk_no_qualif();
6697 const Ttcn::ExtensionAttributes
* extattrs
= parse_extattributes(w_attrib_path
);
6698 if (extattrs
!= 0) {
6699 size_t num_atrs
= extattrs
->size();
6700 for (size_t i
=0; i
< num_atrs
; ++i
) {
6701 ExtensionAttribute
&ea
= extattrs
->get(i
);
6702 switch (ea
.get_type()) {
6703 case ExtensionAttribute::PROTOTYPE
: {
6704 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE
) {
6705 ea
.error("Duplicate attribute `prototype'");
6707 Def_Function_Base::prototype_t proto
= ea
.get_proto();
6708 set_prototype(proto
);
6711 case ExtensionAttribute::ENCODE
: {
6712 switch (get_function_type()) {
6713 case Def_ExtFunction::EXTFUNC_MANUAL
:
6715 case Def_ExtFunction::EXTFUNC_ENCODE
: {
6716 ea
.error("Duplicate attribute `encode'");
6718 case Def_ExtFunction::EXTFUNC_DECODE
: {
6719 ea
.error("Attributes `decode' and `encode' "
6720 "cannot be used at the same time");
6723 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6725 Type::MessageEncodingType_t et
;
6727 ea
.get_encdec_parameters(et
, opt
);
6728 set_encode_parameters(et
, opt
);
6731 case ExtensionAttribute::ERRORBEHAVIOR
: {
6732 add_eb_list(ea
.get_eb_list());
6735 case ExtensionAttribute::DECODE
: {
6736 switch (get_function_type()) {
6737 case Def_ExtFunction::EXTFUNC_MANUAL
:
6739 case Def_ExtFunction::EXTFUNC_ENCODE
: {
6740 ea
.error("Attributes `encode' and `decode' "
6741 "cannot be used at the same time");
6743 case Def_ExtFunction::EXTFUNC_DECODE
: {
6744 ea
.error("Duplicate attribute `decode'");
6747 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6749 Type::MessageEncodingType_t et
;
6751 ea
.get_encdec_parameters(et
, opt
);
6752 set_decode_parameters(et
, opt
);
6755 case ExtensionAttribute::PRINTING
: {
6756 json_printing
= ea
.get_printing();
6759 case ExtensionAttribute::ANYTYPELIST
:
6760 // ignore, because we can't distinguish between a local
6761 // "extension anytype" (which is bogus) and an inherited one
6762 // (which was meant for a type definition)
6765 case ExtensionAttribute::NONE
:
6766 // Ignore, do not issue "wrong type" error
6771 "Only the following extension attributes may be applied to "
6772 "external functions: 'prototype', 'encode', 'decode', 'errorbehavior'");
6780 chk_function_type();
6782 if (NULL
!= json_printing
&& (EXTFUNC_ENCODE
!= function_type
||
6783 Type::CT_JSON
!= encoding_type
)) {
6784 error("Attribute 'printing' is only allowed for JSON encoding functions.");
6788 char *Def_ExtFunction::generate_code_encode(char *str
)
6790 const char *function_name
= id
->get_dispname().c_str();
6791 const char *first_par_name
=
6792 fp_list
->get_fp_byIndex(0)->get_id().get_name().c_str();
6793 // producing debug printout of the input PDU
6794 str
= mputprintf(str
,
6796 "// written by %s in " __FILE__
" at %d\n"
6798 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6799 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6800 "TTCN_Logger::log_event_str(\"%s(): Encoding %s: \");\n"
6802 "TTCN_Logger::end_event();\n"
6805 , __FUNCTION__
, __LINE__
6807 , function_name
, input_type
->get_typename().c_str(), first_par_name
);
6808 // setting error behavior
6809 if (eb_list
) str
= eb_list
->generate_code(str
);
6810 else str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6811 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6812 // encoding PDU into the buffer
6813 str
= mputstr(str
, "TTCN_Buffer ttcn_buffer;\n");
6814 str
= mputprintf(str
, "%s.encode(%s_descr_, ttcn_buffer, TTCN_EncDec::CT_%s",
6816 input_type
->get_genname_typedescriptor(my_scope
).c_str(),
6817 Type::get_encoding_name(encoding_type
));
6818 if (encoding_type
== Type::CT_JSON
) {
6819 if (json_printing
!= NULL
) {
6820 str
= json_printing
->generate_code(str
);
6822 str
= mputstr(str
, ", 0");
6825 if (encoding_options
) str
= mputprintf(str
, ", %s",
6826 encoding_options
->c_str());
6827 str
= mputstr(str
, ");\n");
6828 const char *result_name
;
6829 switch (prototype
) {
6830 case PROTOTYPE_CONVERT
:
6831 result_name
= "ret_val";
6832 // creating a local variable for the result stream
6833 str
= mputprintf(str
, "%s ret_val;\n",
6834 output_type
->get_genname_value(my_scope
).c_str());
6836 case PROTOTYPE_FAST
:
6837 result_name
= fp_list
->get_fp_byIndex(1)->get_id().get_name().c_str();
6840 FATAL_ERROR("Def_ExtFunction::generate_code_encode()");
6843 // taking the result from the buffer and producing debug printout
6844 str
= mputprintf(str
, "ttcn_buffer.get_string(%s);\n"
6845 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6846 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6847 "TTCN_Logger::log_event_str(\"%s(): Stream after encoding: \");\n"
6849 "TTCN_Logger::end_event();\n"
6850 "}\n", result_name
, function_name
, result_name
);
6851 // returning the result stream if necessary
6852 if (prototype
== PROTOTYPE_CONVERT
) {
6853 if (debugger_active
) {
6855 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
6856 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
6858 str
= mputstr(str
, "return ret_val;\n");
6863 char *Def_ExtFunction::generate_code_decode(char *str
)
6865 const char *function_name
= id
->get_dispname().c_str();
6866 const char *first_par_name
=
6867 fp_list
->get_fp_byIndex(0)->get_id().get_name().c_str();
6868 // producing debug printout of the input stream
6869 str
= mputprintf(str
,
6871 "// written by %s in " __FILE__
" at %d\n"
6873 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6874 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6875 "TTCN_Logger::log_event_str(\"%s(): Stream before decoding: \");\n"
6877 "TTCN_Logger::end_event();\n"
6880 , __FUNCTION__
, __LINE__
6882 , function_name
, first_par_name
);
6883 // setting error behavior
6884 if (eb_list
) str
= eb_list
->generate_code(str
);
6885 else if (prototype
== PROTOTYPE_BACKTRACK
|| prototype
== PROTOTYPE_SLIDING
) {
6886 str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6887 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n");
6888 } else str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6889 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6890 // creating a buffer from the input stream
6891 str
= mputprintf(str
, "TTCN_EncDec::clear_error();\n"
6892 "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name
);
6893 const char *result_name
;
6894 if (prototype
== PROTOTYPE_CONVERT
) {
6895 // creating a local variable for the result
6896 str
= mputprintf(str
, "%s ret_val;\n",
6897 output_type
->get_genname_value(my_scope
).c_str());
6898 result_name
= "ret_val";
6900 result_name
= fp_list
->get_fp_byIndex(1)->get_id().get_name().c_str();
6902 if(encoding_type
==Type::CT_TEXT
){
6903 str
= mputprintf(str
,
6904 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6905 " TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_LOG_MATCHING, TTCN_EncDec::EB_WARNING);\n"
6908 str
= mputprintf(str
, "%s.decode(%s_descr_, ttcn_buffer, "
6909 "TTCN_EncDec::CT_%s", result_name
,
6910 output_type
->get_genname_typedescriptor(my_scope
).c_str(),
6911 Type::get_encoding_name(encoding_type
));
6912 if (encoding_options
) str
= mputprintf(str
, ", %s",
6913 encoding_options
->c_str());
6914 str
= mputstr(str
, ");\n");
6915 // producing debug printout of the result PDU
6916 str
= mputprintf(str
,
6917 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6918 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6919 "TTCN_Logger::log_event_str(\"%s(): Decoded %s: \");\n"
6921 "TTCN_Logger::end_event();\n"
6922 "}\n", function_name
, output_type
->get_typename().c_str(), result_name
);
6923 if (prototype
!= PROTOTYPE_SLIDING
) {
6924 // checking for remaining data in the buffer if decoding was successful
6925 str
= mputprintf(str
, "if (TTCN_EncDec::get_last_error_type() == "
6926 "TTCN_EncDec::ET_NONE) {\n"
6927 "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
6928 "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
6929 "ttcn_buffer.cut();\n"
6930 "%s remaining_stream;\n"
6931 "ttcn_buffer.get_string(remaining_stream);\n"
6932 "TTCN_Logger::begin_event(TTCN_WARNING);\n"
6933 "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
6934 "of the stream after successful decoding: \");\n"
6935 "remaining_stream.log();\n"
6936 "TTCN_Logger::end_event();\n"
6937 "}\n", input_type
->get_genname_value(my_scope
).c_str(), function_name
);
6938 // closing the block and returning the appropriate result or status code
6939 if (prototype
== PROTOTYPE_BACKTRACK
) {
6940 if (debugger_active
) {
6941 str
= mputstr(str
, "ttcn3_debugger.set_return_value(\"0\");\n");
6946 if (debugger_active
) {
6947 str
= mputstr(str
, "ttcn3_debugger.set_return_value(\"1\");\n");
6953 str
= mputstr(str
, "}\n");
6954 if (prototype
== PROTOTYPE_CONVERT
) {
6955 if (debugger_active
) {
6957 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
6958 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
6960 str
= mputstr(str
, "return ret_val;\n");
6964 // result handling and debug printout for sliding decoders
6965 str
= mputprintf(str
, "switch (TTCN_EncDec::get_last_error_type()) {\n"
6966 "case TTCN_EncDec::ET_NONE:\n"
6967 // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
6968 "ttcn_buffer.cut();\n"
6969 "ttcn_buffer.get_string(%s);\n"
6970 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6971 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6972 "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
6974 "TTCN_Logger::end_event();\n"
6977 "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
6978 "case TTCN_EncDec::ET_LEN_ERR:\n"
6982 "}\n", first_par_name
, function_name
, first_par_name
,
6983 debugger_active
? "ttcn3_debugger.set_return_value(\"0\");\n" : "",
6984 debugger_active
? "ttcn3_debugger.set_return_value(\"2\");\n" : "",
6985 debugger_active
? "ttcn3_debugger.set_return_value(\"1\");\n" : "");
6990 void Def_ExtFunction::generate_code(output_struct
*target
, bool)
6992 const string
& t_genname
= get_genname();
6993 const char *genname_str
= t_genname
.c_str();
6994 string return_type_name
;
6996 case A_EXT_FUNCTION
:
6997 return_type_name
= "void";
6999 case A_EXT_FUNCTION_RVAL
:
7000 return_type_name
= return_type
->get_genname_value(my_scope
);
7002 case A_EXT_FUNCTION_RTEMP
:
7003 return_type_name
= return_type
->get_genname_template(my_scope
);
7006 FATAL_ERROR("Def_ExtFunction::generate_code()");
7008 const char *return_type_str
= return_type_name
.c_str();
7009 char *formal_par_list
= fp_list
->generate_code(memptystr(), fp_list
->get_nof_fps());
7010 fp_list
->generate_code_defval(target
);
7011 // function prototype
7012 target
->header
.function_prototypes
=
7013 mputprintf(target
->header
.function_prototypes
, "extern %s %s(%s);\n",
7014 return_type_str
, genname_str
, formal_par_list
);
7016 if (function_type
!= EXTFUNC_MANUAL
) {
7017 // function body written by the compiler
7020 body
= mprintf("// written by %s in " __FILE__
" at %d\n"
7021 , __FUNCTION__
, __LINE__
);
7023 body
= mputprintf(body
,
7026 , return_type_str
, genname_str
, formal_par_list
);
7027 if (debugger_active
) {
7028 body
= generate_code_debugger_function_init(body
, this);
7030 switch (function_type
) {
7031 case EXTFUNC_ENCODE
:
7032 body
= generate_code_encode(body
);
7034 case EXTFUNC_DECODE
:
7035 body
= generate_code_decode(body
);
7038 FATAL_ERROR("Def_ExtFunction::generate_code()");
7040 body
= mputstr(body
, "}\n\n");
7041 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7046 Free(formal_par_list
);
7048 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7049 "%s.add_function(\"%s\", (genericfunc_t)&%s, NULL);\n",
7050 get_module_object_name(), id
->get_dispname().c_str(), genname_str
);
7053 void Def_ExtFunction::generate_code(CodeGenHelper
& cgh
) {
7054 generate_code(cgh
.get_current_outputstruct());
7057 void Def_ExtFunction::dump_internal(unsigned level
) const
7059 DEBUG(level
, "External function: %s", id
->get_dispname().c_str());
7060 DEBUG(level
+ 1, "Parameters:");
7061 fp_list
->dump(level
+ 2);
7063 DEBUG(level
+ 1, "Return type:");
7064 return_type
->dump(level
+ 2);
7065 if(asstype
== A_EXT_FUNCTION_RTEMP
) DEBUG(level
+ 1, "Returns template");
7067 if (prototype
!= PROTOTYPE_NONE
)
7068 DEBUG(level
+ 1, "Prototype: %s", get_prototype_name());
7069 if (function_type
!= EXTFUNC_MANUAL
) {
7070 DEBUG(level
+ 1, "Automatically generated: %s",
7071 function_type
== EXTFUNC_ENCODE
? "encoder" : "decoder");
7072 DEBUG(level
+ 2, "Encoding type: %s",
7073 Type::get_encoding_name(encoding_type
));
7074 if (encoding_options
)
7075 DEBUG(level
+ 2, "Encoding options: %s", encoding_options
->c_str());
7077 if (eb_list
) eb_list
->dump(level
+ 1);
7080 void Def_ExtFunction::generate_json_schema_ref(map
<Type
*, JSON_Tokenizer
>& json_refs
)
7082 // only do anything if this is a JSON encoding or decoding function
7083 if (encoding_type
== Type::CT_JSON
&&
7084 (function_type
== EXTFUNC_ENCODE
|| function_type
== EXTFUNC_DECODE
)) {
7085 // retrieve the encoded type
7087 if (function_type
== EXTFUNC_ENCODE
) {
7088 // for encoding functions it's always the first parameter
7089 type
= fp_list
->get_fp_byIndex(0)->get_Type();
7091 // for decoding functions it depends on the prototype
7092 switch (prototype
) {
7093 case PROTOTYPE_CONVERT
:
7096 case PROTOTYPE_FAST
:
7097 case PROTOTYPE_BACKTRACK
:
7098 case PROTOTYPE_SLIDING
:
7099 type
= fp_list
->get_fp_byIndex(1)->get_Type();
7102 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
7106 // step over the type reference created for this function
7107 type
= type
->get_type_refd();
7109 JSON_Tokenizer
* json
= NULL
;
7110 if (json_refs
.has_key(type
)) {
7111 // the schema segment containing the type's reference already exists
7112 json
= json_refs
[type
];
7114 // the schema segment doesn't exist yet, create it and insert the reference
7115 json
= new JSON_Tokenizer
;
7116 json_refs
.add(type
, json
);
7117 type
->generate_json_schema_ref(*json
);
7120 // insert a property to specify which function this is (encoding or decoding)
7121 json
->put_next_token(JSON_TOKEN_NAME
, (function_type
== EXTFUNC_ENCODE
) ?
7122 "encoding" : "decoding");
7124 // place the function's info in an object
7125 json
->put_next_token(JSON_TOKEN_OBJECT_START
);
7127 // insert information related to the function's prototype in an array
7128 json
->put_next_token(JSON_TOKEN_NAME
, "prototype");
7129 json
->put_next_token(JSON_TOKEN_ARRAY_START
);
7131 // 1st element: external function prototype name (as string)
7133 case PROTOTYPE_CONVERT
:
7134 json
->put_next_token(JSON_TOKEN_STRING
, "\"convert\"");
7136 case PROTOTYPE_FAST
:
7137 json
->put_next_token(JSON_TOKEN_STRING
, "\"fast\"");
7139 case PROTOTYPE_BACKTRACK
:
7140 json
->put_next_token(JSON_TOKEN_STRING
, "\"backtrack\"");
7142 case PROTOTYPE_SLIDING
:
7143 json
->put_next_token(JSON_TOKEN_STRING
, "\"sliding\"");
7146 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
7149 // 2nd element: external function name
7150 char* func_name_str
= mprintf("\"%s\"", id
->get_dispname().c_str());
7151 json
->put_next_token(JSON_TOKEN_STRING
, func_name_str
);
7152 Free(func_name_str
);
7154 // the rest of the elements contain the names of the function's parameters (1 or 2)
7155 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7156 char* param_str
= mprintf("\"%s\"",
7157 fp_list
->get_fp_byIndex(i
)->get_id().get_dispname().c_str());
7158 json
->put_next_token(JSON_TOKEN_STRING
, param_str
);
7162 // end of the prototype's array
7163 json
->put_next_token(JSON_TOKEN_ARRAY_END
);
7165 // insert error behavior data
7166 if (eb_list
!= NULL
) {
7167 json
->put_next_token(JSON_TOKEN_NAME
, "errorBehavior");
7168 json
->put_next_token(JSON_TOKEN_OBJECT_START
);
7170 // add each error behavior modification as a property
7171 for (size_t i
= 0; i
< eb_list
->get_nof_ebs(); ++i
) {
7172 ErrorBehaviorSetting
* eb
= eb_list
->get_ebs_byIndex(i
);
7173 json
->put_next_token(JSON_TOKEN_NAME
, eb
->get_error_type().c_str());
7174 char* handling_str
= mprintf("\"%s\"", eb
->get_error_handling().c_str());
7175 json
->put_next_token(JSON_TOKEN_STRING
, handling_str
);
7179 json
->put_next_token(JSON_TOKEN_OBJECT_END
);
7182 // insert printing type
7183 if (json_printing
!= NULL
) {
7184 json
->put_next_token(JSON_TOKEN_NAME
, "printing");
7185 json
->put_next_token(JSON_TOKEN_STRING
,
7186 (json_printing
->get_printing() == PrintingType::PT_PRETTY
) ?
7187 "\"pretty\"" : "\"compact\"");
7190 // end of this function's object
7191 json
->put_next_token(JSON_TOKEN_OBJECT_END
);
7195 // =================================
7196 // ===== Def_Altstep
7197 // =================================
7199 Def_Altstep::Def_Altstep(Identifier
*p_id
, FormalParList
*p_fpl
,
7200 Reference
*p_runs_on_ref
, StatementBlock
*p_sb
,
7202 : Definition(A_ALTSTEP
, p_id
), fp_list(p_fpl
), runs_on_ref(p_runs_on_ref
),
7203 runs_on_type(0), sb(p_sb
), ags(p_ags
)
7205 if (!p_fpl
|| !p_sb
|| !p_ags
)
7206 FATAL_ERROR("Def_Altstep::Def_Altstep()");
7207 fp_list
->set_my_def(this);
7208 sb
->set_my_def(this);
7209 ags
->set_my_def(this);
7210 ags
->set_my_sb(sb
, 0);
7213 Def_Altstep::~Def_Altstep()
7221 Def_Altstep
*Def_Altstep::clone() const
7223 FATAL_ERROR("Def_Altstep::clone");
7226 void Def_Altstep::set_fullname(const string
& p_fullname
)
7228 Definition::set_fullname(p_fullname
);
7229 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
7230 if (runs_on_ref
) runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
7231 sb
->set_fullname(p_fullname
+".<block>");
7232 ags
->set_fullname(p_fullname
+ ".<guards>");
7235 void Def_Altstep::set_my_scope(Scope
*p_scope
)
7237 bridgeScope
.set_parent_scope(p_scope
);
7238 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
7240 Definition::set_my_scope(&bridgeScope
);
7241 // the scope of the parameter list is set during checking
7242 if (runs_on_ref
) runs_on_ref
->set_my_scope(&bridgeScope
);
7243 sb
->set_my_scope(fp_list
);
7244 ags
->set_my_scope(sb
);
7247 Type
*Def_Altstep::get_RunsOnType()
7249 if (!checked
) chk();
7250 return runs_on_type
;
7253 FormalParList
*Def_Altstep::get_FormalParList()
7255 if (!checked
) chk();
7259 RunsOnScope
*Def_Altstep::get_runs_on_scope(Type
*comptype
)
7261 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
7262 if (!my_module
) FATAL_ERROR("Def_Altstep::get_runs_on_scope()");
7263 return my_module
->get_runs_on_scope(comptype
);
7266 void Def_Altstep::chk()
7268 if (checked
) return;
7270 Error_Context
cntxt(this, "In altstep definition `%s'",
7271 id
->get_dispname().c_str());
7272 Scope
*parlist_scope
= my_scope
;
7274 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
7275 runs_on_type
= runs_on_ref
->chk_comptype_ref();
7277 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
7278 runs_on_scope
->set_parent_scope(my_scope
);
7279 parlist_scope
= runs_on_scope
;
7282 fp_list
->set_my_scope(parlist_scope
);
7283 fp_list
->chk(asstype
);
7285 ags
->set_is_altstep();
7286 ags
->set_my_ags(ags
);
7287 ags
->set_my_laic_stmt(ags
, 0);
7289 if (!semantic_check_only
) {
7290 fp_list
->set_genname(get_genname());
7291 sb
->set_code_section(GovernedSimple::CS_INLINE
);
7292 ags
->set_code_section(GovernedSimple::CS_INLINE
);
7294 if (w_attrib_path
) {
7295 w_attrib_path
->chk_global_attrib();
7296 w_attrib_path
->chk_no_qualif();
7300 void Def_Altstep::generate_code(output_struct
*target
, bool)
7302 const string
& t_genname
= get_genname();
7303 const char *genname_str
= t_genname
.c_str();
7304 const char *dispname_str
= id
->get_dispname().c_str();
7306 // function for altstep instance:
7307 // assemble the function body first (this also determines which parameters
7309 char* body
= create_location_object(memptystr(), "ALTSTEP", dispname_str
);
7310 body
= fp_list
->generate_shadow_objects(body
);
7311 if (debugger_active
) {
7312 body
= generate_code_debugger_function_init(body
, this);
7314 body
= sb
->generate_code(body
);
7315 body
= ags
->generate_code_altstep(body
);
7316 // generate a smart formal parameter list (omits unused parameter names)
7317 char *formal_par_list
= fp_list
->generate_code(memptystr());
7318 fp_list
->generate_code_defval(target
);
7320 // function for altstep instance: prototype
7321 target
->header
.function_prototypes
=
7322 mputprintf(target
->header
.function_prototypes
,
7323 "extern alt_status %s_instance(%s);\n", genname_str
, formal_par_list
);
7325 // function for altstep instance: body
7326 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7327 "alt_status %s_instance(%s)\n"
7330 "}\n\n", genname_str
, formal_par_list
, body
);
7331 Free(formal_par_list
);
7334 char *actual_par_list
=
7335 fp_list
->generate_code_actual_parlist(memptystr(), "");
7337 // use a full formal parameter list for the rest of the functions
7338 char *full_formal_par_list
= fp_list
->generate_code(memptystr(),
7339 fp_list
->get_nof_fps());
7341 // wrapper function for stand-alone instantiation: prototype
7342 target
->header
.function_prototypes
=
7343 mputprintf(target
->header
.function_prototypes
,
7344 "extern void %s(%s);\n", genname_str
, full_formal_par_list
);
7346 // wrapper function for stand-alone instantiation: body
7347 target
->source
.function_bodies
=
7348 mputprintf(target
->source
.function_bodies
, "void %s(%s)\n"
7351 "boolean block_flag = FALSE;\n"
7352 "alt_status altstep_flag = ALT_UNCHECKED, "
7353 "default_flag = ALT_UNCHECKED;\n"
7355 "TTCN_Snapshot::take_new(block_flag);\n"
7356 "if (altstep_flag != ALT_NO) {\n"
7357 "altstep_flag = %s_instance(%s);\n"
7358 "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
7359 "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
7361 "if (default_flag != ALT_NO) {\n"
7362 "default_flag = TTCN_Default::try_altsteps();\n"
7363 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
7364 "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
7366 "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
7367 "TTCN_error(\"None of the branches can be chosen in altstep %s.\");\n"
7368 "else block_flag = TRUE;\n"
7370 "}\n\n", genname_str
, full_formal_par_list
, genname_str
, actual_par_list
,
7373 // class for keeping the altstep in the default context
7374 // the class is for internal use, we do not need to publish it in the
7376 char* str
= mprintf("class %s_Default : public Default_Base {\n", genname_str
);
7377 str
= fp_list
->generate_code_object(str
, "par_");
7378 str
= mputprintf(str
, "public:\n"
7380 "alt_status call_altstep();\n"
7381 "};\n\n", genname_str
, full_formal_par_list
);
7382 target
->source
.class_defs
= mputstr(target
->source
.class_defs
, str
);
7384 // member functions of the class
7385 str
= mprintf("%s_Default::%s_Default(%s)\n"
7386 " : Default_Base(\"%s\")", genname_str
, genname_str
, full_formal_par_list
,
7388 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); i
++) {
7389 const char *fp_name_str
=
7390 fp_list
->get_fp_byIndex(i
)->get_id().get_name().c_str();
7391 str
= mputprintf(str
, ", par_%s(%s)", fp_name_str
, fp_name_str
);
7393 str
= mputstr(str
, "\n{\n}\n\n");
7394 char *actual_par_list_prefixed
=
7395 fp_list
->generate_code_actual_parlist(memptystr(), "par_");
7396 str
= mputprintf(str
, "alt_status %s_Default::call_altstep()\n"
7398 "return %s_instance(%s);\n"
7399 "}\n\n", genname_str
, genname_str
, actual_par_list_prefixed
);
7400 Free(actual_par_list_prefixed
);
7401 target
->source
.methods
= mputstr(target
->source
.methods
, str
);
7404 // function for default activation: prototype
7405 target
->header
.function_prototypes
=
7406 mputprintf(target
->header
.function_prototypes
,
7407 "extern Default_Base *activate_%s(%s);\n", genname_str
,
7408 full_formal_par_list
);
7410 // function for default activation: body
7411 str
= mprintf("Default_Base *activate_%s(%s)\n"
7412 "{\n", genname_str
, full_formal_par_list
);
7413 str
= mputprintf(str
, "return new %s_Default(%s);\n"
7414 "}\n\n", genname_str
, actual_par_list
);
7415 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7419 Free(full_formal_par_list
);
7420 Free(actual_par_list
);
7422 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7423 "%s.add_altstep(\"%s\", (genericfunc_t)&%s_instance, (genericfunc_t )&activate_%s, "
7424 "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str
, genname_str
,
7425 genname_str
, genname_str
);
7428 void Def_Altstep::generate_code(CodeGenHelper
& cgh
) {
7429 generate_code(cgh
.get_current_outputstruct());
7432 void Def_Altstep::dump_internal(unsigned level
) const
7434 DEBUG(level
, "Altstep: %s", id
->get_dispname().c_str());
7435 DEBUG(level
+ 1, "Parameters:");
7436 fp_list
->dump(level
+ 1);
7438 DEBUG(level
+ 1, "Runs on clause:");
7439 runs_on_ref
->dump(level
+ 2);
7442 DEBUG(level + 1, "Local definitions:");
7443 sb->dump(level + 2);
7445 DEBUG(level
+ 1, "Guards:");
7446 ags
->dump(level
+ 2);
7449 void Def_Altstep::set_parent_path(WithAttribPath
* p_path
) {
7450 Definition::set_parent_path(p_path
);
7451 sb
->set_parent_path(w_attrib_path
);
7454 // =================================
7455 // ===== Def_Testcase
7456 // =================================
7458 Def_Testcase::Def_Testcase(Identifier
*p_id
, FormalParList
*p_fpl
,
7459 Reference
*p_runs_on_ref
, Reference
*p_system_ref
,
7460 StatementBlock
*p_block
)
7461 : Definition(A_TESTCASE
, p_id
), fp_list(p_fpl
), runs_on_ref(p_runs_on_ref
),
7462 runs_on_type(0), system_ref(p_system_ref
), system_type(0), block(p_block
)
7464 if (!p_fpl
|| !p_runs_on_ref
|| !p_block
)
7465 FATAL_ERROR("Def_Testcase::Def_Testcase()");
7466 fp_list
->set_my_def(this);
7467 block
->set_my_def(this);
7470 Def_Testcase::~Def_Testcase()
7478 Def_Testcase
*Def_Testcase::clone() const
7480 FATAL_ERROR("Def_Testcase::clone");
7483 void Def_Testcase::set_fullname(const string
& p_fullname
)
7485 Definition::set_fullname(p_fullname
);
7486 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
7487 runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
7488 if (system_ref
) system_ref
->set_fullname(p_fullname
+ ".<system_type>");
7489 block
->set_fullname(p_fullname
+ ".<statement_block>");
7492 void Def_Testcase::set_my_scope(Scope
*p_scope
)
7494 bridgeScope
.set_parent_scope(p_scope
);
7495 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
7497 Definition::set_my_scope(&bridgeScope
);
7498 // the scope of the parameter list is set during checking
7499 runs_on_ref
->set_my_scope(&bridgeScope
);
7500 if (system_ref
) system_ref
->set_my_scope(&bridgeScope
);
7501 block
->set_my_scope(fp_list
);
7504 Type
*Def_Testcase::get_RunsOnType()
7506 if (!checked
) chk();
7507 return runs_on_type
;
7510 Type
*Def_Testcase::get_SystemType()
7512 if (!checked
) chk();
7516 FormalParList
*Def_Testcase::get_FormalParList()
7518 if (!checked
) chk();
7522 RunsOnScope
*Def_Testcase::get_runs_on_scope(Type
*comptype
)
7524 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
7525 if (!my_module
) FATAL_ERROR("Def_Testcase::get_runs_on_scope()");
7526 return my_module
->get_runs_on_scope(comptype
);
7529 void Def_Testcase::chk()
7531 if (checked
) return;
7533 Error_Context
cntxt(this, "In testcase definition `%s'",
7534 id
->get_dispname().c_str());
7535 Scope
*parlist_scope
= my_scope
;
7537 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
7538 runs_on_type
= runs_on_ref
->chk_comptype_ref();
7540 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
7541 runs_on_scope
->set_parent_scope(my_scope
);
7542 parlist_scope
= runs_on_scope
;
7546 Error_Context
cntxt2(system_ref
, "In `system' clause");
7547 system_type
= system_ref
->chk_comptype_ref();;
7549 fp_list
->set_my_scope(parlist_scope
);
7550 fp_list
->chk(asstype
);
7552 if (!semantic_check_only
) {
7553 fp_list
->set_genname(get_genname());
7554 block
->set_code_section(GovernedSimple::CS_INLINE
);
7556 if (w_attrib_path
) {
7557 w_attrib_path
->chk_global_attrib();
7558 w_attrib_path
->chk_no_qualif();
7562 void Def_Testcase::generate_code(output_struct
*target
, bool)
7564 const string
& t_genname
= get_genname();
7565 const char *genname_str
= t_genname
.c_str();
7566 const char *dispname_str
= id
->get_dispname().c_str();
7568 // assemble the function body first (this also determines which parameters
7571 // Checking whether the testcase was invoked from another one.
7572 // At this point the location information should refer to the execute()
7573 // statement rather than this testcase.
7574 char* body
= mputstr(memptystr(), "TTCN_Runtime::check_begin_testcase(has_timer, "
7576 body
= create_location_object(body
, "TESTCASE", dispname_str
);
7577 body
= fp_list
->generate_shadow_objects(body
);
7578 if (debugger_active
) {
7579 body
= generate_code_debugger_function_init(body
, this);
7581 body
= mputprintf(body
, "try {\n"
7582 "TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
7583 my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
7585 ComponentTypeBody
*runs_on_body
= runs_on_type
->get_CompBody();
7586 body
= runs_on_body
->generate_code_comptype_name(body
);
7587 body
= mputstr(body
, ", ");
7589 body
= system_type
->get_CompBody()->generate_code_comptype_name(body
);
7590 else body
= runs_on_body
->generate_code_comptype_name(body
);
7591 body
= mputstr(body
, ", has_timer, timer_value);\n");
7592 body
= block
->generate_code(body
);
7593 body
= mputprintf(body
,
7594 "} catch (const TC_Error& tc_error) {\n"
7595 "} catch (const TC_End& tc_end) {\n"
7596 "TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
7597 "}\n", dispname_str
);
7598 body
= mputstr(body
, "return TTCN_Runtime::end_testcase();\n");
7600 // smart formal parameter list (names of unused parameters are omitted)
7601 char *formal_par_list
= fp_list
->generate_code(memptystr());
7602 fp_list
->generate_code_defval(target
);
7603 if (fp_list
->get_nof_fps() > 0)
7604 formal_par_list
= mputstr(formal_par_list
, ", ");
7605 formal_par_list
= mputstr(formal_par_list
,
7606 "boolean has_timer, double timer_value");
7608 // function prototype
7609 target
->header
.function_prototypes
=
7610 mputprintf(target
->header
.function_prototypes
,
7611 "extern verdicttype testcase_%s(%s);\n", genname_str
, formal_par_list
);
7614 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7615 "verdicttype testcase_%s(%s)\n"
7618 "}\n\n", genname_str
, formal_par_list
, body
);
7619 Free(formal_par_list
);
7622 if (fp_list
->get_nof_fps() == 0) {
7623 // adding to the list of startable testcases
7624 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7625 "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
7626 get_module_object_name(), dispname_str
, genname_str
);
7628 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7629 "%s.add_testcase_pard(\"%s\", (genericfunc_t)&testcase_%s);\n",
7630 get_module_object_name(), dispname_str
, genname_str
);
7632 // If every formal parameter has a default value, the testcase
7633 // might be callable after all.
7634 bool callable
= true;
7635 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7636 FormalPar
*fp
= fp_list
->get_fp_byIndex(i
);
7637 if (!fp
->has_defval()) {
7644 // Write a wrapper, which acts as a no-param testcase
7645 // by calling the parameterized testcase with the default values.
7646 target
->header
.function_prototypes
=
7647 mputprintf(target
->header
.function_prototypes
,
7648 "extern verdicttype testcase_%s_defparams(boolean has_timer, double timer_value);\n",
7650 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7651 "verdicttype testcase_%s_defparams(boolean has_timer, double timer_value) {\n"
7652 " return testcase_%s(",
7653 genname_str
, genname_str
);
7655 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7656 FormalPar
*fp
= fp_list
->get_fp_byIndex(i
);
7657 ActualPar
*ap
= fp
->get_defval();
7658 switch (ap
->get_selection()) {
7659 case ActualPar::AP_VALUE
:
7660 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7661 ap
->get_Value()->get_genname_own(my_scope
).c_str());
7663 case ActualPar::AP_TEMPLATE
:
7664 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7665 ap
->get_TemplateInstance()->get_Template()->get_genname_own(my_scope
).c_str());
7667 case ActualPar::AP_REF
:
7668 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7669 ap
->get_Ref()->get_refd_assignment()->get_genname_from_scope(my_scope
).c_str());
7671 case ActualPar::AP_DEFAULT
:
7672 // Can't happen. This ActualPar was created by
7673 // Ttcn::FormalPar::chk_actual_par as the default value for
7674 // a FormalPar, and it only ever creates vale, template or ref.
7677 FATAL_ERROR("Def_Testcase::generate_code()");
7680 // always append a comma, because has_timer and timer_value follows
7681 target
->source
.function_bodies
= mputstrn(target
->source
.function_bodies
,
7685 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7686 "has_timer, timer_value);\n"
7688 // Add the non-parameterized wrapper *after* the parameterized one,
7689 // with the same name. Linear search will always find the first
7690 // (user-visible, parameterized) testcase.
7691 // TTCN_Module::execute_testcase knows that if after a parameterized
7692 // testcase another testcase with the same name follows,
7693 // it's the callable, non-parameterized wrapper.
7695 // TTCN_Module::list_testcases skips parameterized testcases;
7696 // it will now list the non-parameterized wrapper.
7697 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7698 "%s.add_testcase_nonpard(\"%s\", testcase_%s_defparams);\n",
7699 get_module_object_name(), dispname_str
, genname_str
);
7701 } // has formal parameters
7704 void Def_Testcase::generate_code(CodeGenHelper
& cgh
) {
7705 generate_code(cgh
.get_current_outputstruct());
7708 void Def_Testcase::dump_internal(unsigned level
) const
7710 DEBUG(level
, "Testcase: %s", id
->get_dispname().c_str());
7711 DEBUG(level
+ 1, "Parameters:");
7712 fp_list
->dump(level
+ 1);
7713 DEBUG(level
+ 1, "Runs on clause:");
7714 runs_on_ref
->dump(level
+ 2);
7716 DEBUG(level
+ 1, "System clause:");
7717 system_ref
->dump(level
+ 2);
7719 DEBUG(level
+ 1, "Statement block:");
7720 block
->dump(level
+ 2);
7723 void Def_Testcase::set_parent_path(WithAttribPath
* p_path
) {
7724 Definition::set_parent_path(p_path
);
7726 block
->set_parent_path(w_attrib_path
);
7729 // =================================
7731 // =================================
7733 FormalPar::FormalPar(asstype_t p_asstype
, Type
*p_type
, Identifier
* p_name
,
7734 TemplateInstance
*p_defval
, bool p_lazy_eval
)
7735 : Definition(p_asstype
, p_name
), type(p_type
), my_parlist(0),
7736 used_as_lvalue(false), template_restriction(TR_NONE
),
7737 lazy_eval(p_lazy_eval
), defval_generated(false), usage_found(false)
7739 switch (p_asstype
) {
7743 case A_PAR_VAL_INOUT
:
7744 case A_PAR_TEMPL_IN
:
7745 case A_PAR_TEMPL_OUT
:
7746 case A_PAR_TEMPL_INOUT
:
7750 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7753 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7754 type
->set_ownertype(Type::OT_FORMAL_PAR
, this);
7755 defval
.ti
= p_defval
;
7758 FormalPar::FormalPar(asstype_t p_asstype
,
7759 template_restriction_t p_template_restriction
, Type
*p_type
,
7760 Identifier
* p_name
, TemplateInstance
*p_defval
, bool p_lazy_eval
)
7761 : Definition(p_asstype
, p_name
), type(p_type
), my_parlist(0),
7762 used_as_lvalue(false), template_restriction(p_template_restriction
),
7763 lazy_eval(p_lazy_eval
), defval_generated(false), usage_found(false)
7765 switch (p_asstype
) {
7766 case A_PAR_TEMPL_IN
:
7767 case A_PAR_TEMPL_OUT
:
7768 case A_PAR_TEMPL_INOUT
:
7771 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): parameter not template");
7774 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7775 type
->set_ownertype(Type::OT_FORMAL_PAR
, this);
7776 defval
.ti
= p_defval
;
7779 FormalPar::FormalPar(asstype_t p_asstype
, Identifier
* p_name
,
7780 TemplateInstance
*p_defval
)
7781 : Definition(p_asstype
, p_name
), type(0), my_parlist(0),
7782 used_as_lvalue(false), template_restriction(TR_NONE
), lazy_eval(false),
7783 defval_generated(false), usage_found(false)
7785 if (p_asstype
!= A_PAR_TIMER
)
7786 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7787 defval
.ti
= p_defval
;
7790 FormalPar::~FormalPar()
7793 if (checked
) delete defval
.ap
;
7794 else delete defval
.ti
;
7797 FormalPar
* FormalPar::clone() const
7799 FATAL_ERROR("FormalPar::clone");
7802 void FormalPar::set_fullname(const string
& p_fullname
)
7804 Definition::set_fullname(p_fullname
);
7805 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
7807 if (defval
.ap
) defval
.ap
->set_fullname(p_fullname
+ ".<default_value>");
7809 if (defval
.ti
) defval
.ti
->set_fullname(p_fullname
+ ".<default_value>");
7813 void FormalPar::set_my_scope(Scope
*p_scope
)
7815 Definition::set_my_scope(p_scope
);
7816 if (type
) type
->set_my_scope(p_scope
);
7818 if (defval
.ap
) defval
.ap
->set_my_scope(p_scope
);
7820 if (defval
.ti
) defval
.ti
->set_my_scope(p_scope
);
7824 bool FormalPar::is_local() const
7829 Type
*FormalPar::get_Type()
7831 if (!checked
) chk();
7832 if (!type
) FATAL_ERROR("FormalPar::get_Type()");
7836 void FormalPar::chk()
7838 if (checked
) return;
7840 TemplateInstance
*default_value
= defval
.ti
;
7844 Type
*t
= type
->get_type_refd_last();
7845 // checks for forbidden type <-> parameter combinations
7846 switch (t
->get_typetype()) {
7850 case A_PAR_VAL_INOUT
:
7851 asstype
= A_PAR_PORT
;
7854 error("Port type `%s' cannot be used as %s",
7855 t
->get_fullname().c_str(), get_assname());
7858 case Type::T_SIGNATURE
:
7860 case A_PAR_TEMPL_IN
:
7861 case A_PAR_TEMPL_OUT
:
7862 case A_PAR_TEMPL_INOUT
:
7865 error("Signature `%s' cannot be used as %s",
7866 t
->get_fullname().c_str(), get_assname());
7873 FATAL_ERROR("FormalPar::chk()");
7875 asstype
= A_PAR_VAL_IN
;
7880 } else if (asstype
!= A_PAR_TIMER
) FATAL_ERROR("FormalPar::chk()");
7882 if (default_value
) {
7883 Error_Context
cntxt(default_value
, "In default value");
7884 defval
.ap
= chk_actual_par(default_value
, Type::EXPECTED_STATIC_VALUE
);
7885 delete default_value
;
7886 if (!semantic_check_only
)
7887 defval
.ap
->set_code_section(GovernedSimple::CS_POST_INIT
);
7891 bool FormalPar::has_defval() const
7893 if (checked
) return defval
.ap
!= 0;
7894 else return defval
.ti
!= 0;
7897 bool FormalPar::has_notused_defval() const
7899 if (checked
) FATAL_ERROR("FormalPar::has_notused_defval");
7900 if (!defval
.ti
|| !defval
.ti
->get_Template())
7902 return defval
.ti
->get_Template()->get_templatetype()
7903 == Template::TEMPLATE_NOTUSED
;
7906 ActualPar
*FormalPar::get_defval() const
7908 if (!checked
) FATAL_ERROR("FormalPar::get_defval()");
7912 // Extract the TemplateInstance from an ActualPar.
7913 void FormalPar::set_defval(ActualPar
*defpar
)
7915 // ActualPar::clone() is not implemented, since we need such a function
7916 // only here only for AP_{VALUE,TEMPLATE} parameters. AP_ERROR can also
7917 // happen for Def_Template nodes, but they will be errors later.
7918 // FIXME: This function is Def_Template specific.
7919 if (!defval
.ti
->get_Template() || defval
.ti
->get_Template()
7920 ->get_templatetype() != Template::TEMPLATE_NOTUSED
)
7921 FATAL_ERROR("FormalPar::set_defval()");
7922 TemplateInstance
*reversed_ti
= 0;
7923 switch (defpar
->get_selection()) {
7924 case ActualPar::AP_VALUE
:
7925 reversed_ti
= new TemplateInstance(type
->clone(), 0, new Template
7926 (defpar
->get_Value()->clone())); // Trust the clone().
7928 case ActualPar::AP_TEMPLATE
:
7929 reversed_ti
= defpar
->get_TemplateInstance()->clone();
7931 case ActualPar::AP_ERROR
:
7932 break; // Can happen, but let it go.
7933 case ActualPar::AP_REF
:
7934 case ActualPar::AP_DEFAULT
:
7936 FATAL_ERROR("FormalPar::set_defval()");
7940 reversed_ti
->set_my_scope(get_my_scope());
7941 defval
.ti
= reversed_ti
;
7945 ActualPar
*FormalPar::chk_actual_par(TemplateInstance
*actual_par
,
7946 Type::expected_value_t exp_val
)
7948 if (!checked
) chk();
7952 return chk_actual_par_value(actual_par
, exp_val
);
7954 case A_PAR_VAL_INOUT
:
7955 return chk_actual_par_by_ref(actual_par
, false, exp_val
);
7956 case A_PAR_TEMPL_IN
:
7957 return chk_actual_par_template(actual_par
, exp_val
);
7958 case A_PAR_TEMPL_OUT
:
7959 case A_PAR_TEMPL_INOUT
:
7960 return chk_actual_par_by_ref(actual_par
, true, exp_val
);
7962 return chk_actual_par_timer(actual_par
, exp_val
);
7964 return chk_actual_par_port(actual_par
, exp_val
);
7966 FATAL_ERROR("FormalPar::chk_actual_par()");
7968 return 0; // to avoid warnings
7971 ActualPar
*FormalPar::chk_actual_par_value(TemplateInstance
*actual_par
,
7972 Type::expected_value_t exp_val
)
7974 actual_par
->chk_Type(type
);
7975 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
7977 derived_ref
->error("An in-line modified template cannot be used as %s",
7979 actual_par
->chk_DerivedRef(type
);
7981 Template
*ap_template
= actual_par
->get_Template();
7982 if (ap_template
->is_Value()) {
7983 Value
*v
= ap_template
->get_Value();
7984 v
->set_my_governor(type
);
7985 type
->chk_this_value_ref(v
);
7986 type
->chk_this_value(v
, 0, exp_val
, INCOMPLETE_NOT_ALLOWED
,
7987 OMIT_NOT_ALLOWED
, SUB_CHK
);
7988 return new ActualPar(v
);
7990 actual_par
->error("A specific value without matching symbols "
7991 "was expected for a %s", get_assname());
7992 return new ActualPar();
7996 static void chk_defpar_value(const Value
* v
)
7998 Common::Reference
*vref
= v
->get_reference();
7999 Common::Assignment
*ass2
= vref
->get_refd_assignment();
8001 Scope
*scope
= ass2
->get_my_scope();
8002 ComponentTypeBody
*ctb
= dynamic_cast<ComponentTypeBody
*>(scope
);
8003 if (ctb
) { // this is a component variable
8004 v
->error("default value cannot refer to"
8005 " a template field of the component in the `runs on' clause");
8009 static void chk_defpar_template(const Template
*body
,
8010 Type::expected_value_t exp_val
)
8012 switch (body
->get_templatetype()) {
8013 case Template::TEMPLATE_ERROR
:
8014 break; // could be erroneous in the source; skip it
8015 case Template::TEMPLATE_NOTUSED
:
8016 case Template::OMIT_VALUE
:
8017 case Template::ANY_VALUE
:
8018 case Template::ANY_OR_OMIT
:
8019 break; // acceptable (?)
8020 case Template::TEMPLATE_INVOKE
: // calling a function is not acceptable
8021 body
->error("default value can not be a function invocation");
8023 case Template::VALUE_RANGE
: {
8024 ValueRange
*range
= body
->get_value_range();
8025 Value
*low
= range
->get_min_v();
8026 Type::typetype_t tt_low
= low
->get_expr_returntype(exp_val
);
8027 Value
*high
= range
->get_max_v();
8028 Type::typetype_t tt_high
= high
->get_expr_returntype(exp_val
);
8029 if (tt_low
== tt_high
) break;
8032 case Template::BSTR_PATTERN
:
8033 case Template::HSTR_PATTERN
:
8034 case Template::OSTR_PATTERN
:
8035 case Template::CSTR_PATTERN
:
8036 case Template::USTR_PATTERN
:
8037 break; // should be acceptable in all cases (if only fixed strings possible)
8039 case Template::SPECIFIC_VALUE
: {
8040 Common::Value
*v
= body
->get_specific_value();
8041 if (v
->get_valuetype() == Value::V_REFD
) chk_defpar_value(v
);
8044 case Template::ALL_FROM
:
8045 case Template::VALUE_LIST_ALL_FROM
:
8046 FATAL_ERROR("should have been flattened");
8048 case Template::SUPERSET_MATCH
:
8049 case Template::SUBSET_MATCH
:
8050 case Template::PERMUTATION_MATCH
:
8051 case Template::TEMPLATE_LIST
:
8052 case Template::COMPLEMENTED_LIST
:
8053 case Template::VALUE_LIST
: {
8054 // in template charstring par := charstring : ("foo", "bar", "baz")
8055 size_t num
= body
->get_nof_comps();
8056 for (size_t i
= 0; i
< num
; ++i
) {
8057 const Template
*tpl
= body
->get_temp_byIndex(i
);
8058 chk_defpar_template(tpl
, exp_val
);
8062 case Template::NAMED_TEMPLATE_LIST
: {
8063 size_t num
= body
->get_nof_comps();
8064 for (size_t i
= 0; i
< num
; ++i
) {
8065 const NamedTemplate
*nt
= body
->get_namedtemp_byIndex(i
);
8066 const Template
*tpl
= nt
->get_template();
8067 chk_defpar_template(tpl
, exp_val
);
8071 case Template::INDEXED_TEMPLATE_LIST
: {
8072 size_t num
= body
->get_nof_comps();
8073 for (size_t i
= 0; i
< num
; ++i
) {
8074 const IndexedTemplate
*it
= body
->get_indexedtemp_byIndex(i
);
8075 const Template
*tpl
= it
->get_template();
8076 chk_defpar_template(tpl
, exp_val
);
8080 case Template::TEMPLATE_REFD
: {
8081 Ref_base
*ref
= body
->get_reference();
8083 Ttcn::ActualParList
*aplist
= ref
->get_parlist();
8085 size_t num
= aplist
->get_nof_pars();
8086 for (size_t i
= 0; i
< num
; ++i
) {
8087 const Ttcn::ActualPar
*ap
= aplist
->get_par(i
);
8089 switch (ap
->get_selection()) {
8090 case ActualPar::AP_ERROR
: {
8092 case ActualPar::AP_VALUE
: {
8093 Value
*v
= ap
->get_Value(); // "v_variable" as the parameter of the template
8095 switch (v
->get_valuetype()) {
8096 case Value::V_REFD
: {
8097 chk_defpar_value(v
);
8103 case ActualPar::AP_TEMPLATE
: {
8104 // A component cannot contain a template definition, parameterized or not.
8105 // Therefore the template this actual par references, cannot be
8106 // a field of a component => no error possible, nothing to do.
8108 case ActualPar::AP_REF
: {
8109 // A template cannot have an out/inout parameter
8110 FATAL_ERROR("Template with out parameter?");
8112 case ActualPar::AP_DEFAULT
: {
8113 ap
= ap
->get_ActualPar();
8117 } // switch actual par selection
8121 case Template::DECODE_MATCH
:
8122 chk_defpar_template(body
->get_decode_target()->get_Template(), exp_val
);
8124 } // switch templatetype
8128 // This function is called in two situations:
8129 // 1. FormalParList::chk calls FormalPar::chk to compute the default value
8130 // (make an ActualPar from a TemplateInstance).
8131 // In this case, defval.ti==0, and actual_par contains its old value.
8132 // This case is called only if the formal par has a default value.
8133 // 2. FormalParList::chk_actual_parlist calls FormalPar::chk_actual_par
8134 // to check the parameters supplied by the execute statement to the tc.
8135 // In this case, defval.ap has the value computed in case 1.
8136 ActualPar
*FormalPar::chk_actual_par_template(TemplateInstance
*actual_par
,
8137 Type::expected_value_t exp_val
)
8139 actual_par
->chk(type
);
8140 // actual_par->template_body may change: SPECIFIC_VALUE to TEMPLATE_REFD
8141 Definition
*fplist_def
= my_parlist
->get_my_def();
8142 // The parameter list belongs to this definition. If it's a function
8143 // or testcase, it may have a "runs on" clause.
8144 Def_Function
*parent_fn
= dynamic_cast<Def_Function
*>(fplist_def
);
8145 Type
*runs_on_type
= 0;
8146 if (parent_fn
) runs_on_type
= parent_fn
->get_RunsOnType();
8147 else { // not a function; maybe a testcase
8148 Def_Testcase
*parent_tc
= dynamic_cast<Def_Testcase
*>(fplist_def
);
8149 if (parent_tc
) runs_on_type
= parent_tc
->get_RunsOnType();
8152 // If it _has_ a runs on clause, the type must be a component.
8153 if (runs_on_type
->get_typetype() != Type::T_COMPONENT
) FATAL_ERROR("not component?");
8154 // The default value "shall not refer to elements of the component type
8155 // in the runs on clause"
8156 ComponentTypeBody
*runs_on_component
= runs_on_type
->get_CompBody();
8157 size_t compass
= runs_on_component
->get_nof_asss();
8158 for (size_t c
= 0; c
< compass
; c
++) {
8159 Assignment
*ass
= runs_on_component
->get_ass_byIndex(c
);
8164 Ttcn::Template
* body
= actual_par
->get_Template();
8165 if (exp_val
== Type::EXPECTED_STATIC_VALUE
8166 ||exp_val
== Type::EXPECTED_CONSTANT
) {
8167 chk_defpar_template(body
, exp_val
);
8169 // Rip out the type, derived ref and template from actual_par
8170 // (which may come from a function invocation or the definition
8171 // of the default value) and give it to the new ActualPar.
8172 ActualPar
*ret_val
= new ActualPar(
8173 new TemplateInstance(actual_par
->get_Type(),
8174 actual_par
->get_DerivedRef(), actual_par
->get_Template()));
8175 // Zero out these members because the caller will soon call delete
8176 // on actual_par, but they now belong to ret_val.
8177 // FIXME: should this really be in here, or outside in the caller before the delete ?
8178 actual_par
->release();
8180 if (template_restriction
!=TR_NONE
) {
8181 bool needs_runtime_check
=
8182 ret_val
->get_TemplateInstance()->chk_restriction(
8183 "template formal parameter", template_restriction
,
8184 ret_val
->get_TemplateInstance());
8185 if (needs_runtime_check
)
8186 ret_val
->set_gen_restriction_check(template_restriction
);
8191 ActualPar
*FormalPar::chk_actual_par_by_ref(TemplateInstance
*actual_par
,
8192 bool is_template
, Type::expected_value_t exp_val
)
8194 Type
*ap_type
= actual_par
->get_Type();
8196 ap_type
->warning("Explicit type specification is useless for an %s",
8198 actual_par
->chk_Type(type
);
8200 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8202 derived_ref
->error("An in-line modified template cannot be used as %s",
8204 actual_par
->chk_DerivedRef(type
);
8206 // needed for the error messages
8207 const char *expected_string
= is_template
?
8208 "template variable or template parameter" :
8209 "variable or value parameter";
8210 Template
*ap_template
= actual_par
->get_Template();
8211 if (ap_template
->is_Ref()) {
8212 Ref_base
*ref
= ap_template
->get_Ref();
8213 Common::Assignment
*ass
= ref
->get_refd_assignment();
8216 return new ActualPar();
8218 bool asstype_correct
= false;
8219 switch (ass
->get_asstype()) {
8221 ass
->use_as_lvalue(*ref
);
8222 if (get_asstype() == A_PAR_VAL_OUT
|| get_asstype() == A_PAR_TEMPL_OUT
) {
8223 ass
->warning("Passing an `in' parameter as another function's `out' parameter");
8228 case A_PAR_VAL_INOUT
:
8229 if (!is_template
) asstype_correct
= true;
8231 case A_PAR_TEMPL_IN
:
8232 ass
->use_as_lvalue(*ref
);
8233 if (get_asstype() == A_PAR_VAL_OUT
|| get_asstype() == A_PAR_TEMPL_OUT
) {
8234 ass
->warning("Passing an `in' parameter as another function's `out' parameter");
8237 case A_VAR_TEMPLATE
:
8238 case A_PAR_TEMPL_OUT
:
8239 case A_PAR_TEMPL_INOUT
:
8240 if (is_template
) asstype_correct
= true;
8245 if (asstype_correct
) {
8246 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
8247 Type
*ref_type
= ass
->get_Type()->get_field_type(t_subrefs
, exp_val
);
8249 if (!type
->is_identical(ref_type
)) {
8250 ref
->error("Type mismatch: Reference to a %s of type "
8251 "`%s' was expected instead of `%s'", expected_string
,
8252 type
->get_typename().c_str(), ref_type
->get_typename().c_str());
8253 } else if (type
->get_sub_type() && ref_type
->get_sub_type() &&
8254 (type
->get_sub_type()->get_subtypetype()==ref_type
->get_sub_type()->get_subtypetype()) &&
8255 (!type
->get_sub_type()->is_compatible(ref_type
->get_sub_type()))) {
8256 ref
->error("Subtype mismatch: subtype %s has no common value with subtype %s",
8257 type
->get_sub_type()->to_string().c_str(),
8258 ref_type
->get_sub_type()->to_string().c_str());
8260 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
8261 ref
->error("Reference to a string element of type `%s' cannot be "
8262 "used in this context", ref_type
->get_typename().c_str());
8266 ref
->error("Reference to a %s was expected for an %s instead of %s",
8267 expected_string
, get_assname(), ass
->get_description().c_str());
8269 ActualPar
* ret_val_ap
= new ActualPar(ref
);
8270 // restriction checking if this is a reference to a template variable
8271 // this is an 'out' or 'inout' template parameter
8272 if (is_template
&& asstype_correct
) {
8273 template_restriction_t refd_tr
;
8274 switch (ass
->get_asstype()) {
8275 case A_VAR_TEMPLATE
: {
8276 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(ass
);
8277 if (!dvt
) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8278 refd_tr
= dvt
->get_template_restriction();
8280 case A_PAR_TEMPL_IN
:
8281 case A_PAR_TEMPL_OUT
:
8282 case A_PAR_TEMPL_INOUT
: {
8283 FormalPar
* fp
= dynamic_cast<FormalPar
*>(ass
);
8284 if (!fp
) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8285 refd_tr
= fp
->get_template_restriction();
8288 FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8291 refd_tr
= Template::get_sub_restriction(refd_tr
, ref
);
8292 if (template_restriction
!=refd_tr
) {
8293 bool pre_call_check
=
8294 Template::is_less_restrictive(template_restriction
, refd_tr
);
8295 bool post_call_check
=
8296 Template::is_less_restrictive(refd_tr
, template_restriction
);
8297 if (pre_call_check
|| post_call_check
) {
8298 ref
->warning("Inadequate restriction on the referenced %s `%s', "
8299 "this may cause a dynamic test case error at runtime",
8300 ass
->get_assname(), ref
->get_dispname().c_str());
8301 ass
->note("Referenced %s is here", ass
->get_assname());
8304 ret_val_ap
->set_gen_restriction_check(template_restriction
);
8305 if (post_call_check
)
8306 ret_val_ap
->set_gen_post_restriction_check(refd_tr
);
8308 // for out and inout template parameters of external functions
8309 // always check because we do not trust user written C++ code
8310 if (refd_tr
!=TR_NONE
) {
8311 switch (my_parlist
->get_my_def()->get_asstype()) {
8312 case A_EXT_FUNCTION
:
8313 case A_EXT_FUNCTION_RVAL
:
8314 case A_EXT_FUNCTION_RTEMP
:
8315 ret_val_ap
->set_gen_post_restriction_check(refd_tr
);
8324 actual_par
->error("Reference to a %s was expected for an %s",
8325 expected_string
, get_assname());
8326 return new ActualPar();
8330 ActualPar
*FormalPar::chk_actual_par_timer(TemplateInstance
*actual_par
,
8331 Type::expected_value_t exp_val
)
8333 Type
*ap_type
= actual_par
->get_Type();
8335 ap_type
->error("Explicit type specification cannot be used for a "
8337 actual_par
->chk_Type(0);
8339 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8341 derived_ref
->error("An in-line modified template cannot be used as "
8343 actual_par
->chk_DerivedRef(0);
8345 Template
*ap_template
= actual_par
->get_Template();
8346 if (ap_template
->is_Ref()) {
8347 Ref_base
*ref
= ap_template
->get_Ref();
8348 Common::Assignment
*ass
= ref
->get_refd_assignment();
8351 return new ActualPar();
8353 switch (ass
->get_asstype()) {
8355 ArrayDimensions
*dims
= ass
->get_Dimensions();
8356 if (dims
) dims
->chk_indices(ref
, "timer", false, exp_val
);
8357 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8358 "cannot have field or array sub-references",
8359 ass
->get_description().c_str());
8362 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8363 "field or array sub-references", ass
->get_description().c_str());
8366 ref
->error("Reference to a timer or timer parameter was expected for "
8367 "a timer parameter instead of %s", ass
->get_description().c_str());
8369 return new ActualPar(ref
);
8371 actual_par
->error("Reference to a timer or timer parameter was "
8372 "expected for a timer parameter");
8373 return new ActualPar();
8377 ActualPar
*FormalPar::chk_actual_par_port(TemplateInstance
*actual_par
,
8378 Type::expected_value_t exp_val
)
8380 Type
*ap_type
= actual_par
->get_Type();
8382 ap_type
->warning("Explicit type specification is useless for a port "
8384 actual_par
->chk_Type(type
);
8386 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8388 derived_ref
->error("An in-line modified template cannot be used as "
8390 actual_par
->chk_DerivedRef(type
);
8392 Template
*ap_template
= actual_par
->get_Template();
8393 if (ap_template
->is_Ref()) {
8394 Ref_base
*ref
= ap_template
->get_Ref();
8395 Common::Assignment
*ass
= ref
->get_refd_assignment();
8398 return new ActualPar();
8400 bool asstype_correct
= false;
8401 switch (ass
->get_asstype()) {
8403 ArrayDimensions
*dims
= ass
->get_Dimensions();
8404 if (dims
) dims
->chk_indices(ref
, "port", false, exp_val
);
8405 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8406 "cannot have field or array sub-references",
8407 ass
->get_description().c_str());
8408 asstype_correct
= true;
8411 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8412 "field or array sub-references", ass
->get_description().c_str());
8413 asstype_correct
= true;
8416 ref
->error("Reference to a port or port parameter was expected for a "
8417 "port parameter instead of %s", ass
->get_description().c_str());
8419 if (asstype_correct
) {
8420 Type
*ref_type
= ass
->get_Type();
8421 if (ref_type
&& !type
->is_identical(ref_type
))
8422 ref
->error("Type mismatch: Reference to a port or port parameter "
8423 "of type `%s' was expected instead of `%s'",
8424 type
->get_typename().c_str(), ref_type
->get_typename().c_str());
8426 return new ActualPar(ref
);
8428 actual_par
->error("Reference to a port or port parameter was expected "
8429 "for a port parameter");
8430 return new ActualPar();
8434 void FormalPar::use_as_lvalue(const Location
& p_loc
)
8438 case A_PAR_TEMPL_IN
:
8441 FATAL_ERROR("FormalPar::use_as_lvalue()");
8443 if (!used_as_lvalue
) {
8444 Definition
*my_def
= my_parlist
->get_my_def();
8445 if (!my_def
) FATAL_ERROR("FormalPar::use_as_lvalue()");
8446 if (my_def
->get_asstype() == A_TEMPLATE
)
8447 p_loc
.error("Parameter `%s' of the template cannot be passed further "
8448 "as `out' or `inout' parameter", id
->get_dispname().c_str());
8450 // update the genname so that all references in the generated code
8451 // will point to the shadow object
8453 set_genname(id
->get_name() + "_shadow");
8455 used_as_lvalue
= true;
8460 char* FormalPar::generate_code_defval(char* str
)
8462 if (!defval
.ap
|| defval_generated
) return str
;
8463 defval_generated
= true;
8464 switch (defval
.ap
->get_selection()) {
8465 case ActualPar::AP_VALUE
: {
8466 Value
*val
= defval
.ap
->get_Value();
8467 if (use_runtime_2
&& TypeConv::needs_conv_refd(val
)) {
8468 str
= TypeConv::gen_conv_code_refd(str
, val
->get_lhs_name().c_str(), val
);
8470 str
= val
->generate_code_init(str
, val
->get_lhs_name().c_str());
8473 case ActualPar::AP_TEMPLATE
: {
8474 TemplateInstance
*ti
= defval
.ap
->get_TemplateInstance();
8475 Template
*temp
= ti
->get_Template();
8476 Ref_base
*dref
= ti
->get_DerivedRef();
8478 expression_struct expr
;
8479 Code::init_expr(&expr
);
8480 expr
.expr
= mputprintf(expr
.expr
, "%s = ",
8481 temp
->get_lhs_name().c_str());
8482 dref
->generate_code(&expr
);
8483 str
= Code::merge_free_expr(str
, &expr
, false);
8485 if (use_runtime_2
&& TypeConv::needs_conv_refd(temp
)) {
8486 str
= TypeConv::gen_conv_code_refd(str
, temp
->get_lhs_name().c_str(), temp
);
8488 str
= temp
->generate_code_init(str
, temp
->get_lhs_name().c_str());
8490 if (defval
.ap
->get_gen_restriction_check() != TR_NONE
) {
8491 str
= Template::generate_restriction_check_code(str
,
8492 temp
->get_lhs_name().c_str(), defval
.ap
->get_gen_restriction_check());
8495 case ActualPar::AP_REF
:
8498 FATAL_ERROR("FormalPar::generate_code()");
8503 void FormalPar::generate_code_defval(output_struct
*target
, bool)
8505 if (!defval
.ap
) return;
8506 switch (defval
.ap
->get_selection()) {
8507 case ActualPar::AP_VALUE
: {
8508 Value
*val
= defval
.ap
->get_Value();
8510 Code::init_cdef(&cdef
);
8511 type
->generate_code_object(&cdef
, val
);
8512 Code::merge_cdef(target
, &cdef
);
8513 Code::free_cdef(&cdef
);
8515 case ActualPar::AP_TEMPLATE
: {
8516 TemplateInstance
*ti
= defval
.ap
->get_TemplateInstance();
8517 Template
*temp
= ti
->get_Template();
8519 Code::init_cdef(&cdef
);
8520 type
->generate_code_object(&cdef
, temp
);
8521 Code::merge_cdef(target
, &cdef
);
8522 Code::free_cdef(&cdef
);
8524 case ActualPar::AP_REF
:
8527 FATAL_ERROR("FormalPar::generate_code()");
8529 target
->functions
.post_init
= generate_code_defval(target
->functions
.post_init
);
8532 char *FormalPar::generate_code_fpar(char *str
, bool display_unused
/* = false */)
8534 // the name of the parameter should not be displayed if the parameter is not
8535 // used (to avoid a compiler warning)
8536 bool display_name
= (usage_found
|| display_unused
|| debugger_active
||
8537 (!enable_set_bound_out_param
&& (asstype
== A_PAR_VAL_OUT
|| asstype
== A_PAR_TEMPL_OUT
)));
8538 const char *name_str
= display_name
? id
->get_name().c_str() : "";
8542 str
= mputprintf(str
, "Lazy_Param<%s>& %s", type
->get_genname_value(my_scope
).c_str(), name_str
);
8544 str
= mputprintf(str
, "const %s& %s", type
->get_genname_value(my_scope
).c_str(), name_str
);
8548 case A_PAR_VAL_INOUT
:
8550 str
= mputprintf(str
, "%s& %s", type
->get_genname_value(my_scope
).c_str(),
8553 case A_PAR_TEMPL_IN
:
8555 str
= mputprintf(str
, "Lazy_Param<%s>& %s", type
->get_genname_template(my_scope
).c_str(), name_str
);
8557 str
= mputprintf(str
, "const %s& %s", type
->get_genname_template(my_scope
).c_str(), name_str
);
8560 case A_PAR_TEMPL_OUT
:
8561 case A_PAR_TEMPL_INOUT
:
8562 str
= mputprintf(str
, "%s& %s",
8563 type
->get_genname_template(my_scope
).c_str(), name_str
);
8566 str
= mputprintf(str
, "TIMER& %s", name_str
);
8569 FATAL_ERROR("FormalPar::generate_code()");
8574 string
FormalPar::get_reference_name(Scope
* scope
) const
8580 case A_PAR_TEMPL_IN
:
8581 ret_val
+= type
->get_genname_template(scope
);
8584 ret_val
+= type
->get_genname_value(scope
);
8589 ret_val
+= get_id().get_name();
8596 char *FormalPar::generate_code_object(char *str
, const char *p_prefix
, char refch
)
8598 const char *name_str
= id
->get_name().c_str();
8602 str
= mputprintf(str
, "Lazy_Param<%s> %s%s;\n", type
->get_genname_value(my_scope
).c_str(), p_prefix
, name_str
);
8604 str
= mputprintf(str
, "%s %s%s;\n", type
->get_genname_value(my_scope
).c_str(), p_prefix
, name_str
);
8608 case A_PAR_VAL_INOUT
:
8610 str
= mputprintf(str
, "%s%c %s%s;\n",
8611 type
->get_genname_value(my_scope
).c_str(), refch
, p_prefix
, name_str
);
8613 case A_PAR_TEMPL_IN
:
8615 str
= mputprintf(str
, "Lazy_Param<%s> %s%s;\n", type
->get_genname_template(my_scope
).c_str(), p_prefix
, name_str
);
8617 str
= mputprintf(str
, "%s %s%s;\n", type
->get_genname_template(my_scope
).c_str(), p_prefix
, name_str
);
8620 case A_PAR_TEMPL_OUT
:
8621 case A_PAR_TEMPL_INOUT
:
8622 str
= mputprintf(str
, "%s%c %s%s;\n",
8623 type
->get_genname_template(my_scope
).c_str(), refch
, p_prefix
, name_str
);
8626 str
= mputprintf(str
, "TIMER& %s%s;\n", p_prefix
, name_str
);
8629 FATAL_ERROR("FormalPar::generate_code_object()");
8634 char *FormalPar::generate_shadow_object(char *str
) const
8636 if (used_as_lvalue
&& !lazy_eval
) {
8637 const string
& t_genname
= get_genname();
8638 const char *genname_str
= t_genname
.c_str();
8639 const char *name_str
= id
->get_name().c_str();
8642 str
= mputprintf(str
, "%s %s(%s);\n",
8643 type
->get_genname_value(my_scope
).c_str(), genname_str
, name_str
);
8645 case A_PAR_TEMPL_IN
:
8646 str
= mputprintf(str
, "%s %s(%s);\n",
8647 type
->get_genname_template(my_scope
).c_str(), genname_str
, name_str
);
8650 FATAL_ERROR("FormalPar::generate_shadow_object()");
8656 char *FormalPar::generate_code_set_unbound(char *str
) const
8659 case A_PAR_TEMPL_OUT
:
8661 str
= mputprintf(str
, "%s.clean_up();\n", id
->get_name().c_str());
8669 void FormalPar::dump_internal(unsigned level
) const
8671 DEBUG(level
, "%s: %s", get_assname(), id
->get_dispname().c_str());
8672 if (type
) type
->dump(level
+ 1);
8675 DEBUG(level
+ 1, "default value:");
8676 defval
.ap
->dump(level
+ 2);
8680 DEBUG(level
+ 1, "default value:");
8681 defval
.ti
->dump(level
+ 2);
8686 // =================================
8687 // ===== FormalParList
8688 // =================================
8690 FormalParList::~FormalParList()
8692 size_t nof_pars
= pars_v
.size();
8693 for (size_t i
= 0; i
< nof_pars
; i
++) delete pars_v
[i
];
8698 FormalParList
*FormalParList::clone() const
8700 FATAL_ERROR("FormalParList::clone");
8703 void FormalParList::set_fullname(const string
& p_fullname
)
8705 Node::set_fullname(p_fullname
);
8706 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8707 FormalPar
*par
= pars_v
[i
];
8708 par
->set_fullname(p_fullname
+ "." + par
->get_id().get_dispname());
8712 void FormalParList::set_my_scope(Scope
*p_scope
)
8714 set_parent_scope(p_scope
);
8715 Node::set_my_scope(p_scope
);
8716 // the scope of parameters is set to the parent scope instead of this
8717 // because they cannot refer to each other
8718 for (size_t i
= 0; i
< pars_v
.size(); i
++) pars_v
[i
]->set_my_scope(p_scope
);
8721 void FormalParList::add_fp(FormalPar
*p_fp
)
8723 if (!p_fp
) FATAL_ERROR("NULL parameter: Ttcn::FormalParList::add_fp()");
8725 p_fp
->set_my_parlist(this);
8729 bool FormalParList::has_notused_defval() const
8731 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8732 if (pars_v
[i
]->has_notused_defval())
8738 bool FormalParList::has_only_default_values() const
8740 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8741 if (!pars_v
[i
]->has_defval()) {
8749 bool FormalParList::has_fp_withName(const Identifier
& p_name
)
8751 if (!checked
) chk(Definition::A_UNDEF
);
8752 return pars_m
.has_key(p_name
.get_name());
8755 FormalPar
*FormalParList::get_fp_byName(const Identifier
& p_name
)
8757 if (!checked
) chk(Definition::A_UNDEF
);
8758 return pars_m
[p_name
.get_name()];
8761 bool FormalParList::get_startability()
8763 if(!checked
) FATAL_ERROR("FormalParList::get_startability()");
8764 return is_startable
;
8767 Common::Assignment
*FormalParList::get_ass_bySRef(Common::Ref_simple
*p_ref
)
8769 if (!p_ref
|| !checked
) FATAL_ERROR("FormalParList::get_ass_bySRef()");
8770 if (p_ref
->get_modid()) return parent_scope
->get_ass_bySRef(p_ref
);
8772 const string
& name
= p_ref
->get_id()->get_name();
8773 if (pars_m
.has_key(name
)) return pars_m
[name
];
8774 else return parent_scope
->get_ass_bySRef(p_ref
);
8778 bool FormalParList::has_ass_withId(const Identifier
& p_id
)
8780 if (!checked
) FATAL_ERROR("Ttcn::FormalParList::has_ass_withId()");
8781 return pars_m
.has_key(p_id
.get_name())
8782 || parent_scope
->has_ass_withId(p_id
);
8785 void FormalParList::set_genname(const string
& p_prefix
)
8787 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8788 FormalPar
*par
= pars_v
[i
];
8789 const string
& par_name
= par
->get_id().get_name();
8790 if (par
->get_asstype() != Definition::A_PAR_TIMER
)
8791 par
->get_Type()->set_genname(p_prefix
, par_name
);
8792 if (par
->has_defval()) {
8793 string
embedded_genname(p_prefix
);
8794 embedded_genname
+= '_';
8795 embedded_genname
+= par_name
;
8796 embedded_genname
+= "_defval";
8797 ActualPar
*defval
= par
->get_defval();
8798 switch (defval
->get_selection()) {
8799 case ActualPar::AP_ERROR
:
8800 case ActualPar::AP_REF
:
8802 case ActualPar::AP_VALUE
: {
8803 Value
*v
= defval
->get_Value();
8804 v
->set_genname_prefix("const_");
8805 v
->set_genname_recursive(embedded_genname
);
8807 case ActualPar::AP_TEMPLATE
: {
8808 Template
*t
= defval
->get_TemplateInstance()->get_Template();
8809 t
->set_genname_prefix("template_");
8810 t
->set_genname_recursive(embedded_genname
);
8813 FATAL_ERROR("FormalParList::set_genname()");
8819 void FormalParList::chk(Definition::asstype_t deftype
)
8821 if (checked
) return;
8824 is_startable
= true;
8825 Error_Context
cntxt(this, "In formal parameter list");
8826 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8827 FormalPar
*par
= pars_v
[i
];
8828 const Identifier
& id
= par
->get_id();
8829 const string
& name
= id
.get_name();
8830 const char *dispname
= id
.get_dispname().c_str();
8831 if (pars_m
.has_key(name
)) {
8832 par
->error("Duplicate parameter with name `%s'", dispname
);
8833 pars_m
[name
]->note("Previous definition of `%s' is here", dispname
);
8835 pars_m
.add(name
, par
);
8836 if (parent_scope
&& parent_scope
->has_ass_withId(id
)) {
8837 par
->error("Parameter name `%s' is not unique in the scope "
8838 "hierarchy", dispname
);
8839 Reference
ref(0, id
.clone());
8840 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
8841 if (!ass
) FATAL_ERROR("FormalParList::chk()");
8842 ass
->note("Symbol `%s' is already defined here in a higher scope "
8846 Error_Context
cntxt2(par
, "In parameter `%s'", dispname
);
8848 // check whether the parameter type is allowed
8850 case Definition::A_TEMPLATE
:
8851 switch (par
->get_asstype()) {
8852 case Definition::A_PAR_VAL_IN
:
8853 case Definition::A_PAR_TEMPL_IN
:
8854 // these are allowed
8857 par
->error("A template cannot have %s", par
->get_assname());
8860 case Definition::A_TESTCASE
:
8861 switch (par
->get_asstype()) {
8862 case Definition::A_PAR_TIMER
:
8863 case Definition::A_PAR_PORT
:
8864 // these are forbidden
8865 par
->error("A testcase cannot have %s", par
->get_assname());
8870 // everything is allowed for functions and altsteps
8874 switch(par
->get_asstype()) {
8875 case Common::Assignment::A_PAR_VAL_IN
:
8876 case Common::Assignment::A_PAR_TEMPL_IN
:
8877 case Common::Assignment::A_PAR_VAL_INOUT
:
8878 case Common::Assignment::A_PAR_TEMPL_INOUT
:
8879 if (is_startable
&& par
->get_Type()->is_component_internal())
8880 is_startable
= false;
8883 is_startable
= false;
8886 if (!par
->has_defval()) min_nof_pars
= i
+ 1;
8887 // the last parameter without a default value determines the minimum
8891 // check that @lazy paramterization not used in cases currently unsupported
8892 void FormalParList::chk_noLazyParams() {
8893 Error_Context
cntxt(this, "In formal parameter list");
8894 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8895 FormalPar
*par
= pars_v
[i
];
8896 if (par
->get_lazy_eval()) {
8897 par
->error("Formal parameter `%s' cannot be @lazy, not supported in this case.",
8898 par
->get_id().get_dispname().c_str());
8903 void FormalParList::chk_startability(const char *p_what
, const char *p_name
)
8905 if(!checked
) FATAL_ERROR("FormalParList::chk_startability()");
8906 if (is_startable
) return;
8907 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8908 FormalPar
*par
= pars_v
[i
];
8909 switch (par
->get_asstype()) {
8910 case Common::Assignment::A_PAR_VAL_IN
:
8911 case Common::Assignment::A_PAR_TEMPL_IN
:
8912 case Common::Assignment::A_PAR_VAL_INOUT
:
8913 case Common::Assignment::A_PAR_TEMPL_INOUT
:
8914 if (par
->get_Type()->is_component_internal()) {
8915 map
<Type
*,void> type_chain
;
8916 char* err_str
= mprintf("a parameter or embedded in a parameter of "
8917 "a function used in a start operation. "
8918 "%s `%s' cannot be started on a parallel test component "
8919 "because of `%s'", p_what
, p_name
, par
->get_description().c_str());
8920 par
->get_Type()->chk_component_internal(type_chain
, err_str
);
8925 par
->error("%s `%s' cannot be started on a parallel test component "
8926 "because it has %s", p_what
, p_name
, par
->get_description().c_str());
8931 void FormalParList::chk_compatibility(FormalParList
* p_fp_list
,
8934 size_t nof_type_pars
= pars_v
.size();
8935 size_t nof_function_pars
= p_fp_list
->pars_v
.size();
8936 // check for the number of parameters
8937 if (nof_type_pars
!= nof_function_pars
) {
8938 p_fp_list
->error("Too %s parameters: %lu was expected instead of %lu",
8939 nof_type_pars
< nof_function_pars
? "many" : "few",
8940 (unsigned long) nof_type_pars
, (unsigned long) nof_function_pars
);
8942 size_t upper_limit
=
8943 nof_type_pars
< nof_function_pars
? nof_type_pars
: nof_function_pars
;
8944 for (size_t i
= 0; i
< upper_limit
; i
++) {
8945 FormalPar
*type_par
= pars_v
[i
];
8946 FormalPar
*function_par
= p_fp_list
->pars_v
[i
];
8947 Error_Context
cntxt(function_par
, "In parameter #%lu",
8948 (unsigned long) (i
+ 1));
8949 FormalPar::asstype_t type_par_asstype
= type_par
->get_asstype();
8950 FormalPar::asstype_t function_par_asstype
= function_par
->get_asstype();
8951 // check for parameter kind equivalence
8952 // (in, out or inout / value or template)
8953 if (type_par_asstype
!= function_par_asstype
) {
8954 function_par
->error("The kind of the parameter is not the same as in "
8955 "type `%s': %s was expected instead of %s", where
,
8956 type_par
->get_assname(), function_par
->get_assname());
8958 // check for type equivalence
8959 if (type_par_asstype
!= FormalPar::A_PAR_TIMER
&&
8960 function_par_asstype
!= FormalPar::A_PAR_TIMER
) {
8961 Type
*type_par_type
= type_par
->get_Type();
8962 Type
*function_par_type
= function_par
->get_Type();
8963 if (!type_par_type
->is_identical(function_par_type
)) {
8964 function_par_type
->error("The type of the parameter is not the same "
8965 "as in type `%s': `%s' was expected instead of `%s'", where
,
8966 type_par_type
->get_typename().c_str(),
8967 function_par_type
->get_typename().c_str());
8968 } else if (type_par_type
->get_sub_type() && function_par_type
->get_sub_type() &&
8969 (type_par_type
->get_sub_type()->get_subtypetype()==function_par_type
->get_sub_type()->get_subtypetype()) &&
8970 (!type_par_type
->get_sub_type()->is_compatible(function_par_type
->get_sub_type()))) {
8971 // TODO: maybe equivalence should be checked, or maybe that is too strict
8972 function_par_type
->error(
8973 "Subtype mismatch: subtype %s has no common value with subtype %s",
8974 type_par_type
->get_sub_type()->to_string().c_str(),
8975 function_par_type
->get_sub_type()->to_string().c_str());
8978 // check for template restriction equivalence
8979 if (type_par
->get_template_restriction()!=
8980 function_par
->get_template_restriction()) {
8981 function_par
->error("The template restriction of the parameter is "
8982 "not the same as in type `%s': %s restriction was expected instead "
8983 "of %s restriction", where
,
8984 type_par
->get_template_restriction()==TR_NONE
? "no" :
8985 Template::get_restriction_name(type_par
->get_template_restriction()),
8986 function_par
->get_template_restriction()==TR_NONE
? "no" :
8987 Template::get_restriction_name(function_par
->
8988 get_template_restriction()));
8990 // check for @lazy equivalence
8991 if (type_par
->get_lazy_eval()!=function_par
->get_lazy_eval()) {
8992 function_par
->error("Parameter @lazy-ness mismatch");
8994 // check for name equivalence
8995 const Identifier
& type_par_id
= type_par
->get_id();
8996 const Identifier
& function_par_id
= function_par
->get_id();
8997 if (type_par_id
!= function_par_id
) {
8998 function_par
->warning("The name of the parameter is not the same "
8999 "as in type `%s': `%s' was expected instead of `%s'", where
,
9000 type_par_id
.get_dispname().c_str(),
9001 function_par_id
.get_dispname().c_str());
9006 bool FormalParList::fold_named_and_chk(ParsedActualParameters
*p_paps
,
9007 ActualParList
*p_aplist
)
9009 const size_t num_named
= p_paps
->get_nof_nps();
9010 const size_t num_unnamed
= p_paps
->get_nof_tis();
9011 size_t num_actual
= num_unnamed
;
9013 // Construct a map to tell us what index a FormalPar has
9014 typedef map
<FormalPar
*, size_t> formalpar_map_t
;
9015 formalpar_map_t formalpar_map
;
9017 size_t num_fp
= get_nof_fps();
9018 for (size_t fpx
= 0; fpx
< num_fp
; ++fpx
) {
9019 FormalPar
*fp
= get_fp_byIndex(fpx
);
9020 formalpar_map
.add(fp
, new size_t(fpx
));
9023 // Go through the named parameters
9024 for (size_t i
= 0; i
< num_named
; ++i
) {
9025 NamedParam
*np
= p_paps
->extract_np_byIndex(i
);
9026 // We are now responsible for np.
9028 if (has_fp_withName(*np
->get_name())) {
9029 // there is a formal parameter with that name
9030 FormalPar
*fp
= get_fp_byName(*np
->get_name());
9031 const size_t is_at
= *formalpar_map
[fp
]; // the index of the formal par
9032 if (is_at
>= num_actual
) {
9033 // There is no actual par in the unnamed part.
9034 // Create one from the named param.
9036 // First, pad the gap with '-'
9037 for (; num_actual
< is_at
; ++num_actual
) {
9039 if (pars_v
[num_actual
]->has_defval()) {
9040 not_used
= new Template(Template::TEMPLATE_NOTUSED
);
9042 else { // cannot use '-' if no default value
9043 not_used
= new Template(Template::TEMPLATE_ERROR
);
9045 TemplateInstance
*new_ti
= new TemplateInstance(0, 0, not_used
);
9046 // Conjure a location info at the beginning of the unnamed part
9047 // (that is, the beginning of the actual parameter list)
9048 new_ti
->set_location(p_paps
->get_tis()->get_filename(),
9049 p_paps
->get_tis()->get_first_line(),
9050 p_paps
->get_tis()->get_first_column(), 0, 0);
9051 p_paps
->get_tis()->add_ti(new_ti
);
9053 TemplateInstance
* namedti
= np
->extract_ti();
9054 p_paps
->get_tis()->add_ti(namedti
);
9057 // There is already an actual par at that position, fetch it
9058 TemplateInstance
* ti
= p_paps
->get_tis()->get_ti_byIndex(is_at
);
9059 Template::templatetype_t tt
= ti
->get_Template()->get_templatetype();
9061 if (is_at
>= num_unnamed
&& !ti
->get_Type() && !ti
->get_DerivedRef()
9062 && (tt
== Template::TEMPLATE_NOTUSED
|| tt
== Template::TEMPLATE_ERROR
)) {
9063 // NotUsed in the named part => padding
9064 np
->error("Named parameter `%s' out of order",
9065 np
->get_name()->get_dispname().c_str());
9067 // attempt to override an original unnamed param with a named one
9068 np
->error("Formal parameter `%s' assigned more than once",
9069 np
->get_name()->get_dispname().c_str());
9073 else { // no formal parameter with that name
9075 switch (my_def
->get_asstype()) {
9076 case Common::Assignment::A_TYPE
: {
9077 Type
*t
= my_def
->get_Type();
9079 switch (t
? t
->get_typetype() : 0) {
9080 case Type::T_FUNCTION
:
9081 nam
= mcopystr("Function reference");
9083 case Type::T_ALTSTEP
:
9084 nam
= mcopystr("Altstep reference");
9086 case Type::T_TESTCASE
:
9087 nam
= mcopystr("Testcase reference");
9090 FATAL_ERROR("FormalParList::chk_actual_parlist() "
9091 "Unexpected type %s", t
->get_typename().c_str());
9092 } // switch(typetype)
9095 nam
= mcopystr(my_def
->get_assname());
9097 } // switch(asstype)
9099 *nam
&= ~('a'-'A'); // Make the first letter uppercase
9100 p_paps
->get_tis()->error("%s `%s' has no formal parameter `%s'",
9102 my_def
->get_fullname().c_str(),
9103 np
->get_name()->get_dispname().c_str());
9110 for (size_t fpx
= 0; fpx
< num_fp
; ++fpx
) {
9111 delete formalpar_map
.get_nth_elem(fpx
);
9113 formalpar_map
.clear();
9115 return chk_actual_parlist(p_paps
->get_tis(), p_aplist
);
9118 bool FormalParList::chk_actual_parlist(TemplateInstances
*p_tis
,
9119 ActualParList
*p_aplist
)
9121 size_t formal_pars
= pars_v
.size();
9122 size_t actual_pars
= p_tis
->get_nof_tis();
9123 // p_aplist->get_nof_pars() is usually 0 on entry
9124 bool error_flag
= false;
9126 if (min_nof_pars
== formal_pars
) {
9127 // none of the parameters have default value
9128 if (actual_pars
!= formal_pars
) {
9129 p_tis
->error("Too %s parameters: %lu was expected "
9130 "instead of %lu", actual_pars
< formal_pars
? "few" : "many",
9131 (unsigned long) formal_pars
, (unsigned long) actual_pars
);
9135 // some parameters have default value
9136 if (actual_pars
< min_nof_pars
) {
9137 p_tis
->error("Too few parameters: at least %lu "
9138 "was expected instead of %lu",
9139 (unsigned long) min_nof_pars
, (unsigned long) actual_pars
);
9141 } else if (actual_pars
> formal_pars
) {
9142 p_tis
->error("Too many parameters: at most %lu "
9143 "was expected instead of %lu",
9144 (unsigned long) formal_pars
, (unsigned long) actual_pars
);
9149 // Do not check actual parameters in excess of the formal ones
9150 size_t upper_limit
= actual_pars
< formal_pars
? actual_pars
: formal_pars
;
9151 for (size_t i
= 0; i
< upper_limit
; i
++) {
9152 TemplateInstance
*ti
= p_tis
->get_ti_byIndex(i
);
9154 // the formal parameter for the current actual parameter
9155 FormalPar
*fp
= pars_v
[i
];
9156 Error_Context
cntxt(ti
, "In parameter #%lu for `%s'",
9157 (unsigned long) (i
+ 1), fp
->get_id().get_dispname().c_str());
9158 if (!ti
->get_Type() && !ti
->get_DerivedRef() && ti
->get_Template()
9159 ->get_templatetype() == Template::TEMPLATE_NOTUSED
) {
9160 if (fp
->has_defval()) {
9161 ActualPar
*defval
= fp
->get_defval();
9162 p_aplist
->add(new ActualPar(defval
));
9163 if (defval
->is_erroneous()) error_flag
= true;
9165 ti
->error("Not used symbol (`-') cannot be used for parameter "
9166 "that does not have default value");
9167 p_aplist
->add(new ActualPar());
9170 } else if (!ti
->get_Type() && !ti
->get_DerivedRef() && ti
->get_Template()
9171 ->get_templatetype() == Template::TEMPLATE_ERROR
) {
9172 ti
->error("Parameter not specified");
9174 ActualPar
*ap
= fp
->chk_actual_par(ti
, Type::EXPECTED_DYNAMIC_VALUE
);
9176 if (ap
->is_erroneous()) error_flag
= true;
9180 // The rest of formal parameters have no corresponding actual parameters.
9181 // Create actual parameters for them based on their default values
9182 // (which must exist).
9183 for (size_t i
= upper_limit
; i
< formal_pars
; i
++) {
9184 FormalPar
*fp
= pars_v
[i
];
9185 if (fp
->has_defval()) {
9186 ActualPar
*defval
= fp
->get_defval();
9187 p_aplist
->add(new ActualPar(defval
));
9188 if (defval
->is_erroneous()) error_flag
= true;
9190 p_aplist
->add(new ActualPar()); // erroneous
9197 bool FormalParList::chk_activate_argument(ActualParList
*p_aplist
,
9198 const char* p_description
)
9200 bool ret_val
= true;
9201 for(size_t i
= 0; i
< p_aplist
->get_nof_pars(); i
++) {
9202 ActualPar
*t_ap
= p_aplist
->get_par(i
);
9203 if(t_ap
->get_selection() != ActualPar::AP_REF
) continue;
9204 FormalPar
*t_fp
= pars_v
[i
];
9205 switch(t_fp
->get_asstype()) {
9206 case Common::Assignment::A_PAR_VAL_OUT
:
9207 case Common::Assignment::A_PAR_VAL_INOUT
:
9208 case Common::Assignment::A_PAR_TEMPL_OUT
:
9209 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9210 case Common::Assignment::A_PAR_TIMER
:
9211 //the checking shall be performed for these parameter types
9213 case Common::Assignment::A_PAR_PORT
:
9214 // port parameters are always correct because ports can be defined
9215 // only in component types
9218 FATAL_ERROR("FormalParList::chk_activate_argument()");
9220 Ref_base
*t_ref
= t_ap
->get_Ref();
9221 Common::Assignment
*t_par_ass
= t_ref
->get_refd_assignment();
9222 if(!t_par_ass
) FATAL_ERROR("FormalParList::chk_activate_argument()");
9223 switch (t_par_ass
->get_asstype()) {
9224 case Common::Assignment::A_VAR
:
9225 case Common::Assignment::A_VAR_TEMPLATE
:
9226 case Common::Assignment::A_TIMER
:
9227 // it is not allowed to pass references of local variables or timers
9228 if (t_par_ass
->is_local()) {
9229 t_ref
->error("Parameter #%lu of %s refers to %s, which is a local "
9230 "definition within a statement block and may have shorter "
9231 "lifespan than the activated default. Only references to "
9232 "variables and timers defined in the component type can be passed "
9233 "to activated defaults", (unsigned long) (i
+ 1), p_description
,
9234 t_par_ass
->get_description().c_str());
9238 case Common::Assignment::A_PAR_VAL_IN
:
9239 case Common::Assignment::A_PAR_VAL_OUT
:
9240 case Common::Assignment::A_PAR_VAL_INOUT
:
9241 case Common::Assignment::A_PAR_TEMPL_IN
:
9242 case Common::Assignment::A_PAR_TEMPL_OUT
:
9243 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9244 case Common::Assignment::A_PAR_TIMER
: {
9245 // it is not allowed to pass references pointing to formal parameters
9246 // except for activate() statements within testcases
9247 // note: all defaults are deactivated at the end of the testcase
9248 FormalPar
*t_refd_fp
= dynamic_cast<FormalPar
*>(t_par_ass
);
9249 if (!t_refd_fp
) FATAL_ERROR("FormalParList::chk_activate_argument()");
9250 FormalParList
*t_fpl
= t_refd_fp
->get_my_parlist();
9251 if (!t_fpl
|| !t_fpl
->my_def
)
9252 FATAL_ERROR("FormalParList::chk_activate_argument()");
9253 if (t_fpl
->my_def
->get_asstype() != Common::Assignment::A_TESTCASE
) {
9254 t_ref
->error("Parameter #%lu of %s refers to %s, which may have "
9255 "shorter lifespan than the activated default. Only references to "
9256 "variables and timers defined in the component type can be passed "
9257 "to activated defaults", (unsigned long) (i
+ 1), p_description
,
9258 t_par_ass
->get_description().c_str());
9268 char *FormalParList::generate_code(char *str
, size_t display_unused
/* = 0 */)
9270 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9271 if (i
> 0) str
= mputstr(str
, ", ");
9272 str
= pars_v
[i
]->generate_code_fpar(str
, i
< display_unused
);
9277 char* FormalParList::generate_code_defval(char* str
)
9279 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9280 str
= pars_v
[i
]->generate_code_defval(str
);
9285 void FormalParList::generate_code_defval(output_struct
*target
)
9287 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9288 pars_v
[i
]->generate_code_defval(target
);
9292 char *FormalParList::generate_code_actual_parlist(char *str
,
9293 const char *p_prefix
)
9295 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9296 if (i
> 0) str
= mputstr(str
, ", ");
9297 str
= mputstr(str
, p_prefix
);
9298 str
= mputstr(str
, pars_v
[i
]->get_id().get_name().c_str());
9303 char *FormalParList::generate_code_object(char *str
, const char *p_prefix
, char refch
)
9305 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9306 str
= pars_v
[i
]->generate_code_object(str
, p_prefix
, refch
);
9310 char *FormalParList::generate_shadow_objects(char *str
) const
9312 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9313 str
= pars_v
[i
]->generate_shadow_object(str
);
9317 char *FormalParList::generate_code_set_unbound(char *str
) const
9319 if (enable_set_bound_out_param
) return str
;
9320 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9321 str
= pars_v
[i
]->generate_code_set_unbound(str
);
9326 void FormalParList::dump(unsigned level
) const
9328 size_t nof_pars
= pars_v
.size();
9329 DEBUG(level
, "formal parameters: %lu pcs.", (unsigned long) nof_pars
);
9330 for(size_t i
= 0; i
< nof_pars
; i
++) pars_v
[i
]->dump(level
+ 1);
9333 // =================================
9335 // =================================
9337 ActualPar::ActualPar(Value
*v
)
9338 : Node(), selection(AP_VALUE
), my_scope(0), gen_restriction_check(TR_NONE
),
9339 gen_post_restriction_check(TR_NONE
)
9341 if (!v
) FATAL_ERROR("ActualPar::ActualPar()");
9345 ActualPar::ActualPar(TemplateInstance
*t
)
9346 : Node(), selection(AP_TEMPLATE
), my_scope(0),
9347 gen_restriction_check(TR_NONE
), gen_post_restriction_check(TR_NONE
)
9349 if (!t
) FATAL_ERROR("ActualPar::ActualPar()");
9353 ActualPar::ActualPar(Ref_base
*r
)
9354 : Node(), selection(AP_REF
), my_scope(0), gen_restriction_check(TR_NONE
),
9355 gen_post_restriction_check(TR_NONE
)
9357 if (!r
) FATAL_ERROR("ActualPar::ActualPar()");
9361 ActualPar::ActualPar(ActualPar
*a
)
9362 : Node(), selection(AP_DEFAULT
), my_scope(0),
9363 gen_restriction_check(TR_NONE
), gen_post_restriction_check(TR_NONE
)
9365 if (!a
) FATAL_ERROR("ActualPar::ActualPar()");
9369 ActualPar::~ActualPar()
9384 break; // nothing to do with act
9386 FATAL_ERROR("ActualPar::~ActualPar()");
9390 ActualPar
*ActualPar::clone() const
9392 FATAL_ERROR("ActualPar::clone");
9395 void ActualPar::set_fullname(const string
& p_fullname
)
9397 Node::set_fullname(p_fullname
);
9402 val
->set_fullname(p_fullname
);
9405 temp
->set_fullname(p_fullname
);
9408 ref
->set_fullname(p_fullname
);
9413 FATAL_ERROR("ActualPar::set_fullname()");
9417 void ActualPar::set_my_scope(Scope
*p_scope
)
9424 val
->set_my_scope(p_scope
);
9427 temp
->set_my_scope(p_scope
);
9430 ref
->set_my_scope(p_scope
);
9433 switch (act
->selection
) {
9435 ref
->set_my_scope(p_scope
);
9442 FATAL_ERROR("ActualPar::set_my_scope()");
9446 FATAL_ERROR("ActualPar::set_my_scope()");
9450 Value
*ActualPar::get_Value() const
9452 if (selection
!= AP_VALUE
) FATAL_ERROR("ActualPar::get_Value()");
9456 TemplateInstance
*ActualPar::get_TemplateInstance() const
9458 if (selection
!= AP_TEMPLATE
)
9459 FATAL_ERROR("ActualPar::get_TemplateInstance()");
9463 Ref_base
*ActualPar::get_Ref() const
9465 if (selection
!= AP_REF
) FATAL_ERROR("ActualPar::get_Ref()");
9469 ActualPar
*ActualPar::get_ActualPar() const
9471 if (selection
!= AP_DEFAULT
) FATAL_ERROR("ActualPar::get_ActualPar()");
9475 void ActualPar::chk_recursions(ReferenceChain
& refch
)
9477 switch (selection
) {
9480 val
->chk_recursions(refch
);
9484 Ref_base
*derived_ref
= temp
->get_DerivedRef();
9486 ActualParList
*parlist
= derived_ref
->get_parlist();
9489 parlist
->chk_recursions(refch
);
9494 Ttcn::Def_Template
* defTemp
= temp
->get_Referenced_Base_Template();
9497 refch
.add(defTemp
->get_fullname());
9501 temp
->get_Template()->chk_recursions(refch
);
9509 bool ActualPar::has_single_expr()
9511 switch (selection
) {
9513 return val
->has_single_expr();
9515 if (gen_restriction_check
!=TR_NONE
||
9516 gen_post_restriction_check
!=TR_NONE
) return false;
9517 return temp
->has_single_expr();
9519 if (gen_restriction_check
!=TR_NONE
||
9520 gen_post_restriction_check
!=TR_NONE
) return false;
9521 if (use_runtime_2
&& ref
->get_subrefs() != NULL
) {
9522 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
9523 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
9524 if (FieldOrArrayRef::ARRAY_REF
== subrefs
->get_ref(i
)->get_type()) {
9529 return ref
->has_single_expr();
9533 FATAL_ERROR("ActualPar::has_single_expr()");
9538 void ActualPar::set_code_section(
9539 GovernedSimple::code_section_t p_code_section
)
9541 switch (selection
) {
9543 val
->set_code_section(p_code_section
);
9546 temp
->set_code_section(p_code_section
);
9549 ref
->set_code_section(p_code_section
);
9555 void ActualPar::generate_code(expression_struct
*expr
, bool copy_needed
, bool lazy_param
, bool used_as_lvalue
) const
9557 switch (selection
) {
9559 if (lazy_param
) { // copy_needed doesn't matter in this case
9560 LazyParamData::init(used_as_lvalue
);
9561 LazyParamData::generate_code(expr
, val
, my_scope
);
9562 LazyParamData::clean();
9563 if (val
->get_valuetype() == Value::V_REFD
) {
9564 // check if the reference is a parameter, mark it as used if it is
9565 Reference
* ref
= dynamic_cast<Reference
*>(val
->get_reference());
9567 ref
->ref_usage_found();
9571 if (copy_needed
) expr
->expr
= mputprintf(expr
->expr
, "%s(",
9572 val
->get_my_governor()->get_genname_value(my_scope
).c_str());
9573 if (use_runtime_2
&& TypeConv::needs_conv_refd(val
)) {
9574 // Generate everything to preamble to be able to tackle the wrapper
9575 // constructor call. TODO: Reduce the number of temporaries created.
9576 const string
& tmp_id
= val
->get_temporary_id();
9577 const char *tmp_id_str
= tmp_id
.c_str();
9578 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
9579 val
->get_my_governor()->get_genname_value(my_scope
).c_str(),
9581 expr
->preamble
= TypeConv::gen_conv_code_refd(expr
->preamble
,
9583 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
9584 } else val
->generate_code_expr(expr
);
9585 if (copy_needed
) expr
->expr
= mputc(expr
->expr
, ')');
9589 if (lazy_param
) { // copy_needed doesn't matter in this case
9590 LazyParamData::init(used_as_lvalue
);
9591 LazyParamData::generate_code(expr
, temp
, gen_restriction_check
, my_scope
);
9592 LazyParamData::clean();
9593 if (temp
->get_DerivedRef() != NULL
||
9594 temp
->get_Template()->get_templatetype() == Template::TEMPLATE_REFD
) {
9595 // check if the reference is a parameter, mark it as used if it is
9596 Reference
* ref
= dynamic_cast<Reference
*>(temp
->get_DerivedRef() != NULL
?
9597 temp
->get_DerivedRef() : temp
->get_Template()->get_reference());
9599 ref
->ref_usage_found();
9604 expr
->expr
= mputprintf(expr
->expr
, "%s(", temp
->get_Template()
9605 ->get_my_governor()->get_genname_template(my_scope
).c_str());
9606 if (use_runtime_2
&& TypeConv::needs_conv_refd(temp
->get_Template())) {
9607 const string
& tmp_id
= temp
->get_Template()->get_temporary_id();
9608 const char *tmp_id_str
= tmp_id
.c_str();
9609 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
9610 temp
->get_Template()->get_my_governor()
9611 ->get_genname_template(my_scope
).c_str(), tmp_id_str
);
9612 expr
->preamble
= TypeConv::gen_conv_code_refd(expr
->preamble
,
9613 tmp_id_str
, temp
->get_Template());
9614 // Not incorporated into gen_conv_code() yet.
9615 if (gen_restriction_check
!= TR_NONE
)
9616 expr
->preamble
= Template::generate_restriction_check_code(
9617 expr
->preamble
, tmp_id_str
, gen_restriction_check
);
9618 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
9619 } else temp
->generate_code(expr
, gen_restriction_check
);
9620 if (copy_needed
) expr
->expr
= mputc(expr
->expr
, ')');
9624 if (lazy_param
) FATAL_ERROR("ActualPar::generate_code()"); // syntax error should have already happened
9625 if (copy_needed
) FATAL_ERROR("ActualPar::generate_code()");
9626 if (gen_restriction_check
!= TR_NONE
||
9627 gen_post_restriction_check
!= TR_NONE
) {
9628 // generate runtime check for restricted templates
9629 // code for reference + restriction check
9630 Common::Assignment
*ass
= ref
->get_refd_assignment();
9631 const string
& tmp_id
= my_scope
->get_scope_mod_gen()->get_temporary_id();
9632 const char *tmp_id_str
= tmp_id
.c_str();
9633 expression_struct ref_expr
;
9634 Code::init_expr(&ref_expr
);
9635 ref
->generate_code_const_ref(&ref_expr
);
9636 ref_expr
.preamble
= mputprintf(ref_expr
.preamble
, "%s& %s = %s;\n",
9637 ass
->get_Type()->get_genname_template(ref
->get_my_scope()).c_str(),
9638 tmp_id_str
, ref_expr
.expr
);
9639 if (gen_restriction_check
!= TR_NONE
) {
9640 ref_expr
.preamble
= Template::generate_restriction_check_code(
9641 ref_expr
.preamble
, tmp_id_str
, gen_restriction_check
);
9643 if (gen_post_restriction_check
!= TR_NONE
) {
9644 ref_expr
.postamble
= Template::generate_restriction_check_code(
9645 ref_expr
.postamble
, tmp_id_str
, gen_post_restriction_check
);
9647 // copy content of ref_expr to expr
9648 expr
->preamble
= mputstr(expr
->preamble
, ref_expr
.preamble
);
9649 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_id_str
);
9650 expr
->postamble
= mputstr(expr
->postamble
, ref_expr
.postamble
);
9651 Code::free_expr(&ref_expr
);
9653 ref
->generate_code(expr
);
9657 if (copy_needed
) FATAL_ERROR("ActualPar::generate_code()");
9658 switch (act
->selection
) {
9661 LazyParamData::generate_code_ap_default_ref(expr
, act
->ref
, my_scope
);
9663 act
->ref
->generate_code(expr
);
9668 LazyParamData::generate_code_ap_default_value(expr
, act
->val
, my_scope
);
9670 expr
->expr
= mputstr(expr
->expr
, act
->val
->get_genname_own(my_scope
).c_str());
9675 LazyParamData::generate_code_ap_default_ti(expr
, act
->temp
, my_scope
);
9677 expr
->expr
= mputstr(expr
->expr
, act
->temp
->get_Template()->get_genname_own(my_scope
).c_str());
9681 FATAL_ERROR("ActualPar::generate_code()");
9685 FATAL_ERROR("ActualPar::generate_code()");
9689 char *ActualPar::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
9691 switch (selection
) {
9693 str
= val
->rearrange_init_code(str
, usage_mod
);
9696 str
= temp
->rearrange_init_code(str
, usage_mod
);
9700 str
= act
->rearrange_init_code_defval(str
, usage_mod
);
9703 FATAL_ERROR("ActualPar::rearrange_init_code()");
9708 char *ActualPar::rearrange_init_code_defval(char *str
, Common::Module
* usage_mod
)
9710 switch (selection
) {
9712 if (val
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
9713 str
= val
->generate_code_init(str
, val
->get_lhs_name().c_str());
9717 str
= temp
->rearrange_init_code(str
, usage_mod
);
9718 Template
*t
= temp
->get_Template();
9719 if (t
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
9720 Ref_base
*dref
= temp
->get_DerivedRef();
9722 expression_struct expr
;
9723 Code::init_expr(&expr
);
9724 expr
.expr
= mputprintf(expr
.expr
, "%s = ", t
->get_lhs_name().c_str());
9725 dref
->generate_code(&expr
);
9726 str
= Code::merge_free_expr(str
, &expr
, false);
9728 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
9732 FATAL_ERROR("ActualPar::rearrange_init_code_defval()");
9737 void ActualPar::append_stringRepr(string
& str
) const
9739 switch (selection
) {
9741 str
+= val
->get_stringRepr();
9744 temp
->append_stringRepr(str
);
9747 str
+= ref
->get_dispname();
9753 str
+= "<erroneous actual parameter>";
9757 void ActualPar::dump(unsigned level
) const
9759 switch (selection
) {
9761 DEBUG(level
, "actual parameter: value");
9762 val
->dump(level
+ 1);
9765 DEBUG(level
, "actual parameter: template");
9766 temp
->dump(level
+ 1);
9769 DEBUG(level
, "actual parameter: reference");
9770 ref
->dump(level
+ 1);
9773 DEBUG(level
, "actual parameter: default");
9776 DEBUG(level
, "actual parameter: erroneous");
9780 // =================================
9781 // ===== ActualParList
9782 // =================================
9784 ActualParList::ActualParList(const ActualParList
& p
)
9787 size_t nof_pars
= p
.params
.size();
9788 for (size_t i
= 0; i
< nof_pars
; i
++) params
.add(p
.params
[i
]->clone());
9791 ActualParList::~ActualParList()
9793 size_t nof_pars
= params
.size();
9794 for (size_t i
= 0; i
< nof_pars
; i
++) delete params
[i
];
9798 ActualParList
*ActualParList::clone() const
9800 return new ActualParList(*this);
9803 void ActualParList::set_fullname(const string
& p_fullname
)
9805 Node::set_fullname(p_fullname
);
9806 size_t nof_pars
= params
.size();
9807 for(size_t i
= 0; i
< nof_pars
; i
++)
9808 params
[i
]->set_fullname(p_fullname
+
9809 ".<parameter" + Int2string(i
+ 1) + ">");
9812 void ActualParList::set_my_scope(Scope
*p_scope
)
9814 size_t nof_pars
= params
.size();
9815 for (size_t i
= 0; i
< nof_pars
; i
++) params
[i
]->set_my_scope(p_scope
);
9818 void ActualParList::chk_recursions(ReferenceChain
& refch
)
9820 size_t nof_pars
= params
.size();
9821 for (size_t i
= 0; i
< nof_pars
; i
++)
9822 params
[i
]->chk_recursions(refch
);
9825 void ActualParList::generate_code_noalias(expression_struct
*expr
, FormalParList
*p_fpl
)
9827 size_t nof_pars
= params
.size();
9828 for (size_t i
= 0; i
< nof_pars
; i
++) {
9829 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
9830 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());
9834 void ActualParList::generate_code_alias(expression_struct
*expr
,
9835 FormalParList
*p_fpl
, Type
*p_comptype
, bool p_compself
)
9837 size_t nof_pars
= params
.size();
9838 // collect all value and template definitions that are passed by reference
9839 map
<Common::Assignment
*, void> value_refs
, template_refs
;
9840 for (size_t i
= 0; i
< nof_pars
; i
++) {
9841 ActualPar
*par
= params
[i
];
9842 if (par
->get_selection() == ActualPar::AP_DEFAULT
)
9843 par
= par
->get_ActualPar();
9844 if (par
->get_selection() == ActualPar::AP_REF
) {
9845 Common::Assignment
*ass
= par
->get_Ref()->get_refd_assignment();
9846 switch (ass
->get_asstype()) {
9847 case Common::Assignment::A_VAR
:
9848 case Common::Assignment::A_PAR_VAL_IN
:
9849 case Common::Assignment::A_PAR_VAL_OUT
:
9850 case Common::Assignment::A_PAR_VAL_INOUT
:
9851 if (!value_refs
.has_key(ass
)) value_refs
.add(ass
, 0);
9853 case Common::Assignment::A_VAR_TEMPLATE
:
9854 case Common::Assignment::A_PAR_TEMPL_IN
:
9855 case Common::Assignment::A_PAR_TEMPL_OUT
:
9856 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9857 if (!template_refs
.has_key(ass
)) template_refs
.add(ass
, 0);
9863 // walk through the parameter list and generate the code
9864 // add an extra copy constructor call to the referenced value and template
9865 // parameters if the referred definition is also passed by reference to
9866 // another parameter
9867 for (size_t i
= 0; i
< nof_pars
; i
++) {
9868 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
9869 ActualPar
*par
= params
[i
];
9870 bool copy_needed
= false;
9871 // the copy constructor call is not needed if the parameter is copied
9872 // into a shadow object in the body of the called function
9873 if (!p_fpl
|| !p_fpl
->get_fp_byIndex(i
)->get_used_as_lvalue()) {
9874 switch (par
->get_selection()) {
9875 case ActualPar::AP_VALUE
: {
9876 Value
*v
= par
->get_Value();
9877 if (v
->get_valuetype() == Value::V_REFD
) {
9878 Common::Assignment
*t_ass
=
9879 v
->get_reference()->get_refd_assignment();
9880 if (value_refs
.has_key(t_ass
)) {
9881 // a reference to the same variable is also passed to the called
9884 } else if (p_comptype
|| p_compself
) {
9885 // the called definition has a 'runs on' clause so it can access
9886 // component variables
9887 switch (t_ass
->get_asstype()) {
9888 case Common::Assignment::A_PAR_VAL_OUT
:
9889 case Common::Assignment::A_PAR_VAL_INOUT
:
9890 // the parameter may be an alias of a component variable
9893 case Common::Assignment::A_VAR
:
9894 // copy is needed if t_ass is a component variable that is
9895 // visible by the called definition
9896 if (!t_ass
->is_local()) copy_needed
= true;
9897 /** \todo component type compatibility: check whether t_ass is
9898 * visible from p_comptype (otherwise copy is not needed) */
9905 case ActualPar::AP_TEMPLATE
: {
9906 TemplateInstance
*ti
= par
->get_TemplateInstance();
9907 if (!ti
->get_DerivedRef()) {
9908 Template
*t
= ti
->get_Template();
9909 if (t
->get_templatetype() == Template::TEMPLATE_REFD
) {
9910 Common::Assignment
*t_ass
=
9911 t
->get_reference()->get_refd_assignment();
9912 if (template_refs
.has_key(t_ass
)) {
9913 // a reference to the same variable is also passed to the called
9916 } else if (p_comptype
|| p_compself
) {
9917 // the called definition has a 'runs on' clause so it can access
9918 // component variables
9919 switch (t_ass
->get_asstype()) {
9920 case Common::Assignment::A_PAR_TEMPL_OUT
:
9921 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9922 // the parameter may be an alias of a component variable
9925 case Common::Assignment::A_VAR_TEMPLATE
:
9926 // copy is needed if t_ass is a component variable that is
9927 // visible by the called definition
9928 if (!t_ass
->is_local()) copy_needed
= true;
9929 /** \todo component type compatibility: check whether t_ass is
9930 * visible from p_comptype (otherwise copy is not needed) */
9942 if (use_runtime_2
&& ActualPar::AP_REF
== par
->get_selection()) {
9943 // if the parameter references an element of a record of/set of, then
9944 // the record of object needs to know, so it doesn't delete the referenced
9946 Ref_base
* ref
= par
->get_Ref();
9947 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
9948 if (subrefs
!= NULL
) {
9949 Common::Assignment
* ass
= ref
->get_refd_assignment();
9951 for (ref_i
= 0; ref_i
< subrefs
->get_nof_refs(); ++ref_i
) {
9952 FieldOrArrayRef
* subref
= subrefs
->get_ref(ref_i
);
9953 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
9954 // set the referenced index in each array in the subrefs
9955 expression_struct array_expr
;
9956 Code::init_expr(&array_expr
);
9957 // the array object's name contains the reference, followed by
9958 // the subrefs before the current array ref
9959 array_expr
.expr
= mcopystr(LazyParamData::in_lazy() ?
9960 LazyParamData::add_ref_genname(ass
, ref
->get_my_scope()).c_str() :
9961 ass
->get_genname_from_scope(ref
->get_my_scope()).c_str());
9963 subrefs
->generate_code(&array_expr
, ass
, ref_i
);
9965 expression_struct index_expr
;
9966 Code::init_expr(&index_expr
);
9967 subrefs
->get_ref(ref_i
)->get_val()->generate_code_expr(&index_expr
);
9968 // insert any preambles the array object or the index might have
9969 if (array_expr
.preamble
!= NULL
) {
9970 expr
->preamble
= mputstr(expr
->preamble
, array_expr
.preamble
);
9971 expr
->postamble
= mputstr(expr
->postamble
, array_expr
.preamble
);
9973 if (index_expr
.preamble
!= NULL
) {
9974 expr
->preamble
= mputstr(expr
->preamble
, index_expr
.preamble
);
9975 expr
->postamble
= mputstr(expr
->postamble
, index_expr
.preamble
);
9977 // let the array object know that the index is referenced before
9978 // calling the function, and let it know that it's now longer
9979 // referenced after the function call (this is done with the help
9980 // of the RefdIndexHandler's constructor and destructor)
9981 string tmp_id
= ref
->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
9982 expr
->preamble
= mputprintf(expr
->preamble
,
9983 "RefdIndexHandler %s(&%s, %s);\n",
9984 tmp_id
.c_str(), array_expr
.expr
, index_expr
.expr
);
9985 // insert any postambles the array object or the index might have
9986 if (array_expr
.postamble
!= NULL
) {
9987 expr
->preamble
= mputstr(expr
->preamble
, array_expr
.postamble
);
9988 expr
->postamble
= mputstr(expr
->postamble
, array_expr
.postamble
);
9990 if (index_expr
.postamble
!= NULL
) {
9991 expr
->preamble
= mputstr(expr
->preamble
, index_expr
.postamble
);
9992 expr
->postamble
= mputstr(expr
->postamble
, index_expr
.postamble
);
9994 Code::free_expr(&array_expr
);
9995 Code::free_expr(&index_expr
);
9996 } // if (FieldOrArrayRef::ARRAY_REF == subref->get_type())
9998 } // if (subrefs != NULL)
9999 } // if (ActualPar::AP_REF == par->get_selection())
10001 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());
10003 value_refs
.clear();
10004 template_refs
.clear();
10007 char *ActualParList::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
10009 for (size_t i
= 0; i
< params
.size(); i
++)
10010 str
= params
[i
]->rearrange_init_code(str
, usage_mod
);
10014 void ActualParList::dump(unsigned level
) const
10016 DEBUG(level
, "actual parameter list: %lu parameters",
10017 (unsigned long) params
.size());
10018 for (size_t i
= 0; i
< params
.size(); i
++)
10019 params
[i
]->dump(level
+ 1);