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
19 * Zalanyi, Balazs Andor
22 ******************************************************************************/
23 #include "../../common/dbgnew.hh"
24 #include "AST_ttcn3.hh"
25 #include "../Identifier.hh"
26 #include "../CompilerError.hh"
27 #include "../Setting.hh"
29 #include "../CompField.hh"
30 #include "../CompType.hh"
31 #include "../TypeCompat.hh"
32 #include "../Valuestuff.hh"
33 #include "../Value.hh"
34 #include "Ttcnstuff.hh"
35 #include "TtcnTemplate.hh"
36 #include "Templatestuff.hh"
37 #include "ArrayDimensions.hh"
40 #include "Statement.hh"
42 #include "Attributes.hh"
43 #include "PatternString.hh"
44 #include "../../common/version_internal.h"
45 #include "../CodeGenHelper.hh"
46 #include "../../common/JSON_Tokenizer.hh"
47 #include "../DebuggerStuff.hh"
50 // implemented in coding_attrib_p.y
51 extern Ttcn::ExtensionAttributes
* parse_extattributes(
52 Ttcn::WithAttribPath
*w_attrib_path
);
54 // implemented in compiler.y
55 extern Ttcn::ErroneousAttributeSpec
* ttcn3_parse_erroneous_attr_spec_string(
56 const char* p_str
, const Common::Location
& str_loc
);
59 extern void init_coding_attrib_lex(const Ttcn::AttributeSpec
& attrib
);
60 extern int coding_attrib_parse();
61 extern void cleanup_coding_attrib_lex();
62 extern Ttcn::ExtensionAttributes
*extatrs
;
64 /** Create a field name in the anytype
66 * The output of this function will be used to create an identifier
67 * to be used as the field name in the anytype.
68 * The type_name may be a built-in type (e.g. "integer") or a user-defined
71 * If the name has multiple components (a fullname?), it keeps just the last
72 * component without any dots. *
73 * Also, the space in "universal charstring" needs to be replaced
74 * with an underscore to make it an identifier.
76 * Note: Prefixing with "AT_" is not done here, but in defUnionClass().
78 * @param type_name string
79 * @return string to be used as the identifier.
81 string
anytype_field(const string
& type_name
)
83 string
retval(type_name
);
85 // keep just the last part of the name
86 // TODO check if there's a way to get just the last component (note that fetching the string is done outside of this function)
87 size_t dot
= retval
.rfind('.');
88 if (dot
>= retval
.size()) dot
= 0;
90 retval
.replace(0, dot
, "");
95 extern Common::Modules
*modules
; // in main.cc
98 static const string
_T_("_T_");
103 using namespace Common
;
105 // =================================
106 // ===== FieldOrArrayRef
107 // =================================
109 FieldOrArrayRef::FieldOrArrayRef(const FieldOrArrayRef
& p
)
110 : Node(p
), Location(p
), ref_type(p
.ref_type
)
112 switch (p
.ref_type
) {
114 u
.id
= p
.u
.id
->clone();
117 u
.arp
= p
.u
.arp
->clone();
120 FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
124 FieldOrArrayRef::FieldOrArrayRef(Identifier
*p_id
)
125 : Node(), Location(), ref_type(FIELD_REF
)
127 if (!p_id
) FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
131 FieldOrArrayRef::FieldOrArrayRef(Value
*p_arp
)
132 : Node(), Location(), ref_type(ARRAY_REF
)
134 if (!p_arp
) FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
138 FieldOrArrayRef::~FieldOrArrayRef()
148 FATAL_ERROR("FieldOrArrayRef::~FieldOrArrayRef()");
152 FieldOrArrayRef
*FieldOrArrayRef::clone() const
154 return new FieldOrArrayRef(*this);
157 void FieldOrArrayRef::set_fullname(const string
& p_fullname
)
159 Node::set_fullname(p_fullname
);
160 if (ref_type
== ARRAY_REF
)
161 u
.arp
->set_fullname(p_fullname
+ ".<array_index>");
164 void FieldOrArrayRef::set_my_scope(Scope
*p_scope
)
166 if (ref_type
== ARRAY_REF
) u
.arp
->set_my_scope(p_scope
);
169 const Identifier
* FieldOrArrayRef::get_id() const
171 if (ref_type
!= FIELD_REF
) FATAL_ERROR("FieldOrArrayRef::get_id()");
175 Value
*FieldOrArrayRef::get_val() const
177 if (ref_type
!= ARRAY_REF
) FATAL_ERROR("FieldOrArrayRef::get_val()");
181 void FieldOrArrayRef::append_stringRepr(string
& str
) const
186 str
+= u
.id
->get_dispname();
190 str
+= u
.arp
->get_stringRepr();
194 str
+= "<unknown sub-reference>";
198 void FieldOrArrayRef::set_field_name_to_lowercase()
200 if (ref_type
!= FIELD_REF
) FATAL_ERROR("FieldOrArrayRef::set_field_name_to_lowercase()");
201 string new_name
= u
.id
->get_name();
202 if (isupper(new_name
[0])) {
203 new_name
[0] = tolower(new_name
[0]);
204 if (new_name
[new_name
.size() - 1] == '_') {
205 // an underscore is inserted at the end of the field name if it's
206 // a basic type's name (since it would conflict with the class generated
208 // remove the underscore, it won't conflict with anything if its name
209 // starts with a lowercase letter
210 new_name
.replace(new_name
.size() - 1, 1, "");
213 u
.id
= new Identifier(Identifier::ID_NAME
, new_name
);
217 // =================================
218 // ===== FieldOrArrayRefs
219 // =================================
221 FieldOrArrayRefs::FieldOrArrayRefs(const FieldOrArrayRefs
& p
)
222 : Node(p
), refs_str_element(false)
224 for (size_t i
= 0; i
< p
.refs
.size(); i
++) refs
.add(p
.refs
[i
]->clone());
227 FieldOrArrayRefs::~FieldOrArrayRefs()
229 for (size_t i
= 0; i
< refs
.size(); i
++) delete refs
[i
];
233 FieldOrArrayRefs
*FieldOrArrayRefs::clone() const
235 return new FieldOrArrayRefs(*this);
238 void FieldOrArrayRefs::set_fullname(const string
& p_fullname
)
240 Node::set_fullname(p_fullname
);
241 for (size_t i
= 0; i
< refs
.size(); i
++)
242 refs
[i
]->set_fullname(p_fullname
+
243 ".<sub_reference" + Int2string(i
+ 1) + ">");
246 void FieldOrArrayRefs::set_my_scope(Scope
*p_scope
)
248 for (size_t i
= 0; i
< refs
.size(); i
++) refs
[i
]->set_my_scope(p_scope
);
251 bool FieldOrArrayRefs::has_unfoldable_index() const
253 for (size_t i
= 0; i
< refs
.size(); i
++) {
254 FieldOrArrayRef
*ref
= refs
[i
];
255 if (ref
->get_type() == FieldOrArrayRef::ARRAY_REF
) {
256 Value
*v
= ref
->get_val();
257 v
->set_lowerid_to_ref();
258 if (v
->is_unfoldable()) return true;
264 void FieldOrArrayRefs::remove_refs(size_t n
)
266 for (size_t i
= 0; i
< n
; i
++) delete refs
[i
];
267 refs
.replace(0, n
, NULL
);
268 set_fullname(get_fullname());
271 /* remove_last_field is used when unfolding references for
272 ischosen and ispresent function operands.
273 In this case it is NOT sure the last field exists.
274 Calling remove_last_field previously
275 will avoid getting the "variable...Has no member called..." error message.
276 The last field component will be checked as a separate step.
277 Warning: the removed Identifier has to be deleted later */
279 Identifier
* FieldOrArrayRefs::remove_last_field()
281 if (refs
.size() == 0) return 0;
282 size_t last_elem_ind
= refs
.size() - 1;
283 FieldOrArrayRef
* last_elem
= refs
[last_elem_ind
];
284 if (last_elem
->get_type() == FieldOrArrayRef::FIELD_REF
) {
285 Identifier
*ret_val
= last_elem
->get_id()->clone();
287 refs
.replace(last_elem_ind
, 1, NULL
);
292 void FieldOrArrayRefs::generate_code(expression_struct
*expr
,
293 Common::Assignment
*ass
, size_t nof_subrefs
/* = UINT_MAX*/)
296 bool is_template
= false;
297 switch (ass
->get_asstype()) {
298 case Common::Assignment::A_CONST
: // a Def_Const
299 case Common::Assignment::A_EXT_CONST
: // a Def_ExtConst
300 case Common::Assignment::A_MODULEPAR
: // a Def_Modulepar
301 case Common::Assignment::A_VAR
: // a Def_Var
302 case Common::Assignment::A_FUNCTION_RVAL
: // a Def_Function
303 case Common::Assignment::A_EXT_FUNCTION_RVAL
: // a Def_ExtFunction
304 case Common::Assignment::A_PAR_VAL_IN
: // a FormalPar
305 case Common::Assignment::A_PAR_VAL_OUT
: // a FormalPar
306 case Common::Assignment::A_PAR_VAL_INOUT
: // a FormalPar
307 // The type is important since the referred entities are value objects.
308 type
= ass
->get_Type();
310 case Common::Assignment::A_MODULEPAR_TEMP
: // a Def_Modulepar_Template
311 case Common::Assignment::A_TEMPLATE
: // a Def_Template
312 case Common::Assignment::A_VAR_TEMPLATE
: // a Def_Var_Template
313 case Common::Assignment::A_PAR_TEMPL_IN
: // a FormalPar
314 case Common::Assignment::A_PAR_TEMPL_OUT
: // a FormalPar
315 case Common::Assignment::A_PAR_TEMPL_INOUT
: // a FormalPar
316 // The type is semi-important because fields of anytype templates
318 type
= ass
->get_Type();
321 case Common::Assignment::A_TIMER
: // a Def_Timer
322 case Common::Assignment::A_PORT
: // a Def_Port
323 case Common::Assignment::A_FUNCTION_RTEMP
: // a Def_Function
324 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: // a Def_ExtFunction
325 case Common::Assignment::A_PAR_TIMER
: // a FormalPar
326 case Common::Assignment::A_PAR_PORT
: // a FormalPar
327 // The type is not relevant (i.e. the optional fields do not require
328 // special handling).
332 // Reference to other definitions cannot occur during code generation.
333 FATAL_ERROR("FieldOrArrayRefs::generate_code()");
336 size_t n_refs
= (nof_subrefs
!= UINT_MAX
) ? nof_subrefs
: refs
.size();
337 for (size_t i
= 0; i
< n_refs
; i
++) {
338 if (type
) type
= type
->get_type_refd_last();
339 // type changes inside the loop; need to recompute "last" every time.
340 FieldOrArrayRef
*ref
= refs
[i
];
341 if (ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
342 // Write a call to the field accessor method.
343 // Fields of the anytype get a special prefix; see also:
344 // Template::generate_code_init_se, TypeConv::gen_conv_func_choice_anytype,
345 // defUnionClass and defUnionTemplate.
346 const Identifier
& id
= *ref
->get_id();
347 expr
->expr
= mputprintf(expr
->expr
, ".%s%s()",
348 ((type
!=0 && type
->get_typetype()==Type::T_ANYTYPE
) ? "AT_" : ""),
349 id
.get_name().c_str());
351 CompField
*cf
= type
->get_comp_byName(id
);
352 // If the field is optional, the return type of the accessor is an
353 // OPTIONAL<T>. Write a call to OPTIONAL<T>::operator(),
354 // which "reaches into" the OPTIONAL to get the contained type T.
355 // Don't do this at the end of the reference chain.
356 // Accessor methods for a foo_template return a bar_template
357 // and OPTIONAL<> is not involved, hence no "()".
358 if (!is_template
&& i
< n_refs
- 1 && cf
->get_is_optional())
359 expr
->expr
= mputstr(expr
->expr
, "()");
360 // Follow the field type.
361 type
= cf
->get_type();
364 // Generate code for array reference.
365 expr
->expr
= mputc(expr
->expr
, '[');
366 ref
->get_val()->generate_code_expr(expr
);
367 expr
->expr
= mputc(expr
->expr
, ']');
369 // Follow the embedded type.
370 switch (type
->get_typetype()) {
374 type
= type
->get_ofType();
377 // The index points to a string element.
378 // There are no further sub-references.
382 } // if (ref->get_type)
386 void FieldOrArrayRefs::append_stringRepr(string
& str
) const
388 for (size_t i
= 0; i
< refs
.size(); i
++) refs
[i
]->append_stringRepr(str
);
391 // =================================
393 // =================================
395 Ref_base::Ref_base(const Ref_base
& p
)
396 : Ref_simple(p
), subrefs(p
.subrefs
)
398 modid
= p
.modid
? p
.modid
->clone() : 0;
399 id
= p
.id
? p
.id
->clone() : 0;
400 params_checked
= p
.is_erroneous
;
403 Ref_base::Ref_base(Identifier
*p_modid
, Identifier
*p_id
)
404 : Ref_simple(), modid(p_modid
), id(p_id
), params_checked(false)
405 , usedInIsbound(false)
408 FATAL_ERROR("NULL parameter: Ttcn::Ref_base::Ref_base()");
411 Ref_base::~Ref_base()
417 void Ref_base::set_fullname(const string
& p_fullname
)
419 Ref_simple::set_fullname(p_fullname
);
420 subrefs
.set_fullname(p_fullname
);
423 void Ref_base::set_my_scope(Scope
*p_scope
)
425 Ref_simple::set_my_scope(p_scope
);
426 subrefs
.set_my_scope(p_scope
);
429 /* returns the referenced variable's base type or value */
430 Setting
* Ref_base::get_refd_setting()
432 Common::Assignment
*ass
= get_refd_assignment();
433 if (ass
) return ass
->get_Setting();
437 FieldOrArrayRefs
*Ref_base::get_subrefs()
439 if (!id
) get_modid();
440 if (subrefs
.get_nof_refs() == 0) return 0;
441 else return &subrefs
;
444 bool Ref_base::has_single_expr()
446 Common::Assignment
*ass
= get_refd_assignment();
447 if (!ass
) FATAL_ERROR("Ref_base::has_single_expr()");
448 for (size_t i
= 0; i
< subrefs
.get_nof_refs(); i
++) {
449 FieldOrArrayRef
*ref
= subrefs
.get_ref(i
);
450 if (ref
->get_type() == FieldOrArrayRef::ARRAY_REF
&&
451 !ref
->get_val()->has_single_expr()) return false;
456 void Ref_base::set_code_section(
457 GovernedSimple::code_section_t p_code_section
)
459 for (size_t i
= 0; i
< subrefs
.get_nof_refs(); i
++) {
460 FieldOrArrayRef
*ref
= subrefs
.get_ref(i
);
461 if (ref
->get_type() == FieldOrArrayRef::ARRAY_REF
)
462 ref
->get_val()->set_code_section(p_code_section
);
466 void Ref_base::generate_code_const_ref(expression_struct_t */
*expr*/
)
468 FATAL_ERROR("Ref_base::generate_code_const_ref()");
471 // =================================
473 // =================================
475 Reference::Reference(Identifier
*p_id
)
476 : Ref_base(), parlist(0)
478 subrefs
.add(new FieldOrArrayRef(p_id
));
481 Reference::~Reference()
489 * Common::PortTypeBody::PortTypeBody
491 * Common::TypeMappingTarget::TypeMappingTarget
492 * Common::PatternString::ps_elem_t::chk_ref */
493 Reference
*Reference::clone() const
495 return new Reference(*this);
498 string
Reference::get_dispname()
503 ret_val
+= modid
->get_dispname();
506 ret_val
+= id
->get_dispname();
507 subrefs
.append_stringRepr(ret_val
);
509 subrefs
.append_stringRepr(ret_val
);
510 // cut the leading dot
511 if (!ret_val
.empty() && ret_val
[0] == '.')
512 ret_val
.replace(0, 1, "");
517 Common::Assignment
* Reference::get_refd_assignment(bool check_parlist
)
519 Common::Assignment
*ass
= Ref_base::get_refd_assignment(check_parlist
);
520 // In fact calls Ref_simple::get_refd_assignment
521 if (ass
&& check_parlist
&& !params_checked
) {
522 params_checked
= true;
523 FormalParList
*fplist
= ass
->get_FormalParList();
525 if (fplist
->has_only_default_values()
526 && Common::Assignment::A_TEMPLATE
== ass
->get_asstype()) {
527 Ttcn::ParsedActualParameters params
;
528 Error_Context
cntxt(¶ms
, "In actual parameter list of %s",
529 ass
->get_description().c_str());
530 parlist
= new ActualParList();
531 is_erroneous
= fplist
->fold_named_and_chk(¶ms
, parlist
);
532 parlist
->set_fullname(get_fullname());
533 parlist
->set_my_scope(my_scope
);
535 error("Reference to parameterized definition `%s' without "
536 "actual parameter list", ass
->get_id().get_dispname().c_str());
543 const Identifier
* Reference::get_modid()
545 if (!id
) detect_modid();
549 const Identifier
* Reference::get_id()
551 if (!id
) detect_modid();
555 Type
*Reference::chk_variable_ref()
557 Common::Assignment
*t_ass
= get_refd_assignment();
558 if (!t_ass
) return 0;
559 switch (t_ass
->get_asstype()) {
560 case Common::Assignment::A_PAR_VAL_IN
:
561 t_ass
->use_as_lvalue(*this);
563 case Common::Assignment::A_VAR
:
564 case Common::Assignment::A_PAR_VAL_OUT
:
565 case Common::Assignment::A_PAR_VAL_INOUT
:
568 error("Reference to a variable or value parameter was "
569 "expected instead of %s", t_ass
->get_description().c_str());
572 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
573 Type
*ret_val
= t_ass
->get_Type()->get_field_type(t_subrefs
,
574 Type::EXPECTED_DYNAMIC_VALUE
);
575 if (ret_val
&& t_subrefs
&& t_subrefs
->refers_to_string_element()) {
576 error("Reference to a string element of type `%s' cannot be used in "
577 "this context", ret_val
->get_typename().c_str());
582 Type
*Reference::chk_comptype_ref()
584 Common::Assignment
*ass
= get_refd_assignment();
586 if (ass
->get_asstype() == Common::Assignment::A_TYPE
) {
587 Type
*t
= ass
->get_Type()->get_type_refd_last();
588 switch (t
->get_typetype()) {
592 case Type::T_COMPONENT
:
595 error("Reference `%s' does not refer to a component type",
596 get_dispname().c_str());
599 error("Reference `%s' does not refer to a type",
600 get_dispname().c_str());
606 bool Reference::has_single_expr()
608 if (!Ref_base::has_single_expr()) {
611 if (parlist
!= NULL
) {
612 for (size_t i
= 0; i
< parlist
->get_nof_pars(); i
++) {
613 if (!parlist
->get_par(i
)->has_single_expr()) {
621 void Reference::ref_usage_found()
623 Common::Assignment
*ass
= get_refd_assignment();
624 if (!ass
) FATAL_ERROR("Reference::ref_usage_found()");
625 switch (ass
->get_asstype()) {
626 case Common::Assignment::A_PAR_VAL_OUT
:
627 case Common::Assignment::A_PAR_TEMPL_OUT
:
628 case Common::Assignment::A_PAR_VAL
:
629 case Common::Assignment::A_PAR_VAL_IN
:
630 case Common::Assignment::A_PAR_VAL_INOUT
:
631 case Common::Assignment::A_PAR_TEMPL_IN
:
632 case Common::Assignment::A_PAR_TEMPL_INOUT
:
633 case Common::Assignment::A_PAR_PORT
:
634 case Common::Assignment::A_PAR_TIMER
: {
635 FormalPar
*fpar
= dynamic_cast<FormalPar
*>(ass
);
637 FATAL_ERROR("Reference::ref_usage_found()");
639 fpar
->set_usage_found();
641 case Common::Assignment::A_EXT_CONST
: {
642 Def_ExtConst
* def
= dynamic_cast<Def_ExtConst
*>(ass
);
644 FATAL_ERROR("Reference::ref_usage_found()");
646 def
->set_usage_found();
653 void Reference::generate_code(expression_struct_t
*expr
)
656 Common::Assignment
*ass
= get_refd_assignment();
657 if (!ass
) FATAL_ERROR("Reference::generate_code()");
659 // reference without parameters to a template that has only default formal parameters.
660 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
661 expr
->expr
= mputprintf(expr
->expr
, "%s(",
662 ass
->get_genname_from_scope(my_scope
).c_str());
663 parlist
->generate_code_alias(expr
, ass
->get_FormalParList(),
664 ass
->get_RunsOnType(), false);
665 expr
->expr
= mputc(expr
->expr
, ')');
667 expr
->expr
= mputstr(expr
->expr
,
668 LazyParamData::in_lazy() ?
669 LazyParamData::add_ref_genname(ass
, my_scope
).c_str() :
670 ass
->get_genname_from_scope(my_scope
).c_str());
672 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
675 void Reference::generate_code_const_ref(expression_struct_t
*expr
)
677 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
678 if (!t_subrefs
|| t_subrefs
->get_nof_refs() == 0) {
684 Common::Assignment
*ass
= get_refd_assignment();
685 if (!ass
) FATAL_ERROR("Reference::generate_code_const_ref()");
688 switch (ass
->get_asstype()) {
689 case Common::Assignment::A_MODULEPAR
:
690 case Common::Assignment::A_VAR
:
691 case Common::Assignment::A_FUNCTION_RVAL
:
692 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
693 case Common::Assignment::A_PAR_VAL_IN
:
694 case Common::Assignment::A_PAR_VAL_OUT
:
695 case Common::Assignment::A_PAR_VAL_INOUT
: {
698 case Common::Assignment::A_MODULEPAR_TEMP
:
699 case Common::Assignment::A_TEMPLATE
:
700 case Common::Assignment::A_VAR_TEMPLATE
:
701 case Common::Assignment::A_PAR_TEMPL_IN
:
702 case Common::Assignment::A_PAR_TEMPL_OUT
:
703 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
706 case Common::Assignment::A_CONST
:
707 case Common::Assignment::A_EXT_CONST
:
713 Type
*refd_gov
= ass
->get_Type();
715 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
716 refd_gov
->get_genname_template(get_my_scope()).c_str() );
718 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
719 refd_gov
->get_genname_value(get_my_scope()).c_str());
722 // reference without parameters to a template that has only default formal parameters.
723 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
724 expr
->expr
= mputprintf(expr
->expr
, "%s(",
725 ass
->get_genname_from_scope(my_scope
).c_str());
726 parlist
->generate_code_alias(expr
, ass
->get_FormalParList(),
727 ass
->get_RunsOnType(), false);
728 expr
->expr
= mputc(expr
->expr
, ')');
730 expr
->expr
= mputstr(expr
->expr
,
731 LazyParamData::in_lazy() ?
732 LazyParamData::add_ref_genname(ass
, my_scope
).c_str() :
733 ass
->get_genname_from_scope(my_scope
).c_str());
735 expr
->expr
= mputstr(expr
->expr
, ")");
737 if (t_subrefs
&& t_subrefs
->get_nof_refs() > 0)
738 t_subrefs
->generate_code(expr
, ass
);
741 void Reference::generate_code_portref(expression_struct_t
*expr
,
745 Common::Assignment
*ass
= get_refd_assignment();
746 if (!ass
) FATAL_ERROR("Reference::generate_code_portref()");
747 expr
->expr
= mputstr(expr
->expr
,
748 ass
->get_genname_from_scope(p_scope
).c_str());
749 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
753 void Reference::generate_code_ispresentbound(expression_struct_t
*expr
,
754 bool is_template
, const bool isbound
)
757 Common::Assignment
*ass
= get_refd_assignment();
758 const string
& ass_id
= ass
->get_genname_from_scope(my_scope
);
759 const char *ass_id_str
= ass_id
.c_str();
761 if (subrefs
.get_nof_refs() > 0) {
762 const string
& tmp_generalid
= my_scope
->get_scope_mod_gen()
763 ->get_temporary_id();
764 const char *tmp_generalid_str
= tmp_generalid
.c_str();
766 expression_struct isbound_expr
;
767 Code::init_expr(&isbound_expr
);
768 isbound_expr
.preamble
= mputprintf(isbound_expr
.preamble
,
769 "boolean %s = %s.is_bound();\n", tmp_generalid_str
,
771 ass
->get_Type()->generate_code_ispresentbound(&isbound_expr
, &subrefs
, my_scope
->get_scope_mod_gen(),
772 tmp_generalid
, ass_id
, is_template
, isbound
);
774 expr
->preamble
= mputstr(expr
->preamble
, isbound_expr
.preamble
);
775 expr
->preamble
= mputstr(expr
->preamble
, isbound_expr
.expr
);
776 Code::free_expr(&isbound_expr
);
778 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_generalid_str
);
780 expr
->expr
= mputprintf(expr
->expr
, "%s.%s(%s)", ass_id_str
,
781 isbound
? "is_bound":"is_present",
782 (!isbound
&& is_template
&& omit_in_value_list
) ? "TRUE" : "");
786 void Reference::detect_modid()
788 // do nothing if detection is already performed
790 // the first element of subrefs must be an <id>
791 const Identifier
*first_id
= subrefs
.get_ref(0)->get_id(), *second_id
= 0;
792 if (subrefs
.get_nof_refs() > 1) {
793 FieldOrArrayRef
*second_ref
= subrefs
.get_ref(1);
794 if (second_ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
795 // the reference begins with <id>.<id> (most complicated case)
796 // there are 3 possible situations:
797 // 1. first_id points to a local definition (this has the priority)
798 // modid: 0, id: first_id
799 // 2. first_id points to an imported module (trivial case)
800 // modid: first_id, id: second_id
801 // 3. none of the above (first_id might be an imported symbol)
802 // modid: 0, id: first_id
803 // Note: Rule 1 has the priority because it can be overridden using
804 // the notation <id>.objid { ... }.<id> (modid and id are set in the
805 // constructor), but there is no work-around in the reverse way.
806 if (!my_scope
->has_ass_withId(*first_id
)
807 && my_scope
->is_valid_moduleid(*first_id
)) {
808 // rule 1 is not fulfilled, but rule 2 is fulfilled
809 second_id
= second_ref
->get_id();
811 } // else: the reference begins with <id>[<arrayref>] -> there is no modid
812 } // else: the reference consists of a single <id> -> there is no modid
814 modid
= first_id
->clone();
815 id
= second_id
->clone();
816 subrefs
.remove_refs(2);
819 id
= first_id
->clone();
820 subrefs
.remove_refs(1);
824 // =================================
826 // =================================
828 Ref_pard::Ref_pard(const Ref_pard
& p
)
829 : Ref_base(p
), parlist(p
.parlist
), expr_cache(0)
831 params
= p
.params
? p
.params
->clone() : 0;
834 Ref_pard::Ref_pard(Identifier
*p_modid
, Identifier
*p_id
,
835 ParsedActualParameters
*p_params
)
836 : Ref_base(p_modid
, p_id
), parlist(), params(p_params
), expr_cache(0)
839 FATAL_ERROR("Ttcn::Ref_pard::Ref_pard(): NULL parameter");
842 Ref_pard::~Ref_pard()
848 Ref_pard
*Ref_pard::clone() const
850 return new Ref_pard(*this);
853 void Ref_pard::set_fullname(const string
& p_fullname
)
855 Ref_base::set_fullname(p_fullname
);
856 parlist
.set_fullname(p_fullname
);
857 if (params
) params
->set_fullname(p_fullname
);
860 void Ref_pard::set_my_scope(Scope
*p_scope
)
862 Ref_base::set_my_scope(p_scope
);
863 parlist
.set_my_scope(p_scope
);
864 if (params
) params
->set_my_scope(p_scope
);
867 string
Ref_pard::get_dispname()
869 if (is_erroneous
) return string("erroneous");
872 ret_val
+= modid
->get_dispname();
875 ret_val
+= id
->get_dispname();
877 if (params_checked
) {
878 // used after semantic analysis
879 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++) {
880 if (i
> 0) ret_val
+= ", ";
881 parlist
.get_par(i
)->append_stringRepr(ret_val
);
884 // used before semantic analysis
885 for (size_t i
= 0; i
< params
->get_nof_tis(); i
++) {
886 if (i
> 0) ret_val
+= ", ";
887 params
->get_ti_byIndex(i
)->append_stringRepr(ret_val
);
891 subrefs
.append_stringRepr(ret_val
);
895 Common::Assignment
* Ref_pard::get_refd_assignment(bool check_parlist
)
897 Common::Assignment
*ass
= Ref_base::get_refd_assignment(check_parlist
);
898 if (ass
&& check_parlist
&& !params_checked
) {
899 params_checked
= true;
900 FormalParList
*fplist
= ass
->get_FormalParList();
902 Error_Context
cntxt(params
, "In actual parameter list of %s",
903 ass
->get_description().c_str());
904 is_erroneous
= fplist
->fold_named_and_chk(params
, &parlist
);
905 parlist
.set_fullname(get_fullname());
906 parlist
.set_my_scope(my_scope
);
907 // the parsed parameter list is no longer needed
911 params
->error("The referenced %s cannot have actual parameters",
912 ass
->get_description().c_str());
918 const Identifier
* Ref_pard::get_modid()
923 const Identifier
* Ref_pard::get_id()
928 ActualParList
*Ref_pard::get_parlist()
930 if (!params_checked
) FATAL_ERROR("Ref_pard::get_parlist()");
934 bool Ref_pard::chk_activate_argument()
936 Common::Assignment
*t_ass
= get_refd_assignment();
937 if (!t_ass
) return false;
938 if (t_ass
->get_asstype() != Common::Assignment::A_ALTSTEP
) {
939 error("Reference to an altstep was expected in the argument instead of "
940 "%s", t_ass
->get_description().c_str());
943 my_scope
->chk_runs_on_clause(t_ass
, *this, "activate");
944 // the altstep reference cannot have sub-references
945 if (get_subrefs()) FATAL_ERROR("Ref_pard::chk_activate_argument()");
946 FormalParList
*fp_list
= t_ass
->get_FormalParList();
947 // the altstep must have formal parameter list
948 if (!fp_list
) FATAL_ERROR("Ref_pard::chk_activate_argument()");
949 return fp_list
->chk_activate_argument(&parlist
,
950 t_ass
->get_description().c_str());
953 bool Ref_pard::has_single_expr()
955 if (!Ref_base::has_single_expr()) return false;
956 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++)
957 if (!parlist
.get_par(i
)->has_single_expr()) return false;
958 // if any formal parameter has lazy evaluation
959 Common::Assignment
*ass
= get_refd_assignment();
961 const FormalParList
*fplist
= ass
->get_FormalParList();
963 size_t num_formal
= fplist
->get_nof_fps();
964 for (size_t i
=0; i
<num_formal
; ++i
) {
965 const FormalPar
*fp
= fplist
->get_fp_byIndex(i
);
966 if (fp
->get_lazy_eval()) return false;
973 void Ref_pard::set_code_section(
974 GovernedSimple::code_section_t p_code_section
)
976 Ref_base::set_code_section(p_code_section
);
977 for (size_t i
= 0; i
< parlist
.get_nof_pars(); i
++)
978 parlist
.get_par(i
)->set_code_section(p_code_section
);
981 void Ref_pard::generate_code(expression_struct_t
*expr
)
983 Common::Assignment
*ass
= get_refd_assignment();
984 // C++ function reference with actual parameter list
985 expr
->expr
= mputprintf(expr
->expr
, "%s(",
986 ass
->get_genname_from_scope(my_scope
).c_str());
987 parlist
.generate_code_alias(expr
, ass
->get_FormalParList(),
988 ass
->get_RunsOnType(),false);
989 expr
->expr
= mputc(expr
->expr
, ')');
991 if (subrefs
.get_nof_refs() > 0) subrefs
.generate_code(expr
, ass
);
994 void Ref_pard::generate_code_cached(expression_struct_t
*expr
)
997 expr
->expr
= mputstr(expr
->expr
, expr_cache
);
1000 generate_code(expr
);
1001 expr_cache
= mputstr(expr_cache
, expr
->expr
);
1005 void Ref_pard::generate_code_const_ref(expression_struct_t
*expr
)
1007 FieldOrArrayRefs
*t_subrefs
= get_subrefs();
1008 if (!t_subrefs
|| t_subrefs
->get_nof_refs() == 0) {
1009 generate_code(expr
);
1013 Common::Assignment
*ass
= get_refd_assignment();
1014 if (!ass
) FATAL_ERROR("Ref_pard::generate_code_const_ref()");
1017 switch (ass
->get_asstype()) {
1018 case Common::Assignment::A_TEMPLATE
:
1019 if (NULL
== ass
->get_FormalParList()) {
1020 // not a parameterized template
1024 // else fall through
1025 case Common::Assignment::A_CONST
:
1026 case Common::Assignment::A_EXT_CONST
:
1027 case Common::Assignment::A_ALTSTEP
:
1028 case Common::Assignment::A_TESTCASE
:
1029 case Common::Assignment::A_FUNCTION
:
1030 case Common::Assignment::A_EXT_FUNCTION
:
1031 case Common::Assignment::A_FUNCTION_RVAL
:
1032 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
1033 case Common::Assignment::A_FUNCTION_RTEMP
:
1034 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
1035 generate_code(expr
);
1037 case Common::Assignment::A_MODULEPAR
:
1038 case Common::Assignment::A_VAR
:
1039 case Common::Assignment::A_PAR_VAL_IN
:
1040 case Common::Assignment::A_PAR_VAL_OUT
:
1041 case Common::Assignment::A_PAR_VAL_INOUT
: {
1042 is_template
= false;
1044 case Common::Assignment::A_MODULEPAR_TEMP
:
1045 case Common::Assignment::A_VAR_TEMPLATE
:
1046 case Common::Assignment::A_PAR_TEMPL_IN
:
1047 case Common::Assignment::A_PAR_TEMPL_OUT
:
1048 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
1052 is_template
= false;
1056 Type
*refd_gov
= ass
->get_Type();
1058 generate_code(expr
);
1063 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s&>(",
1064 refd_gov
->get_genname_template(get_my_scope()).c_str() );
1066 expr
->expr
= mputprintf(expr
->expr
, "const_cast< const %s%s&>(",
1067 refd_gov
->get_genname_value(get_my_scope()).c_str(),
1068 is_template
? "_template":"");
1071 expr
->expr
= mputprintf(expr
->expr
, "%s(",
1072 ass
->get_genname_from_scope(my_scope
).c_str());
1073 parlist
.generate_code_alias(expr
, ass
->get_FormalParList(),
1074 ass
->get_RunsOnType(), false);
1075 expr
->expr
= mputstr(expr
->expr
, "))");
1077 t_subrefs
->generate_code(expr
, ass
);
1080 // =================================
1081 // ===== NameBridgingScope
1082 // =================================
1083 string
NameBridgingScope::get_scopeMacro_name() const
1085 if (scopeMacro_name
.empty()) FATAL_ERROR("NameBridgingScope::get_scopeMacro_name()");
1086 return scopeMacro_name
;
1089 NameBridgingScope
*NameBridgingScope::clone() const
1091 FATAL_ERROR("NameBridgingScope::clone");
1094 Common::Assignment
* NameBridgingScope::get_ass_bySRef(Ref_simple
*p_ref
)
1096 return get_parent_scope()->get_ass_bySRef(p_ref
);
1099 // =================================
1100 // ===== RunsOnScope
1101 // =================================
1103 RunsOnScope::RunsOnScope(Type
*p_comptype
)
1104 : Scope(), component_type(p_comptype
)
1106 if (!p_comptype
|| p_comptype
->get_typetype() != Type::T_COMPONENT
)
1107 FATAL_ERROR("RunsOnScope::RunsOnScope()");
1108 component_type
->set_ownertype(Type::OT_RUNSON_SCOPE
, this);
1109 component_defs
= p_comptype
->get_CompBody();
1110 set_scope_name("runs on `" + p_comptype
->get_fullname() + "'");
1113 RunsOnScope
*RunsOnScope::clone() const
1115 FATAL_ERROR("RunsOnScope::clone()");
1118 void RunsOnScope::chk_uniq()
1120 // do not perform this check if the component type is defined in the same
1121 // module as the 'runs on' clause
1122 if (parent_scope
->get_scope_mod() == component_defs
->get_scope_mod())
1124 size_t nof_defs
= component_defs
->get_nof_asss();
1125 for (size_t i
= 0; i
< nof_defs
; i
++) {
1126 Common::Assignment
*comp_def
= component_defs
->get_ass_byIndex(i
);
1127 const Identifier
& id
= comp_def
->get_id();
1128 if (parent_scope
->has_ass_withId(id
)) {
1129 comp_def
->warning("Imported component element definition `%s' hides a "
1130 "definition at module scope", comp_def
->get_fullname().c_str());
1131 Reference
ref(0, id
.clone());
1132 Common::Assignment
*hidden_ass
= parent_scope
->get_ass_bySRef(&ref
);
1133 hidden_ass
->warning("Hidden definition `%s' is here",
1134 hidden_ass
->get_fullname().c_str());
1140 RunsOnScope
*RunsOnScope::get_scope_runs_on()
1145 Common::Assignment
*RunsOnScope::get_ass_bySRef(Ref_simple
*p_ref
)
1147 if (!p_ref
) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1148 if (p_ref
->get_modid()) return parent_scope
->get_ass_bySRef(p_ref
);
1150 const Identifier
& id
= *p_ref
->get_id();
1151 if (component_defs
->has_local_ass_withId(id
)) {
1152 Common::Assignment
* ass
= component_defs
->get_local_ass_byId(id
);
1153 if (!ass
) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1155 if (component_defs
->is_own_assignment(ass
)) return ass
;
1156 else if (ass
->get_visibility() == PUBLIC
) {
1160 p_ref
->error("The member definition `%s' in component type `%s'"
1161 " is not visible in this scope", id
.get_dispname().c_str(),
1162 component_defs
->get_id()->get_dispname().c_str());
1164 } else return parent_scope
->get_ass_bySRef(p_ref
);
1168 bool RunsOnScope::has_ass_withId(const Identifier
& p_id
)
1170 return component_defs
->has_ass_withId(p_id
)
1171 || parent_scope
->has_ass_withId(p_id
);
1174 // =================================
1176 // =================================
1178 FriendMod::FriendMod(Identifier
*p_modid
)
1179 : Node(), modid(p_modid
), w_attrib_path(0), parentgroup(0), checked(false)
1181 if (!p_modid
) FATAL_ERROR("NULL parameter: Ttcn::FriendMod::FriendMod()");
1182 set_fullname("<friends>."+modid
->get_dispname());
1185 FriendMod::~FriendMod()
1189 delete w_attrib_path
;
1192 FriendMod
*FriendMod::clone() const
1194 FATAL_ERROR("Ttcn::FriendMod::clone()");
1197 void FriendMod::set_fullname(const string
& p_fullname
)
1199 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
1202 void FriendMod::chk()
1204 if (checked
) return;
1206 Error_Context
cntxt(this, "In friend module declaration");
1208 if (w_attrib_path
) {
1209 w_attrib_path
->chk_global_attrib();
1210 w_attrib_path
->chk_no_qualif();
1216 void FriendMod::set_with_attr(MultiWithAttrib
* p_attrib
)
1218 if (w_attrib_path
) FATAL_ERROR("FriendMod::set_with_attr()");
1219 w_attrib_path
= new WithAttribPath();
1220 if (p_attrib
&& p_attrib
->get_nof_elements() > 0) {
1221 w_attrib_path
->set_with_attr(p_attrib
);
1225 WithAttribPath
* FriendMod::get_attrib_path()
1227 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1228 return w_attrib_path
;
1231 void FriendMod::set_parent_path(WithAttribPath
* p_path
)
1233 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1234 w_attrib_path
->set_parent(p_path
);
1237 void FriendMod::set_parent_group(Group
* p_group
)
1239 if(parentgroup
) FATAL_ERROR("FriendMod::set_parent_group");
1240 parentgroup
= p_group
;
1243 // =================================
1245 // =================================
1247 ImpMod::ImpMod(Identifier
*p_modid
)
1248 : Node(), mod(0), my_mod(0), imptype(I_UNDEF
), modid(p_modid
),
1249 language_spec(0), is_recursive(false),
1250 w_attrib_path(0), parentgroup(0), visibility(PRIVATE
)
1252 if (!p_modid
) FATAL_ERROR("NULL parameter: Ttcn::ImpMod::ImpMod()");
1253 set_fullname("<imports>." + modid
->get_dispname());
1259 delete language_spec
;
1261 delete w_attrib_path
;
1264 ImpMod
*ImpMod::clone() const
1266 FATAL_ERROR("No clone for you!");
1269 void ImpMod::set_fullname(const string
& p_fullname
)
1271 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
1276 if (w_attrib_path
) {
1277 w_attrib_path
->chk_global_attrib();
1278 w_attrib_path
->chk_no_qualif();
1282 void ImpMod::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
1284 Error_Context
cntxt(this, "In import definition");
1286 if (!modules
->has_mod_withId(*modid
)) {
1287 error("There is no module with identifier `%s'",
1288 modid
->get_dispname().c_str());
1292 Common::Module
*m
= modules
->get_mod_byId(*modid
);
1298 error("A module cannot import from itself");
1306 if (refch
.exists(my_mod
->get_fullname())) {
1307 if(my_mod
->get_moduletype()!=Common::Module::MOD_ASN
){ // Do not warning for circular import in ASN.1 module. It is legal
1308 my_mod
->warning("Circular import chain is not recommended: %s",
1309 refch
.get_dispstr(my_mod
->get_fullname()).c_str());
1314 refch
.add(my_mod
->get_fullname());
1316 if (ImpMod::I_IMPORTIMPORT
== imptype
){
1317 Ttcn::Module
* ttcnmodule
=static_cast<Ttcn::Module
*>(m
);
1318 const Imports
& imp
= ttcnmodule
->get_imports();
1320 for (size_t t
= 0; t
< imp
.impmods_v
.size(); t
++) {
1321 const ImpMod
*im
= imp
.impmods_v
[t
];
1322 const Identifier
& im_id
= im
->get_modid();
1323 Common::Module
*cm
= modules
->get_mod_byId(im_id
); // never NULL
1326 if (PRIVATE
!= im
->get_visibility()) {
1327 if (refch
.exists(m
->get_fullname())) {
1328 if(m
->get_moduletype()!=Common::Module::MOD_ASN
){ // Do not warning for circular import in ASN.1 module. It is legal
1329 m
->warning("Circular import chain is not recommended: %s",
1330 refch
.get_dispstr(m
->get_fullname()).c_str());
1335 refch
.add(m
->get_fullname());
1336 cm
->chk_imp(refch
, moduleStack
);
1342 //refch.mark_state();
1343 m
->chk_imp(refch
, moduleStack
);
1344 //refch.prev_state();
1349 size_t state
=moduleStack
.size();
1350 moduleStack
.replace(state
, moduleStack
.size() - state
);
1353 bool ImpMod::has_imported_def(const Identifier
& p_source_modid
,
1354 const Identifier
& p_id
, const Location
*loc
) const
1356 if (!mod
) return false;
1362 Common::Assignment
* return_assignment
= mod
->importAssignment(p_source_modid
, p_id
);
1363 if (return_assignment
!= NULL
) {
1370 case I_IMPORTIMPORT
:
1372 Ttcn::Module
*tm
= static_cast<Ttcn::Module
*>(mod
); // B
1374 const Imports
& imps
= tm
->get_imports();
1376 vector
<ImpMod
> tempusedImpMods
;
1377 for (size_t i
= 0, num
= imps
.impmods_v
.size(); i
< num
; ++i
) {
1378 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
1379 Common::Assignment
* return_assignment
= imps
.impmods_v
[i
]->
1380 get_imported_def(p_source_modid
, p_id
, loc
, referencechain
, tempusedImpMods
); // C
1381 referencechain
->reset();
1382 delete referencechain
;
1384 if (return_assignment
!= NULL
) {
1390 //satisfy destructor
1391 tempusedImpMods
.clear();
1396 FATAL_ERROR("ImpMod::get_imported_def");
1402 Common::Assignment
*ImpMod::get_imported_def(
1403 const Identifier
& p_source_modid
, const Identifier
& p_id
,
1404 const Location
*loc
, ReferenceChain
* refch
,
1405 vector
<ImpMod
>& usedImpMods
) const
1410 Common::Assignment
* result
= NULL
;
1415 result
= mod
->importAssignment(p_source_modid
, p_id
);
1416 if (result
!= NULL
) {
1417 usedImpMods
.add(const_cast<Ttcn::ImpMod
*>(this));
1421 case I_IMPORTIMPORT
:
1423 Ttcn::Module
*tm
= static_cast<Ttcn::Module
*>(mod
);
1425 const Imports
& imps
= tm
->get_imports();
1426 Common::Assignment
* t_ass
= NULL
;
1428 for (size_t i
= 0, num
= imps
.impmods_v
.size(); i
< num
; ++i
) {
1429 vector
<ImpMod
> tempusedImpMods
;
1431 refch
->mark_state();
1432 if (imps
.impmods_v
[i
]->get_visibility() == PUBLIC
) {
1433 t_ass
= imps
.impmods_v
[i
]->get_imported_def(p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1435 else if (imps
.impmods_v
[i
]->get_visibility() == FRIEND
) {
1436 t_ass
= imps
.impmods_v
[i
]->get_imported_def(p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1438 tempusedImpMods
.add(imps
.impmods_v
[i
]);
1441 refch
->prev_state();
1443 if (t_ass
!= NULL
) {
1444 bool visible
= true;
1445 for (size_t j
= 0; j
< tempusedImpMods
.size(); j
++) {
1446 ImpMod
* impmod_l
= tempusedImpMods
[j
];
1447 //check whether the module is TTCN
1448 if (impmod_l
->get_mod()->get_moduletype() == Common::Module::MOD_TTCN
) {
1449 // cast to ttcn module
1450 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(impmod_l
->get_mod());
1451 if (!ttcn_m
->is_visible(mod
->get_modid(), impmod_l
->get_visibility())) {
1457 for (size_t t
= 0; i
< tempusedImpMods
.size(); i
++) {
1458 usedImpMods
.add(tempusedImpMods
[t
]);
1463 } else if(result
!= t_ass
) {
1468 "It is not possible to resolve the reference unambiguously"
1469 ", as it can be resolved to `%s' and to `%s'",
1470 result
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
1476 tempusedImpMods
.clear();
1479 if (result
!= NULL
) {
1480 usedImpMods
.add(const_cast<Ttcn::ImpMod
*>(this));
1486 FATAL_ERROR("ImpMod::get_imported_def");
1491 void ImpMod::set_language_spec(const char *p_language_spec
)
1493 if (language_spec
) FATAL_ERROR("ImpMod::set_language_spec()");
1494 if (p_language_spec
) language_spec
= new string(p_language_spec
);
1497 void ImpMod::generate_code(output_struct
*target
)
1499 const char *module_name
= modid
->get_name().c_str();
1501 target
->header
.includes
= mputprintf(target
->header
.includes
,
1502 "#include \"%s.hh\"\n",
1503 duplicate_underscores
? module_name
: modid
->get_ttcnname().c_str());
1505 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
1506 "%s%s.pre_init_module();\n", module_name
,
1509 if (mod
->get_moduletype() == Common::Module::MOD_TTCN
) {
1510 target
->functions
.post_init
= mputprintf(target
->functions
.post_init
,
1511 "%s%s.post_init_module();\n", module_name
,
1517 void ImpMod::dump(unsigned level
) const
1519 DEBUG(level
, "Import from module %s", modid
->get_dispname().c_str());
1520 if (w_attrib_path
) {
1521 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
1523 DEBUG(level
+ 1, "Attributes:");
1524 attrib
->dump(level
+ 2);
1529 void ImpMod::set_with_attr(MultiWithAttrib
* p_attrib
)
1531 if (w_attrib_path
) FATAL_ERROR("ImpMod::set_with_attr()");
1532 w_attrib_path
= new WithAttribPath();
1533 if (p_attrib
&& p_attrib
->get_nof_elements() > 0) {
1534 w_attrib_path
->set_with_attr(p_attrib
);
1538 WithAttribPath
* ImpMod::get_attrib_path()
1540 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1541 return w_attrib_path
;
1544 void ImpMod::set_parent_path(WithAttribPath
* p_path
)
1546 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1547 w_attrib_path
->set_parent(p_path
);
1550 void ImpMod::set_parent_group(Group
* p_group
)
1552 if(parentgroup
) FATAL_ERROR("ImpMod::set_parent_group");
1553 parentgroup
= p_group
;
1556 // =================================
1558 // =================================
1562 for (size_t i
= 0; i
< impmods_v
.size(); i
++)
1563 delete impmods_v
[i
];
1567 Imports
*Imports::clone() const
1569 FATAL_ERROR("Ttcn::Imports::clone()");
1572 void Imports::add_impmod(ImpMod
*p_impmod
)
1574 if (!p_impmod
) FATAL_ERROR("Ttcn::Imports::add_impmod()");
1575 impmods_v
.add(p_impmod
);
1576 p_impmod
->set_my_mod(my_mod
);
1579 void Imports::set_my_mod(Module
*p_mod
)
1582 for(size_t i
= 0; i
< impmods_v
.size(); i
++)
1583 impmods_v
[i
]->set_my_mod(my_mod
);
1586 bool Imports::has_impmod_withId(const Identifier
& p_id
) const
1588 for (size_t i
= 0, size
= impmods_v
.size(); i
< size
; ++i
) {
1589 const ImpMod
* im
= impmods_v
[i
];
1590 const Identifier
& im_id
= im
->get_modid();
1591 const string
& im_name
= im_id
.get_name();
1592 if (p_id
.get_name() == im_name
) {
1593 // The identifier represents a module imported in the current module
1600 void Imports::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
1602 if (impmods_v
.size() <= 0) return;
1604 if (!my_mod
) FATAL_ERROR("Ttcn::Imports::chk_imp()");
1609 for(size_t n
= 0; n
< impmods_v
.size(); n
++)
1611 impmods_v
[n
]->chk();
1614 //TODO this whole thing should be moved into impmod::chk
1615 Identifier
address_id(Identifier::ID_TTCN
, string("address"));
1616 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1617 ImpMod
*im
= impmods_v
[n
];
1618 im
->chk_imp(refch
, moduleStack
);
1620 const Identifier
& im_id
= im
->get_modid();
1621 Common::Module
*m
= modules
->get_mod_byId(im_id
);
1624 if (m
->get_gen_code()) my_mod
->set_gen_code();
1625 } // next assignment
1628 bool Imports::has_imported_def(const Identifier
& p_id
, const Location
*loc
) const
1630 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1631 ImpMod
*im
= impmods_v
[n
];
1632 bool return_bool
= im
->has_imported_def(my_mod
->get_modid(), p_id
, loc
);
1633 if (return_bool
) return true;
1638 Common::Assignment
*Imports::get_imported_def(
1639 const Identifier
& p_source_modid
, const Identifier
& p_id
,
1640 const Location
*loc
, ReferenceChain
* refch
)
1642 vector
<ImpMod
> tempusedImpMods
;
1643 Common::Assignment
* result
= NULL
;
1644 for (size_t n
= 0; n
< impmods_v
.size(); n
++) {
1645 ImpMod
*im
= impmods_v
[n
];
1646 refch
->mark_state();
1647 Common::Assignment
* ass
= im
->get_imported_def(
1648 p_source_modid
, p_id
, loc
, refch
, tempusedImpMods
);
1649 tempusedImpMods
.clear();
1650 refch
->prev_state();
1655 } else if(result
!= ass
&& loc
) {
1660 "It is not possible to resolve the reference unambiguously"
1661 ", as it can be resolved to `%s' and to `%s'",
1662 result
->get_fullname().c_str(), ass
->get_fullname().c_str());
1670 void Imports::get_imported_mods(Module::module_set_t
& p_imported_mods
) const
1672 for (size_t i
= 0; i
< impmods_v
.size(); i
++) {
1673 ImpMod
*im
= impmods_v
[i
];
1674 Common::Module
*m
= im
->get_mod();
1676 if (!p_imported_mods
.has_key(m
)) {
1677 p_imported_mods
.add(m
, 0);
1678 m
->get_visible_mods(p_imported_mods
);
1683 void Imports::generate_code(output_struct
*target
)
1685 target
->header
.includes
= mputstr(target
->header
.includes
,
1686 "#include <TTCN3.hh>\n");
1687 for (size_t i
= 0; i
< impmods_v
.size(); i
++) {
1688 ImpMod
*im
= impmods_v
[i
];
1689 Common::Module
*m
= im
->get_mod();
1690 // inclusion of m's header file can be eliminated if we find another
1691 // imported module that imports m
1692 bool covered
= false;
1693 for (size_t j
= 0; j
< impmods_v
.size(); j
++) {
1694 // skip over the same import definition
1695 if (j
== i
) continue;
1696 ImpMod
*im2
= impmods_v
[j
];
1697 Common::Module
*m2
= im2
->get_mod();
1698 // a module that is equivalent to the current module due to
1699 // circular imports cannot be used to cover anything
1700 if (m2
->is_visible(my_mod
)) continue;
1701 if (m2
->is_visible(m
) && !m
->is_visible(m2
)) {
1702 // m2 covers m (i.e. m is visible from m2)
1703 // and they are not in the same import loop
1708 // do not generate the #include if a covering module is found
1709 if (!covered
) im
->generate_code(target
);
1713 void Imports::generate_code(CodeGenHelper
& cgh
) {
1714 generate_code(cgh
.get_current_outputstruct());
1717 void Imports::dump(unsigned level
) const
1719 DEBUG(level
, "Imports (%lu pcs.)", (unsigned long) impmods_v
.size());
1720 for (size_t i
= 0; i
< impmods_v
.size(); i
++)
1721 impmods_v
[i
]->dump(level
+ 1);
1724 // =================================
1725 // ===== Definitions
1726 // =================================
1728 Definitions::~Definitions()
1730 for(size_t i
= 0; i
< ass_v
.size(); i
++) delete ass_v
[i
];
1735 Definitions
*Definitions::clone() const
1737 FATAL_ERROR("Definitions::clone");
1740 void Definitions::add_ass(Definition
*p_ass
)
1742 // it is too late to add a new one after it has been checked.
1743 if (checked
|| !p_ass
) FATAL_ERROR("Ttcn::OtherDefinitions::add_ass()");
1745 p_ass
->set_my_scope(this);
1748 void Definitions::set_fullname(const string
& p_fullname
)
1750 Common::Assignments::set_fullname(p_fullname
);
1751 for(size_t i
= 0; i
< ass_v
.size(); i
++) {
1752 Definition
*ass
= ass_v
[i
];
1753 ass
->set_fullname(p_fullname
+ "." + ass
->get_id().get_dispname());
1757 bool Definitions::has_local_ass_withId(const Identifier
& p_id
)
1759 if (!checked
) chk_uniq();
1760 return ass_m
.has_key(p_id
.get_name());
1763 Common::Assignment
* Definitions::get_local_ass_byId(const Identifier
& p_id
)
1765 if (!checked
) chk_uniq();
1766 return ass_m
[p_id
.get_name()];
1769 size_t Definitions::get_nof_asss()
1771 if (!checked
) chk_uniq();
1772 return ass_m
.size();
1775 size_t Definitions::get_nof_raw_asss()
1777 return ass_v
.size();
1780 Common::Assignment
* Definitions::get_ass_byIndex(size_t p_i
)
1782 if (!checked
) chk_uniq();
1783 return ass_m
.get_nth_elem(p_i
);
1786 Ttcn::Definition
* Definitions::get_raw_ass_byIndex(size_t p_i
) {
1790 void Definitions::chk_uniq()
1792 if (checked
) return;
1794 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1795 Definition
*ass
= ass_v
[i
];
1796 const Identifier
& id
= ass
->get_id();
1797 const string
& name
= id
.get_name();
1798 if (ass_m
.has_key(name
)) {
1799 const char *dispname_str
= id
.get_dispname().c_str();
1800 ass
->error("Duplicate definition with name `%s'", dispname_str
);
1801 ass_m
[name
]->note("Previous definition of `%s' is here", dispname_str
);
1803 ass_m
.add(name
, ass
);
1804 if (parent_scope
->is_valid_moduleid(id
)) {
1805 ass
->warning("Definition with name `%s' hides a module identifier",
1806 id
.get_dispname().c_str());
1813 void Definitions::chk()
1815 for (size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->chk();
1818 void Definitions::chk_for()
1820 if (checked
) return;
1823 // all checks are done in one iteration because
1824 // forward referencing is not allowed between the definitions
1825 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1826 Definition
*def
= ass_v
[i
];
1827 const Identifier
& id
= def
->get_id();
1828 const string
& name
= id
.get_name();
1829 if (ass_m
.has_key(name
)) {
1830 const char *dispname_str
= id
.get_dispname().c_str();
1831 def
->error("Duplicate definition with name `%s'", dispname_str
);
1832 ass_m
[name
]->note("Previous definition of `%s' is here", dispname_str
);
1834 ass_m
.add(name
, def
);
1836 if (parent_scope
->has_ass_withId(id
)) {
1837 const char *dispname_str
= id
.get_dispname().c_str();
1838 def
->error("Definition with identifier `%s' is not unique in the "
1839 "scope hierarchy", dispname_str
);
1840 Reference
ref(0, id
.clone());
1841 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
1842 if (!ass
) FATAL_ERROR("OtherDefinitions::chk_for()");
1843 ass
->note("Previous definition with identifier `%s' in higher "
1844 "scope unit is here", dispname_str
);
1845 } else if (parent_scope
->is_valid_moduleid(id
)) {
1846 def
->warning("Definition with name `%s' hides a module identifier",
1847 id
.get_dispname().c_str());
1855 void Definitions::set_genname(const string
& prefix
)
1857 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1858 Definition
*def
= ass_v
[i
];
1859 def
->set_genname(prefix
+ def
->get_id().get_name());
1863 void Definitions::generate_code(output_struct
* target
)
1865 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->generate_code(target
);
1868 void Definitions::generate_code(CodeGenHelper
& cgh
) {
1870 for(size_t i
= 0; i
< ass_v
.size(); i
++) {
1871 ass_v
[i
]->generate_code(cgh
);
1872 CodeGenHelper::update_intervals(cgh
.get_current_outputstruct());
1876 char* Definitions::generate_code_str(char *str
)
1878 for(size_t i
=0; i
<ass_v
.size(); i
++) {
1879 str
= ass_v
[i
]->update_location_object(str
);
1880 str
=ass_v
[i
]->generate_code_str(str
);
1885 void Definitions::ilt_generate_code(ILT
*ilt
)
1887 for(size_t i
=0; i
<ass_v
.size(); i
++)
1888 ass_v
[i
]->ilt_generate_code(ilt
);
1892 void Definitions::dump(unsigned level
) const
1894 DEBUG(level
, "Definitions: (%lu pcs.)", (unsigned long) ass_v
.size());
1895 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->dump(level
+ 1);
1898 // =================================
1900 // =================================
1902 Group::Group(Identifier
*p_id
)
1903 : Node(), Location(), parent_group(0), w_attrib_path(0), id(p_id
),
1906 if (!p_id
) FATAL_ERROR("Group::Group()");
1911 delete w_attrib_path
;
1914 for (size_t i
= 0; i
< group_v
.size(); i
++) delete group_v
[i
];
1918 friendmods_v
.clear();
1922 Group
* Group::clone() const
1924 FATAL_ERROR("Ttcn::Group::clone()");
1927 void Group::set_fullname(const string
& p_fullname
)
1929 Node::set_fullname(p_fullname
);
1930 for(size_t i
= 0; i
< group_v
.size() ; i
++)
1932 group_v
[i
]->set_fullname(p_fullname
+ ".<group " + Int2string(i
) + ">");
1934 if (w_attrib_path
) w_attrib_path
->set_fullname( p_fullname
1938 void Group::add_ass(Definition
* p_ass
)
1941 p_ass
->set_parent_group(this);
1944 void Group::add_group(Group
* p_group
)
1946 group_v
.add(p_group
);
1949 void Group::set_parent_group(Group
* p_parent_group
)
1951 if (parent_group
) FATAL_ERROR("Group::set_parent_group()");
1952 parent_group
= p_parent_group
;
1955 void Group::set_with_attr(MultiWithAttrib
* p_attrib
)
1957 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1958 w_attrib_path
->set_with_attr(p_attrib
);
1961 WithAttribPath
* Group::get_attrib_path()
1963 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1964 return w_attrib_path
;
1967 void Group::set_parent_path(WithAttribPath
* p_path
)
1969 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
1970 w_attrib_path
->set_parent(p_path
);
1973 void Group::chk_uniq()
1975 if (checked
) return;
1979 for (size_t i
= 0; i
< ass_v
.size(); i
++) {
1980 Definition
*ass
= ass_v
[i
];
1981 const string
& ass_name
= ass
->get_id().get_name();
1982 if (!ass_m
.has_key(ass_name
)) ass_m
.add(ass_name
, ass
);
1985 for(size_t i
= 0; i
< group_v
.size(); i
++) {
1986 Group
*group
= group_v
[i
];
1987 const Identifier
& group_id
= group
->get_id();
1988 const string
& group_name
= group_id
.get_name();
1989 if (ass_m
.has_key(group_name
)) {
1990 group
->error("Group name `%s' clashes with a definition",
1991 group_id
.get_dispname().c_str());
1992 ass_m
[group_name
]->note("Definition of `%s' is here",
1993 group_id
.get_dispname().c_str());
1995 if (group_m
.has_key(group_name
)) {
1996 group
->error("Duplicate group with name `%s'",
1997 group_id
.get_dispname().c_str());
1998 group_m
[group_name
]->note("Group `%s' is already defined here",
1999 group_id
.get_dispname().c_str());
2000 } else group_m
.add(group_name
, group
);
2007 Error_Context
cntxt(this, "In group `%s'", id
->get_dispname().c_str());
2011 if (w_attrib_path
) {
2012 w_attrib_path
->chk_global_attrib();
2013 w_attrib_path
->chk_no_qualif();
2016 for(size_t i
= 0; i
< group_v
.size(); i
++) group_v
[i
]->chk();
2019 void Group::add_impmod(ImpMod
*p_impmod
)
2021 impmods_v
.add(p_impmod
);
2022 p_impmod
->set_parent_group(this);
2025 void Group::add_friendmod(FriendMod
*p_friendmod
)
2027 friendmods_v
.add(p_friendmod
);
2028 p_friendmod
->set_parent_group(this);
2031 void Group::dump(unsigned level
) const
2033 DEBUG(level
, "Group: %s", id
->get_dispname().c_str());
2034 DEBUG(level
+ 1, "Nested groups: (%lu pcs.)",
2035 (unsigned long) group_v
.size());
2036 for(size_t i
= 0; i
< group_v
.size(); i
++) group_v
[i
]->dump(level
+ 2);
2037 DEBUG(level
+ 1, "Nested definitions: (%lu pcs.)",
2038 (unsigned long) ass_v
.size());
2039 for(size_t i
= 0; i
< ass_v
.size(); i
++) ass_v
[i
]->dump(level
+ 2);
2040 DEBUG(level
+ 1, "Nested imports: (%lu pcs.)",
2041 (unsigned long) impmods_v
.size());
2042 for(size_t i
= 0; i
< impmods_v
.size(); i
++) impmods_v
[i
]->dump(level
+ 2);
2043 if (w_attrib_path
) {
2044 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2046 DEBUG(level
+ 1, "Group Attributes:");
2047 attrib
->dump(level
+ 2);
2052 // =================================
2053 // ===== ControlPart
2054 // =================================
2056 ControlPart::ControlPart(StatementBlock
* p_block
)
2057 : Node(), Location(), block(p_block
), w_attrib_path(0)
2059 if (!p_block
) FATAL_ERROR("ControlPart::ControlPart()");
2062 ControlPart::~ControlPart()
2065 delete w_attrib_path
;
2068 ControlPart
* ControlPart::clone() const
2070 FATAL_ERROR("ControlPart::clone");
2073 void ControlPart::set_fullname(const string
& p_fullname
)
2075 block
->set_fullname(p_fullname
);
2076 if(w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
2079 void ControlPart::set_my_scope(Scope
*p_scope
)
2081 bridgeScope
.set_parent_scope(p_scope
);
2082 string
temp("control");
2083 bridgeScope
.set_scopeMacro_name(temp
);
2085 block
->set_my_scope(&bridgeScope
);
2088 void ControlPart::chk()
2090 Error_Context
cntxt(this, "In control part");
2092 if (!semantic_check_only
)
2093 block
->set_code_section(GovernedSimple::CS_INLINE
);
2094 if (w_attrib_path
) {
2095 w_attrib_path
->chk_global_attrib();
2096 w_attrib_path
->chk_no_qualif();
2100 void ControlPart::generate_code(output_struct
*target
, Module
*my_module
)
2102 const char *module_dispname
= my_module
->get_modid().get_dispname().c_str();
2103 target
->functions
.control
=
2104 create_location_object(target
->functions
.control
, "CONTROLPART",
2106 target
->functions
.control
= mputprintf(target
->functions
.control
,
2107 "TTCN_Runtime::begin_controlpart(\"%s\");\n", module_dispname
);
2108 if (debugger_active
) {
2109 target
->functions
.control
= mputprintf(target
->functions
.control
,
2110 "charstring_list no_params = NULL_VALUE;\n"
2111 "TTCN3_Debug_Function debug_scope(NULL, \"control\", \"%s\", no_params, no_params, NULL);\n"
2112 "debug_scope.initial_snapshot();\n", module_dispname
);
2114 target
->functions
.control
=
2115 block
->generate_code(target
->functions
.control
);
2116 target
->functions
.control
= mputstr(target
->functions
.control
,
2117 "TTCN_Runtime::end_controlpart();\n");
2120 void ControlPart::set_with_attr(MultiWithAttrib
* p_attrib
)
2122 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2123 w_attrib_path
->set_with_attr(p_attrib
);
2126 WithAttribPath
* ControlPart::get_attrib_path()
2128 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2129 return w_attrib_path
;
2132 void ControlPart::set_parent_path(WithAttribPath
* p_path
)
2134 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2135 w_attrib_path
->set_parent(p_path
);
2136 block
->set_parent_path(w_attrib_path
);
2139 void ControlPart::dump(unsigned level
) const
2141 DEBUG(level
, "Control part");
2142 block
->dump(level
+ 1);
2143 if (w_attrib_path
) {
2144 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2146 DEBUG(level
+ 1, "Attributes:");
2147 attrib
->dump(level
+ 2);
2152 // =================================
2154 // =================================
2156 Module::Module(Identifier
*p_modid
)
2157 : Common::Module(MOD_TTCN
, p_modid
), language_spec(0), w_attrib_path(0),
2160 asss
= new Definitions();
2161 asss
->set_parent_scope(this);
2162 imp
= new Imports();
2163 imp
->set_my_mod(this);
2164 //modified_encodings = true; // Assume always true for TTCN modules
2169 delete language_spec
;
2171 for (size_t i
= 0; i
< group_v
.size(); i
++) delete group_v
[i
];
2175 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) delete friendmods_v
[i
];
2176 friendmods_v
.clear();
2178 for (size_t i
= 0; i
< runs_on_scopes
.size(); i
++)
2179 delete runs_on_scopes
[i
];
2180 runs_on_scopes
.clear();
2181 delete w_attrib_path
;
2184 void Module::add_group(Group
* p_group
)
2186 group_v
.add(p_group
);
2189 void Module::add_friendmod(FriendMod
*p_friendmod
)
2191 friendmods_v
.add(p_friendmod
);
2192 p_friendmod
->set_my_mod(this);
2195 Module
*Module::clone() const
2197 FATAL_ERROR("Ttcn::Module::clone()");
2200 Common::Assignment
*Module::importAssignment(const Identifier
& p_modid
,
2201 const Identifier
& p_id
) const
2203 if (asss
->has_local_ass_withId(p_id
)) {
2204 Common::Assignment
* ass
= asss
->get_local_ass_byId(p_id
);
2205 if (!ass
) FATAL_ERROR("Ttcn::Module::importAssignment()");
2207 switch(ass
->get_visibility()) {
2209 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) {
2210 if (friendmods_v
[i
]->get_modid() == p_modid
) return ass
;
2218 FATAL_ERROR("Ttcn::Module::importAssignment()");
2224 void Module::set_fullname(const string
& p_fullname
)
2226 Node::set_fullname(p_fullname
);
2227 asss
->set_fullname(p_fullname
);
2228 if (controlpart
) controlpart
->set_fullname(p_fullname
+ ".control");
2229 for(size_t i
= 0; i
< group_v
.size(); i
++)
2231 group_v
[i
]->set_fullname(p_fullname
+ ".<group " + Int2string(i
) + ">");
2233 if (w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
2237 Common::Assignments
*Module::get_scope_asss()
2242 bool Module::has_imported_ass_withId(const Identifier
& p_id
)
2244 const Location
*loc
= NULL
;
2245 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2246 const ImpMod
* im
= imp
->get_impmod(i
);
2247 //TODO use a reference instead of an identifier
2248 if(im
->has_imported_def(*modid
, p_id
, loc
)) return true;
2253 Common::Assignment
* Module::get_ass_bySRef(Ref_simple
*p_ref
)
2255 const Identifier
*r_modid
= p_ref
->get_modid();
2256 const Identifier
*r_id
= p_ref
->get_id();
2258 // the reference contains a module name
2259 if (r_modid
->get_name() != modid
->get_name()) {
2260 // the reference points to another module
2261 bool has_impmod_with_name
= false;
2262 Common::Assignment
* result_ass
= NULL
;
2263 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2264 const ImpMod
* im
= imp
->get_impmod(i
);
2265 const Identifier
& im_id
= im
->get_modid();
2266 const string
& im_name
= im_id
.get_name();
2267 if (r_modid
->get_name() == im_name
) {
2268 has_impmod_with_name
= true;
2269 vector
<ImpMod
> tempusedImpMods
;
2270 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2271 Common::Assignment
*t_ass
= im
->get_imported_def(*modid
, *r_id
, p_ref
, referencechain
, tempusedImpMods
);
2272 referencechain
->reset();
2273 delete referencechain
;
2275 if (t_ass
!= NULL
) {
2276 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(im
->get_mod());
2277 if (!ttcn_m
->is_visible(*modid
, t_ass
->get_visibility())) {
2281 if (t_ass
!= NULL
) {
2282 if (result_ass
== NULL
) {
2284 } else if(result_ass
!= t_ass
) {
2286 "It is not possible to resolve the reference unambiguously"
2287 ", as it can be resolved to `%s' and to `%s'",
2288 result_ass
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
2292 tempusedImpMods
.clear();
2295 if (result_ass
) return result_ass
;
2297 if (has_impmod_with_name
) {
2298 p_ref
->error("There is no definition with name `%s' visible from "
2299 "module `%s'", r_id
->get_dispname().c_str(),
2300 r_modid
->get_dispname().c_str());
2302 if (modules
->has_mod_withId(*r_modid
)) {
2303 Common::Module
*m
= modules
->get_mod_byId(*r_modid
);
2304 if (m
->get_asss()->has_ass_withId(*r_id
)) {
2305 p_ref
->error("Definition with name `%s' is not imported from "
2306 "module `%s'", r_id
->get_dispname().c_str(),
2307 r_modid
->get_dispname().c_str());
2309 p_ref
->error("There is no definition with name `%s' in "
2310 "module `%s'", r_id
->get_dispname().c_str(),
2311 r_modid
->get_dispname().c_str());
2314 p_ref
->error("There is no module with name `%s'",
2315 r_modid
->get_dispname().c_str());
2320 // the reference points to the own module
2321 if (asss
->has_local_ass_withId(*r_id
)) {
2322 return asss
->get_local_ass_byId(*r_id
);
2324 p_ref
->error("There is no definition with name `%s' in "
2325 "module `%s'", r_id
->get_dispname().c_str(),
2326 r_modid
->get_dispname().c_str());
2330 // no module name is given in the reference
2331 if (asss
->has_local_ass_withId(*r_id
)) {
2332 return asss
->get_local_ass_byId(*r_id
);
2334 // the reference was not found locally -> look at the import list
2335 Common::Assignment
*t_result
= NULL
, *t_ass
= NULL
;
2336 for (size_t i
= 0, num
= imp
->get_imports_size(); i
< num
; ++i
) {
2337 const ImpMod
* im
= imp
->get_impmod(i
);
2339 vector
<ImpMod
> tempusedImpMods
;
2340 ReferenceChain
* referencechain
= new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2341 t_ass
= im
->get_imported_def(*modid
, *r_id
, p_ref
, referencechain
, tempusedImpMods
);
2342 referencechain
->reset();
2344 delete referencechain
;
2345 if (t_ass
!= NULL
) {
2346 Ttcn::Module
*ttcn_m
= static_cast<Ttcn::Module
*>(im
->get_mod());
2347 if (!ttcn_m
->is_visible(*modid
, t_ass
->get_visibility())) {
2351 if (t_ass
!= NULL
) {
2352 if (t_result
== NULL
) {
2354 } else if(t_result
!= t_ass
) {
2356 "It is not possible to resolve the reference unambiguously"
2357 ", as it can be resolved to `%s' and to `%s'",
2358 t_result
->get_fullname().c_str(), t_ass
->get_fullname().c_str());
2362 tempusedImpMods
.clear();
2365 if (t_result
) return t_result
;
2367 p_ref
->error("There is no local or imported definition with name `%s'"
2368 ,r_id
->get_dispname().c_str());
2374 bool Module::is_valid_moduleid(const Identifier
& p_id
)
2376 // The identifier represents the current module
2377 if (p_id
.get_name() == modid
->get_name()) return true;
2378 // The identifier represents a module imported in the current module
2379 if(imp
->has_impmod_withId(p_id
)) return true;
2383 Common::Assignments
*Module::get_asss()
2388 bool Module::exports_sym(const Identifier
&)
2390 FATAL_ERROR("Ttcn::Module::exports_sym()");
2394 Type
*Module::get_address_type()
2396 Identifier
address_id(Identifier::ID_TTCN
, string("address"));
2397 // return NULL if address type is not defined
2398 if (!asss
->has_local_ass_withId(address_id
)) return 0;
2399 Common::Assignment
*t_ass
= asss
->get_local_ass_byId(address_id
);
2400 if (t_ass
->get_asstype() != Common::Assignment::A_TYPE
)
2401 FATAL_ERROR("Module::get_address_type(): address is not a type");
2402 return t_ass
->get_Type();
2405 void Module::chk_imp(ReferenceChain
& refch
, vector
<Common::Module
>& moduleStack
)
2407 if (imp_checked
) return;
2408 const string
& module_name
= modid
->get_dispname();
2410 Error_Context backup
;
2411 Error_Context
cntxt(this, "In TTCN-3 module `%s'", module_name
.c_str());
2412 imp
->chk_imp(refch
, moduleStack
);
2415 collect_visible_mods();
2420 DEBUG(1, "Checking TTCN-3 module `%s'", modid
->get_dispname().c_str());
2421 Error_Context
cntxt(this, "In TTCN-3 module `%s'",
2422 modid
->get_dispname().c_str());
2423 if (w_attrib_path
) {
2424 w_attrib_path
->chk_global_attrib();
2425 w_attrib_path
->chk_no_qualif();
2427 // Check "extension" attributes in the module's "with" statement
2428 MultiWithAttrib
*multi
= w_attrib_path
->get_with_attr();
2429 if (multi
) for (size_t i
= 0; i
< multi
->get_nof_elements(); ++i
) {
2430 const SingleWithAttrib
*single
= multi
->get_element(i
);
2431 if (single
->get_attribKeyword() != SingleWithAttrib::AT_EXTENSION
) continue;
2432 // Parse the extension attribute
2433 // We circumvent parse_extattributes() in coding_attrib_p.y because
2434 // it processes all attributes in the "with" statement and
2435 // doesn't allow the removal on a case-by-case basis.
2437 init_coding_attrib_lex(single
->get_attribSpec());
2438 int result
= coding_attrib_parse();// 0=OK, 1=error, 2=out of memory
2439 cleanup_coding_attrib_lex();
2446 const size_t num_parsed
= extatrs
->size();
2447 for (size_t a
= 0; a
< num_parsed
; ++a
) {
2448 Ttcn::ExtensionAttribute
& ex
= extatrs
->get(0);
2450 switch (ex
.get_type()) {
2451 case Ttcn::ExtensionAttribute::VERSION_TEMPLATE
:
2452 case Ttcn::ExtensionAttribute::VERSION
: {
2453 char* act_product_number
;
2454 unsigned int act_suffix
, act_rel
, act_patch
, act_build
;
2456 (void)ex
.get_id(act_product_number
, act_suffix
, act_rel
, act_patch
, act_build
, extra_junk
);
2458 if (release
!= UINT_MAX
) {
2459 ex
.error("Duplicate 'version' attribute");
2462 product_number
= mcopystr(act_product_number
);
2463 suffix
= act_suffix
;
2467 extra
= mcopystr(extra_junk
);
2469 // Avoid propagating the attribute needlessly
2470 multi
->delete_element(i
--);
2474 case Ttcn::ExtensionAttribute::REQUIRES
: {
2475 // Imports have already been checked
2476 char* exp_product_number
;
2477 unsigned int exp_suffix
, exp_rel
, exp_patch
, exp_build
;
2479 Common::Identifier
*req_id
= ex
.get_id(exp_product_number
,
2480 exp_suffix
, exp_rel
, exp_patch
, exp_build
, exp_extra
);
2482 if (imp
->has_impmod_withId(*req_id
)) {
2483 Common::Module
* m
= modules
->get_mod_byId(*req_id
);
2484 if (m
->product_number
== NULL
&& exp_product_number
!= NULL
) {
2485 ex
.error("Module '%s' requires module '%s' of product %s"
2486 ", but it is not specified",
2487 this->modid
->get_dispname().c_str(), req_id
->get_dispname().c_str(),
2488 exp_product_number
);
2489 multi
->delete_element(i
--);
2492 } else if (exp_product_number
== NULL
&&
2493 m
->product_number
!= NULL
&& strcmp(m
->product_number
, "") > 0){
2494 ex
.warning("Module '%s' requires module '%s' of any product"
2495 ", while it specifies '%s'",
2496 this->modid
->get_dispname().c_str(),
2497 req_id
->get_dispname().c_str(), m
->product_number
);
2498 } else if (m
->product_number
!= NULL
&& exp_product_number
!= NULL
2499 && 0 != strcmp(m
->product_number
, exp_product_number
)) {
2500 char *req_product_identifier
=
2501 get_product_identifier(exp_product_number
,
2502 exp_suffix
, exp_rel
, exp_patch
, exp_build
);
2503 char *mod_product_identifier
=
2504 get_product_identifier(m
->product_number
,
2505 m
->suffix
, m
->release
, m
->patch
, m
->build
);
2507 ex
.error("Module '%s' requires version %s of module"
2508 " '%s', but only %s is available",
2509 this->modid
->get_dispname().c_str(), req_product_identifier
,
2510 req_id
->get_dispname().c_str(), mod_product_identifier
);
2511 Free(req_product_identifier
);
2512 Free(mod_product_identifier
);
2513 multi
->delete_element(i
--);
2517 // different suffixes are always incompatible
2518 // unless the special version number is used
2519 if (m
->suffix
!= exp_suffix
&& (m
->suffix
!= UINT_MAX
)) {
2520 char *req_product_identifier
=
2521 get_product_identifier(exp_product_number
,exp_suffix
, exp_rel
, exp_patch
, exp_build
);
2522 char *mod_product_identifier
=
2523 get_product_identifier(m
->product_number
,
2524 m
->suffix
, m
->release
, m
->patch
, m
->build
);
2526 ex
.error("Module '%s' requires version %s of module"
2527 " '%s', but only %s is available",
2528 this->modid
->get_dispname().c_str(), req_product_identifier
,
2529 req_id
->get_dispname().c_str(), mod_product_identifier
);
2530 Free(req_product_identifier
);
2531 Free(mod_product_identifier
);
2532 multi
->delete_element(i
--);
2536 if ( m
->release
< exp_rel
2537 ||(m
->release
== exp_rel
&& m
->patch
< exp_patch
)
2538 ||(m
->patch
== exp_patch
&& m
->build
< exp_build
)) {
2539 char *mod_bld_str
= buildstr(m
->build
);
2540 char *exp_bld_str
= buildstr(exp_build
);
2541 if (mod_bld_str
==0 || exp_bld_str
==0) FATAL_ERROR(
2542 "Ttcn::Module::chk() invalid build number");
2543 ex
.error("Module '%s' requires version R%u%c%s of module"
2544 " '%s', but only R%u%c%s is available",
2545 this->modid
->get_dispname().c_str(),
2546 exp_rel
, eri(exp_patch
), exp_bld_str
,
2547 req_id
->get_dispname().c_str(),
2548 m
->release
, eri(m
->patch
), mod_bld_str
);
2553 single
->error("No imported module named '%s'",
2554 req_id
->get_dispname().c_str());
2556 multi
->delete_element(i
--);
2560 case Ttcn::ExtensionAttribute::REQ_TITAN
: {
2561 char* exp_product_number
;
2562 unsigned int exp_suffix
, exp_minor
, exp_patch
, exp_build
;
2564 (void)ex
.get_id(exp_product_number
, exp_suffix
, exp_minor
, exp_patch
, exp_build
, exp_extra
);
2565 if (exp_product_number
!= NULL
&& strcmp(exp_product_number
,"CRL 113 200") != 0) {
2566 ex
.error("This module needs to be compiled with TITAN, but "
2567 " product number %s is not TITAN"
2568 , exp_product_number
);
2570 if (0 == exp_suffix
) {
2571 exp_suffix
= 1; // previous version number format did not list the suffix part
2573 // TTCN3_MAJOR is always 1
2574 int expected_version
= exp_suffix
* 1000000
2575 + exp_minor
* 10000 + exp_patch
* 100 + exp_build
;
2576 if (expected_version
> TTCN3_VERSION_MONOTONE
) {
2577 char *exp_product_identifier
=
2578 get_product_identifier(exp_product_number
, exp_suffix
, exp_minor
, exp_patch
, exp_build
);
2579 ex
.error("This module needs to be compiled with TITAN version"
2580 " %s or higher; version %s detected"
2581 , exp_product_identifier
, PRODUCT_NUMBER
);
2582 Free(exp_product_identifier
);
2584 multi
->delete_element(i
--);
2587 case Ttcn::ExtensionAttribute::PRINTING
: {
2588 ex
.error("Attribute 'printing' not allowed at module level");
2589 multi
->delete_element(i
--);
2595 // Let everything else propagate into the module.
2596 // Extension attributes in the module's "with" statement
2597 // may be impractical, but not outright erroneous.
2608 if (controlpart
) controlpart
->chk();
2609 if (control_ns
&& !*control_ns
) { // set but empty
2610 error("Invalid URI value for control namespace");
2612 if (control_ns_prefix
&& !*control_ns_prefix
) { // set but empty
2613 error("Empty NCName for the control namespace prefix is not allowed");
2615 // TODO proper URI and NCName validation
2618 void Module::chk_friends()
2620 map
<string
, FriendMod
> friends_m
;
2622 for(size_t i
= 0; i
< friendmods_v
.size(); i
++)
2624 FriendMod
* temp_friend
= friendmods_v
[i
];
2625 const Identifier
& friend_id
= temp_friend
->get_modid();
2626 const string
& friend_name
= friend_id
.get_name();
2627 if(friends_m
.has_key(friend_name
))
2629 temp_friend
->error("Duplicate friend module with name `%s'",
2630 friend_id
.get_dispname().c_str());
2631 friends_m
[friend_name
]->note("Friend module `%s' is already defined here",
2632 friend_id
.get_dispname().c_str());
2634 friends_m
.add(friend_name
, temp_friend
);
2637 friendmods_v
[i
]->chk();
2644 void Module::chk_groups()
2646 map
<string
,Common::Assignment
> ass_m
;
2648 for(size_t i
= 0; i
< asss
->get_nof_asss(); i
++)
2650 Common::Assignment
*temp_ass
= asss
->get_ass_byIndex(i
);
2651 if(!temp_ass
->get_parent_group())
2653 const string
& ass_name
= temp_ass
->get_id().get_name();
2654 if (!ass_m
.has_key(ass_name
)) ass_m
.add(ass_name
, temp_ass
);
2658 for(size_t i
= 0; i
< group_v
.size(); i
++)
2660 const Group
* group
= group_v
[i
];
2661 const Identifier
& group_id
= group
->get_id();
2662 const string
& group_name
= group_id
.get_name();
2663 if(ass_m
.has_key(group_name
))
2665 group
->error("Group name `%s' clashes with a definition",
2666 group_id
.get_dispname().c_str());
2667 ass_m
[group_name
]->note("Definition of `%s' is here",
2668 group_id
.get_dispname().c_str());
2670 if(group_m
.has_key(group_name
))
2672 group
->error("Duplicate group with name `%s'",
2673 group_id
.get_dispname().c_str());
2674 group_m
[group_name
]->note("Group `%s' is already defined here",
2675 group_id
.get_dispname().c_str());
2677 group_m
.add(group_name
,group_v
[i
]);
2683 for(size_t i
= 0; i
< group_v
.size(); i
++)
2689 void Module::get_imported_mods(module_set_t
& p_imported_mods
)
2691 imp
->get_imported_mods(p_imported_mods
);
2694 void Module::generate_code_internal(CodeGenHelper
& cgh
) {
2695 imp
->generate_code(cgh
);
2696 asss
->generate_code(cgh
);
2698 controlpart
->generate_code(cgh
.get_outputstruct(modid
->get_ttcnname()), this);
2701 RunsOnScope
*Module::get_runs_on_scope(Type
*comptype
)
2703 RunsOnScope
*ret_val
= new RunsOnScope(comptype
);
2704 runs_on_scopes
.add(ret_val
);
2705 ret_val
->set_parent_scope(asss
);
2706 ret_val
->chk_uniq();
2711 void Module::dump(unsigned level
) const
2713 DEBUG(level
, "TTCN-3 module: %s", modid
->get_dispname().c_str());
2715 if(imp
) imp
->dump(level
);
2716 if(asss
) asss
->dump(level
);
2718 for(size_t i
= 0; i
< group_v
.size(); i
++)
2720 group_v
[i
]->dump(level
);
2723 if(controlpart
) controlpart
->dump(level
);
2725 if (w_attrib_path
) {
2726 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
2728 DEBUG(level
, "Module Attributes:");
2729 attrib
->dump(level
+ 1);
2734 void Module::set_language_spec(const char *p_language_spec
)
2736 if (language_spec
) FATAL_ERROR("Module::set_language_spec()");
2737 if (p_language_spec
) language_spec
= new string(p_language_spec
);
2740 void Module::add_ass(Definition
* p_ass
)
2742 asss
->add_ass(p_ass
);
2745 void Module::add_impmod(ImpMod
*p_impmod
)
2747 imp
->add_impmod(p_impmod
);
2750 void Module::add_controlpart(ControlPart
* p_controlpart
)
2752 if (!p_controlpart
|| controlpart
) FATAL_ERROR("Module::add_controlpart()");
2753 controlpart
= p_controlpart
;
2754 controlpart
->set_my_scope(asss
);
2757 void Module::set_with_attr(MultiWithAttrib
* p_attrib
)
2759 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2760 w_attrib_path
->set_with_attr(p_attrib
);
2763 WithAttribPath
* Module::get_attrib_path()
2765 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2766 return w_attrib_path
;
2769 void Module::set_parent_path(WithAttribPath
* p_path
)
2771 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
2772 w_attrib_path
->set_parent(p_path
);
2775 bool Module::is_visible(const Identifier
& id
, visibility_t visibility
){
2777 if (visibility
== PUBLIC
) {
2780 if (visibility
== FRIEND
) {
2781 for (size_t i
= 0; i
< friendmods_v
.size(); i
++) {
2782 if (friendmods_v
[i
]->get_modid() == id
) {
2790 void Module::generate_json_schema(JSON_Tokenizer
& json
, map
<Type
*, JSON_Tokenizer
>& json_refs
)
2792 // add a new property for this module
2793 json
.put_next_token(JSON_TOKEN_NAME
, modid
->get_ttcnname().c_str());
2795 // add type definitions into an object
2796 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2798 // cycle through each type, generate schema segment and reference when needed
2799 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2800 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2802 Type
* t
= def
->get_Type();
2803 if (t
->has_encoding(Type::CT_JSON
)) {
2804 // insert type's schema segment
2805 t
->generate_json_schema(json
, false, false);
2807 if (json_refs_for_all_types
&& !json_refs
.has_key(t
)) {
2808 // create JSON schema reference for the type
2809 JSON_Tokenizer
* json_ref
= new JSON_Tokenizer
;
2810 json_refs
.add(t
, json_ref
);
2811 t
->generate_json_schema_ref(*json_ref
);
2817 // end of type definitions
2818 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2820 // insert function data
2821 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2822 Def_ExtFunction
* def
= dynamic_cast<Def_ExtFunction
*>(asss
->get_ass_byIndex(i
));
2824 def
->generate_json_schema_ref(json_refs
);
2829 void Module::generate_debugger_init(output_struct
* output
)
2831 static boolean first
= TRUE
;
2832 // create the initializer function
2833 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2834 "\n/* Initializing the TTCN-3 debugger */\n"
2835 "void init_ttcn3_debugger()\n"
2837 "%s", first
? " ttcn3_debugger.activate();\n" : "");
2840 // initialize global scope and variables (including imported variables)
2841 char* str_glob
= generate_debugger_global_vars(NULL
, this);
2842 for (int i
= 0; i
< imp
->get_imports_size(); ++i
) {
2843 str_glob
= imp
->get_impmod(i
)->get_mod()->generate_debugger_global_vars(str_glob
, this);
2845 if (str_glob
!= NULL
) {
2846 // only add the global scope if it actually has variables
2847 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2848 " /* global variables */\n"
2849 " TTCN3_Debug_Scope* global_scope = ttcn3_debugger.add_global_scope(\"%s\");\n"
2851 get_modid().get_dispname().c_str(), str_glob
);
2855 // initialize components' scopes and their variables
2856 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2857 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2859 Type
* comp_type
= def
->get_Type();
2860 if (comp_type
->get_typetype() == Type::T_COMPONENT
) {
2861 char* str_comp
= NULL
;
2862 ComponentTypeBody
* comp_body
= comp_type
->get_CompBody();
2863 for (size_t j
= 0; j
< comp_body
->get_nof_asss(); ++j
) {
2864 str_comp
= generate_code_debugger_add_var(str_comp
, comp_body
->get_ass_byIndex(j
),
2865 this, comp_type
->get_dispname().c_str());
2867 if (str_comp
!= NULL
) {
2868 // only add the component if it actually has variables
2869 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2870 " /* variables of component %s */\n"
2871 " TTCN3_Debug_Scope* %s_scope = ttcn3_debugger.add_component_scope(\"%s\");\n"
2873 , comp_type
->get_dispname().c_str(), comp_type
->get_dispname().c_str()
2874 , comp_type
->get_dispname().c_str(), str_comp
);
2881 // close the initializer function
2882 output
->source
.global_vars
= mputstr(output
->source
.global_vars
, "}\n");
2885 char* Module::generate_debugger_global_vars(char* str
, Common::Module
* current_mod
)
2887 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2888 Common::Assignment
* ass
= asss
->get_ass_byIndex(i
);
2889 switch (ass
->get_asstype()) {
2890 case Common::Assignment::A_TEMPLATE
:
2891 if (ass
->get_FormalParList() != NULL
) {
2892 // don't add parameterized templates, since they are functions in C++
2895 // else fall through
2896 case Common::Assignment::A_CONST
:
2897 case Common::Assignment::A_MODULEPAR
:
2898 case Common::Assignment::A_MODULEPAR_TEMP
:
2899 str
= generate_code_debugger_add_var(str
, ass
, current_mod
, "global");
2901 case Common::Assignment::A_EXT_CONST
: {
2902 Def_ExtConst
* def
= dynamic_cast<Def_ExtConst
*>(ass
);
2904 FATAL_ERROR("Module::generate_debugger_global_vars");
2906 if (def
->is_used()) {
2907 str
= generate_code_debugger_add_var(str
, ass
, current_mod
, "global");
2917 void Module::generate_debugger_functions(output_struct
*output
)
2919 char* print_str
= NULL
;
2920 char* overwrite_str
= NULL
;
2921 for (size_t i
= 0; i
< asss
->get_nof_asss(); ++i
) {
2922 Def_Type
* def
= dynamic_cast<Def_Type
*>(asss
->get_ass_byIndex(i
));
2924 Type
* t
= def
->get_Type();
2925 if (!t
->is_ref() && t
->get_typetype() != Type::T_COMPONENT
&&
2926 t
->get_typetype() != Type::T_PORT
) {
2927 // don't generate code for subtypes
2928 if (t
->get_typetype() != Type::T_SIGNATURE
) {
2929 print_str
= mputprintf(print_str
,
2930 " %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
2931 " ((const %s*)ptr)->log();\n"
2933 , (print_str
!= NULL
) ? "else " : ""
2934 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2935 overwrite_str
= mputprintf(overwrite_str
,
2936 " %sif (!strcmp(p_var.type_name, \"%s\")) {\n"
2937 " ((%s*)p_var.value)->set_param(p_new_value);\n"
2939 , (overwrite_str
!= NULL
) ? "else " : ""
2940 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2942 print_str
= mputprintf(print_str
,
2943 " %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
2944 " ((const %s_template*)ptr)->log();\n"
2946 , (print_str
!= NULL
) ? "else " : ""
2947 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2948 if (t
->get_typetype() != Type::T_SIGNATURE
) {
2949 overwrite_str
= mputprintf(overwrite_str
,
2950 " %sif (!strcmp(p_var.type_name, \"%s template\")) {\n"
2951 " ((%s_template*)p_var.value)->set_param(p_new_value);\n"
2953 , (overwrite_str
!= NULL
) ? "else " : ""
2954 , t
->get_dispname().c_str(), t
->get_genname_value(this).c_str());
2959 if (print_str
!= NULL
) {
2960 // don't generate an empty printing function
2961 output
->header
.class_defs
= mputprintf(output
->header
.class_defs
,
2962 "/* Debugger printing and overwriting functions for types declared in this module */\n\n"
2963 "extern CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var);\n",
2964 get_modid().get_ttcnname().c_str());
2965 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2966 "\n/* Debugger printing function for types declared in this module */\n"
2967 "CHARSTRING print_var_%s(const TTCN3_Debugger::variable_t& p_var)\n"
2969 " const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;\n"
2970 " TTCN_Logger::begin_event_log2str();\n"
2973 " TTCN_Logger::log_event_str(\"<unrecognized value or template>\");\n"
2975 " return TTCN_Logger::end_event_log2str();\n"
2976 "}\n", get_modid().get_ttcnname().c_str(), print_str
);
2979 if (overwrite_str
!= NULL
) {
2980 // don't generate an empty overwriting function
2981 output
->header
.class_defs
= mputprintf(output
->header
.class_defs
,
2982 "extern boolean set_var_%s(TTCN3_Debugger::variable_t& p_var, Module_Param& p_new_value);\n",
2983 get_modid().get_ttcnname().c_str());
2984 output
->source
.global_vars
= mputprintf(output
->source
.global_vars
,
2985 "\n/* Debugger overwriting function for types declared in this module */\n"
2986 "boolean set_var_%s(TTCN3_Debugger::variable_t& p_var, Module_Param& p_new_value)\n"
2993 "}\n", get_modid().get_ttcnname().c_str(), overwrite_str
);
2994 Free(overwrite_str
);
2998 // =================================
3000 // =================================
3002 string
Definition::get_genname() const
3004 if (!genname
.empty()) return genname
;
3005 else return id
->get_name();
3008 namedbool
Definition::has_implicit_omit_attr() const {
3009 if (w_attrib_path
) {
3010 const vector
<SingleWithAttrib
>& real_attribs
=
3011 w_attrib_path
->get_real_attrib();
3012 for (size_t in
= real_attribs
.size(); in
> 0; in
--) {
3013 if (SingleWithAttrib::AT_OPTIONAL
==
3014 real_attribs
[in
-1]->get_attribKeyword()) {
3015 if ("implicit omit" ==
3016 real_attribs
[in
-1]->get_attribSpec().get_spec()) {
3017 return IMPLICIT_OMIT
;
3018 } else if ("explicit omit" ==
3019 real_attribs
[in
-1]->get_attribSpec().get_spec()) {
3020 return NOT_IMPLICIT_OMIT
;
3021 } // error reporting for other values is in chk_global_attrib
3025 return NOT_IMPLICIT_OMIT
;
3028 Definition::~Definition()
3030 delete w_attrib_path
;
3031 delete erroneous_attrs
;
3034 void Definition::set_fullname(const string
& p_fullname
)
3036 Common::Assignment::set_fullname(p_fullname
);
3037 if (w_attrib_path
) w_attrib_path
->set_fullname(p_fullname
+ ".<attribpath>");
3038 if (erroneous_attrs
) erroneous_attrs
->set_fullname(p_fullname
+".<erroneous_attributes>");
3041 bool Definition::is_local() const
3043 if (!my_scope
) FATAL_ERROR("Definition::is_local()");
3044 for (Scope
*scope
= my_scope
; scope
; scope
= scope
->get_parent_scope()) {
3045 if (dynamic_cast<StatementBlock
*>(scope
)) return true;
3050 bool Definition::chk_identical(Definition
*)
3052 FATAL_ERROR("Definition::chk_identical()");
3056 void Definition::chk_erroneous_attr()
3058 if (!w_attrib_path
) return;
3059 const Ttcn::MultiWithAttrib
* attribs
= w_attrib_path
->get_local_attrib();
3060 if (!attribs
) return;
3061 for (size_t i
= 0; i
< attribs
->get_nof_elements(); i
++) {
3062 const Ttcn::SingleWithAttrib
* act_attr
= attribs
->get_element(i
);
3063 if (act_attr
->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_ERRONEOUS
) {
3064 if (!use_runtime_2
) {
3065 error("`erroneous' attributes can be used only with the Function Test Runtime");
3066 note("If you need negative testing use the -R flag when generating the makefile");
3069 size_t nof_qualifiers
= act_attr
->get_attribQualifiers() ? act_attr
->get_attribQualifiers()->get_nof_qualifiers() : 0;
3070 dynamic_array
<Type
*> refd_type_array(nof_qualifiers
); // only the qualifiers pointing to existing fields will be added to erroneous_attrs objects
3071 if (nof_qualifiers
==0) {
3072 act_attr
->error("At least one qualifier must be specified for the `erroneous' attribute");
3074 // check if qualifiers point to existing fields
3075 for (size_t qi
=0; qi
<nof_qualifiers
; qi
++) {
3076 Qualifier
* act_qual
= const_cast<Qualifier
*>(act_attr
->get_attribQualifiers()->get_qualifier(qi
));
3077 act_qual
->set_my_scope(get_my_scope());
3078 Type
* field_type
= get_Type()->get_field_type(act_qual
, Type::EXPECTED_CONSTANT
);
3080 dynamic_array
<size_t> subrefs_array
;
3081 dynamic_array
<Type
*> type_array
;
3082 bool valid_indexes
= get_Type()->get_subrefs_as_array(act_qual
, subrefs_array
, type_array
);
3083 if (!valid_indexes
) field_type
= NULL
;
3084 if (act_qual
->refers_to_string_element()) {
3085 act_qual
->error("Reference to a string element cannot be used in this context");
3089 refd_type_array
.add(field_type
);
3092 // parse the attr. spec.
3093 ErroneousAttributeSpec
* err_attr_spec
= ttcn3_parse_erroneous_attr_spec_string(
3094 act_attr
->get_attribSpec().get_spec().c_str(), act_attr
->get_attribSpec());
3095 if (err_attr_spec
) {
3096 if (!erroneous_attrs
) erroneous_attrs
= new ErroneousAttributes(get_Type());
3097 // attr.spec will be owned by erroneous_attrs object
3098 erroneous_attrs
->add_spec(err_attr_spec
);
3099 err_attr_spec
->set_fullname(get_fullname());
3100 err_attr_spec
->set_my_scope(get_my_scope());
3101 err_attr_spec
->chk();
3102 // create qualifier - err.attr.spec. pairs
3103 for (size_t qi
=0; qi
<nof_qualifiers
; qi
++) {
3104 if (refd_type_array
[qi
] && (err_attr_spec
->get_indicator()!=ErroneousAttributeSpec::I_INVALID
)) {
3105 erroneous_attrs
->add_pair(act_attr
->get_attribQualifiers()->get_qualifier(qi
), err_attr_spec
);
3111 if (erroneous_attrs
) erroneous_attrs
->chk();
3114 char* Definition::generate_code_str(char *str
)
3116 FATAL_ERROR("Definition::generate_code_str()");
3120 void Definition::ilt_generate_code(ILT
*)
3122 FATAL_ERROR("Definition::ilt_generate_code()");
3125 char *Definition::generate_code_init_comp(char *str
, Definition
*)
3127 FATAL_ERROR("Definition::generate_code_init_comp()");
3131 void Definition::set_with_attr(MultiWithAttrib
* p_attrib
)
3133 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3134 w_attrib_path
->set_with_attr(p_attrib
);
3137 WithAttribPath
* Definition::get_attrib_path()
3139 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3140 return w_attrib_path
;
3143 void Definition::set_parent_path(WithAttribPath
* p_path
)
3145 if (!w_attrib_path
) w_attrib_path
= new WithAttribPath();
3146 w_attrib_path
->set_parent(p_path
);
3149 void Definition::set_parent_group(Group
* p_group
)
3151 if(parentgroup
) // there would be a leak!
3152 FATAL_ERROR("Definition::set_parent_group()");
3153 parentgroup
= p_group
;
3156 Group
* Definition::get_parent_group()
3161 void Definition::dump_internal(unsigned level
) const
3163 DEBUG(level
, "Move along, nothing to see here");
3166 void Definition::dump(unsigned level
) const
3168 dump_internal(level
);
3169 if (w_attrib_path
) {
3170 MultiWithAttrib
*attrib
= w_attrib_path
->get_with_attr();
3172 DEBUG(level
+ 1, "Definition Attributes:");
3173 attrib
->dump(level
+ 2);
3176 if (erroneous_attrs
) erroneous_attrs
->dump(level
+1);
3179 // =================================
3181 // =================================
3183 Def_Type::Def_Type(Identifier
*p_id
, Type
*p_type
)
3184 : Definition(A_TYPE
, p_id
), type(p_type
)
3186 if(!p_type
) FATAL_ERROR("Ttcn::Def_Type::Def_Type()");
3187 type
->set_ownertype(Type::OT_TYPE_DEF
, this);
3190 Def_Type::~Def_Type()
3195 Def_Type
*Def_Type::clone() const
3197 FATAL_ERROR("Def_Type::clone");
3200 void Def_Type::set_fullname(const string
& p_fullname
)
3202 Definition::set_fullname(p_fullname
);
3203 type
->set_fullname(p_fullname
);
3206 void Def_Type::set_my_scope(Scope
*p_scope
)
3208 bridgeScope
.set_parent_scope(p_scope
);
3209 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
3211 Definition::set_my_scope(&bridgeScope
);
3212 type
->set_my_scope(&bridgeScope
);
3216 Setting
*Def_Type::get_Setting()
3221 Type
*Def_Type::get_Type()
3227 void Def_Type::chk()
3229 if (checked
) return;
3231 Error_Context
cntxt(this, "In %s definition `%s'",
3232 type
->get_typetype() == Type::T_SIGNATURE
? "signature" : "type",
3233 id
->get_dispname().c_str());
3234 type
->set_genname(get_genname());
3235 if (!semantic_check_only
&& type
->get_typetype() == Type::T_COMPONENT
) {
3236 // the prefix of embedded definitions must be set before the checking
3237 type
->get_CompBody()->set_genname(get_genname() + "_component_");
3240 while (w_attrib_path
) { // not a loop, but we can _break_ out of it
3241 w_attrib_path
->chk_global_attrib();
3242 w_attrib_path
->chk_no_qualif();
3243 if (type
->get_typetype() != Type::T_ANYTYPE
) break;
3244 // This is the anytype; it must be empty (we're about to add the fields)
3245 if (type
->get_nof_comps() > 0) FATAL_ERROR("Def_Type::chk");
3247 Ttcn::ExtensionAttributes
*extattrs
= parse_extattributes(w_attrib_path
);
3248 if (extattrs
== 0) break; // NULL means parsing error
3250 size_t num_atrs
= extattrs
->size();
3251 for (size_t k
= 0; k
< num_atrs
; ++k
) {
3252 ExtensionAttribute
&ea
= extattrs
->get(k
);
3253 switch (ea
.get_type()) {
3254 case ExtensionAttribute::ANYTYPELIST
: {
3255 Types
*anytypes
= ea
.get_types();
3256 // List of types to be converted into fields for the anytype.
3257 // Make sure scope is set on all types in the list.
3258 anytypes
->set_my_scope(get_my_scope());
3260 // Convert the list of types into field names for the anytype
3261 for (size_t i
=0; i
< anytypes
->get_nof_types(); ++i
) {
3262 Type
*t
= anytypes
->extract_type_byIndex(i
);
3263 // we are now the owner of the Type.
3264 if (t
->get_typetype()==Type::T_ERROR
) { // should we give up?
3270 const char* btn
= Type::get_typename_builtin(t
->get_typetype());
3274 else if (t
->get_typetype() == Type::T_REFD
) {
3275 // Extract the identifier
3276 Common::Reference
*ref
= t
->get_Reference();
3277 Ttcn::Reference
*tref
= dynamic_cast<Ttcn::Reference
*>(ref
);
3278 if (!tref
) FATAL_ERROR("Def_Type::chk, wrong kind of reference");
3279 const Common::Identifier
*modid
= tref
->get_modid();
3281 ea
.error("Qualified name '%s' cannot be added to the anytype",
3282 tref
->get_dispname().c_str());
3286 field_name
= tref
->get_id()->get_ttcnname();
3289 // Can't happen here
3290 FATAL_ERROR("Unexpected type %d", t
->get_typetype());
3293 const string
& at_field
= anytype_field(field_name
);
3294 Identifier
*field_id
= new Identifier(Identifier::ID_TTCN
, at_field
);
3295 CompField
*cf
= new CompField(field_id
, t
, false, 0);
3296 cf
->set_location(ea
);
3297 cf
->set_fullname(get_fullname());
3303 w_attrib_path
->get_with_attr()->error("Type def can only have anytype");
3309 break; // do not loop
3312 // Now we can check the type
3314 type
->chk_constructor_name(*id
);
3315 if (id
->get_ttcnname() == "address") type
->chk_address();
3316 ReferenceChain
refch(type
, "While checking embedded recursions");
3317 type
->chk_recursions(refch
);
3319 if (type
->get_typetype()==Type::T_FUNCTION
3320 ||type
->get_typetype()==Type::T_ALTSTEP
3321 ||type
->get_typetype()==Type::T_TESTCASE
) {
3322 // TR 922. This is a function/altstep/testcase reference.
3323 // Set this definition as the definition for the formal parameters.
3324 type
->get_fat_parameters()->set_my_def(this);
3328 void Def_Type::generate_code(output_struct
*target
, bool)
3330 type
->generate_code(target
);
3331 if (type
->get_typetype() == Type::T_COMPONENT
) {
3332 // the C++ equivalents of embedded component element definitions must be
3333 // generated from outside Type::generate_code() because the function can
3334 // call itself recursively and create invalid (overlapped) initializer
3336 type
->get_CompBody()->generate_code(target
);
3340 void Def_Type::generate_code(CodeGenHelper
& cgh
) {
3341 type
->generate_code(cgh
.get_outputstruct(get_Type()));
3342 if (type
->get_typetype() == Type::T_COMPONENT
) {
3343 // the C++ equivalents of embedded component element definitions must be
3344 // generated from outside Type::generate_code() because the function can
3345 // call itself recursively and create invalid (overlapped) initializer
3347 type
->get_CompBody()->generate_code(cgh
.get_current_outputstruct());
3349 cgh
.finalize_generation(get_Type());
3353 void Def_Type::dump_internal(unsigned level
) const
3355 DEBUG(level
, "Type def: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3356 type
->dump(level
+ 1);
3359 void Def_Type::set_with_attr(MultiWithAttrib
* p_attrib
)
3361 if (!w_attrib_path
) {
3362 w_attrib_path
= new WithAttribPath();
3363 type
->set_parent_path(w_attrib_path
);
3365 type
->set_with_attr(p_attrib
);
3368 WithAttribPath
* Def_Type::get_attrib_path()
3370 if (!w_attrib_path
) {
3371 w_attrib_path
= new WithAttribPath();
3372 type
->set_parent_path(w_attrib_path
);
3374 return w_attrib_path
;
3377 void Def_Type::set_parent_path(WithAttribPath
* p_path
)
3379 if (!w_attrib_path
) {
3380 w_attrib_path
= new WithAttribPath();
3381 type
->set_parent_path(w_attrib_path
);
3383 w_attrib_path
->set_parent(p_path
);
3386 // =================================
3388 // =================================
3390 Def_Const::Def_Const(Identifier
*p_id
, Type
*p_type
, Value
*p_value
)
3391 : Definition(A_CONST
, p_id
)
3393 if (!p_type
|| !p_value
) FATAL_ERROR("Ttcn::Def_Const::Def_Const()");
3395 type
->set_ownertype(Type::OT_CONST_DEF
, this);
3397 value_under_check
=false;
3400 Def_Const::~Def_Const()
3406 Def_Const
*Def_Const::clone() const
3408 FATAL_ERROR("Def_Const::clone");
3411 void Def_Const::set_fullname(const string
& p_fullname
)
3413 Definition::set_fullname(p_fullname
);
3414 type
->set_fullname(p_fullname
+ ".<type>");
3415 value
->set_fullname(p_fullname
);
3418 void Def_Const::set_my_scope(Scope
*p_scope
)
3420 Definition::set_my_scope(p_scope
);
3421 type
->set_my_scope(p_scope
);
3422 value
->set_my_scope(p_scope
);
3425 Setting
*Def_Const::get_Setting()
3430 Type
*Def_Const::get_Type()
3437 Value
*Def_Const::get_Value()
3443 void Def_Const::chk()
3446 if (value_under_check
) {
3447 error("Circular reference in constant definition `%s'",
3448 id
->get_dispname().c_str());
3449 value_under_check
= false; // only report the error once for this definition
3453 Error_Context
cntxt(this, "In constant definition `%s'",
3454 id
->get_dispname().c_str());
3455 type
->set_genname(_T_
, get_genname());
3457 value
->set_my_governor(type
);
3458 type
->chk_this_value_ref(value
);
3460 if (w_attrib_path
) {
3461 w_attrib_path
->chk_global_attrib(true);
3462 switch (type
->get_type_refd_last()->get_typetype_ttcn3()) {
3465 case Type::T_CHOICE_T
:
3466 // These types may have qualified attributes
3468 case Type::T_SEQOF
: case Type::T_SETOF
:
3471 w_attrib_path
->chk_no_qualif();
3475 Type
*t
= type
->get_type_refd_last();
3476 switch (t
->get_typetype()) {
3478 error("Constant cannot be defined for port type `%s'",
3479 t
->get_fullname().c_str());
3481 case Type::T_SIGNATURE
:
3482 error("Constant cannot be defined for signature `%s'",
3483 t
->get_fullname().c_str());
3486 value_under_check
= true;
3487 type
->chk_this_value(value
, 0, Type::EXPECTED_CONSTANT
, INCOMPLETE_ALLOWED
,
3488 OMIT_NOT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr());
3489 value_under_check
= false;
3490 chk_erroneous_attr();
3491 if (erroneous_attrs
) value
->set_err_descr(erroneous_attrs
->get_err_descr());
3493 ReferenceChain
refch(type
, "While checking embedded recursions");
3494 value
->chk_recursions(refch
);
3498 if (!semantic_check_only
) {
3499 value
->set_genname_prefix("const_");
3500 value
->set_genname_recursive(get_genname());
3501 value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3505 bool Def_Const::chk_identical(Definition
*p_def
)
3509 if (p_def
->get_asstype() != A_CONST
) {
3510 const char *dispname_str
= id
->get_dispname().c_str();
3511 error("Local definition `%s' is a constant, but the definition "
3512 "inherited from component type `%s' is a %s", dispname_str
,
3513 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
3514 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
3517 Def_Const
*p_def_const
= dynamic_cast<Def_Const
*>(p_def
);
3518 if (!p_def_const
) FATAL_ERROR("Def_Const::chk_identical()");
3519 if (!type
->is_identical(p_def_const
->type
)) {
3520 const char *dispname_str
= id
->get_dispname().c_str();
3521 type
->error("Local constant `%s' has type `%s', but the constant "
3522 "inherited from component type `%s' has type `%s'", dispname_str
,
3523 type
->get_typename().c_str(),
3524 p_def_const
->get_my_scope()->get_fullname().c_str(),
3525 p_def_const
->type
->get_typename().c_str());
3526 p_def_const
->note("The inherited constant `%s' is here", dispname_str
);
3528 } else if (!(*value
== *p_def_const
->value
)) {
3529 const char *dispname_str
= id
->get_dispname().c_str();
3530 value
->error("Local constant `%s' and the constant inherited from "
3531 "component type `%s' have different values", dispname_str
,
3532 p_def_const
->get_my_scope()->get_fullname().c_str());
3533 p_def_const
->note("The inherited constant `%s' is here", dispname_str
);
3538 void Def_Const::generate_code(output_struct
*target
, bool)
3540 type
->generate_code(target
);
3542 Code::init_cdef(&cdef
);
3543 type
->generate_code_object(&cdef
, value
);
3544 cdef
.init
= update_location_object(cdef
.init
);
3545 cdef
.init
= value
->generate_code_init(cdef
.init
,
3546 value
->get_lhs_name().c_str());
3547 Code::merge_cdef(target
, &cdef
);
3548 Code::free_cdef(&cdef
);
3551 void Def_Const::generate_code(Common::CodeGenHelper
& cgh
) {
3552 // constant definitions always go to its containing module
3553 generate_code(cgh
.get_current_outputstruct());
3556 char *Def_Const::generate_code_str(char *str
)
3558 const string
& t_genname
= get_genname();
3559 const char *genname_str
= t_genname
.c_str();
3560 if (value
->has_single_expr()) {
3561 // the value can be represented by a single C++ expression
3562 // the object is initialized by the constructor
3563 str
= mputprintf(str
, "%s %s(%s);\n",
3564 type
->get_genname_value(my_scope
).c_str(), genname_str
,
3565 value
->get_single_expr().c_str());
3567 // use the default constructor
3568 str
= mputprintf(str
, "%s %s;\n",
3569 type
->get_genname_value(my_scope
).c_str(), genname_str
);
3570 // the value is assigned using subsequent statements
3571 str
= value
->generate_code_init(str
, genname_str
);
3573 if (debugger_active
) {
3574 str
= generate_code_debugger_add_var(str
, this);
3579 void Def_Const::ilt_generate_code(ILT
*ilt
)
3581 const string
& t_genname
= get_genname();
3582 const char *genname_str
= t_genname
.c_str();
3583 char*& def
=ilt
->get_out_def();
3584 char*& init
=ilt
->get_out_branches();
3585 def
= mputprintf(def
, "%s %s;\n", type
->get_genname_value(my_scope
).c_str(),
3587 init
= value
->generate_code_init(init
, genname_str
);
3590 char *Def_Const::generate_code_init_comp(char *str
, Definition
*)
3592 /* This function actually does nothing as \a this and \a base_defn are
3593 * exactly the same. */
3597 void Def_Const::dump_internal(unsigned level
) const
3599 DEBUG(level
, "Constant: %s @%p", id
->get_dispname().c_str(), (const void*)this);
3600 type
->dump(level
+ 1);
3601 value
->dump(level
+ 1);
3604 // =================================
3605 // ===== Def_ExtConst
3606 // =================================
3608 Def_ExtConst::Def_ExtConst(Identifier
*p_id
, Type
*p_type
)
3609 : Definition(A_EXT_CONST
, p_id
)
3611 if (!p_type
) FATAL_ERROR("Ttcn::Def_ExtConst::Def_ExtConst()");
3613 type
->set_ownertype(Type::OT_CONST_DEF
, this);
3614 usage_found
= false;
3617 Def_ExtConst::~Def_ExtConst()
3622 Def_ExtConst
*Def_ExtConst::clone() const
3624 FATAL_ERROR("Def_ExtConst::clone");
3627 void Def_ExtConst::set_fullname(const string
& p_fullname
)
3629 Definition::set_fullname(p_fullname
);
3630 type
->set_fullname(p_fullname
+ ".<type>");
3633 void Def_ExtConst::set_my_scope(Scope
*p_scope
)
3635 Definition::set_my_scope(p_scope
);
3636 type
->set_my_scope(p_scope
);
3639 Type
*Def_ExtConst::get_Type()
3645 void Def_ExtConst::chk()
3648 Error_Context
cntxt(this, "In external constant definition `%s'",
3649 id
->get_dispname().c_str());
3650 type
->set_genname(_T_
, get_genname());
3653 Type
*t
= type
->get_type_refd_last();
3654 switch (t
->get_typetype()) {
3656 error("External constant cannot be defined for port type `%s'",
3657 t
->get_fullname().c_str());
3659 case Type::T_SIGNATURE
:
3660 error("External constant cannot be defined for signature `%s'",
3661 t
->get_fullname().c_str());
3666 if (w_attrib_path
) {
3667 w_attrib_path
->chk_global_attrib();
3668 switch (type
->get_type_refd_last()->get_typetype()) {
3671 case Type::T_CHOICE_T
:
3672 // These types may have qualified attributes
3674 case Type::T_SEQOF
: case Type::T_SETOF
:
3677 w_attrib_path
->chk_no_qualif();
3683 void Def_ExtConst::generate_code(output_struct
*target
, bool)
3685 type
->generate_code(target
);
3686 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
3687 "extern const %s& %s;\n", type
->get_genname_value(my_scope
).c_str(),
3688 get_genname().c_str());
3691 void Def_ExtConst::generate_code(Common::CodeGenHelper
& cgh
) {
3692 // constant definitions always go to its containing module
3693 generate_code(cgh
.get_current_outputstruct());
3696 void Def_ExtConst::dump_internal(unsigned level
) const
3698 DEBUG(level
, "External constant: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3699 type
->dump(level
+ 1);
3702 // =================================
3703 // ===== Def_Modulepar
3704 // =================================
3706 Def_Modulepar::Def_Modulepar(Identifier
*p_id
, Type
*p_type
, Value
*p_defval
)
3707 : Definition(A_MODULEPAR
, p_id
)
3709 if (!p_type
) FATAL_ERROR("Ttcn::Def_Modulepar::Def_Modulepar()");
3711 type
->set_ownertype(Type::OT_MODPAR_DEF
, this);
3712 def_value
= p_defval
;
3715 Def_Modulepar::~Def_Modulepar()
3721 Def_Modulepar
* Def_Modulepar::clone() const
3723 FATAL_ERROR("Def_Modulepar::clone");
3726 void Def_Modulepar::set_fullname(const string
& p_fullname
)
3728 Definition::set_fullname(p_fullname
);
3729 type
->set_fullname(p_fullname
+ ".<type>");
3730 if (def_value
) def_value
->set_fullname(p_fullname
+ ".<default_value>");
3733 void Def_Modulepar::set_my_scope(Scope
*p_scope
)
3735 Definition::set_my_scope(p_scope
);
3736 type
->set_my_scope(p_scope
);
3737 if (def_value
) def_value
->set_my_scope(p_scope
);
3740 Type
*Def_Modulepar::get_Type()
3746 void Def_Modulepar::chk()
3749 Error_Context
cntxt(this, "In module parameter definition `%s'",
3750 id
->get_dispname().c_str());
3751 type
->set_genname(_T_
, get_genname());
3753 if (w_attrib_path
) {
3754 w_attrib_path
->chk_global_attrib();
3755 switch (type
->get_type_refd_last()->get_typetype()) {
3758 case Type::T_CHOICE_T
:
3759 // These types may have qualified attributes
3761 case Type::T_SEQOF
: case Type::T_SETOF
:
3764 w_attrib_path
->chk_no_qualif();
3768 map
<Type
*,void> type_chain
;
3769 map
<Type::typetype_t
, void> not_allowed
;
3770 not_allowed
.add(Type::T_PORT
, 0);
3771 Type
*t
= type
->get_type_refd_last();
3772 // if the type is valid the original will be returned
3773 Type::typetype_t tt
= t
->search_for_not_allowed_type(type_chain
, not_allowed
);
3775 not_allowed
.clear();
3778 error("Type of module parameter cannot be or embed port type `%s'",
3779 t
->get_fullname().c_str());
3781 case Type::T_SIGNATURE
:
3782 error("Type of module parameter cannot be signature `%s'",
3783 t
->get_fullname().c_str());
3785 case Type::T_FUNCTION
:
3786 case Type::T_ALTSTEP
:
3787 case Type::T_TESTCASE
:
3788 if (t
->get_fat_runs_on_self()) {
3789 error("Type of module parameter cannot be of function reference type"
3790 " `%s' which has runs on self clause", t
->get_fullname().c_str());
3798 Error_Context
cntxt2(def_value
, "In default value");
3799 def_value
->set_my_governor(type
);
3800 type
->chk_this_value_ref(def_value
);
3802 type
->chk_this_value(def_value
, 0, Type::EXPECTED_CONSTANT
, INCOMPLETE_ALLOWED
,
3803 OMIT_NOT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr());
3804 if (!semantic_check_only
) {
3805 def_value
->set_genname_prefix("modulepar_");
3806 def_value
->set_genname_recursive(get_genname());
3807 def_value
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3809 } else checked
= true;
3815 void Def_Modulepar::generate_code(output_struct
*target
, bool)
3817 type
->generate_code(target
);
3819 Code::init_cdef(&cdef
);
3820 const string
& t_genname
= get_genname();
3821 const char *name
= t_genname
.c_str();
3822 type
->generate_code_object(&cdef
, my_scope
, t_genname
, "modulepar_", false);
3824 cdef
.init
= update_location_object(cdef
.init
);
3825 cdef
.init
= def_value
->generate_code_init(cdef
.init
, def_value
->get_lhs_name().c_str());
3827 Code::merge_cdef(target
, &cdef
);
3828 Code::free_cdef(&cdef
);
3830 if (has_implicit_omit_attr()) {
3831 target
->functions
.post_init
= mputprintf(target
->functions
.post_init
,
3832 "modulepar_%s.set_implicit_omit();\n", name
);
3835 const char *dispname
= id
->get_dispname().c_str();
3836 target
->functions
.set_param
= mputprintf(target
->functions
.set_param
,
3837 "if (!strcmp(par_name, \"%s\")) {\n"
3838 "modulepar_%s.set_param(param);\n"
3840 "} else ", dispname
, name
);
3841 target
->functions
.get_param
= mputprintf(target
->functions
.get_param
,
3842 "if (!strcmp(par_name, \"%s\")) {\n"
3843 "return modulepar_%s.get_param(param_name);\n"
3844 "} else ", dispname
, name
);
3846 if (target
->functions
.log_param
) {
3847 // this is not the first modulepar
3848 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3849 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname
);
3851 // this is the first modulepar
3852 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3853 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname
);
3855 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
3856 "%s.log();\n", name
);
3859 void Def_Modulepar::generate_code(Common::CodeGenHelper
& cgh
) {
3860 // module parameter definitions always go to its containing module
3861 generate_code(cgh
.get_current_outputstruct());
3864 void Def_Modulepar::dump_internal(unsigned level
) const
3866 DEBUG(level
, "Module parameter: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
3867 type
->dump(level
+ 1);
3868 if (def_value
) def_value
->dump(level
+ 1);
3869 else DEBUG(level
+ 1, "No default value");
3872 // =================================
3873 // ===== Def_Modulepar_Template
3874 // =================================
3876 Def_Modulepar_Template::Def_Modulepar_Template(Identifier
*p_id
, Type
*p_type
, Template
*p_deftmpl
)
3877 : Definition(A_MODULEPAR_TEMP
, p_id
)
3879 if (!p_type
) FATAL_ERROR("Ttcn::Def_Modulepar_Template::Def_Modulepar_Template()");
3881 type
->set_ownertype(Type::OT_MODPAR_DEF
, this);
3882 def_template
= p_deftmpl
;
3885 Def_Modulepar_Template::~Def_Modulepar_Template()
3888 delete def_template
;
3891 Def_Modulepar_Template
* Def_Modulepar_Template::clone() const
3893 FATAL_ERROR("Def_Modulepar_Template::clone");
3896 void Def_Modulepar_Template::set_fullname(const string
& p_fullname
)
3898 Definition::set_fullname(p_fullname
);
3899 type
->set_fullname(p_fullname
+ ".<type>");
3900 if (def_template
) def_template
->set_fullname(p_fullname
+ ".<default_template>");
3903 void Def_Modulepar_Template::set_my_scope(Scope
*p_scope
)
3905 Definition::set_my_scope(p_scope
);
3906 type
->set_my_scope(p_scope
);
3907 if (def_template
) def_template
->set_my_scope(p_scope
);
3910 Type
*Def_Modulepar_Template::get_Type()
3916 void Def_Modulepar_Template::chk()
3919 Error_Context
cntxt(this, "In template module parameter definition `%s'",
3920 id
->get_dispname().c_str());
3921 if (w_attrib_path
) {
3922 w_attrib_path
->chk_global_attrib();
3923 switch (type
->get_type_refd_last()->get_typetype()) {
3926 case Type::T_CHOICE_T
:
3927 // These types may have qualified attributes
3929 case Type::T_SEQOF
: case Type::T_SETOF
:
3932 w_attrib_path
->chk_no_qualif();
3936 type
->set_genname(_T_
, get_genname());
3938 Type
*t
= type
->get_type_refd_last();
3939 switch (t
->get_typetype()) {
3941 error("Type of template module parameter cannot be port type `%s'",
3942 t
->get_fullname().c_str());
3944 case Type::T_SIGNATURE
:
3945 error("Type of template module parameter cannot be signature `%s'",
3946 t
->get_fullname().c_str());
3948 case Type::T_FUNCTION
:
3949 case Type::T_ALTSTEP
:
3950 case Type::T_TESTCASE
:
3951 if (t
->get_fat_runs_on_self()) {
3952 error("Type of template module parameter cannot be of function reference type"
3953 " `%s' which has runs on self clause", t
->get_fullname().c_str());
3957 if (has_implicit_omit_attr()) {
3958 error("Implicit omit not supported for template module parameters");
3964 Error_Context
cntxt2(def_template
, "In default template");
3965 def_template
->set_my_governor(type
);
3966 def_template
->flatten(false);
3967 if (def_template
->get_templatetype() == Template::CSTR_PATTERN
&&
3968 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
3969 def_template
->set_templatetype(Template::USTR_PATTERN
);
3970 def_template
->get_ustr_pattern()->set_pattern_type(
3971 PatternString::USTR_PATTERN
);
3973 type
->chk_this_template_ref(def_template
);
3975 type
->chk_this_template_generic(def_template
, INCOMPLETE_ALLOWED
,
3976 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, has_implicit_omit_attr() ? IMPLICIT_OMIT
: NOT_IMPLICIT_OMIT
, 0);
3977 if (!semantic_check_only
) {
3978 def_template
->set_genname_prefix("modulepar_");
3979 def_template
->set_genname_recursive(get_genname());
3980 def_template
->set_code_section(GovernedSimple::CS_PRE_INIT
);
3982 } else checked
= true;
3988 void Def_Modulepar_Template::generate_code(output_struct
*target
, bool)
3990 type
->generate_code(target
);
3992 Code::init_cdef(&cdef
);
3993 const string
& t_genname
= get_genname();
3994 const char *name
= t_genname
.c_str();
3995 type
->generate_code_object(&cdef
, my_scope
, t_genname
, "modulepar_", true);
3997 cdef
.init
= update_location_object(cdef
.init
);
3998 cdef
.init
= def_template
->generate_code_init(cdef
.init
, def_template
->get_lhs_name().c_str());
4000 Code::merge_cdef(target
, &cdef
);
4001 Code::free_cdef(&cdef
);
4003 if (has_implicit_omit_attr()) {
4004 FATAL_ERROR("Def_Modulepar_Template::generate_code()");
4007 const char *dispname
= id
->get_dispname().c_str();
4008 target
->functions
.set_param
= mputprintf(target
->functions
.set_param
,
4009 "if (!strcmp(par_name, \"%s\")) {\n"
4010 "modulepar_%s.set_param(param);\n"
4012 "} else ", dispname
, name
);
4013 target
->functions
.get_param
= mputprintf(target
->functions
.get_param
,
4014 "if (!strcmp(par_name, \"%s\")) {\n"
4015 "return modulepar_%s.get_param(param_name);\n"
4016 "} else ", dispname
, name
);
4018 if (target
->functions
.log_param
) {
4019 // this is not the first modulepar
4020 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
4021 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname
);
4023 // this is the first modulepar
4024 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
4025 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname
);
4027 target
->functions
.log_param
= mputprintf(target
->functions
.log_param
,
4028 "%s.log();\n", name
);
4031 void Def_Modulepar_Template::generate_code(Common::CodeGenHelper
& cgh
) {
4032 // module parameter definitions always go to its containing module
4033 generate_code(cgh
.get_current_outputstruct());
4036 void Def_Modulepar_Template::dump_internal(unsigned level
) const
4038 DEBUG(level
, "Module parameter: %s @ %p", id
->get_dispname().c_str(), (const void*)this);
4039 type
->dump(level
+ 1);
4040 if (def_template
) def_template
->dump(level
+ 1);
4041 else DEBUG(level
+ 1, "No default template");
4044 // =================================
4045 // ===== Def_Template
4046 // =================================
4048 Def_Template::Def_Template(template_restriction_t p_template_restriction
,
4049 Identifier
*p_id
, Type
*p_type
, FormalParList
*p_fpl
,
4050 Reference
*p_derived_ref
, Template
*p_body
)
4051 : Definition(A_TEMPLATE
, p_id
), type(p_type
), fp_list(p_fpl
),
4052 derived_ref(p_derived_ref
), base_template(0), recurs_deriv_checked(false),
4053 body(p_body
), template_restriction(p_template_restriction
),
4054 gen_restriction_check(false)
4056 if (!p_type
|| !p_body
) FATAL_ERROR("Ttcn::Def_Template::Def_Template()");
4057 type
->set_ownertype(Type::OT_TEMPLATE_DEF
, this);
4058 if (fp_list
) fp_list
->set_my_def(this);
4061 Def_Template::~Def_Template()
4069 Def_Template
*Def_Template::clone() const
4071 FATAL_ERROR("Def_Template::clone");
4074 void Def_Template::set_fullname(const string
& p_fullname
)
4076 Definition::set_fullname(p_fullname
);
4077 type
->set_fullname(p_fullname
+ ".<type>");
4078 if (fp_list
) fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
4080 derived_ref
->set_fullname(p_fullname
+ ".<derived_reference>");
4081 body
->set_fullname(p_fullname
);
4084 void Def_Template::set_my_scope(Scope
*p_scope
)
4086 bridgeScope
.set_parent_scope(p_scope
);
4087 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
4089 Definition::set_my_scope(&bridgeScope
);
4090 type
->set_my_scope(&bridgeScope
);
4091 if (derived_ref
) derived_ref
->set_my_scope(&bridgeScope
);
4093 fp_list
->set_my_scope(&bridgeScope
);
4094 body
->set_my_scope(fp_list
);
4095 } else body
->set_my_scope(&bridgeScope
);
4098 Setting
*Def_Template::get_Setting()
4100 return get_Template();
4103 Type
*Def_Template::get_Type()
4105 if (!checked
) chk();
4109 Template
*Def_Template::get_Template()
4111 if (!checked
) chk();
4115 FormalParList
*Def_Template::get_FormalParList()
4117 if (!checked
) chk();
4121 void Def_Template::chk()
4123 if (checked
) return;
4124 Error_Context
cntxt(this, "In template definition `%s'",
4125 id
->get_dispname().c_str());
4126 const string
& t_genname
= get_genname();
4127 type
->set_genname(_T_
, t_genname
);
4129 if (w_attrib_path
) {
4130 w_attrib_path
->chk_global_attrib(true);
4131 switch (type
->get_type_refd_last()->get_typetype_ttcn3()) {
4134 case Type::T_CHOICE_T
:
4135 // These types may have qualified attributes
4137 case Type::T_SEQOF
: case Type::T_SETOF
:
4140 w_attrib_path
->chk_no_qualif();
4146 fp_list
->chk(asstype
);
4147 if (local_scope
) error("Parameterized local template `%s' not supported",
4148 id
->get_dispname().c_str());
4151 // Merge the elements of "all from" into the list
4152 body
->flatten(false);
4154 body
->set_my_governor(type
);
4156 if (body
->get_templatetype() == Template::CSTR_PATTERN
&&
4157 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
4158 body
->set_templatetype(Template::USTR_PATTERN
);
4159 body
->get_ustr_pattern()->set_pattern_type(PatternString::USTR_PATTERN
);
4162 type
->chk_this_template_ref(body
);
4164 Type
*t
= type
->get_type_refd_last();
4165 if (t
->get_typetype() == Type::T_PORT
) {
4166 error("Template cannot be defined for port type `%s'",
4167 t
->get_fullname().c_str());
4170 chk_recursive_derivation();
4171 type
->chk_this_template_generic(body
, INCOMPLETE_ALLOWED
, OMIT_ALLOWED
,
4172 ANY_OR_OMIT_ALLOWED
, SUB_CHK
,
4173 has_implicit_omit_attr() ? IMPLICIT_OMIT
: NOT_IMPLICIT_OMIT
, 0);
4175 chk_erroneous_attr();
4176 if (erroneous_attrs
) body
->set_err_descr(erroneous_attrs
->get_err_descr());
4179 ReferenceChain
refch(type
, "While checking embedded recursions");
4180 body
->chk_recursions(refch
);
4182 if (template_restriction
!=TR_NONE
) {
4183 Error_Context
ec(this, "While checking template restriction `%s'",
4184 Template::get_restriction_name(template_restriction
));
4185 gen_restriction_check
=
4186 body
->chk_restriction("template definition", template_restriction
, body
);
4187 if (fp_list
&& template_restriction
!=TR_PRESENT
) {
4188 size_t nof_fps
= fp_list
->get_nof_fps();
4189 for (size_t i
=0; i
<nof_fps
; i
++) {
4190 FormalPar
* fp
= fp_list
->get_fp_byIndex(i
);
4191 // if formal par is not template then skip restriction checking,
4192 // templates can have only `in' parameters
4193 if (fp
->get_asstype()!=A_PAR_TEMPL_IN
) continue;
4194 template_restriction_t fp_tr
= fp
->get_template_restriction();
4195 switch (template_restriction
) {
4204 fp
->error("Formal parameter with template restriction `%s' "
4205 "not allowed here", Template::get_restriction_name(fp_tr
));
4208 fp
->error("Formal parameter without template restriction "
4209 "not allowed here");
4212 FATAL_ERROR("Ttcn::Def_Template::chk()");
4216 FATAL_ERROR("Ttcn::Def_Template::chk()");
4221 if (!semantic_check_only
) {
4222 if (fp_list
) fp_list
->set_genname(t_genname
);
4223 body
->set_genname_prefix("template_");
4224 body
->set_genname_recursive(t_genname
);
4225 body
->set_code_section(fp_list
? GovernedSimple::CS_INLINE
:
4226 GovernedSimple::CS_POST_INIT
);
4231 void Def_Template::chk_default() const
4233 if (!fp_list
) FATAL_ERROR("Def_Template::chk_default()");
4235 if (fp_list
->has_notused_defval())
4236 fp_list
->error("Only modified templates are allowed to use the not "
4237 "used symbol (`-') as the default parameter");
4240 Common::Assignment
*ass
= derived_ref
->get_refd_assignment(false);
4241 if (!ass
|| ass
->get_asstype() != A_TEMPLATE
) return; // Work locally.
4242 Def_Template
*base
= dynamic_cast<Def_Template
*>(ass
);
4243 if (!base
) FATAL_ERROR("Def_Template::chk_default()");
4244 FormalParList
*base_fpl
= base
->get_FormalParList();
4245 size_t nof_base_fps
= base_fpl
? base_fpl
->get_nof_fps() : 0;
4246 size_t nof_local_fps
= fp_list
? fp_list
->get_nof_fps() : 0;
4247 size_t min_fps
= nof_base_fps
;
4248 if (nof_local_fps
< nof_base_fps
) min_fps
= nof_local_fps
;
4249 for (size_t i
= 0; i
< min_fps
; i
++) {
4250 FormalPar
*base_fp
= base_fpl
->get_fp_byIndex(i
);
4251 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4252 if (local_fp
->has_notused_defval()) {
4253 if (base_fp
->has_defval()) {
4254 local_fp
->set_defval(base_fp
->get_defval());
4256 local_fp
->error("Not used symbol (`-') doesn't have the "
4257 "corresponding default parameter in the "
4262 // Additional parameters in the derived template with using the not used
4263 // symbol. TODO: Merge the loops.
4264 for (size_t i
= nof_base_fps
; i
< nof_local_fps
; i
++) {
4265 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4266 if (local_fp
->has_notused_defval())
4267 local_fp
->error("Not used symbol (`-') doesn't have the "
4268 "corresponding default parameter in the "
4273 void Def_Template::chk_modified()
4275 if (!derived_ref
) return;
4276 // Do not check the (non-existent) actual parameter list of the derived
4277 // reference against the formal parameter list of the base template.
4278 // According to TTCN-3 syntax the derived reference cannot have parameters
4279 // even if the base template is parameterized.
4280 Common::Assignment
*ass
= derived_ref
->get_refd_assignment(false);
4281 // Checking the existence and type compatibility of the base template.
4283 if (ass
->get_asstype() != A_TEMPLATE
) {
4284 derived_ref
->error("Reference to a template was expected in the "
4285 "`modifies' definition instead of %s",
4286 ass
->get_description().c_str());
4289 base_template
= dynamic_cast<Def_Template
*>(ass
);
4290 if (!base_template
) FATAL_ERROR("Def_Template::chk_modified()");
4291 Type
*base_type
= base_template
->get_Type();
4292 TypeCompatInfo
info_base(my_scope
->get_scope_mod(), type
, base_type
, true,
4294 TypeChain l_chain_base
;
4295 TypeChain r_chain_base
;
4296 if (!type
->is_compatible(base_type
, &info_base
, &l_chain_base
,
4298 if (info_base
.is_subtype_error()) {
4299 type
->error("%s", info_base
.get_subtype_error().c_str());
4301 if (!info_base
.is_erroneous()) {
4302 type
->error("The modified template has different type than base "
4303 "template `%s': `%s' was expected instead of `%s'",
4304 ass
->get_fullname().c_str(),
4305 base_type
->get_typename().c_str(),
4306 type
->get_typename().c_str());
4308 // Always use the format string.
4309 type
->error("%s", info_base
.get_error_str_str().c_str());
4312 if (info_base
.needs_conversion())
4313 body
->set_needs_conversion();
4315 // Check for restriction.
4316 if (Template::is_less_restrictive(base_template
->get_template_restriction(),
4317 template_restriction
)) {
4318 error("The template restriction is not the same or more "
4319 "restrictive as of base template `%s'", ass
->get_fullname().c_str());
4321 // Checking formal parameter lists.
4322 FormalParList
*base_fpl
= base_template
->get_FormalParList();
4323 size_t nof_base_fps
= base_fpl
? base_fpl
->get_nof_fps() : 0;
4324 size_t nof_local_fps
= fp_list
? fp_list
->get_nof_fps() : 0;
4326 if (nof_local_fps
< nof_base_fps
) {
4327 error("The modified template has fewer formal parameters than base "
4328 "template `%s': at least %lu parameter%s expected instead of %lu",
4329 ass
->get_fullname().c_str(), (unsigned long)nof_base_fps
,
4330 nof_base_fps
> 1 ? "s were" : " was", (unsigned long)nof_local_fps
);
4331 min_fps
= nof_local_fps
;
4332 } else min_fps
= nof_base_fps
;
4334 for (size_t i
= 0; i
< min_fps
; i
++) {
4335 FormalPar
*base_fp
= base_fpl
->get_fp_byIndex(i
);
4336 FormalPar
*local_fp
= fp_list
->get_fp_byIndex(i
);
4337 Error_Context
cntxt(local_fp
, "In formal parameter #%lu",
4338 (unsigned long)(i
+ 1));
4339 // Check for parameter kind equivalence (value or template).
4340 if (base_fp
->get_asstype() != local_fp
->get_asstype())
4341 local_fp
->error("The kind of parameter is not the same as in base "
4342 "template `%s': %s was expected instead of %s",
4343 ass
->get_fullname().c_str(), base_fp
->get_assname(),
4344 local_fp
->get_assname());
4345 // Check for type compatibility.
4346 Type
*base_fp_type
= base_fp
->get_Type();
4347 Type
*local_fp_type
= local_fp
->get_Type();
4348 TypeCompatInfo
info_par(my_scope
->get_scope_mod(), base_fp_type
,
4349 local_fp_type
, true, false);
4350 TypeChain l_chain_par
;
4351 TypeChain r_chain_par
;
4352 if (!base_fp_type
->is_compatible(local_fp_type
, &info_par
, &l_chain_par
,
4354 if (info_par
.is_subtype_error()) {
4355 local_fp_type
->error("%s", info_par
.get_subtype_error().c_str());
4357 if (!info_par
.is_erroneous()) {
4358 local_fp_type
->error("The type of parameter is not the same as in "
4359 "base template `%s': `%s' was expected instead "
4361 ass
->get_fullname().c_str(),
4362 base_fp_type
->get_typename().c_str(),
4363 local_fp_type
->get_typename().c_str());
4365 local_fp_type
->error("%s", info_par
.get_error_str_str().c_str());
4368 if (info_par
.needs_conversion())
4369 body
->set_needs_conversion();
4371 // Check for name equivalence.
4372 const Identifier
& base_fp_id
= base_fp
->get_id();
4373 const Identifier
& local_fp_id
= local_fp
->get_id();
4374 if (!(base_fp_id
== local_fp_id
))
4375 local_fp
->error("The name of parameter is not the same as in base "
4376 "template `%s': `%s' was expected instead of `%s'",
4377 ass
->get_fullname().c_str(),
4378 base_fp_id
.get_dispname().c_str(),
4379 local_fp_id
.get_dispname().c_str());
4380 // Check for restrictions: the derived must be same or more restrictive.
4381 if (base_fp
->get_asstype()==local_fp
->get_asstype() &&
4382 Template::is_less_restrictive(base_fp
->get_template_restriction(),
4383 local_fp
->get_template_restriction())) {
4384 local_fp
->error("The restriction of parameter is not the same or more "
4385 "restrictive as in base template `%s'", ass
->get_fullname().c_str());
4388 // Set the pointer to the body of base template.
4389 body
->set_base_template(base_template
->get_Template());
4392 void Def_Template::chk_recursive_derivation()
4394 if (recurs_deriv_checked
) return;
4395 if (base_template
) {
4396 ReferenceChain
refch(this, "While checking the chain of base templates");
4397 refch
.add(get_fullname());
4398 for (Def_Template
*iter
= base_template
; iter
; iter
= iter
->base_template
)
4400 if (iter
->recurs_deriv_checked
) break;
4401 else if (refch
.add(iter
->get_fullname()))
4402 iter
->recurs_deriv_checked
= true;
4406 recurs_deriv_checked
= true;
4409 void Def_Template::generate_code(output_struct
*target
, bool)
4411 type
->generate_code(target
);
4413 // Parameterized template. Generate code for a function which returns
4414 // a $(genname)_template and has the appropriate parameters.
4415 const string
& t_genname
= get_genname();
4416 const char *template_name
= t_genname
.c_str();
4417 const char *template_dispname
= id
->get_dispname().c_str();
4418 const string
& type_genname
= type
->get_genname_template(my_scope
);
4419 const char *type_genname_str
= type_genname
.c_str();
4421 // assemble the function body first (this also determines which parameters
4423 size_t nof_base_pars
= 0;
4424 char* function_body
= create_location_object(memptystr(), "TEMPLATE",
4426 if (debugger_active
) {
4427 function_body
= generate_code_debugger_function_init(function_body
, this);
4429 if (base_template
) {
4430 // modified template
4431 function_body
= mputprintf(function_body
, "%s ret_val(%s",
4433 base_template
->get_genname_from_scope(my_scope
).c_str());
4434 if (base_template
->fp_list
) {
4435 // the base template is also parameterized
4436 function_body
= mputc(function_body
, '(');
4437 nof_base_pars
= base_template
->fp_list
->get_nof_fps();
4438 for (size_t i
= 0; i
< nof_base_pars
; i
++) {
4439 if (i
> 0) function_body
= mputstr(function_body
, ", ");
4440 function_body
= mputstr(function_body
,
4441 fp_list
->get_fp_byIndex(i
)->get_id().get_name().c_str());
4443 function_body
= mputc(function_body
, ')');
4445 function_body
= mputstr(function_body
, ");\n");
4448 function_body
= mputprintf(function_body
, "%s ret_val;\n",
4451 if (erroneous_attrs
&& erroneous_attrs
->get_err_descr()) {
4452 function_body
= erroneous_attrs
->get_err_descr()->
4453 generate_code_str(function_body
, target
->header
.global_vars
, string("ret_val"), true);
4455 function_body
= body
->generate_code_init(function_body
, "ret_val");
4456 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4457 function_body
= Template::generate_restriction_check_code(function_body
,
4458 "ret_val", template_restriction
);
4459 if (debugger_active
) {
4460 function_body
= mputstr(function_body
,
4461 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
4462 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
4464 function_body
= mputstr(function_body
, "return ret_val;\n");
4465 // if the template modifies a parameterized template, then the inherited
4466 // formal parameters must always be displayed, otherwise generate a smart
4467 // formal parameter list (where the names of unused parameters are omitted)
4468 char *formal_par_list
= fp_list
->generate_code(memptystr(), nof_base_pars
);
4469 fp_list
->generate_code_defval(target
);
4471 target
->header
.function_prototypes
=
4472 mputprintf(target
->header
.function_prototypes
,
4473 "extern %s %s(%s);\n",
4474 type_genname_str
, template_name
, formal_par_list
);
4475 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
4479 "}\n\n", type_genname_str
, template_name
, formal_par_list
, function_body
);
4480 Free(formal_par_list
);
4481 Free(function_body
);
4483 // non-parameterized template
4485 Code::init_cdef(&cdef
);
4486 type
->generate_code_object(&cdef
, body
);
4487 cdef
.init
= update_location_object(cdef
.init
);
4488 if (base_template
) {
4489 // modified template
4490 if (base_template
->my_scope
->get_scope_mod_gen() ==
4491 my_scope
->get_scope_mod_gen()) {
4492 // if the base template is in the same module its body has to be
4493 // initialized first
4494 cdef
.init
= base_template
->body
->generate_code_init(cdef
.init
,
4495 base_template
->body
->get_lhs_name().c_str());
4497 if (use_runtime_2
&& body
->get_needs_conversion()) {
4498 Type
*body_type
= body
->get_my_governor()->get_type_refd_last();
4499 Type
*base_type
= base_template
->body
->get_my_governor()
4500 ->get_type_refd_last();
4501 if (!body_type
|| !base_type
)
4502 FATAL_ERROR("Def_Template::generate_code()");
4503 const string
& tmp_id
= body
->get_temporary_id();
4504 const char *tmp_id_str
= tmp_id
.c_str();
4505 // base template initialization
4506 cdef
.init
= mputprintf(cdef
.init
,
4508 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4509 "and `%s' are not compatible at run-time\");\n"
4511 body_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
4512 TypeConv::get_conv_func(base_type
, body_type
, my_scope
4513 ->get_scope_mod()).c_str(), tmp_id_str
, base_template
4514 ->get_genname_from_scope(my_scope
).c_str(), base_type
4515 ->get_typename().c_str(), body_type
->get_typename().c_str(),
4516 body
->get_lhs_name().c_str(), tmp_id_str
);
4518 cdef
.init
= mputprintf(cdef
.init
, "%s = %s;\n",
4519 body
->get_lhs_name().c_str(),
4520 base_template
->get_genname_from_scope(my_scope
).c_str());
4523 if (use_runtime_2
&& TypeConv::needs_conv_refd(body
))
4524 cdef
.init
= TypeConv::gen_conv_code_refd(cdef
.init
,
4525 body
->get_lhs_name().c_str(), body
);
4527 cdef
.init
= body
->generate_code_init(cdef
.init
,
4528 body
->get_lhs_name().c_str());
4529 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
4530 cdef
.init
= Template::generate_restriction_check_code(cdef
.init
,
4531 body
->get_lhs_name().c_str(), template_restriction
);
4532 target
->header
.global_vars
= mputstr(target
->header
.global_vars
,
4534 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
4536 target
->functions
.post_init
= mputstr(target
->functions
.post_init
,
4538 Code::free_cdef(&cdef
);
4542 void Def_Template::generate_code(Common::CodeGenHelper
& cgh
) {
4543 generate_code(cgh
.get_outputstruct(this));
4546 char *Def_Template::generate_code_str(char *str
)
4548 const string
& t_genname
= get_genname();
4549 const char *genname_str
= t_genname
.c_str();
4550 const string
& type_genname
= type
->get_genname_template(my_scope
);
4551 const char *type_genname_str
= type_genname
.c_str();
4553 const char *dispname_str
= id
->get_dispname().c_str();
4554 NOTSUPP("Code generation for parameterized local template `%s'",
4556 str
= mputprintf(str
, "/* NOT SUPPORTED: template %s */\n",
4559 if (base_template
) {
4560 // non-parameterized modified template
4561 if (use_runtime_2
&& body
->get_needs_conversion()) {
4562 Type
*body_type
= body
->get_my_governor()->get_type_refd_last();
4563 Type
*base_type
= base_template
->body
->get_my_governor()
4564 ->get_type_refd_last();
4565 if (!body_type
|| !base_type
)
4566 FATAL_ERROR("Def_Template::generate_code_str()");
4567 const string
& tmp_id
= body
->get_temporary_id();
4568 const char *tmp_id_str
= tmp_id
.c_str();
4569 str
= mputprintf(str
,
4571 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4572 "and `%s' are not compatible at run-time\");\n"
4574 body_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
4575 TypeConv::get_conv_func(base_type
, body_type
, my_scope
4576 ->get_scope_mod()).c_str(), tmp_id_str
, base_template
4577 ->get_genname_from_scope(my_scope
).c_str(), base_type
4578 ->get_typename().c_str(), body_type
->get_typename().c_str(),
4579 type_genname_str
, genname_str
, tmp_id_str
);
4581 // the object is initialized from the base template by the
4583 str
= mputprintf(str
, "%s %s(%s);\n", type_genname_str
, genname_str
,
4584 base_template
->get_genname_from_scope(my_scope
).c_str());
4586 // the modified body is assigned in the subsequent statements
4587 str
= body
->generate_code_init(str
, genname_str
);
4589 // non-parameterized non-modified template
4590 if (body
->has_single_expr()) {
4591 // the object is initialized by the constructor
4592 str
= mputprintf(str
, "%s %s(%s);\n", type_genname_str
,
4593 genname_str
, body
->get_single_expr(false).c_str());
4594 // make sure the template's code is not generated twice (TR: HU56425)
4595 body
->set_code_generated();
4597 // the default constructor is used
4598 str
= mputprintf(str
, "%s %s;\n", type_genname_str
, genname_str
);
4599 // the body is assigned in the subsequent statements
4600 str
= body
->generate_code_init(str
, genname_str
);
4603 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
4604 str
= Template::generate_restriction_check_code(str
, genname_str
,
4605 template_restriction
);
4607 if (debugger_active
) {
4608 str
= generate_code_debugger_add_var(str
, this);
4613 void Def_Template::ilt_generate_code(ILT
*ilt
)
4615 const string
& t_genname
= get_genname();
4616 const char *genname_str
= t_genname
.c_str();
4617 char*& def
=ilt
->get_out_def();
4618 char*& init
=ilt
->get_out_branches();
4620 const char *dispname_str
= id
->get_dispname().c_str();
4621 NOTSUPP("Code generation for parameterized local template `%s'",
4623 def
= mputprintf(def
, "/* NOT SUPPORTED: template %s */\n", dispname_str
);
4624 init
= mputprintf(init
, "/* NOT SUPPORTED: template %s */\n",
4627 // non-parameterized template
4628 // use the default constructor for initialization
4629 def
= mputprintf(def
, "%s %s;\n",
4630 type
->get_genname_template(my_scope
).c_str(), genname_str
);
4631 if (base_template
) {
4632 // copy the base template with an assignment
4633 init
= mputprintf(init
, "%s = %s;\n", genname_str
,
4634 base_template
->get_genname_from_scope(my_scope
).c_str());
4636 // finally assign the body
4637 init
= body
->generate_code_init(init
, genname_str
);
4638 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
4639 init
= Template::generate_restriction_check_code(init
, genname_str
,
4640 template_restriction
);
4644 void Def_Template::dump_internal(unsigned level
) const
4646 DEBUG(level
, "Template: %s", id
->get_dispname().c_str());
4647 if (fp_list
) fp_list
->dump(level
+ 1);
4649 DEBUG(level
+ 1, "modifies: %s", derived_ref
->get_dispname().c_str());
4650 if (template_restriction
!=TR_NONE
)
4651 DEBUG(level
+ 1, "restriction: %s",
4652 Template::get_restriction_name(template_restriction
));
4653 type
->dump(level
+ 1);
4654 body
->dump(level
+ 1);
4657 // =================================
4659 // =================================
4661 Def_Var::Def_Var(Identifier
*p_id
, Type
*p_type
, Value
*p_initial_value
)
4662 : Definition(A_VAR
, p_id
), type(p_type
), initial_value(p_initial_value
)
4664 if (!p_type
) FATAL_ERROR("Ttcn::Def_Var::Def_Var()");
4665 type
->set_ownertype(Type::OT_VAR_DEF
, this);
4671 delete initial_value
;
4674 Def_Var
*Def_Var::clone() const
4676 FATAL_ERROR("Def_Var::clone");
4679 void Def_Var::set_fullname(const string
& p_fullname
)
4681 Definition::set_fullname(p_fullname
);
4682 type
->set_fullname(p_fullname
+ ".<type>");
4684 initial_value
->set_fullname(p_fullname
+ ".<initial_value>");
4687 void Def_Var::set_my_scope(Scope
*p_scope
)
4689 Definition::set_my_scope(p_scope
);
4690 type
->set_my_scope(p_scope
);
4691 if (initial_value
) initial_value
->set_my_scope(p_scope
);
4694 Type
*Def_Var::get_Type()
4703 Error_Context
cntxt(this, "In variable definition `%s'",
4704 id
->get_dispname().c_str());
4705 type
->set_genname(_T_
, get_genname());
4708 Type
*t
= type
->get_type_refd_last();
4709 switch (t
->get_typetype()) {
4711 error("Variable cannot be defined for port type `%s'",
4712 t
->get_fullname().c_str());
4714 case Type::T_SIGNATURE
:
4715 error("Variable cannot be defined for signature `%s'",
4716 t
->get_fullname().c_str());
4719 if (initial_value
) {
4720 initial_value
->set_my_governor(type
);
4721 type
->chk_this_value_ref(initial_value
);
4722 type
->chk_this_value(initial_value
, this, is_local() ?
4723 Type::EXPECTED_DYNAMIC_VALUE
: Type::EXPECTED_STATIC_VALUE
,
4724 INCOMPLETE_ALLOWED
, OMIT_NOT_ALLOWED
, SUB_CHK
);
4725 if (!semantic_check_only
) {
4726 initial_value
->set_genname_recursive(get_genname());
4727 initial_value
->set_code_section(GovernedSimple::CS_INLINE
);
4733 if (w_attrib_path
) {
4734 w_attrib_path
->chk_global_attrib();
4735 w_attrib_path
->chk_no_qualif();
4739 bool Def_Var::chk_identical(Definition
*p_def
)
4743 if (p_def
->get_asstype() != A_VAR
) {
4744 const char *dispname_str
= id
->get_dispname().c_str();
4745 error("Local definition `%s' is a variable, but the definition "
4746 "inherited from component type `%s' is a %s", dispname_str
,
4747 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
4748 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
4751 Def_Var
*p_def_var
= dynamic_cast<Def_Var
*>(p_def
);
4752 if (!p_def_var
) FATAL_ERROR("Def_Var::chk_identical()");
4753 if (!type
->is_identical(p_def_var
->type
)) {
4754 const char *dispname_str
= id
->get_dispname().c_str();
4755 type
->error("Local variable `%s' has type `%s', but the variable "
4756 "inherited from component type `%s' has type `%s'", dispname_str
,
4757 type
->get_typename().c_str(),
4758 p_def_var
->get_my_scope()->get_fullname().c_str(),
4759 p_def_var
->type
->get_typename().c_str());
4760 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4763 if (initial_value
) {
4764 if (p_def_var
->initial_value
) {
4765 if (!initial_value
->is_unfoldable() &&
4766 !p_def_var
->initial_value
->is_unfoldable() &&
4767 !(*initial_value
== *p_def_var
->initial_value
)) {
4768 const char *dispname_str
= id
->get_dispname().c_str();
4769 initial_value
->warning("Local variable `%s' and the variable "
4770 "inherited from component type `%s' have different initial values",
4771 dispname_str
, p_def_var
->get_my_scope()->get_fullname().c_str());
4772 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4775 const char *dispname_str
= id
->get_dispname().c_str();
4776 initial_value
->warning("Local variable `%s' has initial value, but "
4777 "the variable inherited from component type `%s' does not",
4778 dispname_str
, p_def_var
->get_my_scope()->get_fullname().c_str());
4779 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4781 } else if (p_def_var
->initial_value
) {
4782 const char *dispname_str
= id
->get_dispname().c_str();
4783 warning("Local variable `%s' does not have initial value, but the "
4784 "variable inherited from component type `%s' has", dispname_str
,
4785 p_def_var
->get_my_scope()->get_fullname().c_str());
4786 p_def_var
->note("The inherited variable `%s' is here", dispname_str
);
4791 void Def_Var::generate_code(output_struct
*target
, bool clean_up
)
4793 type
->generate_code(target
);
4795 Code::init_cdef(&cdef
);
4796 type
->generate_code_object(&cdef
, my_scope
, get_genname(), 0, false);
4797 Code::merge_cdef(target
, &cdef
);
4798 Code::free_cdef(&cdef
);
4799 if (initial_value
) {
4800 target
->functions
.init_comp
=
4801 initial_value
->generate_code_init(target
->functions
.init_comp
,
4802 initial_value
->get_lhs_name().c_str());
4803 } else if (clean_up
) { // No initial value.
4804 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
4805 "%s.clean_up();\n", get_genname().c_str());
4809 void Def_Var::generate_code(CodeGenHelper
& cgh
)
4811 generate_code(cgh
.get_outputstruct(this));
4814 char *Def_Var::generate_code_str(char *str
)
4816 const string
& t_genname
= get_genname();
4817 const char *genname_str
= t_genname
.c_str();
4818 if (initial_value
&& initial_value
->has_single_expr()) {
4819 // the initial value can be represented by a single C++ expression
4820 // the object is initialized by the constructor
4821 str
= mputprintf(str
, "%s %s(%s);\n",
4822 type
->get_genname_value(my_scope
).c_str(), genname_str
,
4823 initial_value
->get_single_expr().c_str());
4825 // use the default constructor
4826 str
= mputprintf(str
, "%s %s;\n",
4827 type
->get_genname_value(my_scope
).c_str(), genname_str
);
4828 if (initial_value
) {
4829 // the initial value is assigned using subsequent statements
4830 str
= initial_value
->generate_code_init(str
, genname_str
);
4833 if (debugger_active
) {
4834 str
= generate_code_debugger_add_var(str
, this);
4839 void Def_Var::ilt_generate_code(ILT
*ilt
)
4841 const string
& t_genname
= get_genname();
4842 const char *genname_str
= t_genname
.c_str();
4843 char*& def
=ilt
->get_out_def();
4844 char*& init
=ilt
->get_out_branches();
4845 def
= mputprintf(def
, "%s %s;\n", type
->get_genname_value(my_scope
).c_str(),
4848 init
= initial_value
->generate_code_init(init
, genname_str
);
4851 char *Def_Var::generate_code_init_comp(char *str
, Definition
*base_defn
)
4853 if (initial_value
) {
4854 str
= initial_value
->generate_code_init(str
,
4855 base_defn
->get_genname_from_scope(my_scope
).c_str());
4860 void Def_Var::dump_internal(unsigned level
) const
4862 DEBUG(level
, "Variable %s", id
->get_dispname().c_str());
4863 type
->dump(level
+ 1);
4864 if (initial_value
) initial_value
->dump(level
+ 1);
4867 // =================================
4868 // ===== Def_Var_Template
4869 // =================================
4871 Def_Var_Template::Def_Var_Template(Identifier
*p_id
, Type
*p_type
,
4872 Template
*p_initial_value
, template_restriction_t p_template_restriction
)
4873 : Definition(A_VAR_TEMPLATE
, p_id
), type(p_type
),
4874 initial_value(p_initial_value
), template_restriction(p_template_restriction
)
4876 if (!p_type
) FATAL_ERROR("Ttcn::Def_Var_Template::Def_Var_Template()");
4877 type
->set_ownertype(Type::OT_VARTMPL_DEF
, this);
4880 Def_Var_Template::~Def_Var_Template()
4883 delete initial_value
;
4886 Def_Var_Template
*Def_Var_Template::clone() const
4888 FATAL_ERROR("Def_Var_Template::clone");
4891 void Def_Var_Template::set_fullname(const string
& p_fullname
)
4893 Definition::set_fullname(p_fullname
);
4894 type
->set_fullname(p_fullname
+ ".<type>");
4896 initial_value
->set_fullname(p_fullname
+ ".<initial_value>");
4899 void Def_Var_Template::set_my_scope(Scope
*p_scope
)
4901 Definition::set_my_scope(p_scope
);
4902 type
->set_my_scope(p_scope
);
4903 if (initial_value
) initial_value
->set_my_scope(p_scope
);
4906 Type
*Def_Var_Template::get_Type()
4912 void Def_Var_Template::chk()
4915 Error_Context
cntxt(this, "In template variable definition `%s'",
4916 id
->get_dispname().c_str());
4917 type
->set_genname(_T_
, get_genname());
4920 Type
*t
= type
->get_type_refd_last();
4921 if (t
->get_typetype() == Type::T_PORT
) {
4922 error("Template variable cannot be defined for port type `%s'",
4923 t
->get_fullname().c_str());
4926 if (initial_value
) {
4927 initial_value
->set_my_governor(type
);
4928 initial_value
->flatten(false);
4930 if (initial_value
->get_templatetype() == Template::CSTR_PATTERN
&&
4931 type
->get_type_refd_last()->get_typetype() == Type::T_USTR
) {
4932 initial_value
->set_templatetype(Template::USTR_PATTERN
);
4933 initial_value
->get_ustr_pattern()->set_pattern_type(
4934 PatternString::USTR_PATTERN
);
4937 type
->chk_this_template_ref(initial_value
);
4938 // temporary hack: to allow incomplete body as initial value
4939 // checking as a modified template, but without a base template
4940 type
->chk_this_template_generic(initial_value
, INCOMPLETE_ALLOWED
,
4941 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, IMPLICIT_OMIT
, 0);
4942 gen_restriction_check
=
4943 initial_value
->chk_restriction("template variable definition",
4944 template_restriction
, initial_value
);
4945 if (!semantic_check_only
) {
4946 initial_value
->set_genname_recursive(get_genname());
4947 initial_value
->set_code_section(GovernedSimple::CS_INLINE
);
4950 if (w_attrib_path
) {
4951 w_attrib_path
->chk_global_attrib();
4952 w_attrib_path
->chk_no_qualif();
4956 bool Def_Var_Template::chk_identical(Definition
*p_def
)
4960 if (p_def
->get_asstype() != A_VAR_TEMPLATE
) {
4961 const char *dispname_str
= id
->get_dispname().c_str();
4962 error("Local definition `%s' is a template variable, but the definition "
4963 "inherited from component type `%s' is a %s", dispname_str
,
4964 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
4965 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
4968 Def_Var_Template
*p_def_var_template
=
4969 dynamic_cast<Def_Var_Template
*>(p_def
);
4970 if (!p_def_var_template
) FATAL_ERROR("Def_Var_Template::chk_identical()");
4971 if (!type
->is_identical(p_def_var_template
->type
)) {
4972 const char *dispname_str
= id
->get_dispname().c_str();
4973 type
->error("Local template variable `%s' has type `%s', but the "
4974 "template variable inherited from component type `%s' has type `%s'",
4975 dispname_str
, type
->get_typename().c_str(),
4976 p_def_var_template
->get_my_scope()->get_fullname().c_str(),
4977 p_def_var_template
->type
->get_typename().c_str());
4978 p_def_var_template
->note("The inherited template variable `%s' is here",
4982 if (initial_value
) {
4983 if (!p_def_var_template
->initial_value
) {
4984 const char *dispname_str
= id
->get_dispname().c_str();
4985 initial_value
->warning("Local template variable `%s' has initial "
4986 "value, but the template variable inherited from component type "
4987 "`%s' does not", dispname_str
,
4988 p_def_var_template
->get_my_scope()->get_fullname().c_str());
4989 p_def_var_template
->note("The inherited template variable `%s' is here",
4992 } else if (p_def_var_template
->initial_value
) {
4993 const char *dispname_str
= id
->get_dispname().c_str();
4994 warning("Local template variable `%s' does not have initial value, but "
4995 "the template variable inherited from component type `%s' has",
4997 p_def_var_template
->get_my_scope()->get_fullname().c_str());
4998 p_def_var_template
->note("The inherited template variable `%s' is here",
5004 void Def_Var_Template::generate_code(output_struct
*target
, bool clean_up
)
5006 type
->generate_code(target
);
5008 Code::init_cdef(&cdef
);
5009 type
->generate_code_object(&cdef
, my_scope
, get_genname(), 0, true);
5010 Code::merge_cdef(target
, &cdef
);
5011 Code::free_cdef(&cdef
);
5012 if (initial_value
) {
5013 if (Common::Type::T_SEQOF
== initial_value
->get_my_governor()->get_typetype() ||
5014 Common::Type::T_ARRAY
== initial_value
->get_my_governor()->get_typetype()) {
5015 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5016 "%s.remove_all_permutations();\n", initial_value
->get_lhs_name().c_str());
5018 target
->functions
.init_comp
=
5019 initial_value
->generate_code_init(target
->functions
.init_comp
,
5020 initial_value
->get_lhs_name().c_str());
5021 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
5022 target
->functions
.init_comp
= Template::generate_restriction_check_code(
5023 target
->functions
.init_comp
, initial_value
->get_lhs_name().c_str(),
5024 template_restriction
);
5025 } else if (clean_up
) { // No initial value.
5026 // Always reset component variables/variable templates on component
5027 // reinitialization. Fix for HM79493.
5028 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5029 "%s.clean_up();\n", get_genname().c_str());
5033 void Def_Var_Template::generate_code(CodeGenHelper
& cgh
)
5035 generate_code(cgh
.get_outputstruct(this));
5038 char *Def_Var_Template::generate_code_str(char *str
)
5040 const string
& t_genname
= get_genname();
5041 const char *genname_str
= t_genname
.c_str();
5042 if (initial_value
&& initial_value
->has_single_expr()) {
5043 // The initial value can be represented by a single C++ expression
5044 // the object is initialized by the constructor.
5045 str
= mputprintf(str
, "%s %s(%s);\n",
5046 type
->get_genname_template(my_scope
).c_str(), genname_str
,
5047 initial_value
->get_single_expr(false).c_str());
5049 // Use the default constructor.
5050 str
= mputprintf(str
, "%s %s;\n",
5051 type
->get_genname_template(my_scope
).c_str(), genname_str
);
5052 if (initial_value
) {
5053 // The initial value is assigned using subsequent statements.
5054 if (use_runtime_2
&& TypeConv::needs_conv_refd(initial_value
))
5055 str
= TypeConv::gen_conv_code_refd(str
, genname_str
, initial_value
);
5056 else str
= initial_value
->generate_code_init(str
, genname_str
);
5059 if (initial_value
&& template_restriction
!= TR_NONE
5060 && gen_restriction_check
)
5061 str
= Template::generate_restriction_check_code(str
, genname_str
,
5062 template_restriction
);
5063 if (debugger_active
) {
5064 str
= generate_code_debugger_add_var(str
, this);
5069 void Def_Var_Template::ilt_generate_code(ILT
*ilt
)
5071 const string
& t_genname
= get_genname();
5072 const char *genname_str
= t_genname
.c_str();
5073 char*& def
=ilt
->get_out_def();
5074 char*& init
=ilt
->get_out_branches();
5075 def
= mputprintf(def
, "%s %s;\n",
5076 type
->get_genname_template(my_scope
).c_str(), genname_str
);
5077 if (initial_value
) {
5078 init
= initial_value
->generate_code_init(init
, genname_str
);
5079 if (template_restriction
!=TR_NONE
&& gen_restriction_check
)
5080 init
= Template::generate_restriction_check_code(init
, genname_str
,
5081 template_restriction
);
5085 char *Def_Var_Template::generate_code_init_comp(char *str
,
5086 Definition
*base_defn
)
5088 if (initial_value
) {
5089 str
= initial_value
->generate_code_init(str
,
5090 base_defn
->get_genname_from_scope(my_scope
).c_str());
5091 if (template_restriction
!= TR_NONE
&& gen_restriction_check
)
5092 str
= Template::generate_restriction_check_code(str
,
5093 base_defn
->get_genname_from_scope(my_scope
).c_str(),
5094 template_restriction
);
5099 void Def_Var_Template::dump_internal(unsigned level
) const
5101 DEBUG(level
, "Template variable %s", id
->get_dispname().c_str());
5102 if (template_restriction
!=TR_NONE
)
5103 DEBUG(level
+ 1, "restriction: %s",
5104 Template::get_restriction_name(template_restriction
));
5105 type
->dump(level
+ 1);
5106 if (initial_value
) initial_value
->dump(level
+ 1);
5109 // =================================
5111 // =================================
5113 Def_Timer::~Def_Timer()
5116 delete default_duration
;
5119 Def_Timer
*Def_Timer::clone() const
5121 FATAL_ERROR("Def_Timer::clone");
5124 void Def_Timer::set_fullname(const string
& p_fullname
)
5126 Definition::set_fullname(p_fullname
);
5127 if (dimensions
) dimensions
->set_fullname(p_fullname
+ ".<dimensions>");
5128 if (default_duration
)
5129 default_duration
->set_fullname(p_fullname
+ ".<default_duration>");
5132 void Def_Timer::set_my_scope(Scope
*p_scope
)
5134 Definition::set_my_scope(p_scope
);
5135 if (dimensions
) dimensions
->set_my_scope(p_scope
);
5136 if (default_duration
) default_duration
->set_my_scope(p_scope
);
5139 ArrayDimensions
*Def_Timer::get_Dimensions()
5141 if (!checked
) chk();
5145 void Def_Timer::chk()
5148 Error_Context
cntxt(this, "In timer definition `%s'",
5149 id
->get_dispname().c_str());
5150 if (dimensions
) dimensions
->chk();
5151 if (default_duration
) {
5152 Error_Context
cntxt2(default_duration
, "In default duration");
5153 if (dimensions
) chk_array_duration(default_duration
);
5154 else chk_single_duration(default_duration
);
5155 if (!semantic_check_only
) {
5156 default_duration
->set_code_section(GovernedSimple::CS_POST_INIT
);
5160 if (w_attrib_path
) {
5161 w_attrib_path
->chk_global_attrib();
5162 w_attrib_path
->chk_no_qualif();
5166 bool Def_Timer::chk_identical(Definition
*p_def
)
5170 if (p_def
->get_asstype() != A_TIMER
) {
5171 const char *dispname_str
= id
->get_dispname().c_str();
5172 error("Local definition `%s' is a timer, but the definition inherited "
5173 "from component type `%s' is a %s", dispname_str
,
5174 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
5175 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
5178 Def_Timer
*p_def_timer
= dynamic_cast<Def_Timer
*>(p_def
);
5179 if (!p_def_timer
) FATAL_ERROR("Def_Timer::chk_identical()");
5181 if (p_def_timer
->dimensions
) {
5182 if (!dimensions
->is_identical(p_def_timer
->dimensions
)) {
5183 const char *dispname_str
= id
->get_dispname().c_str();
5184 error("Local timer `%s' and the timer inherited from component type "
5185 "`%s' have different array dimensions", dispname_str
,
5186 p_def_timer
->get_my_scope()->get_fullname().c_str());
5187 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5191 const char *dispname_str
= id
->get_dispname().c_str();
5192 error("Local definition `%s' is a timer array, but the definition "
5193 "inherited from component type `%s' is a single timer", dispname_str
,
5194 p_def_timer
->get_my_scope()->get_fullname().c_str());
5195 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5198 } else if (p_def_timer
->dimensions
) {
5199 const char *dispname_str
= id
->get_dispname().c_str();
5200 error("Local definition `%s' is a single timer, but the definition "
5201 "inherited from component type `%s' is a timer array", dispname_str
,
5202 p_def_timer
->get_my_scope()->get_fullname().c_str());
5203 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5206 if (default_duration
) {
5207 if (p_def_timer
->default_duration
) {
5208 if (!default_duration
->is_unfoldable() &&
5209 !p_def_timer
->default_duration
->is_unfoldable() &&
5210 !(*default_duration
== *p_def_timer
->default_duration
)) {
5211 const char *dispname_str
= id
->get_dispname().c_str();
5212 default_duration
->warning("Local timer `%s' and the timer inherited "
5213 "from component type `%s' have different default durations",
5214 dispname_str
, p_def_timer
->get_my_scope()->get_fullname().c_str());
5215 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5218 const char *dispname_str
= id
->get_dispname().c_str();
5219 default_duration
->error("Local timer `%s' has default duration, but "
5220 "the timer inherited from component type `%s' does not", dispname_str
,
5221 p_def_timer
->get_my_scope()->get_fullname().c_str());
5222 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5225 } else if (p_def_timer
->default_duration
) {
5226 const char *dispname_str
= id
->get_dispname().c_str();
5227 error("Local timer `%s' does not have default duration, but the timer "
5228 "inherited from component type `%s' has", dispname_str
,
5229 p_def_timer
->get_my_scope()->get_fullname().c_str());
5230 p_def_timer
->note("The inherited timer `%s' is here", dispname_str
);
5236 bool Def_Timer::has_default_duration(FieldOrArrayRefs
*p_subrefs
)
5238 // return true in case of any uncertainity
5239 if (!default_duration
) return false;
5240 else if (!dimensions
|| !p_subrefs
) return true;
5241 Value
*v
= default_duration
;
5242 size_t nof_dims
= dimensions
->get_nof_dims();
5243 size_t nof_refs
= p_subrefs
->get_nof_refs();
5244 size_t upper_limit
= nof_dims
< nof_refs
? nof_dims
: nof_refs
;
5245 for (size_t i
= 0; i
< upper_limit
; i
++) {
5246 v
= v
->get_value_refd_last();
5247 if (v
->get_valuetype() != Value::V_SEQOF
) break;
5248 FieldOrArrayRef
*ref
= p_subrefs
->get_ref(i
);
5249 if (ref
->get_type() != FieldOrArrayRef::ARRAY_REF
) return true;
5250 Value
*v_index
= ref
->get_val()->get_value_refd_last();
5251 if (v_index
->get_valuetype() != Value::V_INT
) return true;
5252 Int index
= v_index
->get_val_Int()->get_val()
5253 - dimensions
->get_dim_byIndex(i
)->get_offset();
5254 if (index
>= 0 && index
< static_cast<Int
>(v
->get_nof_comps()))
5255 v
= v
->get_comp_byIndex(index
);
5258 return v
->get_valuetype() != Value::V_NOTUSED
;
5261 void Def_Timer::chk_single_duration(Value
*dur
)
5263 dur
->chk_expr_float(is_local() ?
5264 Type::EXPECTED_DYNAMIC_VALUE
: Type::EXPECTED_STATIC_VALUE
);
5265 Value
*v
= dur
->get_value_refd_last();
5266 if (v
->get_valuetype() == Value::V_REAL
) {
5267 ttcn3float v_real
= v
->get_val_Real();
5268 if ( (v_real
<0.0) || isSpecialFloatValue(v_real
) ) {
5269 dur
->error("A non-negative float value was expected "
5270 "as timer duration instead of `%s'", Real2string(v_real
).c_str());
5275 void Def_Timer::chk_array_duration(Value
*dur
, size_t start_dim
)
5277 ArrayDimension
*dim
= dimensions
->get_dim_byIndex(start_dim
);
5278 bool array_size_known
= !dim
->get_has_error();
5279 size_t array_size
= 0;
5280 if (array_size_known
) array_size
= dim
->get_size();
5281 Value
*v
= dur
->get_value_refd_last();
5282 switch (v
->get_valuetype()) {
5283 case Value::V_ERROR
:
5285 case Value::V_SEQOF
: {
5286 size_t nof_vs
= v
->get_nof_comps();
5287 // Value-list notation.
5288 if (!v
->is_indexed()) {
5289 if (array_size_known
) {
5290 if (array_size
> nof_vs
) {
5291 dur
->error("Too few elements in the default duration of timer "
5292 "array: %lu was expected instead of %lu",
5293 (unsigned long)array_size
, (unsigned long)nof_vs
);
5294 } else if (array_size
< nof_vs
) {
5295 dur
->error("Too many elements in the default duration of timer "
5296 "array: %lu was expected instead of %lu",
5297 (unsigned long)array_size
, (unsigned long)nof_vs
);
5300 bool last_dimension
= start_dim
+ 1 >= dimensions
->get_nof_dims();
5301 for (size_t i
= 0; i
< nof_vs
; i
++) {
5302 Value
*array_v
= v
->get_comp_byIndex(i
);
5303 if (array_v
->get_valuetype() == Value::V_NOTUSED
) continue;
5304 if (last_dimension
) chk_single_duration(array_v
);
5305 else chk_array_duration(array_v
, start_dim
+ 1);
5308 // Indexed-notation.
5309 bool last_dimension
= start_dim
+ 1 >= dimensions
->get_nof_dims();
5310 map
<Int
, Int
> index_map
;
5311 for (size_t i
= 0; i
< nof_vs
; i
++) {
5312 Value
*array_v
= v
->get_comp_byIndex(i
);
5313 if (array_v
->get_valuetype() == Value::V_NOTUSED
) continue;
5314 if (last_dimension
) chk_single_duration(array_v
);
5315 else chk_array_duration(array_v
, start_dim
+ 1);
5316 Error_Context
cntxt(this, "In timer array element %lu",
5317 (unsigned long)(i
+ 1));
5318 Value
*index
= v
->get_index_byIndex(i
);
5319 dim
->chk_index(index
, Type::EXPECTED_DYNAMIC_VALUE
);
5320 if (index
->get_value_refd_last()->get_valuetype() == Value::V_INT
) {
5321 const int_val_t
*index_int
= index
->get_value_refd_last()
5323 if (*index_int
> INT_MAX
) {
5324 index
->error("An integer value less than `%d' was expected for "
5325 "indexing timer array instead of `%s'", INT_MAX
,
5326 (index_int
->t_str()).c_str());
5327 index
->set_valuetype(Value::V_ERROR
);
5329 Int index_val
= index_int
->get_val();
5330 if (index_map
.has_key(index_val
)) {
5331 index
->error("Duplicate index value `%s' for timer array "
5332 "elements `%s' and `%s'",
5333 Int2string(index_val
).c_str(),
5334 Int2string((Int
)i
+ 1).c_str(),
5335 Int2string(*index_map
[index_val
]).c_str());
5336 index
->set_valuetype(Value::V_ERROR
);
5338 index_map
.add(index_val
, new Int((Int
)i
+ 1));
5343 // It's not possible to have "index_map.size() > array_size", since we
5344 // add only correct constant-index values into the map. It's possible
5345 // to create partially initialized timer arrays.
5346 for (size_t i
= 0; i
< index_map
.size(); i
++)
5347 delete index_map
.get_nth_elem(i
);
5352 if (array_size_known
) {
5353 dur
->error("An array value (with %lu elements) was expected as "
5354 "default duration of timer array",
5355 (unsigned long)array_size
);
5357 dur
->error("An array value was expected as default duration of timer "
5360 dur
->set_valuetype(Value::V_ERROR
);
5365 void Def_Timer::generate_code(output_struct
*target
, bool)
5367 const string
& t_genname
= get_genname();
5368 const char *genname_str
= t_genname
.c_str();
5369 const string
& dispname
= id
->get_dispname();
5372 const string
& array_type
= dimensions
->get_timer_type();
5373 const char *array_type_str
= array_type
.c_str();
5374 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5375 "extern %s %s;\n", array_type_str
, genname_str
);
5376 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5377 "%s %s;\n", array_type_str
, genname_str
);
5378 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
, "{\n"
5379 "static const char * const timer_name = \"");
5380 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
5382 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
5384 "%s.set_name(timer_name);\n"
5385 "}\n", genname_str
);
5386 if (default_duration
) target
->functions
.post_init
=
5387 generate_code_array_duration(target
->functions
.post_init
, genname_str
,
5391 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5392 "extern TIMER %s;\n", genname_str
);
5393 if (default_duration
) {
5394 // has default duration
5395 Value
*v
= default_duration
->get_value_refd_last();
5396 if (v
->get_valuetype() == Value::V_REAL
) {
5397 // duration is known at compilation time -> set in the constructor
5398 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5399 "TIMER %s(\"%s\", %s);\n", genname_str
, dispname
.c_str(),
5400 v
->get_single_expr().c_str());
5402 // duration is known only at runtime -> set in post_init
5403 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5404 "TIMER %s(\"%s\");\n", genname_str
, dispname
.c_str());
5405 expression_struct expr
;
5406 Code::init_expr(&expr
);
5407 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5409 default_duration
->generate_code_expr(&expr
);
5410 expr
.expr
= mputc(expr
.expr
, ')');
5411 target
->functions
.post_init
=
5412 Code::merge_free_expr(target
->functions
.post_init
, &expr
);
5415 // does not have default duration
5416 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5417 "TIMER %s(\"%s\");\n", genname_str
, dispname
.c_str());
5422 void Def_Timer::generate_code(CodeGenHelper
& cgh
) {
5423 generate_code(cgh
.get_current_outputstruct());
5426 char *Def_Timer::generate_code_array_duration(char *str
,
5427 const char *object_name
, Value
*dur
, size_t start_dim
)
5429 ArrayDimension
*dim
= dimensions
->get_dim_byIndex(start_dim
);
5430 size_t dim_size
= dim
->get_size();
5431 Value
*v
= dur
->get_value_refd_last();
5432 if (v
->get_valuetype() != Value::V_SEQOF
5433 || (v
->get_nof_comps() != dim_size
&& !v
->is_indexed()))
5434 FATAL_ERROR("Def_Timer::generate_code_array_duration()");
5435 // Value-list notation.
5436 if (!v
->is_indexed()) {
5437 if (start_dim
+ 1 < dimensions
->get_nof_dims()) {
5438 // There are more dimensions, the elements of "v" are arrays a
5439 // temporary reference shall be introduced if the next dimension has
5440 // more than 1 elements.
5441 bool temp_ref_needed
=
5442 dimensions
->get_dim_byIndex(start_dim
+ 1)->get_size() > 1;
5443 for (size_t i
= 0; i
< dim_size
; i
++) {
5444 Value
*v_elem
= v
->get_comp_byIndex(i
);
5445 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5446 if (temp_ref_needed
) {
5447 const string
& tmp_id
= my_scope
->get_scope_mod_gen()
5448 ->get_temporary_id();
5449 const char *tmp_str
= tmp_id
.c_str();
5450 str
= mputprintf(str
, "{\n"
5451 "%s& %s = %s.array_element(%lu);\n",
5452 dimensions
->get_timer_type(start_dim
+ 1).c_str(),
5453 tmp_str
, object_name
, (unsigned long)i
);
5454 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5456 str
= mputstr(str
, "}\n");
5458 char *tmp_str
= mprintf("%s.array_element(%lu)", object_name
,
5460 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5466 // We are in the last dimension, the elements of "v" are floats.
5467 for (size_t i
= 0; i
< dim_size
; i
++) {
5468 Value
*v_elem
= v
->get_comp_byIndex(i
);
5469 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5470 expression_struct expr
;
5471 Code::init_expr(&expr
);
5472 expr
.expr
= mputprintf(expr
.expr
,
5473 "%s.array_element(%lu).set_default_duration(",
5474 object_name
, (unsigned long)i
);
5475 v_elem
->generate_code_expr(&expr
);
5476 expr
.expr
= mputc(expr
.expr
, ')');
5477 str
= Code::merge_free_expr(str
, &expr
);
5480 // Indexed-list notation.
5482 if (start_dim
+ 1 < dimensions
->get_nof_dims()) {
5483 bool temp_ref_needed
=
5484 dimensions
->get_dim_byIndex(start_dim
+ 1)->get_size() > 1;
5485 for (size_t i
= 0; i
< v
->get_nof_comps(); i
++) {
5486 Value
*v_elem
= v
->get_comp_byIndex(i
);
5487 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5488 if (temp_ref_needed
) {
5489 const string
& tmp_id
= my_scope
->get_scope_mod_gen()
5490 ->get_temporary_id();
5491 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5492 ->get_temporary_id();
5493 const char *tmp_str
= tmp_id
.c_str();
5494 str
= mputstr(str
, "{\n");
5495 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5496 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5498 str
= mputprintf(str
, "%s& %s = %s.array_element(%s);\n",
5499 dimensions
->get_timer_type(start_dim
+ 1).c_str(),
5500 tmp_str
, object_name
, idx_id
.c_str());
5501 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5503 str
= mputstr(str
, "}\n");
5505 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5506 ->get_temporary_id();
5507 str
= mputstr(str
, "{\n");
5508 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5509 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5511 char *tmp_str
= mprintf("%s.array_element(%s)", object_name
,
5513 str
= generate_code_array_duration(str
, tmp_str
, v_elem
,
5515 str
= mputstr(str
, "}\n");
5520 for (size_t i
= 0; i
< v
->get_nof_comps(); i
++) {
5521 Value
*v_elem
= v
->get_comp_byIndex(i
);
5522 if (v_elem
->get_valuetype() == Value::V_NOTUSED
) continue;
5523 expression_struct expr
;
5524 Code::init_expr(&expr
);
5525 str
= mputstr(str
, "{\n");
5526 const string
& idx_id
= my_scope
->get_scope_mod_gen()
5527 ->get_temporary_id();
5528 str
= mputprintf(str
, "int %s;\n", idx_id
.c_str());
5529 str
= v
->get_index_byIndex(i
)->generate_code_init(str
,
5531 str
= mputprintf(str
,
5532 "%s.array_element(%s).set_default_duration(",
5533 object_name
, idx_id
.c_str());
5534 v_elem
->generate_code_expr(&expr
);
5535 expr
.expr
= mputc(expr
.expr
, ')');
5536 str
= Code::merge_free_expr(str
, &expr
);
5537 str
= mputstr(str
, "}\n");
5544 char *Def_Timer::generate_code_str(char *str
)
5546 const string
& t_genname
= get_genname();
5547 const char *genname_str
= t_genname
.c_str();
5548 const string
& dispname
= id
->get_dispname();
5551 const string
& array_type
= dimensions
->get_timer_type();
5552 const char *array_type_str
= array_type
.c_str();
5553 str
= mputprintf(str
, "%s %s;\n", array_type_str
, genname_str
);
5554 str
= mputstr(str
, "{\n"
5555 "static const char * const timer_name = \"");
5556 str
= mputstr(str
, dispname
.c_str());
5557 str
= mputprintf(str
, "\";\n"
5558 "%s.set_name(timer_name);\n"
5559 "}\n", genname_str
);
5560 if (default_duration
) str
= generate_code_array_duration(str
,
5561 genname_str
, default_duration
);
5564 if (default_duration
&& default_duration
->has_single_expr()) {
5565 // the default duration can be passed to the constructor
5566 str
= mputprintf(str
, "TIMER %s(\"%s\", %s);\n", genname_str
,
5567 dispname
.c_str(), default_duration
->get_single_expr().c_str());
5569 // only the name is passed to the constructor
5570 str
= mputprintf(str
, "TIMER %s(\"%s\");\n", genname_str
,
5572 if (default_duration
) {
5573 // the default duration is set explicitly
5574 expression_struct expr
;
5575 Code::init_expr(&expr
);
5576 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5578 default_duration
->generate_code_expr(&expr
);
5579 expr
.expr
= mputc(expr
.expr
, ')');
5580 str
= Code::merge_free_expr(str
, &expr
);
5584 if (debugger_active
) {
5585 str
= generate_code_debugger_add_var(str
, this);
5590 void Def_Timer::ilt_generate_code(ILT
*ilt
)
5592 const string
& t_genname
= get_genname();
5593 const char *genname_str
= t_genname
.c_str();
5594 const string
& dispname
= id
->get_dispname();
5596 char*& def
= ilt
->get_out_def();
5597 char*& init
= ilt
->get_out_branches();
5601 const string
& array_type
= dimensions
->get_timer_type();
5602 const char *array_type_str
= array_type
.c_str();
5603 def
= mputprintf(def
, "%s %s;\n", array_type_str
, genname_str
);
5604 def
= mputstr(def
, "{\n"
5605 "static const char * const timer_names[] = { ");
5606 def
= dimensions
->generate_element_names(def
, dispname
);
5607 def
= mputprintf(def
, " };\n"
5608 "%s.set_name(%lu, timer_names);\n"
5609 "}\n", genname_str
, (unsigned long) dimensions
->get_array_size());
5610 if (default_duration
) init
= generate_code_array_duration(init
,
5611 genname_str
, default_duration
);
5614 if (default_duration
) {
5615 // has default duration
5616 Value
*v
= default_duration
->get_value_refd_last();
5617 if (v
->get_valuetype() == Value::V_REAL
) {
5618 // duration is known at compilation time -> set in the constructor
5619 def
= mputprintf(def
, "TIMER %s(\"%s\", %s);\n", genname_str
,
5620 dispname
.c_str(), v
->get_single_expr().c_str());
5622 // duration is known only at runtime -> set when control reaches the
5624 def
= mputprintf(def
, "TIMER %s(\"%s\");\n", genname_str
,
5626 expression_struct expr
;
5627 Code::init_expr(&expr
);
5628 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5630 default_duration
->generate_code_expr(&expr
);
5631 expr
.expr
= mputc(expr
.expr
, ')');
5632 init
= Code::merge_free_expr(init
, &expr
);
5635 // does not have default duration
5636 def
= mputprintf(def
, "TIMER %s(\"%s\");\n", genname_str
,
5642 char *Def_Timer::generate_code_init_comp(char *str
, Definition
*base_defn
)
5644 if (default_duration
) {
5645 Def_Timer
*base_timer_defn
= dynamic_cast<Def_Timer
*>(base_defn
);
5646 if (!base_timer_defn
|| !base_timer_defn
->default_duration
)
5647 FATAL_ERROR("Def_Timer::generate_code_init_comp()");
5648 // initializer is not needed if the default durations are the same
5649 // constants in both timers
5650 if (default_duration
->is_unfoldable() ||
5651 base_timer_defn
->default_duration
->is_unfoldable() ||
5652 !(*default_duration
== *base_timer_defn
->default_duration
)) {
5654 str
= generate_code_array_duration(str
,
5655 base_timer_defn
->get_genname_from_scope(my_scope
).c_str(),
5658 expression_struct expr
;
5659 Code::init_expr(&expr
);
5660 expr
.expr
= mputprintf(expr
.expr
, "%s.set_default_duration(",
5661 base_timer_defn
->get_genname_from_scope(my_scope
).c_str());
5662 default_duration
->generate_code_expr(&expr
);
5663 expr
.expr
= mputc(expr
.expr
, ')');
5664 str
= Code::merge_free_expr(str
, &expr
);
5671 void Def_Timer::dump_internal(unsigned level
) const
5673 DEBUG(level
, "Timer: %s", id
->get_dispname().c_str());
5674 if (dimensions
) dimensions
->dump(level
+ 1);
5675 if (default_duration
) {
5676 DEBUG(level
+ 1, "Default duration:");
5677 default_duration
->dump(level
+ 1);
5681 // =================================
5683 // =================================
5685 Def_Port::Def_Port(Identifier
*p_id
, Reference
*p_tref
,
5686 ArrayDimensions
*p_dims
)
5687 : Definition(A_PORT
, p_id
), type_ref(p_tref
), port_type(0),
5690 if (!p_tref
) FATAL_ERROR("Def_Port::Def_Port()");
5693 Def_Port::~Def_Port()
5699 Def_Port
*Def_Port::clone() const
5701 FATAL_ERROR("Def_Port::clone");
5704 void Def_Port::set_fullname(const string
& p_fullname
)
5706 Definition::set_fullname(p_fullname
);
5707 type_ref
->set_fullname(p_fullname
+ ".<type_ref>");
5708 if (dimensions
) dimensions
->set_fullname(p_fullname
);
5711 void Def_Port::set_my_scope(Scope
*p_scope
)
5713 Definition::set_my_scope(p_scope
);
5714 type_ref
->set_my_scope(p_scope
);
5715 if (dimensions
) dimensions
->set_my_scope(p_scope
);
5718 Type
*Def_Port::get_Type()
5724 ArrayDimensions
*Def_Port::get_Dimensions()
5726 if (!checked
) chk();
5730 void Def_Port::chk()
5732 if (checked
) return;
5734 Error_Context
cntxt(this, "In port definition `%s'",
5735 id
->get_dispname().c_str());
5736 Common::Assignment
*ass
= type_ref
->get_refd_assignment();
5738 if (ass
->get_asstype() == A_TYPE
) {
5739 Type
*t
= ass
->get_Type()->get_type_refd_last();
5740 if (t
->get_typetype() == Type::T_PORT
) port_type
= t
;
5741 else type_ref
->error("Type reference `%s' does not refer to a "
5742 "port type", type_ref
->get_dispname().c_str());
5743 } else type_ref
->error("Reference `%s' does not refer to a "
5744 "type", type_ref
->get_dispname().c_str());
5746 if (dimensions
) dimensions
->chk();
5747 if (w_attrib_path
) {
5748 w_attrib_path
->chk_global_attrib();
5749 w_attrib_path
->chk_no_qualif();
5753 bool Def_Port::chk_identical(Definition
*p_def
)
5757 if (p_def
->get_asstype() != A_PORT
) {
5758 const char *dispname_str
= id
->get_dispname().c_str();
5759 error("Local definition `%s' is a port, but the definition inherited "
5760 "from component type `%s' is a %s", dispname_str
,
5761 p_def
->get_my_scope()->get_fullname().c_str(), p_def
->get_assname());
5762 p_def
->note("The inherited definition of `%s' is here", dispname_str
);
5765 Def_Port
*p_def_port
= dynamic_cast<Def_Port
*>(p_def
);
5766 if (!p_def_port
) FATAL_ERROR("Def_Port::chk_identical()");
5767 if (port_type
&& p_def_port
->port_type
&&
5768 port_type
!= p_def_port
->port_type
) {
5769 const char *dispname_str
= id
->get_dispname().c_str();
5770 type_ref
->error("Local port `%s' has type `%s', but the port inherited "
5771 "from component type `%s' has type `%s'", dispname_str
,
5772 port_type
->get_typename().c_str(),
5773 p_def_port
->get_my_scope()->get_fullname().c_str(),
5774 p_def_port
->port_type
->get_typename().c_str());
5775 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5779 if (p_def_port
->dimensions
) {
5780 if (!dimensions
->is_identical(p_def_port
->dimensions
)) {
5781 const char *dispname_str
= id
->get_dispname().c_str();
5782 error("Local port `%s' and the port inherited from component type "
5783 "`%s' have different array dimensions", dispname_str
,
5784 p_def_port
->get_my_scope()->get_fullname().c_str());
5785 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5789 const char *dispname_str
= id
->get_dispname().c_str();
5790 error("Local definition `%s' is a port array, but the definition "
5791 "inherited from component type `%s' is a single port", dispname_str
,
5792 p_def_port
->get_my_scope()->get_fullname().c_str());
5793 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5796 } else if (p_def_port
->dimensions
) {
5797 const char *dispname_str
= id
->get_dispname().c_str();
5798 error("Local definition `%s' is a single port, but the definition "
5799 "inherited from component type `%s' is a port array", dispname_str
,
5800 p_def_port
->get_my_scope()->get_fullname().c_str());
5801 p_def_port
->note("The inherited port `%s' is here", dispname_str
);
5807 void Def_Port::generate_code(output_struct
*target
, bool)
5809 const string
& t_genname
= get_genname();
5810 const char *genname_str
= t_genname
.c_str();
5811 const string
& type_genname
= port_type
->get_genname_value(my_scope
);
5812 const string
& dispname
= id
->get_dispname();
5815 const string
& array_type
= dimensions
->get_port_type(type_genname
);
5816 const char *array_type_str
= array_type
.c_str();
5817 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5818 "extern %s %s;\n", array_type_str
, genname_str
);
5819 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5820 "%s %s;\n", array_type_str
, genname_str
);
5821 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
, "{\n"
5822 "static const char * const port_name = \"");
5823 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
5825 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
5827 "%s.set_name(port_name);\n"
5828 "}\n", genname_str
);
5831 const char *type_genname_str
= type_genname
.c_str();
5832 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
5833 "extern %s %s;\n", type_genname_str
, genname_str
);
5834 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
5835 "%s %s(\"%s\");\n", type_genname_str
, genname_str
, dispname
.c_str());
5837 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
5838 "%s.activate_port();\n", genname_str
);
5841 void Def_Port::generate_code(CodeGenHelper
& cgh
) {
5842 generate_code(cgh
.get_current_outputstruct());
5845 char *Def_Port::generate_code_init_comp(char *str
, Definition
*base_defn
)
5847 return mputprintf(str
, "%s.activate_port();\n",
5848 base_defn
->get_genname_from_scope(my_scope
).c_str());
5851 void Def_Port::dump_internal(unsigned level
) const
5853 DEBUG(level
, "Port: %s", id
->get_dispname().c_str());
5854 DEBUG(level
+ 1, "Port type:");
5855 type_ref
->dump(level
+ 2);
5856 if (dimensions
) dimensions
->dump(level
+ 1);
5859 // =================================
5860 // ===== Def_Function_Base
5861 // =================================
5863 Def_Function_Base::asstype_t
Def_Function_Base::determine_asstype(
5864 bool is_external
, bool has_return_type
, bool returns_template
)
5867 if (has_return_type
) {
5868 if (returns_template
) return A_EXT_FUNCTION_RTEMP
;
5869 else return A_EXT_FUNCTION_RVAL
;
5871 if (returns_template
)
5872 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5873 return A_EXT_FUNCTION
;
5875 } else { // not an external function
5876 if (has_return_type
) {
5877 if (returns_template
) return A_FUNCTION_RTEMP
;
5878 else return A_FUNCTION_RVAL
;
5880 if (returns_template
)
5881 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5887 Def_Function_Base::Def_Function_Base(const Def_Function_Base
& p
)
5888 : Definition(p
), prototype(PROTOTYPE_NONE
), input_type(0), output_type(0)
5890 fp_list
= p
.fp_list
->clone();
5891 fp_list
->set_my_def(this);
5892 return_type
= p
.return_type
? p
.return_type
->clone() : 0;
5893 template_restriction
= p
.template_restriction
;
5896 Def_Function_Base::Def_Function_Base(bool is_external
, Identifier
*p_id
,
5897 FormalParList
*p_fpl
, Type
*p_return_type
, bool returns_template
,
5898 template_restriction_t p_template_restriction
)
5899 : Definition(determine_asstype(is_external
, p_return_type
!= 0,
5900 returns_template
), p_id
), fp_list(p_fpl
), return_type(p_return_type
),
5901 prototype(PROTOTYPE_NONE
), input_type(0), output_type(0),
5902 template_restriction(p_template_restriction
)
5904 if (!p_fpl
) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
5905 fp_list
->set_my_def(this);
5906 if (return_type
) return_type
->set_ownertype(Type::OT_FUNCTION_DEF
, this);
5909 Def_Function_Base::~Def_Function_Base()
5915 void Def_Function_Base::set_fullname(const string
& p_fullname
)
5917 Definition::set_fullname(p_fullname
);
5918 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
5919 if (return_type
) return_type
->set_fullname(p_fullname
+ ".<return_type>");
5922 void Def_Function_Base::set_my_scope(Scope
*p_scope
)
5924 Definition::set_my_scope(p_scope
);
5925 fp_list
->set_my_scope(p_scope
);
5926 if (return_type
) return_type
->set_my_scope(p_scope
);
5929 Type
*Def_Function_Base::get_Type()
5931 if (!checked
) chk();
5935 FormalParList
*Def_Function_Base::get_FormalParList()
5937 if (!checked
) chk();
5941 const char *Def_Function_Base::get_prototype_name() const
5943 switch (prototype
) {
5944 case PROTOTYPE_NONE
:
5945 return "<no prototype>";
5946 case PROTOTYPE_CONVERT
:
5948 case PROTOTYPE_FAST
:
5950 case PROTOTYPE_BACKTRACK
:
5952 case PROTOTYPE_SLIDING
:
5955 return "<unknown prototype>";
5959 void Def_Function_Base::chk_prototype()
5961 switch (prototype
) {
5962 case PROTOTYPE_NONE
:
5963 // return immediately
5965 case PROTOTYPE_CONVERT
:
5966 case PROTOTYPE_FAST
:
5967 case PROTOTYPE_BACKTRACK
:
5968 case PROTOTYPE_SLIDING
:
5969 // perform the checks below
5972 FATAL_ERROR("Def_Function_Base::chk_prototype()");
5974 // checking the formal parameter list
5975 if (prototype
== PROTOTYPE_CONVERT
) {
5976 if (fp_list
->get_nof_fps() == 1) {
5977 FormalPar
*par
= fp_list
->get_fp_byIndex(0);
5978 if (par
->get_asstype() == A_PAR_VAL_IN
) {
5979 input_type
= par
->get_Type();
5981 par
->error("The parameter must be an `in' value parameter for "
5982 "attribute `prototype(%s)' instead of %s", get_prototype_name(),
5983 par
->get_assname());
5986 fp_list
->error("The function must have one parameter instead of %lu "
5987 "for attribute `prototype(%s)'", (unsigned long) fp_list
->get_nof_fps(),
5988 get_prototype_name());
5990 } else { // not PROTOTYPE_CONVERT
5991 if (fp_list
->get_nof_fps() == 2) {
5992 FormalPar
*first_par
= fp_list
->get_fp_byIndex(0);
5993 if (prototype
== PROTOTYPE_SLIDING
) {
5994 if (first_par
->get_asstype() == A_PAR_VAL_INOUT
) {
5995 Type
*first_par_type
= first_par
->get_Type();
5996 switch (first_par_type
->get_type_refd_last()
5997 ->get_typetype_ttcn3()) {
6002 input_type
= first_par_type
;
6005 first_par_type
->error("The type of the first parameter must be "
6006 "`octetstring' or `charstring' or `bitstring' for attribute "
6007 "`prototype(%s)' instead of `%s'", get_prototype_name(),
6008 first_par_type
->get_typename().c_str());
6011 first_par
->error("The first parameter must be an `inout' value "
6012 "parameter for attribute `prototype(%s)' instead of %s",
6013 get_prototype_name(), first_par
->get_assname());
6016 if (first_par
->get_asstype() == A_PAR_VAL_IN
) {
6017 input_type
= first_par
->get_Type();
6019 first_par
->error("The first parameter must be an `in' value "
6020 "parameter for attribute `prototype(%s)' instead of %s",
6021 get_prototype_name(), first_par
->get_assname());
6024 FormalPar
*second_par
= fp_list
->get_fp_byIndex(1);
6025 if (second_par
->get_asstype() == A_PAR_VAL_OUT
) {
6026 output_type
= second_par
->get_Type();
6028 second_par
->error("The second parameter must be an `out' value "
6029 "parameter for attribute `prototype(%s)' instead of %s",
6030 get_prototype_name(), second_par
->get_assname());
6033 fp_list
->error("The function must have two parameters for attribute "
6034 "`prototype(%s)' instead of %lu", get_prototype_name(),
6035 (unsigned long) fp_list
->get_nof_fps());
6038 // checking the return type
6039 if (prototype
== PROTOTYPE_FAST
) {
6041 return_type
->error("The function cannot have return type for "
6042 "attribute `prototype(%s)'", get_prototype_name());
6046 if (asstype
== A_FUNCTION_RTEMP
|| asstype
== A_EXT_FUNCTION_RTEMP
)
6047 return_type
->error("The function must return a value instead of a "
6048 "template for attribute `prototype(%s)'", get_prototype_name());
6049 if (prototype
== PROTOTYPE_CONVERT
) {
6050 output_type
= return_type
;
6052 switch (return_type
->get_type_refd_last()->get_typetype_ttcn3()) {
6057 return_type
->error("The return type of the function must be "
6058 "`integer' instead of `%s' for attribute `prototype(%s)'",
6059 return_type
->get_typename().c_str(), get_prototype_name());
6063 error("The function must have return type for attribute "
6064 "`prototype(%s)'", get_prototype_name());
6067 // checking the 'runs on' clause
6068 if (get_RunsOnType()) {
6069 error("The function cannot have `runs on' clause for attribute "
6070 "`prototype(%s)'", get_prototype_name());
6074 Type
*Def_Function_Base::get_input_type()
6076 if (!checked
) chk();
6080 Type
*Def_Function_Base::get_output_type()
6082 if (!checked
) chk();
6087 // =================================
6088 // ===== Def_Function
6089 // =================================
6091 Def_Function::Def_Function(Identifier
*p_id
, FormalParList
*p_fpl
,
6092 Reference
*p_runs_on_ref
, Type
*p_return_type
,
6093 bool returns_template
,
6094 template_restriction_t p_template_restriction
,
6095 StatementBlock
*p_block
)
6096 : Def_Function_Base(false, p_id
, p_fpl
, p_return_type
, returns_template
,
6097 p_template_restriction
),
6098 runs_on_ref(p_runs_on_ref
), runs_on_type(0), block(p_block
),
6099 is_startable(false), transparent(false)
6101 if (!p_block
) FATAL_ERROR("Def_Function::Def_Function()");
6102 block
->set_my_def(this);
6105 Def_Function::~Def_Function()
6111 Def_Function
*Def_Function::clone() const
6113 FATAL_ERROR("Def_Function::clone");
6116 void Def_Function::set_fullname(const string
& p_fullname
)
6118 Def_Function_Base::set_fullname(p_fullname
);
6119 if (runs_on_ref
) runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
6120 block
->set_fullname(p_fullname
+ ".<statement_block>");
6123 void Def_Function::set_my_scope(Scope
*p_scope
)
6125 bridgeScope
.set_parent_scope(p_scope
);
6126 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
6128 Def_Function_Base::set_my_scope(&bridgeScope
);
6129 if (runs_on_ref
) runs_on_ref
->set_my_scope(&bridgeScope
);
6130 block
->set_my_scope(fp_list
);
6133 Type
*Def_Function::get_RunsOnType()
6135 if (!checked
) chk();
6136 return runs_on_type
;
6139 RunsOnScope
*Def_Function::get_runs_on_scope(Type
*comptype
)
6141 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
6142 if (!my_module
) FATAL_ERROR("Def_Function::get_runs_on_scope()");
6143 return my_module
->get_runs_on_scope(comptype
);
6146 void Def_Function::chk()
6148 if (checked
) return;
6150 Error_Context
cntxt(this, "In function definition `%s'",
6151 id
->get_dispname().c_str());
6152 // checking the `runs on' clause
6154 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
6155 runs_on_type
= runs_on_ref
->chk_comptype_ref();
6156 // override the scope of the formal parameter list
6158 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
6159 runs_on_scope
->set_parent_scope(my_scope
);
6160 fp_list
->set_my_scope(runs_on_scope
);
6163 // checking the formal parameter list
6164 fp_list
->chk(asstype
);
6165 // checking of return type
6167 Error_Context
cntxt2(return_type
, "In return type");
6169 return_type
->chk_as_return_type(asstype
== A_FUNCTION_RVAL
,"function");
6171 // decision of startability
6172 is_startable
= runs_on_ref
!= 0;
6173 if (is_startable
&& !fp_list
->get_startability()) is_startable
= false;
6174 if (is_startable
&& return_type
&& return_type
->is_component_internal())
6175 is_startable
= false;
6176 // checking of statement block
6179 // checking the presence of return statements
6180 switch (block
->has_return()) {
6181 case StatementBlock::RS_NO
:
6182 error("The function has return type, but it does not have any return "
6185 case StatementBlock::RS_MAYBE
:
6186 error("The function has return type, but control might leave it "
6187 "without reaching a return statement");
6192 if (!semantic_check_only
) {
6193 fp_list
->set_genname(get_genname());
6194 block
->set_code_section(GovernedSimple::CS_INLINE
);
6196 if (w_attrib_path
) {
6197 w_attrib_path
->chk_global_attrib();
6198 w_attrib_path
->chk_no_qualif();
6199 Ttcn::ExtensionAttributes
* extattrs
= parse_extattributes(w_attrib_path
);
6200 if (extattrs
!= 0) { // NULL means parsing error
6201 size_t num_atrs
= extattrs
->size();
6202 for (size_t i
=0; i
< num_atrs
; ++i
) {
6203 ExtensionAttribute
&ea
= extattrs
->get(i
);
6204 switch (ea
.get_type()) {
6205 case ExtensionAttribute::PROTOTYPE
: {
6206 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE
) {
6207 ea
.error("Duplicate attribute `prototype'");
6209 Def_Function_Base::prototype_t proto
= ea
.get_proto();
6210 set_prototype(proto
);
6213 case ExtensionAttribute::ANYTYPELIST
: // ignore it
6214 case ExtensionAttribute::NONE
: // erroneous, do not issue an error
6217 case ExtensionAttribute::TRANSPARENT
:
6221 case ExtensionAttribute::ENCODE
:
6222 case ExtensionAttribute::DECODE
:
6223 case ExtensionAttribute::ERRORBEHAVIOR
:
6224 case ExtensionAttribute::PRINTING
:
6225 ea
.error("Extension attribute 'encode', 'decode', 'errorbehavior'"
6226 " or 'printing' can only be applied to external functions");
6229 default: // complain
6230 ea
.error("Function definition can only have the 'prototype'"
6231 " extension attribute");
6241 bool Def_Function::chk_startable()
6243 if (!checked
) chk();
6244 if (is_startable
) return true;
6245 if (!runs_on_ref
) error("Function `%s' cannot be started on a parallel "
6246 "test component because it does not have `runs on' clause",
6247 get_fullname().c_str());
6248 fp_list
->chk_startability("Function", get_fullname().c_str());
6249 if (return_type
&& return_type
->is_component_internal()) {
6250 map
<Type
*,void> type_chain
;
6251 char* err_str
= mprintf("the return type or embedded in the return type "
6252 "of function `%s' if it is started on a parallel test component",
6253 get_fullname().c_str());
6254 return_type
->chk_component_internal(type_chain
, err_str
);
6260 void Def_Function::generate_code(output_struct
*target
, bool)
6262 transparency_holder
glass(*this);
6263 const string
& t_genname
= get_genname();
6264 const char *genname_str
= t_genname
.c_str();
6265 const char *dispname_str
= id
->get_dispname().c_str();
6266 string return_type_name
;
6269 return_type_name
= "void";
6271 case A_FUNCTION_RVAL
:
6272 return_type_name
= return_type
->get_genname_value(my_scope
);
6274 case A_FUNCTION_RTEMP
:
6275 return_type_name
= return_type
->get_genname_template(my_scope
);
6278 FATAL_ERROR("Def_Function::generate_code()");
6280 const char *return_type_str
= return_type_name
.c_str();
6282 // assemble the function body first (this also determines which parameters
6284 char* body
= create_location_object(memptystr(), "FUNCTION", dispname_str
);
6285 if (!enable_set_bound_out_param
)
6286 body
= fp_list
->generate_code_set_unbound(body
); // conform the standard out parameter is unbound
6287 body
= fp_list
->generate_shadow_objects(body
);
6288 if (debugger_active
) {
6289 body
= generate_code_debugger_function_init(body
, this);
6291 body
= block
->generate_code(body
);
6292 // smart formal parameter list (names of unused parameters are omitted)
6293 char *formal_par_list
= fp_list
->generate_code(memptystr());
6294 fp_list
->generate_code_defval(target
);
6295 // function prototype
6296 target
->header
.function_prototypes
=
6297 mputprintf(target
->header
.function_prototypes
, "extern %s %s(%s);\n",
6298 return_type_str
, genname_str
, formal_par_list
);
6301 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
6305 "}\n\n", return_type_str
, genname_str
, formal_par_list
, body
);
6306 Free(formal_par_list
);
6310 size_t nof_fps
= fp_list
->get_nof_fps();
6311 // use the full list of formal parameters here (since they are all logged)
6312 char *full_formal_par_list
= fp_list
->generate_code(memptystr(), nof_fps
);
6313 // starter function (stub)
6314 // function prototype
6315 target
->header
.function_prototypes
=
6316 mputprintf(target
->header
.function_prototypes
,
6317 "extern void start_%s(const COMPONENT& component_reference%s%s);\n",
6318 genname_str
, nof_fps
>0?", ":"", full_formal_par_list
);
6320 body
= mprintf("void start_%s(const COMPONENT& component_reference%s"
6323 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6324 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6325 genname_str
, nof_fps
>0?", ":"", full_formal_par_list
, dispname_str
);
6326 for (size_t i
= 0; i
< nof_fps
; i
++) {
6327 if (i
> 0) body
= mputstr(body
,
6328 "TTCN_Logger::log_event_str(\", \");\n");
6329 body
= mputprintf(body
, "%s.log();\n",
6330 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6332 body
= mputprintf(body
,
6333 "TTCN_Logger::log_event_str(\") on component \");\n"
6334 "component_reference.log();\n"
6335 "TTCN_Logger::log_char('.');\n"
6336 "TTCN_Logger::end_event();\n"
6337 "Text_Buf text_buf;\n"
6338 "TTCN_Runtime::prepare_start_component(component_reference, "
6339 "\"%s\", \"%s\", text_buf);\n",
6340 my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
6342 for (size_t i
= 0; i
< nof_fps
; i
++) {
6343 body
= mputprintf(body
, "%s.encode_text(text_buf);\n",
6344 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6346 body
= mputstr(body
, "TTCN_Runtime::send_start_component(text_buf);\n"
6348 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
6352 // an entry in start_ptc_function
6353 body
= mprintf("if (!strcmp(function_name, \"%s\")) {\n",
6356 body
= fp_list
->generate_code_object(body
, "", ' ');
6357 for (size_t i
= 0; i
< nof_fps
; i
++) {
6358 body
= mputprintf(body
, "%s.decode_text(function_arguments);\n",
6359 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6361 body
= mputprintf(body
,
6362 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6363 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6365 for (size_t i
= 0; i
< nof_fps
; i
++) {
6366 if (i
> 0) body
= mputstr(body
,
6367 "TTCN_Logger::log_event_str(\", \");\n");
6368 body
= mputprintf(body
, "%s.log();\n",
6369 fp_list
->get_fp_byIndex(i
)->get_reference_name(my_scope
).c_str());
6371 body
= mputstr(body
, "TTCN_Logger::log_event_str(\").\");\n"
6372 "TTCN_Logger::end_event();\n");
6374 body
= mputprintf(body
,
6375 "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
6376 "%s().\");\n", dispname_str
);
6378 body
= mputstr(body
,
6379 "TTCN_Runtime::function_started(function_arguments);\n");
6380 char *actual_par_list
=
6381 fp_list
->generate_code_actual_parlist(memptystr(), "");
6382 bool return_value_kept
= false;
6383 if (asstype
== A_FUNCTION_RVAL
) {
6384 // the return value is kept only if the function returns a value
6385 // (rather than a template) and the return type has the "done"
6386 // extension attribute
6387 for (Type
*t
= return_type
; ; t
= t
->get_type_refd()) {
6388 if (t
->has_done_attribute()) {
6389 return_value_kept
= true;
6391 } else if (!t
->is_ref()) break;
6394 if (return_value_kept
) {
6395 const string
& return_type_dispname
= return_type
->get_typename();
6396 const char *return_type_dispname_str
= return_type_dispname
.c_str();
6397 body
= mputprintf(body
, "%s ret_val(%s(%s));\n"
6398 "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
6399 "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
6401 "Text_Buf text_buf;\n"
6402 "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
6403 "ret_val.encode_text(text_buf);\n"
6404 "TTCN_Runtime::send_function_finished(text_buf);\n",
6405 return_type_str
, genname_str
, actual_par_list
, dispname_str
,
6406 return_type_dispname_str
, return_type_dispname_str
);
6408 body
= mputprintf(body
, "%s(%s);\n"
6409 "TTCN_Runtime::function_finished(\"%s\");\n",
6410 genname_str
, actual_par_list
, dispname_str
);
6412 Free(actual_par_list
);
6413 body
= mputstr(body
, "return TRUE;\n"
6415 target
->functions
.start
= mputstr(target
->functions
.start
, body
);
6417 Free(full_formal_par_list
);
6420 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
6421 "%s.add_function(\"%s\", (genericfunc_t)&%s, ", get_module_object_name(),
6422 dispname_str
, genname_str
);
6424 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
6425 "(genericfunc_t)&start_%s);\n", genname_str
);
6427 target
->functions
.pre_init
= mputstr(target
->functions
.pre_init
,
6431 void Def_Function::generate_code(CodeGenHelper
& cgh
) {
6432 generate_code(cgh
.get_current_outputstruct());
6435 void Def_Function::dump_internal(unsigned level
) const
6437 DEBUG(level
, "Function: %s", id
->get_dispname().c_str());
6438 DEBUG(level
+ 1, "Parameters:");
6439 fp_list
->dump(level
+ 1);
6441 DEBUG(level
+ 1, "Runs on clause:");
6442 runs_on_ref
->dump(level
+ 2);
6445 DEBUG(level
+ 1, "Return type:");
6446 return_type
->dump(level
+ 2);
6447 if (asstype
== A_FUNCTION_RTEMP
) DEBUG(level
+ 1, "Returns template");
6449 if (prototype
!= PROTOTYPE_NONE
)
6450 DEBUG(level
+ 1, "Prototype: %s", get_prototype_name());
6451 //DEBUG(level + 1, "Statement block:");
6452 block
->dump(level
+ 1);
6455 void Def_Function::set_parent_path(WithAttribPath
* p_path
) {
6456 Def_Function_Base::set_parent_path(p_path
);
6457 block
->set_parent_path(w_attrib_path
);
6460 // =================================
6461 // ===== Def_ExtFunction
6462 // =================================
6464 Def_ExtFunction::~Def_ExtFunction()
6466 delete encoding_options
;
6468 if (NULL
!= json_printing
) {
6469 delete json_printing
;
6473 Def_ExtFunction
*Def_ExtFunction::clone() const
6475 FATAL_ERROR("Def_ExtFunction::clone");
6478 void Def_ExtFunction::set_fullname(const string
& p_fullname
)
6480 Def_Function_Base::set_fullname(p_fullname
);
6481 if (eb_list
) eb_list
->set_fullname(p_fullname
+ ".<errorbehavior_list>");
6484 void Def_ExtFunction::set_encode_parameters(Type::MessageEncodingType_t
6485 p_encoding_type
, string
*p_encoding_options
)
6487 function_type
= EXTFUNC_ENCODE
;
6488 encoding_type
= p_encoding_type
;
6489 delete encoding_options
;
6490 encoding_options
= p_encoding_options
;
6493 void Def_ExtFunction::set_decode_parameters(Type::MessageEncodingType_t
6494 p_encoding_type
, string
*p_encoding_options
)
6496 function_type
= EXTFUNC_DECODE
;
6497 encoding_type
= p_encoding_type
;
6498 delete encoding_options
;
6499 encoding_options
= p_encoding_options
;
6502 void Def_ExtFunction::add_eb_list(Ttcn::ErrorBehaviorList
*p_eb_list
)
6504 if (!p_eb_list
) FATAL_ERROR("Def_ExtFunction::add_eb_list()");
6506 eb_list
->steal_ebs(p_eb_list
);
6509 eb_list
= p_eb_list
;
6510 eb_list
->set_fullname(get_fullname() + ".<errorbehavior_list>");
6514 void Def_ExtFunction::chk_function_type()
6516 switch (function_type
) {
6517 case EXTFUNC_MANUAL
:
6519 eb_list
->error("Attribute `errorbehavior' can only be used together "
6520 "with `encode' or `decode'");
6524 case EXTFUNC_ENCODE
:
6525 switch (prototype
) {
6526 case PROTOTYPE_NONE
:
6527 error("Attribute `encode' cannot be used without `prototype'");
6529 case PROTOTYPE_BACKTRACK
:
6530 case PROTOTYPE_SLIDING
:
6531 error("Attribute `encode' cannot be used with `prototype(%s)'",
6532 get_prototype_name());
6533 default: /* CONVERT and FAST allowed */
6538 if (!input_type
->has_encoding(encoding_type
, encoding_options
)) {
6539 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6540 input_type
->error("Input type `%s' does not support custom encoding '%s'",
6541 input_type
->get_typename().c_str(), encoding_options
->c_str());
6544 input_type
->error("Input type `%s' does not support %s encoding",
6545 input_type
->get_typename().c_str(),
6546 Type::get_encoding_name(encoding_type
));
6550 if (Common::Type::CT_XER
== encoding_type
6551 && input_type
->get_type_refd_last()->is_untagged()) {
6552 // "untagged" on the (toplevel) input type will have no effect.
6553 warning("UNTAGGED encoding attribute is ignored on top-level type");
6555 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6556 if (PROTOTYPE_CONVERT
!= prototype
) {
6557 error("Only `prototype(convert)' is allowed for custom encoding functions");
6560 // let the input type know that this is its encoding function
6561 input_type
->get_type_refd()->set_coding_function(true,
6562 get_genname_from_scope(input_type
->get_type_refd()->get_my_scope()));
6563 // treat this as a manual external function during code generation
6564 function_type
= EXTFUNC_MANUAL
;
6570 if(encoding_type
== Common::Type::CT_TEXT
) { // TEXT encoding supports both octetstring and charstring stream types
6571 Type
*stream_type
= Type::get_stream_type(encoding_type
,0);
6572 Type
*stream_type2
= Type::get_stream_type(encoding_type
,1);
6573 if ( (!stream_type
->is_identical(output_type
)) && (!stream_type2
->is_identical(output_type
)) ) {
6574 output_type
->error("The output type of %s encoding should be `%s' or `%s' "
6575 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6576 stream_type
->get_typename().c_str(),
6577 stream_type2
->get_typename().c_str(),
6578 output_type
->get_typename().c_str());
6581 Type
*stream_type
= Type::get_stream_type(encoding_type
);
6582 if (!stream_type
->is_identical(output_type
)) {
6583 output_type
->error("The output type of %s encoding should be `%s' "
6584 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6585 stream_type
->get_typename().c_str(),
6586 output_type
->get_typename().c_str());
6590 if (eb_list
) eb_list
->chk();
6591 chk_allowed_encode();
6593 case EXTFUNC_DECODE
:
6594 if (prototype
== PROTOTYPE_NONE
) {
6595 error("Attribute `decode' cannot be used without `prototype'");
6598 if(encoding_type
== Common::Type::CT_TEXT
) { // TEXT encoding supports both octetstring and charstring stream types
6599 Type
*stream_type
= Type::get_stream_type(encoding_type
,0);
6600 Type
*stream_type2
= Type::get_stream_type(encoding_type
,1);
6601 if ( (!stream_type
->is_identical(input_type
)) && (!stream_type2
->is_identical(input_type
)) ) {
6602 input_type
->error("The input type of %s decoding should be `%s' or `%s' "
6603 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6604 stream_type
->get_typename().c_str(),
6605 stream_type2
->get_typename().c_str(),
6606 input_type
->get_typename().c_str());
6609 Type
*stream_type
= Type::get_stream_type(encoding_type
);
6610 if (!stream_type
->is_identical(input_type
)) {
6611 input_type
->error("The input type of %s decoding should be `%s' "
6612 "instead of `%s'", Type::get_encoding_name(encoding_type
),
6613 stream_type
->get_typename().c_str(),
6614 input_type
->get_typename().c_str());
6619 if (output_type
&& !output_type
->has_encoding(encoding_type
, encoding_options
)) {
6620 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6621 output_type
->error("Output type `%s' does not support custom encoding '%s'",
6622 output_type
->get_typename().c_str(), encoding_options
->c_str());
6625 output_type
->error("Output type `%s' does not support %s encoding",
6626 output_type
->get_typename().c_str(),
6627 Type::get_encoding_name(encoding_type
));
6631 if (Common::Type::CT_CUSTOM
== encoding_type
) {
6632 if (PROTOTYPE_SLIDING
!= prototype
) {
6633 error("Only `prototype(sliding)' is allowed for custom decoding functions");
6635 else if (output_type
) {
6636 // let the output type know that this is its decoding function
6637 output_type
->get_type_refd()->set_coding_function(false,
6638 get_genname_from_scope(output_type
->get_type_refd()->get_my_scope()));
6639 // treat this as a manual external function during code generation
6640 function_type
= EXTFUNC_MANUAL
;
6644 if (eb_list
) eb_list
->chk();
6645 chk_allowed_encode();
6648 FATAL_ERROR("Def_ExtFunction::chk()");
6652 void Def_ExtFunction::chk_allowed_encode()
6654 switch (encoding_type
) {
6656 if (enable_ber()) return; // ok
6659 if (enable_raw()) return; // ok
6662 if (enable_text()) return; // ok
6665 if (enable_xer()) return; // ok
6668 if (enable_per()) return; // ok?
6671 if (enable_json()) return;
6673 case Type::CT_CUSTOM
:
6674 return; // cannot be disabled
6676 FATAL_ERROR("Def_ExtFunction::chk_allowed_encode");
6680 error("%s encoding is disallowed by license or commandline options",
6681 Type::get_encoding_name(encoding_type
));
6684 void Def_ExtFunction::chk()
6686 if (checked
) return;
6688 Error_Context
cntxt(this, "In external function definition `%s'",
6689 id
->get_dispname().c_str());
6690 fp_list
->chk(asstype
);
6692 Error_Context
cntxt2(return_type
, "In return type");
6694 return_type
->chk_as_return_type(asstype
== A_EXT_FUNCTION_RVAL
,
6695 "external function");
6697 if (!semantic_check_only
) fp_list
->set_genname(get_genname());
6698 if (w_attrib_path
) {
6699 w_attrib_path
->chk_global_attrib();
6700 w_attrib_path
->chk_no_qualif();
6701 const Ttcn::ExtensionAttributes
* extattrs
= parse_extattributes(w_attrib_path
);
6702 if (extattrs
!= 0) {
6703 size_t num_atrs
= extattrs
->size();
6704 for (size_t i
=0; i
< num_atrs
; ++i
) {
6705 ExtensionAttribute
&ea
= extattrs
->get(i
);
6706 switch (ea
.get_type()) {
6707 case ExtensionAttribute::PROTOTYPE
: {
6708 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE
) {
6709 ea
.error("Duplicate attribute `prototype'");
6711 Def_Function_Base::prototype_t proto
= ea
.get_proto();
6712 set_prototype(proto
);
6715 case ExtensionAttribute::ENCODE
: {
6716 switch (get_function_type()) {
6717 case Def_ExtFunction::EXTFUNC_MANUAL
:
6719 case Def_ExtFunction::EXTFUNC_ENCODE
: {
6720 ea
.error("Duplicate attribute `encode'");
6722 case Def_ExtFunction::EXTFUNC_DECODE
: {
6723 ea
.error("Attributes `decode' and `encode' "
6724 "cannot be used at the same time");
6727 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6729 Type::MessageEncodingType_t et
;
6731 ea
.get_encdec_parameters(et
, opt
);
6732 set_encode_parameters(et
, opt
);
6735 case ExtensionAttribute::ERRORBEHAVIOR
: {
6736 add_eb_list(ea
.get_eb_list());
6739 case ExtensionAttribute::DECODE
: {
6740 switch (get_function_type()) {
6741 case Def_ExtFunction::EXTFUNC_MANUAL
:
6743 case Def_ExtFunction::EXTFUNC_ENCODE
: {
6744 ea
.error("Attributes `encode' and `decode' "
6745 "cannot be used at the same time");
6747 case Def_ExtFunction::EXTFUNC_DECODE
: {
6748 ea
.error("Duplicate attribute `decode'");
6751 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6753 Type::MessageEncodingType_t et
;
6755 ea
.get_encdec_parameters(et
, opt
);
6756 set_decode_parameters(et
, opt
);
6759 case ExtensionAttribute::PRINTING
: {
6760 json_printing
= ea
.get_printing();
6763 case ExtensionAttribute::ANYTYPELIST
:
6764 // ignore, because we can't distinguish between a local
6765 // "extension anytype" (which is bogus) and an inherited one
6766 // (which was meant for a type definition)
6769 case ExtensionAttribute::NONE
:
6770 // Ignore, do not issue "wrong type" error
6775 "Only the following extension attributes may be applied to "
6776 "external functions: 'prototype', 'encode', 'decode', 'errorbehavior'");
6784 chk_function_type();
6786 if (NULL
!= json_printing
&& (EXTFUNC_ENCODE
!= function_type
||
6787 Type::CT_JSON
!= encoding_type
)) {
6788 error("Attribute 'printing' is only allowed for JSON encoding functions.");
6792 char *Def_ExtFunction::generate_code_encode(char *str
)
6794 const char *function_name
= id
->get_dispname().c_str();
6795 const char *first_par_name
=
6796 fp_list
->get_fp_byIndex(0)->get_id().get_name().c_str();
6797 // producing debug printout of the input PDU
6798 str
= mputprintf(str
,
6800 "// written by %s in " __FILE__
" at %d\n"
6802 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6803 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6804 "TTCN_Logger::log_event_str(\"%s(): Encoding %s: \");\n"
6806 "TTCN_Logger::end_event();\n"
6809 , __FUNCTION__
, __LINE__
6811 , function_name
, input_type
->get_typename().c_str(), first_par_name
);
6812 // setting error behavior
6813 if (eb_list
) str
= eb_list
->generate_code(str
);
6814 else str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6815 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6816 // encoding PDU into the buffer
6817 str
= mputstr(str
, "TTCN_Buffer ttcn_buffer;\n");
6818 str
= mputprintf(str
, "%s.encode(%s_descr_, ttcn_buffer, TTCN_EncDec::CT_%s",
6820 input_type
->get_genname_typedescriptor(my_scope
).c_str(),
6821 Type::get_encoding_name(encoding_type
));
6822 if (encoding_type
== Type::CT_JSON
) {
6823 if (json_printing
!= NULL
) {
6824 str
= json_printing
->generate_code(str
);
6826 str
= mputstr(str
, ", 0");
6829 if (encoding_options
) str
= mputprintf(str
, ", %s",
6830 encoding_options
->c_str());
6831 str
= mputstr(str
, ");\n");
6832 const char *result_name
;
6833 switch (prototype
) {
6834 case PROTOTYPE_CONVERT
:
6835 result_name
= "ret_val";
6836 // creating a local variable for the result stream
6837 str
= mputprintf(str
, "%s ret_val;\n",
6838 output_type
->get_genname_value(my_scope
).c_str());
6840 case PROTOTYPE_FAST
:
6841 result_name
= fp_list
->get_fp_byIndex(1)->get_id().get_name().c_str();
6844 FATAL_ERROR("Def_ExtFunction::generate_code_encode()");
6847 // taking the result from the buffer and producing debug printout
6848 str
= mputprintf(str
, "ttcn_buffer.get_string(%s);\n"
6849 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6850 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6851 "TTCN_Logger::log_event_str(\"%s(): Stream after encoding: \");\n"
6853 "TTCN_Logger::end_event();\n"
6854 "}\n", result_name
, function_name
, result_name
);
6855 // returning the result stream if necessary
6856 if (prototype
== PROTOTYPE_CONVERT
) {
6857 if (debugger_active
) {
6859 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
6860 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
6862 str
= mputstr(str
, "return ret_val;\n");
6867 char *Def_ExtFunction::generate_code_decode(char *str
)
6869 const char *function_name
= id
->get_dispname().c_str();
6870 const char *first_par_name
=
6871 fp_list
->get_fp_byIndex(0)->get_id().get_name().c_str();
6872 // producing debug printout of the input stream
6873 str
= mputprintf(str
,
6875 "// written by %s in " __FILE__
" at %d\n"
6877 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6878 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6879 "TTCN_Logger::log_event_str(\"%s(): Stream before decoding: \");\n"
6881 "TTCN_Logger::end_event();\n"
6884 , __FUNCTION__
, __LINE__
6886 , function_name
, first_par_name
);
6887 // setting error behavior
6888 if (eb_list
) str
= eb_list
->generate_code(str
);
6889 else if (prototype
== PROTOTYPE_BACKTRACK
|| prototype
== PROTOTYPE_SLIDING
) {
6890 str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6891 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n");
6892 } else str
= mputstr(str
, "TTCN_EncDec::set_error_behavior("
6893 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6894 // creating a buffer from the input stream
6895 str
= mputprintf(str
, "TTCN_EncDec::clear_error();\n"
6896 "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name
);
6897 const char *result_name
;
6898 if (prototype
== PROTOTYPE_CONVERT
) {
6899 // creating a local variable for the result
6900 str
= mputprintf(str
, "%s ret_val;\n",
6901 output_type
->get_genname_value(my_scope
).c_str());
6902 result_name
= "ret_val";
6904 result_name
= fp_list
->get_fp_byIndex(1)->get_id().get_name().c_str();
6906 if(encoding_type
==Type::CT_TEXT
){
6907 str
= mputprintf(str
,
6908 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6909 " TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_LOG_MATCHING, TTCN_EncDec::EB_WARNING);\n"
6912 str
= mputprintf(str
, "%s.decode(%s_descr_, ttcn_buffer, "
6913 "TTCN_EncDec::CT_%s", result_name
,
6914 output_type
->get_genname_typedescriptor(my_scope
).c_str(),
6915 Type::get_encoding_name(encoding_type
));
6916 if (encoding_options
) str
= mputprintf(str
, ", %s",
6917 encoding_options
->c_str());
6918 str
= mputstr(str
, ");\n");
6919 // producing debug printout of the result PDU
6920 str
= mputprintf(str
,
6921 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6922 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6923 "TTCN_Logger::log_event_str(\"%s(): Decoded %s: \");\n"
6925 "TTCN_Logger::end_event();\n"
6926 "}\n", function_name
, output_type
->get_typename().c_str(), result_name
);
6927 if (prototype
!= PROTOTYPE_SLIDING
) {
6928 // checking for remaining data in the buffer if decoding was successful
6929 str
= mputprintf(str
, "if (TTCN_EncDec::get_last_error_type() == "
6930 "TTCN_EncDec::ET_NONE) {\n"
6931 "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
6932 "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
6933 "ttcn_buffer.cut();\n"
6934 "%s remaining_stream;\n"
6935 "ttcn_buffer.get_string(remaining_stream);\n"
6936 "TTCN_Logger::begin_event(TTCN_WARNING);\n"
6937 "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
6938 "of the stream after successful decoding: \");\n"
6939 "remaining_stream.log();\n"
6940 "TTCN_Logger::end_event();\n"
6941 "}\n", input_type
->get_genname_value(my_scope
).c_str(), function_name
);
6942 // closing the block and returning the appropriate result or status code
6943 if (prototype
== PROTOTYPE_BACKTRACK
) {
6944 if (debugger_active
) {
6945 str
= mputstr(str
, "ttcn3_debugger.set_return_value(\"0\");\n");
6950 if (debugger_active
) {
6951 str
= mputstr(str
, "ttcn3_debugger.set_return_value(\"1\");\n");
6957 str
= mputstr(str
, "}\n");
6958 if (prototype
== PROTOTYPE_CONVERT
) {
6959 if (debugger_active
) {
6961 "ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), "
6962 "ret_val.log(), TTCN_Logger::end_event_log2str()));\n");
6964 str
= mputstr(str
, "return ret_val;\n");
6968 // result handling and debug printout for sliding decoders
6969 str
= mputprintf(str
, "switch (TTCN_EncDec::get_last_error_type()) {\n"
6970 "case TTCN_EncDec::ET_NONE:\n"
6971 // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
6972 "ttcn_buffer.cut();\n"
6973 "ttcn_buffer.get_string(%s);\n"
6974 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6975 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6976 "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
6978 "TTCN_Logger::end_event();\n"
6981 "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
6982 "case TTCN_EncDec::ET_LEN_ERR:\n"
6986 "}\n", first_par_name
, function_name
, first_par_name
,
6987 debugger_active
? "ttcn3_debugger.set_return_value(\"0\");\n" : "",
6988 debugger_active
? "ttcn3_debugger.set_return_value(\"2\");\n" : "",
6989 debugger_active
? "ttcn3_debugger.set_return_value(\"1\");\n" : "");
6994 void Def_ExtFunction::generate_code(output_struct
*target
, bool)
6996 const string
& t_genname
= get_genname();
6997 const char *genname_str
= t_genname
.c_str();
6998 string return_type_name
;
7000 case A_EXT_FUNCTION
:
7001 return_type_name
= "void";
7003 case A_EXT_FUNCTION_RVAL
:
7004 return_type_name
= return_type
->get_genname_value(my_scope
);
7006 case A_EXT_FUNCTION_RTEMP
:
7007 return_type_name
= return_type
->get_genname_template(my_scope
);
7010 FATAL_ERROR("Def_ExtFunction::generate_code()");
7012 const char *return_type_str
= return_type_name
.c_str();
7013 char *formal_par_list
= fp_list
->generate_code(memptystr(), fp_list
->get_nof_fps());
7014 fp_list
->generate_code_defval(target
);
7015 // function prototype
7016 target
->header
.function_prototypes
=
7017 mputprintf(target
->header
.function_prototypes
, "extern %s %s(%s);\n",
7018 return_type_str
, genname_str
, formal_par_list
);
7020 if (function_type
!= EXTFUNC_MANUAL
) {
7021 // function body written by the compiler
7024 body
= mprintf("// written by %s in " __FILE__
" at %d\n"
7025 , __FUNCTION__
, __LINE__
);
7027 body
= mputprintf(body
,
7030 , return_type_str
, genname_str
, formal_par_list
);
7031 if (debugger_active
) {
7032 body
= generate_code_debugger_function_init(body
, this);
7034 switch (function_type
) {
7035 case EXTFUNC_ENCODE
:
7036 body
= generate_code_encode(body
);
7038 case EXTFUNC_DECODE
:
7039 body
= generate_code_decode(body
);
7042 FATAL_ERROR("Def_ExtFunction::generate_code()");
7044 body
= mputstr(body
, "}\n\n");
7045 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7050 Free(formal_par_list
);
7052 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7053 "%s.add_function(\"%s\", (genericfunc_t)&%s, NULL);\n",
7054 get_module_object_name(), id
->get_dispname().c_str(), genname_str
);
7057 void Def_ExtFunction::generate_code(CodeGenHelper
& cgh
) {
7058 generate_code(cgh
.get_current_outputstruct());
7061 void Def_ExtFunction::dump_internal(unsigned level
) const
7063 DEBUG(level
, "External function: %s", id
->get_dispname().c_str());
7064 DEBUG(level
+ 1, "Parameters:");
7065 fp_list
->dump(level
+ 2);
7067 DEBUG(level
+ 1, "Return type:");
7068 return_type
->dump(level
+ 2);
7069 if(asstype
== A_EXT_FUNCTION_RTEMP
) DEBUG(level
+ 1, "Returns template");
7071 if (prototype
!= PROTOTYPE_NONE
)
7072 DEBUG(level
+ 1, "Prototype: %s", get_prototype_name());
7073 if (function_type
!= EXTFUNC_MANUAL
) {
7074 DEBUG(level
+ 1, "Automatically generated: %s",
7075 function_type
== EXTFUNC_ENCODE
? "encoder" : "decoder");
7076 DEBUG(level
+ 2, "Encoding type: %s",
7077 Type::get_encoding_name(encoding_type
));
7078 if (encoding_options
)
7079 DEBUG(level
+ 2, "Encoding options: %s", encoding_options
->c_str());
7081 if (eb_list
) eb_list
->dump(level
+ 1);
7084 void Def_ExtFunction::generate_json_schema_ref(map
<Type
*, JSON_Tokenizer
>& json_refs
)
7086 // only do anything if this is a JSON encoding or decoding function
7087 if (encoding_type
== Type::CT_JSON
&&
7088 (function_type
== EXTFUNC_ENCODE
|| function_type
== EXTFUNC_DECODE
)) {
7089 // retrieve the encoded type
7091 if (function_type
== EXTFUNC_ENCODE
) {
7092 // for encoding functions it's always the first parameter
7093 type
= fp_list
->get_fp_byIndex(0)->get_Type();
7095 // for decoding functions it depends on the prototype
7096 switch (prototype
) {
7097 case PROTOTYPE_CONVERT
:
7100 case PROTOTYPE_FAST
:
7101 case PROTOTYPE_BACKTRACK
:
7102 case PROTOTYPE_SLIDING
:
7103 type
= fp_list
->get_fp_byIndex(1)->get_Type();
7106 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
7110 // step over the type reference created for this function
7111 type
= type
->get_type_refd();
7113 JSON_Tokenizer
* json
= NULL
;
7114 if (json_refs
.has_key(type
)) {
7115 // the schema segment containing the type's reference already exists
7116 json
= json_refs
[type
];
7118 // the schema segment doesn't exist yet, create it and insert the reference
7119 json
= new JSON_Tokenizer
;
7120 json_refs
.add(type
, json
);
7121 type
->generate_json_schema_ref(*json
);
7124 // insert a property to specify which function this is (encoding or decoding)
7125 json
->put_next_token(JSON_TOKEN_NAME
, (function_type
== EXTFUNC_ENCODE
) ?
7126 "encoding" : "decoding");
7128 // place the function's info in an object
7129 json
->put_next_token(JSON_TOKEN_OBJECT_START
);
7131 // insert information related to the function's prototype in an array
7132 json
->put_next_token(JSON_TOKEN_NAME
, "prototype");
7133 json
->put_next_token(JSON_TOKEN_ARRAY_START
);
7135 // 1st element: external function prototype name (as string)
7137 case PROTOTYPE_CONVERT
:
7138 json
->put_next_token(JSON_TOKEN_STRING
, "\"convert\"");
7140 case PROTOTYPE_FAST
:
7141 json
->put_next_token(JSON_TOKEN_STRING
, "\"fast\"");
7143 case PROTOTYPE_BACKTRACK
:
7144 json
->put_next_token(JSON_TOKEN_STRING
, "\"backtrack\"");
7146 case PROTOTYPE_SLIDING
:
7147 json
->put_next_token(JSON_TOKEN_STRING
, "\"sliding\"");
7150 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
7153 // 2nd element: external function name
7154 char* func_name_str
= mprintf("\"%s\"", id
->get_dispname().c_str());
7155 json
->put_next_token(JSON_TOKEN_STRING
, func_name_str
);
7156 Free(func_name_str
);
7158 // the rest of the elements contain the names of the function's parameters (1 or 2)
7159 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7160 char* param_str
= mprintf("\"%s\"",
7161 fp_list
->get_fp_byIndex(i
)->get_id().get_dispname().c_str());
7162 json
->put_next_token(JSON_TOKEN_STRING
, param_str
);
7166 // end of the prototype's array
7167 json
->put_next_token(JSON_TOKEN_ARRAY_END
);
7169 // insert error behavior data
7170 if (eb_list
!= NULL
) {
7171 json
->put_next_token(JSON_TOKEN_NAME
, "errorBehavior");
7172 json
->put_next_token(JSON_TOKEN_OBJECT_START
);
7174 // add each error behavior modification as a property
7175 for (size_t i
= 0; i
< eb_list
->get_nof_ebs(); ++i
) {
7176 ErrorBehaviorSetting
* eb
= eb_list
->get_ebs_byIndex(i
);
7177 json
->put_next_token(JSON_TOKEN_NAME
, eb
->get_error_type().c_str());
7178 char* handling_str
= mprintf("\"%s\"", eb
->get_error_handling().c_str());
7179 json
->put_next_token(JSON_TOKEN_STRING
, handling_str
);
7183 json
->put_next_token(JSON_TOKEN_OBJECT_END
);
7186 // insert printing type
7187 if (json_printing
!= NULL
) {
7188 json
->put_next_token(JSON_TOKEN_NAME
, "printing");
7189 json
->put_next_token(JSON_TOKEN_STRING
,
7190 (json_printing
->get_printing() == PrintingType::PT_PRETTY
) ?
7191 "\"pretty\"" : "\"compact\"");
7194 // end of this function's object
7195 json
->put_next_token(JSON_TOKEN_OBJECT_END
);
7199 // =================================
7200 // ===== Def_Altstep
7201 // =================================
7203 Def_Altstep::Def_Altstep(Identifier
*p_id
, FormalParList
*p_fpl
,
7204 Reference
*p_runs_on_ref
, StatementBlock
*p_sb
,
7206 : Definition(A_ALTSTEP
, p_id
), fp_list(p_fpl
), runs_on_ref(p_runs_on_ref
),
7207 runs_on_type(0), sb(p_sb
), ags(p_ags
)
7209 if (!p_fpl
|| !p_sb
|| !p_ags
)
7210 FATAL_ERROR("Def_Altstep::Def_Altstep()");
7211 fp_list
->set_my_def(this);
7212 sb
->set_my_def(this);
7213 ags
->set_my_def(this);
7214 ags
->set_my_sb(sb
, 0);
7217 Def_Altstep::~Def_Altstep()
7225 Def_Altstep
*Def_Altstep::clone() const
7227 FATAL_ERROR("Def_Altstep::clone");
7230 void Def_Altstep::set_fullname(const string
& p_fullname
)
7232 Definition::set_fullname(p_fullname
);
7233 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
7234 if (runs_on_ref
) runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
7235 sb
->set_fullname(p_fullname
+".<block>");
7236 ags
->set_fullname(p_fullname
+ ".<guards>");
7239 void Def_Altstep::set_my_scope(Scope
*p_scope
)
7241 bridgeScope
.set_parent_scope(p_scope
);
7242 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
7244 Definition::set_my_scope(&bridgeScope
);
7245 // the scope of the parameter list is set during checking
7246 if (runs_on_ref
) runs_on_ref
->set_my_scope(&bridgeScope
);
7247 sb
->set_my_scope(fp_list
);
7248 ags
->set_my_scope(sb
);
7251 Type
*Def_Altstep::get_RunsOnType()
7253 if (!checked
) chk();
7254 return runs_on_type
;
7257 FormalParList
*Def_Altstep::get_FormalParList()
7259 if (!checked
) chk();
7263 RunsOnScope
*Def_Altstep::get_runs_on_scope(Type
*comptype
)
7265 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
7266 if (!my_module
) FATAL_ERROR("Def_Altstep::get_runs_on_scope()");
7267 return my_module
->get_runs_on_scope(comptype
);
7270 void Def_Altstep::chk()
7272 if (checked
) return;
7274 Error_Context
cntxt(this, "In altstep definition `%s'",
7275 id
->get_dispname().c_str());
7276 Scope
*parlist_scope
= my_scope
;
7278 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
7279 runs_on_type
= runs_on_ref
->chk_comptype_ref();
7281 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
7282 runs_on_scope
->set_parent_scope(my_scope
);
7283 parlist_scope
= runs_on_scope
;
7286 fp_list
->set_my_scope(parlist_scope
);
7287 fp_list
->chk(asstype
);
7289 ags
->set_is_altstep();
7290 ags
->set_my_ags(ags
);
7291 ags
->set_my_laic_stmt(ags
, 0);
7293 if (!semantic_check_only
) {
7294 fp_list
->set_genname(get_genname());
7295 sb
->set_code_section(GovernedSimple::CS_INLINE
);
7296 ags
->set_code_section(GovernedSimple::CS_INLINE
);
7298 if (w_attrib_path
) {
7299 w_attrib_path
->chk_global_attrib();
7300 w_attrib_path
->chk_no_qualif();
7304 void Def_Altstep::generate_code(output_struct
*target
, bool)
7306 const string
& t_genname
= get_genname();
7307 const char *genname_str
= t_genname
.c_str();
7308 const char *dispname_str
= id
->get_dispname().c_str();
7310 // function for altstep instance:
7311 // assemble the function body first (this also determines which parameters
7313 char* body
= create_location_object(memptystr(), "ALTSTEP", dispname_str
);
7314 body
= fp_list
->generate_shadow_objects(body
);
7315 if (debugger_active
) {
7316 body
= generate_code_debugger_function_init(body
, this);
7318 body
= sb
->generate_code(body
);
7319 body
= ags
->generate_code_altstep(body
);
7320 // generate a smart formal parameter list (omits unused parameter names)
7321 char *formal_par_list
= fp_list
->generate_code(memptystr());
7322 fp_list
->generate_code_defval(target
);
7324 // function for altstep instance: prototype
7325 target
->header
.function_prototypes
=
7326 mputprintf(target
->header
.function_prototypes
,
7327 "extern alt_status %s_instance(%s);\n", genname_str
, formal_par_list
);
7329 // function for altstep instance: body
7330 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7331 "alt_status %s_instance(%s)\n"
7334 "}\n\n", genname_str
, formal_par_list
, body
);
7335 Free(formal_par_list
);
7338 char *actual_par_list
=
7339 fp_list
->generate_code_actual_parlist(memptystr(), "");
7341 // use a full formal parameter list for the rest of the functions
7342 char *full_formal_par_list
= fp_list
->generate_code(memptystr(),
7343 fp_list
->get_nof_fps());
7345 // wrapper function for stand-alone instantiation: prototype
7346 target
->header
.function_prototypes
=
7347 mputprintf(target
->header
.function_prototypes
,
7348 "extern void %s(%s);\n", genname_str
, full_formal_par_list
);
7350 // wrapper function for stand-alone instantiation: body
7351 target
->source
.function_bodies
=
7352 mputprintf(target
->source
.function_bodies
, "void %s(%s)\n"
7355 "boolean block_flag = FALSE;\n"
7356 "alt_status altstep_flag = ALT_UNCHECKED, "
7357 "default_flag = ALT_UNCHECKED;\n"
7359 "TTCN_Snapshot::take_new(block_flag);\n"
7360 "if (altstep_flag != ALT_NO) {\n"
7361 "altstep_flag = %s_instance(%s);\n"
7362 "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
7363 "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
7365 "if (default_flag != ALT_NO) {\n"
7366 "default_flag = TTCN_Default::try_altsteps();\n"
7367 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
7368 "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
7370 "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
7371 "TTCN_error(\"None of the branches can be chosen in altstep %s.\");\n"
7372 "else block_flag = TRUE;\n"
7374 "}\n\n", genname_str
, full_formal_par_list
, genname_str
, actual_par_list
,
7377 // class for keeping the altstep in the default context
7378 // the class is for internal use, we do not need to publish it in the
7380 char* str
= mprintf("class %s_Default : public Default_Base {\n", genname_str
);
7381 str
= fp_list
->generate_code_object(str
, "par_");
7382 str
= mputprintf(str
, "public:\n"
7384 "alt_status call_altstep();\n"
7385 "};\n\n", genname_str
, full_formal_par_list
);
7386 target
->source
.class_defs
= mputstr(target
->source
.class_defs
, str
);
7388 // member functions of the class
7389 str
= mprintf("%s_Default::%s_Default(%s)\n"
7390 " : Default_Base(\"%s\")", genname_str
, genname_str
, full_formal_par_list
,
7392 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); i
++) {
7393 const char *fp_name_str
=
7394 fp_list
->get_fp_byIndex(i
)->get_id().get_name().c_str();
7395 str
= mputprintf(str
, ", par_%s(%s)", fp_name_str
, fp_name_str
);
7397 str
= mputstr(str
, "\n{\n}\n\n");
7398 char *actual_par_list_prefixed
=
7399 fp_list
->generate_code_actual_parlist(memptystr(), "par_");
7400 str
= mputprintf(str
, "alt_status %s_Default::call_altstep()\n"
7402 "return %s_instance(%s);\n"
7403 "}\n\n", genname_str
, genname_str
, actual_par_list_prefixed
);
7404 Free(actual_par_list_prefixed
);
7405 target
->source
.methods
= mputstr(target
->source
.methods
, str
);
7408 // function for default activation: prototype
7409 target
->header
.function_prototypes
=
7410 mputprintf(target
->header
.function_prototypes
,
7411 "extern Default_Base *activate_%s(%s);\n", genname_str
,
7412 full_formal_par_list
);
7414 // function for default activation: body
7415 str
= mprintf("Default_Base *activate_%s(%s)\n"
7416 "{\n", genname_str
, full_formal_par_list
);
7417 str
= mputprintf(str
, "return new %s_Default(%s);\n"
7418 "}\n\n", genname_str
, actual_par_list
);
7419 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7423 Free(full_formal_par_list
);
7424 Free(actual_par_list
);
7426 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7427 "%s.add_altstep(\"%s\", (genericfunc_t)&%s_instance, (genericfunc_t )&activate_%s, "
7428 "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str
, genname_str
,
7429 genname_str
, genname_str
);
7432 void Def_Altstep::generate_code(CodeGenHelper
& cgh
) {
7433 generate_code(cgh
.get_current_outputstruct());
7436 void Def_Altstep::dump_internal(unsigned level
) const
7438 DEBUG(level
, "Altstep: %s", id
->get_dispname().c_str());
7439 DEBUG(level
+ 1, "Parameters:");
7440 fp_list
->dump(level
+ 1);
7442 DEBUG(level
+ 1, "Runs on clause:");
7443 runs_on_ref
->dump(level
+ 2);
7446 DEBUG(level + 1, "Local definitions:");
7447 sb->dump(level + 2);
7449 DEBUG(level
+ 1, "Guards:");
7450 ags
->dump(level
+ 2);
7453 void Def_Altstep::set_parent_path(WithAttribPath
* p_path
) {
7454 Definition::set_parent_path(p_path
);
7455 sb
->set_parent_path(w_attrib_path
);
7458 // =================================
7459 // ===== Def_Testcase
7460 // =================================
7462 Def_Testcase::Def_Testcase(Identifier
*p_id
, FormalParList
*p_fpl
,
7463 Reference
*p_runs_on_ref
, Reference
*p_system_ref
,
7464 StatementBlock
*p_block
)
7465 : Definition(A_TESTCASE
, p_id
), fp_list(p_fpl
), runs_on_ref(p_runs_on_ref
),
7466 runs_on_type(0), system_ref(p_system_ref
), system_type(0), block(p_block
)
7468 if (!p_fpl
|| !p_runs_on_ref
|| !p_block
)
7469 FATAL_ERROR("Def_Testcase::Def_Testcase()");
7470 fp_list
->set_my_def(this);
7471 block
->set_my_def(this);
7474 Def_Testcase::~Def_Testcase()
7482 Def_Testcase
*Def_Testcase::clone() const
7484 FATAL_ERROR("Def_Testcase::clone");
7487 void Def_Testcase::set_fullname(const string
& p_fullname
)
7489 Definition::set_fullname(p_fullname
);
7490 fp_list
->set_fullname(p_fullname
+ ".<formal_par_list>");
7491 runs_on_ref
->set_fullname(p_fullname
+ ".<runs_on_type>");
7492 if (system_ref
) system_ref
->set_fullname(p_fullname
+ ".<system_type>");
7493 block
->set_fullname(p_fullname
+ ".<statement_block>");
7496 void Def_Testcase::set_my_scope(Scope
*p_scope
)
7498 bridgeScope
.set_parent_scope(p_scope
);
7499 bridgeScope
.set_scopeMacro_name(id
->get_dispname());
7501 Definition::set_my_scope(&bridgeScope
);
7502 // the scope of the parameter list is set during checking
7503 runs_on_ref
->set_my_scope(&bridgeScope
);
7504 if (system_ref
) system_ref
->set_my_scope(&bridgeScope
);
7505 block
->set_my_scope(fp_list
);
7508 Type
*Def_Testcase::get_RunsOnType()
7510 if (!checked
) chk();
7511 return runs_on_type
;
7514 Type
*Def_Testcase::get_SystemType()
7516 if (!checked
) chk();
7520 FormalParList
*Def_Testcase::get_FormalParList()
7522 if (!checked
) chk();
7526 RunsOnScope
*Def_Testcase::get_runs_on_scope(Type
*comptype
)
7528 Module
*my_module
= dynamic_cast<Module
*>(my_scope
->get_scope_mod());
7529 if (!my_module
) FATAL_ERROR("Def_Testcase::get_runs_on_scope()");
7530 return my_module
->get_runs_on_scope(comptype
);
7533 void Def_Testcase::chk()
7535 if (checked
) return;
7537 Error_Context
cntxt(this, "In testcase definition `%s'",
7538 id
->get_dispname().c_str());
7539 Scope
*parlist_scope
= my_scope
;
7541 Error_Context
cntxt2(runs_on_ref
, "In `runs on' clause");
7542 runs_on_type
= runs_on_ref
->chk_comptype_ref();
7544 Scope
*runs_on_scope
= get_runs_on_scope(runs_on_type
);
7545 runs_on_scope
->set_parent_scope(my_scope
);
7546 parlist_scope
= runs_on_scope
;
7550 Error_Context
cntxt2(system_ref
, "In `system' clause");
7551 system_type
= system_ref
->chk_comptype_ref();;
7553 fp_list
->set_my_scope(parlist_scope
);
7554 fp_list
->chk(asstype
);
7556 if (!semantic_check_only
) {
7557 fp_list
->set_genname(get_genname());
7558 block
->set_code_section(GovernedSimple::CS_INLINE
);
7560 if (w_attrib_path
) {
7561 w_attrib_path
->chk_global_attrib();
7562 w_attrib_path
->chk_no_qualif();
7566 void Def_Testcase::generate_code(output_struct
*target
, bool)
7568 const string
& t_genname
= get_genname();
7569 const char *genname_str
= t_genname
.c_str();
7570 const char *dispname_str
= id
->get_dispname().c_str();
7572 // assemble the function body first (this also determines which parameters
7575 // Checking whether the testcase was invoked from another one.
7576 // At this point the location information should refer to the execute()
7577 // statement rather than this testcase.
7578 char* body
= mputstr(memptystr(), "TTCN_Runtime::check_begin_testcase(has_timer, "
7580 body
= create_location_object(body
, "TESTCASE", dispname_str
);
7581 body
= fp_list
->generate_shadow_objects(body
);
7582 if (debugger_active
) {
7583 body
= generate_code_debugger_function_init(body
, this);
7585 body
= mputprintf(body
, "try {\n"
7586 "TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
7587 my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
7589 ComponentTypeBody
*runs_on_body
= runs_on_type
->get_CompBody();
7590 body
= runs_on_body
->generate_code_comptype_name(body
);
7591 body
= mputstr(body
, ", ");
7593 body
= system_type
->get_CompBody()->generate_code_comptype_name(body
);
7594 else body
= runs_on_body
->generate_code_comptype_name(body
);
7595 body
= mputstr(body
, ", has_timer, timer_value);\n");
7596 body
= block
->generate_code(body
);
7597 body
= mputprintf(body
,
7598 "} catch (const TC_Error& tc_error) {\n"
7599 "} catch (const TC_End& tc_end) {\n"
7600 "TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
7601 "}\n", dispname_str
);
7602 body
= mputstr(body
, "return TTCN_Runtime::end_testcase();\n");
7604 // smart formal parameter list (names of unused parameters are omitted)
7605 char *formal_par_list
= fp_list
->generate_code(memptystr());
7606 fp_list
->generate_code_defval(target
);
7607 if (fp_list
->get_nof_fps() > 0)
7608 formal_par_list
= mputstr(formal_par_list
, ", ");
7609 formal_par_list
= mputstr(formal_par_list
,
7610 "boolean has_timer, double timer_value");
7612 // function prototype
7613 target
->header
.function_prototypes
=
7614 mputprintf(target
->header
.function_prototypes
,
7615 "extern verdicttype testcase_%s(%s);\n", genname_str
, formal_par_list
);
7618 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7619 "verdicttype testcase_%s(%s)\n"
7622 "}\n\n", genname_str
, formal_par_list
, body
);
7623 Free(formal_par_list
);
7626 if (fp_list
->get_nof_fps() == 0) {
7627 // adding to the list of startable testcases
7628 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7629 "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
7630 get_module_object_name(), dispname_str
, genname_str
);
7632 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7633 "%s.add_testcase_pard(\"%s\", (genericfunc_t)&testcase_%s);\n",
7634 get_module_object_name(), dispname_str
, genname_str
);
7636 // If every formal parameter has a default value, the testcase
7637 // might be callable after all.
7638 bool callable
= true;
7639 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7640 FormalPar
*fp
= fp_list
->get_fp_byIndex(i
);
7641 if (!fp
->has_defval()) {
7648 // Write a wrapper, which acts as a no-param testcase
7649 // by calling the parameterized testcase with the default values.
7650 target
->header
.function_prototypes
=
7651 mputprintf(target
->header
.function_prototypes
,
7652 "extern verdicttype testcase_%s_defparams(boolean has_timer, double timer_value);\n",
7654 target
->source
.function_bodies
= mputprintf(target
->source
.function_bodies
,
7655 "verdicttype testcase_%s_defparams(boolean has_timer, double timer_value) {\n"
7656 " return testcase_%s(",
7657 genname_str
, genname_str
);
7659 for (size_t i
= 0; i
< fp_list
->get_nof_fps(); ++i
) {
7660 FormalPar
*fp
= fp_list
->get_fp_byIndex(i
);
7661 ActualPar
*ap
= fp
->get_defval();
7662 switch (ap
->get_selection()) {
7663 case ActualPar::AP_VALUE
:
7664 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7665 ap
->get_Value()->get_genname_own(my_scope
).c_str());
7667 case ActualPar::AP_TEMPLATE
:
7668 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7669 ap
->get_TemplateInstance()->get_Template()->get_genname_own(my_scope
).c_str());
7671 case ActualPar::AP_REF
:
7672 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7673 ap
->get_Ref()->get_refd_assignment()->get_genname_from_scope(my_scope
).c_str());
7675 case ActualPar::AP_DEFAULT
:
7676 // Can't happen. This ActualPar was created by
7677 // Ttcn::FormalPar::chk_actual_par as the default value for
7678 // a FormalPar, and it only ever creates vale, template or ref.
7681 FATAL_ERROR("Def_Testcase::generate_code()");
7684 // always append a comma, because has_timer and timer_value follows
7685 target
->source
.function_bodies
= mputstrn(target
->source
.function_bodies
,
7689 target
->source
.function_bodies
= mputstr(target
->source
.function_bodies
,
7690 "has_timer, timer_value);\n"
7692 // Add the non-parameterized wrapper *after* the parameterized one,
7693 // with the same name. Linear search will always find the first
7694 // (user-visible, parameterized) testcase.
7695 // TTCN_Module::execute_testcase knows that if after a parameterized
7696 // testcase another testcase with the same name follows,
7697 // it's the callable, non-parameterized wrapper.
7699 // TTCN_Module::list_testcases skips parameterized testcases;
7700 // it will now list the non-parameterized wrapper.
7701 target
->functions
.pre_init
= mputprintf(target
->functions
.pre_init
,
7702 "%s.add_testcase_nonpard(\"%s\", testcase_%s_defparams);\n",
7703 get_module_object_name(), dispname_str
, genname_str
);
7705 } // has formal parameters
7708 void Def_Testcase::generate_code(CodeGenHelper
& cgh
) {
7709 generate_code(cgh
.get_current_outputstruct());
7712 void Def_Testcase::dump_internal(unsigned level
) const
7714 DEBUG(level
, "Testcase: %s", id
->get_dispname().c_str());
7715 DEBUG(level
+ 1, "Parameters:");
7716 fp_list
->dump(level
+ 1);
7717 DEBUG(level
+ 1, "Runs on clause:");
7718 runs_on_ref
->dump(level
+ 2);
7720 DEBUG(level
+ 1, "System clause:");
7721 system_ref
->dump(level
+ 2);
7723 DEBUG(level
+ 1, "Statement block:");
7724 block
->dump(level
+ 2);
7727 void Def_Testcase::set_parent_path(WithAttribPath
* p_path
) {
7728 Definition::set_parent_path(p_path
);
7730 block
->set_parent_path(w_attrib_path
);
7733 // =================================
7735 // =================================
7737 FormalPar::FormalPar(asstype_t p_asstype
, Type
*p_type
, Identifier
* p_name
,
7738 TemplateInstance
*p_defval
, bool p_lazy_eval
)
7739 : Definition(p_asstype
, p_name
), type(p_type
), my_parlist(0),
7740 used_as_lvalue(false), template_restriction(TR_NONE
),
7741 lazy_eval(p_lazy_eval
), defval_generated(false), usage_found(false)
7743 switch (p_asstype
) {
7747 case A_PAR_VAL_INOUT
:
7748 case A_PAR_TEMPL_IN
:
7749 case A_PAR_TEMPL_OUT
:
7750 case A_PAR_TEMPL_INOUT
:
7754 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7757 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7758 type
->set_ownertype(Type::OT_FORMAL_PAR
, this);
7759 defval
.ti
= p_defval
;
7762 FormalPar::FormalPar(asstype_t p_asstype
,
7763 template_restriction_t p_template_restriction
, Type
*p_type
,
7764 Identifier
* p_name
, TemplateInstance
*p_defval
, bool p_lazy_eval
)
7765 : Definition(p_asstype
, p_name
), type(p_type
), my_parlist(0),
7766 used_as_lvalue(false), template_restriction(p_template_restriction
),
7767 lazy_eval(p_lazy_eval
), defval_generated(false), usage_found(false)
7769 switch (p_asstype
) {
7770 case A_PAR_TEMPL_IN
:
7771 case A_PAR_TEMPL_OUT
:
7772 case A_PAR_TEMPL_INOUT
:
7775 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): parameter not template");
7778 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7779 type
->set_ownertype(Type::OT_FORMAL_PAR
, this);
7780 defval
.ti
= p_defval
;
7783 FormalPar::FormalPar(asstype_t p_asstype
, Identifier
* p_name
,
7784 TemplateInstance
*p_defval
)
7785 : Definition(p_asstype
, p_name
), type(0), my_parlist(0),
7786 used_as_lvalue(false), template_restriction(TR_NONE
), lazy_eval(false),
7787 defval_generated(false), usage_found(false)
7789 if (p_asstype
!= A_PAR_TIMER
)
7790 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7791 defval
.ti
= p_defval
;
7794 FormalPar::~FormalPar()
7797 if (checked
) delete defval
.ap
;
7798 else delete defval
.ti
;
7801 FormalPar
* FormalPar::clone() const
7803 FATAL_ERROR("FormalPar::clone");
7806 void FormalPar::set_fullname(const string
& p_fullname
)
7808 Definition::set_fullname(p_fullname
);
7809 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
7811 if (defval
.ap
) defval
.ap
->set_fullname(p_fullname
+ ".<default_value>");
7813 if (defval
.ti
) defval
.ti
->set_fullname(p_fullname
+ ".<default_value>");
7817 void FormalPar::set_my_scope(Scope
*p_scope
)
7819 Definition::set_my_scope(p_scope
);
7820 if (type
) type
->set_my_scope(p_scope
);
7822 if (defval
.ap
) defval
.ap
->set_my_scope(p_scope
);
7824 if (defval
.ti
) defval
.ti
->set_my_scope(p_scope
);
7828 bool FormalPar::is_local() const
7833 Type
*FormalPar::get_Type()
7835 if (!checked
) chk();
7836 if (!type
) FATAL_ERROR("FormalPar::get_Type()");
7840 void FormalPar::chk()
7842 if (checked
) return;
7844 TemplateInstance
*default_value
= defval
.ti
;
7848 Type
*t
= type
->get_type_refd_last();
7849 // checks for forbidden type <-> parameter combinations
7850 switch (t
->get_typetype()) {
7854 case A_PAR_VAL_INOUT
:
7855 asstype
= A_PAR_PORT
;
7858 error("Port type `%s' cannot be used as %s",
7859 t
->get_fullname().c_str(), get_assname());
7862 case Type::T_SIGNATURE
:
7864 case A_PAR_TEMPL_IN
:
7865 case A_PAR_TEMPL_OUT
:
7866 case A_PAR_TEMPL_INOUT
:
7869 error("Signature `%s' cannot be used as %s",
7870 t
->get_fullname().c_str(), get_assname());
7877 FATAL_ERROR("FormalPar::chk()");
7879 asstype
= A_PAR_VAL_IN
;
7884 } else if (asstype
!= A_PAR_TIMER
) FATAL_ERROR("FormalPar::chk()");
7886 if (default_value
) {
7887 Error_Context
cntxt(default_value
, "In default value");
7888 defval
.ap
= chk_actual_par(default_value
, Type::EXPECTED_STATIC_VALUE
);
7889 delete default_value
;
7890 if (!semantic_check_only
)
7891 defval
.ap
->set_code_section(GovernedSimple::CS_POST_INIT
);
7895 bool FormalPar::has_defval() const
7897 if (checked
) return defval
.ap
!= 0;
7898 else return defval
.ti
!= 0;
7901 bool FormalPar::has_notused_defval() const
7903 if (checked
) FATAL_ERROR("FormalPar::has_notused_defval");
7904 if (!defval
.ti
|| !defval
.ti
->get_Template())
7906 return defval
.ti
->get_Template()->get_templatetype()
7907 == Template::TEMPLATE_NOTUSED
;
7910 ActualPar
*FormalPar::get_defval() const
7912 if (!checked
) FATAL_ERROR("FormalPar::get_defval()");
7916 // Extract the TemplateInstance from an ActualPar.
7917 void FormalPar::set_defval(ActualPar
*defpar
)
7919 // ActualPar::clone() is not implemented, since we need such a function
7920 // only here only for AP_{VALUE,TEMPLATE} parameters. AP_ERROR can also
7921 // happen for Def_Template nodes, but they will be errors later.
7922 // FIXME: This function is Def_Template specific.
7923 if (!defval
.ti
->get_Template() || defval
.ti
->get_Template()
7924 ->get_templatetype() != Template::TEMPLATE_NOTUSED
)
7925 FATAL_ERROR("FormalPar::set_defval()");
7926 TemplateInstance
*reversed_ti
= 0;
7927 switch (defpar
->get_selection()) {
7928 case ActualPar::AP_VALUE
:
7929 reversed_ti
= new TemplateInstance(type
->clone(), 0, new Template
7930 (defpar
->get_Value()->clone())); // Trust the clone().
7932 case ActualPar::AP_TEMPLATE
:
7933 reversed_ti
= defpar
->get_TemplateInstance()->clone();
7935 case ActualPar::AP_ERROR
:
7936 break; // Can happen, but let it go.
7937 case ActualPar::AP_REF
:
7938 case ActualPar::AP_DEFAULT
:
7940 FATAL_ERROR("FormalPar::set_defval()");
7944 reversed_ti
->set_my_scope(get_my_scope());
7945 defval
.ti
= reversed_ti
;
7949 ActualPar
*FormalPar::chk_actual_par(TemplateInstance
*actual_par
,
7950 Type::expected_value_t exp_val
)
7952 if (!checked
) chk();
7956 return chk_actual_par_value(actual_par
, exp_val
);
7958 case A_PAR_VAL_INOUT
:
7959 return chk_actual_par_by_ref(actual_par
, false, exp_val
);
7960 case A_PAR_TEMPL_IN
:
7961 return chk_actual_par_template(actual_par
, exp_val
);
7962 case A_PAR_TEMPL_OUT
:
7963 case A_PAR_TEMPL_INOUT
:
7964 return chk_actual_par_by_ref(actual_par
, true, exp_val
);
7966 return chk_actual_par_timer(actual_par
, exp_val
);
7968 return chk_actual_par_port(actual_par
, exp_val
);
7970 FATAL_ERROR("FormalPar::chk_actual_par()");
7972 return 0; // to avoid warnings
7975 ActualPar
*FormalPar::chk_actual_par_value(TemplateInstance
*actual_par
,
7976 Type::expected_value_t exp_val
)
7978 actual_par
->chk_Type(type
);
7979 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
7981 derived_ref
->error("An in-line modified template cannot be used as %s",
7983 actual_par
->chk_DerivedRef(type
);
7985 Template
*ap_template
= actual_par
->get_Template();
7986 if (ap_template
->is_Value()) {
7987 Value
*v
= ap_template
->get_Value();
7988 v
->set_my_governor(type
);
7989 type
->chk_this_value_ref(v
);
7990 type
->chk_this_value(v
, 0, exp_val
, INCOMPLETE_NOT_ALLOWED
,
7991 OMIT_NOT_ALLOWED
, SUB_CHK
);
7992 return new ActualPar(v
);
7994 actual_par
->error("A specific value without matching symbols "
7995 "was expected for a %s", get_assname());
7996 return new ActualPar();
8000 static void chk_defpar_value(const Value
* v
)
8002 Common::Reference
*vref
= v
->get_reference();
8003 Common::Assignment
*ass2
= vref
->get_refd_assignment();
8005 Scope
*scope
= ass2
->get_my_scope();
8006 ComponentTypeBody
*ctb
= dynamic_cast<ComponentTypeBody
*>(scope
);
8007 if (ctb
) { // this is a component variable
8008 v
->error("default value cannot refer to"
8009 " a template field of the component in the `runs on' clause");
8013 static void chk_defpar_template(const Template
*body
,
8014 Type::expected_value_t exp_val
)
8016 switch (body
->get_templatetype()) {
8017 case Template::TEMPLATE_ERROR
:
8018 break; // could be erroneous in the source; skip it
8019 case Template::TEMPLATE_NOTUSED
:
8020 case Template::OMIT_VALUE
:
8021 case Template::ANY_VALUE
:
8022 case Template::ANY_OR_OMIT
:
8023 break; // acceptable (?)
8024 case Template::TEMPLATE_INVOKE
: // calling a function is not acceptable
8025 body
->error("default value can not be a function invocation");
8027 case Template::VALUE_RANGE
: {
8028 ValueRange
*range
= body
->get_value_range();
8029 Value
*low
= range
->get_min_v();
8030 Type::typetype_t tt_low
= low
->get_expr_returntype(exp_val
);
8031 Value
*high
= range
->get_max_v();
8032 Type::typetype_t tt_high
= high
->get_expr_returntype(exp_val
);
8033 if (tt_low
== tt_high
) break;
8036 case Template::BSTR_PATTERN
:
8037 case Template::HSTR_PATTERN
:
8038 case Template::OSTR_PATTERN
:
8039 case Template::CSTR_PATTERN
:
8040 case Template::USTR_PATTERN
:
8041 break; // should be acceptable in all cases (if only fixed strings possible)
8043 case Template::SPECIFIC_VALUE
: {
8044 Common::Value
*v
= body
->get_specific_value();
8045 if (v
->get_valuetype() == Value::V_REFD
) chk_defpar_value(v
);
8048 case Template::ALL_FROM
:
8049 case Template::VALUE_LIST_ALL_FROM
:
8050 FATAL_ERROR("should have been flattened");
8052 case Template::SUPERSET_MATCH
:
8053 case Template::SUBSET_MATCH
:
8054 case Template::PERMUTATION_MATCH
:
8055 case Template::TEMPLATE_LIST
:
8056 case Template::COMPLEMENTED_LIST
:
8057 case Template::VALUE_LIST
: {
8058 // in template charstring par := charstring : ("foo", "bar", "baz")
8059 size_t num
= body
->get_nof_comps();
8060 for (size_t i
= 0; i
< num
; ++i
) {
8061 const Template
*tpl
= body
->get_temp_byIndex(i
);
8062 chk_defpar_template(tpl
, exp_val
);
8066 case Template::NAMED_TEMPLATE_LIST
: {
8067 size_t num
= body
->get_nof_comps();
8068 for (size_t i
= 0; i
< num
; ++i
) {
8069 const NamedTemplate
*nt
= body
->get_namedtemp_byIndex(i
);
8070 const Template
*tpl
= nt
->get_template();
8071 chk_defpar_template(tpl
, exp_val
);
8075 case Template::INDEXED_TEMPLATE_LIST
: {
8076 size_t num
= body
->get_nof_comps();
8077 for (size_t i
= 0; i
< num
; ++i
) {
8078 const IndexedTemplate
*it
= body
->get_indexedtemp_byIndex(i
);
8079 const Template
*tpl
= it
->get_template();
8080 chk_defpar_template(tpl
, exp_val
);
8084 case Template::TEMPLATE_REFD
: {
8085 Ref_base
*ref
= body
->get_reference();
8087 Ttcn::ActualParList
*aplist
= ref
->get_parlist();
8089 size_t num
= aplist
->get_nof_pars();
8090 for (size_t i
= 0; i
< num
; ++i
) {
8091 const Ttcn::ActualPar
*ap
= aplist
->get_par(i
);
8093 switch (ap
->get_selection()) {
8094 case ActualPar::AP_ERROR
: {
8096 case ActualPar::AP_VALUE
: {
8097 Value
*v
= ap
->get_Value(); // "v_variable" as the parameter of the template
8099 switch (v
->get_valuetype()) {
8100 case Value::V_REFD
: {
8101 chk_defpar_value(v
);
8107 case ActualPar::AP_TEMPLATE
: {
8108 // A component cannot contain a template definition, parameterized or not.
8109 // Therefore the template this actual par references, cannot be
8110 // a field of a component => no error possible, nothing to do.
8112 case ActualPar::AP_REF
: {
8113 // A template cannot have an out/inout parameter
8114 FATAL_ERROR("Template with out parameter?");
8116 case ActualPar::AP_DEFAULT
: {
8117 ap
= ap
->get_ActualPar();
8121 } // switch actual par selection
8125 case Template::DECODE_MATCH
:
8126 chk_defpar_template(body
->get_decode_target()->get_Template(), exp_val
);
8128 } // switch templatetype
8132 // This function is called in two situations:
8133 // 1. FormalParList::chk calls FormalPar::chk to compute the default value
8134 // (make an ActualPar from a TemplateInstance).
8135 // In this case, defval.ti==0, and actual_par contains its old value.
8136 // This case is called only if the formal par has a default value.
8137 // 2. FormalParList::chk_actual_parlist calls FormalPar::chk_actual_par
8138 // to check the parameters supplied by the execute statement to the tc.
8139 // In this case, defval.ap has the value computed in case 1.
8140 ActualPar
*FormalPar::chk_actual_par_template(TemplateInstance
*actual_par
,
8141 Type::expected_value_t exp_val
)
8143 actual_par
->chk(type
);
8144 // actual_par->template_body may change: SPECIFIC_VALUE to TEMPLATE_REFD
8145 Definition
*fplist_def
= my_parlist
->get_my_def();
8146 // The parameter list belongs to this definition. If it's a function
8147 // or testcase, it may have a "runs on" clause.
8148 Def_Function
*parent_fn
= dynamic_cast<Def_Function
*>(fplist_def
);
8149 Type
*runs_on_type
= 0;
8150 if (parent_fn
) runs_on_type
= parent_fn
->get_RunsOnType();
8151 else { // not a function; maybe a testcase
8152 Def_Testcase
*parent_tc
= dynamic_cast<Def_Testcase
*>(fplist_def
);
8153 if (parent_tc
) runs_on_type
= parent_tc
->get_RunsOnType();
8156 // If it _has_ a runs on clause, the type must be a component.
8157 if (runs_on_type
->get_typetype() != Type::T_COMPONENT
) FATAL_ERROR("not component?");
8158 // The default value "shall not refer to elements of the component type
8159 // in the runs on clause"
8160 ComponentTypeBody
*runs_on_component
= runs_on_type
->get_CompBody();
8161 size_t compass
= runs_on_component
->get_nof_asss();
8162 for (size_t c
= 0; c
< compass
; c
++) {
8163 Assignment
*ass
= runs_on_component
->get_ass_byIndex(c
);
8168 Ttcn::Template
* body
= actual_par
->get_Template();
8169 if (exp_val
== Type::EXPECTED_STATIC_VALUE
8170 ||exp_val
== Type::EXPECTED_CONSTANT
) {
8171 chk_defpar_template(body
, exp_val
);
8173 // Rip out the type, derived ref and template from actual_par
8174 // (which may come from a function invocation or the definition
8175 // of the default value) and give it to the new ActualPar.
8176 ActualPar
*ret_val
= new ActualPar(
8177 new TemplateInstance(actual_par
->get_Type(),
8178 actual_par
->get_DerivedRef(), actual_par
->get_Template()));
8179 // Zero out these members because the caller will soon call delete
8180 // on actual_par, but they now belong to ret_val.
8181 // FIXME: should this really be in here, or outside in the caller before the delete ?
8182 actual_par
->release();
8184 if (template_restriction
!=TR_NONE
) {
8185 bool needs_runtime_check
=
8186 ret_val
->get_TemplateInstance()->chk_restriction(
8187 "template formal parameter", template_restriction
,
8188 ret_val
->get_TemplateInstance());
8189 if (needs_runtime_check
)
8190 ret_val
->set_gen_restriction_check(template_restriction
);
8195 ActualPar
*FormalPar::chk_actual_par_by_ref(TemplateInstance
*actual_par
,
8196 bool is_template
, Type::expected_value_t exp_val
)
8198 Type
*ap_type
= actual_par
->get_Type();
8200 ap_type
->warning("Explicit type specification is useless for an %s",
8202 actual_par
->chk_Type(type
);
8204 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8206 derived_ref
->error("An in-line modified template cannot be used as %s",
8208 actual_par
->chk_DerivedRef(type
);
8210 // needed for the error messages
8211 const char *expected_string
= is_template
?
8212 "template variable or template parameter" :
8213 "variable or value parameter";
8214 Template
*ap_template
= actual_par
->get_Template();
8215 if (ap_template
->is_Ref()) {
8216 Ref_base
*ref
= ap_template
->get_Ref();
8217 Common::Assignment
*ass
= ref
->get_refd_assignment();
8220 return new ActualPar();
8222 bool asstype_correct
= false;
8223 switch (ass
->get_asstype()) {
8225 ass
->use_as_lvalue(*ref
);
8226 if (get_asstype() == A_PAR_VAL_OUT
|| get_asstype() == A_PAR_TEMPL_OUT
) {
8227 ass
->warning("Passing an `in' parameter as another function's `out' parameter");
8232 case A_PAR_VAL_INOUT
:
8233 if (!is_template
) asstype_correct
= true;
8235 case A_PAR_TEMPL_IN
:
8236 ass
->use_as_lvalue(*ref
);
8237 if (get_asstype() == A_PAR_VAL_OUT
|| get_asstype() == A_PAR_TEMPL_OUT
) {
8238 ass
->warning("Passing an `in' parameter as another function's `out' parameter");
8241 case A_VAR_TEMPLATE
:
8242 case A_PAR_TEMPL_OUT
:
8243 case A_PAR_TEMPL_INOUT
:
8244 if (is_template
) asstype_correct
= true;
8249 if (asstype_correct
) {
8250 FieldOrArrayRefs
*t_subrefs
= ref
->get_subrefs();
8251 Type
*ref_type
= ass
->get_Type()->get_field_type(t_subrefs
, exp_val
);
8253 if (!type
->is_identical(ref_type
)) {
8254 ref
->error("Type mismatch: Reference to a %s of type "
8255 "`%s' was expected instead of `%s'", expected_string
,
8256 type
->get_typename().c_str(), ref_type
->get_typename().c_str());
8257 } else if (type
->get_sub_type() && ref_type
->get_sub_type() &&
8258 (type
->get_sub_type()->get_subtypetype()==ref_type
->get_sub_type()->get_subtypetype()) &&
8259 (!type
->get_sub_type()->is_compatible(ref_type
->get_sub_type()))) {
8260 ref
->error("Subtype mismatch: subtype %s has no common value with subtype %s",
8261 type
->get_sub_type()->to_string().c_str(),
8262 ref_type
->get_sub_type()->to_string().c_str());
8264 if (t_subrefs
&& t_subrefs
->refers_to_string_element()) {
8265 ref
->error("Reference to a string element of type `%s' cannot be "
8266 "used in this context", ref_type
->get_typename().c_str());
8270 ref
->error("Reference to a %s was expected for an %s instead of %s",
8271 expected_string
, get_assname(), ass
->get_description().c_str());
8273 ActualPar
* ret_val_ap
= new ActualPar(ref
);
8274 // restriction checking if this is a reference to a template variable
8275 // this is an 'out' or 'inout' template parameter
8276 if (is_template
&& asstype_correct
) {
8277 template_restriction_t refd_tr
;
8278 switch (ass
->get_asstype()) {
8279 case A_VAR_TEMPLATE
: {
8280 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(ass
);
8281 if (!dvt
) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8282 refd_tr
= dvt
->get_template_restriction();
8284 case A_PAR_TEMPL_IN
:
8285 case A_PAR_TEMPL_OUT
:
8286 case A_PAR_TEMPL_INOUT
: {
8287 FormalPar
* fp
= dynamic_cast<FormalPar
*>(ass
);
8288 if (!fp
) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8289 refd_tr
= fp
->get_template_restriction();
8292 FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
8295 refd_tr
= Template::get_sub_restriction(refd_tr
, ref
);
8296 if (template_restriction
!=refd_tr
) {
8297 bool pre_call_check
=
8298 Template::is_less_restrictive(template_restriction
, refd_tr
);
8299 bool post_call_check
=
8300 Template::is_less_restrictive(refd_tr
, template_restriction
);
8301 if (pre_call_check
|| post_call_check
) {
8302 ref
->warning("Inadequate restriction on the referenced %s `%s', "
8303 "this may cause a dynamic test case error at runtime",
8304 ass
->get_assname(), ref
->get_dispname().c_str());
8305 ass
->note("Referenced %s is here", ass
->get_assname());
8308 ret_val_ap
->set_gen_restriction_check(template_restriction
);
8309 if (post_call_check
)
8310 ret_val_ap
->set_gen_post_restriction_check(refd_tr
);
8312 // for out and inout template parameters of external functions
8313 // always check because we do not trust user written C++ code
8314 if (refd_tr
!=TR_NONE
) {
8315 switch (my_parlist
->get_my_def()->get_asstype()) {
8316 case A_EXT_FUNCTION
:
8317 case A_EXT_FUNCTION_RVAL
:
8318 case A_EXT_FUNCTION_RTEMP
:
8319 ret_val_ap
->set_gen_post_restriction_check(refd_tr
);
8328 actual_par
->error("Reference to a %s was expected for an %s",
8329 expected_string
, get_assname());
8330 return new ActualPar();
8334 ActualPar
*FormalPar::chk_actual_par_timer(TemplateInstance
*actual_par
,
8335 Type::expected_value_t exp_val
)
8337 Type
*ap_type
= actual_par
->get_Type();
8339 ap_type
->error("Explicit type specification cannot be used for a "
8341 actual_par
->chk_Type(0);
8343 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8345 derived_ref
->error("An in-line modified template cannot be used as "
8347 actual_par
->chk_DerivedRef(0);
8349 Template
*ap_template
= actual_par
->get_Template();
8350 if (ap_template
->is_Ref()) {
8351 Ref_base
*ref
= ap_template
->get_Ref();
8352 Common::Assignment
*ass
= ref
->get_refd_assignment();
8355 return new ActualPar();
8357 switch (ass
->get_asstype()) {
8359 ArrayDimensions
*dims
= ass
->get_Dimensions();
8360 if (dims
) dims
->chk_indices(ref
, "timer", false, exp_val
);
8361 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8362 "cannot have field or array sub-references",
8363 ass
->get_description().c_str());
8366 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8367 "field or array sub-references", ass
->get_description().c_str());
8370 ref
->error("Reference to a timer or timer parameter was expected for "
8371 "a timer parameter instead of %s", ass
->get_description().c_str());
8373 return new ActualPar(ref
);
8375 actual_par
->error("Reference to a timer or timer parameter was "
8376 "expected for a timer parameter");
8377 return new ActualPar();
8381 ActualPar
*FormalPar::chk_actual_par_port(TemplateInstance
*actual_par
,
8382 Type::expected_value_t exp_val
)
8384 Type
*ap_type
= actual_par
->get_Type();
8386 ap_type
->warning("Explicit type specification is useless for a port "
8388 actual_par
->chk_Type(type
);
8390 Ref_base
*derived_ref
= actual_par
->get_DerivedRef();
8392 derived_ref
->error("An in-line modified template cannot be used as "
8394 actual_par
->chk_DerivedRef(type
);
8396 Template
*ap_template
= actual_par
->get_Template();
8397 if (ap_template
->is_Ref()) {
8398 Ref_base
*ref
= ap_template
->get_Ref();
8399 Common::Assignment
*ass
= ref
->get_refd_assignment();
8402 return new ActualPar();
8404 bool asstype_correct
= false;
8405 switch (ass
->get_asstype()) {
8407 ArrayDimensions
*dims
= ass
->get_Dimensions();
8408 if (dims
) dims
->chk_indices(ref
, "port", false, exp_val
);
8409 else if (ref
->get_subrefs()) ref
->error("Reference to single %s "
8410 "cannot have field or array sub-references",
8411 ass
->get_description().c_str());
8412 asstype_correct
= true;
8415 if (ref
->get_subrefs()) ref
->error("Reference to %s cannot have "
8416 "field or array sub-references", ass
->get_description().c_str());
8417 asstype_correct
= true;
8420 ref
->error("Reference to a port or port parameter was expected for a "
8421 "port parameter instead of %s", ass
->get_description().c_str());
8423 if (asstype_correct
) {
8424 Type
*ref_type
= ass
->get_Type();
8425 if (ref_type
&& !type
->is_identical(ref_type
))
8426 ref
->error("Type mismatch: Reference to a port or port parameter "
8427 "of type `%s' was expected instead of `%s'",
8428 type
->get_typename().c_str(), ref_type
->get_typename().c_str());
8430 return new ActualPar(ref
);
8432 actual_par
->error("Reference to a port or port parameter was expected "
8433 "for a port parameter");
8434 return new ActualPar();
8438 void FormalPar::use_as_lvalue(const Location
& p_loc
)
8442 case A_PAR_TEMPL_IN
:
8445 FATAL_ERROR("FormalPar::use_as_lvalue()");
8447 if (!used_as_lvalue
) {
8448 Definition
*my_def
= my_parlist
->get_my_def();
8449 if (!my_def
) FATAL_ERROR("FormalPar::use_as_lvalue()");
8450 if (my_def
->get_asstype() == A_TEMPLATE
)
8451 p_loc
.error("Parameter `%s' of the template cannot be passed further "
8452 "as `out' or `inout' parameter", id
->get_dispname().c_str());
8454 // update the genname so that all references in the generated code
8455 // will point to the shadow object
8457 set_genname(id
->get_name() + "_shadow");
8459 used_as_lvalue
= true;
8464 char* FormalPar::generate_code_defval(char* str
)
8466 if (!defval
.ap
|| defval_generated
) return str
;
8467 defval_generated
= true;
8468 switch (defval
.ap
->get_selection()) {
8469 case ActualPar::AP_VALUE
: {
8470 Value
*val
= defval
.ap
->get_Value();
8471 if (use_runtime_2
&& TypeConv::needs_conv_refd(val
)) {
8472 str
= TypeConv::gen_conv_code_refd(str
, val
->get_lhs_name().c_str(), val
);
8474 str
= val
->generate_code_init(str
, val
->get_lhs_name().c_str());
8477 case ActualPar::AP_TEMPLATE
: {
8478 TemplateInstance
*ti
= defval
.ap
->get_TemplateInstance();
8479 Template
*temp
= ti
->get_Template();
8480 Ref_base
*dref
= ti
->get_DerivedRef();
8482 expression_struct expr
;
8483 Code::init_expr(&expr
);
8484 expr
.expr
= mputprintf(expr
.expr
, "%s = ",
8485 temp
->get_lhs_name().c_str());
8486 dref
->generate_code(&expr
);
8487 str
= Code::merge_free_expr(str
, &expr
, false);
8489 if (use_runtime_2
&& TypeConv::needs_conv_refd(temp
)) {
8490 str
= TypeConv::gen_conv_code_refd(str
, temp
->get_lhs_name().c_str(), temp
);
8492 str
= temp
->generate_code_init(str
, temp
->get_lhs_name().c_str());
8494 if (defval
.ap
->get_gen_restriction_check() != TR_NONE
) {
8495 str
= Template::generate_restriction_check_code(str
,
8496 temp
->get_lhs_name().c_str(), defval
.ap
->get_gen_restriction_check());
8499 case ActualPar::AP_REF
:
8502 FATAL_ERROR("FormalPar::generate_code()");
8507 void FormalPar::generate_code_defval(output_struct
*target
, bool)
8509 if (!defval
.ap
) return;
8510 switch (defval
.ap
->get_selection()) {
8511 case ActualPar::AP_VALUE
: {
8512 Value
*val
= defval
.ap
->get_Value();
8514 Code::init_cdef(&cdef
);
8515 type
->generate_code_object(&cdef
, val
);
8516 Code::merge_cdef(target
, &cdef
);
8517 Code::free_cdef(&cdef
);
8519 case ActualPar::AP_TEMPLATE
: {
8520 TemplateInstance
*ti
= defval
.ap
->get_TemplateInstance();
8521 Template
*temp
= ti
->get_Template();
8523 Code::init_cdef(&cdef
);
8524 type
->generate_code_object(&cdef
, temp
);
8525 Code::merge_cdef(target
, &cdef
);
8526 Code::free_cdef(&cdef
);
8528 case ActualPar::AP_REF
:
8531 FATAL_ERROR("FormalPar::generate_code()");
8533 target
->functions
.post_init
= generate_code_defval(target
->functions
.post_init
);
8536 char *FormalPar::generate_code_fpar(char *str
, bool display_unused
/* = false */)
8538 // the name of the parameter should not be displayed if the parameter is not
8539 // used (to avoid a compiler warning)
8540 bool display_name
= (usage_found
|| display_unused
|| debugger_active
||
8541 (!enable_set_bound_out_param
&& (asstype
== A_PAR_VAL_OUT
|| asstype
== A_PAR_TEMPL_OUT
)));
8542 const char *name_str
= display_name
? id
->get_name().c_str() : "";
8546 str
= mputprintf(str
, "Lazy_Param<%s>& %s", type
->get_genname_value(my_scope
).c_str(), name_str
);
8548 str
= mputprintf(str
, "const %s& %s", type
->get_genname_value(my_scope
).c_str(), name_str
);
8552 case A_PAR_VAL_INOUT
:
8554 str
= mputprintf(str
, "%s& %s", type
->get_genname_value(my_scope
).c_str(),
8557 case A_PAR_TEMPL_IN
:
8559 str
= mputprintf(str
, "Lazy_Param<%s>& %s", type
->get_genname_template(my_scope
).c_str(), name_str
);
8561 str
= mputprintf(str
, "const %s& %s", type
->get_genname_template(my_scope
).c_str(), name_str
);
8564 case A_PAR_TEMPL_OUT
:
8565 case A_PAR_TEMPL_INOUT
:
8566 str
= mputprintf(str
, "%s& %s",
8567 type
->get_genname_template(my_scope
).c_str(), name_str
);
8570 str
= mputprintf(str
, "TIMER& %s", name_str
);
8573 FATAL_ERROR("FormalPar::generate_code()");
8578 string
FormalPar::get_reference_name(Scope
* scope
) const
8584 case A_PAR_TEMPL_IN
:
8585 ret_val
+= type
->get_genname_template(scope
);
8588 ret_val
+= type
->get_genname_value(scope
);
8593 ret_val
+= get_id().get_name();
8600 char *FormalPar::generate_code_object(char *str
, const char *p_prefix
, char refch
)
8602 const char *name_str
= id
->get_name().c_str();
8606 str
= mputprintf(str
, "Lazy_Param<%s> %s%s;\n", type
->get_genname_value(my_scope
).c_str(), p_prefix
, name_str
);
8608 str
= mputprintf(str
, "%s %s%s;\n", type
->get_genname_value(my_scope
).c_str(), p_prefix
, name_str
);
8612 case A_PAR_VAL_INOUT
:
8614 str
= mputprintf(str
, "%s%c %s%s;\n",
8615 type
->get_genname_value(my_scope
).c_str(), refch
, p_prefix
, name_str
);
8617 case A_PAR_TEMPL_IN
:
8619 str
= mputprintf(str
, "Lazy_Param<%s> %s%s;\n", type
->get_genname_template(my_scope
).c_str(), p_prefix
, name_str
);
8621 str
= mputprintf(str
, "%s %s%s;\n", type
->get_genname_template(my_scope
).c_str(), p_prefix
, name_str
);
8624 case A_PAR_TEMPL_OUT
:
8625 case A_PAR_TEMPL_INOUT
:
8626 str
= mputprintf(str
, "%s%c %s%s;\n",
8627 type
->get_genname_template(my_scope
).c_str(), refch
, p_prefix
, name_str
);
8630 str
= mputprintf(str
, "TIMER& %s%s;\n", p_prefix
, name_str
);
8633 FATAL_ERROR("FormalPar::generate_code_object()");
8638 char *FormalPar::generate_shadow_object(char *str
) const
8640 if (used_as_lvalue
&& !lazy_eval
) {
8641 const string
& t_genname
= get_genname();
8642 const char *genname_str
= t_genname
.c_str();
8643 const char *name_str
= id
->get_name().c_str();
8646 str
= mputprintf(str
, "%s %s(%s);\n",
8647 type
->get_genname_value(my_scope
).c_str(), genname_str
, name_str
);
8649 case A_PAR_TEMPL_IN
:
8650 str
= mputprintf(str
, "%s %s(%s);\n",
8651 type
->get_genname_template(my_scope
).c_str(), genname_str
, name_str
);
8654 FATAL_ERROR("FormalPar::generate_shadow_object()");
8660 char *FormalPar::generate_code_set_unbound(char *str
) const
8663 case A_PAR_TEMPL_OUT
:
8665 str
= mputprintf(str
, "%s.clean_up();\n", id
->get_name().c_str());
8673 void FormalPar::dump_internal(unsigned level
) const
8675 DEBUG(level
, "%s: %s", get_assname(), id
->get_dispname().c_str());
8676 if (type
) type
->dump(level
+ 1);
8679 DEBUG(level
+ 1, "default value:");
8680 defval
.ap
->dump(level
+ 2);
8684 DEBUG(level
+ 1, "default value:");
8685 defval
.ti
->dump(level
+ 2);
8690 // =================================
8691 // ===== FormalParList
8692 // =================================
8694 FormalParList::~FormalParList()
8696 size_t nof_pars
= pars_v
.size();
8697 for (size_t i
= 0; i
< nof_pars
; i
++) delete pars_v
[i
];
8702 FormalParList
*FormalParList::clone() const
8704 FATAL_ERROR("FormalParList::clone");
8707 void FormalParList::set_fullname(const string
& p_fullname
)
8709 Node::set_fullname(p_fullname
);
8710 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8711 FormalPar
*par
= pars_v
[i
];
8712 par
->set_fullname(p_fullname
+ "." + par
->get_id().get_dispname());
8716 void FormalParList::set_my_scope(Scope
*p_scope
)
8718 set_parent_scope(p_scope
);
8719 Node::set_my_scope(p_scope
);
8720 // the scope of parameters is set to the parent scope instead of this
8721 // because they cannot refer to each other
8722 for (size_t i
= 0; i
< pars_v
.size(); i
++) pars_v
[i
]->set_my_scope(p_scope
);
8725 void FormalParList::add_fp(FormalPar
*p_fp
)
8727 if (!p_fp
) FATAL_ERROR("NULL parameter: Ttcn::FormalParList::add_fp()");
8729 p_fp
->set_my_parlist(this);
8733 bool FormalParList::has_notused_defval() const
8735 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8736 if (pars_v
[i
]->has_notused_defval())
8742 bool FormalParList::has_only_default_values() const
8744 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8745 if (!pars_v
[i
]->has_defval()) {
8753 bool FormalParList::has_fp_withName(const Identifier
& p_name
)
8755 if (!checked
) chk(Definition::A_UNDEF
);
8756 return pars_m
.has_key(p_name
.get_name());
8759 FormalPar
*FormalParList::get_fp_byName(const Identifier
& p_name
)
8761 if (!checked
) chk(Definition::A_UNDEF
);
8762 return pars_m
[p_name
.get_name()];
8765 bool FormalParList::get_startability()
8767 if(!checked
) FATAL_ERROR("FormalParList::get_startability()");
8768 return is_startable
;
8771 Common::Assignment
*FormalParList::get_ass_bySRef(Common::Ref_simple
*p_ref
)
8773 if (!p_ref
|| !checked
) FATAL_ERROR("FormalParList::get_ass_bySRef()");
8774 if (p_ref
->get_modid()) return parent_scope
->get_ass_bySRef(p_ref
);
8776 const string
& name
= p_ref
->get_id()->get_name();
8777 if (pars_m
.has_key(name
)) return pars_m
[name
];
8778 else return parent_scope
->get_ass_bySRef(p_ref
);
8782 bool FormalParList::has_ass_withId(const Identifier
& p_id
)
8784 if (!checked
) FATAL_ERROR("Ttcn::FormalParList::has_ass_withId()");
8785 return pars_m
.has_key(p_id
.get_name())
8786 || parent_scope
->has_ass_withId(p_id
);
8789 void FormalParList::set_genname(const string
& p_prefix
)
8791 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8792 FormalPar
*par
= pars_v
[i
];
8793 const string
& par_name
= par
->get_id().get_name();
8794 if (par
->get_asstype() != Definition::A_PAR_TIMER
)
8795 par
->get_Type()->set_genname(p_prefix
, par_name
);
8796 if (par
->has_defval()) {
8797 string
embedded_genname(p_prefix
);
8798 embedded_genname
+= '_';
8799 embedded_genname
+= par_name
;
8800 embedded_genname
+= "_defval";
8801 ActualPar
*defval
= par
->get_defval();
8802 switch (defval
->get_selection()) {
8803 case ActualPar::AP_ERROR
:
8804 case ActualPar::AP_REF
:
8806 case ActualPar::AP_VALUE
: {
8807 Value
*v
= defval
->get_Value();
8808 v
->set_genname_prefix("const_");
8809 v
->set_genname_recursive(embedded_genname
);
8811 case ActualPar::AP_TEMPLATE
: {
8812 Template
*t
= defval
->get_TemplateInstance()->get_Template();
8813 t
->set_genname_prefix("template_");
8814 t
->set_genname_recursive(embedded_genname
);
8817 FATAL_ERROR("FormalParList::set_genname()");
8823 void FormalParList::chk(Definition::asstype_t deftype
)
8825 if (checked
) return;
8828 is_startable
= true;
8829 Error_Context
cntxt(this, "In formal parameter list");
8830 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8831 FormalPar
*par
= pars_v
[i
];
8832 const Identifier
& id
= par
->get_id();
8833 const string
& name
= id
.get_name();
8834 const char *dispname
= id
.get_dispname().c_str();
8835 if (pars_m
.has_key(name
)) {
8836 par
->error("Duplicate parameter with name `%s'", dispname
);
8837 pars_m
[name
]->note("Previous definition of `%s' is here", dispname
);
8839 pars_m
.add(name
, par
);
8840 if (parent_scope
&& parent_scope
->has_ass_withId(id
)) {
8841 par
->error("Parameter name `%s' is not unique in the scope "
8842 "hierarchy", dispname
);
8843 Reference
ref(0, id
.clone());
8844 Common::Assignment
*ass
= parent_scope
->get_ass_bySRef(&ref
);
8845 if (!ass
) FATAL_ERROR("FormalParList::chk()");
8846 ass
->note("Symbol `%s' is already defined here in a higher scope "
8850 Error_Context
cntxt2(par
, "In parameter `%s'", dispname
);
8852 // check whether the parameter type is allowed
8854 case Definition::A_TEMPLATE
:
8855 switch (par
->get_asstype()) {
8856 case Definition::A_PAR_VAL_IN
:
8857 case Definition::A_PAR_TEMPL_IN
:
8858 // these are allowed
8861 par
->error("A template cannot have %s", par
->get_assname());
8864 case Definition::A_TESTCASE
:
8865 switch (par
->get_asstype()) {
8866 case Definition::A_PAR_TIMER
:
8867 case Definition::A_PAR_PORT
:
8868 // these are forbidden
8869 par
->error("A testcase cannot have %s", par
->get_assname());
8874 // everything is allowed for functions and altsteps
8878 switch(par
->get_asstype()) {
8879 case Common::Assignment::A_PAR_VAL_IN
:
8880 case Common::Assignment::A_PAR_TEMPL_IN
:
8881 case Common::Assignment::A_PAR_VAL_INOUT
:
8882 case Common::Assignment::A_PAR_TEMPL_INOUT
:
8883 if (is_startable
&& par
->get_Type()->is_component_internal())
8884 is_startable
= false;
8887 is_startable
= false;
8890 if (!par
->has_defval()) min_nof_pars
= i
+ 1;
8891 // the last parameter without a default value determines the minimum
8895 // check that @lazy paramterization not used in cases currently unsupported
8896 void FormalParList::chk_noLazyParams() {
8897 Error_Context
cntxt(this, "In formal parameter list");
8898 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8899 FormalPar
*par
= pars_v
[i
];
8900 if (par
->get_lazy_eval()) {
8901 par
->error("Formal parameter `%s' cannot be @lazy, not supported in this case.",
8902 par
->get_id().get_dispname().c_str());
8907 void FormalParList::chk_startability(const char *p_what
, const char *p_name
)
8909 if(!checked
) FATAL_ERROR("FormalParList::chk_startability()");
8910 if (is_startable
) return;
8911 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
8912 FormalPar
*par
= pars_v
[i
];
8913 switch (par
->get_asstype()) {
8914 case Common::Assignment::A_PAR_VAL_IN
:
8915 case Common::Assignment::A_PAR_TEMPL_IN
:
8916 case Common::Assignment::A_PAR_VAL_INOUT
:
8917 case Common::Assignment::A_PAR_TEMPL_INOUT
:
8918 if (par
->get_Type()->is_component_internal()) {
8919 map
<Type
*,void> type_chain
;
8920 char* err_str
= mprintf("a parameter or embedded in a parameter of "
8921 "a function used in a start operation. "
8922 "%s `%s' cannot be started on a parallel test component "
8923 "because of `%s'", p_what
, p_name
, par
->get_description().c_str());
8924 par
->get_Type()->chk_component_internal(type_chain
, err_str
);
8929 par
->error("%s `%s' cannot be started on a parallel test component "
8930 "because it has %s", p_what
, p_name
, par
->get_description().c_str());
8935 void FormalParList::chk_compatibility(FormalParList
* p_fp_list
,
8938 size_t nof_type_pars
= pars_v
.size();
8939 size_t nof_function_pars
= p_fp_list
->pars_v
.size();
8940 // check for the number of parameters
8941 if (nof_type_pars
!= nof_function_pars
) {
8942 p_fp_list
->error("Too %s parameters: %lu was expected instead of %lu",
8943 nof_type_pars
< nof_function_pars
? "many" : "few",
8944 (unsigned long) nof_type_pars
, (unsigned long) nof_function_pars
);
8946 size_t upper_limit
=
8947 nof_type_pars
< nof_function_pars
? nof_type_pars
: nof_function_pars
;
8948 for (size_t i
= 0; i
< upper_limit
; i
++) {
8949 FormalPar
*type_par
= pars_v
[i
];
8950 FormalPar
*function_par
= p_fp_list
->pars_v
[i
];
8951 Error_Context
cntxt(function_par
, "In parameter #%lu",
8952 (unsigned long) (i
+ 1));
8953 FormalPar::asstype_t type_par_asstype
= type_par
->get_asstype();
8954 FormalPar::asstype_t function_par_asstype
= function_par
->get_asstype();
8955 // check for parameter kind equivalence
8956 // (in, out or inout / value or template)
8957 if (type_par_asstype
!= function_par_asstype
) {
8958 function_par
->error("The kind of the parameter is not the same as in "
8959 "type `%s': %s was expected instead of %s", where
,
8960 type_par
->get_assname(), function_par
->get_assname());
8962 // check for type equivalence
8963 if (type_par_asstype
!= FormalPar::A_PAR_TIMER
&&
8964 function_par_asstype
!= FormalPar::A_PAR_TIMER
) {
8965 Type
*type_par_type
= type_par
->get_Type();
8966 Type
*function_par_type
= function_par
->get_Type();
8967 if (!type_par_type
->is_identical(function_par_type
)) {
8968 function_par_type
->error("The type of the parameter is not the same "
8969 "as in type `%s': `%s' was expected instead of `%s'", where
,
8970 type_par_type
->get_typename().c_str(),
8971 function_par_type
->get_typename().c_str());
8972 } else if (type_par_type
->get_sub_type() && function_par_type
->get_sub_type() &&
8973 (type_par_type
->get_sub_type()->get_subtypetype()==function_par_type
->get_sub_type()->get_subtypetype()) &&
8974 (!type_par_type
->get_sub_type()->is_compatible(function_par_type
->get_sub_type()))) {
8975 // TODO: maybe equivalence should be checked, or maybe that is too strict
8976 function_par_type
->error(
8977 "Subtype mismatch: subtype %s has no common value with subtype %s",
8978 type_par_type
->get_sub_type()->to_string().c_str(),
8979 function_par_type
->get_sub_type()->to_string().c_str());
8982 // check for template restriction equivalence
8983 if (type_par
->get_template_restriction()!=
8984 function_par
->get_template_restriction()) {
8985 function_par
->error("The template restriction of the parameter is "
8986 "not the same as in type `%s': %s restriction was expected instead "
8987 "of %s restriction", where
,
8988 type_par
->get_template_restriction()==TR_NONE
? "no" :
8989 Template::get_restriction_name(type_par
->get_template_restriction()),
8990 function_par
->get_template_restriction()==TR_NONE
? "no" :
8991 Template::get_restriction_name(function_par
->
8992 get_template_restriction()));
8994 // check for @lazy equivalence
8995 if (type_par
->get_lazy_eval()!=function_par
->get_lazy_eval()) {
8996 function_par
->error("Parameter @lazy-ness mismatch");
8998 // check for name equivalence
8999 const Identifier
& type_par_id
= type_par
->get_id();
9000 const Identifier
& function_par_id
= function_par
->get_id();
9001 if (type_par_id
!= function_par_id
) {
9002 function_par
->warning("The name of the parameter is not the same "
9003 "as in type `%s': `%s' was expected instead of `%s'", where
,
9004 type_par_id
.get_dispname().c_str(),
9005 function_par_id
.get_dispname().c_str());
9010 bool FormalParList::fold_named_and_chk(ParsedActualParameters
*p_paps
,
9011 ActualParList
*p_aplist
)
9013 const size_t num_named
= p_paps
->get_nof_nps();
9014 const size_t num_unnamed
= p_paps
->get_nof_tis();
9015 size_t num_actual
= num_unnamed
;
9017 // Construct a map to tell us what index a FormalPar has
9018 typedef map
<FormalPar
*, size_t> formalpar_map_t
;
9019 formalpar_map_t formalpar_map
;
9021 size_t num_fp
= get_nof_fps();
9022 for (size_t fpx
= 0; fpx
< num_fp
; ++fpx
) {
9023 FormalPar
*fp
= get_fp_byIndex(fpx
);
9024 formalpar_map
.add(fp
, new size_t(fpx
));
9027 // Go through the named parameters
9028 for (size_t i
= 0; i
< num_named
; ++i
) {
9029 NamedParam
*np
= p_paps
->extract_np_byIndex(i
);
9030 // We are now responsible for np.
9032 if (has_fp_withName(*np
->get_name())) {
9033 // there is a formal parameter with that name
9034 FormalPar
*fp
= get_fp_byName(*np
->get_name());
9035 const size_t is_at
= *formalpar_map
[fp
]; // the index of the formal par
9036 if (is_at
>= num_actual
) {
9037 // There is no actual par in the unnamed part.
9038 // Create one from the named param.
9040 // First, pad the gap with '-'
9041 for (; num_actual
< is_at
; ++num_actual
) {
9043 if (pars_v
[num_actual
]->has_defval()) {
9044 not_used
= new Template(Template::TEMPLATE_NOTUSED
);
9046 else { // cannot use '-' if no default value
9047 not_used
= new Template(Template::TEMPLATE_ERROR
);
9049 TemplateInstance
*new_ti
= new TemplateInstance(0, 0, not_used
);
9050 // Conjure a location info at the beginning of the unnamed part
9051 // (that is, the beginning of the actual parameter list)
9052 new_ti
->set_location(p_paps
->get_tis()->get_filename(),
9053 p_paps
->get_tis()->get_first_line(),
9054 p_paps
->get_tis()->get_first_column(), 0, 0);
9055 p_paps
->get_tis()->add_ti(new_ti
);
9057 TemplateInstance
* namedti
= np
->extract_ti();
9058 p_paps
->get_tis()->add_ti(namedti
);
9061 // There is already an actual par at that position, fetch it
9062 TemplateInstance
* ti
= p_paps
->get_tis()->get_ti_byIndex(is_at
);
9063 Template::templatetype_t tt
= ti
->get_Template()->get_templatetype();
9065 if (is_at
>= num_unnamed
&& !ti
->get_Type() && !ti
->get_DerivedRef()
9066 && (tt
== Template::TEMPLATE_NOTUSED
|| tt
== Template::TEMPLATE_ERROR
)) {
9067 // NotUsed in the named part => padding
9068 np
->error("Named parameter `%s' out of order",
9069 np
->get_name()->get_dispname().c_str());
9071 // attempt to override an original unnamed param with a named one
9072 np
->error("Formal parameter `%s' assigned more than once",
9073 np
->get_name()->get_dispname().c_str());
9077 else { // no formal parameter with that name
9079 switch (my_def
->get_asstype()) {
9080 case Common::Assignment::A_TYPE
: {
9081 Type
*t
= my_def
->get_Type();
9083 switch (t
? t
->get_typetype() : 0) {
9084 case Type::T_FUNCTION
:
9085 nam
= mcopystr("Function reference");
9087 case Type::T_ALTSTEP
:
9088 nam
= mcopystr("Altstep reference");
9090 case Type::T_TESTCASE
:
9091 nam
= mcopystr("Testcase reference");
9094 FATAL_ERROR("FormalParList::chk_actual_parlist() "
9095 "Unexpected type %s", t
->get_typename().c_str());
9096 } // switch(typetype)
9099 nam
= mcopystr(my_def
->get_assname());
9101 } // switch(asstype)
9103 *nam
&= ~('a'-'A'); // Make the first letter uppercase
9104 p_paps
->get_tis()->error("%s `%s' has no formal parameter `%s'",
9106 my_def
->get_fullname().c_str(),
9107 np
->get_name()->get_dispname().c_str());
9114 for (size_t fpx
= 0; fpx
< num_fp
; ++fpx
) {
9115 delete formalpar_map
.get_nth_elem(fpx
);
9117 formalpar_map
.clear();
9119 return chk_actual_parlist(p_paps
->get_tis(), p_aplist
);
9122 bool FormalParList::chk_actual_parlist(TemplateInstances
*p_tis
,
9123 ActualParList
*p_aplist
)
9125 size_t formal_pars
= pars_v
.size();
9126 size_t actual_pars
= p_tis
->get_nof_tis();
9127 // p_aplist->get_nof_pars() is usually 0 on entry
9128 bool error_flag
= false;
9130 if (min_nof_pars
== formal_pars
) {
9131 // none of the parameters have default value
9132 if (actual_pars
!= formal_pars
) {
9133 p_tis
->error("Too %s parameters: %lu was expected "
9134 "instead of %lu", actual_pars
< formal_pars
? "few" : "many",
9135 (unsigned long) formal_pars
, (unsigned long) actual_pars
);
9139 // some parameters have default value
9140 if (actual_pars
< min_nof_pars
) {
9141 p_tis
->error("Too few parameters: at least %lu "
9142 "was expected instead of %lu",
9143 (unsigned long) min_nof_pars
, (unsigned long) actual_pars
);
9145 } else if (actual_pars
> formal_pars
) {
9146 p_tis
->error("Too many parameters: at most %lu "
9147 "was expected instead of %lu",
9148 (unsigned long) formal_pars
, (unsigned long) actual_pars
);
9153 // Do not check actual parameters in excess of the formal ones
9154 size_t upper_limit
= actual_pars
< formal_pars
? actual_pars
: formal_pars
;
9155 for (size_t i
= 0; i
< upper_limit
; i
++) {
9156 TemplateInstance
*ti
= p_tis
->get_ti_byIndex(i
);
9158 // the formal parameter for the current actual parameter
9159 FormalPar
*fp
= pars_v
[i
];
9160 Error_Context
cntxt(ti
, "In parameter #%lu for `%s'",
9161 (unsigned long) (i
+ 1), fp
->get_id().get_dispname().c_str());
9162 if (!ti
->get_Type() && !ti
->get_DerivedRef() && ti
->get_Template()
9163 ->get_templatetype() == Template::TEMPLATE_NOTUSED
) {
9164 if (fp
->has_defval()) {
9165 ActualPar
*defval
= fp
->get_defval();
9166 p_aplist
->add(new ActualPar(defval
));
9167 if (defval
->is_erroneous()) error_flag
= true;
9169 ti
->error("Not used symbol (`-') cannot be used for parameter "
9170 "that does not have default value");
9171 p_aplist
->add(new ActualPar());
9174 } else if (!ti
->get_Type() && !ti
->get_DerivedRef() && ti
->get_Template()
9175 ->get_templatetype() == Template::TEMPLATE_ERROR
) {
9176 ti
->error("Parameter not specified");
9178 ActualPar
*ap
= fp
->chk_actual_par(ti
, Type::EXPECTED_DYNAMIC_VALUE
);
9180 if (ap
->is_erroneous()) error_flag
= true;
9184 // The rest of formal parameters have no corresponding actual parameters.
9185 // Create actual parameters for them based on their default values
9186 // (which must exist).
9187 for (size_t i
= upper_limit
; i
< formal_pars
; i
++) {
9188 FormalPar
*fp
= pars_v
[i
];
9189 if (fp
->has_defval()) {
9190 ActualPar
*defval
= fp
->get_defval();
9191 p_aplist
->add(new ActualPar(defval
));
9192 if (defval
->is_erroneous()) error_flag
= true;
9194 p_aplist
->add(new ActualPar()); // erroneous
9201 bool FormalParList::chk_activate_argument(ActualParList
*p_aplist
,
9202 const char* p_description
)
9204 bool ret_val
= true;
9205 for(size_t i
= 0; i
< p_aplist
->get_nof_pars(); i
++) {
9206 ActualPar
*t_ap
= p_aplist
->get_par(i
);
9207 if(t_ap
->get_selection() != ActualPar::AP_REF
) continue;
9208 FormalPar
*t_fp
= pars_v
[i
];
9209 switch(t_fp
->get_asstype()) {
9210 case Common::Assignment::A_PAR_VAL_OUT
:
9211 case Common::Assignment::A_PAR_VAL_INOUT
:
9212 case Common::Assignment::A_PAR_TEMPL_OUT
:
9213 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9214 case Common::Assignment::A_PAR_TIMER
:
9215 //the checking shall be performed for these parameter types
9217 case Common::Assignment::A_PAR_PORT
:
9218 // port parameters are always correct because ports can be defined
9219 // only in component types
9222 FATAL_ERROR("FormalParList::chk_activate_argument()");
9224 Ref_base
*t_ref
= t_ap
->get_Ref();
9225 Common::Assignment
*t_par_ass
= t_ref
->get_refd_assignment();
9226 if(!t_par_ass
) FATAL_ERROR("FormalParList::chk_activate_argument()");
9227 switch (t_par_ass
->get_asstype()) {
9228 case Common::Assignment::A_VAR
:
9229 case Common::Assignment::A_VAR_TEMPLATE
:
9230 case Common::Assignment::A_TIMER
:
9231 // it is not allowed to pass references of local variables or timers
9232 if (t_par_ass
->is_local()) {
9233 t_ref
->error("Parameter #%lu of %s refers to %s, which is a local "
9234 "definition within a statement block and may have shorter "
9235 "lifespan than the activated default. Only references to "
9236 "variables and timers defined in the component type can be passed "
9237 "to activated defaults", (unsigned long) (i
+ 1), p_description
,
9238 t_par_ass
->get_description().c_str());
9242 case Common::Assignment::A_PAR_VAL_IN
:
9243 case Common::Assignment::A_PAR_VAL_OUT
:
9244 case Common::Assignment::A_PAR_VAL_INOUT
:
9245 case Common::Assignment::A_PAR_TEMPL_IN
:
9246 case Common::Assignment::A_PAR_TEMPL_OUT
:
9247 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9248 case Common::Assignment::A_PAR_TIMER
: {
9249 // it is not allowed to pass references pointing to formal parameters
9250 // except for activate() statements within testcases
9251 // note: all defaults are deactivated at the end of the testcase
9252 FormalPar
*t_refd_fp
= dynamic_cast<FormalPar
*>(t_par_ass
);
9253 if (!t_refd_fp
) FATAL_ERROR("FormalParList::chk_activate_argument()");
9254 FormalParList
*t_fpl
= t_refd_fp
->get_my_parlist();
9255 if (!t_fpl
|| !t_fpl
->my_def
)
9256 FATAL_ERROR("FormalParList::chk_activate_argument()");
9257 if (t_fpl
->my_def
->get_asstype() != Common::Assignment::A_TESTCASE
) {
9258 t_ref
->error("Parameter #%lu of %s refers to %s, which may have "
9259 "shorter lifespan than the activated default. Only references to "
9260 "variables and timers defined in the component type can be passed "
9261 "to activated defaults", (unsigned long) (i
+ 1), p_description
,
9262 t_par_ass
->get_description().c_str());
9272 char *FormalParList::generate_code(char *str
, size_t display_unused
/* = 0 */)
9274 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9275 if (i
> 0) str
= mputstr(str
, ", ");
9276 str
= pars_v
[i
]->generate_code_fpar(str
, i
< display_unused
);
9281 char* FormalParList::generate_code_defval(char* str
)
9283 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9284 str
= pars_v
[i
]->generate_code_defval(str
);
9289 void FormalParList::generate_code_defval(output_struct
*target
)
9291 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9292 pars_v
[i
]->generate_code_defval(target
);
9296 char *FormalParList::generate_code_actual_parlist(char *str
,
9297 const char *p_prefix
)
9299 for (size_t i
= 0; i
< pars_v
.size(); i
++) {
9300 if (i
> 0) str
= mputstr(str
, ", ");
9301 str
= mputstr(str
, p_prefix
);
9302 str
= mputstr(str
, pars_v
[i
]->get_id().get_name().c_str());
9307 char *FormalParList::generate_code_object(char *str
, const char *p_prefix
, char refch
)
9309 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9310 str
= pars_v
[i
]->generate_code_object(str
, p_prefix
, refch
);
9314 char *FormalParList::generate_shadow_objects(char *str
) const
9316 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9317 str
= pars_v
[i
]->generate_shadow_object(str
);
9321 char *FormalParList::generate_code_set_unbound(char *str
) const
9323 if (enable_set_bound_out_param
) return str
;
9324 for (size_t i
= 0; i
< pars_v
.size(); i
++)
9325 str
= pars_v
[i
]->generate_code_set_unbound(str
);
9330 void FormalParList::dump(unsigned level
) const
9332 size_t nof_pars
= pars_v
.size();
9333 DEBUG(level
, "formal parameters: %lu pcs.", (unsigned long) nof_pars
);
9334 for(size_t i
= 0; i
< nof_pars
; i
++) pars_v
[i
]->dump(level
+ 1);
9337 // =================================
9339 // =================================
9341 ActualPar::ActualPar(Value
*v
)
9342 : Node(), selection(AP_VALUE
), my_scope(0), gen_restriction_check(TR_NONE
),
9343 gen_post_restriction_check(TR_NONE
)
9345 if (!v
) FATAL_ERROR("ActualPar::ActualPar()");
9349 ActualPar::ActualPar(TemplateInstance
*t
)
9350 : Node(), selection(AP_TEMPLATE
), my_scope(0),
9351 gen_restriction_check(TR_NONE
), gen_post_restriction_check(TR_NONE
)
9353 if (!t
) FATAL_ERROR("ActualPar::ActualPar()");
9357 ActualPar::ActualPar(Ref_base
*r
)
9358 : Node(), selection(AP_REF
), my_scope(0), gen_restriction_check(TR_NONE
),
9359 gen_post_restriction_check(TR_NONE
)
9361 if (!r
) FATAL_ERROR("ActualPar::ActualPar()");
9365 ActualPar::ActualPar(ActualPar
*a
)
9366 : Node(), selection(AP_DEFAULT
), my_scope(0),
9367 gen_restriction_check(TR_NONE
), gen_post_restriction_check(TR_NONE
)
9369 if (!a
) FATAL_ERROR("ActualPar::ActualPar()");
9373 ActualPar::~ActualPar()
9388 break; // nothing to do with act
9390 FATAL_ERROR("ActualPar::~ActualPar()");
9394 ActualPar
*ActualPar::clone() const
9396 FATAL_ERROR("ActualPar::clone");
9399 void ActualPar::set_fullname(const string
& p_fullname
)
9401 Node::set_fullname(p_fullname
);
9406 val
->set_fullname(p_fullname
);
9409 temp
->set_fullname(p_fullname
);
9412 ref
->set_fullname(p_fullname
);
9417 FATAL_ERROR("ActualPar::set_fullname()");
9421 void ActualPar::set_my_scope(Scope
*p_scope
)
9428 val
->set_my_scope(p_scope
);
9431 temp
->set_my_scope(p_scope
);
9434 ref
->set_my_scope(p_scope
);
9437 switch (act
->selection
) {
9439 ref
->set_my_scope(p_scope
);
9446 FATAL_ERROR("ActualPar::set_my_scope()");
9450 FATAL_ERROR("ActualPar::set_my_scope()");
9454 Value
*ActualPar::get_Value() const
9456 if (selection
!= AP_VALUE
) FATAL_ERROR("ActualPar::get_Value()");
9460 TemplateInstance
*ActualPar::get_TemplateInstance() const
9462 if (selection
!= AP_TEMPLATE
)
9463 FATAL_ERROR("ActualPar::get_TemplateInstance()");
9467 Ref_base
*ActualPar::get_Ref() const
9469 if (selection
!= AP_REF
) FATAL_ERROR("ActualPar::get_Ref()");
9473 ActualPar
*ActualPar::get_ActualPar() const
9475 if (selection
!= AP_DEFAULT
) FATAL_ERROR("ActualPar::get_ActualPar()");
9479 void ActualPar::chk_recursions(ReferenceChain
& refch
)
9481 switch (selection
) {
9484 val
->chk_recursions(refch
);
9488 Ref_base
*derived_ref
= temp
->get_DerivedRef();
9490 ActualParList
*parlist
= derived_ref
->get_parlist();
9493 parlist
->chk_recursions(refch
);
9498 Ttcn::Def_Template
* defTemp
= temp
->get_Referenced_Base_Template();
9501 refch
.add(defTemp
->get_fullname());
9505 temp
->get_Template()->chk_recursions(refch
);
9513 bool ActualPar::has_single_expr()
9515 switch (selection
) {
9517 return val
->has_single_expr();
9519 if (gen_restriction_check
!=TR_NONE
||
9520 gen_post_restriction_check
!=TR_NONE
) return false;
9521 return temp
->has_single_expr();
9523 if (gen_restriction_check
!=TR_NONE
||
9524 gen_post_restriction_check
!=TR_NONE
) return false;
9525 if (use_runtime_2
&& ref
->get_subrefs() != NULL
) {
9526 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
9527 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
9528 if (FieldOrArrayRef::ARRAY_REF
== subrefs
->get_ref(i
)->get_type()) {
9533 return ref
->has_single_expr();
9537 FATAL_ERROR("ActualPar::has_single_expr()");
9542 void ActualPar::set_code_section(
9543 GovernedSimple::code_section_t p_code_section
)
9545 switch (selection
) {
9547 val
->set_code_section(p_code_section
);
9550 temp
->set_code_section(p_code_section
);
9553 ref
->set_code_section(p_code_section
);
9559 void ActualPar::generate_code(expression_struct
*expr
, bool copy_needed
, bool lazy_param
, bool used_as_lvalue
) const
9561 switch (selection
) {
9563 if (lazy_param
) { // copy_needed doesn't matter in this case
9564 LazyParamData::init(used_as_lvalue
);
9565 LazyParamData::generate_code(expr
, val
, my_scope
);
9566 LazyParamData::clean();
9567 if (val
->get_valuetype() == Value::V_REFD
) {
9568 // check if the reference is a parameter, mark it as used if it is
9569 Reference
* ref
= dynamic_cast<Reference
*>(val
->get_reference());
9571 ref
->ref_usage_found();
9575 if (copy_needed
) expr
->expr
= mputprintf(expr
->expr
, "%s(",
9576 val
->get_my_governor()->get_genname_value(my_scope
).c_str());
9577 if (use_runtime_2
&& TypeConv::needs_conv_refd(val
)) {
9578 // Generate everything to preamble to be able to tackle the wrapper
9579 // constructor call. TODO: Reduce the number of temporaries created.
9580 const string
& tmp_id
= val
->get_temporary_id();
9581 const char *tmp_id_str
= tmp_id
.c_str();
9582 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
9583 val
->get_my_governor()->get_genname_value(my_scope
).c_str(),
9585 expr
->preamble
= TypeConv::gen_conv_code_refd(expr
->preamble
,
9587 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
9588 } else val
->generate_code_expr(expr
);
9589 if (copy_needed
) expr
->expr
= mputc(expr
->expr
, ')');
9593 if (lazy_param
) { // copy_needed doesn't matter in this case
9594 LazyParamData::init(used_as_lvalue
);
9595 LazyParamData::generate_code(expr
, temp
, gen_restriction_check
, my_scope
);
9596 LazyParamData::clean();
9597 if (temp
->get_DerivedRef() != NULL
||
9598 temp
->get_Template()->get_templatetype() == Template::TEMPLATE_REFD
) {
9599 // check if the reference is a parameter, mark it as used if it is
9600 Reference
* ref
= dynamic_cast<Reference
*>(temp
->get_DerivedRef() != NULL
?
9601 temp
->get_DerivedRef() : temp
->get_Template()->get_reference());
9603 ref
->ref_usage_found();
9608 expr
->expr
= mputprintf(expr
->expr
, "%s(", temp
->get_Template()
9609 ->get_my_governor()->get_genname_template(my_scope
).c_str());
9610 if (use_runtime_2
&& TypeConv::needs_conv_refd(temp
->get_Template())) {
9611 const string
& tmp_id
= temp
->get_Template()->get_temporary_id();
9612 const char *tmp_id_str
= tmp_id
.c_str();
9613 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
9614 temp
->get_Template()->get_my_governor()
9615 ->get_genname_template(my_scope
).c_str(), tmp_id_str
);
9616 expr
->preamble
= TypeConv::gen_conv_code_refd(expr
->preamble
,
9617 tmp_id_str
, temp
->get_Template());
9618 // Not incorporated into gen_conv_code() yet.
9619 if (gen_restriction_check
!= TR_NONE
)
9620 expr
->preamble
= Template::generate_restriction_check_code(
9621 expr
->preamble
, tmp_id_str
, gen_restriction_check
);
9622 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
9623 } else temp
->generate_code(expr
, gen_restriction_check
);
9624 if (copy_needed
) expr
->expr
= mputc(expr
->expr
, ')');
9628 if (lazy_param
) FATAL_ERROR("ActualPar::generate_code()"); // syntax error should have already happened
9629 if (copy_needed
) FATAL_ERROR("ActualPar::generate_code()");
9630 if (gen_restriction_check
!= TR_NONE
||
9631 gen_post_restriction_check
!= TR_NONE
) {
9632 // generate runtime check for restricted templates
9633 // code for reference + restriction check
9634 Common::Assignment
*ass
= ref
->get_refd_assignment();
9635 const string
& tmp_id
= my_scope
->get_scope_mod_gen()->get_temporary_id();
9636 const char *tmp_id_str
= tmp_id
.c_str();
9637 expression_struct ref_expr
;
9638 Code::init_expr(&ref_expr
);
9639 ref
->generate_code_const_ref(&ref_expr
);
9640 ref_expr
.preamble
= mputprintf(ref_expr
.preamble
, "%s& %s = %s;\n",
9641 ass
->get_Type()->get_genname_template(ref
->get_my_scope()).c_str(),
9642 tmp_id_str
, ref_expr
.expr
);
9643 if (gen_restriction_check
!= TR_NONE
) {
9644 ref_expr
.preamble
= Template::generate_restriction_check_code(
9645 ref_expr
.preamble
, tmp_id_str
, gen_restriction_check
);
9647 if (gen_post_restriction_check
!= TR_NONE
) {
9648 ref_expr
.postamble
= Template::generate_restriction_check_code(
9649 ref_expr
.postamble
, tmp_id_str
, gen_post_restriction_check
);
9651 // copy content of ref_expr to expr
9652 expr
->preamble
= mputstr(expr
->preamble
, ref_expr
.preamble
);
9653 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_id_str
);
9654 expr
->postamble
= mputstr(expr
->postamble
, ref_expr
.postamble
);
9655 Code::free_expr(&ref_expr
);
9657 ref
->generate_code(expr
);
9661 if (copy_needed
) FATAL_ERROR("ActualPar::generate_code()");
9662 switch (act
->selection
) {
9665 LazyParamData::generate_code_ap_default_ref(expr
, act
->ref
, my_scope
);
9667 act
->ref
->generate_code(expr
);
9672 LazyParamData::generate_code_ap_default_value(expr
, act
->val
, my_scope
);
9674 expr
->expr
= mputstr(expr
->expr
, act
->val
->get_genname_own(my_scope
).c_str());
9679 LazyParamData::generate_code_ap_default_ti(expr
, act
->temp
, my_scope
);
9681 expr
->expr
= mputstr(expr
->expr
, act
->temp
->get_Template()->get_genname_own(my_scope
).c_str());
9685 FATAL_ERROR("ActualPar::generate_code()");
9689 FATAL_ERROR("ActualPar::generate_code()");
9693 char *ActualPar::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
9695 switch (selection
) {
9697 str
= val
->rearrange_init_code(str
, usage_mod
);
9700 str
= temp
->rearrange_init_code(str
, usage_mod
);
9704 str
= act
->rearrange_init_code_defval(str
, usage_mod
);
9707 FATAL_ERROR("ActualPar::rearrange_init_code()");
9712 char *ActualPar::rearrange_init_code_defval(char *str
, Common::Module
* usage_mod
)
9714 switch (selection
) {
9716 if (val
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
9717 str
= val
->generate_code_init(str
, val
->get_lhs_name().c_str());
9721 str
= temp
->rearrange_init_code(str
, usage_mod
);
9722 Template
*t
= temp
->get_Template();
9723 if (t
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
9724 Ref_base
*dref
= temp
->get_DerivedRef();
9726 expression_struct expr
;
9727 Code::init_expr(&expr
);
9728 expr
.expr
= mputprintf(expr
.expr
, "%s = ", t
->get_lhs_name().c_str());
9729 dref
->generate_code(&expr
);
9730 str
= Code::merge_free_expr(str
, &expr
, false);
9732 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
9736 FATAL_ERROR("ActualPar::rearrange_init_code_defval()");
9741 void ActualPar::append_stringRepr(string
& str
) const
9743 switch (selection
) {
9745 str
+= val
->get_stringRepr();
9748 temp
->append_stringRepr(str
);
9751 str
+= ref
->get_dispname();
9757 str
+= "<erroneous actual parameter>";
9761 void ActualPar::dump(unsigned level
) const
9763 switch (selection
) {
9765 DEBUG(level
, "actual parameter: value");
9766 val
->dump(level
+ 1);
9769 DEBUG(level
, "actual parameter: template");
9770 temp
->dump(level
+ 1);
9773 DEBUG(level
, "actual parameter: reference");
9774 ref
->dump(level
+ 1);
9777 DEBUG(level
, "actual parameter: default");
9780 DEBUG(level
, "actual parameter: erroneous");
9784 // =================================
9785 // ===== ActualParList
9786 // =================================
9788 ActualParList::ActualParList(const ActualParList
& p
)
9791 size_t nof_pars
= p
.params
.size();
9792 for (size_t i
= 0; i
< nof_pars
; i
++) params
.add(p
.params
[i
]->clone());
9795 ActualParList::~ActualParList()
9797 size_t nof_pars
= params
.size();
9798 for (size_t i
= 0; i
< nof_pars
; i
++) delete params
[i
];
9802 ActualParList
*ActualParList::clone() const
9804 return new ActualParList(*this);
9807 void ActualParList::set_fullname(const string
& p_fullname
)
9809 Node::set_fullname(p_fullname
);
9810 size_t nof_pars
= params
.size();
9811 for(size_t i
= 0; i
< nof_pars
; i
++)
9812 params
[i
]->set_fullname(p_fullname
+
9813 ".<parameter" + Int2string(i
+ 1) + ">");
9816 void ActualParList::set_my_scope(Scope
*p_scope
)
9818 size_t nof_pars
= params
.size();
9819 for (size_t i
= 0; i
< nof_pars
; i
++) params
[i
]->set_my_scope(p_scope
);
9822 void ActualParList::chk_recursions(ReferenceChain
& refch
)
9824 size_t nof_pars
= params
.size();
9825 for (size_t i
= 0; i
< nof_pars
; i
++)
9826 params
[i
]->chk_recursions(refch
);
9829 void ActualParList::generate_code_noalias(expression_struct
*expr
, FormalParList
*p_fpl
)
9831 size_t nof_pars
= params
.size();
9832 for (size_t i
= 0; i
< nof_pars
; i
++) {
9833 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
9834 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());
9838 void ActualParList::generate_code_alias(expression_struct
*expr
,
9839 FormalParList
*p_fpl
, Type
*p_comptype
, bool p_compself
)
9841 size_t nof_pars
= params
.size();
9842 // collect all value and template definitions that are passed by reference
9843 map
<Common::Assignment
*, void> value_refs
, template_refs
;
9844 for (size_t i
= 0; i
< nof_pars
; i
++) {
9845 ActualPar
*par
= params
[i
];
9846 if (par
->get_selection() == ActualPar::AP_DEFAULT
)
9847 par
= par
->get_ActualPar();
9848 if (par
->get_selection() == ActualPar::AP_REF
) {
9849 Common::Assignment
*ass
= par
->get_Ref()->get_refd_assignment();
9850 switch (ass
->get_asstype()) {
9851 case Common::Assignment::A_VAR
:
9852 case Common::Assignment::A_PAR_VAL_IN
:
9853 case Common::Assignment::A_PAR_VAL_OUT
:
9854 case Common::Assignment::A_PAR_VAL_INOUT
:
9855 if (!value_refs
.has_key(ass
)) value_refs
.add(ass
, 0);
9857 case Common::Assignment::A_VAR_TEMPLATE
:
9858 case Common::Assignment::A_PAR_TEMPL_IN
:
9859 case Common::Assignment::A_PAR_TEMPL_OUT
:
9860 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9861 if (!template_refs
.has_key(ass
)) template_refs
.add(ass
, 0);
9867 // walk through the parameter list and generate the code
9868 // add an extra copy constructor call to the referenced value and template
9869 // parameters if the referred definition is also passed by reference to
9870 // another parameter
9871 for (size_t i
= 0; i
< nof_pars
; i
++) {
9872 if (i
> 0) expr
->expr
= mputstr(expr
->expr
, ", ");
9873 ActualPar
*par
= params
[i
];
9874 bool copy_needed
= false;
9875 // the copy constructor call is not needed if the parameter is copied
9876 // into a shadow object in the body of the called function
9877 if (!p_fpl
|| !p_fpl
->get_fp_byIndex(i
)->get_used_as_lvalue()) {
9878 switch (par
->get_selection()) {
9879 case ActualPar::AP_VALUE
: {
9880 Value
*v
= par
->get_Value();
9881 if (v
->get_valuetype() == Value::V_REFD
) {
9882 Common::Assignment
*t_ass
=
9883 v
->get_reference()->get_refd_assignment();
9884 if (value_refs
.has_key(t_ass
)) {
9885 // a reference to the same variable is also passed to the called
9888 } else if (p_comptype
|| p_compself
) {
9889 // the called definition has a 'runs on' clause so it can access
9890 // component variables
9891 switch (t_ass
->get_asstype()) {
9892 case Common::Assignment::A_PAR_VAL_OUT
:
9893 case Common::Assignment::A_PAR_VAL_INOUT
:
9894 // the parameter may be an alias of a component variable
9897 case Common::Assignment::A_VAR
:
9898 // copy is needed if t_ass is a component variable that is
9899 // visible by the called definition
9900 if (!t_ass
->is_local()) copy_needed
= true;
9901 /** \todo component type compatibility: check whether t_ass is
9902 * visible from p_comptype (otherwise copy is not needed) */
9909 case ActualPar::AP_TEMPLATE
: {
9910 TemplateInstance
*ti
= par
->get_TemplateInstance();
9911 if (!ti
->get_DerivedRef()) {
9912 Template
*t
= ti
->get_Template();
9913 if (t
->get_templatetype() == Template::TEMPLATE_REFD
) {
9914 Common::Assignment
*t_ass
=
9915 t
->get_reference()->get_refd_assignment();
9916 if (template_refs
.has_key(t_ass
)) {
9917 // a reference to the same variable is also passed to the called
9920 } else if (p_comptype
|| p_compself
) {
9921 // the called definition has a 'runs on' clause so it can access
9922 // component variables
9923 switch (t_ass
->get_asstype()) {
9924 case Common::Assignment::A_PAR_TEMPL_OUT
:
9925 case Common::Assignment::A_PAR_TEMPL_INOUT
:
9926 // the parameter may be an alias of a component variable
9929 case Common::Assignment::A_VAR_TEMPLATE
:
9930 // copy is needed if t_ass is a component variable that is
9931 // visible by the called definition
9932 if (!t_ass
->is_local()) copy_needed
= true;
9933 /** \todo component type compatibility: check whether t_ass is
9934 * visible from p_comptype (otherwise copy is not needed) */
9946 if (use_runtime_2
&& ActualPar::AP_REF
== par
->get_selection()) {
9947 // if the parameter references an element of a record of/set of, then
9948 // the record of object needs to know, so it doesn't delete the referenced
9950 Ref_base
* ref
= par
->get_Ref();
9951 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
9952 if (subrefs
!= NULL
) {
9953 Common::Assignment
* ass
= ref
->get_refd_assignment();
9955 for (ref_i
= 0; ref_i
< subrefs
->get_nof_refs(); ++ref_i
) {
9956 FieldOrArrayRef
* subref
= subrefs
->get_ref(ref_i
);
9957 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
9958 // set the referenced index in each array in the subrefs
9959 expression_struct array_expr
;
9960 Code::init_expr(&array_expr
);
9961 // the array object's name contains the reference, followed by
9962 // the subrefs before the current array ref
9963 array_expr
.expr
= mcopystr(LazyParamData::in_lazy() ?
9964 LazyParamData::add_ref_genname(ass
, ref
->get_my_scope()).c_str() :
9965 ass
->get_genname_from_scope(ref
->get_my_scope()).c_str());
9967 subrefs
->generate_code(&array_expr
, ass
, ref_i
);
9969 expression_struct index_expr
;
9970 Code::init_expr(&index_expr
);
9971 subrefs
->get_ref(ref_i
)->get_val()->generate_code_expr(&index_expr
);
9972 // insert any preambles the array object or the index might have
9973 if (array_expr
.preamble
!= NULL
) {
9974 expr
->preamble
= mputstr(expr
->preamble
, array_expr
.preamble
);
9975 expr
->postamble
= mputstr(expr
->postamble
, array_expr
.preamble
);
9977 if (index_expr
.preamble
!= NULL
) {
9978 expr
->preamble
= mputstr(expr
->preamble
, index_expr
.preamble
);
9979 expr
->postamble
= mputstr(expr
->postamble
, index_expr
.preamble
);
9981 // let the array object know that the index is referenced before
9982 // calling the function, and let it know that it's now longer
9983 // referenced after the function call (this is done with the help
9984 // of the RefdIndexHandler's constructor and destructor)
9985 string tmp_id
= ref
->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
9986 expr
->preamble
= mputprintf(expr
->preamble
,
9987 "RefdIndexHandler %s(&%s, %s);\n",
9988 tmp_id
.c_str(), array_expr
.expr
, index_expr
.expr
);
9989 // insert any postambles the array object or the index might have
9990 if (array_expr
.postamble
!= NULL
) {
9991 expr
->preamble
= mputstr(expr
->preamble
, array_expr
.postamble
);
9992 expr
->postamble
= mputstr(expr
->postamble
, array_expr
.postamble
);
9994 if (index_expr
.postamble
!= NULL
) {
9995 expr
->preamble
= mputstr(expr
->preamble
, index_expr
.postamble
);
9996 expr
->postamble
= mputstr(expr
->postamble
, index_expr
.postamble
);
9998 Code::free_expr(&array_expr
);
9999 Code::free_expr(&index_expr
);
10000 } // if (FieldOrArrayRef::ARRAY_REF == subref->get_type())
10002 } // if (subrefs != NULL)
10003 } // if (ActualPar::AP_REF == par->get_selection())
10005 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());
10007 value_refs
.clear();
10008 template_refs
.clear();
10011 char *ActualParList::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
10013 for (size_t i
= 0; i
< params
.size(); i
++)
10014 str
= params
[i
]->rearrange_init_code(str
, usage_mod
);
10018 void ActualParList::dump(unsigned level
) const
10020 DEBUG(level
, "actual parameter list: %lu parameters",
10021 (unsigned long) params
.size());
10022 for (size_t i
= 0; i
< params
.size(); i
++)
10023 params
[i
]->dump(level
+ 1);